Renamed every instance of "game" to "match"

This commit is contained in:
2025-12-11 20:07:32 +01:00
parent d0059b44a8
commit 99cea1e703
41 changed files with 1525 additions and 1459 deletions

View File

@@ -1,320 +0,0 @@
import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/db/tables/game_table.dart';
import 'package:game_tracker/data/dto/game.dart';
import 'package:game_tracker/data/dto/group.dart';
import 'package:game_tracker/data/dto/player.dart';
part 'game_dao.g.dart';
@DriftAccessor(tables: [GameTable])
class GameDao extends DatabaseAccessor<AppDatabase> with _$GameDaoMixin {
GameDao(super.db);
/// Retrieves all games from the database.
Future<List<Game>> getAllGames() async {
final query = select(gameTable);
final result = await query.get();
return Future.wait(
result.map((row) async {
final group = await db.groupGameDao.getGroupOfGame(gameId: row.id);
final players = await db.playerGameDao.getPlayersOfGame(gameId: row.id);
final winner = row.winnerId != null
? await db.playerDao.getPlayerById(playerId: row.winnerId!)
: null;
return Game(
id: row.id,
name: row.name,
group: group,
players: players,
createdAt: row.createdAt,
winner: winner,
);
}),
);
}
/// Retrieves a [Game] by its [gameId].
Future<Game> getGameById({required String gameId}) async {
final query = select(gameTable)..where((g) => g.id.equals(gameId));
final result = await query.getSingle();
List<Player>? players;
if (await db.playerGameDao.gameHasPlayers(gameId: gameId)) {
players = await db.playerGameDao.getPlayersOfGame(gameId: gameId);
}
Group? group;
if (await db.groupGameDao.gameHasGroup(gameId: gameId)) {
group = await db.groupGameDao.getGroupOfGame(gameId: gameId);
}
Player? winner;
if (result.winnerId != null) {
winner = await db.playerDao.getPlayerById(playerId: result.winnerId!);
}
return Game(
id: result.id,
name: result.name,
players: players,
group: group,
winner: winner,
createdAt: result.createdAt,
);
}
/// Adds a new [Game] to the database.
/// Also adds associated players and group if they exist.
Future<void> addGame({required Game game}) async {
await db.transaction(() async {
await into(gameTable).insert(
GameTableCompanion.insert(
id: game.id,
name: game.name,
winnerId: Value(game.winner?.id),
createdAt: game.createdAt,
),
mode: InsertMode.insertOrReplace,
);
if (game.players != null) {
await db.playerDao.addPlayersAsList(players: game.players!);
for (final p in game.players ?? []) {
await db.playerGameDao.addPlayerToGame(
gameId: game.id,
playerId: p.id,
);
}
}
if (game.group != null) {
await db.groupDao.addGroup(group: game.group!);
await db.groupGameDao.addGroupToGame(
gameId: game.id,
groupId: game.group!.id,
);
}
});
}
/// Adds multiple [Game]s to the database in a batch operation.
/// Also adds associated players and groups if they exist.
/// If the [games] list is empty, the method returns immediately.
Future<void> addGamesAsList({required List<Game> games}) async {
if (games.isEmpty) return;
await db.transaction(() async {
// Add all games in batch
await db.batch(
(b) => b.insertAll(
gameTable,
games
.map(
(game) => GameTableCompanion.insert(
id: game.id,
name: game.name,
createdAt: game.createdAt,
winnerId: Value(game.winner?.id),
),
)
.toList(),
mode: InsertMode.insertOrReplace,
),
);
// Add all groups of the games in batch
await db.batch(
(b) => b.insertAll(
db.groupTable,
games
.where((game) => game.group != null)
.map(
(game) => GroupTableCompanion.insert(
id: game.group!.id,
name: game.group!.name,
createdAt: game.group!.createdAt,
),
)
.toList(),
mode: InsertMode.insertOrReplace,
),
);
// Add all players of the games in batch (unique)
final uniquePlayers = <String, Player>{};
for (final game in games) {
if (game.players != null) {
for (final p in game.players!) {
uniquePlayers[p.id] = p;
}
}
// Also include members of groups
if (game.group != null) {
for (final m in game.group!.members) {
uniquePlayers[m.id] = m;
}
}
}
if (uniquePlayers.isNotEmpty) {
await db.batch(
(b) => b.insertAll(
db.playerTable,
uniquePlayers.values
.map(
(p) => PlayerTableCompanion.insert(
id: p.id,
name: p.name,
createdAt: p.createdAt,
),
)
.toList(),
mode: InsertMode.insertOrReplace,
),
);
}
// Add all player-game associations in batch
await db.batch((b) {
for (final game in games) {
if (game.players != null) {
for (final p in game.players ?? []) {
b.insert(
db.playerGameTable,
PlayerGameTableCompanion.insert(
gameId: game.id,
playerId: p.id,
),
mode: InsertMode.insertOrReplace,
);
}
}
}
});
// Add all player-group associations in batch
await db.batch((b) {
for (final game in games) {
if (game.group != null) {
for (final m in game.group!.members) {
b.insert(
db.playerGroupTable,
PlayerGroupTableCompanion.insert(
playerId: m.id,
groupId: game.group!.id,
),
mode: InsertMode.insertOrReplace,
);
}
}
}
});
// Add all group-game associations in batch
await db.batch((b) {
for (final game in games) {
if (game.group != null) {
b.insert(
db.groupGameTable,
GroupGameTableCompanion.insert(
gameId: game.id,
groupId: game.group!.id,
),
mode: InsertMode.insertOrReplace,
);
}
}
});
});
}
/// Deletes the game with the given [gameId] from the database.
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteGame({required String gameId}) async {
final query = delete(gameTable)..where((g) => g.id.equals(gameId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Retrieves the number of games in the database.
Future<int> getGameCount() async {
final count =
await (selectOnly(gameTable)..addColumns([gameTable.id.count()]))
.map((row) => row.read(gameTable.id.count()))
.getSingle();
return count ?? 0;
}
/// Checks if a game with the given [gameId] exists in the database.
/// Returns `true` if the game exists, otherwise `false`.
Future<bool> gameExists({required String gameId}) async {
final query = select(gameTable)..where((g) => g.id.equals(gameId));
final result = await query.getSingleOrNull();
return result != null;
}
/// Deletes all games from the database.
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteAllGames() async {
final query = delete(gameTable);
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Sets the winner of the game with the given [gameId] to the player with
/// the given [winnerId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> setWinner({
required String gameId,
required String winnerId,
}) async {
final query = update(gameTable)..where((g) => g.id.equals(gameId));
final rowsAffected = await query.write(
GameTableCompanion(winnerId: Value(winnerId)),
);
return rowsAffected > 0;
}
/// Retrieves the winner of the game with the given [gameId].
/// Returns the [Player] who won the game, or `null` if no winner is set.
Future<Player?> getWinner({required String gameId}) async {
final query = select(gameTable)..where((g) => g.id.equals(gameId));
final result = await query.getSingleOrNull();
if (result == null || result.winnerId == null) {
return null;
}
final winner = await db.playerDao.getPlayerById(playerId: result.winnerId!);
return winner;
}
/// Removes the winner of the game with the given [gameId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> removeWinner({required String gameId}) async {
final query = update(gameTable)..where((g) => g.id.equals(gameId));
final rowsAffected = await query.write(
const GameTableCompanion(winnerId: Value(null)),
);
return rowsAffected > 0;
}
/// Checks if the game with the given [gameId] has a winner set.
/// Returns `true` if a winner is set, otherwise `false`.
Future<bool> hasWinner({required String gameId}) async {
final query = select(gameTable)
..where((g) => g.id.equals(gameId) & g.winnerId.isNotNull());
final result = await query.getSingleOrNull();
return result != null;
}
/// Changes the title of the game with the given [gameId] to [newName].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateGameName({
required String gameId,
required String newName,
}) async {
final query = update(gameTable)..where((g) => g.id.equals(gameId));
final rowsAffected = await query.write(
GameTableCompanion(name: Value(newName)),
);
return rowsAffected > 0;
}
}

