6 Commits

Author SHA1 Message Date
gelbeinhalb
a12f4eb1c1 implement winner methods
Some checks failed
Pull Request Pipeline / test (pull_request) Failing after 28s
Pull Request Pipeline / lint (pull_request) Failing after 40s
2026-02-07 17:35:43 +01:00
gelbeinhalb
0eb8e2683c add replace players in a match test 2026-02-07 17:31:23 +01:00
gelbeinhalb
07b9b78252 add replace players in a match method 2026-02-07 17:31:19 +01:00
gelbeinhalb
fa9ad9dbae add test for replacing group players 2026-02-07 17:26:07 +01:00
gelbeinhalb
25699dffc0 add replaceGroupPlayers method 2026-02-07 17:25:49 +01:00
gelbeinhalb
70d6178829 restructure tests 2026-02-01 19:51:57 +01:00
10 changed files with 196 additions and 15 deletions

View File

@@ -231,4 +231,44 @@ class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Replaces all players in a group with the provided list of players.
/// Removes all existing players from the group and adds the new players.
/// Also adds any new players to the player table if they don't exist.
Future<void> replaceGroupPlayers({
required String groupId,
required List<Player> newPlayers,
}) async {
await db.transaction(() async {
// Remove all existing players from the group
final deleteQuery = delete(db.playerGroupTable)
..where((p) => p.groupId.equals(groupId));
await deleteQuery.go();
// Add new players to the player table if they don't exist
await Future.wait(
newPlayers.map((player) async {
if (!await db.playerDao.playerExists(playerId: player.id)) {
await db.playerDao.addPlayer(player: player);
}
}),
);
// Add the new players to the group
await db.batch(
(b) => b.insertAll(
db.playerGroupTable,
newPlayers
.map(
(player) => PlayerGroupTableCompanion.insert(
playerId: player.id,
groupId: groupId,
),
)
.toList(),
mode: InsertMode.insertOrReplace,
),
);
});
}
}

View File

@@ -355,39 +355,119 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
return rowsAffected > 0;
}
/// Replaces all players in a match with the provided list of players.
/// Removes all existing players from the match and adds the new players.
/// Also adds any new players to the player table if they don't exist.
Future<void> replaceMatchPlayers({
required String matchId,
required List<Player> newPlayers,
}) async {
await db.transaction(() async {
// Remove all existing players from the match
final deleteQuery = delete(db.playerMatchTable)
..where((p) => p.matchId.equals(matchId));
await deleteQuery.go();
// Add new players to the player table if they don't exist
await Future.wait(
newPlayers.map((player) async {
if (!await db.playerDao.playerExists(playerId: player.id)) {
await db.playerDao.addPlayer(player: player);
}
}),
);
// Add the new players to the match
await Future.wait(
newPlayers.map((player) => db.playerMatchDao.addPlayerToMatch(
matchId: matchId,
playerId: player.id,
)),
);
});
}
// ============================================================
// TEMPORARY: Winner methods - these are stubs and do not persist data
// TODO: Implement proper winner handling
// Winner methods - handle winner logic via player scores
// ============================================================
/// TEMPORARY: Checks if a match has a winner.
/// Currently returns true if the match has any players.
/// Checks if a match has a winner.
/// Returns true if any player in the match has their score set to 1.
Future<bool> hasWinner({required String matchId}) async {
final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId) ?? [];
return players.isNotEmpty;
for (final player in players) {
final score = await db.playerMatchDao.getPlayerScore(
matchId: matchId,
playerId: player.id,
);
if (score == 1) {
return true;
}
}
return false;
}
/// TEMPORARY: Gets the winner of a match.
/// Currently returns the first player in the match's player list.
/// Gets the winner of a match.
/// Returns the player with score 1, or null if no winner is set.
Future<Player?> getWinner({required String matchId}) async {
final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId) ?? [];
return players.isNotEmpty ? players.first : null;
for (final player in players) {
final score = await db.playerMatchDao.getPlayerScore(
matchId: matchId,
playerId: player.id,
);
if (score == 1) {
return player;
}
}
return null;
}
/// TEMPORARY: Sets the winner of a match.
/// Currently does nothing - winner is not persisted.
/// Sets the winner of a match.
/// Sets all players' scores to 0, then sets the specified player's score to 1.
/// Returns `true` if the operation was successful, otherwise `false`.
Future<bool> setWinner({
required String matchId,
required String winnerId,
}) async {
// TODO: Implement winner persistence
await db.transaction(() async {
final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId) ?? [];
// Set all players' scores to 0
for (final player in players) {
await db.playerMatchDao.updatePlayerScore(
matchId: matchId,
playerId: player.id,
newScore: 0,
);
}
// Set the winner's score to 1
await db.playerMatchDao.updatePlayerScore(
matchId: matchId,
playerId: winnerId,
newScore: 1,
);
});
return true;
}
/// TEMPORARY: Removes the winner of a match.
/// Currently does nothing - winner is not persisted.
/// Removes the winner of a match.
/// Sets the current winner's score to 0 (no winner).
/// Returns `true` if a winner was removed, otherwise `false`.
Future<bool> removeWinner({required String matchId}) async {
// TODO: Implement winner persistence
return true;
final winner = await getWinner(matchId: matchId);
if (winner == null) {
return false;
}
final success = await db.playerMatchDao.updatePlayerScore(
matchId: matchId,
playerId: winner.id,
newScore: 0,
);
return success;
}
}

