diff --git a/lib/data/dao/player_game_dao.dart b/lib/data/dao/player_game_dao.dart index ef15a80..b7f253f 100644 --- a/lib/data/dao/player_game_dao.dart +++ b/lib/data/dao/player_game_dao.dart @@ -79,4 +79,50 @@ class PlayerGameDao extends DatabaseAccessor final rowsAffected = await query.go(); return rowsAffected > 0; } + + /// Updates the players associated with a game based on the provided + /// [newPlayer] list. It adds new players and removes players that are no + /// longer associated with the game. + Future updatePlayersFromGame({ + required String gameId, + required List newPlayer, + }) async { + final currentPlayers = await getPlayersOfGame(gameId: gameId); + // Create sets of player IDs for easy comparison + final currentPlayerIds = currentPlayers?.map((p) => p.id).toSet() ?? {}; + final newPlayerIdsSet = newPlayer.map((p) => p.id).toSet(); + + // Determine players to add and remove + final playersToAdd = newPlayerIdsSet.difference(currentPlayerIds); + final playersToRemove = currentPlayerIds.difference(newPlayerIdsSet); + + db.transaction(() async { + // Remove old players + if (playersToRemove.isNotEmpty) { + await (delete(playerGameTable)..where( + (pg) => + pg.gameId.equals(gameId) & + pg.playerId.isIn(playersToRemove.toList()), + )) + .go(); + } + + // Add new players + if (playersToAdd.isNotEmpty) { + final inserts = playersToAdd + .map( + (id) => + PlayerGameTableCompanion.insert(playerId: id, gameId: gameId), + ) + .toList(); + await Future.wait( + inserts.map( + (c) => into( + playerGameTable, + ).insert(c, mode: InsertMode.insertOrReplace), + ), + ); + } + }); + } } diff --git a/test/db_tests/player_game_test.dart b/test/db_tests/player_game_test.dart index e8fd707..4c3bc77 100644 --- a/test/db_tests/player_game_test.dart +++ b/test/db_tests/player_game_test.dart @@ -136,5 +136,49 @@ void main() { expect(players[i].createdAt, testGameOnlyPlayers.players![i].createdAt); } }); + + test('Updating the games players works coreclty', () async { + await database.gameDao.addGame(game: testGameOnlyPlayers); + + final newPlayers = [testPlayer1, testPlayer2, testPlayer4]; + await database.playerDao.addPlayers(players: newPlayers); + + // First, remove all existing players + final existingPlayers = await database.playerGameDao.getPlayersOfGame( + gameId: testGameOnlyPlayers.id, + ); + + print('existingPlayers: $existingPlayers'); + if (existingPlayers == null || existingPlayers.isEmpty) { + fail('Existing players should not be null or empty'); + } + + await database.playerGameDao.updatePlayersFromGame( + gameId: testGameOnlyPlayers.id, + newPlayer: newPlayers, + ); + + final updatedPlayers = await database.playerGameDao.getPlayersOfGame( + gameId: testGameOnlyPlayers.id, + ); + + if (updatedPlayers == null) { + fail('Updated players should not be null'); + } + + expect(updatedPlayers.length, newPlayers.length); + + /// Create a map of new players for easy lookup + final testPlayers = {for (var p in newPlayers) p.id: p}; + + /// Verify each updated player matches the new players + for (final player in updatedPlayers) { + final testPlayer = testPlayers[player.id]!; + + expect(player.id, testPlayer.id); + expect(player.name, testPlayer.name); + expect(player.createdAt, testPlayer.createdAt); + } + }); }); }