Compare commits
7 Commits
867d0c55da
...
b9b6ff85ea
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b9b6ff85ea | ||
|
|
52c1605ce9 | ||
|
|
c2a9bda8b1 | ||
|
|
a13d9c55ea | ||
|
|
b737cae356 | ||
|
|
3857665444 | ||
|
|
4b900c12bf |
8
lib/data/dao/game_dao.g.dart
Normal file
8
lib/data/dao/game_dao.g.dart
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// 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;
|
||||||
|
}
|
||||||
@@ -1,108 +0,0 @@
|
|||||||
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/db/tables/group_table.dart';
|
|
||||||
import 'package:game_tracker/data/dto/group.dart';
|
|
||||||
|
|
||||||
part 'group_match_dao.g.dart';
|
|
||||||
|
|
||||||
@DriftAccessor(tables: [GroupMatchTable, GroupTable])
|
|
||||||
class GroupMatchDao extends DatabaseAccessor<AppDatabase>
|
|
||||||
with _$GroupMatchDaoMixin {
|
|
||||||
GroupMatchDao(super.db);
|
|
||||||
|
|
||||||
/// Adds a group to a match by inserting a record into the [GroupMatchTable].
|
|
||||||
Future<void> addGroupToMatch({
|
|
||||||
required String matchId,
|
|
||||||
required String groupId,
|
|
||||||
}) async {
|
|
||||||
await into(groupMatchTable).insert(
|
|
||||||
GroupMatchTableCompanion.insert(
|
|
||||||
matchId: matchId,
|
|
||||||
groupId: groupId,
|
|
||||||
),
|
|
||||||
mode: InsertMode.insertOrIgnore,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieves the [Group] associated with the given [matchId].
|
|
||||||
/// Returns null if no group is found.
|
|
||||||
Future<Group?> getGroupOfMatch({required String matchId}) async {
|
|
||||||
final query = select(groupMatchTable)
|
|
||||||
..where((gm) => gm.matchId.equals(matchId));
|
|
||||||
final result = await query.getSingleOrNull();
|
|
||||||
|
|
||||||
if (result == null) return null;
|
|
||||||
|
|
||||||
return db.groupDao.getGroupById(groupId: result.groupId);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Checks if a match has a group associated with it.
|
|
||||||
/// Returns `true` if the match has 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 query = select(groupMatchTable)
|
|
||||||
..where(
|
|
||||||
(gm) => gm.matchId.equals(matchId) & gm.groupId.equals(groupId),
|
|
||||||
);
|
|
||||||
final result = await query.getSingleOrNull();
|
|
||||||
return result != null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Removes the association of a group with a match by deleting the record
|
|
||||||
/// from the [GroupMatchTable].
|
|
||||||
/// 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((gm) => gm.matchId.equals(matchId) & gm.groupId.equals(groupId));
|
|
||||||
final rowsAffected = await query.go();
|
|
||||||
return rowsAffected > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Updates the group associated with a match.
|
|
||||||
/// Removes the existing group association and adds the new one.
|
|
||||||
Future<void> updateGroupOfMatch({
|
|
||||||
required String matchId,
|
|
||||||
required String newGroupId,
|
|
||||||
}) async {
|
|
||||||
await db.transaction(() async {
|
|
||||||
// Remove existing group association
|
|
||||||
await (delete(groupMatchTable)
|
|
||||||
..where((gm) => gm.matchId.equals(matchId)))
|
|
||||||
.go();
|
|
||||||
|
|
||||||
// Add new group association
|
|
||||||
await into(groupMatchTable).insert(
|
|
||||||
GroupMatchTableCompanion.insert(
|
|
||||||
matchId: matchId,
|
|
||||||
groupId: newGroupId,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Retrieves all matches associated with a specific group.
|
|
||||||
Future<List<String>> getMatchIdsForGroup({required String groupId}) async {
|
|
||||||
final query = select(groupMatchTable)
|
|
||||||
..where((gm) => gm.groupId.equals(groupId));
|
|
||||||
final result = await query.get();
|
|
||||||
return result.map((row) => row.matchId).toList();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -4,5 +4,11 @@ part of 'match_dao.dart';
|
|||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
mixin _$MatchDaoMixin on DatabaseAccessor<AppDatabase> {
|
mixin _$MatchDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||||
|
$GameTableTable get gameTable => attachedDatabase.gameTable;
|
||||||
|
$GroupTableTable get groupTable => attachedDatabase.groupTable;
|
||||||
$MatchTableTable get matchTable => attachedDatabase.matchTable;
|
$MatchTableTable get matchTable => attachedDatabase.matchTable;
|
||||||
|
$PlayerTableTable get playerTable => attachedDatabase.playerTable;
|
||||||
|
$TeamTableTable get teamTable => attachedDatabase.teamTable;
|
||||||
|
$PlayerMatchTableTable get playerMatchTable =>
|
||||||
|
attachedDatabase.playerMatchTable;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,7 +15,12 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
|
|||||||
final result = await query.get();
|
final result = await query.get();
|
||||||
return result
|
return result
|
||||||
.map(
|
.map(
|
||||||
(row) => Player(id: row.id, name: row.name, createdAt: row.createdAt),
|
(row) => Player(
|
||||||
|
id: row.id,
|
||||||
|
name: row.name,
|
||||||
|
description: row.description,
|
||||||
|
createdAt: row.createdAt,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
@@ -27,6 +32,7 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
|
|||||||
return Player(
|
return Player(
|
||||||
id: result.id,
|
id: result.id,
|
||||||
name: result.name,
|
name: result.name,
|
||||||
|
description: result.description,
|
||||||
createdAt: result.createdAt,
|
createdAt: result.createdAt,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -40,6 +46,7 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
|
|||||||
PlayerTableCompanion.insert(
|
PlayerTableCompanion.insert(
|
||||||
id: player.id,
|
id: player.id,
|
||||||
name: player.name,
|
name: player.name,
|
||||||
|
description: Value(player.description),
|
||||||
createdAt: player.createdAt,
|
createdAt: player.createdAt,
|
||||||
),
|
),
|
||||||
mode: InsertMode.insertOrReplace,
|
mode: InsertMode.insertOrReplace,
|
||||||
@@ -63,6 +70,7 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
|
|||||||
(player) => PlayerTableCompanion.insert(
|
(player) => PlayerTableCompanion.insert(
|
||||||
id: player.id,
|
id: player.id,
|
||||||
name: player.name,
|
name: player.name,
|
||||||
|
description: Value(player.description),
|
||||||
createdAt: player.createdAt,
|
createdAt: player.createdAt,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,23 +1,31 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:game_tracker/data/db/database.dart';
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
import 'package:game_tracker/data/db/tables/player_match_table.dart';
|
import 'package:game_tracker/data/db/tables/player_match_table.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/team_table.dart';
|
||||||
import 'package:game_tracker/data/dto/player.dart';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
|
|
||||||
part 'player_match_dao.g.dart';
|
part 'player_match_dao.g.dart';
|
||||||
|
|
||||||
@DriftAccessor(tables: [PlayerMatchTable])
|
@DriftAccessor(tables: [PlayerMatchTable, TeamTable])
|
||||||
class PlayerMatchDao extends DatabaseAccessor<AppDatabase>
|
class PlayerMatchDao extends DatabaseAccessor<AppDatabase>
|
||||||
with _$PlayerMatchDaoMixin {
|
with _$PlayerMatchDaoMixin {
|
||||||
PlayerMatchDao(super.db);
|
PlayerMatchDao(super.db);
|
||||||
|
|
||||||
/// Associates a player with a match by inserting a record into the
|
/// Associates a player with a match by inserting a record into the
|
||||||
/// [PlayerMatchTable].
|
/// [PlayerMatchTable]. Optionally associates with a team and sets initial score.
|
||||||
Future<void> addPlayerToMatch({
|
Future<void> addPlayerToMatch({
|
||||||
required String matchId,
|
required String matchId,
|
||||||
required String playerId,
|
required String playerId,
|
||||||
|
String? teamId,
|
||||||
|
int score = 0,
|
||||||
}) async {
|
}) async {
|
||||||
await into(playerMatchTable).insert(
|
await into(playerMatchTable).insert(
|
||||||
PlayerMatchTableCompanion.insert(playerId: playerId, matchId: matchId),
|
PlayerMatchTableCompanion.insert(
|
||||||
|
playerId: playerId,
|
||||||
|
matchId: matchId,
|
||||||
|
teamId: Value(teamId),
|
||||||
|
score: score,
|
||||||
|
),
|
||||||
mode: InsertMode.insertOrIgnore,
|
mode: InsertMode.insertOrIgnore,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -38,6 +46,50 @@ class PlayerMatchDao extends DatabaseAccessor<AppDatabase>
|
|||||||
return players;
|
return players;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves a player's score for a specific match.
|
||||||
|
/// Returns null if the player is not in the match.
|
||||||
|
Future<int?> getPlayerScore({
|
||||||
|
required String matchId,
|
||||||
|
required String playerId,
|
||||||
|
}) async {
|
||||||
|
final result = await (select(playerMatchTable)
|
||||||
|
..where(
|
||||||
|
(p) => p.matchId.equals(matchId) & p.playerId.equals(playerId),
|
||||||
|
))
|
||||||
|
.getSingleOrNull();
|
||||||
|
return result?.score;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the score for a player in a match.
|
||||||
|
/// Returns `true` if the update was successful, otherwise `false`.
|
||||||
|
Future<bool> updatePlayerScore({
|
||||||
|
required String matchId,
|
||||||
|
required String playerId,
|
||||||
|
required int newScore,
|
||||||
|
}) async {
|
||||||
|
final rowsAffected = await (update(playerMatchTable)
|
||||||
|
..where(
|
||||||
|
(p) => p.matchId.equals(matchId) & p.playerId.equals(playerId),
|
||||||
|
))
|
||||||
|
.write(PlayerMatchTableCompanion(score: Value(newScore)));
|
||||||
|
return rowsAffected > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the team for a player in a match.
|
||||||
|
/// Returns `true` if the update was successful, otherwise `false`.
|
||||||
|
Future<bool> updatePlayerTeam({
|
||||||
|
required String matchId,
|
||||||
|
required String playerId,
|
||||||
|
required String? teamId,
|
||||||
|
}) async {
|
||||||
|
final rowsAffected = await (update(playerMatchTable)
|
||||||
|
..where(
|
||||||
|
(p) => p.matchId.equals(matchId) & p.playerId.equals(playerId),
|
||||||
|
))
|
||||||
|
.write(PlayerMatchTableCompanion(teamId: Value(teamId)));
|
||||||
|
return rowsAffected > 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks if there are any players associated with the given [matchId].
|
/// Checks if there are any players associated with the given [matchId].
|
||||||
/// Returns `true` if there are players, otherwise `false`.
|
/// Returns `true` if there are players, otherwise `false`.
|
||||||
Future<bool> matchHasPlayers({required String matchId}) async {
|
Future<bool> matchHasPlayers({required String matchId}) async {
|
||||||
@@ -114,6 +166,7 @@ class PlayerMatchDao extends DatabaseAccessor<AppDatabase>
|
|||||||
(id) => PlayerMatchTableCompanion.insert(
|
(id) => PlayerMatchTableCompanion.insert(
|
||||||
playerId: id,
|
playerId: id,
|
||||||
matchId: matchId,
|
matchId: matchId,
|
||||||
|
score: 0,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
@@ -127,4 +180,23 @@ class PlayerMatchDao extends DatabaseAccessor<AppDatabase>
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves all players in a specific team for a match.
|
||||||
|
Future<List<Player>> getPlayersInTeam({
|
||||||
|
required String matchId,
|
||||||
|
required String teamId,
|
||||||
|
}) async {
|
||||||
|
final result = await (select(playerMatchTable)
|
||||||
|
..where(
|
||||||
|
(p) => p.matchId.equals(matchId) & p.teamId.equals(teamId),
|
||||||
|
))
|
||||||
|
.get();
|
||||||
|
|
||||||
|
if (result.isEmpty) return [];
|
||||||
|
|
||||||
|
final futures = result.map(
|
||||||
|
(row) => db.playerDao.getPlayerById(playerId: row.playerId),
|
||||||
|
);
|
||||||
|
return Future.wait(futures);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ part of 'player_match_dao.dart';
|
|||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
mixin _$PlayerMatchDaoMixin on DatabaseAccessor<AppDatabase> {
|
mixin _$PlayerMatchDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||||
$PlayerTableTable get playerTable => attachedDatabase.playerTable;
|
$PlayerTableTable get playerTable => attachedDatabase.playerTable;
|
||||||
|
$GameTableTable get gameTable => attachedDatabase.gameTable;
|
||||||
|
$GroupTableTable get groupTable => attachedDatabase.groupTable;
|
||||||
$MatchTableTable get matchTable => attachedDatabase.matchTable;
|
$MatchTableTable get matchTable => attachedDatabase.matchTable;
|
||||||
|
$TeamTableTable get teamTable => attachedDatabase.teamTable;
|
||||||
$PlayerMatchTableTable get playerMatchTable =>
|
$PlayerMatchTableTable get playerMatchTable =>
|
||||||
attachedDatabase.playerMatchTable;
|
attachedDatabase.playerMatchTable;
|
||||||
}
|
}
|
||||||
|
|||||||
191
lib/data/dao/score_dao.dart
Normal file
191
lib/data/dao/score_dao.dart
Normal file
@@ -0,0 +1,191 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/score_table.dart';
|
||||||
|
|
||||||
|
part 'score_dao.g.dart';
|
||||||
|
|
||||||
|
/// A data class representing a score entry.
|
||||||
|
class ScoreEntry {
|
||||||
|
final String playerId;
|
||||||
|
final String matchId;
|
||||||
|
final int roundNumber;
|
||||||
|
final int score;
|
||||||
|
final int change;
|
||||||
|
|
||||||
|
ScoreEntry({
|
||||||
|
required this.playerId,
|
||||||
|
required this.matchId,
|
||||||
|
required this.roundNumber,
|
||||||
|
required this.score,
|
||||||
|
required this.change,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [ScoreTable])
|
||||||
|
class ScoreDao extends DatabaseAccessor<AppDatabase> with _$ScoreDaoMixin {
|
||||||
|
ScoreDao(super.db);
|
||||||
|
|
||||||
|
/// Adds a score entry to the database.
|
||||||
|
Future<void> addScore({
|
||||||
|
required String playerId,
|
||||||
|
required String matchId,
|
||||||
|
required int roundNumber,
|
||||||
|
required int score,
|
||||||
|
required int change,
|
||||||
|
}) async {
|
||||||
|
await into(scoreTable).insert(
|
||||||
|
ScoreTableCompanion.insert(
|
||||||
|
playerId: playerId,
|
||||||
|
matchId: matchId,
|
||||||
|
roundNumber: roundNumber,
|
||||||
|
score: score,
|
||||||
|
change: change,
|
||||||
|
),
|
||||||
|
mode: InsertMode.insertOrReplace,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieves all scores for a specific match.
|
||||||
|
Future<List<ScoreEntry>> getScoresForMatch({required String matchId}) async {
|
||||||
|
final query = select(scoreTable)..where((s) => s.matchId.equals(matchId));
|
||||||
|
final result = await query.get();
|
||||||
|
return result
|
||||||
|
.map(
|
||||||
|
(row) => ScoreEntry(
|
||||||
|
playerId: row.playerId,
|
||||||
|
matchId: row.matchId,
|
||||||
|
roundNumber: row.roundNumber,
|
||||||
|
score: row.score,
|
||||||
|
change: row.change,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieves all scores for a specific player in a match.
|
||||||
|
Future<List<ScoreEntry>> getPlayerScoresInMatch({
|
||||||
|
required String playerId,
|
||||||
|
required String matchId,
|
||||||
|
}) async {
|
||||||
|
final query = select(scoreTable)
|
||||||
|
..where(
|
||||||
|
(s) => s.playerId.equals(playerId) & s.matchId.equals(matchId),
|
||||||
|
)
|
||||||
|
..orderBy([(s) => OrderingTerm.asc(s.roundNumber)]);
|
||||||
|
final result = await query.get();
|
||||||
|
return result
|
||||||
|
.map(
|
||||||
|
(row) => ScoreEntry(
|
||||||
|
playerId: row.playerId,
|
||||||
|
matchId: row.matchId,
|
||||||
|
roundNumber: row.roundNumber,
|
||||||
|
score: row.score,
|
||||||
|
change: row.change,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieves the score for a specific round.
|
||||||
|
Future<ScoreEntry?> getScoreForRound({
|
||||||
|
required String playerId,
|
||||||
|
required String matchId,
|
||||||
|
required int roundNumber,
|
||||||
|
}) async {
|
||||||
|
final query = select(scoreTable)
|
||||||
|
..where(
|
||||||
|
(s) =>
|
||||||
|
s.playerId.equals(playerId) &
|
||||||
|
s.matchId.equals(matchId) &
|
||||||
|
s.roundNumber.equals(roundNumber),
|
||||||
|
);
|
||||||
|
final result = await query.getSingleOrNull();
|
||||||
|
if (result == null) return null;
|
||||||
|
return ScoreEntry(
|
||||||
|
playerId: result.playerId,
|
||||||
|
matchId: result.matchId,
|
||||||
|
roundNumber: result.roundNumber,
|
||||||
|
score: result.score,
|
||||||
|
change: result.change,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates a score entry.
|
||||||
|
Future<bool> updateScore({
|
||||||
|
required String playerId,
|
||||||
|
required String matchId,
|
||||||
|
required int roundNumber,
|
||||||
|
required int newScore,
|
||||||
|
required int newChange,
|
||||||
|
}) async {
|
||||||
|
final rowsAffected = await (update(scoreTable)
|
||||||
|
..where(
|
||||||
|
(s) =>
|
||||||
|
s.playerId.equals(playerId) &
|
||||||
|
s.matchId.equals(matchId) &
|
||||||
|
s.roundNumber.equals(roundNumber),
|
||||||
|
))
|
||||||
|
.write(
|
||||||
|
ScoreTableCompanion(
|
||||||
|
score: Value(newScore),
|
||||||
|
change: Value(newChange),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return rowsAffected > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes a score entry.
|
||||||
|
Future<bool> deleteScore({
|
||||||
|
required String playerId,
|
||||||
|
required String matchId,
|
||||||
|
required int roundNumber,
|
||||||
|
}) async {
|
||||||
|
final query = delete(scoreTable)
|
||||||
|
..where(
|
||||||
|
(s) =>
|
||||||
|
s.playerId.equals(playerId) &
|
||||||
|
s.matchId.equals(matchId) &
|
||||||
|
s.roundNumber.equals(roundNumber),
|
||||||
|
);
|
||||||
|
final rowsAffected = await query.go();
|
||||||
|
return rowsAffected > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes all scores for a specific match.
|
||||||
|
Future<bool> deleteScoresForMatch({required String matchId}) async {
|
||||||
|
final query = delete(scoreTable)..where((s) => s.matchId.equals(matchId));
|
||||||
|
final rowsAffected = await query.go();
|
||||||
|
return rowsAffected > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes all scores for a specific player.
|
||||||
|
Future<bool> deleteScoresForPlayer({required String playerId}) async {
|
||||||
|
final query = delete(scoreTable)..where((s) => s.playerId.equals(playerId));
|
||||||
|
final rowsAffected = await query.go();
|
||||||
|
return rowsAffected > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the latest round number for a 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Gets the total score for a player in a match (sum of all changes).
|
||||||
|
Future<int> getTotalScoreForPlayer({
|
||||||
|
required String playerId,
|
||||||
|
required String matchId,
|
||||||
|
}) async {
|
||||||
|
final scores = await getPlayerScoresInMatch(
|
||||||
|
playerId: playerId,
|
||||||
|
matchId: matchId,
|
||||||
|
);
|
||||||
|
if (scores.isEmpty) return 0;
|
||||||
|
// Return the score from the latest round
|
||||||
|
return scores.last.score;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
12
lib/data/dao/score_dao.g.dart
Normal file
12
lib/data/dao/score_dao.g.dart
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'score_dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$ScoreDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||||
|
$PlayerTableTable get playerTable => attachedDatabase.playerTable;
|
||||||
|
$GameTableTable get gameTable => attachedDatabase.gameTable;
|
||||||
|
$GroupTableTable get groupTable => attachedDatabase.groupTable;
|
||||||
|
$MatchTableTable get matchTable => attachedDatabase.matchTable;
|
||||||
|
$ScoreTableTable get scoreTable => attachedDatabase.scoreTable;
|
||||||
|
}
|
||||||
145
lib/data/dao/team_dao.dart
Normal file
145
lib/data/dao/team_dao.dart
Normal file
@@ -0,0 +1,145 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/team_table.dart';
|
||||||
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
|
import 'package:game_tracker/data/dto/team.dart';
|
||||||
|
|
||||||
|
part 'team_dao.g.dart';
|
||||||
|
|
||||||
|
@DriftAccessor(tables: [TeamTable])
|
||||||
|
class TeamDao extends DatabaseAccessor<AppDatabase> with _$TeamDaoMixin {
|
||||||
|
TeamDao(super.db);
|
||||||
|
|
||||||
|
/// Retrieves all teams from the database.
|
||||||
|
/// Note: This returns teams without their members. Use getTeamById for full team data.
|
||||||
|
Future<List<Team>> getAllTeams() async {
|
||||||
|
final query = select(teamTable);
|
||||||
|
final result = await query.get();
|
||||||
|
return Future.wait(
|
||||||
|
result.map((row) async {
|
||||||
|
final members = await _getTeamMembers(teamId: row.id);
|
||||||
|
return Team(
|
||||||
|
id: row.id,
|
||||||
|
createdAt: row.createdAt,
|
||||||
|
members: members,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieves a [Team] by its [teamId], including its members.
|
||||||
|
Future<Team> getTeamById({required String teamId}) async {
|
||||||
|
final query = select(teamTable)..where((t) => t.id.equals(teamId));
|
||||||
|
final result = await query.getSingle();
|
||||||
|
final members = await _getTeamMembers(teamId: teamId);
|
||||||
|
return Team(
|
||||||
|
id: result.id,
|
||||||
|
createdAt: result.createdAt,
|
||||||
|
members: members,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper method to get team members from player_match_table.
|
||||||
|
/// This assumes team members are tracked via the player_match_table.
|
||||||
|
Future<List<Player>> _getTeamMembers({required String teamId}) async {
|
||||||
|
// Get all player_match entries with this teamId
|
||||||
|
final playerMatchQuery = select(db.playerMatchTable)
|
||||||
|
..where((pm) => pm.teamId.equals(teamId));
|
||||||
|
final playerMatches = await playerMatchQuery.get();
|
||||||
|
|
||||||
|
if (playerMatches.isEmpty) return [];
|
||||||
|
|
||||||
|
// Get unique player IDs
|
||||||
|
final playerIds = playerMatches.map((pm) => pm.playerId).toSet();
|
||||||
|
|
||||||
|
// Fetch all players
|
||||||
|
final players = await Future.wait(
|
||||||
|
playerIds.map((id) => db.playerDao.getPlayerById(playerId: id)),
|
||||||
|
);
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a new [team] to the database.
|
||||||
|
/// Returns `true` if the team was added, `false` otherwise.
|
||||||
|
Future<bool> addTeam({required Team team}) async {
|
||||||
|
if (!await teamExists(teamId: team.id)) {
|
||||||
|
await into(teamTable).insert(
|
||||||
|
TeamTableCompanion.insert(
|
||||||
|
id: team.id,
|
||||||
|
name: '', // Team name from table (not in DTO currently)
|
||||||
|
createdAt: team.createdAt,
|
||||||
|
),
|
||||||
|
mode: InsertMode.insertOrReplace,
|
||||||
|
);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds multiple [teams] to the database in a batch operation.
|
||||||
|
Future<bool> addTeamsAsList({required List<Team> teams}) async {
|
||||||
|
if (teams.isEmpty) return false;
|
||||||
|
|
||||||
|
await db.batch(
|
||||||
|
(b) => b.insertAll(
|
||||||
|
teamTable,
|
||||||
|
teams
|
||||||
|
.map(
|
||||||
|
(team) => TeamTableCompanion.insert(
|
||||||
|
id: team.id,
|
||||||
|
name: '',
|
||||||
|
createdAt: team.createdAt,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
mode: InsertMode.insertOrIgnore,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes the team with the given [teamId] from the database.
|
||||||
|
/// Returns `true` if the team was deleted, `false` otherwise.
|
||||||
|
Future<bool> deleteTeam({required String teamId}) async {
|
||||||
|
final query = delete(teamTable)..where((t) => t.id.equals(teamId));
|
||||||
|
final rowsAffected = await query.go();
|
||||||
|
return rowsAffected > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Checks if a team with the given [teamId] exists in the database.
|
||||||
|
/// Returns `true` if the team exists, `false` otherwise.
|
||||||
|
Future<bool> teamExists({required String teamId}) async {
|
||||||
|
final query = select(teamTable)..where((t) => t.id.equals(teamId));
|
||||||
|
final result = await query.getSingleOrNull();
|
||||||
|
return result != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the name of the team with the given [teamId].
|
||||||
|
Future<void> updateTeamName({
|
||||||
|
required String teamId,
|
||||||
|
required String newName,
|
||||||
|
}) async {
|
||||||
|
await (update(teamTable)..where((t) => t.id.equals(teamId))).write(
|
||||||
|
TeamTableCompanion(name: Value(newName)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieves the total count of teams in the database.
|
||||||
|
Future<int> getTeamCount() async {
|
||||||
|
final count =
|
||||||
|
await (selectOnly(teamTable)..addColumns([teamTable.id.count()]))
|
||||||
|
.map((row) => row.read(teamTable.id.count()))
|
||||||
|
.getSingle();
|
||||||
|
return count ?? 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Deletes all teams from the database.
|
||||||
|
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
||||||
|
Future<bool> deleteAllTeams() async {
|
||||||
|
final query = delete(teamTable);
|
||||||
|
final rowsAffected = await query.go();
|
||||||
|
return rowsAffected > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
8
lib/data/dao/team_dao.g.dart
Normal file
8
lib/data/dao/team_dao.g.dart
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'team_dao.dart';
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
mixin _$TeamDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||||
|
$TeamTableTable get teamTable => attachedDatabase.teamTable;
|
||||||
|
}
|
||||||
@@ -1,15 +1,21 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:drift_flutter/drift_flutter.dart';
|
import 'package:drift_flutter/drift_flutter.dart';
|
||||||
|
import 'package:game_tracker/data/dao/game_dao.dart';
|
||||||
import 'package:game_tracker/data/dao/group_dao.dart';
|
import 'package:game_tracker/data/dao/group_dao.dart';
|
||||||
import 'package:game_tracker/data/dao/match_dao.dart';
|
import 'package:game_tracker/data/dao/match_dao.dart';
|
||||||
import 'package:game_tracker/data/dao/player_dao.dart';
|
import 'package:game_tracker/data/dao/player_dao.dart';
|
||||||
import 'package:game_tracker/data/dao/player_group_dao.dart';
|
import 'package:game_tracker/data/dao/player_group_dao.dart';
|
||||||
import 'package:game_tracker/data/dao/player_match_dao.dart';
|
import 'package:game_tracker/data/dao/player_match_dao.dart';
|
||||||
|
import 'package:game_tracker/data/dao/score_dao.dart';
|
||||||
|
import 'package:game_tracker/data/dao/team_dao.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/game_table.dart';
|
||||||
import 'package:game_tracker/data/db/tables/group_table.dart';
|
import 'package:game_tracker/data/db/tables/group_table.dart';
|
||||||
import 'package:game_tracker/data/db/tables/match_table.dart';
|
import 'package:game_tracker/data/db/tables/match_table.dart';
|
||||||
import 'package:game_tracker/data/db/tables/player_group_table.dart';
|
import 'package:game_tracker/data/db/tables/player_group_table.dart';
|
||||||
import 'package:game_tracker/data/db/tables/player_match_table.dart';
|
import 'package:game_tracker/data/db/tables/player_match_table.dart';
|
||||||
import 'package:game_tracker/data/db/tables/player_table.dart';
|
import 'package:game_tracker/data/db/tables/player_table.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/score_table.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/team_table.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
part 'database.g.dart';
|
part 'database.g.dart';
|
||||||
@@ -18,23 +24,29 @@ part 'database.g.dart';
|
|||||||
tables: [
|
tables: [
|
||||||
PlayerTable,
|
PlayerTable,
|
||||||
GroupTable,
|
GroupTable,
|
||||||
|
GameTable,
|
||||||
|
TeamTable,
|
||||||
MatchTable,
|
MatchTable,
|
||||||
PlayerGroupTable,
|
PlayerGroupTable,
|
||||||
PlayerMatchTable
|
PlayerMatchTable,
|
||||||
|
ScoreTable,
|
||||||
],
|
],
|
||||||
daos: [
|
daos: [
|
||||||
PlayerDao,
|
PlayerDao,
|
||||||
GroupDao,
|
GroupDao,
|
||||||
|
GameDao,
|
||||||
|
TeamDao,
|
||||||
MatchDao,
|
MatchDao,
|
||||||
PlayerGroupDao,
|
PlayerGroupDao,
|
||||||
PlayerMatchDao
|
PlayerMatchDao,
|
||||||
|
ScoreDao,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
class AppDatabase extends _$AppDatabase {
|
class AppDatabase extends _$AppDatabase {
|
||||||
AppDatabase([QueryExecutor? executor]) : super(executor ?? _openConnection());
|
AppDatabase([QueryExecutor? executor]) : super(executor ?? _openConnection());
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 1;
|
int get schemaVersion => 2;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MigrationStrategy get migration {
|
MigrationStrategy get migration {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user