Add support for multiple winners and update localization
Some checks failed
Pull Request Pipeline / test (pull_request) Successful in 47s
Pull Request Pipeline / lint (pull_request) Failing after 51s

This commit is contained in:
2026-05-10 16:26:51 +02:00
parent 03ab2045b2
commit 3c5c0dbf20
10 changed files with 110 additions and 16 deletions

View File

@@ -269,9 +269,9 @@ class _MatchDetailViewState extends State<MatchDetailView> {
/// Returns the widget to be displayed in the result [InfoTile]
Widget getResultWidget(AppLocalizations loc) {
///TODO: add support for multiple winners
if (isSingleRowResult()) {
return Row(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: getSingleResultRow(loc),
);
@@ -300,7 +300,8 @@ class _MatchDetailViewState extends State<MatchDetailView> {
),
];
// Single Loser
} else if (match.game.ruleset == Ruleset.singleLoser) {
} else if (match.mvp.isNotEmpty &&
match.game.ruleset == Ruleset.singleLoser) {
return [
Text(
loc.loser,
@@ -315,6 +316,28 @@ class _MatchDetailViewState extends State<MatchDetailView> {
),
),
];
// Multiple Winners
} else if (match.mvp.isNotEmpty &&
match.game.ruleset == Ruleset.multipleWinners) {
return [
Text(
loc.winners,
style: const TextStyle(fontSize: 16, color: CustomTheme.textColor),
),
Flexible(
child: Container(
padding: EdgeInsets.only(left: 40),
child: Text(
match.mvp.map((player) => player.name).join(', '),
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: CustomTheme.primaryColor,
),
),
),
),
];
// No result entered yet
} else {
return [
@@ -402,7 +425,8 @@ class _MatchDetailViewState extends State<MatchDetailView> {
// Returns if the result can be displayed in a single row
bool isSingleRowResult() {
return match.game.ruleset == Ruleset.singleWinner ||
match.game.ruleset == Ruleset.singleLoser;
match.game.ruleset == Ruleset.singleLoser ||
match.game.ruleset == Ruleset.multipleWinners;
}
String getPlacementText(BuildContext context, int rank) {

View File

@@ -50,7 +50,7 @@ class _MatchResultViewState extends State<MatchResultView> {
Player? _selectedPlayer;
/// Currently selected winners (multiple winners)
Set<String> _selectedWinners = {};
Set<Player> _selectedWinners = {};
@override
void initState() {
@@ -85,9 +85,12 @@ class _MatchResultViewState extends State<MatchResultView> {
return scoreB.compareTo(scoreA);
});
} else if (rulesetSupportsMultipleWinners()) {
//TODO: Implement winners pre filling
for (int i = 0; i < allPlayers.length; i++) {
if (widget.match.scores[allPlayers[i].id]?.score == 1) {
_selectedWinners.add(allPlayers[i]);
}
}
}
;
super.initState();
}
}
@@ -337,17 +340,17 @@ class _MatchResultViewState extends State<MatchResultView> {
return CustomCheckboxListTile(
text: allPlayers[index].name,
value: _selectedWinners.contains(
allPlayers[index].id,
allPlayers[index],
),
onChanged: (bool value) {
setState(() {
if (value) {
_selectedWinners.add(
allPlayers[index].id,
allPlayers[index],
);
} else {
_selectedWinners.remove(
allPlayers[index].id,
allPlayers[index],
);
}
});
@@ -426,7 +429,7 @@ class _MatchResultViewState extends State<MatchResultView> {
widget.onWinnerChanged?.call();
}
/// Handles saving or removing the winner in the database.
/// Handles saving or removing the (single) winner in the database.
Future<bool> _handleWinner() async {
if (_selectedPlayer == null) {
return await db.scoreEntryDao.removeWinner(matchId: widget.match.id);
@@ -438,10 +441,16 @@ class _MatchResultViewState extends State<MatchResultView> {
}
}
/// Handles saving the winners to the database.
/// Handles saving the (multiple) winners to the database.
Future<bool> _handleWinners() async {
//TODO: Implement winner handling
return true;
if (_selectedWinners.isEmpty) {
return await db.scoreEntryDao.removeWinners(matchId: widget.match.id);
} else {
return await db.scoreEntryDao.setWinners(
matchId: widget.match.id,
winners: allPlayers.where((p) => _selectedWinners.contains(p)).toList(),
);
}
}
/// Handles saving or removing the loser in the database.

View File

@@ -264,6 +264,9 @@ class _MatchTileState extends State<MatchTile> {
return '${loc.winner}: $mvpNames (${getPointLabel(loc, mvpScore)})';
} else if (ruleset == Ruleset.placement) {
return '${loc.winner}: ${widget.match.mvp.first.name}';
} else if (ruleset == Ruleset.multipleWinners) {
final mvpNames = widget.match.mvp.map((player) => player.name).join(', ');
return '${loc.winners}: $mvpNames';
}
return '${loc.winner}: n.A.';
}