Updated score saving in match

This commit is contained in:
2026-04-11 23:34:57 +02:00
parent 520edd0ca6
commit 26d60fc8b2
5 changed files with 77 additions and 35 deletions

View File

@@ -29,6 +29,9 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
}
final players =
await db.playerMatchDao.getPlayersOfMatch(matchId: row.id) ?? [];
final scores = await db.scoreDao.getAllMatchScores(matchId: row.id);
final winner = await db.scoreDao.getWinner(matchId: row.id);
return Match(
id: row.id,
@@ -39,6 +42,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
notes: row.notes ?? '',
createdAt: row.createdAt,
endedAt: row.endedAt,
scores: scores,
winner: winner,
);
}),
@@ -60,6 +64,8 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
final players =
await db.playerMatchDao.getPlayersOfMatch(matchId: matchId) ?? [];
final scores = await db.scoreDao.getAllMatchScores(matchId: matchId);
final winner = await db.scoreDao.getWinner(matchId: matchId);
return Match(
@@ -71,6 +77,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
notes: result.notes ?? '',
createdAt: result.createdAt,
endedAt: result.endedAt,
scores: scores,
winner: winner,
);
}
@@ -100,6 +107,15 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
);
}
for (final pid in match.scores.keys) {
final playerScores = match.scores[pid]!;
await db.scoreDao.addScoresAsList(
scores: playerScores,
playerId: pid,
matchId: match.id,
);
}
if (match.winner != null) {
await db.scoreDao.setWinner(
matchId: match.id,

View File

@@ -1,3 +1,5 @@
import 'dart:async';
import 'package:drift/drift.dart';
import 'package:tallee/data/db/database.dart';
import 'package:tallee/data/db/tables/score_table.dart';
@@ -30,6 +32,29 @@ class ScoreDao extends DatabaseAccessor<AppDatabase> with _$ScoreDaoMixin {
);
}
Future<void> addScoresAsList({
required List<Score> scores,
required String playerId,
required String matchId,
}) async {
if (scores.isEmpty) return;
final entries = scores
.map(
(score) => ScoreTableCompanion.insert(
playerId: playerId,
matchId: matchId,
roundNumber: score.roundNumber,
score: score.score,
change: score.change,
),
)
.toList();
await batch((batch) {
batch.insertAll(scoreTable, entries, mode: InsertMode.insertOrReplace);
});
}
/// Retrieves the score for a specific round.
Future<Score?> getScore({
required String playerId,
@@ -48,7 +73,6 @@ class ScoreDao extends DatabaseAccessor<AppDatabase> with _$ScoreDaoMixin {
if (result == null) return null;
return Score(
playerId: result.playerId,
roundNumber: result.roundNumber,
score: result.score,
change: result.change,
@@ -56,19 +80,23 @@ class ScoreDao extends DatabaseAccessor<AppDatabase> with _$ScoreDaoMixin {
}
/// Retrieves all scores for a specific match.
Future<List<Score>> getAllMatchScores({required String matchId}) async {
Future<Map<String, List<Score>>> getAllMatchScores({
required String matchId,
}) async {
final query = select(scoreTable)..where((s) => s.matchId.equals(matchId));
final result = await query.get();
return result
.map(
(row) => Score(
playerId: row.playerId,
roundNumber: row.roundNumber,
score: row.score,
change: row.change,
),
)
.toList();
final Map<String, List<Score>> scoresByPlayer = {};
for (final row in result) {
final score = Score(
roundNumber: row.roundNumber,
score: row.score,
change: row.change,
);
scoresByPlayer.putIfAbsent(row.playerId, () => []).add(score);
}
return scoresByPlayer;
}
/// Retrieves all scores for a specific player in a match.
@@ -83,13 +111,15 @@ class ScoreDao extends DatabaseAccessor<AppDatabase> with _$ScoreDaoMixin {
return result
.map(
(row) => Score(
playerId: row.playerId,
roundNumber: row.roundNumber,
score: row.score,
change: row.change,
),
)
.toList();
.toList()
..sort(
(scoreA, scoreB) => scoreA.roundNumber.compareTo(scoreB.roundNumber),
);
}
/// Updates a score entry.
@@ -149,16 +179,19 @@ class ScoreDao extends DatabaseAccessor<AppDatabase> with _$ScoreDaoMixin {
return rowsAffected > 0;
}
/// Gets the latest round number for a match.
Future<int> getLatestRoundNumber({required String matchId}) async {
/// Gets the highest (latest) round number for a match.
/// Returns `null` if there are no scores for the match.
Future<int?> getLatestRoundNumber({required String matchId}) async {
final query = selectOnly(scoreTable)
..where(scoreTable.matchId.equals(matchId))
..addColumns([scoreTable.roundNumber.max()]);
final result = await query.getSingle();
return result.read(scoreTable.roundNumber.max()) ?? 0;
return result.read(scoreTable.roundNumber.max());
}
/// Gets the total score for a player in a match (sum of all changes).
/// Aggregates the total score for a player in a match by summing all their
/// score entry changes. Returns `0` if there are no scores for the player
/// in the match.
Future<int> getTotalScoreForPlayer({
required String playerId,
required String matchId,
@@ -168,8 +201,8 @@ class ScoreDao extends DatabaseAccessor<AppDatabase> with _$ScoreDaoMixin {
matchId: matchId,
);
if (scores.isEmpty) return 0;
// Return the score from the latest round
return scores.last.score;
// Return the sum of all score changes
return scores.fold<int>(0, (sum, element) => sum + element.change);
}
Future<bool> hasWinner({required String matchId}) async {

View File

@@ -15,7 +15,7 @@ class Match {
final Group? group;
final List<Player> players;
final String notes;
List<Score> scores;
Map<String, List<Score>> scores;
Player? winner;
Match({
@@ -27,10 +27,11 @@ class Match {
this.group,
this.players = const [],
this.notes = '',
this.scores = const [],
Map<String, List<Score>>? scores,
this.winner,
}) : id = id ?? const Uuid().v4(),
createdAt = createdAt ?? clock.now();
createdAt = createdAt ?? clock.now(),
scores = scores ?? {for (var player in players) player.id: []};
@override
String toString() {
@@ -67,7 +68,7 @@ class Match {
'gameId': game.id,
'groupId': group?.id,
'playerIds': players.map((player) => player.id).toList(),
'scores': scores.map((score) => score.toJson()).toList(),
'scores': scores,
'notes': notes,
};
}

View File

@@ -1,24 +1,16 @@
class Score {
final String playerId;
final int roundNumber;
int score = 0;
int change = 0;
Score({
required this.playerId,
required this.roundNumber,
required this.score,
required this.change,
});
Score({required this.roundNumber, required this.score, required this.change});
Score.fromJson(Map<String, dynamic> json)
: playerId = json['playerId'],
roundNumber = json['roundNumber'],
: roundNumber = json['roundNumber'],
score = json['score'],
change = json['change'];
Map<String, dynamic> toJson() => {
'playerId': playerId,
'roundNumber': roundNumber,
'score': score,
'change': change,