View File

@@ -1,8 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'game_dao.dart';
// ignore_for_file: type=lint
mixin _$GameDaoMixin on DatabaseAccessor<AppDatabase> {
$GameTableTable get gameTable => attachedDatabase.gameTable;
}

View File

@@ -1,12 +1,13 @@
import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/db/tables/group_table.dart';
import 'package:game_tracker/data/db/tables/player_group_table.dart';
import 'package:game_tracker/data/dto/group.dart';
import 'package:game_tracker/data/dto/player.dart';
part 'group_dao.g.dart';
@DriftAccessor(tables: [GroupTable])
@DriftAccessor(tables: [GroupTable, PlayerGroupTable])
class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
GroupDao(super.db);

View File

@@ -5,4 +5,7 @@ part of 'group_dao.dart';
// ignore_for_file: type=lint
mixin _$GroupDaoMixin on DatabaseAccessor<AppDatabase> {
$GroupTableTable get groupTable => attachedDatabase.groupTable;
$PlayerTableTable get playerTable => attachedDatabase.playerTable;
$PlayerGroupTableTable get playerGroupTable =>
attachedDatabase.playerGroupTable;
}

View File

@@ -1,98 +0,0 @@
import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/db/tables/group_game_table.dart';
import 'package:game_tracker/data/dto/group.dart';
part 'group_game_dao.g.dart';
@DriftAccessor(tables: [GroupGameTable])
class GroupGameDao extends DatabaseAccessor<AppDatabase>
with _$GroupGameDaoMixin {
GroupGameDao(super.db);
/// Associates a group with a game by inserting a record into the
/// [GroupGameTable].
Future<void> addGroupToGame({
required String gameId,
required String groupId,
}) async {
if (await gameHasGroup(gameId: gameId)) {
throw Exception('Game already has a group');
}
await into(groupGameTable).insert(
GroupGameTableCompanion.insert(groupId: groupId, gameId: gameId),
mode: InsertMode.insertOrReplace,
);
}
/// Retrieves the [Group] associated with the given [gameId].
/// Returns `null` if no group is found.
Future<Group?> getGroupOfGame({required String gameId}) async {
final result = await (select(
groupGameTable,
)..where((g) => g.gameId.equals(gameId))).getSingleOrNull();
if (result == null) {
return null;
}
final group = await db.groupDao.getGroupById(groupId: result.groupId);
return group;
}
/// Checks if there is a group associated with the given [gameId].
/// Returns `true` if there is a group, otherwise `false`.
Future<bool> gameHasGroup({required String gameId}) async {
final count =
await (selectOnly(groupGameTable)
..where(groupGameTable.gameId.equals(gameId))
..addColumns([groupGameTable.groupId.count()]))
.map((row) => row.read(groupGameTable.groupId.count()))
.getSingle();
return (count ?? 0) > 0;
}
/// Checks if a specific group is associated with a specific game.
/// Returns `true` if the group is in the game, otherwise `false`.
Future<bool> isGroupInGame({
required String gameId,
required String groupId,
}) async {
final count =
await (selectOnly(groupGameTable)
..where(
groupGameTable.gameId.equals(gameId) &
groupGameTable.groupId.equals(groupId),
)
..addColumns([groupGameTable.groupId.count()]))
.map((row) => row.read(groupGameTable.groupId.count()))
.getSingle();
return (count ?? 0) > 0;
}
/// Removes the association of a group from a game based on [groupId] and
/// [gameId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> removeGroupFromGame({
required String gameId,
required String groupId,
}) async {
final query = delete(groupGameTable)
..where((g) => g.gameId.equals(gameId) & g.groupId.equals(groupId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Updates the group associated with a game to [newGroupId] based on
/// [gameId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateGroupOfGame({
required String gameId,
required String newGroupId,
}) async {
final updatedRows =
await (update(groupGameTable)..where((g) => g.gameId.equals(gameId)))
.write(GroupGameTableCompanion(groupId: Value(newGroupId)));
return updatedRows > 0;
}
}

