Add support for multiple winners and update localization
This commit is contained in:
@@ -228,7 +228,7 @@ class ScoreEntryDao extends DatabaseAccessor<AppDatabase>
|
|||||||
required String playerId,
|
required String playerId,
|
||||||
}) async {
|
}) async {
|
||||||
// Clear previous winner if exists
|
// Clear previous winner if exists
|
||||||
deleteAllScoresForMatch(matchId: matchId);
|
await deleteAllScoresForMatch(matchId: matchId);
|
||||||
|
|
||||||
// Set the winner's score to 1
|
// Set the winner's score to 1
|
||||||
final rowsAffected = await into(scoreEntryTable).insert(
|
final rowsAffected = await into(scoreEntryTable).insert(
|
||||||
@@ -245,7 +245,7 @@ class ScoreEntryDao extends DatabaseAccessor<AppDatabase>
|
|||||||
return rowsAffected > 0;
|
return rowsAffected > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieves the winner of a match by looking for a score entry where score
|
/// Retrieves the winner of a match by looking for a score entry where score
|
||||||
/// is 1. Returns `null` if no player found, else the first with the score.
|
/// is 1. Returns `null` if no player found, else the first with the score.
|
||||||
Future<Player?> getWinner({required String matchId}) async {
|
Future<Player?> getWinner({required String matchId}) async {
|
||||||
final query =
|
final query =
|
||||||
@@ -285,6 +285,48 @@ class ScoreEntryDao extends DatabaseAccessor<AppDatabase>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* multiple winners handling */
|
||||||
|
|
||||||
|
/// Sets the winners for a match.
|
||||||
|
///
|
||||||
|
/// Returns `true` if more than 0 rows were affected
|
||||||
|
Future<bool> setWinners({
|
||||||
|
required List<Player> winners,
|
||||||
|
required String matchId,
|
||||||
|
}) async {
|
||||||
|
// Clear previous winners if exists
|
||||||
|
await deleteAllScoresForMatch(matchId: matchId);
|
||||||
|
|
||||||
|
if (winners.isEmpty) return false;
|
||||||
|
|
||||||
|
await batch((batch) {
|
||||||
|
batch.insertAll(
|
||||||
|
scoreEntryTable,
|
||||||
|
winners
|
||||||
|
.map(
|
||||||
|
(player) => ScoreEntryTableCompanion.insert(
|
||||||
|
playerId: player.id,
|
||||||
|
matchId: matchId,
|
||||||
|
roundNumber: 0,
|
||||||
|
score: 1,
|
||||||
|
change: 0,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
mode: InsertMode.insertOrReplace,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes the winners of a match.
|
||||||
|
///
|
||||||
|
/// Returns `true` if more than 0 rows were affected, `false` otherwise.
|
||||||
|
Future<bool> removeWinners({required String matchId}) async {
|
||||||
|
return await deleteAllScoresForMatch(matchId: matchId);
|
||||||
|
}
|
||||||
|
|
||||||
/* Loser handling */
|
/* Loser handling */
|
||||||
|
|
||||||
Future<bool> hasLoser({required String matchId}) async {
|
Future<bool> hasLoser({required String matchId}) async {
|
||||||
@@ -354,6 +396,8 @@ class ScoreEntryDao extends DatabaseAccessor<AppDatabase>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* placement handling */
|
||||||
|
|
||||||
/// Sets the placement for each player in a match.
|
/// Sets the placement for each player in a match.
|
||||||
/// The highest score is assigned to the first player, the second highest to the second player, and so on.
|
/// The highest score is assigned to the first player, the second highest to the second player, and so on.
|
||||||
Future<void> setPlacements({
|
Future<void> setPlacements({
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ class Match {
|
|||||||
return _getPlayersWithLowestScore().take(1).toList();
|
return _getPlayersWithLowestScore().take(1).toList();
|
||||||
|
|
||||||
case Ruleset.multipleWinners:
|
case Ruleset.multipleWinners:
|
||||||
return [];
|
return _getPlayersWithHighestScore().toList();
|
||||||
|
|
||||||
case Ruleset.placement:
|
case Ruleset.placement:
|
||||||
return _getPlayersWithHighestScore().take(1).toList();
|
return _getPlayersWithHighestScore().take(1).toList();
|
||||||
|
|||||||
@@ -141,6 +141,7 @@
|
|||||||
"undo": "Rückgängig",
|
"undo": "Rückgängig",
|
||||||
"unknown_exception": "Unbekannter Fehler (siehe Konsole)",
|
"unknown_exception": "Unbekannter Fehler (siehe Konsole)",
|
||||||
"winner": "Gewinner:in",
|
"winner": "Gewinner:in",
|
||||||
|
"winners": "Gewinner:innen",
|
||||||
"winrate": "Siegquote",
|
"winrate": "Siegquote",
|
||||||
"wins": "Siege",
|
"wins": "Siege",
|
||||||
"yesterday_at": "Gestern um"
|
"yesterday_at": "Gestern um"
|
||||||
|
|||||||
@@ -150,6 +150,7 @@
|
|||||||
"undo": "Undo",
|
"undo": "Undo",
|
||||||
"unknown_exception": "Unknown Exception (see console)",
|
"unknown_exception": "Unknown Exception (see console)",
|
||||||
"winner": "Winner",
|
"winner": "Winner",
|
||||||
|
"winners": "Winners",
|
||||||
"winrate": "Winrate",
|
"winrate": "Winrate",
|
||||||
"wins": "Wins",
|
"wins": "Wins",
|
||||||
"yesterday_at": "Yesterday at"
|
"yesterday_at": "Yesterday at"
|
||||||
|
|||||||
@@ -896,6 +896,12 @@ abstract class AppLocalizations {
|
|||||||
/// **'Winner'**
|
/// **'Winner'**
|
||||||
String get winner;
|
String get winner;
|
||||||
|
|
||||||
|
/// No description provided for @winners.
|
||||||
|
///
|
||||||
|
/// In en, this message translates to:
|
||||||
|
/// **'Winners'**
|
||||||
|
String get winners;
|
||||||
|
|
||||||
/// No description provided for @winrate.
|
/// No description provided for @winrate.
|
||||||
///
|
///
|
||||||
/// In en, this message translates to:
|
/// In en, this message translates to:
|
||||||
|
|||||||
@@ -434,6 +434,9 @@ class AppLocalizationsDe extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get winner => 'Gewinner:in';
|
String get winner => 'Gewinner:in';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get winners => 'Gewinner:innen';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get winrate => 'Siegquote';
|
String get winrate => 'Siegquote';
|
||||||
|
|
||||||
|
|||||||
@@ -433,6 +433,9 @@ class AppLocalizationsEn extends AppLocalizations {
|
|||||||
@override
|
@override
|
||||||
String get winner => 'Winner';
|
String get winner => 'Winner';
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get winners => 'Winners';
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String get winrate => 'Winrate';
|
String get winrate => 'Winrate';
|
||||||
|
|
||||||
|
|||||||
@@ -269,9 +269,9 @@ class _MatchDetailViewState extends State<MatchDetailView> {
|
|||||||
|
|
||||||
/// Returns the widget to be displayed in the result [InfoTile]
|
/// Returns the widget to be displayed in the result [InfoTile]
|
||||||
Widget getResultWidget(AppLocalizations loc) {
|
Widget getResultWidget(AppLocalizations loc) {
|
||||||
///TODO: add support for multiple winners
|
|
||||||
if (isSingleRowResult()) {
|
if (isSingleRowResult()) {
|
||||||
return Row(
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: getSingleResultRow(loc),
|
children: getSingleResultRow(loc),
|
||||||
);
|
);
|
||||||
@@ -300,7 +300,8 @@ class _MatchDetailViewState extends State<MatchDetailView> {
|
|||||||
),
|
),
|
||||||
];
|
];
|
||||||
// Single Loser
|
// Single Loser
|
||||||
} else if (match.game.ruleset == Ruleset.singleLoser) {
|
} else if (match.mvp.isNotEmpty &&
|
||||||
|
match.game.ruleset == Ruleset.singleLoser) {
|
||||||
return [
|
return [
|
||||||
Text(
|
Text(
|
||||||
loc.loser,
|
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
|
// No result entered yet
|
||||||
} else {
|
} else {
|
||||||
return [
|
return [
|
||||||
@@ -402,7 +425,8 @@ class _MatchDetailViewState extends State<MatchDetailView> {
|
|||||||
// Returns if the result can be displayed in a single row
|
// Returns if the result can be displayed in a single row
|
||||||
bool isSingleRowResult() {
|
bool isSingleRowResult() {
|
||||||
return match.game.ruleset == Ruleset.singleWinner ||
|
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) {
|
String getPlacementText(BuildContext context, int rank) {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ class _MatchResultViewState extends State<MatchResultView> {
|
|||||||
Player? _selectedPlayer;
|
Player? _selectedPlayer;
|
||||||
|
|
||||||
/// Currently selected winners (multiple winners)
|
/// Currently selected winners (multiple winners)
|
||||||
Set<String> _selectedWinners = {};
|
Set<Player> _selectedWinners = {};
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
@@ -85,9 +85,12 @@ class _MatchResultViewState extends State<MatchResultView> {
|
|||||||
return scoreB.compareTo(scoreA);
|
return scoreB.compareTo(scoreA);
|
||||||
});
|
});
|
||||||
} else if (rulesetSupportsMultipleWinners()) {
|
} 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();
|
super.initState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -337,17 +340,17 @@ class _MatchResultViewState extends State<MatchResultView> {
|
|||||||
return CustomCheckboxListTile(
|
return CustomCheckboxListTile(
|
||||||
text: allPlayers[index].name,
|
text: allPlayers[index].name,
|
||||||
value: _selectedWinners.contains(
|
value: _selectedWinners.contains(
|
||||||
allPlayers[index].id,
|
allPlayers[index],
|
||||||
),
|
),
|
||||||
onChanged: (bool value) {
|
onChanged: (bool value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
if (value) {
|
if (value) {
|
||||||
_selectedWinners.add(
|
_selectedWinners.add(
|
||||||
allPlayers[index].id,
|
allPlayers[index],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
_selectedWinners.remove(
|
_selectedWinners.remove(
|
||||||
allPlayers[index].id,
|
allPlayers[index],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -426,7 +429,7 @@ class _MatchResultViewState extends State<MatchResultView> {
|
|||||||
widget.onWinnerChanged?.call();
|
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 {
|
Future<bool> _handleWinner() async {
|
||||||
if (_selectedPlayer == null) {
|
if (_selectedPlayer == null) {
|
||||||
return await db.scoreEntryDao.removeWinner(matchId: widget.match.id);
|
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 {
|
Future<bool> _handleWinners() async {
|
||||||
//TODO: Implement winner handling
|
if (_selectedWinners.isEmpty) {
|
||||||
return true;
|
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.
|
/// Handles saving or removing the loser in the database.
|
||||||
|
|||||||
@@ -264,6 +264,9 @@ class _MatchTileState extends State<MatchTile> {
|
|||||||
return '${loc.winner}: $mvpNames (${getPointLabel(loc, mvpScore)})';
|
return '${loc.winner}: $mvpNames (${getPointLabel(loc, mvpScore)})';
|
||||||
} else if (ruleset == Ruleset.placement) {
|
} else if (ruleset == Ruleset.placement) {
|
||||||
return '${loc.winner}: ${widget.match.mvp.first.name}';
|
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.';
|
return '${loc.winner}: n.A.';
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user