Renamed every instance of "game" to "match"
This commit is contained in:
@@ -23,9 +23,9 @@ enum ImportResult {
|
|||||||
/// - [ExportResult.unknownException]: An exception occurred during export.
|
/// - [ExportResult.unknownException]: An exception occurred during export.
|
||||||
enum ExportResult { success, canceled, unknownException }
|
enum ExportResult { success, canceled, unknownException }
|
||||||
|
|
||||||
/// Different rulesets available for games
|
/// Different rulesets available for matches
|
||||||
/// - [Ruleset.singleWinner]: The game is won by a single player
|
/// - [Ruleset.singleWinner]: The match is won by a single player
|
||||||
/// - [Ruleset.singleLoser]: The game is lost by a single player
|
/// - [Ruleset.singleLoser]: The match is lost by a single player
|
||||||
/// - [Ruleset.mostPoints]: The player with the most points wins.
|
/// - [Ruleset.mostPoints]: The player with the most points wins.
|
||||||
/// - [Ruleset.leastPoints]: The player with the fewest points wins.
|
/// - [Ruleset.leastPoints]: The player with the fewest points wins.
|
||||||
enum Ruleset { singleWinner, singleLoser, mostPoints, leastPoints }
|
enum Ruleset { singleWinner, singleLoser, mostPoints, leastPoints }
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -1,12 +1,13 @@
|
|||||||
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/group_table.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/group.dart';
|
||||||
import 'package:game_tracker/data/dto/player.dart';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
|
|
||||||
part 'group_dao.g.dart';
|
part 'group_dao.g.dart';
|
||||||
|
|
||||||
@DriftAccessor(tables: [GroupTable])
|
@DriftAccessor(tables: [GroupTable, PlayerGroupTable])
|
||||||
class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
|
class GroupDao extends DatabaseAccessor<AppDatabase> with _$GroupDaoMixin {
|
||||||
GroupDao(super.db);
|
GroupDao(super.db);
|
||||||
|
|
||||||
|
|||||||
@@ -5,4 +5,7 @@ part of 'group_dao.dart';
|
|||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
mixin _$GroupDaoMixin on DatabaseAccessor<AppDatabase> {
|
mixin _$GroupDaoMixin on DatabaseAccessor<AppDatabase> {
|
||||||
$GroupTableTable get groupTable => attachedDatabase.groupTable;
|
$GroupTableTable get groupTable => attachedDatabase.groupTable;
|
||||||
|
$PlayerTableTable get playerTable => attachedDatabase.playerTable;
|
||||||
|
$PlayerGroupTableTable get playerGroupTable =>
|
||||||
|
attachedDatabase.playerGroupTable;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
98
lib/data/dao/group_match_dao.dart
Normal file
98
lib/data/dao/group_match_dao.dart
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
10
lib/data/dao/group_match_dao.g.dart
Normal file
10
lib/data/dao/group_match_dao.g.dart
Normal 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
322
lib/data/dao/match_dao.dart
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
8
lib/data/dao/match_dao.g.dart
Normal file
8
lib/data/dao/match_dao.g.dart
Normal 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;
|
||||||
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,12 @@
|
|||||||
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_group_table.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';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
|
|
||||||
part 'player_group_dao.g.dart';
|
part 'player_group_dao.g.dart';
|
||||||
|
|
||||||
@DriftAccessor(tables: [PlayerGroupTable])
|
@DriftAccessor(tables: [PlayerGroupTable, PlayerTable])
|
||||||
class PlayerGroupDao extends DatabaseAccessor<AppDatabase>
|
class PlayerGroupDao extends DatabaseAccessor<AppDatabase>
|
||||||
with _$PlayerGroupDaoMixin {
|
with _$PlayerGroupDaoMixin {
|
||||||
PlayerGroupDao(super.db);
|
PlayerGroupDao(super.db);
|
||||||
|
|||||||
@@ -1,33 +1,33 @@
|
|||||||
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_game_table.dart';
|
import 'package:game_tracker/data/db/tables/player_match_table.dart';
|
||||||
import 'package:game_tracker/data/dto/player.dart';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
|
|
||||||
part 'player_game_dao.g.dart';
|
part 'player_match_dao.g.dart';
|
||||||
|
|
||||||
@DriftAccessor(tables: [PlayerGameTable])
|
@DriftAccessor(tables: [PlayerMatchTable])
|
||||||
class PlayerGameDao extends DatabaseAccessor<AppDatabase>
|
class PlayerMatchDao extends DatabaseAccessor<AppDatabase>
|
||||||
with _$PlayerGameDaoMixin {
|
with _$PlayerMatchDaoMixin {
|
||||||
PlayerGameDao(super.db);
|
PlayerMatchDao(super.db);
|
||||||
|
|
||||||
/// Associates a player with a game by inserting a record into the
|
/// Associates a player with a match by inserting a record into the
|
||||||
/// [PlayerGameTable].
|
/// [PlayerMatchTable].
|
||||||
Future<void> addPlayerToGame({
|
Future<void> addPlayerToMatch({
|
||||||
required String gameId,
|
required String matchId,
|
||||||
required String playerId,
|
required String playerId,
|
||||||
}) async {
|
}) async {
|
||||||
await into(playerGameTable).insert(
|
await into(playerMatchTable).insert(
|
||||||
PlayerGameTableCompanion.insert(playerId: playerId, gameId: gameId),
|
PlayerMatchTableCompanion.insert(playerId: playerId, matchId: matchId),
|
||||||
mode: InsertMode.insertOrReplace,
|
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.
|
/// 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(
|
final result = await (select(
|
||||||
playerGameTable,
|
playerMatchTable,
|
||||||
)..where((p) => p.gameId.equals(gameId))).get();
|
)..where((p) => p.matchId.equals(matchId))).get();
|
||||||
|
|
||||||
if (result.isEmpty) return null;
|
if (result.isEmpty) return null;
|
||||||
|
|
||||||
@@ -38,43 +38,43 @@ class PlayerGameDao extends DatabaseAccessor<AppDatabase>
|
|||||||
return players;
|
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`.
|
/// Returns `true` if there are players, otherwise `false`.
|
||||||
Future<bool> gameHasPlayers({required String gameId}) async {
|
Future<bool> matchHasPlayers({required String matchId}) async {
|
||||||
final count =
|
final count =
|
||||||
await (selectOnly(playerGameTable)
|
await (selectOnly(playerMatchTable)
|
||||||
..where(playerGameTable.gameId.equals(gameId))
|
..where(playerMatchTable.matchId.equals(matchId))
|
||||||
..addColumns([playerGameTable.playerId.count()]))
|
..addColumns([playerMatchTable.playerId.count()]))
|
||||||
.map((row) => row.read(playerGameTable.playerId.count()))
|
.map((row) => row.read(playerMatchTable.playerId.count()))
|
||||||
.getSingle();
|
.getSingle();
|
||||||
return (count ?? 0) > 0;
|
return (count ?? 0) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if a specific player is associated with a specific game.
|
/// Checks if a specific player is associated with a specific match.
|
||||||
/// Returns `true` if the player is in the game, otherwise `false`.
|
/// Returns `true` if the player is in the match, otherwise `false`.
|
||||||
Future<bool> isPlayerInGame({
|
Future<bool> isPlayerInMatch({
|
||||||
required String gameId,
|
required String matchId,
|
||||||
required String playerId,
|
required String playerId,
|
||||||
}) async {
|
}) async {
|
||||||
final count =
|
final count =
|
||||||
await (selectOnly(playerGameTable)
|
await (selectOnly(playerMatchTable)
|
||||||
..where(playerGameTable.gameId.equals(gameId))
|
..where(playerMatchTable.matchId.equals(matchId))
|
||||||
..where(playerGameTable.playerId.equals(playerId))
|
..where(playerMatchTable.playerId.equals(playerId))
|
||||||
..addColumns([playerGameTable.playerId.count()]))
|
..addColumns([playerMatchTable.playerId.count()]))
|
||||||
.map((row) => row.read(playerGameTable.playerId.count()))
|
.map((row) => row.read(playerMatchTable.playerId.count()))
|
||||||
.getSingle();
|
.getSingle();
|
||||||
return (count ?? 0) > 0;
|
return (count ?? 0) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes the association of a player with a game by deleting the record
|
/// 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`.
|
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
||||||
Future<bool> removePlayerFromGame({
|
Future<bool> removePlayerFromMatch({
|
||||||
required String gameId,
|
required String matchId,
|
||||||
required String playerId,
|
required String playerId,
|
||||||
}) async {
|
}) async {
|
||||||
final query = delete(playerGameTable)
|
final query = delete(playerMatchTable)
|
||||||
..where((pg) => pg.gameId.equals(gameId))
|
..where((pg) => pg.matchId.equals(matchId))
|
||||||
..where((pg) => pg.playerId.equals(playerId));
|
..where((pg) => pg.playerId.equals(playerId));
|
||||||
final rowsAffected = await query.go();
|
final rowsAffected = await query.go();
|
||||||
return rowsAffected > 0;
|
return rowsAffected > 0;
|
||||||
@@ -83,11 +83,11 @@ class PlayerGameDao extends DatabaseAccessor<AppDatabase>
|
|||||||
/// Updates the players associated with a game based on the provided
|
/// Updates the players associated with a game based on the provided
|
||||||
/// [newPlayer] list. It adds new players and removes players that are no
|
/// [newPlayer] list. It adds new players and removes players that are no
|
||||||
/// longer associated with the game.
|
/// longer associated with the game.
|
||||||
Future<void> updatePlayersFromGame({
|
Future<void> updatePlayersFromMatch({
|
||||||
required String gameId,
|
required String matchId,
|
||||||
required List<Player> newPlayer,
|
required List<Player> newPlayer,
|
||||||
}) async {
|
}) async {
|
||||||
final currentPlayers = await getPlayersOfGame(gameId: gameId);
|
final currentPlayers = await getPlayersOfMatch(matchId: matchId);
|
||||||
// Create sets of player IDs for easy comparison
|
// Create sets of player IDs for easy comparison
|
||||||
final currentPlayerIds = currentPlayers?.map((p) => p.id).toSet() ?? {};
|
final currentPlayerIds = currentPlayers?.map((p) => p.id).toSet() ?? {};
|
||||||
final newPlayerIdsSet = newPlayer.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 {
|
db.transaction(() async {
|
||||||
// Remove old players
|
// Remove old players
|
||||||
if (playersToRemove.isNotEmpty) {
|
if (playersToRemove.isNotEmpty) {
|
||||||
await (delete(playerGameTable)..where(
|
await (delete(playerMatchTable)..where(
|
||||||
(pg) =>
|
(pg) =>
|
||||||
pg.gameId.equals(gameId) &
|
pg.matchId.equals(matchId) &
|
||||||
pg.playerId.isIn(playersToRemove.toList()),
|
pg.playerId.isIn(playersToRemove.toList()),
|
||||||
))
|
))
|
||||||
.go();
|
.go();
|
||||||
@@ -111,14 +111,16 @@ class PlayerGameDao extends DatabaseAccessor<AppDatabase>
|
|||||||
if (playersToAdd.isNotEmpty) {
|
if (playersToAdd.isNotEmpty) {
|
||||||
final inserts = playersToAdd
|
final inserts = playersToAdd
|
||||||
.map(
|
.map(
|
||||||
(id) =>
|
(id) => PlayerMatchTableCompanion.insert(
|
||||||
PlayerGameTableCompanion.insert(playerId: id, gameId: gameId),
|
playerId: id,
|
||||||
|
matchId: matchId,
|
||||||
|
),
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
await Future.wait(
|
await Future.wait(
|
||||||
inserts.map(
|
inserts.map(
|
||||||
(c) => into(
|
(c) => into(
|
||||||
playerGameTable,
|
playerMatchTable,
|
||||||
).insert(c, mode: InsertMode.insertOrReplace),
|
).insert(c, mode: InsertMode.insertOrReplace),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
11
lib/data/dao/player_match_dao.g.dart
Normal file
11
lib/data/dao/player_match_dao.g.dart
Normal 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;
|
||||||
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
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/group_game_dao.dart';
|
import 'package:game_tracker/data/dao/group_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_game_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/db/tables/game_table.dart';
|
import 'package:game_tracker/data/dao/player_match_dao.dart';
|
||||||
import 'package:game_tracker/data/db/tables/group_game_table.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/db/tables/group_table.dart';
|
||||||
import 'package:game_tracker/data/db/tables/player_game_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_table.dart';
|
import 'package:game_tracker/data/db/tables/player_table.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
|
|
||||||
@@ -20,18 +20,18 @@ part 'database.g.dart';
|
|||||||
tables: [
|
tables: [
|
||||||
PlayerTable,
|
PlayerTable,
|
||||||
GroupTable,
|
GroupTable,
|
||||||
GameTable,
|
MatchTable,
|
||||||
PlayerGroupTable,
|
PlayerGroupTable,
|
||||||
PlayerGameTable,
|
PlayerMatchTable,
|
||||||
GroupGameTable,
|
GroupMatchTable,
|
||||||
],
|
],
|
||||||
daos: [
|
daos: [
|
||||||
PlayerDao,
|
PlayerDao,
|
||||||
GroupDao,
|
GroupDao,
|
||||||
GameDao,
|
MatchDao,
|
||||||
PlayerGroupDao,
|
PlayerGroupDao,
|
||||||
PlayerGameDao,
|
PlayerMatchDao,
|
||||||
GroupGameDao,
|
GroupMatchDao,
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
class AppDatabase extends _$AppDatabase {
|
class AppDatabase extends _$AppDatabase {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,13 +0,0 @@
|
|||||||
import 'package:drift/drift.dart';
|
|
||||||
import 'package:game_tracker/data/db/tables/game_table.dart';
|
|
||||||
import 'package:game_tracker/data/db/tables/group_table.dart';
|
|
||||||
|
|
||||||
class GroupGameTable extends Table {
|
|
||||||
TextColumn get groupId =>
|
|
||||||
text().references(GroupTable, #id, onDelete: KeyAction.cascade)();
|
|
||||||
TextColumn get gameId =>
|
|
||||||
text().references(GameTable, #id, onDelete: KeyAction.cascade)();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Set<Column<Object>> get primaryKey => {groupId, gameId};
|
|
||||||
}
|
|
||||||
13
lib/data/db/tables/group_match_table.dart
Normal file
13
lib/data/db/tables/group_match_table.dart
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/group_table.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/match_table.dart';
|
||||||
|
|
||||||
|
class GroupMatchTable extends Table {
|
||||||
|
TextColumn get groupId =>
|
||||||
|
text().references(GroupTable, #id, onDelete: KeyAction.cascade)();
|
||||||
|
TextColumn get matchId =>
|
||||||
|
text().references(MatchTable, #id, onDelete: KeyAction.cascade)();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column<Object>> get primaryKey => {groupId, matchId};
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
|
|
||||||
class GameTable extends Table {
|
class MatchTable extends Table {
|
||||||
TextColumn get id => text()();
|
TextColumn get id => text()();
|
||||||
TextColumn get name => text()();
|
TextColumn get name => text()();
|
||||||
late final winnerId = text().nullable()();
|
late final winnerId = text().nullable()();
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import 'package:drift/drift.dart';
|
|
||||||
import 'package:game_tracker/data/db/tables/game_table.dart';
|
|
||||||
import 'package:game_tracker/data/db/tables/player_table.dart';
|
|
||||||
|
|
||||||
class PlayerGameTable extends Table {
|
|
||||||
TextColumn get playerId =>
|
|
||||||
text().references(PlayerTable, #id, onDelete: KeyAction.cascade)();
|
|
||||||
TextColumn get gameId =>
|
|
||||||
text().references(GameTable, #id, onDelete: KeyAction.cascade)();
|
|
||||||
|
|
||||||
@override
|
|
||||||
Set<Column<Object>> get primaryKey => {playerId, gameId};
|
|
||||||
}
|
|
||||||
13
lib/data/db/tables/player_match_table.dart
Normal file
13
lib/data/db/tables/player_match_table.dart
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/match_table.dart';
|
||||||
|
import 'package:game_tracker/data/db/tables/player_table.dart';
|
||||||
|
|
||||||
|
class PlayerMatchTable extends Table {
|
||||||
|
TextColumn get playerId =>
|
||||||
|
text().references(PlayerTable, #id, onDelete: KeyAction.cascade)();
|
||||||
|
TextColumn get matchId =>
|
||||||
|
text().references(MatchTable, #id, onDelete: KeyAction.cascade)();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Set<Column<Object>> get primaryKey => {playerId, matchId};
|
||||||
|
}
|
||||||
@@ -3,7 +3,7 @@ import 'package:game_tracker/data/dto/group.dart';
|
|||||||
import 'package:game_tracker/data/dto/player.dart';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
class Game {
|
class Match {
|
||||||
final String id;
|
final String id;
|
||||||
final DateTime createdAt;
|
final DateTime createdAt;
|
||||||
final String name;
|
final String name;
|
||||||
@@ -11,7 +11,7 @@ class Game {
|
|||||||
final Group? group;
|
final Group? group;
|
||||||
final Player? winner;
|
final Player? winner;
|
||||||
|
|
||||||
Game({
|
Match({
|
||||||
String? id,
|
String? id,
|
||||||
DateTime? createdAt,
|
DateTime? createdAt,
|
||||||
required this.name,
|
required this.name,
|
||||||
@@ -23,11 +23,11 @@ class Game {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'Game{\n\tid: $id,\n\tname: $name,\n\tplayers: $players,\n\tgroup: $group,\n\twinner: $winner\n}';
|
return 'Match{\n\tid: $id,\n\tname: $name,\n\tplayers: $players,\n\tgroup: $group,\n\twinner: $winner\n}';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a Game instance from a JSON object.
|
/// Creates a Match instance from a JSON object.
|
||||||
Game.fromJson(Map<String, dynamic> json)
|
Match.fromJson(Map<String, dynamic> json)
|
||||||
: id = json['id'],
|
: id = json['id'],
|
||||||
name = json['name'],
|
name = json['name'],
|
||||||
createdAt = DateTime.parse(json['createdAt']),
|
createdAt = DateTime.parse(json['createdAt']),
|
||||||
@@ -39,7 +39,7 @@ class Game {
|
|||||||
group = json['group'] != null ? Group.fromJson(json['group']) : null,
|
group = json['group'] != null ? Group.fromJson(json['group']) : null,
|
||||||
winner = json['winner'] != null ? Player.fromJson(json['winner']) : null;
|
winner = json['winner'] != null ? Player.fromJson(json['winner']) : null;
|
||||||
|
|
||||||
/// Converts the Game instance to a JSON object.
|
/// Converts the Match instance to a JSON object.
|
||||||
Map<String, dynamic> toJson() => {
|
Map<String, dynamic> toJson() => {
|
||||||
'id': id,
|
'id': id,
|
||||||
'createdAt': createdAt.toIso8601String(),
|
'createdAt': createdAt.toIso8601String(),
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:game_tracker/core/custom_theme.dart';
|
import 'package:game_tracker/core/custom_theme.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/game_history_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/group_view/groups_view.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/groups_view.dart';
|
|
||||||
import 'package:game_tracker/presentation/views/main_menu/home_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/home_view.dart';
|
||||||
|
import 'package:game_tracker/presentation/views/main_menu/match_view/match_view.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/settings_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/settings_view.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/statistics_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/statistics_view.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/navbar_item.dart';
|
import 'package:game_tracker/presentation/widgets/navbar_item.dart';
|
||||||
@@ -30,8 +30,8 @@ class _CustomNavigationBarState extends State<CustomNavigationBar>
|
|||||||
final List<Widget> tabs = [
|
final List<Widget> tabs = [
|
||||||
KeyedSubtree(key: ValueKey('home_$tabKeyCount'), child: const HomeView()),
|
KeyedSubtree(key: ValueKey('home_$tabKeyCount'), child: const HomeView()),
|
||||||
KeyedSubtree(
|
KeyedSubtree(
|
||||||
key: ValueKey('games_$tabKeyCount'),
|
key: ValueKey('matches_$tabKeyCount'),
|
||||||
child: const GameHistoryView(),
|
child: const MatchView(),
|
||||||
),
|
),
|
||||||
KeyedSubtree(
|
KeyedSubtree(
|
||||||
key: ValueKey('groups_$tabKeyCount'),
|
key: ValueKey('groups_$tabKeyCount'),
|
||||||
@@ -96,7 +96,7 @@ class _CustomNavigationBarState extends State<CustomNavigationBar>
|
|||||||
index: 1,
|
index: 1,
|
||||||
isSelected: currentIndex == 1,
|
isSelected: currentIndex == 1,
|
||||||
icon: Icons.gamepad_rounded,
|
icon: Icons.gamepad_rounded,
|
||||||
label: 'Games',
|
label: 'Matches',
|
||||||
onTabTapped: onTabTapped,
|
onTabTapped: onTabTapped,
|
||||||
),
|
),
|
||||||
NavbarItem(
|
NavbarItem(
|
||||||
@@ -133,7 +133,7 @@ class _CustomNavigationBarState extends State<CustomNavigationBar>
|
|||||||
case 0:
|
case 0:
|
||||||
return 'Home';
|
return 'Home';
|
||||||
case 1:
|
case 1:
|
||||||
return 'Game History';
|
return 'Matches';
|
||||||
case 2:
|
case 2:
|
||||||
return 'Groups';
|
return 'Groups';
|
||||||
case 3:
|
case 3:
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import 'package:game_tracker/core/custom_theme.dart';
|
|||||||
import 'package:game_tracker/data/db/database.dart';
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
import 'package:game_tracker/data/dto/group.dart';
|
import 'package:game_tracker/data/dto/group.dart';
|
||||||
import 'package:game_tracker/data/dto/player.dart';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/create_group_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/group_view/create_group_view.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/app_skeleton.dart';
|
import 'package:game_tracker/presentation/widgets/app_skeleton.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart';
|
import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/tiles/group_tile.dart';
|
import 'package:game_tracker/presentation/widgets/tiles/group_tile.dart';
|
||||||
@@ -25,7 +25,7 @@ class _GroupsViewState extends State<GroupsView> {
|
|||||||
late final List<Group> skeletonData = List.filled(
|
late final List<Group> skeletonData = List.filled(
|
||||||
7,
|
7,
|
||||||
Group(
|
Group(
|
||||||
name: 'Skeleton Game',
|
name: 'Skeleton Match',
|
||||||
members: [player, player, player, player, player, player],
|
members: [player, player, player, player, player, player],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:game_tracker/data/db/database.dart';
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
import 'package:game_tracker/data/dto/game.dart';
|
|
||||||
import 'package:game_tracker/data/dto/group.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';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/app_skeleton.dart';
|
import 'package:game_tracker/presentation/widgets/app_skeleton.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/buttons/quick_create_button.dart';
|
import 'package:game_tracker/presentation/widgets/buttons/quick_create_button.dart';
|
||||||
@@ -18,15 +18,15 @@ class HomeView extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _HomeViewState extends State<HomeView> {
|
class _HomeViewState extends State<HomeView> {
|
||||||
late Future<int> _gameCountFuture;
|
late Future<int> _matchCountFuture;
|
||||||
late Future<int> _groupCountFuture;
|
late Future<int> _groupCountFuture;
|
||||||
late Future<List<Game>> _recentGamesFuture;
|
late Future<List<Match>> _recentMatchesFuture;
|
||||||
bool isLoading = true;
|
bool isLoading = true;
|
||||||
|
|
||||||
late final List<Game> skeletonData = List.filled(
|
late final List<Match> skeletonData = List.filled(
|
||||||
2,
|
2,
|
||||||
Game(
|
Match(
|
||||||
name: 'Skeleton Game',
|
name: 'Skeleton Match',
|
||||||
group: Group(
|
group: Group(
|
||||||
name: 'Skeleton Group',
|
name: 'Skeleton Group',
|
||||||
members: [
|
members: [
|
||||||
@@ -42,20 +42,22 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
initState() {
|
initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
final db = Provider.of<AppDatabase>(context, listen: false);
|
final db = Provider.of<AppDatabase>(context, listen: false);
|
||||||
_gameCountFuture = db.gameDao.getGameCount();
|
_matchCountFuture = db.matchDao.getMatchCount();
|
||||||
_groupCountFuture = db.groupDao.getGroupCount();
|
_groupCountFuture = db.groupDao.getGroupCount();
|
||||||
_recentGamesFuture = db.gameDao.getAllGames();
|
_recentMatchesFuture = db.matchDao.getAllMatches();
|
||||||
|
|
||||||
Future.wait([_gameCountFuture, _groupCountFuture, _recentGamesFuture]).then(
|
Future.wait([
|
||||||
(_) async {
|
_matchCountFuture,
|
||||||
await Future.delayed(const Duration(milliseconds: 250));
|
_groupCountFuture,
|
||||||
if (mounted) {
|
_recentMatchesFuture,
|
||||||
setState(() {
|
]).then((_) async {
|
||||||
isLoading = false;
|
await Future.delayed(const Duration(milliseconds: 250));
|
||||||
});
|
if (mounted) {
|
||||||
}
|
setState(() {
|
||||||
},
|
isLoading = false;
|
||||||
);
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -72,7 +74,7 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
FutureBuilder<int>(
|
FutureBuilder<int>(
|
||||||
future: _gameCountFuture,
|
future: _matchCountFuture,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final int count = (snapshot.hasData)
|
final int count = (snapshot.hasData)
|
||||||
? snapshot.data!
|
? snapshot.data!
|
||||||
@@ -115,11 +117,11 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
content: Padding(
|
content: Padding(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 40.0),
|
padding: const EdgeInsets.symmetric(horizontal: 40.0),
|
||||||
child: FutureBuilder(
|
child: FutureBuilder(
|
||||||
future: _recentGamesFuture,
|
future: _recentMatchesFuture,
|
||||||
builder:
|
builder:
|
||||||
(
|
(
|
||||||
BuildContext context,
|
BuildContext context,
|
||||||
AsyncSnapshot<List<Game>> snapshot,
|
AsyncSnapshot<List<Match>> snapshot,
|
||||||
) {
|
) {
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
return const Center(
|
return const Center(
|
||||||
@@ -129,7 +131,7 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
final List<Game> games =
|
final List<Match> matches =
|
||||||
(isLoading
|
(isLoading
|
||||||
? skeletonData
|
? skeletonData
|
||||||
: (snapshot.data ?? [])
|
: (snapshot.data ?? [])
|
||||||
@@ -140,19 +142,19 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
))
|
))
|
||||||
.take(2)
|
.take(2)
|
||||||
.toList();
|
.toList();
|
||||||
if (games.isNotEmpty) {
|
if (matches.isNotEmpty) {
|
||||||
return Column(
|
return Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.start,
|
mainAxisAlignment: MainAxisAlignment.start,
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
GameTile(
|
MatchTile(
|
||||||
gameTitle: games[0].name,
|
matchTitle: matches[0].name,
|
||||||
gameType: 'Winner',
|
game: 'Winner',
|
||||||
ruleset: 'Ruleset',
|
ruleset: 'Ruleset',
|
||||||
players: _getPlayerText(games[0]),
|
players: _getPlayerText(matches[0]),
|
||||||
winner: games[0].winner == null
|
winner: matches[0].winner == null
|
||||||
? 'Game in progress...'
|
? 'Game in progress...'
|
||||||
: games[0].winner!.name,
|
: matches[0].winner!.name,
|
||||||
),
|
),
|
||||||
const Padding(
|
const Padding(
|
||||||
padding: EdgeInsets.symmetric(
|
padding: EdgeInsets.symmetric(
|
||||||
@@ -160,15 +162,15 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
),
|
),
|
||||||
child: Divider(),
|
child: Divider(),
|
||||||
),
|
),
|
||||||
if (games.length > 1) ...[
|
if (matches.length > 1) ...[
|
||||||
GameTile(
|
MatchTile(
|
||||||
gameTitle: games[1].name,
|
matchTitle: matches[1].name,
|
||||||
gameType: 'Winner',
|
game: 'Winner',
|
||||||
ruleset: 'Ruleset',
|
ruleset: 'Ruleset',
|
||||||
players: _getPlayerText(games[1]),
|
players: _getPlayerText(matches[1]),
|
||||||
winner: games[1].winner == null
|
winner: matches[1].winner == null
|
||||||
? 'Game in progress...'
|
? 'Game in progress...'
|
||||||
: games[1].winner!.name,
|
: matches[1].winner!.name,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
] else ...[
|
] else ...[
|
||||||
@@ -249,7 +251,7 @@ class _HomeViewState extends State<HomeView> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getPlayerText(Game game) {
|
String _getPlayerText(Match game) {
|
||||||
if (game.group == null) {
|
if (game.group == null) {
|
||||||
final playerCount = game.players?.length ?? 0;
|
final playerCount = game.players?.length ?? 0;
|
||||||
return '$playerCount Players';
|
return '$playerCount Players';
|
||||||
|
|||||||
@@ -3,28 +3,28 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:game_tracker/core/custom_theme.dart';
|
import 'package:game_tracker/core/custom_theme.dart';
|
||||||
import 'package:game_tracker/core/enums.dart';
|
import 'package:game_tracker/core/enums.dart';
|
||||||
import 'package:game_tracker/data/db/database.dart';
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
import 'package:game_tracker/data/dto/game.dart';
|
|
||||||
import 'package:game_tracker/data/dto/group.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';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/create_game/choose_game_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/match_view/create_match/choose_game_view.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/create_game/choose_group_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/match_view/create_match/choose_group_view.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/create_game/choose_ruleset_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/match_view/create_match/choose_ruleset_view.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/game_result_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/match_view/match_result_view.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart';
|
import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/player_selection.dart';
|
import 'package:game_tracker/presentation/widgets/player_selection.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/text_input/text_input_field.dart';
|
import 'package:game_tracker/presentation/widgets/text_input/text_input_field.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/tiles/choose_tile.dart';
|
import 'package:game_tracker/presentation/widgets/tiles/choose_tile.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class CreateGameView extends StatefulWidget {
|
class CreateMatchView extends StatefulWidget {
|
||||||
final VoidCallback? onWinnerChanged;
|
final VoidCallback? onWinnerChanged;
|
||||||
const CreateGameView({super.key, this.onWinnerChanged});
|
const CreateMatchView({super.key, this.onWinnerChanged});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<CreateGameView> createState() => _CreateGameViewState();
|
State<CreateMatchView> createState() => _CreateMatchViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _CreateGameViewState extends State<CreateGameView> {
|
class _CreateMatchViewState extends State<CreateMatchView> {
|
||||||
/// Reference to the app database
|
/// Reference to the app database
|
||||||
late final AppDatabase db;
|
late final AppDatabase db;
|
||||||
|
|
||||||
@@ -234,20 +234,20 @@ class _CreateGameViewState extends State<CreateGameView> {
|
|||||||
buttonType: ButtonType.primary,
|
buttonType: ButtonType.primary,
|
||||||
onPressed: _enableCreateGameButton()
|
onPressed: _enableCreateGameButton()
|
||||||
? () async {
|
? () async {
|
||||||
Game game = Game(
|
Match match = Match(
|
||||||
name: _gameNameController.text.trim(),
|
name: _gameNameController.text.trim(),
|
||||||
createdAt: DateTime.now(),
|
createdAt: DateTime.now(),
|
||||||
group: selectedGroup,
|
group: selectedGroup,
|
||||||
players: selectedPlayers,
|
players: selectedPlayers,
|
||||||
);
|
);
|
||||||
await db.gameDao.addGame(game: game);
|
await db.matchDao.addMatch(match: match);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
Navigator.pushReplacement(
|
Navigator.pushReplacement(
|
||||||
context,
|
context,
|
||||||
CupertinoPageRoute(
|
CupertinoPageRoute(
|
||||||
fullscreenDialog: true,
|
fullscreenDialog: true,
|
||||||
builder: (context) => GameResultView(
|
builder: (context) => GameResultView(
|
||||||
game: game,
|
match: match,
|
||||||
onWinnerChanged: widget.onWinnerChanged,
|
onWinnerChanged: widget.onWinnerChanged,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -1,17 +1,17 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:game_tracker/core/custom_theme.dart';
|
import 'package:game_tracker/core/custom_theme.dart';
|
||||||
import 'package:game_tracker/data/db/database.dart';
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
import 'package:game_tracker/data/dto/game.dart';
|
import 'package:game_tracker/data/dto/match.dart';
|
||||||
import 'package:game_tracker/data/dto/player.dart';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/tiles/custom_radio_list_tile.dart';
|
import 'package:game_tracker/presentation/widgets/tiles/custom_radio_list_tile.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class GameResultView extends StatefulWidget {
|
class GameResultView extends StatefulWidget {
|
||||||
final Game game;
|
final Match match;
|
||||||
|
|
||||||
final VoidCallback? onWinnerChanged;
|
final VoidCallback? onWinnerChanged;
|
||||||
|
|
||||||
const GameResultView({super.key, required this.game, this.onWinnerChanged});
|
const GameResultView({super.key, required this.match, this.onWinnerChanged});
|
||||||
@override
|
@override
|
||||||
State<GameResultView> createState() => _GameResultViewState();
|
State<GameResultView> createState() => _GameResultViewState();
|
||||||
}
|
}
|
||||||
@@ -24,10 +24,10 @@ class _GameResultViewState extends State<GameResultView> {
|
|||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
db = Provider.of<AppDatabase>(context, listen: false);
|
db = Provider.of<AppDatabase>(context, listen: false);
|
||||||
allPlayers = getAllPlayers(widget.game);
|
allPlayers = getAllPlayers(widget.match);
|
||||||
if (widget.game.winner != null) {
|
if (widget.match.winner != null) {
|
||||||
_selectedPlayer = allPlayers.firstWhere(
|
_selectedPlayer = allPlayers.firstWhere(
|
||||||
(p) => p.id == widget.game.winner!.id,
|
(p) => p.id == widget.match.winner!.id,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
super.initState();
|
super.initState();
|
||||||
@@ -41,7 +41,7 @@ class _GameResultViewState extends State<GameResultView> {
|
|||||||
backgroundColor: CustomTheme.backgroundColor,
|
backgroundColor: CustomTheme.backgroundColor,
|
||||||
scrolledUnderElevation: 0,
|
scrolledUnderElevation: 0,
|
||||||
title: Text(
|
title: Text(
|
||||||
widget.game.name,
|
widget.match.name,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
@@ -125,17 +125,17 @@ class _GameResultViewState extends State<GameResultView> {
|
|||||||
|
|
||||||
Future<void> _handleWinnerSaving() async {
|
Future<void> _handleWinnerSaving() async {
|
||||||
if (_selectedPlayer == null) {
|
if (_selectedPlayer == null) {
|
||||||
await db.gameDao.removeWinner(gameId: widget.game.id);
|
await db.matchDao.removeWinner(matchId: widget.match.id);
|
||||||
} else {
|
} else {
|
||||||
await db.gameDao.setWinner(
|
await db.matchDao.setWinner(
|
||||||
gameId: widget.game.id,
|
matchId: widget.match.id,
|
||||||
winnerId: _selectedPlayer!.id,
|
winnerId: _selectedPlayer!.id,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
widget.onWinnerChanged?.call();
|
widget.onWinnerChanged?.call();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<Player> getAllPlayers(Game game) {
|
List<Player> getAllPlayers(Match game) {
|
||||||
if (game.group == null && game.players != null) {
|
if (game.group == null && game.players != null) {
|
||||||
return [...game.players!];
|
return [...game.players!];
|
||||||
} else if (game.group != null && game.players != null) {
|
} else if (game.group != null && game.players != null) {
|
||||||
@@ -1,32 +1,34 @@
|
|||||||
|
import 'dart:core' hide Match;
|
||||||
|
|
||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:game_tracker/core/custom_theme.dart';
|
import 'package:game_tracker/core/custom_theme.dart';
|
||||||
import 'package:game_tracker/data/db/database.dart';
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
import 'package:game_tracker/data/dto/game.dart';
|
|
||||||
import 'package:game_tracker/data/dto/group.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';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/create_game/create_game_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/match_view/create_match/create_match_view.dart';
|
||||||
import 'package:game_tracker/presentation/views/main_menu/game_result_view.dart';
|
import 'package:game_tracker/presentation/views/main_menu/match_view/match_result_view.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/app_skeleton.dart';
|
import 'package:game_tracker/presentation/widgets/app_skeleton.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart';
|
import 'package:game_tracker/presentation/widgets/buttons/custom_width_button.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/tiles/game_history_tile.dart';
|
import 'package:game_tracker/presentation/widgets/tiles/game_history_tile.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/top_centered_message.dart';
|
import 'package:game_tracker/presentation/widgets/top_centered_message.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
|
||||||
class GameHistoryView extends StatefulWidget {
|
class MatchView extends StatefulWidget {
|
||||||
const GameHistoryView({super.key});
|
const MatchView({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GameHistoryView> createState() => _GameHistoryViewState();
|
State<MatchView> createState() => _MatchViewState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GameHistoryViewState extends State<GameHistoryView> {
|
class _MatchViewState extends State<MatchView> {
|
||||||
late Future<List<Game>> _gameListFuture;
|
late Future<List<Match>> _gameListFuture;
|
||||||
late final AppDatabase db;
|
late final AppDatabase db;
|
||||||
|
|
||||||
late final List<Game> skeletonData = List.filled(
|
late final List<Match> skeletonData = List.filled(
|
||||||
4,
|
4,
|
||||||
Game(
|
Match(
|
||||||
name: 'Skeleton Gamename',
|
name: 'Skeleton Gamename',
|
||||||
group: Group(
|
group: Group(
|
||||||
name: 'Groupname',
|
name: 'Groupname',
|
||||||
@@ -43,7 +45,7 @@ class _GameHistoryViewState extends State<GameHistoryView> {
|
|||||||
db = Provider.of<AppDatabase>(context, listen: false);
|
db = Provider.of<AppDatabase>(context, listen: false);
|
||||||
_gameListFuture = Future.delayed(
|
_gameListFuture = Future.delayed(
|
||||||
const Duration(milliseconds: 250),
|
const Duration(milliseconds: 250),
|
||||||
() => db.gameDao.getAllGames(),
|
() => db.matchDao.getAllMatches(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,10 +56,10 @@ class _GameHistoryViewState extends State<GameHistoryView> {
|
|||||||
body: Stack(
|
body: Stack(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: [
|
children: [
|
||||||
FutureBuilder<List<Game>>(
|
FutureBuilder<List<Match>>(
|
||||||
future: _gameListFuture,
|
future: _gameListFuture,
|
||||||
builder:
|
builder:
|
||||||
(BuildContext context, AsyncSnapshot<List<Game>> snapshot) {
|
(BuildContext context, AsyncSnapshot<List<Match>> snapshot) {
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
return const Center(
|
return const Center(
|
||||||
child: TopCenteredMessage(
|
child: TopCenteredMessage(
|
||||||
@@ -79,7 +81,7 @@ class _GameHistoryViewState extends State<GameHistoryView> {
|
|||||||
}
|
}
|
||||||
final bool isLoading =
|
final bool isLoading =
|
||||||
snapshot.connectionState == ConnectionState.waiting;
|
snapshot.connectionState == ConnectionState.waiting;
|
||||||
final List<Game> games =
|
final List<Match> matches =
|
||||||
(isLoading ? skeletonData : (snapshot.data ?? [])
|
(isLoading ? skeletonData : (snapshot.data ?? [])
|
||||||
..sort(
|
..sort(
|
||||||
(a, b) => b.createdAt.compareTo(a.createdAt),
|
(a, b) => b.createdAt.compareTo(a.createdAt),
|
||||||
@@ -89,9 +91,9 @@ class _GameHistoryViewState extends State<GameHistoryView> {
|
|||||||
enabled: isLoading,
|
enabled: isLoading,
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
padding: const EdgeInsets.only(bottom: 85),
|
padding: const EdgeInsets.only(bottom: 85),
|
||||||
itemCount: games.length + 1,
|
itemCount: matches.length + 1,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
if (index == games.length) {
|
if (index == matches.length) {
|
||||||
return SizedBox(
|
return SizedBox(
|
||||||
height: MediaQuery.paddingOf(context).bottom - 80,
|
height: MediaQuery.paddingOf(context).bottom - 80,
|
||||||
);
|
);
|
||||||
@@ -103,13 +105,13 @@ class _GameHistoryViewState extends State<GameHistoryView> {
|
|||||||
CupertinoPageRoute(
|
CupertinoPageRoute(
|
||||||
fullscreenDialog: true,
|
fullscreenDialog: true,
|
||||||
builder: (context) => GameResultView(
|
builder: (context) => GameResultView(
|
||||||
game: games[index],
|
match: matches[index],
|
||||||
onWinnerChanged: refreshGameList,
|
onWinnerChanged: refreshGameList,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
game: games[index],
|
match: matches[index],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -126,7 +128,7 @@ class _GameHistoryViewState extends State<GameHistoryView> {
|
|||||||
context,
|
context,
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) =>
|
builder: (context) =>
|
||||||
CreateGameView(onWinnerChanged: refreshGameList),
|
CreateMatchView(onWinnerChanged: refreshGameList),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -139,7 +141,7 @@ class _GameHistoryViewState extends State<GameHistoryView> {
|
|||||||
|
|
||||||
void refreshGameList() {
|
void refreshGameList() {
|
||||||
setState(() {
|
setState(() {
|
||||||
_gameListFuture = db.gameDao.getAllGames();
|
_gameListFuture = db.matchDao.getAllMatches();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:game_tracker/data/db/database.dart';
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
import 'package:game_tracker/data/dto/game.dart';
|
import 'package:game_tracker/data/dto/match.dart';
|
||||||
import 'package:game_tracker/data/dto/player.dart';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/app_skeleton.dart';
|
import 'package:game_tracker/presentation/widgets/app_skeleton.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/tiles/statistics_tile.dart';
|
import 'package:game_tracker/presentation/widgets/tiles/statistics_tile.dart';
|
||||||
@@ -14,10 +14,10 @@ class StatisticsView extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _StatisticsViewState extends State<StatisticsView> {
|
class _StatisticsViewState extends State<StatisticsView> {
|
||||||
late Future<List<Game>> _gamesFuture;
|
late Future<List<Match>> _matchesFuture;
|
||||||
late Future<List<Player>> _playersFuture;
|
late Future<List<Player>> _playersFuture;
|
||||||
List<(String, int)> winCounts = List.filled(6, ('Skeleton Player', 1));
|
List<(String, int)> winCounts = List.filled(6, ('Skeleton Player', 1));
|
||||||
List<(String, int)> gameCounts = List.filled(6, ('Skeleton Player', 1));
|
List<(String, int)> matchCounts = List.filled(6, ('Skeleton Player', 1));
|
||||||
List<(String, double)> winRates = List.filled(6, ('Skeleton Player', 1));
|
List<(String, double)> winRates = List.filled(6, ('Skeleton Player', 1));
|
||||||
bool isLoading = true;
|
bool isLoading = true;
|
||||||
|
|
||||||
@@ -25,16 +25,16 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
final db = Provider.of<AppDatabase>(context, listen: false);
|
final db = Provider.of<AppDatabase>(context, listen: false);
|
||||||
_gamesFuture = db.gameDao.getAllGames();
|
_matchesFuture = db.matchDao.getAllMatches();
|
||||||
_playersFuture = db.playerDao.getAllPlayers();
|
_playersFuture = db.playerDao.getAllPlayers();
|
||||||
|
|
||||||
Future.wait([_gamesFuture, _playersFuture]).then((results) async {
|
Future.wait([_matchesFuture, _playersFuture]).then((results) async {
|
||||||
await Future.delayed(const Duration(milliseconds: 250));
|
await Future.delayed(const Duration(milliseconds: 250));
|
||||||
final games = results[0] as List<Game>;
|
final matches = results[0] as List<Match>;
|
||||||
final players = results[1] as List<Player>;
|
final players = results[1] as List<Player>;
|
||||||
winCounts = _calculateWinsForAllPlayers(games, players);
|
winCounts = _calculateWinsForAllPlayers(matches, players);
|
||||||
gameCounts = _calculateGameAmountsForAllPlayers(games, players);
|
matchCounts = _calculateGameAmountsForAllPlayers(matches, players);
|
||||||
winRates = computeWinRatePercent(wins: winCounts, games: gameCounts);
|
winRates = computeWinRatePercent(wins: winCounts, matches: matchCounts);
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
@@ -78,9 +78,9 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
SizedBox(height: constraints.maxHeight * 0.02),
|
SizedBox(height: constraints.maxHeight * 0.02),
|
||||||
StatisticsTile(
|
StatisticsTile(
|
||||||
icon: Icons.casino,
|
icon: Icons.casino,
|
||||||
title: 'Games per Player',
|
title: 'Match per Player',
|
||||||
width: constraints.maxWidth * 0.95,
|
width: constraints.maxWidth * 0.95,
|
||||||
values: gameCounts,
|
values: matchCounts,
|
||||||
itemCount: 10,
|
itemCount: 10,
|
||||||
barColor: Colors.green,
|
barColor: Colors.green,
|
||||||
),
|
),
|
||||||
@@ -97,7 +97,7 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
/// Calculates the number of wins for each player
|
/// Calculates the number of wins for each player
|
||||||
/// and returns a sorted list of tuples (playerName, winCount)
|
/// and returns a sorted list of tuples (playerName, winCount)
|
||||||
List<(String, int)> _calculateWinsForAllPlayers(
|
List<(String, int)> _calculateWinsForAllPlayers(
|
||||||
List<Game> games,
|
List<Match> games,
|
||||||
List<Player> players,
|
List<Player> players,
|
||||||
) {
|
) {
|
||||||
List<(String, int)> winCounts = [];
|
List<(String, int)> winCounts = [];
|
||||||
@@ -141,39 +141,39 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
return winCounts;
|
return winCounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculates the number of games played for each player
|
/// Calculates the number of matches played for each player
|
||||||
/// and returns a sorted list of tuples (playerName, gameCount)
|
/// and returns a sorted list of tuples (playerName, matchCount)
|
||||||
List<(String, int)> _calculateGameAmountsForAllPlayers(
|
List<(String, int)> _calculateGameAmountsForAllPlayers(
|
||||||
List<Game> games,
|
List<Match> matches,
|
||||||
List<Player> players,
|
List<Player> players,
|
||||||
) {
|
) {
|
||||||
List<(String, int)> gameCounts = [];
|
List<(String, int)> matchCounts = [];
|
||||||
|
|
||||||
// Counting games for each player
|
// Counting matches for each player
|
||||||
for (var game in games) {
|
for (var match in matches) {
|
||||||
if (game.group != null) {
|
if (match.group != null) {
|
||||||
final members = game.group!.members.map((p) => p.id).toList();
|
final members = match.group!.members.map((p) => p.id).toList();
|
||||||
for (var playerId in members) {
|
for (var playerId in members) {
|
||||||
final index = gameCounts.indexWhere((entry) => entry.$1 == playerId);
|
final index = matchCounts.indexWhere((entry) => entry.$1 == playerId);
|
||||||
// -1 means player not found in gameCounts
|
// -1 means player not found in gameCounts
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
final current = gameCounts[index].$2;
|
final current = matchCounts[index].$2;
|
||||||
gameCounts[index] = (playerId, current + 1);
|
matchCounts[index] = (playerId, current + 1);
|
||||||
} else {
|
} else {
|
||||||
gameCounts.add((playerId, 1));
|
matchCounts.add((playerId, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (game.players != null) {
|
if (match.players != null) {
|
||||||
final members = game.players!.map((p) => p.id).toList();
|
final members = match.players!.map((p) => p.id).toList();
|
||||||
for (var playerId in members) {
|
for (var playerId in members) {
|
||||||
final index = gameCounts.indexWhere((entry) => entry.$1 == playerId);
|
final index = matchCounts.indexWhere((entry) => entry.$1 == playerId);
|
||||||
// -1 means player not found in gameCounts
|
// -1 means player not found in gameCounts
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
final current = gameCounts[index].$2;
|
final current = matchCounts[index].$2;
|
||||||
gameCounts[index] = (playerId, current + 1);
|
matchCounts[index] = (playerId, current + 1);
|
||||||
} else {
|
} else {
|
||||||
gameCounts.add((playerId, 1));
|
matchCounts.add((playerId, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -181,35 +181,35 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
|
|
||||||
// Adding all players with zero games
|
// Adding all players with zero games
|
||||||
for (var player in players) {
|
for (var player in players) {
|
||||||
final index = gameCounts.indexWhere((entry) => entry.$1 == player.id);
|
final index = matchCounts.indexWhere((entry) => entry.$1 == player.id);
|
||||||
// -1 means player not found in gameCounts
|
// -1 means player not found in gameCounts
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
gameCounts.add((player.id, 0));
|
matchCounts.add((player.id, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace player IDs with names
|
// Replace player IDs with names
|
||||||
for (int i = 0; i < gameCounts.length; i++) {
|
for (int i = 0; i < matchCounts.length; i++) {
|
||||||
final playerId = gameCounts[i].$1;
|
final playerId = matchCounts[i].$1;
|
||||||
final player = players.firstWhere(
|
final player = players.firstWhere(
|
||||||
(p) => p.id == playerId,
|
(p) => p.id == playerId,
|
||||||
orElse: () => Player(id: playerId, name: 'N.a.'),
|
orElse: () => Player(id: playerId, name: 'N.a.'),
|
||||||
);
|
);
|
||||||
gameCounts[i] = (player.name, gameCounts[i].$2);
|
matchCounts[i] = (player.name, matchCounts[i].$2);
|
||||||
}
|
}
|
||||||
|
|
||||||
gameCounts.sort((a, b) => b.$2.compareTo(a.$2));
|
matchCounts.sort((a, b) => b.$2.compareTo(a.$2));
|
||||||
|
|
||||||
return gameCounts;
|
return matchCounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dart
|
// dart
|
||||||
List<(String, double)> computeWinRatePercent({
|
List<(String, double)> computeWinRatePercent({
|
||||||
required List<(String, int)> wins,
|
required List<(String, int)> wins,
|
||||||
required List<(String, int)> games,
|
required List<(String, int)> matches,
|
||||||
}) {
|
}) {
|
||||||
final Map<String, int> winsMap = {for (var e in wins) e.$1: e.$2};
|
final Map<String, int> winsMap = {for (var e in wins) e.$1: e.$2};
|
||||||
final Map<String, int> gamesMap = {for (var e in games) e.$1: e.$2};
|
final Map<String, int> gamesMap = {for (var e in matches) e.$1: e.$2};
|
||||||
|
|
||||||
// Get all unique player names
|
// Get all unique player names
|
||||||
final names = {...winsMap.keys, ...gamesMap.keys};
|
final names = {...winsMap.keys, ...gamesMap.keys};
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:game_tracker/core/custom_theme.dart';
|
import 'package:game_tracker/core/custom_theme.dart';
|
||||||
import 'package:game_tracker/data/dto/game.dart';
|
import 'package:game_tracker/data/dto/match.dart';
|
||||||
import 'package:game_tracker/presentation/widgets/tiles/text_icon_tile.dart';
|
import 'package:game_tracker/presentation/widgets/tiles/text_icon_tile.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
class GameHistoryTile extends StatefulWidget {
|
class GameHistoryTile extends StatefulWidget {
|
||||||
final Game game;
|
final Match match;
|
||||||
final VoidCallback onTap;
|
final VoidCallback onTap;
|
||||||
|
|
||||||
const GameHistoryTile({super.key, required this.game, required this.onTap});
|
const GameHistoryTile({super.key, required this.match, required this.onTap});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GameHistoryTile> createState() => _GameHistoryTileState();
|
State<GameHistoryTile> createState() => _GameHistoryTileState();
|
||||||
@@ -17,8 +17,8 @@ class GameHistoryTile extends StatefulWidget {
|
|||||||
class _GameHistoryTileState extends State<GameHistoryTile> {
|
class _GameHistoryTileState extends State<GameHistoryTile> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final group = widget.game.group;
|
final group = widget.match.group;
|
||||||
final winner = widget.game.winner;
|
final winner = widget.match.winner;
|
||||||
final allPlayers = _getAllPlayers();
|
final allPlayers = _getAllPlayers();
|
||||||
|
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
@@ -39,7 +39,7 @@ class _GameHistoryTileState extends State<GameHistoryTile> {
|
|||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
widget.game.name,
|
widget.match.name,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 18,
|
fontSize: 18,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
@@ -48,7 +48,7 @@ class _GameHistoryTileState extends State<GameHistoryTile> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
_formatDate(widget.game.createdAt),
|
_formatDate(widget.match.createdAt),
|
||||||
style: const TextStyle(fontSize: 12, color: Colors.grey),
|
style: const TextStyle(fontSize: 12, color: Colors.grey),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -156,8 +156,8 @@ class _GameHistoryTileState extends State<GameHistoryTile> {
|
|||||||
final playerIds = <String>{};
|
final playerIds = <String>{};
|
||||||
|
|
||||||
// Add players from game.players
|
// Add players from game.players
|
||||||
if (widget.game.players != null) {
|
if (widget.match.players != null) {
|
||||||
for (var player in widget.game.players!) {
|
for (var player in widget.match.players!) {
|
||||||
if (!playerIds.contains(player.id)) {
|
if (!playerIds.contains(player.id)) {
|
||||||
allPlayers.add(player);
|
allPlayers.add(player);
|
||||||
playerIds.add(player.id);
|
playerIds.add(player.id);
|
||||||
@@ -166,8 +166,8 @@ class _GameHistoryTileState extends State<GameHistoryTile> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add players from game.group.players
|
// Add players from game.group.players
|
||||||
if (widget.game.group?.members != null) {
|
if (widget.match.group?.members != null) {
|
||||||
for (var player in widget.game.group!.members) {
|
for (var player in widget.match.group!.members) {
|
||||||
if (!playerIds.contains(player.id)) {
|
if (!playerIds.contains(player.id)) {
|
||||||
allPlayers.add(player);
|
allPlayers.add(player);
|
||||||
playerIds.add(player.id);
|
playerIds.add(player.id);
|
||||||
|
|||||||
@@ -2,27 +2,27 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:game_tracker/core/custom_theme.dart';
|
import 'package:game_tracker/core/custom_theme.dart';
|
||||||
import 'package:skeletonizer/skeletonizer.dart';
|
import 'package:skeletonizer/skeletonizer.dart';
|
||||||
|
|
||||||
class GameTile extends StatefulWidget {
|
class MatchTile extends StatefulWidget {
|
||||||
final String gameTitle;
|
final String matchTitle;
|
||||||
final String gameType;
|
final String game;
|
||||||
final String ruleset;
|
final String ruleset;
|
||||||
final String players;
|
final String players;
|
||||||
final String winner;
|
final String winner;
|
||||||
|
|
||||||
const GameTile({
|
const MatchTile({
|
||||||
super.key,
|
super.key,
|
||||||
required this.gameTitle,
|
required this.matchTitle,
|
||||||
required this.gameType,
|
required this.game,
|
||||||
required this.ruleset,
|
required this.ruleset,
|
||||||
required this.players,
|
required this.players,
|
||||||
required this.winner,
|
required this.winner,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GameTile> createState() => _GameTileState();
|
State<MatchTile> createState() => _MatchTileState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GameTileState extends State<GameTile> {
|
class _MatchTileState extends State<MatchTile> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
@@ -31,12 +31,12 @@ class _GameTileState extends State<GameTile> {
|
|||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
widget.gameTitle,
|
widget.matchTitle,
|
||||||
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.bold),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 5),
|
const SizedBox(width: 5),
|
||||||
Text(
|
Text(
|
||||||
widget.gameType,
|
widget.game,
|
||||||
style: const TextStyle(fontSize: 14, color: Colors.grey),
|
style: const TextStyle(fontSize: 14, color: Colors.grey),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -40,11 +40,11 @@ class StatisticsTile extends StatelessWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: List.generate(min(values.length, itemCount), (index) {
|
children: List.generate(min(values.length, itemCount), (index) {
|
||||||
/// The maximum wins among all players
|
/// The maximum wins among all players
|
||||||
final maxGames = values.isNotEmpty ? values[0].$2 : 0;
|
final maxMatches = values.isNotEmpty ? values[0].$2 : 0;
|
||||||
|
|
||||||
/// Fraction of wins
|
/// Fraction of wins
|
||||||
final double fraction = (maxGames > 0)
|
final double fraction = (maxMatches > 0)
|
||||||
? (values[index].$2 / maxGames)
|
? (values[index].$2 / maxMatches)
|
||||||
: 0.0;
|
: 0.0;
|
||||||
|
|
||||||
/// Calculated width for current the bar
|
/// Calculated width for current the bar
|
||||||
|
|||||||
@@ -6,8 +6,8 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:game_tracker/core/enums.dart';
|
import 'package:game_tracker/core/enums.dart';
|
||||||
import 'package:game_tracker/data/db/database.dart';
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
import 'package:game_tracker/data/dto/game.dart';
|
|
||||||
import 'package:game_tracker/data/dto/group.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';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
import 'package:json_schema/json_schema.dart';
|
import 'package:json_schema/json_schema.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
@@ -16,7 +16,7 @@ class DataTransferService {
|
|||||||
/// Deletes all data from the database.
|
/// Deletes all data from the database.
|
||||||
static Future<void> deleteAllData(BuildContext context) async {
|
static Future<void> deleteAllData(BuildContext context) async {
|
||||||
final db = Provider.of<AppDatabase>(context, listen: false);
|
final db = Provider.of<AppDatabase>(context, listen: false);
|
||||||
await db.gameDao.deleteAllGames();
|
await db.matchDao.deleteAllMatches();
|
||||||
await db.groupDao.deleteAllGroups();
|
await db.groupDao.deleteAllGroups();
|
||||||
await db.playerDao.deleteAllPlayers();
|
await db.playerDao.deleteAllPlayers();
|
||||||
}
|
}
|
||||||
@@ -25,13 +25,13 @@ class DataTransferService {
|
|||||||
/// Returns the JSON string representation of the data.
|
/// Returns the JSON string representation of the data.
|
||||||
static Future<String> getAppDataAsJson(BuildContext context) async {
|
static Future<String> getAppDataAsJson(BuildContext context) async {
|
||||||
final db = Provider.of<AppDatabase>(context, listen: false);
|
final db = Provider.of<AppDatabase>(context, listen: false);
|
||||||
final games = await db.gameDao.getAllGames();
|
final matches = await db.matchDao.getAllMatches();
|
||||||
final groups = await db.groupDao.getAllGroups();
|
final groups = await db.groupDao.getAllGroups();
|
||||||
final players = await db.playerDao.getAllPlayers();
|
final players = await db.playerDao.getAllPlayers();
|
||||||
|
|
||||||
// Construct a JSON representation of the data
|
// Construct a JSON representation of the data
|
||||||
final Map<String, dynamic> jsonMap = {
|
final Map<String, dynamic> jsonMap = {
|
||||||
'games': games.map((game) => game.toJson()).toList(),
|
'matches': matches.map((match) => match.toJson()).toList(),
|
||||||
'groups': groups.map((group) => group.toJson()).toList(),
|
'groups': groups.map((group) => group.toJson()).toList(),
|
||||||
'players': players.map((player) => player.toJson()).toList(),
|
'players': players.map((player) => player.toJson()).toList(),
|
||||||
};
|
};
|
||||||
@@ -89,14 +89,15 @@ class DataTransferService {
|
|||||||
final Map<String, dynamic> jsonData =
|
final Map<String, dynamic> jsonData =
|
||||||
json.decode(jsonString) as Map<String, dynamic>;
|
json.decode(jsonString) as Map<String, dynamic>;
|
||||||
|
|
||||||
final List<dynamic>? gamesJson = jsonData['games'] as List<dynamic>?;
|
final List<dynamic>? matchesJson =
|
||||||
|
jsonData['matches'] as List<dynamic>?;
|
||||||
final List<dynamic>? groupsJson = jsonData['groups'] as List<dynamic>?;
|
final List<dynamic>? groupsJson = jsonData['groups'] as List<dynamic>?;
|
||||||
final List<dynamic>? playersJson =
|
final List<dynamic>? playersJson =
|
||||||
jsonData['players'] as List<dynamic>?;
|
jsonData['players'] as List<dynamic>?;
|
||||||
|
|
||||||
final List<Game> importedGames =
|
final List<Match> importedMatches =
|
||||||
gamesJson
|
matchesJson
|
||||||
?.map((g) => Game.fromJson(g as Map<String, dynamic>))
|
?.map((g) => Match.fromJson(g as Map<String, dynamic>))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
[];
|
[];
|
||||||
final List<Group> importedGroups =
|
final List<Group> importedGroups =
|
||||||
@@ -112,7 +113,7 @@ class DataTransferService {
|
|||||||
|
|
||||||
await db.playerDao.addPlayersAsList(players: importedPlayers);
|
await db.playerDao.addPlayersAsList(players: importedPlayers);
|
||||||
await db.groupDao.addGroupsAsList(groups: importedGroups);
|
await db.groupDao.addGroupsAsList(groups: importedGroups);
|
||||||
await db.gameDao.addGamesAsList(games: importedGames);
|
await db.matchDao.addMatchAsList(matches: importedMatches);
|
||||||
} else {
|
} else {
|
||||||
return ImportResult.invalidSchema;
|
return ImportResult.invalidSchema;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import 'package:drift/drift.dart';
|
|||||||
import 'package:drift/native.dart';
|
import 'package:drift/native.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:game_tracker/data/db/database.dart';
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
import 'package:game_tracker/data/dto/game.dart';
|
|
||||||
import 'package:game_tracker/data/dto/group.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';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@@ -16,10 +16,10 @@ void main() {
|
|||||||
late Player testPlayer5;
|
late Player testPlayer5;
|
||||||
late Group testGroup1;
|
late Group testGroup1;
|
||||||
late Group testGroup2;
|
late Group testGroup2;
|
||||||
late Game testGame1;
|
late Match testMatch1;
|
||||||
late Game testGame2;
|
late Match testMatch2;
|
||||||
late Game testGameOnlyPlayers;
|
late Match testMatchOnlyPlayers;
|
||||||
late Game testGameOnlyGroup;
|
late Match testMatchOnlyGroup;
|
||||||
final fixedDate = DateTime(2025, 19, 11, 00, 11, 23);
|
final fixedDate = DateTime(2025, 19, 11, 00, 11, 23);
|
||||||
final fakeClock = Clock(() => fixedDate);
|
final fakeClock = Clock(() => fixedDate);
|
||||||
|
|
||||||
@@ -46,46 +46,51 @@ void main() {
|
|||||||
name: 'Test Group 2',
|
name: 'Test Group 2',
|
||||||
members: [testPlayer4, testPlayer5],
|
members: [testPlayer4, testPlayer5],
|
||||||
);
|
);
|
||||||
testGame1 = Game(
|
testMatch1 = Match(
|
||||||
name: 'First Test Game',
|
name: 'First Test Match',
|
||||||
group: testGroup1,
|
group: testGroup1,
|
||||||
players: [testPlayer4, testPlayer5],
|
players: [testPlayer4, testPlayer5],
|
||||||
winner: testPlayer4,
|
winner: testPlayer4,
|
||||||
);
|
);
|
||||||
testGame2 = Game(
|
testMatch2 = Match(
|
||||||
name: 'Second Test Game',
|
name: 'Second Test Match',
|
||||||
group: testGroup2,
|
group: testGroup2,
|
||||||
players: [testPlayer1, testPlayer2, testPlayer3],
|
players: [testPlayer1, testPlayer2, testPlayer3],
|
||||||
winner: testPlayer2,
|
winner: testPlayer2,
|
||||||
);
|
);
|
||||||
testGameOnlyPlayers = Game(
|
testMatchOnlyPlayers = Match(
|
||||||
name: 'Test Game with Players',
|
name: 'Test Match with Players',
|
||||||
players: [testPlayer1, testPlayer2, testPlayer3],
|
players: [testPlayer1, testPlayer2, testPlayer3],
|
||||||
winner: testPlayer3,
|
winner: testPlayer3,
|
||||||
);
|
);
|
||||||
testGameOnlyGroup = Game(name: 'Test Game with Group', group: testGroup2);
|
testMatchOnlyGroup = Match(
|
||||||
|
name: 'Test Match with Group',
|
||||||
|
group: testGroup2,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
tearDown(() async {
|
tearDown(() async {
|
||||||
await database.close();
|
await database.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
group('Game Tests', () {
|
group('Match Tests', () {
|
||||||
test('Adding and fetching single game works correctly', () async {
|
test('Adding and fetching single match works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testGame1);
|
await database.matchDao.addMatch(match: testMatch1);
|
||||||
|
|
||||||
final result = await database.gameDao.getGameById(gameId: testGame1.id);
|
final result = await database.matchDao.getMatchById(
|
||||||
|
matchId: testMatch1.id,
|
||||||
|
);
|
||||||
|
|
||||||
expect(result.id, testGame1.id);
|
expect(result.id, testMatch1.id);
|
||||||
expect(result.name, testGame1.name);
|
expect(result.name, testMatch1.name);
|
||||||
expect(result.createdAt, testGame1.createdAt);
|
expect(result.createdAt, testMatch1.createdAt);
|
||||||
|
|
||||||
if (result.winner != null && testGame1.winner != null) {
|
if (result.winner != null && testMatch1.winner != null) {
|
||||||
expect(result.winner!.id, testGame1.winner!.id);
|
expect(result.winner!.id, testMatch1.winner!.id);
|
||||||
expect(result.winner!.name, testGame1.winner!.name);
|
expect(result.winner!.name, testMatch1.winner!.name);
|
||||||
expect(result.winner!.createdAt, testGame1.winner!.createdAt);
|
expect(result.winner!.createdAt, testMatch1.winner!.createdAt);
|
||||||
} else {
|
} else {
|
||||||
expect(result.winner, testGame1.winner);
|
expect(result.winner, testMatch1.winner);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result.group != null) {
|
if (result.group != null) {
|
||||||
@@ -99,188 +104,203 @@ void main() {
|
|||||||
fail('Group is null');
|
fail('Group is null');
|
||||||
}
|
}
|
||||||
if (result.players != null) {
|
if (result.players != null) {
|
||||||
expect(result.players!.length, testGame1.players!.length);
|
expect(result.players!.length, testMatch1.players!.length);
|
||||||
|
|
||||||
for (int i = 0; i < testGame1.players!.length; i++) {
|
for (int i = 0; i < testMatch1.players!.length; i++) {
|
||||||
expect(result.players![i].id, testGame1.players![i].id);
|
expect(result.players![i].id, testMatch1.players![i].id);
|
||||||
expect(result.players![i].name, testGame1.players![i].name);
|
expect(result.players![i].name, testMatch1.players![i].name);
|
||||||
expect(result.players![i].createdAt, testGame1.players![i].createdAt);
|
expect(
|
||||||
|
result.players![i].createdAt,
|
||||||
|
testMatch1.players![i].createdAt,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fail('Players is null');
|
fail('Players is null');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Adding and fetching multiple games works correctly', () async {
|
test('Adding and fetching multiple matches works correctly', () async {
|
||||||
await database.gameDao.addGamesAsList(
|
await database.matchDao.addMatchAsList(
|
||||||
games: [testGame1, testGame2, testGameOnlyGroup, testGameOnlyPlayers],
|
matches: [
|
||||||
|
testMatch1,
|
||||||
|
testMatch2,
|
||||||
|
testMatchOnlyGroup,
|
||||||
|
testMatchOnlyPlayers,
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
final allGames = await database.gameDao.getAllGames();
|
final allMatches = await database.matchDao.getAllMatches();
|
||||||
expect(allGames.length, 4);
|
expect(allMatches.length, 4);
|
||||||
|
|
||||||
final testGames = {
|
final testMatches = {
|
||||||
testGame1.id: testGame1,
|
testMatch1.id: testMatch1,
|
||||||
testGame2.id: testGame2,
|
testMatch2.id: testMatch2,
|
||||||
testGameOnlyGroup.id: testGameOnlyGroup,
|
testMatchOnlyGroup.id: testMatchOnlyGroup,
|
||||||
testGameOnlyPlayers.id: testGameOnlyPlayers,
|
testMatchOnlyPlayers.id: testMatchOnlyPlayers,
|
||||||
};
|
};
|
||||||
|
|
||||||
for (final game in allGames) {
|
for (final match in allMatches) {
|
||||||
final testGame = testGames[game.id]!;
|
final testMatch = testMatches[match.id]!;
|
||||||
|
|
||||||
// Game-Checks
|
// Match-Checks
|
||||||
expect(game.id, testGame.id);
|
expect(match.id, testMatch.id);
|
||||||
expect(game.name, testGame.name);
|
expect(match.name, testMatch.name);
|
||||||
expect(game.createdAt, testGame.createdAt);
|
expect(match.createdAt, testMatch.createdAt);
|
||||||
if (game.winner != null && testGame.winner != null) {
|
if (match.winner != null && testMatch.winner != null) {
|
||||||
expect(game.winner!.id, testGame.winner!.id);
|
expect(match.winner!.id, testMatch.winner!.id);
|
||||||
expect(game.winner!.name, testGame.winner!.name);
|
expect(match.winner!.name, testMatch.winner!.name);
|
||||||
expect(game.winner!.createdAt, testGame.winner!.createdAt);
|
expect(match.winner!.createdAt, testMatch.winner!.createdAt);
|
||||||
} else {
|
} else {
|
||||||
expect(game.winner, testGame.winner);
|
expect(match.winner, testMatch.winner);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Group-Checks
|
// Group-Checks
|
||||||
if (testGame.group != null) {
|
if (testMatch.group != null) {
|
||||||
expect(game.group!.id, testGame.group!.id);
|
expect(match.group!.id, testMatch.group!.id);
|
||||||
expect(game.group!.name, testGame.group!.name);
|
expect(match.group!.name, testMatch.group!.name);
|
||||||
expect(game.group!.createdAt, testGame.group!.createdAt);
|
expect(match.group!.createdAt, testMatch.group!.createdAt);
|
||||||
|
|
||||||
// Group Members-Checks
|
// Group Members-Checks
|
||||||
expect(game.group!.members.length, testGame.group!.members.length);
|
expect(match.group!.members.length, testMatch.group!.members.length);
|
||||||
for (int i = 0; i < testGame.group!.members.length; i++) {
|
for (int i = 0; i < testMatch.group!.members.length; i++) {
|
||||||
expect(game.group!.members[i].id, testGame.group!.members[i].id);
|
expect(match.group!.members[i].id, testMatch.group!.members[i].id);
|
||||||
expect(
|
expect(
|
||||||
game.group!.members[i].name,
|
match.group!.members[i].name,
|
||||||
testGame.group!.members[i].name,
|
testMatch.group!.members[i].name,
|
||||||
);
|
);
|
||||||
expect(
|
expect(
|
||||||
game.group!.members[i].createdAt,
|
match.group!.members[i].createdAt,
|
||||||
testGame.group!.members[i].createdAt,
|
testMatch.group!.members[i].createdAt,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
expect(game.group, null);
|
expect(match.group, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Players-Checks
|
// Players-Checks
|
||||||
if (testGame.players != null) {
|
if (testMatch.players != null) {
|
||||||
expect(game.players!.length, testGame.players!.length);
|
expect(match.players!.length, testMatch.players!.length);
|
||||||
for (int i = 0; i < testGame.players!.length; i++) {
|
for (int i = 0; i < testMatch.players!.length; i++) {
|
||||||
expect(game.players![i].id, testGame.players![i].id);
|
expect(match.players![i].id, testMatch.players![i].id);
|
||||||
expect(game.players![i].name, testGame.players![i].name);
|
expect(match.players![i].name, testMatch.players![i].name);
|
||||||
expect(game.players![i].createdAt, testGame.players![i].createdAt);
|
expect(
|
||||||
|
match.players![i].createdAt,
|
||||||
|
testMatch.players![i].createdAt,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
expect(game.players, null);
|
expect(match.players, null);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Adding the same game twice does not create duplicates', () async {
|
test('Adding the same match twice does not create duplicates', () async {
|
||||||
await database.gameDao.addGame(game: testGame1);
|
await database.matchDao.addMatch(match: testMatch1);
|
||||||
await database.gameDao.addGame(game: testGame1);
|
await database.matchDao.addMatch(match: testMatch1);
|
||||||
|
|
||||||
final gameCount = await database.gameDao.getGameCount();
|
final matchCount = await database.matchDao.getMatchCount();
|
||||||
expect(gameCount, 1);
|
expect(matchCount, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Game existence check works correctly', () async {
|
test('Match existence check works correctly', () async {
|
||||||
var gameExists = await database.gameDao.gameExists(gameId: testGame1.id);
|
var matchExists = await database.matchDao.matchExists(
|
||||||
expect(gameExists, false);
|
matchId: testMatch1.id,
|
||||||
|
|
||||||
await database.gameDao.addGame(game: testGame1);
|
|
||||||
|
|
||||||
gameExists = await database.gameDao.gameExists(gameId: testGame1.id);
|
|
||||||
expect(gameExists, true);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('Deleting a game works correctly', () async {
|
|
||||||
await database.gameDao.addGame(game: testGame1);
|
|
||||||
|
|
||||||
final gameDeleted = await database.gameDao.deleteGame(
|
|
||||||
gameId: testGame1.id,
|
|
||||||
);
|
);
|
||||||
expect(gameDeleted, true);
|
expect(matchExists, false);
|
||||||
|
|
||||||
final gameExists = await database.gameDao.gameExists(
|
await database.matchDao.addMatch(match: testMatch1);
|
||||||
gameId: testGame1.id,
|
|
||||||
|
matchExists = await database.matchDao.matchExists(matchId: testMatch1.id);
|
||||||
|
expect(matchExists, true);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Deleting a match works correctly', () async {
|
||||||
|
await database.matchDao.addMatch(match: testMatch1);
|
||||||
|
|
||||||
|
final matchDeleted = await database.matchDao.deleteMatch(
|
||||||
|
matchId: testMatch1.id,
|
||||||
);
|
);
|
||||||
expect(gameExists, false);
|
expect(matchDeleted, true);
|
||||||
|
|
||||||
|
final matchExists = await database.matchDao.matchExists(
|
||||||
|
matchId: testMatch1.id,
|
||||||
|
);
|
||||||
|
expect(matchExists, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Getting the game count works correctly', () async {
|
test('Getting the match count works correctly', () async {
|
||||||
var gameCount = await database.gameDao.getGameCount();
|
var matchCount = await database.matchDao.getMatchCount();
|
||||||
expect(gameCount, 0);
|
expect(matchCount, 0);
|
||||||
|
|
||||||
await database.gameDao.addGame(game: testGame1);
|
await database.matchDao.addMatch(match: testMatch1);
|
||||||
|
|
||||||
gameCount = await database.gameDao.getGameCount();
|
matchCount = await database.matchDao.getMatchCount();
|
||||||
expect(gameCount, 1);
|
expect(matchCount, 1);
|
||||||
|
|
||||||
await database.gameDao.addGame(game: testGame2);
|
await database.matchDao.addMatch(match: testMatch2);
|
||||||
|
|
||||||
gameCount = await database.gameDao.getGameCount();
|
matchCount = await database.matchDao.getMatchCount();
|
||||||
expect(gameCount, 2);
|
expect(matchCount, 2);
|
||||||
|
|
||||||
await database.gameDao.deleteGame(gameId: testGame1.id);
|
await database.matchDao.deleteMatch(matchId: testMatch1.id);
|
||||||
|
|
||||||
gameCount = await database.gameDao.getGameCount();
|
matchCount = await database.matchDao.getMatchCount();
|
||||||
expect(gameCount, 1);
|
expect(matchCount, 1);
|
||||||
|
|
||||||
await database.gameDao.deleteGame(gameId: testGame2.id);
|
await database.matchDao.deleteMatch(matchId: testMatch2.id);
|
||||||
|
|
||||||
gameCount = await database.gameDao.getGameCount();
|
matchCount = await database.matchDao.getMatchCount();
|
||||||
expect(gameCount, 0);
|
expect(matchCount, 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Checking if game has winner works correclty', () async {
|
test('Checking if match has winner works correclty', () async {
|
||||||
await database.gameDao.addGame(game: testGame1);
|
await database.matchDao.addMatch(match: testMatch1);
|
||||||
await database.gameDao.addGame(game: testGameOnlyGroup);
|
await database.matchDao.addMatch(match: testMatchOnlyGroup);
|
||||||
|
|
||||||
var hasWinner = await database.gameDao.hasWinner(gameId: testGame1.id);
|
var hasWinner = await database.matchDao.hasWinner(matchId: testMatch1.id);
|
||||||
expect(hasWinner, true);
|
expect(hasWinner, true);
|
||||||
|
|
||||||
hasWinner = await database.gameDao.hasWinner(
|
hasWinner = await database.matchDao.hasWinner(
|
||||||
gameId: testGameOnlyGroup.id,
|
matchId: testMatchOnlyGroup.id,
|
||||||
);
|
);
|
||||||
expect(hasWinner, false);
|
expect(hasWinner, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Fetching the winner of a game works correctly', () async {
|
test('Fetching the winner of a match works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testGame1);
|
await database.matchDao.addMatch(match: testMatch1);
|
||||||
|
|
||||||
final winner = await database.gameDao.getWinner(gameId: testGame1.id);
|
final winner = await database.matchDao.getWinner(matchId: testMatch1.id);
|
||||||
if (winner == null) {
|
if (winner == null) {
|
||||||
fail('Winner is null');
|
fail('Winner is null');
|
||||||
} else {
|
} else {
|
||||||
expect(winner.id, testGame1.winner!.id);
|
expect(winner.id, testMatch1.winner!.id);
|
||||||
expect(winner.name, testGame1.winner!.name);
|
expect(winner.name, testMatch1.winner!.name);
|
||||||
expect(winner.createdAt, testGame1.winner!.createdAt);
|
expect(winner.createdAt, testMatch1.winner!.createdAt);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Updating the winner of a game works correctly', () async {
|
test('Updating the winner of a match works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testGame1);
|
await database.matchDao.addMatch(match: testMatch1);
|
||||||
|
|
||||||
final winner = await database.gameDao.getWinner(gameId: testGame1.id);
|
final winner = await database.matchDao.getWinner(matchId: testMatch1.id);
|
||||||
if (winner == null) {
|
if (winner == null) {
|
||||||
fail('Winner is null');
|
fail('Winner is null');
|
||||||
} else {
|
} else {
|
||||||
expect(winner.id, testGame1.winner!.id);
|
expect(winner.id, testMatch1.winner!.id);
|
||||||
expect(winner.name, testGame1.winner!.name);
|
expect(winner.name, testMatch1.winner!.name);
|
||||||
expect(winner.createdAt, testGame1.winner!.createdAt);
|
expect(winner.createdAt, testMatch1.winner!.createdAt);
|
||||||
expect(winner.id, testPlayer4.id);
|
expect(winner.id, testPlayer4.id);
|
||||||
expect(winner.id != testPlayer5.id, true);
|
expect(winner.id != testPlayer5.id, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
await database.gameDao.setWinner(
|
await database.matchDao.setWinner(
|
||||||
gameId: testGame1.id,
|
matchId: testMatch1.id,
|
||||||
winnerId: testPlayer5.id,
|
winnerId: testPlayer5.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
final newWinner = await database.gameDao.getWinner(gameId: testGame1.id);
|
final newWinner = await database.matchDao.getWinner(
|
||||||
|
matchId: testMatch1.id,
|
||||||
|
);
|
||||||
|
|
||||||
if (newWinner == null) {
|
if (newWinner == null) {
|
||||||
fail('New winner is null');
|
fail('New winner is null');
|
||||||
@@ -292,39 +312,41 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('Removing a winner works correctly', () async {
|
test('Removing a winner works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testGame2);
|
await database.matchDao.addMatch(match: testMatch2);
|
||||||
|
|
||||||
var hasWinner = await database.gameDao.hasWinner(gameId: testGame2.id);
|
var hasWinner = await database.matchDao.hasWinner(matchId: testMatch2.id);
|
||||||
expect(hasWinner, true);
|
expect(hasWinner, true);
|
||||||
|
|
||||||
await database.gameDao.removeWinner(gameId: testGame2.id);
|
await database.matchDao.removeWinner(matchId: testMatch2.id);
|
||||||
|
|
||||||
hasWinner = await database.gameDao.hasWinner(gameId: testGame2.id);
|
hasWinner = await database.matchDao.hasWinner(matchId: testMatch2.id);
|
||||||
expect(hasWinner, false);
|
expect(hasWinner, false);
|
||||||
|
|
||||||
final removedWinner = await database.gameDao.getWinner(
|
final removedWinner = await database.matchDao.getWinner(
|
||||||
gameId: testGame2.id,
|
matchId: testMatch2.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(removedWinner, null);
|
expect(removedWinner, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Renaming a game works correctly', () async {
|
test('Renaming a match works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testGame1);
|
await database.matchDao.addMatch(match: testMatch1);
|
||||||
|
|
||||||
var fetchedGame = await database.gameDao.getGameById(
|
var fetchedMatch = await database.matchDao.getMatchById(
|
||||||
gameId: testGame1.id,
|
matchId: testMatch1.id,
|
||||||
);
|
);
|
||||||
expect(fetchedGame.name, testGame1.name);
|
expect(fetchedMatch.name, testMatch1.name);
|
||||||
|
|
||||||
const newName = 'Updated Game Name';
|
const newName = 'Updated Match Name';
|
||||||
await database.gameDao.updateGameName(
|
await database.matchDao.updateMatchName(
|
||||||
gameId: testGame1.id,
|
matchId: testMatch1.id,
|
||||||
newName: newName,
|
newName: newName,
|
||||||
);
|
);
|
||||||
|
|
||||||
fetchedGame = await database.gameDao.getGameById(gameId: testGame1.id);
|
fetchedMatch = await database.matchDao.getMatchById(
|
||||||
expect(fetchedGame.name, newName);
|
matchId: testMatch1.id,
|
||||||
|
);
|
||||||
|
expect(fetchedMatch.name, newName);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import 'package:drift/drift.dart';
|
|||||||
import 'package:drift/native.dart';
|
import 'package:drift/native.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:game_tracker/data/db/database.dart';
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
import 'package:game_tracker/data/dto/game.dart';
|
|
||||||
import 'package:game_tracker/data/dto/group.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';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@@ -16,8 +16,8 @@ void main() {
|
|||||||
late Player testPlayer5;
|
late Player testPlayer5;
|
||||||
late Group testGroup1;
|
late Group testGroup1;
|
||||||
late Group testGroup2;
|
late Group testGroup2;
|
||||||
late Game testgameWithGroup;
|
late Match testMatchWithGroup;
|
||||||
late Game testgameWithPlayers;
|
late Match testMatchWithPlayers;
|
||||||
final fixedDate = DateTime(2025, 19, 11, 00, 11, 23);
|
final fixedDate = DateTime(2025, 19, 11, 00, 11, 23);
|
||||||
final fakeClock = Clock(() => fixedDate);
|
final fakeClock = Clock(() => fixedDate);
|
||||||
|
|
||||||
@@ -44,81 +44,84 @@ void main() {
|
|||||||
name: 'Test Group',
|
name: 'Test Group',
|
||||||
members: [testPlayer3, testPlayer2],
|
members: [testPlayer3, testPlayer2],
|
||||||
);
|
);
|
||||||
testgameWithPlayers = Game(
|
testMatchWithPlayers = Match(
|
||||||
name: 'Test Game with Players',
|
name: 'Test Match with Players',
|
||||||
players: [testPlayer4, testPlayer5],
|
players: [testPlayer4, testPlayer5],
|
||||||
);
|
);
|
||||||
testgameWithGroup = Game(name: 'Test Game with Group', group: testGroup1);
|
testMatchWithGroup = Match(
|
||||||
|
name: 'Test Match with Group',
|
||||||
|
group: testGroup1,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
tearDown(() async {
|
tearDown(() async {
|
||||||
await database.close();
|
await database.close();
|
||||||
});
|
});
|
||||||
group('Group-Game Tests', () {
|
group('Group-Match Tests', () {
|
||||||
test('Game has group works correctly', () async {
|
test('matchHasGroup() has group works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testgameWithPlayers);
|
await database.matchDao.addMatch(match: testMatchWithPlayers);
|
||||||
await database.groupDao.addGroup(group: testGroup1);
|
await database.groupDao.addGroup(group: testGroup1);
|
||||||
|
|
||||||
var gameHasGroup = await database.groupGameDao.gameHasGroup(
|
var matchHasGroup = await database.groupMatchDao.matchHasGroup(
|
||||||
gameId: testgameWithPlayers.id,
|
matchId: testMatchWithPlayers.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(gameHasGroup, false);
|
expect(matchHasGroup, false);
|
||||||
|
|
||||||
await database.groupGameDao.addGroupToGame(
|
await database.groupMatchDao.addGroupToMatch(
|
||||||
gameId: testgameWithPlayers.id,
|
matchId: testMatchWithPlayers.id,
|
||||||
groupId: testGroup1.id,
|
groupId: testGroup1.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
gameHasGroup = await database.groupGameDao.gameHasGroup(
|
matchHasGroup = await database.groupMatchDao.matchHasGroup(
|
||||||
gameId: testgameWithPlayers.id,
|
matchId: testMatchWithPlayers.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(gameHasGroup, true);
|
expect(matchHasGroup, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Adding a group to a game works correctly', () async {
|
test('Adding a group to a match works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testgameWithPlayers);
|
await database.matchDao.addMatch(match: testMatchWithPlayers);
|
||||||
await database.groupDao.addGroup(group: testGroup1);
|
await database.groupDao.addGroup(group: testGroup1);
|
||||||
await database.groupGameDao.addGroupToGame(
|
await database.groupMatchDao.addGroupToMatch(
|
||||||
gameId: testgameWithPlayers.id,
|
matchId: testMatchWithPlayers.id,
|
||||||
groupId: testGroup1.id,
|
groupId: testGroup1.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
var groupAdded = await database.groupGameDao.isGroupInGame(
|
var groupAdded = await database.groupMatchDao.isGroupInMatch(
|
||||||
gameId: testgameWithPlayers.id,
|
matchId: testMatchWithPlayers.id,
|
||||||
groupId: testGroup1.id,
|
groupId: testGroup1.id,
|
||||||
);
|
);
|
||||||
expect(groupAdded, true);
|
expect(groupAdded, true);
|
||||||
|
|
||||||
groupAdded = await database.groupGameDao.isGroupInGame(
|
groupAdded = await database.groupMatchDao.isGroupInMatch(
|
||||||
gameId: testgameWithPlayers.id,
|
matchId: testMatchWithPlayers.id,
|
||||||
groupId: '',
|
groupId: '',
|
||||||
);
|
);
|
||||||
expect(groupAdded, false);
|
expect(groupAdded, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Removing group from game works correctly', () async {
|
test('Removing group from match works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testgameWithGroup);
|
await database.matchDao.addMatch(match: testMatchWithGroup);
|
||||||
|
|
||||||
final groupToRemove = testgameWithGroup.group!;
|
final groupToRemove = testMatchWithGroup.group!;
|
||||||
|
|
||||||
final removed = await database.groupGameDao.removeGroupFromGame(
|
final removed = await database.groupMatchDao.removeGroupFromMatch(
|
||||||
groupId: groupToRemove.id,
|
groupId: groupToRemove.id,
|
||||||
gameId: testgameWithGroup.id,
|
matchId: testMatchWithGroup.id,
|
||||||
);
|
);
|
||||||
expect(removed, true);
|
expect(removed, true);
|
||||||
|
|
||||||
final result = await database.gameDao.getGameById(
|
final result = await database.matchDao.getMatchById(
|
||||||
gameId: testgameWithGroup.id,
|
matchId: testMatchWithGroup.id,
|
||||||
);
|
);
|
||||||
expect(result.group, null);
|
expect(result.group, null);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Retrieving group of a game works correctly', () async {
|
test('Retrieving group of a match works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testgameWithGroup);
|
await database.matchDao.addMatch(match: testMatchWithGroup);
|
||||||
final group = await database.groupGameDao.getGroupOfGame(
|
final group = await database.groupMatchDao.getGroupOfMatch(
|
||||||
gameId: testgameWithGroup.id,
|
matchId: testMatchWithGroup.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (group == null) {
|
if (group == null) {
|
||||||
@@ -136,11 +139,11 @@ void main() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Updating the group of a game works correctly', () async {
|
test('Updating the group of a match works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testgameWithGroup);
|
await database.matchDao.addMatch(match: testMatchWithGroup);
|
||||||
|
|
||||||
var group = await database.groupGameDao.getGroupOfGame(
|
var group = await database.groupMatchDao.getGroupOfMatch(
|
||||||
gameId: testgameWithGroup.id,
|
matchId: testMatchWithGroup.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (group == null) {
|
if (group == null) {
|
||||||
@@ -153,13 +156,13 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await database.groupDao.addGroup(group: testGroup2);
|
await database.groupDao.addGroup(group: testGroup2);
|
||||||
await database.groupGameDao.updateGroupOfGame(
|
await database.groupMatchDao.updateGroupOfMatch(
|
||||||
gameId: testgameWithGroup.id,
|
matchId: testMatchWithGroup.id,
|
||||||
newGroupId: testGroup2.id,
|
newGroupId: testGroup2.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
group = await database.groupGameDao.getGroupOfGame(
|
group = await database.groupMatchDao.getGroupOfMatch(
|
||||||
gameId: testgameWithGroup.id,
|
matchId: testMatchWithGroup.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (group == null) {
|
if (group == null) {
|
||||||
|
|||||||
@@ -3,8 +3,8 @@ import 'package:drift/drift.dart';
|
|||||||
import 'package:drift/native.dart';
|
import 'package:drift/native.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:game_tracker/data/db/database.dart';
|
import 'package:game_tracker/data/db/database.dart';
|
||||||
import 'package:game_tracker/data/dto/game.dart';
|
|
||||||
import 'package:game_tracker/data/dto/group.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';
|
import 'package:game_tracker/data/dto/player.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
@@ -16,8 +16,8 @@ void main() {
|
|||||||
late Player testPlayer5;
|
late Player testPlayer5;
|
||||||
late Player testPlayer6;
|
late Player testPlayer6;
|
||||||
late Group testgroup;
|
late Group testgroup;
|
||||||
late Game testGameOnlyGroup;
|
late Match testMatchOnlyGroup;
|
||||||
late Game testGameOnlyPlayers;
|
late Match testMatchOnlyPlayers;
|
||||||
final fixedDate = DateTime(2025, 19, 11, 00, 11, 23);
|
final fixedDate = DateTime(2025, 19, 11, 00, 11, 23);
|
||||||
final fakeClock = Clock(() => fixedDate);
|
final fakeClock = Clock(() => fixedDate);
|
||||||
|
|
||||||
@@ -41,9 +41,12 @@ void main() {
|
|||||||
name: 'Test Group',
|
name: 'Test Group',
|
||||||
members: [testPlayer1, testPlayer2, testPlayer3],
|
members: [testPlayer1, testPlayer2, testPlayer3],
|
||||||
);
|
);
|
||||||
testGameOnlyGroup = Game(name: 'Test Game with Group', group: testgroup);
|
testMatchOnlyGroup = Match(
|
||||||
testGameOnlyPlayers = Game(
|
name: 'Test Match with Group',
|
||||||
name: 'Test Game with Players',
|
group: testgroup,
|
||||||
|
);
|
||||||
|
testMatchOnlyPlayers = Match(
|
||||||
|
name: 'Test Match with Players',
|
||||||
players: [testPlayer4, testPlayer5, testPlayer6],
|
players: [testPlayer4, testPlayer5, testPlayer6],
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -52,67 +55,67 @@ void main() {
|
|||||||
await database.close();
|
await database.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
group('Player-Game Tests', () {
|
group('Player-Match Tests', () {
|
||||||
test('Game has player works correctly', () async {
|
test('Match has player works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testGameOnlyGroup);
|
await database.matchDao.addMatch(match: testMatchOnlyGroup);
|
||||||
await database.playerDao.addPlayer(player: testPlayer1);
|
await database.playerDao.addPlayer(player: testPlayer1);
|
||||||
|
|
||||||
var gameHasPlayers = await database.playerGameDao.gameHasPlayers(
|
var matchHasPlayers = await database.playerMatchDao.matchHasPlayers(
|
||||||
gameId: testGameOnlyGroup.id,
|
matchId: testMatchOnlyGroup.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(gameHasPlayers, false);
|
expect(matchHasPlayers, false);
|
||||||
|
|
||||||
await database.playerGameDao.addPlayerToGame(
|
await database.playerMatchDao.addPlayerToMatch(
|
||||||
gameId: testGameOnlyGroup.id,
|
matchId: testMatchOnlyGroup.id,
|
||||||
playerId: testPlayer1.id,
|
playerId: testPlayer1.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
gameHasPlayers = await database.playerGameDao.gameHasPlayers(
|
matchHasPlayers = await database.playerMatchDao.matchHasPlayers(
|
||||||
gameId: testGameOnlyGroup.id,
|
matchId: testMatchOnlyGroup.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(gameHasPlayers, true);
|
expect(matchHasPlayers, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Adding a player to a game works correctly', () async {
|
test('Adding a player to a match works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testGameOnlyGroup);
|
await database.matchDao.addMatch(match: testMatchOnlyGroup);
|
||||||
await database.playerDao.addPlayer(player: testPlayer5);
|
await database.playerDao.addPlayer(player: testPlayer5);
|
||||||
await database.playerGameDao.addPlayerToGame(
|
await database.playerMatchDao.addPlayerToMatch(
|
||||||
gameId: testGameOnlyGroup.id,
|
matchId: testMatchOnlyGroup.id,
|
||||||
playerId: testPlayer5.id,
|
playerId: testPlayer5.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
var playerAdded = await database.playerGameDao.isPlayerInGame(
|
var playerAdded = await database.playerMatchDao.isPlayerInMatch(
|
||||||
gameId: testGameOnlyGroup.id,
|
matchId: testMatchOnlyGroup.id,
|
||||||
playerId: testPlayer5.id,
|
playerId: testPlayer5.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(playerAdded, true);
|
expect(playerAdded, true);
|
||||||
|
|
||||||
playerAdded = await database.playerGameDao.isPlayerInGame(
|
playerAdded = await database.playerMatchDao.isPlayerInMatch(
|
||||||
gameId: testGameOnlyGroup.id,
|
matchId: testMatchOnlyGroup.id,
|
||||||
playerId: '',
|
playerId: '',
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(playerAdded, false);
|
expect(playerAdded, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Removing player from game works correctly', () async {
|
test('Removing player from match works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testGameOnlyPlayers);
|
await database.matchDao.addMatch(match: testMatchOnlyPlayers);
|
||||||
|
|
||||||
final playerToRemove = testGameOnlyPlayers.players![0];
|
final playerToRemove = testMatchOnlyPlayers.players![0];
|
||||||
|
|
||||||
final removed = await database.playerGameDao.removePlayerFromGame(
|
final removed = await database.playerMatchDao.removePlayerFromMatch(
|
||||||
playerId: playerToRemove.id,
|
playerId: playerToRemove.id,
|
||||||
gameId: testGameOnlyPlayers.id,
|
matchId: testMatchOnlyPlayers.id,
|
||||||
);
|
);
|
||||||
expect(removed, true);
|
expect(removed, true);
|
||||||
|
|
||||||
final result = await database.gameDao.getGameById(
|
final result = await database.matchDao.getMatchById(
|
||||||
gameId: testGameOnlyPlayers.id,
|
matchId: testMatchOnlyPlayers.id,
|
||||||
);
|
);
|
||||||
expect(result.players!.length, testGameOnlyPlayers.players!.length - 1);
|
expect(result.players!.length, testMatchOnlyPlayers.players!.length - 1);
|
||||||
|
|
||||||
final playerExists = result.players!.any(
|
final playerExists = result.players!.any(
|
||||||
(p) => p.id == playerToRemove.id,
|
(p) => p.id == playerToRemove.id,
|
||||||
@@ -120,10 +123,10 @@ void main() {
|
|||||||
expect(playerExists, false);
|
expect(playerExists, false);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Retrieving players of a game works correctly', () async {
|
test('Retrieving players of a match works correctly', () async {
|
||||||
await database.gameDao.addGame(game: testGameOnlyPlayers);
|
await database.matchDao.addMatch(match: testMatchOnlyPlayers);
|
||||||
final players = await database.playerGameDao.getPlayersOfGame(
|
final players = await database.playerMatchDao.getPlayersOfMatch(
|
||||||
gameId: testGameOnlyPlayers.id,
|
matchId: testMatchOnlyPlayers.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (players == null) {
|
if (players == null) {
|
||||||
@@ -131,34 +134,37 @@ void main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < players.length; i++) {
|
for (int i = 0; i < players.length; i++) {
|
||||||
expect(players[i].id, testGameOnlyPlayers.players![i].id);
|
expect(players[i].id, testMatchOnlyPlayers.players![i].id);
|
||||||
expect(players[i].name, testGameOnlyPlayers.players![i].name);
|
expect(players[i].name, testMatchOnlyPlayers.players![i].name);
|
||||||
expect(players[i].createdAt, testGameOnlyPlayers.players![i].createdAt);
|
expect(
|
||||||
|
players[i].createdAt,
|
||||||
|
testMatchOnlyPlayers.players![i].createdAt,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Updating the games players works coreclty', () async {
|
test('Updating the match players works coreclty', () async {
|
||||||
await database.gameDao.addGame(game: testGameOnlyPlayers);
|
await database.matchDao.addMatch(match: testMatchOnlyPlayers);
|
||||||
|
|
||||||
final newPlayers = [testPlayer1, testPlayer2, testPlayer4];
|
final newPlayers = [testPlayer1, testPlayer2, testPlayer4];
|
||||||
await database.playerDao.addPlayersAsList(players: newPlayers);
|
await database.playerDao.addPlayersAsList(players: newPlayers);
|
||||||
|
|
||||||
// First, remove all existing players
|
// First, remove all existing players
|
||||||
final existingPlayers = await database.playerGameDao.getPlayersOfGame(
|
final existingPlayers = await database.playerMatchDao.getPlayersOfMatch(
|
||||||
gameId: testGameOnlyPlayers.id,
|
matchId: testMatchOnlyPlayers.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (existingPlayers == null || existingPlayers.isEmpty) {
|
if (existingPlayers == null || existingPlayers.isEmpty) {
|
||||||
fail('Existing players should not be null or empty');
|
fail('Existing players should not be null or empty');
|
||||||
}
|
}
|
||||||
|
|
||||||
await database.playerGameDao.updatePlayersFromGame(
|
await database.playerMatchDao.updatePlayersFromMatch(
|
||||||
gameId: testGameOnlyPlayers.id,
|
matchId: testMatchOnlyPlayers.id,
|
||||||
newPlayer: newPlayers,
|
newPlayer: newPlayers,
|
||||||
);
|
);
|
||||||
|
|
||||||
final updatedPlayers = await database.playerGameDao.getPlayersOfGame(
|
final updatedPlayers = await database.playerMatchDao.getPlayersOfMatch(
|
||||||
gameId: testGameOnlyPlayers.id,
|
matchId: testMatchOnlyPlayers.id,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (updatedPlayers == null) {
|
if (updatedPlayers == null) {
|
||||||
|
|||||||
Reference in New Issue
Block a user