View File

@@ -1,10 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'group_game_dao.dart';
// ignore_for_file: type=lint
mixin _$GroupGameDaoMixin on DatabaseAccessor<AppDatabase> {
$GroupTableTable get groupTable => attachedDatabase.groupTable;
$GameTableTable get gameTable => attachedDatabase.gameTable;
$GroupGameTableTable get groupGameTable => attachedDatabase.groupGameTable;
}

View File

@@ -0,0 +1,98 @@
import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/db/tables/group_match_table.dart';
import 'package:game_tracker/data/dto/group.dart';
part 'group_match_dao.g.dart';
@DriftAccessor(tables: [GroupMatchTable])
class GroupMatchDao extends DatabaseAccessor<AppDatabase>
with _$GroupMatchDaoMixin {
GroupMatchDao(super.db);
/// Associates a group with a match by inserting a record into the
/// [GroupMatchTable].
Future<void> addGroupToMatch({
required String matchId,
required String groupId,
}) async {
if (await matchHasGroup(matchId: matchId)) {
throw Exception('Match already has a group');
}
await into(groupMatchTable).insert(
GroupMatchTableCompanion.insert(groupId: groupId, matchId: matchId),
mode: InsertMode.insertOrReplace,
);
}
/// Retrieves the [Group] associated with the given [matchId].
/// Returns `null` if no group is found.
Future<Group?> getGroupOfMatch({required String matchId}) async {
final result = await (select(
groupMatchTable,
)..where((g) => g.matchId.equals(matchId))).getSingleOrNull();
if (result == null) {
return null;
}
final group = await db.groupDao.getGroupById(groupId: result.groupId);
return group;
}
/// Checks if there is a group associated with the given [matchId].
/// Returns `true` if there is a group, otherwise `false`.
Future<bool> matchHasGroup({required String matchId}) async {
final count =
await (selectOnly(groupMatchTable)
..where(groupMatchTable.matchId.equals(matchId))
..addColumns([groupMatchTable.groupId.count()]))
.map((row) => row.read(groupMatchTable.groupId.count()))
.getSingle();
return (count ?? 0) > 0;
}
/// Checks if a specific group is associated with a specific match.
/// Returns `true` if the group is in the match, otherwise `false`.
Future<bool> isGroupInMatch({
required String matchId,
required String groupId,
}) async {
final count =
await (selectOnly(groupMatchTable)
..where(
groupMatchTable.matchId.equals(matchId) &
groupMatchTable.groupId.equals(groupId),
)
..addColumns([groupMatchTable.groupId.count()]))
.map((row) => row.read(groupMatchTable.groupId.count()))
.getSingle();
return (count ?? 0) > 0;
}
/// Removes the association of a group from a match based on [groupId] and
/// [matchId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> removeGroupFromMatch({
required String matchId,
required String groupId,
}) async {
final query = delete(groupMatchTable)
..where((g) => g.matchId.equals(matchId) & g.groupId.equals(groupId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Updates the group associated with a match to [newGroupId] based on
/// [matchId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateGroupOfMatch({
required String matchId,
required String newGroupId,
}) async {
final updatedRows =
await (update(groupMatchTable)..where((g) => g.matchId.equals(matchId)))
.write(GroupMatchTableCompanion(groupId: Value(newGroupId)));
return updatedRows > 0;
}
}

