Merge branch 'development' into feature/119-implementierung-der-games-2
# Conflicts: # lib/data/dao/match_dao.dart
This commit is contained in:
@@ -8,6 +8,7 @@ import 'package:tallee/data/models/game.dart';
|
||||
import 'package:tallee/data/models/group.dart';
|
||||
import 'package:tallee/data/models/match.dart';
|
||||
import 'package:tallee/data/models/player.dart';
|
||||
import 'package:tallee/data/models/team.dart';
|
||||
|
||||
part 'match_dao.g.dart';
|
||||
|
||||
@@ -15,74 +16,13 @@ part 'match_dao.g.dart';
|
||||
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();
|
||||
/* Create */
|
||||
|
||||
return Future.wait(
|
||||
result.map((row) async {
|
||||
final game = await db.gameDao.getGameById(gameId: row.gameId);
|
||||
Group? group;
|
||||
if (row.groupId != null) {
|
||||
group = await db.groupDao.getGroupById(groupId: row.groupId!);
|
||||
}
|
||||
final players =
|
||||
await db.playerMatchDao.getPlayersOfMatch(matchId: row.id) ?? [];
|
||||
|
||||
final scores = await db.scoreEntryDao.getAllMatchScores(
|
||||
matchId: row.id,
|
||||
);
|
||||
|
||||
return Match(
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
game: game,
|
||||
group: group,
|
||||
players: players,
|
||||
notes: row.notes ?? '',
|
||||
createdAt: row.createdAt,
|
||||
endedAt: row.endedAt,
|
||||
scores: scores,
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/// 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();
|
||||
|
||||
final game = await db.gameDao.getGameById(gameId: result.gameId);
|
||||
|
||||
Group? group;
|
||||
if (result.groupId != null) {
|
||||
group = await db.groupDao.getGroupById(groupId: result.groupId!);
|
||||
}
|
||||
|
||||
final players =
|
||||
await db.playerMatchDao.getPlayersOfMatch(matchId: matchId) ?? [];
|
||||
|
||||
final scores = await db.scoreEntryDao.getAllMatchScores(matchId: matchId);
|
||||
|
||||
return Match(
|
||||
id: result.id,
|
||||
name: result.name,
|
||||
game: game,
|
||||
group: group,
|
||||
players: players,
|
||||
notes: result.notes ?? '',
|
||||
createdAt: result.createdAt,
|
||||
endedAt: result.endedAt,
|
||||
scores: scores,
|
||||
);
|
||||
}
|
||||
|
||||
/// Adds a new [Match] to the database. Also adds players associations.
|
||||
/// Adds a new [Match] to the database. Also adds players associations and teams.
|
||||
/// This method assumes that the game and group (if any) are already present
|
||||
/// in the database.
|
||||
Future<void> addMatch({required Match match}) async {
|
||||
Future<bool> addMatch({required Match match}) async {
|
||||
if (await matchExists(matchId: match.id)) return false;
|
||||
await db.transaction(() async {
|
||||
await into(matchTable).insert(
|
||||
MatchTableCompanion.insert(
|
||||
@@ -90,18 +30,36 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
|
||||
gameId: match.game.id,
|
||||
groupId: Value(match.group?.id),
|
||||
name: match.name,
|
||||
notes: Value(match.notes),
|
||||
notes: match.notes,
|
||||
createdAt: match.createdAt,
|
||||
endedAt: Value(match.endedAt),
|
||||
),
|
||||
mode: InsertMode.insertOrReplace,
|
||||
);
|
||||
|
||||
// Add teams
|
||||
if (match.teams != null && match.teams!.isNotEmpty) {
|
||||
await db.teamDao.addTeamsAsList(teams: match.teams!, matchId: match.id);
|
||||
}
|
||||
|
||||
// Collect all player IDs that are already in teams
|
||||
final playersInTeams = <String>{};
|
||||
if (match.teams != null) {
|
||||
for (final team in match.teams!) {
|
||||
for (final member in team.members) {
|
||||
playersInTeams.add(member.id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Add players that are not in teams
|
||||
for (final p in match.players) {
|
||||
await db.playerMatchDao.addPlayerToMatch(
|
||||
matchId: match.id,
|
||||
playerId: p.id,
|
||||
);
|
||||
if (!playersInTeams.contains(p.id)) {
|
||||
await db.playerMatchDao.addPlayerToMatch(
|
||||
matchId: match.id,
|
||||
playerId: p.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
for (final pid in match.scores.keys) {
|
||||
@@ -115,14 +73,15 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Adds multiple [Match]es 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.
|
||||
/// This method should only be used to import matches from a different device.
|
||||
Future<void> addMatchAsList({required List<Match> matches}) async {
|
||||
if (matches.isEmpty) return;
|
||||
Future<bool> addMatchesAsList({required List<Match> matches}) async {
|
||||
if (matches.isEmpty) return false;
|
||||
await db.transaction(() async {
|
||||
// Add all games first (deduplicated)
|
||||
final uniqueGames = <String, Game>{};
|
||||
@@ -183,7 +142,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
|
||||
gameId: match.game.id,
|
||||
groupId: Value(match.group?.id),
|
||||
name: match.name,
|
||||
notes: Value(match.notes),
|
||||
notes: match.notes,
|
||||
createdAt: match.createdAt,
|
||||
endedAt: Value(match.endedAt),
|
||||
),
|
||||
@@ -279,15 +238,28 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Add teams for matches
|
||||
for (final match in matches) {
|
||||
if (match.teams != null && match.teams!.isNotEmpty) {
|
||||
await db.teamDao.addTeamsAsList(
|
||||
teams: match.teams!,
|
||||
matchId: match.id,
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
/// 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;
|
||||
/* Read */
|
||||
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// Retrieves the number of matches in the database.
|
||||
@@ -299,6 +271,76 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
|
||||
return count ?? 0;
|
||||
}
|
||||
|
||||
/// 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 game = await db.gameDao.getGameById(gameId: row.gameId);
|
||||
Group? group;
|
||||
if (row.groupId != null) {
|
||||
group = await db.groupDao.getGroupById(groupId: row.groupId!);
|
||||
}
|
||||
final players = await db.playerMatchDao.getPlayersOfMatch(
|
||||
matchId: row.id,
|
||||
);
|
||||
|
||||
final scores = await db.scoreEntryDao.getAllMatchScores(
|
||||
matchId: row.id,
|
||||
);
|
||||
|
||||
final teams = await _getMatchTeams(matchId: row.id);
|
||||
|
||||
return Match(
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
game: game,
|
||||
group: group,
|
||||
players: players,
|
||||
teams: teams.isEmpty ? null : teams,
|
||||
notes: row.notes,
|
||||
createdAt: row.createdAt,
|
||||
endedAt: row.endedAt,
|
||||
scores: scores,
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/// 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();
|
||||
|
||||
final game = await db.gameDao.getGameById(gameId: result.gameId);
|
||||
|
||||
Group? group;
|
||||
if (result.groupId != null) {
|
||||
group = await db.groupDao.getGroupById(groupId: result.groupId!);
|
||||
}
|
||||
|
||||
final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId);
|
||||
|
||||
final scores = await db.scoreEntryDao.getAllMatchScores(matchId: matchId);
|
||||
|
||||
final teams = await _getMatchTeams(matchId: matchId);
|
||||
|
||||
return Match(
|
||||
id: result.id,
|
||||
name: result.name,
|
||||
game: game,
|
||||
group: group,
|
||||
players: players,
|
||||
teams: teams.isEmpty ? null : teams,
|
||||
notes: result.notes,
|
||||
createdAt: result.createdAt,
|
||||
endedAt: result.endedAt,
|
||||
scores: scores,
|
||||
);
|
||||
}
|
||||
|
||||
/// Retrieves the number of matches associated with a specific game.
|
||||
Future<int> getMatchCountByGame({required String gameId}) async {
|
||||
final count =
|
||||
@@ -310,14 +352,6 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
|
||||
return count ?? 0;
|
||||
}
|
||||
|
||||
/// Deletes all matches associated with a specific game.
|
||||
/// Returns the number of matches deleted.
|
||||
Future<int> deleteMatchesByGame({required String gameId}) async {
|
||||
final query = delete(matchTable)..where((m) => m.gameId.equals(gameId));
|
||||
final rowsAffected = await query.go();
|
||||
return rowsAffected;
|
||||
}
|
||||
|
||||
/// Retrieves all matches associated with the given [groupId].
|
||||
/// Queries the database directly, filtering by [groupId].
|
||||
Future<List<Match>> getGroupMatches({required String groupId}) async {
|
||||
@@ -328,15 +362,18 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
|
||||
rows.map((row) async {
|
||||
final game = await db.gameDao.getGameById(gameId: row.gameId);
|
||||
final group = await db.groupDao.getGroupById(groupId: groupId);
|
||||
final players =
|
||||
await db.playerMatchDao.getPlayersOfMatch(matchId: row.id) ?? [];
|
||||
final players = await db.playerMatchDao.getPlayersOfMatch(
|
||||
matchId: row.id,
|
||||
);
|
||||
final teams = await _getMatchTeams(matchId: row.id);
|
||||
return Match(
|
||||
id: row.id,
|
||||
name: row.name,
|
||||
game: game,
|
||||
group: group,
|
||||
players: players,
|
||||
notes: row.notes ?? '',
|
||||
teams: teams.isEmpty ? null : teams,
|
||||
notes: row.notes,
|
||||
createdAt: row.createdAt,
|
||||
endedAt: row.endedAt,
|
||||
);
|
||||
@@ -344,19 +381,56 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
|
||||
);
|
||||
}
|
||||
|
||||
/// 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;
|
||||
/// Helper method to retrieve teams for a specific match
|
||||
Future<List<Team>> _getMatchTeams({required String matchId}) async {
|
||||
// Get all unique team IDs from PlayerMatchTable for this match
|
||||
final playerMatchQuery = select(db.playerMatchTable)
|
||||
..where((pm) => pm.matchId.equals(matchId) & pm.teamId.isNotNull());
|
||||
final playerMatches = await playerMatchQuery.get();
|
||||
|
||||
if (playerMatches.isEmpty) return [];
|
||||
|
||||
final teamIds = playerMatches
|
||||
.map((pm) => pm.teamId)
|
||||
.whereType<String>()
|
||||
.toSet()
|
||||
.toList();
|
||||
|
||||
// Fetch all teams
|
||||
final teams = await Future.wait(
|
||||
teamIds.map((teamId) => db.teamDao.getTeamById(teamId: teamId)),
|
||||
);
|
||||
|
||||
return teams;
|
||||
}
|
||||
|
||||
/// Deletes all matches from the database.
|
||||
/* Update */
|
||||
|
||||
/// Changes the name of the match with the given [matchId] to [name].
|
||||
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
||||
Future<bool> deleteAllMatches() async {
|
||||
final query = delete(matchTable);
|
||||
final rowsAffected = await query.go();
|
||||
Future<bool> updateMatchName({
|
||||
required String matchId,
|
||||
required String name,
|
||||
}) async {
|
||||
final query = update(matchTable)..where((g) => g.id.equals(matchId));
|
||||
final rowsAffected = await query.write(
|
||||
MatchTableCompanion(name: Value(name)),
|
||||
);
|
||||
return rowsAffected > 0;
|
||||
}
|
||||
|
||||
/// Updates the group of the match with the given [matchId].
|
||||
/// Replaces the existing group association with the new group specified by [groupId].
|
||||
/// Pass null to remove the group association.
|
||||
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
||||
Future<bool> updateMatchGroup({
|
||||
required String matchId,
|
||||
required String? groupId,
|
||||
}) async {
|
||||
final query = update(matchTable)..where((g) => g.id.equals(matchId));
|
||||
final rowsAffected = await query.write(
|
||||
MatchTableCompanion(groupId: Value(groupId)),
|
||||
);
|
||||
return rowsAffected > 0;
|
||||
}
|
||||
|
||||
@@ -364,7 +438,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
|
||||
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
||||
Future<bool> updateMatchNotes({
|
||||
required String matchId,
|
||||
required String? notes,
|
||||
required String notes,
|
||||
}) async {
|
||||
final query = update(matchTable)..where((g) => g.id.equals(matchId));
|
||||
final rowsAffected = await query.write(
|
||||
@@ -373,47 +447,6 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
|
||||
return rowsAffected > 0;
|
||||
}
|
||||
|
||||
/// Changes the name 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;
|
||||
}
|
||||
|
||||
/// Updates the game of the match with the given [matchId].
|
||||
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
||||
Future<bool> updateMatchGame({
|
||||
required String matchId,
|
||||
required String gameId,
|
||||
}) async {
|
||||
final query = update(matchTable)..where((g) => g.id.equals(matchId));
|
||||
final rowsAffected = await query.write(
|
||||
MatchTableCompanion(gameId: Value(gameId)),
|
||||
);
|
||||
return rowsAffected > 0;
|
||||
}
|
||||
|
||||
/// Updates the group of the match with the given [matchId].
|
||||
/// Replaces the existing group association with the new group specified by [newGroupId].
|
||||
/// Pass null to remove the group association.
|
||||
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
||||
Future<bool> updateMatchGroup({
|
||||
required String matchId,
|
||||
required String? newGroupId,
|
||||
}) async {
|
||||
final query = update(matchTable)..where((g) => g.id.equals(matchId));
|
||||
final rowsAffected = await query.write(
|
||||
MatchTableCompanion(groupId: Value(newGroupId)),
|
||||
);
|
||||
return rowsAffected > 0;
|
||||
}
|
||||
|
||||
/// Removes the group association of the match with the given [matchId].
|
||||
/// Sets the groupId to null.
|
||||
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
||||
@@ -425,25 +458,12 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
|
||||
return rowsAffected > 0;
|
||||
}
|
||||
|
||||
/// Updates the createdAt timestamp of the match with the given [matchId].
|
||||
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
||||
Future<bool> updateMatchCreatedAt({
|
||||
required String matchId,
|
||||
required DateTime createdAt,
|
||||
}) async {
|
||||
final query = update(matchTable)..where((g) => g.id.equals(matchId));
|
||||
final rowsAffected = await query.write(
|
||||
MatchTableCompanion(createdAt: Value(createdAt)),
|
||||
);
|
||||
return rowsAffected > 0;
|
||||
}
|
||||
|
||||
/// Updates the endedAt timestamp of the match with the given [matchId].
|
||||
/// Pass null to remove the ended time (mark match as ongoing).
|
||||
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
||||
Future<bool> updateMatchEndedAt({
|
||||
required String matchId,
|
||||
required DateTime? endedAt,
|
||||
required DateTime endedAt,
|
||||
}) async {
|
||||
final query = update(matchTable)..where((g) => g.id.equals(matchId));
|
||||
final rowsAffected = await query.write(
|
||||
@@ -452,37 +472,29 @@ 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();
|
||||
/* Delete */
|
||||
|
||||
// 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);
|
||||
}
|
||||
}),
|
||||
);
|
||||
/// 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;
|
||||
}
|
||||
|
||||
// Add the new players to the match
|
||||
await Future.wait(
|
||||
newPlayers.map(
|
||||
(player) => db.playerMatchDao.addPlayerToMatch(
|
||||
matchId: matchId,
|
||||
playerId: player.id,
|
||||
),
|
||||
),
|
||||
);
|
||||
});
|
||||
/// 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;
|
||||
}
|
||||
|
||||
/// Deletes all matches associated with a specific game.
|
||||
/// Returns the number of matches deleted.
|
||||
Future<int> deleteMatchesByGame({required String gameId}) async {
|
||||
final query = delete(matchTable)..where((m) => m.gameId.equals(gameId));
|
||||
final rowsAffected = await query.go();
|
||||
return rowsAffected;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user