View File

@@ -308,5 +308,35 @@ void main() {
);
expect(secondRemoval, false);
});
// Verifies that replaceGroupPlayers removes all existing players and replaces with new list.
test('replaceGroupPlayers replaces all group members correctly', () async {
// Create initial group with 3 players
await database.groupDao.addGroup(group: testGroup);
// Verify initial members
var groupMembers = await database.groupDao.getGroupById(
groupId: testGroup.id,
);
expect(groupMembers.members.length, 3);
// Replace with new list containing 2 different players
final newPlayersList = [testPlayer3, testPlayer4];
await database.groupDao.replaceGroupPlayers(
groupId: testGroup.id,
newPlayers: newPlayersList,
);
// Get updated group and verify members
groupMembers = await database.groupDao.getGroupById(
groupId: testGroup.id,
);
expect(groupMembers.members.length, 2);
expect(groupMembers.members.any((p) => p.id == testPlayer3.id), true);
expect(groupMembers.members.any((p) => p.id == testPlayer4.id), true);
expect(groupMembers.members.any((p) => p.id == testPlayer1.id), false);
expect(groupMembers.members.any((p) => p.id == testPlayer2.id), false);
});
});
}

View File

@@ -884,5 +884,36 @@ void main() {
expect(playersInTeam.length, 1);
expect(playersInTeam[0].id, testPlayer2.id);
});
// Verifies that replaceMatchPlayers removes all existing players and replaces with new list.
test('replaceMatchPlayers replaces all match players correctly', () async {
// Create initial match with 3 players
await database.matchDao.addMatch(match: testMatchOnlyPlayers);
// Verify initial players
var matchPlayers = await database.matchDao.getMatchById(
matchId: testMatchOnlyPlayers.id,
);
expect(matchPlayers.players.length, 3);
// Replace with new list containing 2 different players
final newPlayersList = [testPlayer1, testPlayer2];
await database.matchDao.replaceMatchPlayers(
matchId: testMatchOnlyPlayers.id,
newPlayers: newPlayersList,
);
// Get updated match and verify players
matchPlayers = await database.matchDao.getMatchById(
matchId: testMatchOnlyPlayers.id,
);
expect(matchPlayers.players.length, 2);
expect(matchPlayers.players.any((p) => p.id == testPlayer1.id), true);
expect(matchPlayers.players.any((p) => p.id == testPlayer2.id), true);
expect(matchPlayers.players.any((p) => p.id == testPlayer4.id), false);
expect(matchPlayers.players.any((p) => p.id == testPlayer5.id), false);
expect(matchPlayers.players.any((p) => p.id == testPlayer6.id), false);
});
});
}