View File

@@ -0,0 +1,10 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'group_match_dao.dart';
// ignore_for_file: type=lint
mixin _$GroupMatchDaoMixin on DatabaseAccessor<AppDatabase> {
$GroupTableTable get groupTable => attachedDatabase.groupTable;
$MatchTableTable get matchTable => attachedDatabase.matchTable;
$GroupMatchTableTable get groupMatchTable => attachedDatabase.groupMatchTable;
}

322
lib/data/dao/match_dao.dart Normal file
View File

@@ -0,0 +1,322 @@
import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/db/tables/match_table.dart';
import 'package:game_tracker/data/dto/group.dart';
import 'package:game_tracker/data/dto/match.dart';
import 'package:game_tracker/data/dto/player.dart';
part 'match_dao.g.dart';
@DriftAccessor(tables: [MatchTable])
class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
MatchDao(super.db);
/// Retrieves all matches from the database.
Future<List<Match>> getAllMatches() async {
final query = select(matchTable);
final result = await query.get();
return Future.wait(
result.map((row) async {
final group = await db.groupMatchDao.getGroupOfMatch(matchId: row.id);
final players = await db.playerMatchDao.getPlayersOfMatch(
matchId: row.id,
);
final winner = row.winnerId != null
? await db.playerDao.getPlayerById(playerId: row.winnerId!)
: null;
return Match(
id: row.id,
name: row.name,
group: group,
players: players,
createdAt: row.createdAt,
winner: winner,
);
}),
);
}
/// Retrieves a [Match] by its [matchId].
Future<Match> getMatchById({required String matchId}) async {
final query = select(matchTable)..where((g) => g.id.equals(matchId));
final result = await query.getSingle();
List<Player>? players;
if (await db.playerMatchDao.matchHasPlayers(matchId: matchId)) {
players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId);
}
Group? group;
if (await db.groupMatchDao.matchHasGroup(matchId: matchId)) {
group = await db.groupMatchDao.getGroupOfMatch(matchId: matchId);
}
Player? winner;
if (result.winnerId != null) {
winner = await db.playerDao.getPlayerById(playerId: result.winnerId!);
}
return Match(
id: result.id,
name: result.name,
players: players,
group: group,
winner: winner,
createdAt: result.createdAt,
);
}
/// Adds a new [Match] to the database.
/// Also adds associated players and group if they exist.
Future<void> addMatch({required Match match}) async {
await db.transaction(() async {
await into(matchTable).insert(
MatchTableCompanion.insert(
id: match.id,
name: match.name,
winnerId: Value(match.winner?.id),
createdAt: match.createdAt,
),
mode: InsertMode.insertOrReplace,
);
if (match.players != null) {
await db.playerDao.addPlayersAsList(players: match.players!);
for (final p in match.players ?? []) {
await db.playerMatchDao.addPlayerToMatch(
matchId: match.id,
playerId: p.id,
);
}
}
if (match.group != null) {
await db.groupDao.addGroup(group: match.group!);
await db.groupMatchDao.addGroupToMatch(
matchId: match.id,
groupId: match.group!.id,
);
}
});
}
/// Adds multiple [Match]s to the database in a batch operation.
/// Also adds associated players and groups if they exist.
/// If the [matches] list is empty, the method returns immediately.
Future<void> addMatchAsList({required List<Match> matches}) async {
if (matches.isEmpty) return;
await db.transaction(() async {
// Add all matches in batch
await db.batch(
(b) => b.insertAll(
matchTable,
matches
.map(
(match) => MatchTableCompanion.insert(
id: match.id,
name: match.name,
createdAt: match.createdAt,
winnerId: Value(match.winner?.id),
),
)
.toList(),
mode: InsertMode.insertOrReplace,
),
);
// Add all groups of the matches in batch
await db.batch(
(b) => b.insertAll(
db.groupTable,
matches
.where((match) => match.group != null)
.map(
(matches) => GroupTableCompanion.insert(
id: matches.group!.id,
name: matches.group!.name,
createdAt: matches.group!.createdAt,
),
)
.toList(),
mode: InsertMode.insertOrReplace,
),
);
// Add all players of the matches in batch (unique)
final uniquePlayers = <String, Player>{};
for (final match in matches) {
if (match.players != null) {
for (final p in match.players!) {
uniquePlayers[p.id] = p;
}
}
// Also include members of groups
if (match.group != null) {
for (final m in match.group!.members) {
uniquePlayers[m.id] = m;
}
}
}
if (uniquePlayers.isNotEmpty) {
await db.batch(
(b) => b.insertAll(
db.playerTable,
uniquePlayers.values
.map(
(p) => PlayerTableCompanion.insert(
id: p.id,
name: p.name,
createdAt: p.createdAt,
),
)
.toList(),
mode: InsertMode.insertOrReplace,
),
);
}
// Add all player-match associations in batch
await db.batch((b) {
for (final match in matches) {
if (match.players != null) {
for (final p in match.players ?? []) {
b.insert(
db.playerMatchTable,
PlayerMatchTableCompanion.insert(
matchId: match.id,
playerId: p.id,
),
mode: InsertMode.insertOrReplace,
);
}
}
}
});
// Add all player-group associations in batch
await db.batch((b) {
for (final match in matches) {
if (match.group != null) {
for (final m in match.group!.members) {
b.insert(
db.playerGroupTable,
PlayerGroupTableCompanion.insert(
playerId: m.id,
groupId: match.group!.id,
),
mode: InsertMode.insertOrReplace,
);
}
}
}
});
// Add all group-match associations in batch
await db.batch((b) {
for (final match in matches) {
if (match.group != null) {
b.insert(
db.groupMatchTable,
GroupMatchTableCompanion.insert(
matchId: match.id,
groupId: match.group!.id,
),
mode: InsertMode.insertOrReplace,
);
}
}
});
});
}
/// Deletes the match with the given [matchId] from the database.
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteMatch({required String matchId}) async {
final query = delete(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Retrieves the number of matches in the database.
Future<int> getMatchCount() async {
final count =
await (selectOnly(matchTable)..addColumns([matchTable.id.count()]))
.map((row) => row.read(matchTable.id.count()))
.getSingle();
return count ?? 0;
}
/// Checks if a match with the given [matchId] exists in the database.
/// Returns `true` if the match exists, otherwise `false`.
Future<bool> matchExists({required String matchId}) async {
final query = select(matchTable)..where((g) => g.id.equals(matchId));
final result = await query.getSingleOrNull();
return result != null;
}
/// Deletes all matches from the database.
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> deleteAllMatches() async {
final query = delete(matchTable);
final rowsAffected = await query.go();
return rowsAffected > 0;
}
/// Sets the winner of the match with the given [matchId] to the player with
/// the given [winnerId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> setWinner({
required String matchId,
required String winnerId,
}) async {
final query = update(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.write(
MatchTableCompanion(winnerId: Value(winnerId)),
);
return rowsAffected > 0;
}
/// Retrieves the winner of the match with the given [matchId].
/// Returns the [Player] who won the match, or `null` if no winner is set.
Future<Player?> getWinner({required String matchId}) async {
final query = select(matchTable)..where((g) => g.id.equals(matchId));
final result = await query.getSingleOrNull();
if (result == null || result.winnerId == null) {
return null;
}
final winner = await db.playerDao.getPlayerById(playerId: result.winnerId!);
return winner;
}
/// Removes the winner of the match with the given [matchId].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> removeWinner({required String matchId}) async {
final query = update(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.write(
const MatchTableCompanion(winnerId: Value(null)),
);
return rowsAffected > 0;
}
/// Checks if the match with the given [matchId] has a winner set.
/// Returns `true` if a winner is set, otherwise `false`.
Future<bool> hasWinner({required String matchId}) async {
final query = select(matchTable)
..where((g) => g.id.equals(matchId) & g.winnerId.isNotNull());
final result = await query.getSingleOrNull();
return result != null;
}
/// Changes the title of the match with the given [matchId] to [newName].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateMatchName({
required String matchId,
required String newName,
}) async {
final query = update(matchTable)..where((g) => g.id.equals(matchId));
final rowsAffected = await query.write(
MatchTableCompanion(name: Value(newName)),
);
return rowsAffected > 0;
}
}

View File

@@ -0,0 +1,8 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'match_dao.dart';
// ignore_for_file: type=lint
mixin _$MatchDaoMixin on DatabaseAccessor<AppDatabase> {
$MatchTableTable get matchTable => attachedDatabase.matchTable;
}

View File

@@ -1,10 +0,0 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'player_game_dao.dart';
// ignore_for_file: type=lint
mixin _$PlayerGameDaoMixin on DatabaseAccessor<AppDatabase> {
$PlayerTableTable get playerTable => attachedDatabase.playerTable;
$GameTableTable get gameTable => attachedDatabase.gameTable;
$PlayerGameTableTable get playerGameTable => attachedDatabase.playerGameTable;
}

View File

@@ -1,11 +1,12 @@
import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/db/tables/player_group_table.dart';
import 'package:game_tracker/data/db/tables/player_table.dart';
import 'package:game_tracker/data/dto/player.dart';
part 'player_group_dao.g.dart';
@DriftAccessor(tables: [PlayerGroupTable])
@DriftAccessor(tables: [PlayerGroupTable, PlayerTable])
class PlayerGroupDao extends DatabaseAccessor<AppDatabase>
with _$PlayerGroupDaoMixin {
PlayerGroupDao(super.db);

View File

@@ -1,33 +1,33 @@
import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/db/tables/player_game_table.dart';
import 'package:game_tracker/data/db/tables/player_match_table.dart';
import 'package:game_tracker/data/dto/player.dart';
part 'player_game_dao.g.dart';
part 'player_match_dao.g.dart';
@DriftAccessor(tables: [PlayerGameTable])
class PlayerGameDao extends DatabaseAccessor<AppDatabase>
with _$PlayerGameDaoMixin {
PlayerGameDao(super.db);
@DriftAccessor(tables: [PlayerMatchTable])
class PlayerMatchDao extends DatabaseAccessor<AppDatabase>
with _$PlayerMatchDaoMixin {
PlayerMatchDao(super.db);
/// Associates a player with a game by inserting a record into the
/// [PlayerGameTable].
Future<void> addPlayerToGame({
required String gameId,
/// Associates a player with a match by inserting a record into the
/// [PlayerMatchTable].
Future<void> addPlayerToMatch({
required String matchId,
required String playerId,
}) async {
await into(playerGameTable).insert(
PlayerGameTableCompanion.insert(playerId: playerId, gameId: gameId),
await into(playerMatchTable).insert(
PlayerMatchTableCompanion.insert(playerId: playerId, matchId: matchId),
mode: InsertMode.insertOrReplace,
);
}
/// Retrieves a list of [Player]s associated with the given [gameId].
/// Retrieves a list of [Player]s associated with the given [matchId].
/// Returns null if no players are found.
Future<List<Player>?> getPlayersOfGame({required String gameId}) async {
Future<List<Player>?> getPlayersOfMatch({required String matchId}) async {
final result = await (select(
playerGameTable,
)..where((p) => p.gameId.equals(gameId))).get();
playerMatchTable,
)..where((p) => p.matchId.equals(matchId))).get();
if (result.isEmpty) return null;
@@ -38,43 +38,43 @@ class PlayerGameDao extends DatabaseAccessor<AppDatabase>
return players;
}
/// Checks if there are any players associated with the given [gameId].
/// Checks if there are any players associated with the given [matchId].
/// Returns `true` if there are players, otherwise `false`.
Future<bool> gameHasPlayers({required String gameId}) async {
Future<bool> matchHasPlayers({required String matchId}) async {
final count =
await (selectOnly(playerGameTable)
..where(playerGameTable.gameId.equals(gameId))
..addColumns([playerGameTable.playerId.count()]))
.map((row) => row.read(playerGameTable.playerId.count()))
await (selectOnly(playerMatchTable)
..where(playerMatchTable.matchId.equals(matchId))
..addColumns([playerMatchTable.playerId.count()]))
.map((row) => row.read(playerMatchTable.playerId.count()))
.getSingle();
return (count ?? 0) > 0;
}
/// Checks if a specific player is associated with a specific game.
/// Returns `true` if the player is in the game, otherwise `false`.
Future<bool> isPlayerInGame({
required String gameId,
/// Checks if a specific player is associated with a specific match.
/// Returns `true` if the player is in the match, otherwise `false`.
Future<bool> isPlayerInMatch({
required String matchId,
required String playerId,
}) async {
final count =
await (selectOnly(playerGameTable)
..where(playerGameTable.gameId.equals(gameId))
..where(playerGameTable.playerId.equals(playerId))
..addColumns([playerGameTable.playerId.count()]))
.map((row) => row.read(playerGameTable.playerId.count()))
await (selectOnly(playerMatchTable)
..where(playerMatchTable.matchId.equals(matchId))
..where(playerMatchTable.playerId.equals(playerId))
..addColumns([playerMatchTable.playerId.count()]))
.map((row) => row.read(playerMatchTable.playerId.count()))
.getSingle();
return (count ?? 0) > 0;
}
/// Removes the association of a player with a game by deleting the record
/// from the [PlayerGameTable].
/// from the [PlayerMatchTable].
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> removePlayerFromGame({
required String gameId,
Future<bool> removePlayerFromMatch({
required String matchId,
required String playerId,
}) async {
final query = delete(playerGameTable)
..where((pg) => pg.gameId.equals(gameId))
final query = delete(playerMatchTable)
..where((pg) => pg.matchId.equals(matchId))
..where((pg) => pg.playerId.equals(playerId));
final rowsAffected = await query.go();
return rowsAffected > 0;
@@ -83,11 +83,11 @@ class PlayerGameDao extends DatabaseAccessor<AppDatabase>
/// 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<void> updatePlayersFromGame({
required String gameId,
Future<void> updatePlayersFromMatch({
required String matchId,
required List<Player> newPlayer,
}) async {
final currentPlayers = await getPlayersOfGame(gameId: gameId);
final currentPlayers = await getPlayersOfMatch(matchId: matchId);
// Create sets of player IDs for easy comparison
final currentPlayerIds = currentPlayers?.map((p) => p.id).toSet() ?? {};
final newPlayerIdsSet = newPlayer.map((p) => p.id).toSet();
@@ -99,9 +99,9 @@ class PlayerGameDao extends DatabaseAccessor<AppDatabase>
db.transaction(() async {
// Remove old players
if (playersToRemove.isNotEmpty) {
await (delete(playerGameTable)..where(
await (delete(playerMatchTable)..where(
(pg) =>
pg.gameId.equals(gameId) &
pg.matchId.equals(matchId) &
pg.playerId.isIn(playersToRemove.toList()),
))
.go();
@@ -111,14 +111,16 @@ class PlayerGameDao extends DatabaseAccessor<AppDatabase>
if (playersToAdd.isNotEmpty) {
final inserts = playersToAdd
.map(
(id) =>
PlayerGameTableCompanion.insert(playerId: id, gameId: gameId),
(id) => PlayerMatchTableCompanion.insert(
playerId: id,
matchId: matchId,
),
)
.toList();
await Future.wait(
inserts.map(
(c) => into(
playerGameTable,
playerMatchTable,
).insert(c, mode: InsertMode.insertOrReplace),
),
);

View File

@@ -0,0 +1,11 @@
// GENERATED CODE - DO NOT MODIFY BY HAND
part of 'player_match_dao.dart';
// ignore_for_file: type=lint
mixin _$PlayerMatchDaoMixin on DatabaseAccessor<AppDatabase> {
$PlayerTableTable get playerTable => attachedDatabase.playerTable;
$MatchTableTable get matchTable => attachedDatabase.matchTable;
$PlayerMatchTableTable get playerMatchTable =>
attachedDatabase.playerMatchTable;
}