From 56562b22bb3353f43d1e05d411fde988ef3a8646 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 12 Jan 2026 11:16:02 +0100 Subject: [PATCH 01/87] add description to player --- lib/data/db/tables/player_table.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/data/db/tables/player_table.dart b/lib/data/db/tables/player_table.dart index 794958e..63b666e 100644 --- a/lib/data/db/tables/player_table.dart +++ b/lib/data/db/tables/player_table.dart @@ -4,6 +4,7 @@ class PlayerTable extends Table { TextColumn get id => text()(); TextColumn get name => text()(); DateTimeColumn get createdAt => dateTime()(); + TextColumn get description => text().nullable()(); @override Set> get primaryKey => {id}; From 9b66e58dc08bc820859313d5f45c3503e81b7f98 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 12 Jan 2026 11:17:13 +0100 Subject: [PATCH 02/87] add team table --- lib/data/db/tables/team_table.dart | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 lib/data/db/tables/team_table.dart diff --git a/lib/data/db/tables/team_table.dart b/lib/data/db/tables/team_table.dart new file mode 100644 index 0000000..73e9998 --- /dev/null +++ b/lib/data/db/tables/team_table.dart @@ -0,0 +1,9 @@ +import 'package:drift/drift.dart'; + +class TeamTable extends Table { + TextColumn get id => text()(); + TextColumn get name => text()(); + + @override + Set> get primaryKey => {id}; +} From 3344575132b77b2fed035988ef48d9e208150ae4 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 12 Jan 2026 11:20:40 +0100 Subject: [PATCH 03/87] add team id and score --- lib/data/db/tables/player_match_table.dart | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/lib/data/db/tables/player_match_table.dart b/lib/data/db/tables/player_match_table.dart index e155cd5..721e222 100644 --- a/lib/data/db/tables/player_match_table.dart +++ b/lib/data/db/tables/player_match_table.dart @@ -1,12 +1,16 @@ 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'; +import 'package:game_tracker/data/db/tables/team_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)(); + TextColumn get teamId => + text().references(TeamTable, #id).nullable()(); + IntColumn get score => integer()(); @override Set> get primaryKey => {playerId, matchId}; From 7e6c309de044d86fb8b793d62252973471b3ef70 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 12 Jan 2026 11:26:39 +0100 Subject: [PATCH 04/87] add game table --- lib/data/db/tables/game_table.dart | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 lib/data/db/tables/game_table.dart diff --git a/lib/data/db/tables/game_table.dart b/lib/data/db/tables/game_table.dart new file mode 100644 index 0000000..2074ae7 --- /dev/null +++ b/lib/data/db/tables/game_table.dart @@ -0,0 +1,14 @@ +import 'package:drift/drift.dart'; + +class GameTable extends Table { + TextColumn get id => text()(); + TextColumn get name => text()(); + TextColumn get ruleset => text()(); + TextColumn get description => text().nullable()(); + TextColumn get color => text().nullable()(); + TextColumn get icon => text().nullable()(); + DateTimeColumn get createdAt => dateTime()(); + + @override + Set> get primaryKey => {id}; +} From d8abad6fd822c0e16d17557215a5742b95c5b4ee Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 12 Jan 2026 11:30:37 +0100 Subject: [PATCH 05/87] add groupid gameid and notes to match --- lib/data/db/tables/match_table.dart | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/data/db/tables/match_table.dart b/lib/data/db/tables/match_table.dart index 96aff2a..c71f8bd 100644 --- a/lib/data/db/tables/match_table.dart +++ b/lib/data/db/tables/match_table.dart @@ -1,9 +1,15 @@ 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 MatchTable extends Table { TextColumn get id => text()(); - TextColumn get name => text()(); - late final winnerId = text().nullable()(); + TextColumn get name => text().nullable()(); + TextColumn get gameId => + text().references(GameTable, #id, onDelete: KeyAction.cascade)(); + TextColumn get groupId => + text().references(GroupTable, #id, onDelete: KeyAction.cascade).nullable()(); // Nullable if not part of a group + TextColumn get notes => text().nullable()(); DateTimeColumn get createdAt => dateTime()(); @override From 0394f5edf954b68ac41d951498b205fd84dfdfee Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 12 Jan 2026 11:32:23 +0100 Subject: [PATCH 06/87] delete group_match_table.dart --- lib/data/db/tables/group_match_table.dart | 13 ------------- 1 file changed, 13 deletions(-) delete mode 100644 lib/data/db/tables/group_match_table.dart diff --git a/lib/data/db/tables/group_match_table.dart b/lib/data/db/tables/group_match_table.dart deleted file mode 100644 index 3f77dcb..0000000 --- a/lib/data/db/tables/group_match_table.dart +++ /dev/null @@ -1,13 +0,0 @@ -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> get primaryKey => {groupId, matchId}; -} From 5dd8f31942e4cc278c791061e2fdf08a7e17a372 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 12 Jan 2026 11:33:00 +0100 Subject: [PATCH 07/87] add description to group_table.dart --- lib/data/db/tables/group_table.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/data/db/tables/group_table.dart b/lib/data/db/tables/group_table.dart index 5c52355..09bf79d 100644 --- a/lib/data/db/tables/group_table.dart +++ b/lib/data/db/tables/group_table.dart @@ -3,6 +3,7 @@ import 'package:drift/drift.dart'; class GroupTable extends Table { TextColumn get id => text()(); TextColumn get name => text()(); + TextColumn get description => text().nullable()(); DateTimeColumn get createdAt => dateTime()(); @override From 0f987f4c7adbd5328288049380bebf5e0e01cb15 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 12 Jan 2026 11:34:02 +0100 Subject: [PATCH 08/87] move match below ids --- lib/data/db/tables/match_table.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/data/db/tables/match_table.dart b/lib/data/db/tables/match_table.dart index c71f8bd..5deb5c5 100644 --- a/lib/data/db/tables/match_table.dart +++ b/lib/data/db/tables/match_table.dart @@ -4,14 +4,14 @@ import 'package:game_tracker/data/db/tables/group_table.dart'; class MatchTable extends Table { TextColumn get id => text()(); - TextColumn get name => text().nullable()(); TextColumn get gameId => text().references(GameTable, #id, onDelete: KeyAction.cascade)(); TextColumn get groupId => text().references(GroupTable, #id, onDelete: KeyAction.cascade).nullable()(); // Nullable if not part of a group + TextColumn get name => text().nullable()(); TextColumn get notes => text().nullable()(); DateTimeColumn get createdAt => dateTime()(); @override Set> get primaryKey => {id}; -} +} \ No newline at end of file From 189daf76ddd9a2cfbcb3ac8fc3e410d803c73a6a Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 12 Jan 2026 11:35:57 +0100 Subject: [PATCH 09/87] move createdAt below description --- lib/data/db/tables/player_table.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/data/db/tables/player_table.dart b/lib/data/db/tables/player_table.dart index 63b666e..3e061a0 100644 --- a/lib/data/db/tables/player_table.dart +++ b/lib/data/db/tables/player_table.dart @@ -3,8 +3,8 @@ import 'package:drift/drift.dart'; class PlayerTable extends Table { TextColumn get id => text()(); TextColumn get name => text()(); - DateTimeColumn get createdAt => dateTime()(); TextColumn get description => text().nullable()(); + DateTimeColumn get createdAt => dateTime()(); @override Set> get primaryKey => {id}; From b72ab70e02a3030654049b0d635bf087f20955cb Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 12 Jan 2026 11:38:38 +0100 Subject: [PATCH 10/87] add score table --- lib/data/db/tables/score_table.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 lib/data/db/tables/score_table.dart diff --git a/lib/data/db/tables/score_table.dart b/lib/data/db/tables/score_table.dart new file mode 100644 index 0000000..93542c3 --- /dev/null +++ b/lib/data/db/tables/score_table.dart @@ -0,0 +1,16 @@ +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 ScoreTable extends Table { + TextColumn get playerId => + text().references(PlayerTable, #id, onDelete: KeyAction.cascade)(); + TextColumn get matchId => + text().references(MatchTable, #id, onDelete: KeyAction.cascade)(); + IntColumn get roundNumber => integer()(); + IntColumn get score => integer()(); + IntColumn get change => integer()(); + + @override + Set> get primaryKey => {playerId, matchId, roundNumber}; +} \ No newline at end of file From e2fe0c7d4dacc4952d8caa27a29ab6f6d0d8a04d Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 12 Jan 2026 11:42:03 +0100 Subject: [PATCH 11/87] remove group_match_dao --- lib/data/dao/group_match_dao.dart | 98 ----------------------------- lib/data/dao/group_match_dao.g.dart | 10 --- lib/data/db/database.dart | 8 +-- 3 files changed, 2 insertions(+), 114 deletions(-) delete mode 100644 lib/data/dao/group_match_dao.dart delete mode 100644 lib/data/dao/group_match_dao.g.dart diff --git a/lib/data/dao/group_match_dao.dart b/lib/data/dao/group_match_dao.dart deleted file mode 100644 index d428fb5..0000000 --- a/lib/data/dao/group_match_dao.dart +++ /dev/null @@ -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_match_table.dart'; -import 'package:game_tracker/data/dto/group.dart'; - -part 'group_match_dao.g.dart'; - -@DriftAccessor(tables: [GroupMatchTable]) -class GroupMatchDao extends DatabaseAccessor - with _$GroupMatchDaoMixin { - GroupMatchDao(super.db); - - /// Associates a group with a match by inserting a record into the - /// [GroupMatchTable]. - Future 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.insertOrIgnore, - ); - } - - /// Retrieves the [Group] associated with the given [matchId]. - /// Returns `null` if no group is found. - Future 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 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 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 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 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; - } -} diff --git a/lib/data/dao/group_match_dao.g.dart b/lib/data/dao/group_match_dao.g.dart deleted file mode 100644 index 5cc0b82..0000000 --- a/lib/data/dao/group_match_dao.g.dart +++ /dev/null @@ -1,10 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'group_match_dao.dart'; - -// ignore_for_file: type=lint -mixin _$GroupMatchDaoMixin on DatabaseAccessor { - $GroupTableTable get groupTable => attachedDatabase.groupTable; - $MatchTableTable get matchTable => attachedDatabase.matchTable; - $GroupMatchTableTable get groupMatchTable => attachedDatabase.groupMatchTable; -} diff --git a/lib/data/db/database.dart b/lib/data/db/database.dart index e6c322f..632a4c6 100644 --- a/lib/data/db/database.dart +++ b/lib/data/db/database.dart @@ -1,12 +1,10 @@ import 'package:drift/drift.dart'; import 'package:drift_flutter/drift_flutter.dart'; import 'package:game_tracker/data/dao/group_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_group_dao.dart'; import 'package:game_tracker/data/dao/player_match_dao.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/match_table.dart'; import 'package:game_tracker/data/db/tables/player_group_table.dart'; @@ -22,16 +20,14 @@ part 'database.g.dart'; GroupTable, MatchTable, PlayerGroupTable, - PlayerMatchTable, - GroupMatchTable, + PlayerMatchTable ], daos: [ PlayerDao, GroupDao, MatchDao, PlayerGroupDao, - PlayerMatchDao, - GroupMatchDao, + PlayerMatchDao ], ) class AppDatabase extends _$AppDatabase { From be01b5f72aa80de6b97648b8df04de2d66f3f3f6 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 12 Jan 2026 12:51:25 +0100 Subject: [PATCH 12/87] add description to group --- lib/data/dto/group.dart | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/data/dto/group.dart b/lib/data/dto/group.dart index 92dbd09..4a6f7cd 100644 --- a/lib/data/dto/group.dart +++ b/lib/data/dto/group.dart @@ -4,21 +4,23 @@ import 'package:uuid/uuid.dart'; class Group { final String id; - final DateTime createdAt; final String name; + final String? description; + final DateTime createdAt; final List members; Group({ String? id, DateTime? createdAt, required this.name, + this.description, required this.members, }) : id = id ?? const Uuid().v4(), createdAt = createdAt ?? clock.now(); @override String toString() { - return 'Group{id: $id, name: $name,members: $members}'; + return 'Group{id: $id, name: $name, description: $description, members: $members}'; } /// Creates a Group instance from a JSON object. @@ -26,6 +28,7 @@ class Group { : id = json['id'], createdAt = DateTime.parse(json['createdAt']), name = json['name'], + description = json['description'], members = (json['members'] as List) .map((memberJson) => Player.fromJson(memberJson)) .toList(); @@ -35,6 +38,7 @@ class Group { 'id': id, 'createdAt': createdAt.toIso8601String(), 'name': name, + 'description': description, 'members': members.map((member) => member.toJson()).toList(), }; } From 6a9e5dc9ebfe4c481bdc50a6c75346417e619105 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 10:28:55 +0100 Subject: [PATCH 13/87] add game.dart --- lib/data/dto/game.dart | 50 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 lib/data/dto/game.dart diff --git a/lib/data/dto/game.dart b/lib/data/dto/game.dart new file mode 100644 index 0000000..9e271e5 --- /dev/null +++ b/lib/data/dto/game.dart @@ -0,0 +1,50 @@ +import 'package:clock/clock.dart'; +import 'package:uuid/uuid.dart'; + +class Game { + final String id; + final DateTime createdAt; + final String name; + final String? ruleset; + final String? description; + final int? color; + final String? icon; + + Game({ + String? id, + DateTime? createdAt, + required this.name, + this.ruleset, + this.description, + this.color, + this.icon, + }) : id = id ?? const Uuid().v4(), + createdAt = createdAt ?? clock.now(); + + @override + String toString() { + return 'Game{id: $id, name: $name, ruleset: $ruleset, description: $description, color: $color, icon: $icon}'; + } + + /// Creates a Game instance from a JSON object. + Game.fromJson(Map json) + : id = json['id'], + createdAt = DateTime.parse(json['createdAt']), + name = json['name'], + ruleset = json['ruleset'], + description = json['description'], + color = json['color'], + icon = json['icon']; + + /// Converts the Game instance to a JSON object. + Map toJson() => { + 'id': id, + 'createdAt': createdAt.toIso8601String(), + 'name': name, + 'ruleset': ruleset, + 'description': description, + 'color': color, + 'icon': icon, + }; +} + From 072021bd4c466ea1d784fa949655ddf9f1002745 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 10:50:03 +0100 Subject: [PATCH 14/87] update match class --- lib/data/dto/match.dart | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/lib/data/dto/match.dart b/lib/data/dto/match.dart index 9570f66..c91dc92 100644 --- a/lib/data/dto/match.dart +++ b/lib/data/dto/match.dart @@ -1,4 +1,5 @@ import 'package:clock/clock.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'; import 'package:uuid/uuid.dart'; @@ -7,45 +8,49 @@ class Match { final String id; final DateTime createdAt; final String name; - final List? players; + final Game? game; final Group? group; - Player? winner; + final List? players; + final String? notes; Match({ String? id, DateTime? createdAt, required this.name, - this.players, + this.game, this.group, - this.winner, + this.players, + this.notes, }) : id = id ?? const Uuid().v4(), createdAt = createdAt ?? clock.now(); @override String toString() { - return 'Match{\n\tid: $id,\n\tname: $name,\n\tplayers: $players,\n\tgroup: $group,\n\twinner: $winner\n}'; + return 'Match{id: $id, name: $name, game: $game, group: $group, players: $players, notes: $notes}'; } /// Creates a Match instance from a JSON object. Match.fromJson(Map json) : id = json['id'], - name = json['name'], createdAt = DateTime.parse(json['createdAt']), + name = json['name'], + game = json['game'] != null ? Game.fromJson(json['game']) : null, + group = json['group'] != null ? Group.fromJson(json['group']) : null, players = json['players'] != null ? (json['players'] as List) - .map((playerJson) => Player.fromJson(playerJson)) - .toList() + .map((playerJson) => Player.fromJson(playerJson)) + .toList() : null, - group = json['group'] != null ? Group.fromJson(json['group']) : null, - winner = json['winner'] != null ? Player.fromJson(json['winner']) : null; + notes = json['notes']; /// Converts the Match instance to a JSON object. Map toJson() => { 'id': id, 'createdAt': createdAt.toIso8601String(), 'name': name, - 'players': players?.map((player) => player.toJson()).toList(), + 'game': game?.toJson(), 'group': group?.toJson(), - 'winner': winner?.toJson(), + 'players': players?.map((player) => player.toJson()).toList(), + 'notes': notes, }; } From c82d72544e1a671389e9be7fbe17c6adbda9ae3a Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 11:04:54 +0100 Subject: [PATCH 15/87] add description to player --- lib/data/dto/player.dart | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/lib/data/dto/player.dart b/lib/data/dto/player.dart index cfb4f4b..6c3ab6d 100644 --- a/lib/data/dto/player.dart +++ b/lib/data/dto/player.dart @@ -5,26 +5,33 @@ class Player { final String id; final DateTime createdAt; final String name; + final String? description; - Player({String? id, DateTime? createdAt, required this.name}) - : id = id ?? const Uuid().v4(), - createdAt = createdAt ?? clock.now(); + Player({ + String? id, + DateTime? createdAt, + required this.name, + this.description, + }) : id = id ?? const Uuid().v4(), + createdAt = createdAt ?? clock.now(); @override String toString() { - return 'Player{id: $id,name: $name}'; + return 'Player{id: $id, name: $name, description: $description}'; } /// Creates a Player instance from a JSON object. Player.fromJson(Map json) : id = json['id'], createdAt = DateTime.parse(json['createdAt']), - name = json['name']; + name = json['name'], + description = json['description']; /// Converts the Player instance to a JSON object. Map toJson() => { 'id': id, 'createdAt': createdAt.toIso8601String(), 'name': name, + 'description': description, }; } From f2a12265ad6560ddc5cb0bc6bff5cea73432867a Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 11:09:08 +0100 Subject: [PATCH 16/87] add createdAt to team --- lib/data/db/tables/team_table.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/data/db/tables/team_table.dart b/lib/data/db/tables/team_table.dart index 73e9998..b1a24a9 100644 --- a/lib/data/db/tables/team_table.dart +++ b/lib/data/db/tables/team_table.dart @@ -3,6 +3,7 @@ import 'package:drift/drift.dart'; class TeamTable extends Table { TextColumn get id => text()(); TextColumn get name => text()(); + DateTimeColumn get createdAt => dateTime()(); @override Set> get primaryKey => {id}; From 4a56df7f8fed45f19ab6778d1dbe6770ec0d7818 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 11:09:18 +0100 Subject: [PATCH 17/87] add team --- lib/data/dto/team.dart | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 lib/data/dto/team.dart diff --git a/lib/data/dto/team.dart b/lib/data/dto/team.dart new file mode 100644 index 0000000..8b015ba --- /dev/null +++ b/lib/data/dto/team.dart @@ -0,0 +1,37 @@ +import 'package:clock/clock.dart'; +import 'package:game_tracker/data/dto/player.dart'; +import 'package:uuid/uuid.dart'; + +class Team { + final String id; + final DateTime createdAt; + final List members; + + Team({ + String? id, + DateTime? createdAt, + required this.members, + }) : id = id ?? const Uuid().v4(), + createdAt = createdAt ?? clock.now(); + + @override + String toString() { + return 'Team{id: $id, members: $members}'; + } + + /// Creates a Team instance from a JSON object. + Team.fromJson(Map json) + : id = json['id'], + createdAt = DateTime.parse(json['createdAt']), + members = (json['members'] as List) + .map((memberJson) => Player.fromJson(memberJson)) + .toList(); + + /// Converts the Team instance to a JSON object. + Map toJson() => { + 'id': id, + 'createdAt': createdAt.toIso8601String(), + 'members': members.map((member) => member.toJson()).toList(), + }; +} + From b9b72cdd509302096aa5a4fc6916c55b5da6fb86 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 11:10:42 +0100 Subject: [PATCH 18/87] add pair --- lib/data/dto/pair.dart | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 lib/data/dto/pair.dart diff --git a/lib/data/dto/pair.dart b/lib/data/dto/pair.dart new file mode 100644 index 0000000..2cce9f8 --- /dev/null +++ b/lib/data/dto/pair.dart @@ -0,0 +1,16 @@ +import 'package:game_tracker/data/dto/team.dart'; + +class Pair extends Team { + Pair({ + super.id, + super.createdAt, + required super.members, + }); + + @override + String toString() { + return 'Pair{id: $id, members: $members}'; + } + +} + From cb66b76e5a4bd8bb16a70bfdc311044c053a19d2 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 11:55:47 +0100 Subject: [PATCH 19/87] add game_dao.dart --- lib/data/dao/game_dao.dart | 179 +++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) create mode 100644 lib/data/dao/game_dao.dart diff --git a/lib/data/dao/game_dao.dart b/lib/data/dao/game_dao.dart new file mode 100644 index 0000000..4b99dfa --- /dev/null +++ b/lib/data/dao/game_dao.dart @@ -0,0 +1,179 @@ +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'; + +part 'game_dao.g.dart'; + +@DriftAccessor(tables: [GameTable]) +class GameDao extends DatabaseAccessor with _$GameDaoMixin { + GameDao(super.db); + + /// Retrieves all games from the database. + Future> getAllGames() async { + final query = select(gameTable); + final result = await query.get(); + return result + .map( + (row) => Game( + id: row.id, + name: row.name, + ruleset: row.ruleset, + description: row.description, + color: row.color != null ? int.tryParse(row.color!) : null, + icon: row.icon, + createdAt: row.createdAt, + ), + ) + .toList(); + } + + /// Retrieves a [Game] by its [gameId]. + Future getGameById({required String gameId}) async { + final query = select(gameTable)..where((g) => g.id.equals(gameId)); + final result = await query.getSingle(); + return Game( + id: result.id, + name: result.name, + ruleset: result.ruleset, + description: result.description, + color: result.color != null ? int.tryParse(result.color!) : null, + icon: result.icon, + createdAt: result.createdAt, + ); + } + + /// Adds a new [game] to the database. + /// If a game with the same ID already exists, no action is taken. + /// Returns `true` if the game was added, `false` otherwise. + Future addGame({required Game game}) async { + if (!await gameExists(gameId: game.id)) { + await into(gameTable).insert( + GameTableCompanion.insert( + id: game.id, + name: game.name, + ruleset: game.ruleset ?? '', + description: Value(game.description), + color: Value(game.color?.toString()), + icon: Value(game.icon), + createdAt: game.createdAt, + ), + mode: InsertMode.insertOrReplace, + ); + return true; + } + return false; + } + + /// Adds multiple [games] to the database in a batch operation. + /// Uses insertOrIgnore to avoid overwriting existing games. + Future addGamesAsList({required List games}) async { + if (games.isEmpty) return false; + + await db.batch( + (b) => b.insertAll( + gameTable, + games + .map( + (game) => GameTableCompanion.insert( + id: game.id, + name: game.name, + ruleset: game.ruleset ?? '', + description: Value(game.description), + color: Value(game.color?.toString()), + icon: Value(game.icon), + createdAt: game.createdAt, + ), + ) + .toList(), + mode: InsertMode.insertOrIgnore, + ), + ); + + return true; + } + + /// Deletes the game with the given [gameId] from the database. + /// Returns `true` if the game was deleted, `false` if the game did not exist. + Future deleteGame({required String gameId}) async { + final query = delete(gameTable)..where((g) => g.id.equals(gameId)); + final rowsAffected = await query.go(); + return rowsAffected > 0; + } + + /// Checks if a game with the given [gameId] exists in the database. + /// Returns `true` if the game exists, `false` otherwise. + Future gameExists({required String gameId}) async { + final query = select(gameTable)..where((g) => g.id.equals(gameId)); + final result = await query.getSingleOrNull(); + return result != null; + } + + /// Updates the name of the game with the given [gameId] to [newName]. + Future updateGameName({ + required String gameId, + required String newName, + }) async { + await (update(gameTable)..where((g) => g.id.equals(gameId))).write( + GameTableCompanion(name: Value(newName)), + ); + } + + /// Updates the ruleset of the game with the given [gameId]. + Future updateGameRuleset({ + required String gameId, + required String newRuleset, + }) async { + await (update(gameTable)..where((g) => g.id.equals(gameId))).write( + GameTableCompanion(ruleset: Value(newRuleset)), + ); + } + + /// Updates the description of the game with the given [gameId]. + Future updateGameDescription({ + required String gameId, + required String? newDescription, + }) async { + await (update(gameTable)..where((g) => g.id.equals(gameId))).write( + GameTableCompanion(description: Value(newDescription)), + ); + } + + /// Updates the color of the game with the given [gameId]. + Future updateGameColor({ + required String gameId, + required int? newColor, + }) async { + await (update(gameTable)..where((g) => g.id.equals(gameId))).write( + GameTableCompanion(color: Value(newColor?.toString())), + ); + } + + /// Updates the icon of the game with the given [gameId]. + Future updateGameIcon({ + required String gameId, + required String? newIcon, + }) async { + await (update(gameTable)..where((g) => g.id.equals(gameId))).write( + GameTableCompanion(icon: Value(newIcon)), + ); + } + + /// Retrieves the total count of games in the database. + Future getGameCount() async { + final count = + await (selectOnly(gameTable)..addColumns([gameTable.id.count()])) + .map((row) => row.read(gameTable.id.count())) + .getSingle(); + return count ?? 0; + } + + /// Deletes all games from the database. + /// Returns `true` if more than 0 rows were affected, otherwise `false`. + Future deleteAllGames() async { + final query = delete(gameTable); + final rowsAffected = await query.go(); + return rowsAffected > 0; + } +} + From 3ca612b0a11f697d31465a199e7a0ac3a4884d08 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 11:56:47 +0100 Subject: [PATCH 20/87] add description attribute to group_dao.dart --- lib/data/dao/group_dao.dart | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/lib/data/dao/group_dao.dart b/lib/data/dao/group_dao.dart index 98c602a..999200d 100644 --- a/lib/data/dao/group_dao.dart +++ b/lib/data/dao/group_dao.dart @@ -23,6 +23,7 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { return Group( id: groupData.id, name: groupData.name, + description: groupData.description, members: members, createdAt: groupData.createdAt, ); @@ -42,6 +43,7 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { return Group( id: result.id, name: result.name, + description: result.description, members: members, createdAt: result.createdAt, ); @@ -56,6 +58,7 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { GroupTableCompanion.insert( id: group.id, name: group.name, + description: Value(group.description), createdAt: group.createdAt, ), mode: InsertMode.insertOrReplace, @@ -105,6 +108,7 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { (group) => GroupTableCompanion.insert( id: group.id, name: group.name, + description: Value(group.description), createdAt: group.createdAt, ), ) @@ -132,6 +136,7 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { (p) => PlayerTableCompanion.insert( id: p.id, name: p.name, + description: Value(p.description), createdAt: p.createdAt, ), ) From 02d3220c1a2c0b40fe5479105b23b97b2d228e77 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 11:57:50 +0100 Subject: [PATCH 21/87] add group_match_dao.dart --- lib/data/dao/group_match_dao.dart | 108 ++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 lib/data/dao/group_match_dao.dart diff --git a/lib/data/dao/group_match_dao.dart b/lib/data/dao/group_match_dao.dart new file mode 100644 index 0000000..8f0700a --- /dev/null +++ b/lib/data/dao/group_match_dao.dart @@ -0,0 +1,108 @@ +import 'package:drift/drift.dart'; +import 'package:game_tracker/data/db/database.dart'; +import 'package:game_tracker/data/db/tables/group_match_table.dart'; +import 'package:game_tracker/data/db/tables/group_table.dart'; +import 'package:game_tracker/data/dto/group.dart'; + +part 'group_match_dao.g.dart'; + +@DriftAccessor(tables: [GroupMatchTable, GroupTable]) +class GroupMatchDao extends DatabaseAccessor + with _$GroupMatchDaoMixin { + GroupMatchDao(super.db); + + /// Adds a group to a match by inserting a record into the [GroupMatchTable]. + Future addGroupToMatch({ + required String matchId, + required String groupId, + }) async { + await into(groupMatchTable).insert( + GroupMatchTableCompanion.insert( + matchId: matchId, + groupId: groupId, + ), + mode: InsertMode.insertOrIgnore, + ); + } + + /// Retrieves the [Group] associated with the given [matchId]. + /// Returns null if no group is found. + Future getGroupOfMatch({required String matchId}) async { + final query = select(groupMatchTable) + ..where((gm) => gm.matchId.equals(matchId)); + final result = await query.getSingleOrNull(); + + if (result == null) return null; + + return db.groupDao.getGroupById(groupId: result.groupId); + } + + /// Checks if a match has a group associated with it. + /// Returns `true` if the match has a group, otherwise `false`. + Future 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 isGroupInMatch({ + required String matchId, + required String groupId, + }) async { + final query = select(groupMatchTable) + ..where( + (gm) => gm.matchId.equals(matchId) & gm.groupId.equals(groupId), + ); + final result = await query.getSingleOrNull(); + return result != null; + } + + /// Removes the association of a group with a match by deleting the record + /// from the [GroupMatchTable]. + /// Returns `true` if more than 0 rows were affected, otherwise `false`. + Future removeGroupFromMatch({ + required String matchId, + required String groupId, + }) async { + final query = delete(groupMatchTable) + ..where((gm) => gm.matchId.equals(matchId) & gm.groupId.equals(groupId)); + final rowsAffected = await query.go(); + return rowsAffected > 0; + } + + /// Updates the group associated with a match. + /// Removes the existing group association and adds the new one. + Future updateGroupOfMatch({ + required String matchId, + required String newGroupId, + }) async { + await db.transaction(() async { + // Remove existing group association + await (delete(groupMatchTable) + ..where((gm) => gm.matchId.equals(matchId))) + .go(); + + // Add new group association + await into(groupMatchTable).insert( + GroupMatchTableCompanion.insert( + matchId: matchId, + groupId: newGroupId, + ), + ); + }); + } + + /// Retrieves all matches associated with a specific group. + Future> getMatchIdsForGroup({required String groupId}) async { + final query = select(groupMatchTable) + ..where((gm) => gm.groupId.equals(groupId)); + final result = await query.get(); + return result.map((row) => row.matchId).toList(); + } +} + From 867d0c55daff826b6f0dd2d7087fcfd3f550b995 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 12:00:07 +0100 Subject: [PATCH 22/87] update match_dao.dart --- lib/data/dao/match_dao.dart | 240 +++++++++++++++++++----------------- 1 file changed, 128 insertions(+), 112 deletions(-) diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index 160686a..0c16a6b 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -1,13 +1,17 @@ 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/db/tables/group_table.dart'; import 'package:game_tracker/data/db/tables/match_table.dart'; +import 'package:game_tracker/data/db/tables/player_match_table.dart'; +import 'package:game_tracker/data/dto/game.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]) +@DriftAccessor(tables: [MatchTable, GameTable, GroupTable, PlayerMatchTable]) class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { MatchDao(super.db); @@ -18,20 +22,22 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { return Future.wait( result.map((row) async { - final group = await db.groupMatchDao.getGroupOfMatch(matchId: row.id); + final game = await db.gameDao.getGameById(gameId: row.gameId); + Group? group; + if (row.groupId != null) { + group = await db.groupDao.getGroupById(groupId: row.groupId!); + } final players = await db.playerMatchDao.getPlayersOfMatch( matchId: row.id, ); - final winner = row.winnerId != null - ? await db.playerDao.getPlayerById(playerId: row.winnerId!) - : null; return Match( id: row.id, - name: row.name, + name: row.name ?? '', + game: game, group: group, players: players, + notes: row.notes, createdAt: row.createdAt, - winner: winner, ); }), ); @@ -42,100 +48,110 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { final query = select(matchTable)..where((g) => g.id.equals(matchId)); final result = await query.getSingle(); + final game = await db.gameDao.getGameById(gameId: result.gameId); + + Group? group; + if (result.groupId != null) { + group = await db.groupDao.getGroupById(groupId: result.groupId!); + } + List? 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, + name: result.name ?? '', + game: game, group: group, - winner: winner, + players: players, + notes: result.notes, createdAt: result.createdAt, ); } - /// Adds a new [Match] to the database. Also adds players and group - /// associations. This method assumes that the players and groups added to - /// this match are already present in the database. + /// Adds a new [Match] to the database. Also adds players associations. + /// This method assumes that the game and group (if any) are already present + /// in the database. Future addMatch({required Match match}) async { + if (match.game == null) { + throw ArgumentError('Match must have a game associated with it'); + } + await db.transaction(() async { await into(matchTable).insert( MatchTableCompanion.insert( id: match.id, - name: match.name, - winnerId: Value(match.winner?.id), + gameId: match.game!.id, + groupId: Value(match.group?.id), + name: Value(match.name), + notes: Value(match.notes), createdAt: match.createdAt, ), mode: InsertMode.insertOrReplace, ); if (match.players != null) { - for (final p in match.players ?? []) { + for (final p in match.players!) { await db.playerMatchDao.addPlayerToMatch( matchId: match.id, playerId: p.id, ); } } - - if (match.group != null) { - await db.groupMatchDao.addGroupToMatch( - matchId: match.id, - groupId: match.group!.id, - ); - } }); } - /// Adds multiple [Match]s to the database in a batch operation. + /// Adds multiple [Match]es to the database in a batch operation. /// Also adds associated players and groups if they exist. /// If the [matches] list is empty, the method returns immediately. - /// This Method should only be used to import matches from a different device. + /// This method should only be used to import matches from a different device. Future addMatchAsList({required List 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 games first (deduplicated) + final uniqueGames = {}; + for (final match in matches) { + if (match.game != null) { + uniqueGames[match.game!.id] = match.game!; + } + } + + if (uniqueGames.isNotEmpty) { + await db.batch( + (b) => b.insertAll( + db.gameTable, + uniqueGames.values + .map( + (game) => GameTableCompanion.insert( + id: game.id, + name: game.name, + ruleset: game.ruleset ?? '', + description: Value(game.description), + color: Value(game.color?.toString()), + icon: Value(game.icon), + createdAt: game.createdAt, + ), + ) + .toList(), + mode: InsertMode.insertOrIgnore, + ), + ); + } // Add all groups of the matches in batch - // Using insertOrIgnore to avoid overwriting existing groups (which would - // trigger cascade deletes on player_group associations) 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, + (match) => GroupTableCompanion.insert( + id: match.group!.id, + name: match.group!.name, + description: Value(match.group!.description), + createdAt: match.group!.createdAt, ), ) .toList(), @@ -143,6 +159,27 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { ), ); + // Add all matches in batch + await db.batch( + (b) => b.insertAll( + matchTable, + matches + .where((match) => match.game != null) + .map( + (match) => MatchTableCompanion.insert( + id: match.id, + gameId: match.game!.id, + groupId: Value(match.group?.id), + name: Value(match.name), + notes: Value(match.notes), + createdAt: match.createdAt, + ), + ) + .toList(), + mode: InsertMode.insertOrReplace, + ), + ); + // Add all players of the matches in batch (unique) final uniquePlayers = {}; for (final match in matches) { @@ -160,8 +197,6 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { } if (uniquePlayers.isNotEmpty) { - // Using insertOrIgnore to avoid triggering cascade deletes on - // player_group/player_match associations when players already exist await db.batch( (b) => b.insertAll( db.playerTable, @@ -170,6 +205,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { (p) => PlayerTableCompanion.insert( id: p.id, name: p.name, + description: Value(p.description), createdAt: p.createdAt, ), ) @@ -183,12 +219,13 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { await db.batch((b) { for (final match in matches) { if (match.players != null) { - for (final p in match.players ?? []) { + for (final p in match.players!) { b.insert( db.playerMatchTable, PlayerMatchTableCompanion.insert( matchId: match.id, playerId: p.id, + score: 0, ), mode: InsertMode.insertOrIgnore, ); @@ -214,22 +251,6 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { } } }); - - // 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.insertOrIgnore, - ); - } - } - }); }); } @@ -266,52 +287,20 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { return rowsAffected > 0; } - /// Sets the winner of the match with the given [matchId] to the player with - /// the given [winnerId]. + /// Updates the notes of the match with the given [matchId]. /// Returns `true` if more than 0 rows were affected, otherwise `false`. - Future setWinner({ + Future updateMatchNotes({ required String matchId, - required String winnerId, + required String? notes, }) async { final query = update(matchTable)..where((g) => g.id.equals(matchId)); final rowsAffected = await query.write( - MatchTableCompanion(winnerId: Value(winnerId)), + MatchTableCompanion(notes: Value(notes)), ); 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 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 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 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]. + /// Changes the name of the match with the given [matchId] to [newName]. /// Returns `true` if more than 0 rows were affected, otherwise `false`. Future updateMatchName({ required String matchId, @@ -323,4 +312,31 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { ); return rowsAffected > 0; } + + /// Updates the game of the match with the given [matchId]. + /// Returns `true` if more than 0 rows were affected, otherwise `false`. + Future updateMatchGame({ + required String matchId, + required String gameId, + }) async { + final query = update(matchTable)..where((g) => g.id.equals(matchId)); + final rowsAffected = await query.write( + MatchTableCompanion(gameId: Value(gameId)), + ); + return rowsAffected > 0; + } + + /// Updates the group of the match with the given [matchId]. + /// Pass null to remove the group association. + /// Returns `true` if more than 0 rows were affected, otherwise `false`. + Future updateMatchGroup({ + required String matchId, + required String? groupId, + }) async { + final query = update(matchTable)..where((g) => g.id.equals(matchId)); + final rowsAffected = await query.write( + MatchTableCompanion(groupId: Value(groupId)), + ); + return rowsAffected > 0; + } } From 4b900c12bf1fe7a0b769cb67c18717a1037e70c3 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 12:22:23 +0100 Subject: [PATCH 23/87] add description to player --- lib/data/dao/player_dao.dart | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/data/dao/player_dao.dart b/lib/data/dao/player_dao.dart index c8db800..40c5c98 100644 --- a/lib/data/dao/player_dao.dart +++ b/lib/data/dao/player_dao.dart @@ -15,7 +15,12 @@ class PlayerDao extends DatabaseAccessor with _$PlayerDaoMixin { final result = await query.get(); return result .map( - (row) => Player(id: row.id, name: row.name, createdAt: row.createdAt), + (row) => Player( + id: row.id, + name: row.name, + description: row.description, + createdAt: row.createdAt, + ), ) .toList(); } @@ -27,6 +32,7 @@ class PlayerDao extends DatabaseAccessor with _$PlayerDaoMixin { return Player( id: result.id, name: result.name, + description: result.description, createdAt: result.createdAt, ); } @@ -40,6 +46,7 @@ class PlayerDao extends DatabaseAccessor with _$PlayerDaoMixin { PlayerTableCompanion.insert( id: player.id, name: player.name, + description: Value(player.description), createdAt: player.createdAt, ), mode: InsertMode.insertOrReplace, @@ -63,6 +70,7 @@ class PlayerDao extends DatabaseAccessor with _$PlayerDaoMixin { (player) => PlayerTableCompanion.insert( id: player.id, name: player.name, + description: Value(player.description), createdAt: player.createdAt, ), ) From 3857665444d297f21aac034f10596bebad8a80ab Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 12:23:24 +0100 Subject: [PATCH 24/87] update player_match_dao.dart --- lib/data/dao/player_match_dao.dart | 78 ++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/lib/data/dao/player_match_dao.dart b/lib/data/dao/player_match_dao.dart index 7ebaee6..a2185e6 100644 --- a/lib/data/dao/player_match_dao.dart +++ b/lib/data/dao/player_match_dao.dart @@ -1,23 +1,31 @@ import 'package:drift/drift.dart'; import 'package:game_tracker/data/db/database.dart'; import 'package:game_tracker/data/db/tables/player_match_table.dart'; +import 'package:game_tracker/data/db/tables/team_table.dart'; import 'package:game_tracker/data/dto/player.dart'; part 'player_match_dao.g.dart'; -@DriftAccessor(tables: [PlayerMatchTable]) +@DriftAccessor(tables: [PlayerMatchTable, TeamTable]) class PlayerMatchDao extends DatabaseAccessor with _$PlayerMatchDaoMixin { PlayerMatchDao(super.db); /// Associates a player with a match by inserting a record into the - /// [PlayerMatchTable]. + /// [PlayerMatchTable]. Optionally associates with a team and sets initial score. Future addPlayerToMatch({ required String matchId, required String playerId, + String? teamId, + int score = 0, }) async { await into(playerMatchTable).insert( - PlayerMatchTableCompanion.insert(playerId: playerId, matchId: matchId), + PlayerMatchTableCompanion.insert( + playerId: playerId, + matchId: matchId, + teamId: Value(teamId), + score: score, + ), mode: InsertMode.insertOrIgnore, ); } @@ -38,6 +46,50 @@ class PlayerMatchDao extends DatabaseAccessor return players; } + /// Retrieves a player's score for a specific match. + /// Returns null if the player is not in the match. + Future getPlayerScore({ + required String matchId, + required String playerId, + }) async { + final result = await (select(playerMatchTable) + ..where( + (p) => p.matchId.equals(matchId) & p.playerId.equals(playerId), + )) + .getSingleOrNull(); + return result?.score; + } + + /// Updates the score for a player in a match. + /// Returns `true` if the update was successful, otherwise `false`. + Future updatePlayerScore({ + required String matchId, + required String playerId, + required int newScore, + }) async { + final rowsAffected = await (update(playerMatchTable) + ..where( + (p) => p.matchId.equals(matchId) & p.playerId.equals(playerId), + )) + .write(PlayerMatchTableCompanion(score: Value(newScore))); + return rowsAffected > 0; + } + + /// Updates the team for a player in a match. + /// Returns `true` if the update was successful, otherwise `false`. + Future updatePlayerTeam({ + required String matchId, + required String playerId, + required String? teamId, + }) async { + final rowsAffected = await (update(playerMatchTable) + ..where( + (p) => p.matchId.equals(matchId) & p.playerId.equals(playerId), + )) + .write(PlayerMatchTableCompanion(teamId: Value(teamId))); + return rowsAffected > 0; + } + /// Checks if there are any players associated with the given [matchId]. /// Returns `true` if there are players, otherwise `false`. Future matchHasPlayers({required String matchId}) async { @@ -114,6 +166,7 @@ class PlayerMatchDao extends DatabaseAccessor (id) => PlayerMatchTableCompanion.insert( playerId: id, matchId: matchId, + score: 0, ), ) .toList(); @@ -127,4 +180,23 @@ class PlayerMatchDao extends DatabaseAccessor } }); } + + /// Retrieves all players in a specific team for a match. + Future> getPlayersInTeam({ + required String matchId, + required String teamId, + }) async { + final result = await (select(playerMatchTable) + ..where( + (p) => p.matchId.equals(matchId) & p.teamId.equals(teamId), + )) + .get(); + + if (result.isEmpty) return []; + + final futures = result.map( + (row) => db.playerDao.getPlayerById(playerId: row.playerId), + ); + return Future.wait(futures); + } } From b737cae356a7f5c43b89e41f34e12a12fde207dd Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 12:27:20 +0100 Subject: [PATCH 25/87] remove group_match_dao.dart --- lib/data/dao/group_match_dao.dart | 108 ------------------------------ 1 file changed, 108 deletions(-) delete mode 100644 lib/data/dao/group_match_dao.dart diff --git a/lib/data/dao/group_match_dao.dart b/lib/data/dao/group_match_dao.dart deleted file mode 100644 index 8f0700a..0000000 --- a/lib/data/dao/group_match_dao.dart +++ /dev/null @@ -1,108 +0,0 @@ -import 'package:drift/drift.dart'; -import 'package:game_tracker/data/db/database.dart'; -import 'package:game_tracker/data/db/tables/group_match_table.dart'; -import 'package:game_tracker/data/db/tables/group_table.dart'; -import 'package:game_tracker/data/dto/group.dart'; - -part 'group_match_dao.g.dart'; - -@DriftAccessor(tables: [GroupMatchTable, GroupTable]) -class GroupMatchDao extends DatabaseAccessor - with _$GroupMatchDaoMixin { - GroupMatchDao(super.db); - - /// Adds a group to a match by inserting a record into the [GroupMatchTable]. - Future addGroupToMatch({ - required String matchId, - required String groupId, - }) async { - await into(groupMatchTable).insert( - GroupMatchTableCompanion.insert( - matchId: matchId, - groupId: groupId, - ), - mode: InsertMode.insertOrIgnore, - ); - } - - /// Retrieves the [Group] associated with the given [matchId]. - /// Returns null if no group is found. - Future getGroupOfMatch({required String matchId}) async { - final query = select(groupMatchTable) - ..where((gm) => gm.matchId.equals(matchId)); - final result = await query.getSingleOrNull(); - - if (result == null) return null; - - return db.groupDao.getGroupById(groupId: result.groupId); - } - - /// Checks if a match has a group associated with it. - /// Returns `true` if the match has a group, otherwise `false`. - Future 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 isGroupInMatch({ - required String matchId, - required String groupId, - }) async { - final query = select(groupMatchTable) - ..where( - (gm) => gm.matchId.equals(matchId) & gm.groupId.equals(groupId), - ); - final result = await query.getSingleOrNull(); - return result != null; - } - - /// Removes the association of a group with a match by deleting the record - /// from the [GroupMatchTable]. - /// Returns `true` if more than 0 rows were affected, otherwise `false`. - Future removeGroupFromMatch({ - required String matchId, - required String groupId, - }) async { - final query = delete(groupMatchTable) - ..where((gm) => gm.matchId.equals(matchId) & gm.groupId.equals(groupId)); - final rowsAffected = await query.go(); - return rowsAffected > 0; - } - - /// Updates the group associated with a match. - /// Removes the existing group association and adds the new one. - Future updateGroupOfMatch({ - required String matchId, - required String newGroupId, - }) async { - await db.transaction(() async { - // Remove existing group association - await (delete(groupMatchTable) - ..where((gm) => gm.matchId.equals(matchId))) - .go(); - - // Add new group association - await into(groupMatchTable).insert( - GroupMatchTableCompanion.insert( - matchId: matchId, - groupId: newGroupId, - ), - ); - }); - } - - /// Retrieves all matches associated with a specific group. - Future> getMatchIdsForGroup({required String groupId}) async { - final query = select(groupMatchTable) - ..where((gm) => gm.groupId.equals(groupId)); - final result = await query.get(); - return result.map((row) => row.matchId).toList(); - } -} - From a13d9c55ea777096d896c091e4bc1552784ddec2 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 12:37:37 +0100 Subject: [PATCH 26/87] add score_dao.dart --- lib/data/dao/score_dao.dart | 191 ++++++++++++++++++++++++++++++++++++ 1 file changed, 191 insertions(+) create mode 100644 lib/data/dao/score_dao.dart diff --git a/lib/data/dao/score_dao.dart b/lib/data/dao/score_dao.dart new file mode 100644 index 0000000..5fa29da --- /dev/null +++ b/lib/data/dao/score_dao.dart @@ -0,0 +1,191 @@ +import 'package:drift/drift.dart'; +import 'package:game_tracker/data/db/database.dart'; +import 'package:game_tracker/data/db/tables/score_table.dart'; + +part 'score_dao.g.dart'; + +/// A data class representing a score entry. +class ScoreEntry { + final String playerId; + final String matchId; + final int roundNumber; + final int score; + final int change; + + ScoreEntry({ + required this.playerId, + required this.matchId, + required this.roundNumber, + required this.score, + required this.change, + }); +} + +@DriftAccessor(tables: [ScoreTable]) +class ScoreDao extends DatabaseAccessor with _$ScoreDaoMixin { + ScoreDao(super.db); + + /// Adds a score entry to the database. + Future addScore({ + required String playerId, + required String matchId, + required int roundNumber, + required int score, + required int change, + }) async { + await into(scoreTable).insert( + ScoreTableCompanion.insert( + playerId: playerId, + matchId: matchId, + roundNumber: roundNumber, + score: score, + change: change, + ), + mode: InsertMode.insertOrReplace, + ); + } + + /// Retrieves all scores for a specific match. + Future> getScoresForMatch({required String matchId}) async { + final query = select(scoreTable)..where((s) => s.matchId.equals(matchId)); + final result = await query.get(); + return result + .map( + (row) => ScoreEntry( + playerId: row.playerId, + matchId: row.matchId, + roundNumber: row.roundNumber, + score: row.score, + change: row.change, + ), + ) + .toList(); + } + + /// Retrieves all scores for a specific player in a match. + Future> getPlayerScoresInMatch({ + required String playerId, + required String matchId, + }) async { + final query = select(scoreTable) + ..where( + (s) => s.playerId.equals(playerId) & s.matchId.equals(matchId), + ) + ..orderBy([(s) => OrderingTerm.asc(s.roundNumber)]); + final result = await query.get(); + return result + .map( + (row) => ScoreEntry( + playerId: row.playerId, + matchId: row.matchId, + roundNumber: row.roundNumber, + score: row.score, + change: row.change, + ), + ) + .toList(); + } + + /// Retrieves the score for a specific round. + Future getScoreForRound({ + required String playerId, + required String matchId, + required int roundNumber, + }) async { + final query = select(scoreTable) + ..where( + (s) => + s.playerId.equals(playerId) & + s.matchId.equals(matchId) & + s.roundNumber.equals(roundNumber), + ); + final result = await query.getSingleOrNull(); + if (result == null) return null; + return ScoreEntry( + playerId: result.playerId, + matchId: result.matchId, + roundNumber: result.roundNumber, + score: result.score, + change: result.change, + ); + } + + /// Updates a score entry. + Future updateScore({ + required String playerId, + required String matchId, + required int roundNumber, + required int newScore, + required int newChange, + }) async { + final rowsAffected = await (update(scoreTable) + ..where( + (s) => + s.playerId.equals(playerId) & + s.matchId.equals(matchId) & + s.roundNumber.equals(roundNumber), + )) + .write( + ScoreTableCompanion( + score: Value(newScore), + change: Value(newChange), + ), + ); + return rowsAffected > 0; + } + + /// Deletes a score entry. + Future deleteScore({ + required String playerId, + required String matchId, + required int roundNumber, + }) async { + final query = delete(scoreTable) + ..where( + (s) => + s.playerId.equals(playerId) & + s.matchId.equals(matchId) & + s.roundNumber.equals(roundNumber), + ); + final rowsAffected = await query.go(); + return rowsAffected > 0; + } + + /// Deletes all scores for a specific match. + Future deleteScoresForMatch({required String matchId}) async { + final query = delete(scoreTable)..where((s) => s.matchId.equals(matchId)); + final rowsAffected = await query.go(); + return rowsAffected > 0; + } + + /// Deletes all scores for a specific player. + Future deleteScoresForPlayer({required String playerId}) async { + final query = delete(scoreTable)..where((s) => s.playerId.equals(playerId)); + final rowsAffected = await query.go(); + return rowsAffected > 0; + } + + /// Gets the latest round number for a match. + Future getLatestRoundNumber({required String matchId}) async { + final query = selectOnly(scoreTable) + ..where(scoreTable.matchId.equals(matchId)) + ..addColumns([scoreTable.roundNumber.max()]); + final result = await query.getSingle(); + return result.read(scoreTable.roundNumber.max()) ?? 0; + } + + /// Gets the total score for a player in a match (sum of all changes). + Future getTotalScoreForPlayer({ + required String playerId, + required String matchId, + }) async { + final scores = await getPlayerScoresInMatch( + playerId: playerId, + matchId: matchId, + ); + if (scores.isEmpty) return 0; + // Return the score from the latest round + return scores.last.score; + } +} + From c2a9bda8b1fdf98ff962a512f8e6dfd84da4a058 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 12:38:09 +0100 Subject: [PATCH 27/87] add team_dao.dart --- lib/data/dao/team_dao.dart | 145 +++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 lib/data/dao/team_dao.dart diff --git a/lib/data/dao/team_dao.dart b/lib/data/dao/team_dao.dart new file mode 100644 index 0000000..a382643 --- /dev/null +++ b/lib/data/dao/team_dao.dart @@ -0,0 +1,145 @@ +import 'package:drift/drift.dart'; +import 'package:game_tracker/data/db/database.dart'; +import 'package:game_tracker/data/db/tables/team_table.dart'; +import 'package:game_tracker/data/dto/player.dart'; +import 'package:game_tracker/data/dto/team.dart'; + +part 'team_dao.g.dart'; + +@DriftAccessor(tables: [TeamTable]) +class TeamDao extends DatabaseAccessor with _$TeamDaoMixin { + TeamDao(super.db); + + /// Retrieves all teams from the database. + /// Note: This returns teams without their members. Use getTeamById for full team data. + Future> getAllTeams() async { + final query = select(teamTable); + final result = await query.get(); + return Future.wait( + result.map((row) async { + final members = await _getTeamMembers(teamId: row.id); + return Team( + id: row.id, + createdAt: row.createdAt, + members: members, + ); + }), + ); + } + + /// Retrieves a [Team] by its [teamId], including its members. + Future getTeamById({required String teamId}) async { + final query = select(teamTable)..where((t) => t.id.equals(teamId)); + final result = await query.getSingle(); + final members = await _getTeamMembers(teamId: teamId); + return Team( + id: result.id, + createdAt: result.createdAt, + members: members, + ); + } + + /// Helper method to get team members from player_match_table. + /// This assumes team members are tracked via the player_match_table. + Future> _getTeamMembers({required String teamId}) async { + // Get all player_match entries with this teamId + final playerMatchQuery = select(db.playerMatchTable) + ..where((pm) => pm.teamId.equals(teamId)); + final playerMatches = await playerMatchQuery.get(); + + if (playerMatches.isEmpty) return []; + + // Get unique player IDs + final playerIds = playerMatches.map((pm) => pm.playerId).toSet(); + + // Fetch all players + final players = await Future.wait( + playerIds.map((id) => db.playerDao.getPlayerById(playerId: id)), + ); + return players; + } + + /// Adds a new [team] to the database. + /// Returns `true` if the team was added, `false` otherwise. + Future addTeam({required Team team}) async { + if (!await teamExists(teamId: team.id)) { + await into(teamTable).insert( + TeamTableCompanion.insert( + id: team.id, + name: '', // Team name from table (not in DTO currently) + createdAt: team.createdAt, + ), + mode: InsertMode.insertOrReplace, + ); + return true; + } + return false; + } + + /// Adds multiple [teams] to the database in a batch operation. + Future addTeamsAsList({required List teams}) async { + if (teams.isEmpty) return false; + + await db.batch( + (b) => b.insertAll( + teamTable, + teams + .map( + (team) => TeamTableCompanion.insert( + id: team.id, + name: '', + createdAt: team.createdAt, + ), + ) + .toList(), + mode: InsertMode.insertOrIgnore, + ), + ); + + return true; + } + + /// Deletes the team with the given [teamId] from the database. + /// Returns `true` if the team was deleted, `false` otherwise. + Future deleteTeam({required String teamId}) async { + final query = delete(teamTable)..where((t) => t.id.equals(teamId)); + final rowsAffected = await query.go(); + return rowsAffected > 0; + } + + /// Checks if a team with the given [teamId] exists in the database. + /// Returns `true` if the team exists, `false` otherwise. + Future teamExists({required String teamId}) async { + final query = select(teamTable)..where((t) => t.id.equals(teamId)); + final result = await query.getSingleOrNull(); + return result != null; + } + + /// Updates the name of the team with the given [teamId]. + Future updateTeamName({ + required String teamId, + required String newName, + }) async { + await (update(teamTable)..where((t) => t.id.equals(teamId))).write( + TeamTableCompanion(name: Value(newName)), + ); + } + + /// Retrieves the total count of teams in the database. + Future getTeamCount() async { + final count = + await (selectOnly(teamTable)..addColumns([teamTable.id.count()])) + .map((row) => row.read(teamTable.id.count())) + .getSingle(); + return count ?? 0; + } + + /// Deletes all teams from the database. + /// Returns `true` if more than 0 rows were affected, otherwise `false`. + Future deleteAllTeams() async { + final query = delete(teamTable); + final rowsAffected = await query.go(); + return rowsAffected > 0; + } +} + From 52c1605ce901dac73eb3184d212bbddb73813fd3 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 12:38:16 +0100 Subject: [PATCH 28/87] update database.dart --- lib/data/db/database.dart | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/lib/data/db/database.dart b/lib/data/db/database.dart index 632a4c6..628e013 100644 --- a/lib/data/db/database.dart +++ b/lib/data/db/database.dart @@ -1,15 +1,21 @@ import 'package:drift/drift.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/match_dao.dart'; import 'package:game_tracker/data/dao/player_dao.dart'; import 'package:game_tracker/data/dao/player_group_dao.dart'; import 'package:game_tracker/data/dao/player_match_dao.dart'; +import 'package:game_tracker/data/dao/score_dao.dart'; +import 'package:game_tracker/data/dao/team_dao.dart'; +import 'package:game_tracker/data/db/tables/game_table.dart'; import 'package:game_tracker/data/db/tables/group_table.dart'; import 'package:game_tracker/data/db/tables/match_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/score_table.dart'; +import 'package:game_tracker/data/db/tables/team_table.dart'; import 'package:path_provider/path_provider.dart'; part 'database.g.dart'; @@ -18,23 +24,29 @@ part 'database.g.dart'; tables: [ PlayerTable, GroupTable, + GameTable, + TeamTable, MatchTable, PlayerGroupTable, - PlayerMatchTable + PlayerMatchTable, + ScoreTable, ], daos: [ PlayerDao, GroupDao, + GameDao, + TeamDao, MatchDao, PlayerGroupDao, - PlayerMatchDao + PlayerMatchDao, + ScoreDao, ], ) class AppDatabase extends _$AppDatabase { AppDatabase([QueryExecutor? executor]) : super(executor ?? _openConnection()); @override - int get schemaVersion => 1; + int get schemaVersion => 2; @override MigrationStrategy get migration { From b9b6ff85ea524589263f18104055c94a4a0658c4 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 12:38:25 +0100 Subject: [PATCH 29/87] update g files --- lib/data/dao/game_dao.g.dart | 8 + lib/data/dao/match_dao.g.dart | 6 + lib/data/dao/player_match_dao.g.dart | 3 + lib/data/dao/score_dao.g.dart | 12 + lib/data/dao/team_dao.g.dart | 8 + lib/data/db/database.g.dart | 3814 +++++++++++++++++++++----- 6 files changed, 3117 insertions(+), 734 deletions(-) create mode 100644 lib/data/dao/game_dao.g.dart create mode 100644 lib/data/dao/score_dao.g.dart create mode 100644 lib/data/dao/team_dao.g.dart diff --git a/lib/data/dao/game_dao.g.dart b/lib/data/dao/game_dao.g.dart new file mode 100644 index 0000000..b5a29fe --- /dev/null +++ b/lib/data/dao/game_dao.g.dart @@ -0,0 +1,8 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'game_dao.dart'; + +// ignore_for_file: type=lint +mixin _$GameDaoMixin on DatabaseAccessor { + $GameTableTable get gameTable => attachedDatabase.gameTable; +} diff --git a/lib/data/dao/match_dao.g.dart b/lib/data/dao/match_dao.g.dart index a9f6f4c..fa75fee 100644 --- a/lib/data/dao/match_dao.g.dart +++ b/lib/data/dao/match_dao.g.dart @@ -4,5 +4,11 @@ part of 'match_dao.dart'; // ignore_for_file: type=lint mixin _$MatchDaoMixin on DatabaseAccessor { + $GameTableTable get gameTable => attachedDatabase.gameTable; + $GroupTableTable get groupTable => attachedDatabase.groupTable; $MatchTableTable get matchTable => attachedDatabase.matchTable; + $PlayerTableTable get playerTable => attachedDatabase.playerTable; + $TeamTableTable get teamTable => attachedDatabase.teamTable; + $PlayerMatchTableTable get playerMatchTable => + attachedDatabase.playerMatchTable; } diff --git a/lib/data/dao/player_match_dao.g.dart b/lib/data/dao/player_match_dao.g.dart index bcc8ef7..4c8bcbe 100644 --- a/lib/data/dao/player_match_dao.g.dart +++ b/lib/data/dao/player_match_dao.g.dart @@ -5,7 +5,10 @@ part of 'player_match_dao.dart'; // ignore_for_file: type=lint mixin _$PlayerMatchDaoMixin on DatabaseAccessor { $PlayerTableTable get playerTable => attachedDatabase.playerTable; + $GameTableTable get gameTable => attachedDatabase.gameTable; + $GroupTableTable get groupTable => attachedDatabase.groupTable; $MatchTableTable get matchTable => attachedDatabase.matchTable; + $TeamTableTable get teamTable => attachedDatabase.teamTable; $PlayerMatchTableTable get playerMatchTable => attachedDatabase.playerMatchTable; } diff --git a/lib/data/dao/score_dao.g.dart b/lib/data/dao/score_dao.g.dart new file mode 100644 index 0000000..1f4e367 --- /dev/null +++ b/lib/data/dao/score_dao.g.dart @@ -0,0 +1,12 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'score_dao.dart'; + +// ignore_for_file: type=lint +mixin _$ScoreDaoMixin on DatabaseAccessor { + $PlayerTableTable get playerTable => attachedDatabase.playerTable; + $GameTableTable get gameTable => attachedDatabase.gameTable; + $GroupTableTable get groupTable => attachedDatabase.groupTable; + $MatchTableTable get matchTable => attachedDatabase.matchTable; + $ScoreTableTable get scoreTable => attachedDatabase.scoreTable; +} diff --git a/lib/data/dao/team_dao.g.dart b/lib/data/dao/team_dao.g.dart new file mode 100644 index 0000000..1bf5b21 --- /dev/null +++ b/lib/data/dao/team_dao.g.dart @@ -0,0 +1,8 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'team_dao.dart'; + +// ignore_for_file: type=lint +mixin _$TeamDaoMixin on DatabaseAccessor { + $TeamTableTable get teamTable => attachedDatabase.teamTable; +} diff --git a/lib/data/db/database.g.dart b/lib/data/db/database.g.dart index 6bc493c..fbc76f0 100644 --- a/lib/data/db/database.g.dart +++ b/lib/data/db/database.g.dart @@ -27,6 +27,17 @@ class $PlayerTableTable extends PlayerTable type: DriftSqlType.string, requiredDuringInsert: true, ); + static const VerificationMeta _descriptionMeta = const VerificationMeta( + 'description', + ); + @override + late final GeneratedColumn description = GeneratedColumn( + 'description', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); static const VerificationMeta _createdAtMeta = const VerificationMeta( 'createdAt', ); @@ -39,7 +50,7 @@ class $PlayerTableTable extends PlayerTable requiredDuringInsert: true, ); @override - List get $columns => [id, name, createdAt]; + List get $columns => [id, name, description, createdAt]; @override String get aliasedName => _alias ?? actualTableName; @override @@ -65,6 +76,15 @@ class $PlayerTableTable extends PlayerTable } else if (isInserting) { context.missing(_nameMeta); } + if (data.containsKey('description')) { + context.handle( + _descriptionMeta, + description.isAcceptableOrUnknown( + data['description']!, + _descriptionMeta, + ), + ); + } if (data.containsKey('created_at')) { context.handle( _createdAtMeta, @@ -90,6 +110,10 @@ class $PlayerTableTable extends PlayerTable DriftSqlType.string, data['${effectivePrefix}name'], )!, + description: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}description'], + ), createdAt: attachedDatabase.typeMapping.read( DriftSqlType.dateTime, data['${effectivePrefix}created_at'], @@ -106,10 +130,12 @@ class $PlayerTableTable extends PlayerTable class PlayerTableData extends DataClass implements Insertable { final String id; final String name; + final String? description; final DateTime createdAt; const PlayerTableData({ required this.id, required this.name, + this.description, required this.createdAt, }); @override @@ -117,6 +143,9 @@ class PlayerTableData extends DataClass implements Insertable { final map = {}; map['id'] = Variable(id); map['name'] = Variable(name); + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } map['created_at'] = Variable(createdAt); return map; } @@ -125,6 +154,9 @@ class PlayerTableData extends DataClass implements Insertable { return PlayerTableCompanion( id: Value(id), name: Value(name), + description: description == null && nullToAbsent + ? const Value.absent() + : Value(description), createdAt: Value(createdAt), ); } @@ -137,6 +169,7 @@ class PlayerTableData extends DataClass implements Insertable { return PlayerTableData( id: serializer.fromJson(json['id']), name: serializer.fromJson(json['name']), + description: serializer.fromJson(json['description']), createdAt: serializer.fromJson(json['createdAt']), ); } @@ -146,20 +179,29 @@ class PlayerTableData extends DataClass implements Insertable { return { 'id': serializer.toJson(id), 'name': serializer.toJson(name), + 'description': serializer.toJson(description), 'createdAt': serializer.toJson(createdAt), }; } - PlayerTableData copyWith({String? id, String? name, DateTime? createdAt}) => - PlayerTableData( - id: id ?? this.id, - name: name ?? this.name, - createdAt: createdAt ?? this.createdAt, - ); + PlayerTableData copyWith({ + String? id, + String? name, + Value description = const Value.absent(), + DateTime? createdAt, + }) => PlayerTableData( + id: id ?? this.id, + name: name ?? this.name, + description: description.present ? description.value : this.description, + createdAt: createdAt ?? this.createdAt, + ); PlayerTableData copyWithCompanion(PlayerTableCompanion data) { return PlayerTableData( id: data.id.present ? data.id.value : this.id, name: data.name.present ? data.name.value : this.name, + description: data.description.present + ? data.description.value + : this.description, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, ); } @@ -169,36 +211,41 @@ class PlayerTableData extends DataClass implements Insertable { return (StringBuffer('PlayerTableData(') ..write('id: $id, ') ..write('name: $name, ') + ..write('description: $description, ') ..write('createdAt: $createdAt') ..write(')')) .toString(); } @override - int get hashCode => Object.hash(id, name, createdAt); + int get hashCode => Object.hash(id, name, description, createdAt); @override bool operator ==(Object other) => identical(this, other) || (other is PlayerTableData && other.id == this.id && other.name == this.name && + other.description == this.description && other.createdAt == this.createdAt); } class PlayerTableCompanion extends UpdateCompanion { final Value id; final Value name; + final Value description; final Value createdAt; final Value rowid; const PlayerTableCompanion({ this.id = const Value.absent(), this.name = const Value.absent(), + this.description = const Value.absent(), this.createdAt = const Value.absent(), this.rowid = const Value.absent(), }); PlayerTableCompanion.insert({ required String id, required String name, + this.description = const Value.absent(), required DateTime createdAt, this.rowid = const Value.absent(), }) : id = Value(id), @@ -207,12 +254,14 @@ class PlayerTableCompanion extends UpdateCompanion { static Insertable custom({ Expression? id, Expression? name, + Expression? description, Expression? createdAt, Expression? rowid, }) { return RawValuesInsertable({ if (id != null) 'id': id, if (name != null) 'name': name, + if (description != null) 'description': description, if (createdAt != null) 'created_at': createdAt, if (rowid != null) 'rowid': rowid, }); @@ -221,12 +270,14 @@ class PlayerTableCompanion extends UpdateCompanion { PlayerTableCompanion copyWith({ Value? id, Value? name, + Value? description, Value? createdAt, Value? rowid, }) { return PlayerTableCompanion( id: id ?? this.id, name: name ?? this.name, + description: description ?? this.description, createdAt: createdAt ?? this.createdAt, rowid: rowid ?? this.rowid, ); @@ -241,6 +292,9 @@ class PlayerTableCompanion extends UpdateCompanion { if (name.present) { map['name'] = Variable(name.value); } + if (description.present) { + map['description'] = Variable(description.value); + } if (createdAt.present) { map['created_at'] = Variable(createdAt.value); } @@ -255,6 +309,7 @@ class PlayerTableCompanion extends UpdateCompanion { return (StringBuffer('PlayerTableCompanion(') ..write('id: $id, ') ..write('name: $name, ') + ..write('description: $description, ') ..write('createdAt: $createdAt, ') ..write('rowid: $rowid') ..write(')')) @@ -286,6 +341,17 @@ class $GroupTableTable extends GroupTable type: DriftSqlType.string, requiredDuringInsert: true, ); + static const VerificationMeta _descriptionMeta = const VerificationMeta( + 'description', + ); + @override + late final GeneratedColumn description = GeneratedColumn( + 'description', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); static const VerificationMeta _createdAtMeta = const VerificationMeta( 'createdAt', ); @@ -298,7 +364,7 @@ class $GroupTableTable extends GroupTable requiredDuringInsert: true, ); @override - List get $columns => [id, name, createdAt]; + List get $columns => [id, name, description, createdAt]; @override String get aliasedName => _alias ?? actualTableName; @override @@ -324,6 +390,15 @@ class $GroupTableTable extends GroupTable } else if (isInserting) { context.missing(_nameMeta); } + if (data.containsKey('description')) { + context.handle( + _descriptionMeta, + description.isAcceptableOrUnknown( + data['description']!, + _descriptionMeta, + ), + ); + } if (data.containsKey('created_at')) { context.handle( _createdAtMeta, @@ -349,6 +424,10 @@ class $GroupTableTable extends GroupTable DriftSqlType.string, data['${effectivePrefix}name'], )!, + description: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}description'], + ), createdAt: attachedDatabase.typeMapping.read( DriftSqlType.dateTime, data['${effectivePrefix}created_at'], @@ -365,8 +444,755 @@ class $GroupTableTable extends GroupTable class GroupTableData extends DataClass implements Insertable { final String id; final String name; + final String? description; final DateTime createdAt; const GroupTableData({ + required this.id, + required this.name, + this.description, + required this.createdAt, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + map['created_at'] = Variable(createdAt); + return map; + } + + GroupTableCompanion toCompanion(bool nullToAbsent) { + return GroupTableCompanion( + id: Value(id), + name: Value(name), + description: description == null && nullToAbsent + ? const Value.absent() + : Value(description), + createdAt: Value(createdAt), + ); + } + + factory GroupTableData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return GroupTableData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + description: serializer.fromJson(json['description']), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'description': serializer.toJson(description), + 'createdAt': serializer.toJson(createdAt), + }; + } + + GroupTableData copyWith({ + String? id, + String? name, + Value description = const Value.absent(), + DateTime? createdAt, + }) => GroupTableData( + id: id ?? this.id, + name: name ?? this.name, + description: description.present ? description.value : this.description, + createdAt: createdAt ?? this.createdAt, + ); + GroupTableData copyWithCompanion(GroupTableCompanion data) { + return GroupTableData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + description: data.description.present + ? data.description.value + : this.description, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + ); + } + + @override + String toString() { + return (StringBuffer('GroupTableData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, name, description, createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is GroupTableData && + other.id == this.id && + other.name == this.name && + other.description == this.description && + other.createdAt == this.createdAt); +} + +class GroupTableCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value description; + final Value createdAt; + final Value rowid; + const GroupTableCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.description = const Value.absent(), + this.createdAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + GroupTableCompanion.insert({ + required String id, + required String name, + this.description = const Value.absent(), + required DateTime createdAt, + this.rowid = const Value.absent(), + }) : id = Value(id), + name = Value(name), + createdAt = Value(createdAt); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? description, + Expression? createdAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (description != null) 'description': description, + if (createdAt != null) 'created_at': createdAt, + if (rowid != null) 'rowid': rowid, + }); + } + + GroupTableCompanion copyWith({ + Value? id, + Value? name, + Value? description, + Value? createdAt, + Value? rowid, + }) { + return GroupTableCompanion( + id: id ?? this.id, + name: name ?? this.name, + description: description ?? this.description, + createdAt: createdAt ?? this.createdAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('GroupTableCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('description: $description, ') + ..write('createdAt: $createdAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class $GameTableTable extends GameTable + with TableInfo<$GameTableTable, GameTableData> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $GameTableTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + static const VerificationMeta _nameMeta = const VerificationMeta('name'); + @override + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + static const VerificationMeta _rulesetMeta = const VerificationMeta( + 'ruleset', + ); + @override + late final GeneratedColumn ruleset = GeneratedColumn( + 'ruleset', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + static const VerificationMeta _descriptionMeta = const VerificationMeta( + 'description', + ); + @override + late final GeneratedColumn description = GeneratedColumn( + 'description', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + static const VerificationMeta _colorMeta = const VerificationMeta('color'); + @override + late final GeneratedColumn color = GeneratedColumn( + 'color', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + static const VerificationMeta _iconMeta = const VerificationMeta('icon'); + @override + late final GeneratedColumn icon = GeneratedColumn( + 'icon', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + ); + static const VerificationMeta _createdAtMeta = const VerificationMeta( + 'createdAt', + ); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + id, + name, + ruleset, + description, + color, + icon, + createdAt, + ]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'game_table'; + @override + VerificationContext validateIntegrity( + Insertable instance, { + bool isInserting = false, + }) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('name')) { + context.handle( + _nameMeta, + name.isAcceptableOrUnknown(data['name']!, _nameMeta), + ); + } else if (isInserting) { + context.missing(_nameMeta); + } + if (data.containsKey('ruleset')) { + context.handle( + _rulesetMeta, + ruleset.isAcceptableOrUnknown(data['ruleset']!, _rulesetMeta), + ); + } else if (isInserting) { + context.missing(_rulesetMeta); + } + if (data.containsKey('description')) { + context.handle( + _descriptionMeta, + description.isAcceptableOrUnknown( + data['description']!, + _descriptionMeta, + ), + ); + } + if (data.containsKey('color')) { + context.handle( + _colorMeta, + color.isAcceptableOrUnknown(data['color']!, _colorMeta), + ); + } + if (data.containsKey('icon')) { + context.handle( + _iconMeta, + icon.isAcceptableOrUnknown(data['icon']!, _iconMeta), + ); + } + if (data.containsKey('created_at')) { + context.handle( + _createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta), + ); + } else if (isInserting) { + context.missing(_createdAtMeta); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + GameTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return GameTableData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + ruleset: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}ruleset'], + )!, + description: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}description'], + ), + color: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}color'], + ), + icon: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}icon'], + ), + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + ); + } + + @override + $GameTableTable createAlias(String alias) { + return $GameTableTable(attachedDatabase, alias); + } +} + +class GameTableData extends DataClass implements Insertable { + final String id; + final String name; + final String ruleset; + final String? description; + final String? color; + final String? icon; + final DateTime createdAt; + const GameTableData({ + required this.id, + required this.name, + required this.ruleset, + this.description, + this.color, + this.icon, + required this.createdAt, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['ruleset'] = Variable(ruleset); + if (!nullToAbsent || description != null) { + map['description'] = Variable(description); + } + if (!nullToAbsent || color != null) { + map['color'] = Variable(color); + } + if (!nullToAbsent || icon != null) { + map['icon'] = Variable(icon); + } + map['created_at'] = Variable(createdAt); + return map; + } + + GameTableCompanion toCompanion(bool nullToAbsent) { + return GameTableCompanion( + id: Value(id), + name: Value(name), + ruleset: Value(ruleset), + description: description == null && nullToAbsent + ? const Value.absent() + : Value(description), + color: color == null && nullToAbsent + ? const Value.absent() + : Value(color), + icon: icon == null && nullToAbsent ? const Value.absent() : Value(icon), + createdAt: Value(createdAt), + ); + } + + factory GameTableData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return GameTableData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + ruleset: serializer.fromJson(json['ruleset']), + description: serializer.fromJson(json['description']), + color: serializer.fromJson(json['color']), + icon: serializer.fromJson(json['icon']), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'ruleset': serializer.toJson(ruleset), + 'description': serializer.toJson(description), + 'color': serializer.toJson(color), + 'icon': serializer.toJson(icon), + 'createdAt': serializer.toJson(createdAt), + }; + } + + GameTableData copyWith({ + String? id, + String? name, + String? ruleset, + Value description = const Value.absent(), + Value color = const Value.absent(), + Value icon = const Value.absent(), + DateTime? createdAt, + }) => GameTableData( + id: id ?? this.id, + name: name ?? this.name, + ruleset: ruleset ?? this.ruleset, + description: description.present ? description.value : this.description, + color: color.present ? color.value : this.color, + icon: icon.present ? icon.value : this.icon, + createdAt: createdAt ?? this.createdAt, + ); + GameTableData copyWithCompanion(GameTableCompanion data) { + return GameTableData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + ruleset: data.ruleset.present ? data.ruleset.value : this.ruleset, + description: data.description.present + ? data.description.value + : this.description, + color: data.color.present ? data.color.value : this.color, + icon: data.icon.present ? data.icon.value : this.icon, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + ); + } + + @override + String toString() { + return (StringBuffer('GameTableData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('ruleset: $ruleset, ') + ..write('description: $description, ') + ..write('color: $color, ') + ..write('icon: $icon, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => + Object.hash(id, name, ruleset, description, color, icon, createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is GameTableData && + other.id == this.id && + other.name == this.name && + other.ruleset == this.ruleset && + other.description == this.description && + other.color == this.color && + other.icon == this.icon && + other.createdAt == this.createdAt); +} + +class GameTableCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value ruleset; + final Value description; + final Value color; + final Value icon; + final Value createdAt; + final Value rowid; + const GameTableCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.ruleset = const Value.absent(), + this.description = const Value.absent(), + this.color = const Value.absent(), + this.icon = const Value.absent(), + this.createdAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + GameTableCompanion.insert({ + required String id, + required String name, + required String ruleset, + this.description = const Value.absent(), + this.color = const Value.absent(), + this.icon = const Value.absent(), + required DateTime createdAt, + this.rowid = const Value.absent(), + }) : id = Value(id), + name = Value(name), + ruleset = Value(ruleset), + createdAt = Value(createdAt); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? ruleset, + Expression? description, + Expression? color, + Expression? icon, + Expression? createdAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (ruleset != null) 'ruleset': ruleset, + if (description != null) 'description': description, + if (color != null) 'color': color, + if (icon != null) 'icon': icon, + if (createdAt != null) 'created_at': createdAt, + if (rowid != null) 'rowid': rowid, + }); + } + + GameTableCompanion copyWith({ + Value? id, + Value? name, + Value? ruleset, + Value? description, + Value? color, + Value? icon, + Value? createdAt, + Value? rowid, + }) { + return GameTableCompanion( + id: id ?? this.id, + name: name ?? this.name, + ruleset: ruleset ?? this.ruleset, + description: description ?? this.description, + color: color ?? this.color, + icon: icon ?? this.icon, + createdAt: createdAt ?? this.createdAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (ruleset.present) { + map['ruleset'] = Variable(ruleset.value); + } + if (description.present) { + map['description'] = Variable(description.value); + } + if (color.present) { + map['color'] = Variable(color.value); + } + if (icon.present) { + map['icon'] = Variable(icon.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('GameTableCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('ruleset: $ruleset, ') + ..write('description: $description, ') + ..write('color: $color, ') + ..write('icon: $icon, ') + ..write('createdAt: $createdAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + +class $TeamTableTable extends TeamTable + with TableInfo<$TeamTableTable, TeamTableData> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $TeamTableTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + static const VerificationMeta _nameMeta = const VerificationMeta('name'); + @override + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + static const VerificationMeta _createdAtMeta = const VerificationMeta( + 'createdAt', + ); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: true, + ); + @override + List get $columns => [id, name, createdAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'team_table'; + @override + VerificationContext validateIntegrity( + Insertable instance, { + bool isInserting = false, + }) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('name')) { + context.handle( + _nameMeta, + name.isAcceptableOrUnknown(data['name']!, _nameMeta), + ); + } else if (isInserting) { + context.missing(_nameMeta); + } + if (data.containsKey('created_at')) { + context.handle( + _createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta), + ); + } else if (isInserting) { + context.missing(_createdAtMeta); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + TeamTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return TeamTableData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + ); + } + + @override + $TeamTableTable createAlias(String alias) { + return $TeamTableTable(attachedDatabase, alias); + } +} + +class TeamTableData extends DataClass implements Insertable { + final String id; + final String name; + final DateTime createdAt; + const TeamTableData({ required this.id, required this.name, required this.createdAt, @@ -380,20 +1206,20 @@ class GroupTableData extends DataClass implements Insertable { return map; } - GroupTableCompanion toCompanion(bool nullToAbsent) { - return GroupTableCompanion( + TeamTableCompanion toCompanion(bool nullToAbsent) { + return TeamTableCompanion( id: Value(id), name: Value(name), createdAt: Value(createdAt), ); } - factory GroupTableData.fromJson( + factory TeamTableData.fromJson( Map json, { ValueSerializer? serializer, }) { serializer ??= driftRuntimeOptions.defaultSerializer; - return GroupTableData( + return TeamTableData( id: serializer.fromJson(json['id']), name: serializer.fromJson(json['name']), createdAt: serializer.fromJson(json['createdAt']), @@ -409,14 +1235,14 @@ class GroupTableData extends DataClass implements Insertable { }; } - GroupTableData copyWith({String? id, String? name, DateTime? createdAt}) => - GroupTableData( + TeamTableData copyWith({String? id, String? name, DateTime? createdAt}) => + TeamTableData( id: id ?? this.id, name: name ?? this.name, createdAt: createdAt ?? this.createdAt, ); - GroupTableData copyWithCompanion(GroupTableCompanion data) { - return GroupTableData( + TeamTableData copyWithCompanion(TeamTableCompanion data) { + return TeamTableData( id: data.id.present ? data.id.value : this.id, name: data.name.present ? data.name.value : this.name, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, @@ -425,7 +1251,7 @@ class GroupTableData extends DataClass implements Insertable { @override String toString() { - return (StringBuffer('GroupTableData(') + return (StringBuffer('TeamTableData(') ..write('id: $id, ') ..write('name: $name, ') ..write('createdAt: $createdAt') @@ -438,24 +1264,24 @@ class GroupTableData extends DataClass implements Insertable { @override bool operator ==(Object other) => identical(this, other) || - (other is GroupTableData && + (other is TeamTableData && other.id == this.id && other.name == this.name && other.createdAt == this.createdAt); } -class GroupTableCompanion extends UpdateCompanion { +class TeamTableCompanion extends UpdateCompanion { final Value id; final Value name; final Value createdAt; final Value rowid; - const GroupTableCompanion({ + const TeamTableCompanion({ this.id = const Value.absent(), this.name = const Value.absent(), this.createdAt = const Value.absent(), this.rowid = const Value.absent(), }); - GroupTableCompanion.insert({ + TeamTableCompanion.insert({ required String id, required String name, required DateTime createdAt, @@ -463,7 +1289,7 @@ class GroupTableCompanion extends UpdateCompanion { }) : id = Value(id), name = Value(name), createdAt = Value(createdAt); - static Insertable custom({ + static Insertable custom({ Expression? id, Expression? name, Expression? createdAt, @@ -477,13 +1303,13 @@ class GroupTableCompanion extends UpdateCompanion { }); } - GroupTableCompanion copyWith({ + TeamTableCompanion copyWith({ Value? id, Value? name, Value? createdAt, Value? rowid, }) { - return GroupTableCompanion( + return TeamTableCompanion( id: id ?? this.id, name: name ?? this.name, createdAt: createdAt ?? this.createdAt, @@ -511,7 +1337,7 @@ class GroupTableCompanion extends UpdateCompanion { @override String toString() { - return (StringBuffer('GroupTableCompanion(') + return (StringBuffer('TeamTableCompanion(') ..write('id: $id, ') ..write('name: $name, ') ..write('createdAt: $createdAt, ') @@ -536,21 +1362,45 @@ class $MatchTableTable extends MatchTable type: DriftSqlType.string, requiredDuringInsert: true, ); + static const VerificationMeta _gameIdMeta = const VerificationMeta('gameId'); + @override + late final GeneratedColumn gameId = GeneratedColumn( + 'game_id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES game_table (id) ON DELETE CASCADE', + ), + ); + static const VerificationMeta _groupIdMeta = const VerificationMeta( + 'groupId', + ); + @override + late final GeneratedColumn groupId = GeneratedColumn( + 'group_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES group_table (id) ON DELETE CASCADE', + ), + ); static const VerificationMeta _nameMeta = const VerificationMeta('name'); @override late final GeneratedColumn name = GeneratedColumn( 'name', aliasedName, - false, + true, type: DriftSqlType.string, - requiredDuringInsert: true, - ); - static const VerificationMeta _winnerIdMeta = const VerificationMeta( - 'winnerId', + requiredDuringInsert: false, ); + static const VerificationMeta _notesMeta = const VerificationMeta('notes'); @override - late final GeneratedColumn winnerId = GeneratedColumn( - 'winner_id', + late final GeneratedColumn notes = GeneratedColumn( + 'notes', aliasedName, true, type: DriftSqlType.string, @@ -568,7 +1418,14 @@ class $MatchTableTable extends MatchTable requiredDuringInsert: true, ); @override - List get $columns => [id, name, winnerId, createdAt]; + List get $columns => [ + id, + gameId, + groupId, + name, + notes, + createdAt, + ]; @override String get aliasedName => _alias ?? actualTableName; @override @@ -586,18 +1443,30 @@ class $MatchTableTable extends MatchTable } else if (isInserting) { context.missing(_idMeta); } + if (data.containsKey('game_id')) { + context.handle( + _gameIdMeta, + gameId.isAcceptableOrUnknown(data['game_id']!, _gameIdMeta), + ); + } else if (isInserting) { + context.missing(_gameIdMeta); + } + if (data.containsKey('group_id')) { + context.handle( + _groupIdMeta, + groupId.isAcceptableOrUnknown(data['group_id']!, _groupIdMeta), + ); + } if (data.containsKey('name')) { context.handle( _nameMeta, name.isAcceptableOrUnknown(data['name']!, _nameMeta), ); - } else if (isInserting) { - context.missing(_nameMeta); } - if (data.containsKey('winner_id')) { + if (data.containsKey('notes')) { context.handle( - _winnerIdMeta, - winnerId.isAcceptableOrUnknown(data['winner_id']!, _winnerIdMeta), + _notesMeta, + notes.isAcceptableOrUnknown(data['notes']!, _notesMeta), ); } if (data.containsKey('created_at')) { @@ -621,13 +1490,21 @@ class $MatchTableTable extends MatchTable DriftSqlType.string, data['${effectivePrefix}id'], )!, + gameId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}game_id'], + )!, + groupId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}group_id'], + ), name: attachedDatabase.typeMapping.read( DriftSqlType.string, data['${effectivePrefix}name'], - )!, - winnerId: attachedDatabase.typeMapping.read( + ), + notes: attachedDatabase.typeMapping.read( DriftSqlType.string, - data['${effectivePrefix}winner_id'], + data['${effectivePrefix}notes'], ), createdAt: attachedDatabase.typeMapping.read( DriftSqlType.dateTime, @@ -644,22 +1521,32 @@ class $MatchTableTable extends MatchTable class MatchTableData extends DataClass implements Insertable { final String id; - final String name; - final String? winnerId; + final String gameId; + final String? groupId; + final String? name; + final String? notes; final DateTime createdAt; const MatchTableData({ required this.id, - required this.name, - this.winnerId, + required this.gameId, + this.groupId, + this.name, + this.notes, required this.createdAt, }); @override Map toColumns(bool nullToAbsent) { final map = {}; map['id'] = Variable(id); - map['name'] = Variable(name); - if (!nullToAbsent || winnerId != null) { - map['winner_id'] = Variable(winnerId); + map['game_id'] = Variable(gameId); + if (!nullToAbsent || groupId != null) { + map['group_id'] = Variable(groupId); + } + if (!nullToAbsent || name != null) { + map['name'] = Variable(name); + } + if (!nullToAbsent || notes != null) { + map['notes'] = Variable(notes); } map['created_at'] = Variable(createdAt); return map; @@ -668,10 +1555,14 @@ class MatchTableData extends DataClass implements Insertable { MatchTableCompanion toCompanion(bool nullToAbsent) { return MatchTableCompanion( id: Value(id), - name: Value(name), - winnerId: winnerId == null && nullToAbsent + gameId: Value(gameId), + groupId: groupId == null && nullToAbsent ? const Value.absent() - : Value(winnerId), + : Value(groupId), + name: name == null && nullToAbsent ? const Value.absent() : Value(name), + notes: notes == null && nullToAbsent + ? const Value.absent() + : Value(notes), createdAt: Value(createdAt), ); } @@ -683,8 +1574,10 @@ class MatchTableData extends DataClass implements Insertable { serializer ??= driftRuntimeOptions.defaultSerializer; return MatchTableData( id: serializer.fromJson(json['id']), - name: serializer.fromJson(json['name']), - winnerId: serializer.fromJson(json['winnerId']), + gameId: serializer.fromJson(json['gameId']), + groupId: serializer.fromJson(json['groupId']), + name: serializer.fromJson(json['name']), + notes: serializer.fromJson(json['notes']), createdAt: serializer.fromJson(json['createdAt']), ); } @@ -693,28 +1586,36 @@ class MatchTableData extends DataClass implements Insertable { serializer ??= driftRuntimeOptions.defaultSerializer; return { 'id': serializer.toJson(id), - 'name': serializer.toJson(name), - 'winnerId': serializer.toJson(winnerId), + 'gameId': serializer.toJson(gameId), + 'groupId': serializer.toJson(groupId), + 'name': serializer.toJson(name), + 'notes': serializer.toJson(notes), 'createdAt': serializer.toJson(createdAt), }; } MatchTableData copyWith({ String? id, - String? name, - Value winnerId = const Value.absent(), + String? gameId, + Value groupId = const Value.absent(), + Value name = const Value.absent(), + Value notes = const Value.absent(), DateTime? createdAt, }) => MatchTableData( id: id ?? this.id, - name: name ?? this.name, - winnerId: winnerId.present ? winnerId.value : this.winnerId, + gameId: gameId ?? this.gameId, + groupId: groupId.present ? groupId.value : this.groupId, + name: name.present ? name.value : this.name, + notes: notes.present ? notes.value : this.notes, createdAt: createdAt ?? this.createdAt, ); MatchTableData copyWithCompanion(MatchTableCompanion data) { return MatchTableData( id: data.id.present ? data.id.value : this.id, + gameId: data.gameId.present ? data.gameId.value : this.gameId, + groupId: data.groupId.present ? data.groupId.value : this.groupId, name: data.name.present ? data.name.value : this.name, - winnerId: data.winnerId.present ? data.winnerId.value : this.winnerId, + notes: data.notes.present ? data.notes.value : this.notes, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, ); } @@ -723,58 +1624,72 @@ class MatchTableData extends DataClass implements Insertable { String toString() { return (StringBuffer('MatchTableData(') ..write('id: $id, ') + ..write('gameId: $gameId, ') + ..write('groupId: $groupId, ') ..write('name: $name, ') - ..write('winnerId: $winnerId, ') + ..write('notes: $notes, ') ..write('createdAt: $createdAt') ..write(')')) .toString(); } @override - int get hashCode => Object.hash(id, name, winnerId, createdAt); + int get hashCode => Object.hash(id, gameId, groupId, name, notes, createdAt); @override bool operator ==(Object other) => identical(this, other) || (other is MatchTableData && other.id == this.id && + other.gameId == this.gameId && + other.groupId == this.groupId && other.name == this.name && - other.winnerId == this.winnerId && + other.notes == this.notes && other.createdAt == this.createdAt); } class MatchTableCompanion extends UpdateCompanion { final Value id; - final Value name; - final Value winnerId; + final Value gameId; + final Value groupId; + final Value name; + final Value notes; final Value createdAt; final Value rowid; const MatchTableCompanion({ this.id = const Value.absent(), + this.gameId = const Value.absent(), + this.groupId = const Value.absent(), this.name = const Value.absent(), - this.winnerId = const Value.absent(), + this.notes = const Value.absent(), this.createdAt = const Value.absent(), this.rowid = const Value.absent(), }); MatchTableCompanion.insert({ required String id, - required String name, - this.winnerId = const Value.absent(), + required String gameId, + this.groupId = const Value.absent(), + this.name = const Value.absent(), + this.notes = const Value.absent(), required DateTime createdAt, this.rowid = const Value.absent(), }) : id = Value(id), - name = Value(name), + gameId = Value(gameId), createdAt = Value(createdAt); static Insertable custom({ Expression? id, + Expression? gameId, + Expression? groupId, Expression? name, - Expression? winnerId, + Expression? notes, Expression? createdAt, Expression? rowid, }) { return RawValuesInsertable({ if (id != null) 'id': id, + if (gameId != null) 'game_id': gameId, + if (groupId != null) 'group_id': groupId, if (name != null) 'name': name, - if (winnerId != null) 'winner_id': winnerId, + if (notes != null) 'notes': notes, if (createdAt != null) 'created_at': createdAt, if (rowid != null) 'rowid': rowid, }); @@ -782,15 +1697,19 @@ class MatchTableCompanion extends UpdateCompanion { MatchTableCompanion copyWith({ Value? id, - Value? name, - Value? winnerId, + Value? gameId, + Value? groupId, + Value? name, + Value? notes, Value? createdAt, Value? rowid, }) { return MatchTableCompanion( id: id ?? this.id, + gameId: gameId ?? this.gameId, + groupId: groupId ?? this.groupId, name: name ?? this.name, - winnerId: winnerId ?? this.winnerId, + notes: notes ?? this.notes, createdAt: createdAt ?? this.createdAt, rowid: rowid ?? this.rowid, ); @@ -802,11 +1721,17 @@ class MatchTableCompanion extends UpdateCompanion { if (id.present) { map['id'] = Variable(id.value); } + if (gameId.present) { + map['game_id'] = Variable(gameId.value); + } + if (groupId.present) { + map['group_id'] = Variable(groupId.value); + } if (name.present) { map['name'] = Variable(name.value); } - if (winnerId.present) { - map['winner_id'] = Variable(winnerId.value); + if (notes.present) { + map['notes'] = Variable(notes.value); } if (createdAt.present) { map['created_at'] = Variable(createdAt.value); @@ -821,8 +1746,10 @@ class MatchTableCompanion extends UpdateCompanion { String toString() { return (StringBuffer('MatchTableCompanion(') ..write('id: $id, ') + ..write('gameId: $gameId, ') + ..write('groupId: $groupId, ') ..write('name: $name, ') - ..write('winnerId: $winnerId, ') + ..write('notes: $notes, ') ..write('createdAt: $createdAt, ') ..write('rowid: $rowid') ..write(')')) @@ -1089,8 +2016,29 @@ class $PlayerMatchTableTable extends PlayerMatchTable 'REFERENCES match_table (id) ON DELETE CASCADE', ), ); + static const VerificationMeta _teamIdMeta = const VerificationMeta('teamId'); @override - List get $columns => [playerId, matchId]; + late final GeneratedColumn teamId = GeneratedColumn( + 'team_id', + aliasedName, + true, + type: DriftSqlType.string, + requiredDuringInsert: false, + defaultConstraints: GeneratedColumn.constraintIsAlways( + 'REFERENCES team_table (id)', + ), + ); + static const VerificationMeta _scoreMeta = const VerificationMeta('score'); + @override + late final GeneratedColumn score = GeneratedColumn( + 'score', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + @override + List get $columns => [playerId, matchId, teamId, score]; @override String get aliasedName => _alias ?? actualTableName; @override @@ -1119,6 +2067,20 @@ class $PlayerMatchTableTable extends PlayerMatchTable } else if (isInserting) { context.missing(_matchIdMeta); } + if (data.containsKey('team_id')) { + context.handle( + _teamIdMeta, + teamId.isAcceptableOrUnknown(data['team_id']!, _teamIdMeta), + ); + } + if (data.containsKey('score')) { + context.handle( + _scoreMeta, + score.isAcceptableOrUnknown(data['score']!, _scoreMeta), + ); + } else if (isInserting) { + context.missing(_scoreMeta); + } return context; } @@ -1136,6 +2098,14 @@ class $PlayerMatchTableTable extends PlayerMatchTable DriftSqlType.string, data['${effectivePrefix}match_id'], )!, + teamId: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}team_id'], + ), + score: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}score'], + )!, ); } @@ -1149,12 +2119,23 @@ class PlayerMatchTableData extends DataClass implements Insertable { final String playerId; final String matchId; - const PlayerMatchTableData({required this.playerId, required this.matchId}); + final String? teamId; + final int score; + const PlayerMatchTableData({ + required this.playerId, + required this.matchId, + this.teamId, + required this.score, + }); @override Map toColumns(bool nullToAbsent) { final map = {}; map['player_id'] = Variable(playerId); map['match_id'] = Variable(matchId); + if (!nullToAbsent || teamId != null) { + map['team_id'] = Variable(teamId); + } + map['score'] = Variable(score); return map; } @@ -1162,6 +2143,10 @@ class PlayerMatchTableData extends DataClass return PlayerMatchTableCompanion( playerId: Value(playerId), matchId: Value(matchId), + teamId: teamId == null && nullToAbsent + ? const Value.absent() + : Value(teamId), + score: Value(score), ); } @@ -1173,6 +2158,8 @@ class PlayerMatchTableData extends DataClass return PlayerMatchTableData( playerId: serializer.fromJson(json['playerId']), matchId: serializer.fromJson(json['matchId']), + teamId: serializer.fromJson(json['teamId']), + score: serializer.fromJson(json['score']), ); } @override @@ -1181,18 +2168,28 @@ class PlayerMatchTableData extends DataClass return { 'playerId': serializer.toJson(playerId), 'matchId': serializer.toJson(matchId), + 'teamId': serializer.toJson(teamId), + 'score': serializer.toJson(score), }; } - PlayerMatchTableData copyWith({String? playerId, String? matchId}) => - PlayerMatchTableData( - playerId: playerId ?? this.playerId, - matchId: matchId ?? this.matchId, - ); + PlayerMatchTableData copyWith({ + String? playerId, + String? matchId, + Value teamId = const Value.absent(), + int? score, + }) => PlayerMatchTableData( + playerId: playerId ?? this.playerId, + matchId: matchId ?? this.matchId, + teamId: teamId.present ? teamId.value : this.teamId, + score: score ?? this.score, + ); PlayerMatchTableData copyWithCompanion(PlayerMatchTableCompanion data) { return PlayerMatchTableData( playerId: data.playerId.present ? data.playerId.value : this.playerId, matchId: data.matchId.present ? data.matchId.value : this.matchId, + teamId: data.teamId.present ? data.teamId.value : this.teamId, + score: data.score.present ? data.score.value : this.score, ); } @@ -1200,44 +2197,59 @@ class PlayerMatchTableData extends DataClass String toString() { return (StringBuffer('PlayerMatchTableData(') ..write('playerId: $playerId, ') - ..write('matchId: $matchId') + ..write('matchId: $matchId, ') + ..write('teamId: $teamId, ') + ..write('score: $score') ..write(')')) .toString(); } @override - int get hashCode => Object.hash(playerId, matchId); + int get hashCode => Object.hash(playerId, matchId, teamId, score); @override bool operator ==(Object other) => identical(this, other) || (other is PlayerMatchTableData && other.playerId == this.playerId && - other.matchId == this.matchId); + other.matchId == this.matchId && + other.teamId == this.teamId && + other.score == this.score); } class PlayerMatchTableCompanion extends UpdateCompanion { final Value playerId; final Value matchId; + final Value teamId; + final Value score; final Value rowid; const PlayerMatchTableCompanion({ this.playerId = const Value.absent(), this.matchId = const Value.absent(), + this.teamId = const Value.absent(), + this.score = const Value.absent(), this.rowid = const Value.absent(), }); PlayerMatchTableCompanion.insert({ required String playerId, required String matchId, + this.teamId = const Value.absent(), + required int score, this.rowid = const Value.absent(), }) : playerId = Value(playerId), - matchId = Value(matchId); + matchId = Value(matchId), + score = Value(score); static Insertable custom({ Expression? playerId, Expression? matchId, + Expression? teamId, + Expression? score, Expression? rowid, }) { return RawValuesInsertable({ if (playerId != null) 'player_id': playerId, if (matchId != null) 'match_id': matchId, + if (teamId != null) 'team_id': teamId, + if (score != null) 'score': score, if (rowid != null) 'rowid': rowid, }); } @@ -1245,11 +2257,15 @@ class PlayerMatchTableCompanion extends UpdateCompanion { PlayerMatchTableCompanion copyWith({ Value? playerId, Value? matchId, + Value? teamId, + Value? score, Value? rowid, }) { return PlayerMatchTableCompanion( playerId: playerId ?? this.playerId, matchId: matchId ?? this.matchId, + teamId: teamId ?? this.teamId, + score: score ?? this.score, rowid: rowid ?? this.rowid, ); } @@ -1263,6 +2279,12 @@ class PlayerMatchTableCompanion extends UpdateCompanion { if (matchId.present) { map['match_id'] = Variable(matchId.value); } + if (teamId.present) { + map['team_id'] = Variable(teamId.value); + } + if (score.present) { + map['score'] = Variable(score.value); + } if (rowid.present) { map['rowid'] = Variable(rowid.value); } @@ -1274,30 +2296,32 @@ class PlayerMatchTableCompanion extends UpdateCompanion { return (StringBuffer('PlayerMatchTableCompanion(') ..write('playerId: $playerId, ') ..write('matchId: $matchId, ') + ..write('teamId: $teamId, ') + ..write('score: $score, ') ..write('rowid: $rowid') ..write(')')) .toString(); } } -class $GroupMatchTableTable extends GroupMatchTable - with TableInfo<$GroupMatchTableTable, GroupMatchTableData> { +class $ScoreTableTable extends ScoreTable + with TableInfo<$ScoreTableTable, ScoreTableData> { @override final GeneratedDatabase attachedDatabase; final String? _alias; - $GroupMatchTableTable(this.attachedDatabase, [this._alias]); - static const VerificationMeta _groupIdMeta = const VerificationMeta( - 'groupId', + $ScoreTableTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _playerIdMeta = const VerificationMeta( + 'playerId', ); @override - late final GeneratedColumn groupId = GeneratedColumn( - 'group_id', + late final GeneratedColumn playerId = GeneratedColumn( + 'player_id', aliasedName, false, type: DriftSqlType.string, requiredDuringInsert: true, defaultConstraints: GeneratedColumn.constraintIsAlways( - 'REFERENCES group_table (id) ON DELETE CASCADE', + 'REFERENCES player_table (id) ON DELETE CASCADE', ), ); static const VerificationMeta _matchIdMeta = const VerificationMeta( @@ -1314,27 +2338,62 @@ class $GroupMatchTableTable extends GroupMatchTable 'REFERENCES match_table (id) ON DELETE CASCADE', ), ); + static const VerificationMeta _roundNumberMeta = const VerificationMeta( + 'roundNumber', + ); @override - List get $columns => [groupId, matchId]; + late final GeneratedColumn roundNumber = GeneratedColumn( + 'round_number', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + static const VerificationMeta _scoreMeta = const VerificationMeta('score'); + @override + late final GeneratedColumn score = GeneratedColumn( + 'score', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + static const VerificationMeta _changeMeta = const VerificationMeta('change'); + @override + late final GeneratedColumn change = GeneratedColumn( + 'change', + aliasedName, + false, + type: DriftSqlType.int, + requiredDuringInsert: true, + ); + @override + List get $columns => [ + playerId, + matchId, + roundNumber, + score, + change, + ]; @override String get aliasedName => _alias ?? actualTableName; @override String get actualTableName => $name; - static const String $name = 'group_match_table'; + static const String $name = 'score_table'; @override VerificationContext validateIntegrity( - Insertable instance, { + Insertable instance, { bool isInserting = false, }) { final context = VerificationContext(); final data = instance.toColumns(true); - if (data.containsKey('group_id')) { + if (data.containsKey('player_id')) { context.handle( - _groupIdMeta, - groupId.isAcceptableOrUnknown(data['group_id']!, _groupIdMeta), + _playerIdMeta, + playerId.isAcceptableOrUnknown(data['player_id']!, _playerIdMeta), ); } else if (isInserting) { - context.missing(_groupIdMeta); + context.missing(_playerIdMeta); } if (data.containsKey('match_id')) { context.handle( @@ -1344,137 +2403,240 @@ class $GroupMatchTableTable extends GroupMatchTable } else if (isInserting) { context.missing(_matchIdMeta); } + if (data.containsKey('round_number')) { + context.handle( + _roundNumberMeta, + roundNumber.isAcceptableOrUnknown( + data['round_number']!, + _roundNumberMeta, + ), + ); + } else if (isInserting) { + context.missing(_roundNumberMeta); + } + if (data.containsKey('score')) { + context.handle( + _scoreMeta, + score.isAcceptableOrUnknown(data['score']!, _scoreMeta), + ); + } else if (isInserting) { + context.missing(_scoreMeta); + } + if (data.containsKey('change')) { + context.handle( + _changeMeta, + change.isAcceptableOrUnknown(data['change']!, _changeMeta), + ); + } else if (isInserting) { + context.missing(_changeMeta); + } return context; } @override - Set get $primaryKey => {groupId, matchId}; + Set get $primaryKey => {playerId, matchId, roundNumber}; @override - GroupMatchTableData map(Map data, {String? tablePrefix}) { + ScoreTableData map(Map data, {String? tablePrefix}) { final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return GroupMatchTableData( - groupId: attachedDatabase.typeMapping.read( + return ScoreTableData( + playerId: attachedDatabase.typeMapping.read( DriftSqlType.string, - data['${effectivePrefix}group_id'], + data['${effectivePrefix}player_id'], )!, matchId: attachedDatabase.typeMapping.read( DriftSqlType.string, data['${effectivePrefix}match_id'], )!, + roundNumber: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}round_number'], + )!, + score: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}score'], + )!, + change: attachedDatabase.typeMapping.read( + DriftSqlType.int, + data['${effectivePrefix}change'], + )!, ); } @override - $GroupMatchTableTable createAlias(String alias) { - return $GroupMatchTableTable(attachedDatabase, alias); + $ScoreTableTable createAlias(String alias) { + return $ScoreTableTable(attachedDatabase, alias); } } -class GroupMatchTableData extends DataClass - implements Insertable { - final String groupId; +class ScoreTableData extends DataClass implements Insertable { + final String playerId; final String matchId; - const GroupMatchTableData({required this.groupId, required this.matchId}); + final int roundNumber; + final int score; + final int change; + const ScoreTableData({ + required this.playerId, + required this.matchId, + required this.roundNumber, + required this.score, + required this.change, + }); @override Map toColumns(bool nullToAbsent) { final map = {}; - map['group_id'] = Variable(groupId); + map['player_id'] = Variable(playerId); map['match_id'] = Variable(matchId); + map['round_number'] = Variable(roundNumber); + map['score'] = Variable(score); + map['change'] = Variable(change); return map; } - GroupMatchTableCompanion toCompanion(bool nullToAbsent) { - return GroupMatchTableCompanion( - groupId: Value(groupId), + ScoreTableCompanion toCompanion(bool nullToAbsent) { + return ScoreTableCompanion( + playerId: Value(playerId), matchId: Value(matchId), + roundNumber: Value(roundNumber), + score: Value(score), + change: Value(change), ); } - factory GroupMatchTableData.fromJson( + factory ScoreTableData.fromJson( Map json, { ValueSerializer? serializer, }) { serializer ??= driftRuntimeOptions.defaultSerializer; - return GroupMatchTableData( - groupId: serializer.fromJson(json['groupId']), + return ScoreTableData( + playerId: serializer.fromJson(json['playerId']), matchId: serializer.fromJson(json['matchId']), + roundNumber: serializer.fromJson(json['roundNumber']), + score: serializer.fromJson(json['score']), + change: serializer.fromJson(json['change']), ); } @override Map toJson({ValueSerializer? serializer}) { serializer ??= driftRuntimeOptions.defaultSerializer; return { - 'groupId': serializer.toJson(groupId), + 'playerId': serializer.toJson(playerId), 'matchId': serializer.toJson(matchId), + 'roundNumber': serializer.toJson(roundNumber), + 'score': serializer.toJson(score), + 'change': serializer.toJson(change), }; } - GroupMatchTableData copyWith({String? groupId, String? matchId}) => - GroupMatchTableData( - groupId: groupId ?? this.groupId, - matchId: matchId ?? this.matchId, - ); - GroupMatchTableData copyWithCompanion(GroupMatchTableCompanion data) { - return GroupMatchTableData( - groupId: data.groupId.present ? data.groupId.value : this.groupId, + ScoreTableData copyWith({ + String? playerId, + String? matchId, + int? roundNumber, + int? score, + int? change, + }) => ScoreTableData( + playerId: playerId ?? this.playerId, + matchId: matchId ?? this.matchId, + roundNumber: roundNumber ?? this.roundNumber, + score: score ?? this.score, + change: change ?? this.change, + ); + ScoreTableData copyWithCompanion(ScoreTableCompanion data) { + return ScoreTableData( + playerId: data.playerId.present ? data.playerId.value : this.playerId, matchId: data.matchId.present ? data.matchId.value : this.matchId, + roundNumber: data.roundNumber.present + ? data.roundNumber.value + : this.roundNumber, + score: data.score.present ? data.score.value : this.score, + change: data.change.present ? data.change.value : this.change, ); } @override String toString() { - return (StringBuffer('GroupMatchTableData(') - ..write('groupId: $groupId, ') - ..write('matchId: $matchId') + return (StringBuffer('ScoreTableData(') + ..write('playerId: $playerId, ') + ..write('matchId: $matchId, ') + ..write('roundNumber: $roundNumber, ') + ..write('score: $score, ') + ..write('change: $change') ..write(')')) .toString(); } @override - int get hashCode => Object.hash(groupId, matchId); + int get hashCode => + Object.hash(playerId, matchId, roundNumber, score, change); @override bool operator ==(Object other) => identical(this, other) || - (other is GroupMatchTableData && - other.groupId == this.groupId && - other.matchId == this.matchId); + (other is ScoreTableData && + other.playerId == this.playerId && + other.matchId == this.matchId && + other.roundNumber == this.roundNumber && + other.score == this.score && + other.change == this.change); } -class GroupMatchTableCompanion extends UpdateCompanion { - final Value groupId; +class ScoreTableCompanion extends UpdateCompanion { + final Value playerId; final Value matchId; + final Value roundNumber; + final Value score; + final Value change; final Value rowid; - const GroupMatchTableCompanion({ - this.groupId = const Value.absent(), + const ScoreTableCompanion({ + this.playerId = const Value.absent(), this.matchId = const Value.absent(), + this.roundNumber = const Value.absent(), + this.score = const Value.absent(), + this.change = const Value.absent(), this.rowid = const Value.absent(), }); - GroupMatchTableCompanion.insert({ - required String groupId, + ScoreTableCompanion.insert({ + required String playerId, required String matchId, + required int roundNumber, + required int score, + required int change, this.rowid = const Value.absent(), - }) : groupId = Value(groupId), - matchId = Value(matchId); - static Insertable custom({ - Expression? groupId, + }) : playerId = Value(playerId), + matchId = Value(matchId), + roundNumber = Value(roundNumber), + score = Value(score), + change = Value(change); + static Insertable custom({ + Expression? playerId, Expression? matchId, + Expression? roundNumber, + Expression? score, + Expression? change, Expression? rowid, }) { return RawValuesInsertable({ - if (groupId != null) 'group_id': groupId, + if (playerId != null) 'player_id': playerId, if (matchId != null) 'match_id': matchId, + if (roundNumber != null) 'round_number': roundNumber, + if (score != null) 'score': score, + if (change != null) 'change': change, if (rowid != null) 'rowid': rowid, }); } - GroupMatchTableCompanion copyWith({ - Value? groupId, + ScoreTableCompanion copyWith({ + Value? playerId, Value? matchId, + Value? roundNumber, + Value? score, + Value? change, Value? rowid, }) { - return GroupMatchTableCompanion( - groupId: groupId ?? this.groupId, + return ScoreTableCompanion( + playerId: playerId ?? this.playerId, matchId: matchId ?? this.matchId, + roundNumber: roundNumber ?? this.roundNumber, + score: score ?? this.score, + change: change ?? this.change, rowid: rowid ?? this.rowid, ); } @@ -1482,12 +2644,21 @@ class GroupMatchTableCompanion extends UpdateCompanion { @override Map toColumns(bool nullToAbsent) { final map = {}; - if (groupId.present) { - map['group_id'] = Variable(groupId.value); + if (playerId.present) { + map['player_id'] = Variable(playerId.value); } if (matchId.present) { map['match_id'] = Variable(matchId.value); } + if (roundNumber.present) { + map['round_number'] = Variable(roundNumber.value); + } + if (score.present) { + map['score'] = Variable(score.value); + } + if (change.present) { + map['change'] = Variable(change.value); + } if (rowid.present) { map['rowid'] = Variable(rowid.value); } @@ -1496,9 +2667,12 @@ class GroupMatchTableCompanion extends UpdateCompanion { @override String toString() { - return (StringBuffer('GroupMatchTableCompanion(') - ..write('groupId: $groupId, ') + return (StringBuffer('ScoreTableCompanion(') + ..write('playerId: $playerId, ') ..write('matchId: $matchId, ') + ..write('roundNumber: $roundNumber, ') + ..write('score: $score, ') + ..write('change: $change, ') ..write('rowid: $rowid') ..write(')')) .toString(); @@ -1510,6 +2684,8 @@ abstract class _$AppDatabase extends GeneratedDatabase { $AppDatabaseManager get managers => $AppDatabaseManager(this); late final $PlayerTableTable playerTable = $PlayerTableTable(this); late final $GroupTableTable groupTable = $GroupTableTable(this); + late final $GameTableTable gameTable = $GameTableTable(this); + late final $TeamTableTable teamTable = $TeamTableTable(this); late final $MatchTableTable matchTable = $MatchTableTable(this); late final $PlayerGroupTableTable playerGroupTable = $PlayerGroupTableTable( this, @@ -1517,11 +2693,11 @@ abstract class _$AppDatabase extends GeneratedDatabase { late final $PlayerMatchTableTable playerMatchTable = $PlayerMatchTableTable( this, ); - late final $GroupMatchTableTable groupMatchTable = $GroupMatchTableTable( - this, - ); + late final $ScoreTableTable scoreTable = $ScoreTableTable(this); late final PlayerDao playerDao = PlayerDao(this as AppDatabase); late final GroupDao groupDao = GroupDao(this as AppDatabase); + late final GameDao gameDao = GameDao(this as AppDatabase); + late final TeamDao teamDao = TeamDao(this as AppDatabase); late final MatchDao matchDao = MatchDao(this as AppDatabase); late final PlayerGroupDao playerGroupDao = PlayerGroupDao( this as AppDatabase, @@ -1529,7 +2705,7 @@ abstract class _$AppDatabase extends GeneratedDatabase { late final PlayerMatchDao playerMatchDao = PlayerMatchDao( this as AppDatabase, ); - late final GroupMatchDao groupMatchDao = GroupMatchDao(this as AppDatabase); + late final ScoreDao scoreDao = ScoreDao(this as AppDatabase); @override Iterable> get allTables => allSchemaEntities.whereType>(); @@ -1537,13 +2713,29 @@ abstract class _$AppDatabase extends GeneratedDatabase { List get allSchemaEntities => [ playerTable, groupTable, + gameTable, + teamTable, matchTable, playerGroupTable, playerMatchTable, - groupMatchTable, + scoreTable, ]; @override StreamQueryUpdateRules get streamUpdateRules => const StreamQueryUpdateRules([ + WritePropagation( + on: TableUpdateQuery.onTableName( + 'game_table', + limitUpdateKind: UpdateKind.delete, + ), + result: [TableUpdate('match_table', kind: UpdateKind.delete)], + ), + WritePropagation( + on: TableUpdateQuery.onTableName( + 'group_table', + limitUpdateKind: UpdateKind.delete, + ), + result: [TableUpdate('match_table', kind: UpdateKind.delete)], + ), WritePropagation( on: TableUpdateQuery.onTableName( 'player_table', @@ -1574,17 +2766,17 @@ abstract class _$AppDatabase extends GeneratedDatabase { ), WritePropagation( on: TableUpdateQuery.onTableName( - 'group_table', + 'player_table', limitUpdateKind: UpdateKind.delete, ), - result: [TableUpdate('group_match_table', kind: UpdateKind.delete)], + result: [TableUpdate('score_table', kind: UpdateKind.delete)], ), WritePropagation( on: TableUpdateQuery.onTableName( 'match_table', limitUpdateKind: UpdateKind.delete, ), - result: [TableUpdate('group_match_table', kind: UpdateKind.delete)], + result: [TableUpdate('score_table', kind: UpdateKind.delete)], ), ]); } @@ -1593,6 +2785,7 @@ typedef $$PlayerTableTableCreateCompanionBuilder = PlayerTableCompanion Function({ required String id, required String name, + Value description, required DateTime createdAt, Value rowid, }); @@ -1600,6 +2793,7 @@ typedef $$PlayerTableTableUpdateCompanionBuilder = PlayerTableCompanion Function({ Value id, Value name, + Value description, Value createdAt, Value rowid, }); @@ -1653,6 +2847,24 @@ final class $$PlayerTableTableReferences manager.$state.copyWith(prefetchedData: cache), ); } + + static MultiTypedResultKey<$ScoreTableTable, List> + _scoreTableRefsTable(_$AppDatabase db) => MultiTypedResultKey.fromTable( + db.scoreTable, + aliasName: $_aliasNameGenerator(db.playerTable.id, db.scoreTable.playerId), + ); + + $$ScoreTableTableProcessedTableManager get scoreTableRefs { + final manager = $$ScoreTableTableTableManager( + $_db, + $_db.scoreTable, + ).filter((f) => f.playerId.id.sqlEquals($_itemColumn('id')!)); + + final cache = $_typedResult.readTableOrNull(_scoreTableRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache), + ); + } } class $$PlayerTableTableFilterComposer @@ -1674,6 +2886,11 @@ class $$PlayerTableTableFilterComposer builder: (column) => ColumnFilters(column), ); + ColumnFilters get description => $composableBuilder( + column: $table.description, + builder: (column) => ColumnFilters(column), + ); + ColumnFilters get createdAt => $composableBuilder( column: $table.createdAt, builder: (column) => ColumnFilters(column), @@ -1728,6 +2945,31 @@ class $$PlayerTableTableFilterComposer ); return f(composer); } + + Expression scoreTableRefs( + Expression Function($$ScoreTableTableFilterComposer f) f, + ) { + final $$ScoreTableTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.scoreTable, + getReferencedColumn: (t) => t.playerId, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$ScoreTableTableFilterComposer( + $db: $db, + $table: $db.scoreTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return f(composer); + } } class $$PlayerTableTableOrderingComposer @@ -1749,6 +2991,11 @@ class $$PlayerTableTableOrderingComposer builder: (column) => ColumnOrderings(column), ); + ColumnOrderings get description => $composableBuilder( + column: $table.description, + builder: (column) => ColumnOrderings(column), + ); + ColumnOrderings get createdAt => $composableBuilder( column: $table.createdAt, builder: (column) => ColumnOrderings(column), @@ -1770,6 +3017,11 @@ class $$PlayerTableTableAnnotationComposer GeneratedColumn get name => $composableBuilder(column: $table.name, builder: (column) => column); + GeneratedColumn get description => $composableBuilder( + column: $table.description, + builder: (column) => column, + ); + GeneratedColumn get createdAt => $composableBuilder(column: $table.createdAt, builder: (column) => column); @@ -1822,6 +3074,31 @@ class $$PlayerTableTableAnnotationComposer ); return f(composer); } + + Expression scoreTableRefs( + Expression Function($$ScoreTableTableAnnotationComposer a) f, + ) { + final $$ScoreTableTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.scoreTable, + getReferencedColumn: (t) => t.playerId, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$ScoreTableTableAnnotationComposer( + $db: $db, + $table: $db.scoreTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return f(composer); + } } class $$PlayerTableTableTableManager @@ -1840,6 +3117,7 @@ class $$PlayerTableTableTableManager PrefetchHooks Function({ bool playerGroupTableRefs, bool playerMatchTableRefs, + bool scoreTableRefs, }) > { $$PlayerTableTableTableManager(_$AppDatabase db, $PlayerTableTable table) @@ -1857,11 +3135,13 @@ class $$PlayerTableTableTableManager ({ Value id = const Value.absent(), Value name = const Value.absent(), + Value description = const Value.absent(), Value createdAt = const Value.absent(), Value rowid = const Value.absent(), }) => PlayerTableCompanion( id: id, name: name, + description: description, createdAt: createdAt, rowid: rowid, ), @@ -1869,11 +3149,13 @@ class $$PlayerTableTableTableManager ({ required String id, required String name, + Value description = const Value.absent(), required DateTime createdAt, Value rowid = const Value.absent(), }) => PlayerTableCompanion.insert( id: id, name: name, + description: description, createdAt: createdAt, rowid: rowid, ), @@ -1886,12 +3168,17 @@ class $$PlayerTableTableTableManager ) .toList(), prefetchHooksCallback: - ({playerGroupTableRefs = false, playerMatchTableRefs = false}) { + ({ + playerGroupTableRefs = false, + playerMatchTableRefs = false, + scoreTableRefs = false, + }) { return PrefetchHooks( db: db, explicitlyWatchedTables: [ if (playerGroupTableRefs) db.playerGroupTable, if (playerMatchTableRefs) db.playerMatchTable, + if (scoreTableRefs) db.scoreTable, ], addJoins: null, getPrefetchedDataCallback: (items) async { @@ -1938,6 +3225,27 @@ class $$PlayerTableTableTableManager ), typedResults: items, ), + if (scoreTableRefs) + await $_getPrefetchedData< + PlayerTableData, + $PlayerTableTable, + ScoreTableData + >( + currentTable: table, + referencedTable: $$PlayerTableTableReferences + ._scoreTableRefsTable(db), + managerFromTypedResult: (p0) => + $$PlayerTableTableReferences( + db, + table, + p0, + ).scoreTableRefs, + referencedItemsForCurrentItem: + (item, referencedItems) => referencedItems.where( + (e) => e.playerId == item.id, + ), + typedResults: items, + ), ]; }, ); @@ -1961,12 +3269,14 @@ typedef $$PlayerTableTableProcessedTableManager = PrefetchHooks Function({ bool playerGroupTableRefs, bool playerMatchTableRefs, + bool scoreTableRefs, }) >; typedef $$GroupTableTableCreateCompanionBuilder = GroupTableCompanion Function({ required String id, required String name, + Value description, required DateTime createdAt, Value rowid, }); @@ -1974,6 +3284,7 @@ typedef $$GroupTableTableUpdateCompanionBuilder = GroupTableCompanion Function({ Value id, Value name, + Value description, Value createdAt, Value rowid, }); @@ -1982,6 +3293,24 @@ final class $$GroupTableTableReferences extends BaseReferences<_$AppDatabase, $GroupTableTable, GroupTableData> { $$GroupTableTableReferences(super.$_db, super.$_table, super.$_typedResult); + static MultiTypedResultKey<$MatchTableTable, List> + _matchTableRefsTable(_$AppDatabase db) => MultiTypedResultKey.fromTable( + db.matchTable, + aliasName: $_aliasNameGenerator(db.groupTable.id, db.matchTable.groupId), + ); + + $$MatchTableTableProcessedTableManager get matchTableRefs { + final manager = $$MatchTableTableTableManager( + $_db, + $_db.matchTable, + ).filter((f) => f.groupId.id.sqlEquals($_itemColumn('id')!)); + + final cache = $_typedResult.readTableOrNull(_matchTableRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache), + ); + } + static MultiTypedResultKey<$PlayerGroupTableTable, List> _playerGroupTableRefsTable(_$AppDatabase db) => MultiTypedResultKey.fromTable( db.playerGroupTable, @@ -2004,29 +3333,6 @@ final class $$GroupTableTableReferences manager.$state.copyWith(prefetchedData: cache), ); } - - static MultiTypedResultKey<$GroupMatchTableTable, List> - _groupMatchTableRefsTable(_$AppDatabase db) => MultiTypedResultKey.fromTable( - db.groupMatchTable, - aliasName: $_aliasNameGenerator( - db.groupTable.id, - db.groupMatchTable.groupId, - ), - ); - - $$GroupMatchTableTableProcessedTableManager get groupMatchTableRefs { - final manager = $$GroupMatchTableTableTableManager( - $_db, - $_db.groupMatchTable, - ).filter((f) => f.groupId.id.sqlEquals($_itemColumn('id')!)); - - final cache = $_typedResult.readTableOrNull( - _groupMatchTableRefsTable($_db), - ); - return ProcessedTableManager( - manager.$state.copyWith(prefetchedData: cache), - ); - } } class $$GroupTableTableFilterComposer @@ -2048,11 +3354,41 @@ class $$GroupTableTableFilterComposer builder: (column) => ColumnFilters(column), ); + ColumnFilters get description => $composableBuilder( + column: $table.description, + builder: (column) => ColumnFilters(column), + ); + ColumnFilters get createdAt => $composableBuilder( column: $table.createdAt, builder: (column) => ColumnFilters(column), ); + Expression matchTableRefs( + Expression Function($$MatchTableTableFilterComposer f) f, + ) { + final $$MatchTableTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.matchTable, + getReferencedColumn: (t) => t.groupId, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$MatchTableTableFilterComposer( + $db: $db, + $table: $db.matchTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return f(composer); + } + Expression playerGroupTableRefs( Expression Function($$PlayerGroupTableTableFilterComposer f) f, ) { @@ -2077,31 +3413,6 @@ class $$GroupTableTableFilterComposer ); return f(composer); } - - Expression groupMatchTableRefs( - Expression Function($$GroupMatchTableTableFilterComposer f) f, - ) { - final $$GroupMatchTableTableFilterComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.id, - referencedTable: $db.groupMatchTable, - getReferencedColumn: (t) => t.groupId, - builder: - ( - joinBuilder, { - $addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer, - }) => $$GroupMatchTableTableFilterComposer( - $db: $db, - $table: $db.groupMatchTable, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - ), - ); - return f(composer); - } } class $$GroupTableTableOrderingComposer @@ -2123,6 +3434,11 @@ class $$GroupTableTableOrderingComposer builder: (column) => ColumnOrderings(column), ); + ColumnOrderings get description => $composableBuilder( + column: $table.description, + builder: (column) => ColumnOrderings(column), + ); + ColumnOrderings get createdAt => $composableBuilder( column: $table.createdAt, builder: (column) => ColumnOrderings(column), @@ -2144,9 +3460,39 @@ class $$GroupTableTableAnnotationComposer GeneratedColumn get name => $composableBuilder(column: $table.name, builder: (column) => column); + GeneratedColumn get description => $composableBuilder( + column: $table.description, + builder: (column) => column, + ); + GeneratedColumn get createdAt => $composableBuilder(column: $table.createdAt, builder: (column) => column); + Expression matchTableRefs( + Expression Function($$MatchTableTableAnnotationComposer a) f, + ) { + final $$MatchTableTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.matchTable, + getReferencedColumn: (t) => t.groupId, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$MatchTableTableAnnotationComposer( + $db: $db, + $table: $db.matchTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return f(composer); + } + Expression playerGroupTableRefs( Expression Function($$PlayerGroupTableTableAnnotationComposer a) f, ) { @@ -2171,31 +3517,6 @@ class $$GroupTableTableAnnotationComposer ); return f(composer); } - - Expression groupMatchTableRefs( - Expression Function($$GroupMatchTableTableAnnotationComposer a) f, - ) { - final $$GroupMatchTableTableAnnotationComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.id, - referencedTable: $db.groupMatchTable, - getReferencedColumn: (t) => t.groupId, - builder: - ( - joinBuilder, { - $addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer, - }) => $$GroupMatchTableTableAnnotationComposer( - $db: $db, - $table: $db.groupMatchTable, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - ), - ); - return f(composer); - } } class $$GroupTableTableTableManager @@ -2212,8 +3533,8 @@ class $$GroupTableTableTableManager (GroupTableData, $$GroupTableTableReferences), GroupTableData, PrefetchHooks Function({ + bool matchTableRefs, bool playerGroupTableRefs, - bool groupMatchTableRefs, }) > { $$GroupTableTableTableManager(_$AppDatabase db, $GroupTableTable table) @@ -2231,11 +3552,13 @@ class $$GroupTableTableTableManager ({ Value id = const Value.absent(), Value name = const Value.absent(), + Value description = const Value.absent(), Value createdAt = const Value.absent(), Value rowid = const Value.absent(), }) => GroupTableCompanion( id: id, name: name, + description: description, createdAt: createdAt, rowid: rowid, ), @@ -2243,11 +3566,13 @@ class $$GroupTableTableTableManager ({ required String id, required String name, + Value description = const Value.absent(), required DateTime createdAt, Value rowid = const Value.absent(), }) => GroupTableCompanion.insert( id: id, name: name, + description: description, createdAt: createdAt, rowid: rowid, ), @@ -2260,16 +3585,37 @@ class $$GroupTableTableTableManager ) .toList(), prefetchHooksCallback: - ({playerGroupTableRefs = false, groupMatchTableRefs = false}) { + ({matchTableRefs = false, playerGroupTableRefs = false}) { return PrefetchHooks( db: db, explicitlyWatchedTables: [ + if (matchTableRefs) db.matchTable, if (playerGroupTableRefs) db.playerGroupTable, - if (groupMatchTableRefs) db.groupMatchTable, ], addJoins: null, getPrefetchedDataCallback: (items) async { return [ + if (matchTableRefs) + await $_getPrefetchedData< + GroupTableData, + $GroupTableTable, + MatchTableData + >( + currentTable: table, + referencedTable: $$GroupTableTableReferences + ._matchTableRefsTable(db), + managerFromTypedResult: (p0) => + $$GroupTableTableReferences( + db, + table, + p0, + ).matchTableRefs, + referencedItemsForCurrentItem: + (item, referencedItems) => referencedItems.where( + (e) => e.groupId == item.id, + ), + typedResults: items, + ), if (playerGroupTableRefs) await $_getPrefetchedData< GroupTableData, @@ -2291,27 +3637,6 @@ class $$GroupTableTableTableManager ), typedResults: items, ), - if (groupMatchTableRefs) - await $_getPrefetchedData< - GroupTableData, - $GroupTableTable, - GroupMatchTableData - >( - currentTable: table, - referencedTable: $$GroupTableTableReferences - ._groupMatchTableRefsTable(db), - managerFromTypedResult: (p0) => - $$GroupTableTableReferences( - db, - table, - p0, - ).groupMatchTableRefs, - referencedItemsForCurrentItem: - (item, referencedItems) => referencedItems.where( - (e) => e.groupId == item.id, - ), - typedResults: items, - ), ]; }, ); @@ -2332,24 +3657,636 @@ typedef $$GroupTableTableProcessedTableManager = $$GroupTableTableUpdateCompanionBuilder, (GroupTableData, $$GroupTableTableReferences), GroupTableData, - PrefetchHooks Function({ - bool playerGroupTableRefs, - bool groupMatchTableRefs, - }) + PrefetchHooks Function({bool matchTableRefs, bool playerGroupTableRefs}) + >; +typedef $$GameTableTableCreateCompanionBuilder = + GameTableCompanion Function({ + required String id, + required String name, + required String ruleset, + Value description, + Value color, + Value icon, + required DateTime createdAt, + Value rowid, + }); +typedef $$GameTableTableUpdateCompanionBuilder = + GameTableCompanion Function({ + Value id, + Value name, + Value ruleset, + Value description, + Value color, + Value icon, + Value createdAt, + Value rowid, + }); + +final class $$GameTableTableReferences + extends BaseReferences<_$AppDatabase, $GameTableTable, GameTableData> { + $$GameTableTableReferences(super.$_db, super.$_table, super.$_typedResult); + + static MultiTypedResultKey<$MatchTableTable, List> + _matchTableRefsTable(_$AppDatabase db) => MultiTypedResultKey.fromTable( + db.matchTable, + aliasName: $_aliasNameGenerator(db.gameTable.id, db.matchTable.gameId), + ); + + $$MatchTableTableProcessedTableManager get matchTableRefs { + final manager = $$MatchTableTableTableManager( + $_db, + $_db.matchTable, + ).filter((f) => f.gameId.id.sqlEquals($_itemColumn('id')!)); + + final cache = $_typedResult.readTableOrNull(_matchTableRefsTable($_db)); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache), + ); + } +} + +class $$GameTableTableFilterComposer + extends Composer<_$AppDatabase, $GameTableTable> { + $$GameTableTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get name => $composableBuilder( + column: $table.name, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get ruleset => $composableBuilder( + column: $table.ruleset, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get description => $composableBuilder( + column: $table.description, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get color => $composableBuilder( + column: $table.color, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get icon => $composableBuilder( + column: $table.icon, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, + builder: (column) => ColumnFilters(column), + ); + + Expression matchTableRefs( + Expression Function($$MatchTableTableFilterComposer f) f, + ) { + final $$MatchTableTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.matchTable, + getReferencedColumn: (t) => t.gameId, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$MatchTableTableFilterComposer( + $db: $db, + $table: $db.matchTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return f(composer); + } +} + +class $$GameTableTableOrderingComposer + extends Composer<_$AppDatabase, $GameTableTable> { + $$GameTableTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get name => $composableBuilder( + column: $table.name, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get ruleset => $composableBuilder( + column: $table.ruleset, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get description => $composableBuilder( + column: $table.description, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get color => $composableBuilder( + column: $table.color, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get icon => $composableBuilder( + column: $table.icon, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, + builder: (column) => ColumnOrderings(column), + ); +} + +class $$GameTableTableAnnotationComposer + extends Composer<_$AppDatabase, $GameTableTable> { + $$GameTableTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get name => + $composableBuilder(column: $table.name, builder: (column) => column); + + GeneratedColumn get ruleset => + $composableBuilder(column: $table.ruleset, builder: (column) => column); + + GeneratedColumn get description => $composableBuilder( + column: $table.description, + builder: (column) => column, + ); + + GeneratedColumn get color => + $composableBuilder(column: $table.color, builder: (column) => column); + + GeneratedColumn get icon => + $composableBuilder(column: $table.icon, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); + + Expression matchTableRefs( + Expression Function($$MatchTableTableAnnotationComposer a) f, + ) { + final $$MatchTableTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.matchTable, + getReferencedColumn: (t) => t.gameId, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$MatchTableTableAnnotationComposer( + $db: $db, + $table: $db.matchTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return f(composer); + } +} + +class $$GameTableTableTableManager + extends + RootTableManager< + _$AppDatabase, + $GameTableTable, + GameTableData, + $$GameTableTableFilterComposer, + $$GameTableTableOrderingComposer, + $$GameTableTableAnnotationComposer, + $$GameTableTableCreateCompanionBuilder, + $$GameTableTableUpdateCompanionBuilder, + (GameTableData, $$GameTableTableReferences), + GameTableData, + PrefetchHooks Function({bool matchTableRefs}) + > { + $$GameTableTableTableManager(_$AppDatabase db, $GameTableTable table) + : super( + TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$GameTableTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$GameTableTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$GameTableTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: + ({ + Value id = const Value.absent(), + Value name = const Value.absent(), + Value ruleset = const Value.absent(), + Value description = const Value.absent(), + Value color = const Value.absent(), + Value icon = const Value.absent(), + Value createdAt = const Value.absent(), + Value rowid = const Value.absent(), + }) => GameTableCompanion( + id: id, + name: name, + ruleset: ruleset, + description: description, + color: color, + icon: icon, + createdAt: createdAt, + rowid: rowid, + ), + createCompanionCallback: + ({ + required String id, + required String name, + required String ruleset, + Value description = const Value.absent(), + Value color = const Value.absent(), + Value icon = const Value.absent(), + required DateTime createdAt, + Value rowid = const Value.absent(), + }) => GameTableCompanion.insert( + id: id, + name: name, + ruleset: ruleset, + description: description, + color: color, + icon: icon, + createdAt: createdAt, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map( + (e) => ( + e.readTable(table), + $$GameTableTableReferences(db, table, e), + ), + ) + .toList(), + prefetchHooksCallback: ({matchTableRefs = false}) { + return PrefetchHooks( + db: db, + explicitlyWatchedTables: [if (matchTableRefs) db.matchTable], + addJoins: null, + getPrefetchedDataCallback: (items) async { + return [ + if (matchTableRefs) + await $_getPrefetchedData< + GameTableData, + $GameTableTable, + MatchTableData + >( + currentTable: table, + referencedTable: $$GameTableTableReferences + ._matchTableRefsTable(db), + managerFromTypedResult: (p0) => + $$GameTableTableReferences( + db, + table, + p0, + ).matchTableRefs, + referencedItemsForCurrentItem: (item, referencedItems) => + referencedItems.where((e) => e.gameId == item.id), + typedResults: items, + ), + ]; + }, + ); + }, + ), + ); +} + +typedef $$GameTableTableProcessedTableManager = + ProcessedTableManager< + _$AppDatabase, + $GameTableTable, + GameTableData, + $$GameTableTableFilterComposer, + $$GameTableTableOrderingComposer, + $$GameTableTableAnnotationComposer, + $$GameTableTableCreateCompanionBuilder, + $$GameTableTableUpdateCompanionBuilder, + (GameTableData, $$GameTableTableReferences), + GameTableData, + PrefetchHooks Function({bool matchTableRefs}) + >; +typedef $$TeamTableTableCreateCompanionBuilder = + TeamTableCompanion Function({ + required String id, + required String name, + required DateTime createdAt, + Value rowid, + }); +typedef $$TeamTableTableUpdateCompanionBuilder = + TeamTableCompanion Function({ + Value id, + Value name, + Value createdAt, + Value rowid, + }); + +final class $$TeamTableTableReferences + extends BaseReferences<_$AppDatabase, $TeamTableTable, TeamTableData> { + $$TeamTableTableReferences(super.$_db, super.$_table, super.$_typedResult); + + static MultiTypedResultKey<$PlayerMatchTableTable, List> + _playerMatchTableRefsTable(_$AppDatabase db) => MultiTypedResultKey.fromTable( + db.playerMatchTable, + aliasName: $_aliasNameGenerator( + db.teamTable.id, + db.playerMatchTable.teamId, + ), + ); + + $$PlayerMatchTableTableProcessedTableManager get playerMatchTableRefs { + final manager = $$PlayerMatchTableTableTableManager( + $_db, + $_db.playerMatchTable, + ).filter((f) => f.teamId.id.sqlEquals($_itemColumn('id')!)); + + final cache = $_typedResult.readTableOrNull( + _playerMatchTableRefsTable($_db), + ); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache), + ); + } +} + +class $$TeamTableTableFilterComposer + extends Composer<_$AppDatabase, $TeamTableTable> { + $$TeamTableTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get name => $composableBuilder( + column: $table.name, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, + builder: (column) => ColumnFilters(column), + ); + + Expression playerMatchTableRefs( + Expression Function($$PlayerMatchTableTableFilterComposer f) f, + ) { + final $$PlayerMatchTableTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.playerMatchTable, + getReferencedColumn: (t) => t.teamId, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$PlayerMatchTableTableFilterComposer( + $db: $db, + $table: $db.playerMatchTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return f(composer); + } +} + +class $$TeamTableTableOrderingComposer + extends Composer<_$AppDatabase, $TeamTableTable> { + $$TeamTableTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get name => $composableBuilder( + column: $table.name, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, + builder: (column) => ColumnOrderings(column), + ); +} + +class $$TeamTableTableAnnotationComposer + extends Composer<_$AppDatabase, $TeamTableTable> { + $$TeamTableTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get name => + $composableBuilder(column: $table.name, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); + + Expression playerMatchTableRefs( + Expression Function($$PlayerMatchTableTableAnnotationComposer a) f, + ) { + final $$PlayerMatchTableTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.playerMatchTable, + getReferencedColumn: (t) => t.teamId, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$PlayerMatchTableTableAnnotationComposer( + $db: $db, + $table: $db.playerMatchTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return f(composer); + } +} + +class $$TeamTableTableTableManager + extends + RootTableManager< + _$AppDatabase, + $TeamTableTable, + TeamTableData, + $$TeamTableTableFilterComposer, + $$TeamTableTableOrderingComposer, + $$TeamTableTableAnnotationComposer, + $$TeamTableTableCreateCompanionBuilder, + $$TeamTableTableUpdateCompanionBuilder, + (TeamTableData, $$TeamTableTableReferences), + TeamTableData, + PrefetchHooks Function({bool playerMatchTableRefs}) + > { + $$TeamTableTableTableManager(_$AppDatabase db, $TeamTableTable table) + : super( + TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$TeamTableTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$TeamTableTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$TeamTableTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: + ({ + Value id = const Value.absent(), + Value name = const Value.absent(), + Value createdAt = const Value.absent(), + Value rowid = const Value.absent(), + }) => TeamTableCompanion( + id: id, + name: name, + createdAt: createdAt, + rowid: rowid, + ), + createCompanionCallback: + ({ + required String id, + required String name, + required DateTime createdAt, + Value rowid = const Value.absent(), + }) => TeamTableCompanion.insert( + id: id, + name: name, + createdAt: createdAt, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map( + (e) => ( + e.readTable(table), + $$TeamTableTableReferences(db, table, e), + ), + ) + .toList(), + prefetchHooksCallback: ({playerMatchTableRefs = false}) { + return PrefetchHooks( + db: db, + explicitlyWatchedTables: [ + if (playerMatchTableRefs) db.playerMatchTable, + ], + addJoins: null, + getPrefetchedDataCallback: (items) async { + return [ + if (playerMatchTableRefs) + await $_getPrefetchedData< + TeamTableData, + $TeamTableTable, + PlayerMatchTableData + >( + currentTable: table, + referencedTable: $$TeamTableTableReferences + ._playerMatchTableRefsTable(db), + managerFromTypedResult: (p0) => + $$TeamTableTableReferences( + db, + table, + p0, + ).playerMatchTableRefs, + referencedItemsForCurrentItem: (item, referencedItems) => + referencedItems.where((e) => e.teamId == item.id), + typedResults: items, + ), + ]; + }, + ); + }, + ), + ); +} + +typedef $$TeamTableTableProcessedTableManager = + ProcessedTableManager< + _$AppDatabase, + $TeamTableTable, + TeamTableData, + $$TeamTableTableFilterComposer, + $$TeamTableTableOrderingComposer, + $$TeamTableTableAnnotationComposer, + $$TeamTableTableCreateCompanionBuilder, + $$TeamTableTableUpdateCompanionBuilder, + (TeamTableData, $$TeamTableTableReferences), + TeamTableData, + PrefetchHooks Function({bool playerMatchTableRefs}) >; typedef $$MatchTableTableCreateCompanionBuilder = MatchTableCompanion Function({ required String id, - required String name, - Value winnerId, + required String gameId, + Value groupId, + Value name, + Value notes, required DateTime createdAt, Value rowid, }); typedef $$MatchTableTableUpdateCompanionBuilder = MatchTableCompanion Function({ Value id, - Value name, - Value winnerId, + Value gameId, + Value groupId, + Value name, + Value notes, Value createdAt, Value rowid, }); @@ -2358,6 +4295,42 @@ final class $$MatchTableTableReferences extends BaseReferences<_$AppDatabase, $MatchTableTable, MatchTableData> { $$MatchTableTableReferences(super.$_db, super.$_table, super.$_typedResult); + static $GameTableTable _gameIdTable(_$AppDatabase db) => db.gameTable + .createAlias($_aliasNameGenerator(db.matchTable.gameId, db.gameTable.id)); + + $$GameTableTableProcessedTableManager get gameId { + final $_column = $_itemColumn('game_id')!; + + final manager = $$GameTableTableTableManager( + $_db, + $_db.gameTable, + ).filter((f) => f.id.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_gameIdTable($_db)); + if (item == null) return manager; + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item]), + ); + } + + static $GroupTableTable _groupIdTable(_$AppDatabase db) => + db.groupTable.createAlias( + $_aliasNameGenerator(db.matchTable.groupId, db.groupTable.id), + ); + + $$GroupTableTableProcessedTableManager? get groupId { + final $_column = $_itemColumn('group_id'); + if ($_column == null) return null; + final manager = $$GroupTableTableTableManager( + $_db, + $_db.groupTable, + ).filter((f) => f.id.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_groupIdTable($_db)); + if (item == null) return manager; + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item]), + ); + } + static MultiTypedResultKey<$PlayerMatchTableTable, List> _playerMatchTableRefsTable(_$AppDatabase db) => MultiTypedResultKey.fromTable( db.playerMatchTable, @@ -2381,24 +4354,19 @@ final class $$MatchTableTableReferences ); } - static MultiTypedResultKey<$GroupMatchTableTable, List> - _groupMatchTableRefsTable(_$AppDatabase db) => MultiTypedResultKey.fromTable( - db.groupMatchTable, - aliasName: $_aliasNameGenerator( - db.matchTable.id, - db.groupMatchTable.matchId, - ), + static MultiTypedResultKey<$ScoreTableTable, List> + _scoreTableRefsTable(_$AppDatabase db) => MultiTypedResultKey.fromTable( + db.scoreTable, + aliasName: $_aliasNameGenerator(db.matchTable.id, db.scoreTable.matchId), ); - $$GroupMatchTableTableProcessedTableManager get groupMatchTableRefs { - final manager = $$GroupMatchTableTableTableManager( + $$ScoreTableTableProcessedTableManager get scoreTableRefs { + final manager = $$ScoreTableTableTableManager( $_db, - $_db.groupMatchTable, + $_db.scoreTable, ).filter((f) => f.matchId.id.sqlEquals($_itemColumn('id')!)); - final cache = $_typedResult.readTableOrNull( - _groupMatchTableRefsTable($_db), - ); + final cache = $_typedResult.readTableOrNull(_scoreTableRefsTable($_db)); return ProcessedTableManager( manager.$state.copyWith(prefetchedData: cache), ); @@ -2424,8 +4392,8 @@ class $$MatchTableTableFilterComposer builder: (column) => ColumnFilters(column), ); - ColumnFilters get winnerId => $composableBuilder( - column: $table.winnerId, + ColumnFilters get notes => $composableBuilder( + column: $table.notes, builder: (column) => ColumnFilters(column), ); @@ -2434,6 +4402,52 @@ class $$MatchTableTableFilterComposer builder: (column) => ColumnFilters(column), ); + $$GameTableTableFilterComposer get gameId { + final $$GameTableTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.gameId, + referencedTable: $db.gameTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$GameTableTableFilterComposer( + $db: $db, + $table: $db.gameTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } + + $$GroupTableTableFilterComposer get groupId { + final $$GroupTableTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.groupId, + referencedTable: $db.groupTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$GroupTableTableFilterComposer( + $db: $db, + $table: $db.groupTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } + Expression playerMatchTableRefs( Expression Function($$PlayerMatchTableTableFilterComposer f) f, ) { @@ -2459,22 +4473,22 @@ class $$MatchTableTableFilterComposer return f(composer); } - Expression groupMatchTableRefs( - Expression Function($$GroupMatchTableTableFilterComposer f) f, + Expression scoreTableRefs( + Expression Function($$ScoreTableTableFilterComposer f) f, ) { - final $$GroupMatchTableTableFilterComposer composer = $composerBuilder( + final $$ScoreTableTableFilterComposer composer = $composerBuilder( composer: this, getCurrentColumn: (t) => t.id, - referencedTable: $db.groupMatchTable, + referencedTable: $db.scoreTable, getReferencedColumn: (t) => t.matchId, builder: ( joinBuilder, { $addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer, - }) => $$GroupMatchTableTableFilterComposer( + }) => $$ScoreTableTableFilterComposer( $db: $db, - $table: $db.groupMatchTable, + $table: $db.scoreTable, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -2504,8 +4518,8 @@ class $$MatchTableTableOrderingComposer builder: (column) => ColumnOrderings(column), ); - ColumnOrderings get winnerId => $composableBuilder( - column: $table.winnerId, + ColumnOrderings get notes => $composableBuilder( + column: $table.notes, builder: (column) => ColumnOrderings(column), ); @@ -2513,6 +4527,52 @@ class $$MatchTableTableOrderingComposer column: $table.createdAt, builder: (column) => ColumnOrderings(column), ); + + $$GameTableTableOrderingComposer get gameId { + final $$GameTableTableOrderingComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.gameId, + referencedTable: $db.gameTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$GameTableTableOrderingComposer( + $db: $db, + $table: $db.gameTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } + + $$GroupTableTableOrderingComposer get groupId { + final $$GroupTableTableOrderingComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.groupId, + referencedTable: $db.groupTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$GroupTableTableOrderingComposer( + $db: $db, + $table: $db.groupTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } } class $$MatchTableTableAnnotationComposer @@ -2530,12 +4590,58 @@ class $$MatchTableTableAnnotationComposer GeneratedColumn get name => $composableBuilder(column: $table.name, builder: (column) => column); - GeneratedColumn get winnerId => - $composableBuilder(column: $table.winnerId, builder: (column) => column); + GeneratedColumn get notes => + $composableBuilder(column: $table.notes, builder: (column) => column); GeneratedColumn get createdAt => $composableBuilder(column: $table.createdAt, builder: (column) => column); + $$GameTableTableAnnotationComposer get gameId { + final $$GameTableTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.gameId, + referencedTable: $db.gameTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$GameTableTableAnnotationComposer( + $db: $db, + $table: $db.gameTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } + + $$GroupTableTableAnnotationComposer get groupId { + final $$GroupTableTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.groupId, + referencedTable: $db.groupTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$GroupTableTableAnnotationComposer( + $db: $db, + $table: $db.groupTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } + Expression playerMatchTableRefs( Expression Function($$PlayerMatchTableTableAnnotationComposer a) f, ) { @@ -2561,22 +4667,22 @@ class $$MatchTableTableAnnotationComposer return f(composer); } - Expression groupMatchTableRefs( - Expression Function($$GroupMatchTableTableAnnotationComposer a) f, + Expression scoreTableRefs( + Expression Function($$ScoreTableTableAnnotationComposer a) f, ) { - final $$GroupMatchTableTableAnnotationComposer composer = $composerBuilder( + final $$ScoreTableTableAnnotationComposer composer = $composerBuilder( composer: this, getCurrentColumn: (t) => t.id, - referencedTable: $db.groupMatchTable, + referencedTable: $db.scoreTable, getReferencedColumn: (t) => t.matchId, builder: ( joinBuilder, { $addJoinBuilderToRootComposer, $removeJoinBuilderFromRootComposer, - }) => $$GroupMatchTableTableAnnotationComposer( + }) => $$ScoreTableTableAnnotationComposer( $db: $db, - $table: $db.groupMatchTable, + $table: $db.scoreTable, $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, joinBuilder: joinBuilder, $removeJoinBuilderFromRootComposer: @@ -2601,8 +4707,10 @@ class $$MatchTableTableTableManager (MatchTableData, $$MatchTableTableReferences), MatchTableData, PrefetchHooks Function({ + bool gameId, + bool groupId, bool playerMatchTableRefs, - bool groupMatchTableRefs, + bool scoreTableRefs, }) > { $$MatchTableTableTableManager(_$AppDatabase db, $MatchTableTable table) @@ -2619,28 +4727,36 @@ class $$MatchTableTableTableManager updateCompanionCallback: ({ Value id = const Value.absent(), - Value name = const Value.absent(), - Value winnerId = const Value.absent(), + Value gameId = const Value.absent(), + Value groupId = const Value.absent(), + Value name = const Value.absent(), + Value notes = const Value.absent(), Value createdAt = const Value.absent(), Value rowid = const Value.absent(), }) => MatchTableCompanion( id: id, + gameId: gameId, + groupId: groupId, name: name, - winnerId: winnerId, + notes: notes, createdAt: createdAt, rowid: rowid, ), createCompanionCallback: ({ required String id, - required String name, - Value winnerId = const Value.absent(), + required String gameId, + Value groupId = const Value.absent(), + Value name = const Value.absent(), + Value notes = const Value.absent(), required DateTime createdAt, Value rowid = const Value.absent(), }) => MatchTableCompanion.insert( id: id, + gameId: gameId, + groupId: groupId, name: name, - winnerId: winnerId, + notes: notes, createdAt: createdAt, rowid: rowid, ), @@ -2653,14 +4769,65 @@ class $$MatchTableTableTableManager ) .toList(), prefetchHooksCallback: - ({playerMatchTableRefs = false, groupMatchTableRefs = false}) { + ({ + gameId = false, + groupId = false, + playerMatchTableRefs = false, + scoreTableRefs = false, + }) { return PrefetchHooks( db: db, explicitlyWatchedTables: [ if (playerMatchTableRefs) db.playerMatchTable, - if (groupMatchTableRefs) db.groupMatchTable, + if (scoreTableRefs) db.scoreTable, ], - addJoins: null, + addJoins: + < + T extends TableManagerState< + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic + > + >(state) { + if (gameId) { + state = + state.withJoin( + currentTable: table, + currentColumn: table.gameId, + referencedTable: $$MatchTableTableReferences + ._gameIdTable(db), + referencedColumn: + $$MatchTableTableReferences + ._gameIdTable(db) + .id, + ) + as T; + } + if (groupId) { + state = + state.withJoin( + currentTable: table, + currentColumn: table.groupId, + referencedTable: $$MatchTableTableReferences + ._groupIdTable(db), + referencedColumn: + $$MatchTableTableReferences + ._groupIdTable(db) + .id, + ) + as T; + } + + return state; + }, getPrefetchedDataCallback: (items) async { return [ if (playerMatchTableRefs) @@ -2684,21 +4851,21 @@ class $$MatchTableTableTableManager ), typedResults: items, ), - if (groupMatchTableRefs) + if (scoreTableRefs) await $_getPrefetchedData< MatchTableData, $MatchTableTable, - GroupMatchTableData + ScoreTableData >( currentTable: table, referencedTable: $$MatchTableTableReferences - ._groupMatchTableRefsTable(db), + ._scoreTableRefsTable(db), managerFromTypedResult: (p0) => $$MatchTableTableReferences( db, table, p0, - ).groupMatchTableRefs, + ).scoreTableRefs, referencedItemsForCurrentItem: (item, referencedItems) => referencedItems.where( (e) => e.matchId == item.id, @@ -2726,8 +4893,10 @@ typedef $$MatchTableTableProcessedTableManager = (MatchTableData, $$MatchTableTableReferences), MatchTableData, PrefetchHooks Function({ + bool gameId, + bool groupId, bool playerMatchTableRefs, - bool groupMatchTableRefs, + bool scoreTableRefs, }) >; typedef $$PlayerGroupTableTableCreateCompanionBuilder = @@ -3099,12 +5268,16 @@ typedef $$PlayerMatchTableTableCreateCompanionBuilder = PlayerMatchTableCompanion Function({ required String playerId, required String matchId, + Value teamId, + required int score, Value rowid, }); typedef $$PlayerMatchTableTableUpdateCompanionBuilder = PlayerMatchTableCompanion Function({ Value playerId, Value matchId, + Value teamId, + Value score, Value rowid, }); @@ -3158,6 +5331,25 @@ final class $$PlayerMatchTableTableReferences manager.$state.copyWith(prefetchedData: [item]), ); } + + static $TeamTableTable _teamIdTable(_$AppDatabase db) => + db.teamTable.createAlias( + $_aliasNameGenerator(db.playerMatchTable.teamId, db.teamTable.id), + ); + + $$TeamTableTableProcessedTableManager? get teamId { + final $_column = $_itemColumn('team_id'); + if ($_column == null) return null; + final manager = $$TeamTableTableTableManager( + $_db, + $_db.teamTable, + ).filter((f) => f.id.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_teamIdTable($_db)); + if (item == null) return manager; + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item]), + ); + } } class $$PlayerMatchTableTableFilterComposer @@ -3169,6 +5361,489 @@ class $$PlayerMatchTableTableFilterComposer super.$addJoinBuilderToRootComposer, super.$removeJoinBuilderFromRootComposer, }); + ColumnFilters get score => $composableBuilder( + column: $table.score, + builder: (column) => ColumnFilters(column), + ); + + $$PlayerTableTableFilterComposer get playerId { + final $$PlayerTableTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.playerId, + referencedTable: $db.playerTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$PlayerTableTableFilterComposer( + $db: $db, + $table: $db.playerTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } + + $$MatchTableTableFilterComposer get matchId { + final $$MatchTableTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.matchId, + referencedTable: $db.matchTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$MatchTableTableFilterComposer( + $db: $db, + $table: $db.matchTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } + + $$TeamTableTableFilterComposer get teamId { + final $$TeamTableTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.teamId, + referencedTable: $db.teamTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$TeamTableTableFilterComposer( + $db: $db, + $table: $db.teamTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } +} + +class $$PlayerMatchTableTableOrderingComposer + extends Composer<_$AppDatabase, $PlayerMatchTableTable> { + $$PlayerMatchTableTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get score => $composableBuilder( + column: $table.score, + builder: (column) => ColumnOrderings(column), + ); + + $$PlayerTableTableOrderingComposer get playerId { + final $$PlayerTableTableOrderingComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.playerId, + referencedTable: $db.playerTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$PlayerTableTableOrderingComposer( + $db: $db, + $table: $db.playerTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } + + $$MatchTableTableOrderingComposer get matchId { + final $$MatchTableTableOrderingComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.matchId, + referencedTable: $db.matchTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$MatchTableTableOrderingComposer( + $db: $db, + $table: $db.matchTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } + + $$TeamTableTableOrderingComposer get teamId { + final $$TeamTableTableOrderingComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.teamId, + referencedTable: $db.teamTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$TeamTableTableOrderingComposer( + $db: $db, + $table: $db.teamTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } +} + +class $$PlayerMatchTableTableAnnotationComposer + extends Composer<_$AppDatabase, $PlayerMatchTableTable> { + $$PlayerMatchTableTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get score => + $composableBuilder(column: $table.score, builder: (column) => column); + + $$PlayerTableTableAnnotationComposer get playerId { + final $$PlayerTableTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.playerId, + referencedTable: $db.playerTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$PlayerTableTableAnnotationComposer( + $db: $db, + $table: $db.playerTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } + + $$MatchTableTableAnnotationComposer get matchId { + final $$MatchTableTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.matchId, + referencedTable: $db.matchTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$MatchTableTableAnnotationComposer( + $db: $db, + $table: $db.matchTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } + + $$TeamTableTableAnnotationComposer get teamId { + final $$TeamTableTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.teamId, + referencedTable: $db.teamTable, + getReferencedColumn: (t) => t.id, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$TeamTableTableAnnotationComposer( + $db: $db, + $table: $db.teamTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return composer; + } +} + +class $$PlayerMatchTableTableTableManager + extends + RootTableManager< + _$AppDatabase, + $PlayerMatchTableTable, + PlayerMatchTableData, + $$PlayerMatchTableTableFilterComposer, + $$PlayerMatchTableTableOrderingComposer, + $$PlayerMatchTableTableAnnotationComposer, + $$PlayerMatchTableTableCreateCompanionBuilder, + $$PlayerMatchTableTableUpdateCompanionBuilder, + (PlayerMatchTableData, $$PlayerMatchTableTableReferences), + PlayerMatchTableData, + PrefetchHooks Function({bool playerId, bool matchId, bool teamId}) + > { + $$PlayerMatchTableTableTableManager( + _$AppDatabase db, + $PlayerMatchTableTable table, + ) : super( + TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$PlayerMatchTableTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$PlayerMatchTableTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$PlayerMatchTableTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: + ({ + Value playerId = const Value.absent(), + Value matchId = const Value.absent(), + Value teamId = const Value.absent(), + Value score = const Value.absent(), + Value rowid = const Value.absent(), + }) => PlayerMatchTableCompanion( + playerId: playerId, + matchId: matchId, + teamId: teamId, + score: score, + rowid: rowid, + ), + createCompanionCallback: + ({ + required String playerId, + required String matchId, + Value teamId = const Value.absent(), + required int score, + Value rowid = const Value.absent(), + }) => PlayerMatchTableCompanion.insert( + playerId: playerId, + matchId: matchId, + teamId: teamId, + score: score, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map( + (e) => ( + e.readTable(table), + $$PlayerMatchTableTableReferences(db, table, e), + ), + ) + .toList(), + prefetchHooksCallback: + ({playerId = false, matchId = false, teamId = false}) { + return PrefetchHooks( + db: db, + explicitlyWatchedTables: [], + addJoins: + < + T extends TableManagerState< + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic, + dynamic + > + >(state) { + if (playerId) { + state = + state.withJoin( + currentTable: table, + currentColumn: table.playerId, + referencedTable: + $$PlayerMatchTableTableReferences + ._playerIdTable(db), + referencedColumn: + $$PlayerMatchTableTableReferences + ._playerIdTable(db) + .id, + ) + as T; + } + if (matchId) { + state = + state.withJoin( + currentTable: table, + currentColumn: table.matchId, + referencedTable: + $$PlayerMatchTableTableReferences + ._matchIdTable(db), + referencedColumn: + $$PlayerMatchTableTableReferences + ._matchIdTable(db) + .id, + ) + as T; + } + if (teamId) { + state = + state.withJoin( + currentTable: table, + currentColumn: table.teamId, + referencedTable: + $$PlayerMatchTableTableReferences + ._teamIdTable(db), + referencedColumn: + $$PlayerMatchTableTableReferences + ._teamIdTable(db) + .id, + ) + as T; + } + + return state; + }, + getPrefetchedDataCallback: (items) async { + return []; + }, + ); + }, + ), + ); +} + +typedef $$PlayerMatchTableTableProcessedTableManager = + ProcessedTableManager< + _$AppDatabase, + $PlayerMatchTableTable, + PlayerMatchTableData, + $$PlayerMatchTableTableFilterComposer, + $$PlayerMatchTableTableOrderingComposer, + $$PlayerMatchTableTableAnnotationComposer, + $$PlayerMatchTableTableCreateCompanionBuilder, + $$PlayerMatchTableTableUpdateCompanionBuilder, + (PlayerMatchTableData, $$PlayerMatchTableTableReferences), + PlayerMatchTableData, + PrefetchHooks Function({bool playerId, bool matchId, bool teamId}) + >; +typedef $$ScoreTableTableCreateCompanionBuilder = + ScoreTableCompanion Function({ + required String playerId, + required String matchId, + required int roundNumber, + required int score, + required int change, + Value rowid, + }); +typedef $$ScoreTableTableUpdateCompanionBuilder = + ScoreTableCompanion Function({ + Value playerId, + Value matchId, + Value roundNumber, + Value score, + Value change, + Value rowid, + }); + +final class $$ScoreTableTableReferences + extends BaseReferences<_$AppDatabase, $ScoreTableTable, ScoreTableData> { + $$ScoreTableTableReferences(super.$_db, super.$_table, super.$_typedResult); + + static $PlayerTableTable _playerIdTable(_$AppDatabase db) => + db.playerTable.createAlias( + $_aliasNameGenerator(db.scoreTable.playerId, db.playerTable.id), + ); + + $$PlayerTableTableProcessedTableManager get playerId { + final $_column = $_itemColumn('player_id')!; + + final manager = $$PlayerTableTableTableManager( + $_db, + $_db.playerTable, + ).filter((f) => f.id.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_playerIdTable($_db)); + if (item == null) return manager; + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item]), + ); + } + + static $MatchTableTable _matchIdTable(_$AppDatabase db) => + db.matchTable.createAlias( + $_aliasNameGenerator(db.scoreTable.matchId, db.matchTable.id), + ); + + $$MatchTableTableProcessedTableManager get matchId { + final $_column = $_itemColumn('match_id')!; + + final manager = $$MatchTableTableTableManager( + $_db, + $_db.matchTable, + ).filter((f) => f.id.sqlEquals($_column)); + final item = $_typedResult.readTableOrNull(_matchIdTable($_db)); + if (item == null) return manager; + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: [item]), + ); + } +} + +class $$ScoreTableTableFilterComposer + extends Composer<_$AppDatabase, $ScoreTableTable> { + $$ScoreTableTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get roundNumber => $composableBuilder( + column: $table.roundNumber, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get score => $composableBuilder( + column: $table.score, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get change => $composableBuilder( + column: $table.change, + builder: (column) => ColumnFilters(column), + ); + $$PlayerTableTableFilterComposer get playerId { final $$PlayerTableTableFilterComposer composer = $composerBuilder( composer: this, @@ -3216,15 +5891,30 @@ class $$PlayerMatchTableTableFilterComposer } } -class $$PlayerMatchTableTableOrderingComposer - extends Composer<_$AppDatabase, $PlayerMatchTableTable> { - $$PlayerMatchTableTableOrderingComposer({ +class $$ScoreTableTableOrderingComposer + extends Composer<_$AppDatabase, $ScoreTableTable> { + $$ScoreTableTableOrderingComposer({ required super.$db, required super.$table, super.joinBuilder, super.$addJoinBuilderToRootComposer, super.$removeJoinBuilderFromRootComposer, }); + ColumnOrderings get roundNumber => $composableBuilder( + column: $table.roundNumber, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get score => $composableBuilder( + column: $table.score, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get change => $composableBuilder( + column: $table.change, + builder: (column) => ColumnOrderings(column), + ); + $$PlayerTableTableOrderingComposer get playerId { final $$PlayerTableTableOrderingComposer composer = $composerBuilder( composer: this, @@ -3272,15 +5962,26 @@ class $$PlayerMatchTableTableOrderingComposer } } -class $$PlayerMatchTableTableAnnotationComposer - extends Composer<_$AppDatabase, $PlayerMatchTableTable> { - $$PlayerMatchTableTableAnnotationComposer({ +class $$ScoreTableTableAnnotationComposer + extends Composer<_$AppDatabase, $ScoreTableTable> { + $$ScoreTableTableAnnotationComposer({ required super.$db, required super.$table, super.joinBuilder, super.$addJoinBuilderToRootComposer, super.$removeJoinBuilderFromRootComposer, }); + GeneratedColumn get roundNumber => $composableBuilder( + column: $table.roundNumber, + builder: (column) => column, + ); + + GeneratedColumn get score => + $composableBuilder(column: $table.score, builder: (column) => column); + + GeneratedColumn get change => + $composableBuilder(column: $table.change, builder: (column) => column); + $$PlayerTableTableAnnotationComposer get playerId { final $$PlayerTableTableAnnotationComposer composer = $composerBuilder( composer: this, @@ -3328,59 +6029,69 @@ class $$PlayerMatchTableTableAnnotationComposer } } -class $$PlayerMatchTableTableTableManager +class $$ScoreTableTableTableManager extends RootTableManager< _$AppDatabase, - $PlayerMatchTableTable, - PlayerMatchTableData, - $$PlayerMatchTableTableFilterComposer, - $$PlayerMatchTableTableOrderingComposer, - $$PlayerMatchTableTableAnnotationComposer, - $$PlayerMatchTableTableCreateCompanionBuilder, - $$PlayerMatchTableTableUpdateCompanionBuilder, - (PlayerMatchTableData, $$PlayerMatchTableTableReferences), - PlayerMatchTableData, + $ScoreTableTable, + ScoreTableData, + $$ScoreTableTableFilterComposer, + $$ScoreTableTableOrderingComposer, + $$ScoreTableTableAnnotationComposer, + $$ScoreTableTableCreateCompanionBuilder, + $$ScoreTableTableUpdateCompanionBuilder, + (ScoreTableData, $$ScoreTableTableReferences), + ScoreTableData, PrefetchHooks Function({bool playerId, bool matchId}) > { - $$PlayerMatchTableTableTableManager( - _$AppDatabase db, - $PlayerMatchTableTable table, - ) : super( + $$ScoreTableTableTableManager(_$AppDatabase db, $ScoreTableTable table) + : super( TableManagerState( db: db, table: table, createFilteringComposer: () => - $$PlayerMatchTableTableFilterComposer($db: db, $table: table), + $$ScoreTableTableFilterComposer($db: db, $table: table), createOrderingComposer: () => - $$PlayerMatchTableTableOrderingComposer($db: db, $table: table), + $$ScoreTableTableOrderingComposer($db: db, $table: table), createComputedFieldComposer: () => - $$PlayerMatchTableTableAnnotationComposer($db: db, $table: table), + $$ScoreTableTableAnnotationComposer($db: db, $table: table), updateCompanionCallback: ({ Value playerId = const Value.absent(), Value matchId = const Value.absent(), + Value roundNumber = const Value.absent(), + Value score = const Value.absent(), + Value change = const Value.absent(), Value rowid = const Value.absent(), - }) => PlayerMatchTableCompanion( + }) => ScoreTableCompanion( playerId: playerId, matchId: matchId, + roundNumber: roundNumber, + score: score, + change: change, rowid: rowid, ), createCompanionCallback: ({ required String playerId, required String matchId, + required int roundNumber, + required int score, + required int change, Value rowid = const Value.absent(), - }) => PlayerMatchTableCompanion.insert( + }) => ScoreTableCompanion.insert( playerId: playerId, matchId: matchId, + roundNumber: roundNumber, + score: score, + change: change, rowid: rowid, ), withReferenceMapper: (p0) => p0 .map( (e) => ( e.readTable(table), - $$PlayerMatchTableTableReferences(db, table, e), + $$ScoreTableTableReferences(db, table, e), ), ) .toList(), @@ -3409,13 +6120,11 @@ class $$PlayerMatchTableTableTableManager state.withJoin( currentTable: table, currentColumn: table.playerId, - referencedTable: - $$PlayerMatchTableTableReferences - ._playerIdTable(db), - referencedColumn: - $$PlayerMatchTableTableReferences - ._playerIdTable(db) - .id, + referencedTable: $$ScoreTableTableReferences + ._playerIdTable(db), + referencedColumn: $$ScoreTableTableReferences + ._playerIdTable(db) + .id, ) as T; } @@ -3424,13 +6133,11 @@ class $$PlayerMatchTableTableTableManager state.withJoin( currentTable: table, currentColumn: table.matchId, - referencedTable: - $$PlayerMatchTableTableReferences - ._matchIdTable(db), - referencedColumn: - $$PlayerMatchTableTableReferences - ._matchIdTable(db) - .id, + referencedTable: $$ScoreTableTableReferences + ._matchIdTable(db), + referencedColumn: $$ScoreTableTableReferences + ._matchIdTable(db) + .id, ) as T; } @@ -3446,385 +6153,20 @@ class $$PlayerMatchTableTableTableManager ); } -typedef $$PlayerMatchTableTableProcessedTableManager = +typedef $$ScoreTableTableProcessedTableManager = ProcessedTableManager< _$AppDatabase, - $PlayerMatchTableTable, - PlayerMatchTableData, - $$PlayerMatchTableTableFilterComposer, - $$PlayerMatchTableTableOrderingComposer, - $$PlayerMatchTableTableAnnotationComposer, - $$PlayerMatchTableTableCreateCompanionBuilder, - $$PlayerMatchTableTableUpdateCompanionBuilder, - (PlayerMatchTableData, $$PlayerMatchTableTableReferences), - PlayerMatchTableData, + $ScoreTableTable, + ScoreTableData, + $$ScoreTableTableFilterComposer, + $$ScoreTableTableOrderingComposer, + $$ScoreTableTableAnnotationComposer, + $$ScoreTableTableCreateCompanionBuilder, + $$ScoreTableTableUpdateCompanionBuilder, + (ScoreTableData, $$ScoreTableTableReferences), + ScoreTableData, PrefetchHooks Function({bool playerId, bool matchId}) >; -typedef $$GroupMatchTableTableCreateCompanionBuilder = - GroupMatchTableCompanion Function({ - required String groupId, - required String matchId, - Value rowid, - }); -typedef $$GroupMatchTableTableUpdateCompanionBuilder = - GroupMatchTableCompanion Function({ - Value groupId, - Value matchId, - Value rowid, - }); - -final class $$GroupMatchTableTableReferences - extends - BaseReferences< - _$AppDatabase, - $GroupMatchTableTable, - GroupMatchTableData - > { - $$GroupMatchTableTableReferences( - super.$_db, - super.$_table, - super.$_typedResult, - ); - - static $GroupTableTable _groupIdTable(_$AppDatabase db) => - db.groupTable.createAlias( - $_aliasNameGenerator(db.groupMatchTable.groupId, db.groupTable.id), - ); - - $$GroupTableTableProcessedTableManager get groupId { - final $_column = $_itemColumn('group_id')!; - - final manager = $$GroupTableTableTableManager( - $_db, - $_db.groupTable, - ).filter((f) => f.id.sqlEquals($_column)); - final item = $_typedResult.readTableOrNull(_groupIdTable($_db)); - if (item == null) return manager; - return ProcessedTableManager( - manager.$state.copyWith(prefetchedData: [item]), - ); - } - - static $MatchTableTable _matchIdTable(_$AppDatabase db) => - db.matchTable.createAlias( - $_aliasNameGenerator(db.groupMatchTable.matchId, db.matchTable.id), - ); - - $$MatchTableTableProcessedTableManager get matchId { - final $_column = $_itemColumn('match_id')!; - - final manager = $$MatchTableTableTableManager( - $_db, - $_db.matchTable, - ).filter((f) => f.id.sqlEquals($_column)); - final item = $_typedResult.readTableOrNull(_matchIdTable($_db)); - if (item == null) return manager; - return ProcessedTableManager( - manager.$state.copyWith(prefetchedData: [item]), - ); - } -} - -class $$GroupMatchTableTableFilterComposer - extends Composer<_$AppDatabase, $GroupMatchTableTable> { - $$GroupMatchTableTableFilterComposer({ - required super.$db, - required super.$table, - super.joinBuilder, - super.$addJoinBuilderToRootComposer, - super.$removeJoinBuilderFromRootComposer, - }); - $$GroupTableTableFilterComposer get groupId { - final $$GroupTableTableFilterComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.groupId, - referencedTable: $db.groupTable, - getReferencedColumn: (t) => t.id, - builder: - ( - joinBuilder, { - $addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer, - }) => $$GroupTableTableFilterComposer( - $db: $db, - $table: $db.groupTable, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - ), - ); - return composer; - } - - $$MatchTableTableFilterComposer get matchId { - final $$MatchTableTableFilterComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.matchId, - referencedTable: $db.matchTable, - getReferencedColumn: (t) => t.id, - builder: - ( - joinBuilder, { - $addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer, - }) => $$MatchTableTableFilterComposer( - $db: $db, - $table: $db.matchTable, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - ), - ); - return composer; - } -} - -class $$GroupMatchTableTableOrderingComposer - extends Composer<_$AppDatabase, $GroupMatchTableTable> { - $$GroupMatchTableTableOrderingComposer({ - required super.$db, - required super.$table, - super.joinBuilder, - super.$addJoinBuilderToRootComposer, - super.$removeJoinBuilderFromRootComposer, - }); - $$GroupTableTableOrderingComposer get groupId { - final $$GroupTableTableOrderingComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.groupId, - referencedTable: $db.groupTable, - getReferencedColumn: (t) => t.id, - builder: - ( - joinBuilder, { - $addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer, - }) => $$GroupTableTableOrderingComposer( - $db: $db, - $table: $db.groupTable, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - ), - ); - return composer; - } - - $$MatchTableTableOrderingComposer get matchId { - final $$MatchTableTableOrderingComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.matchId, - referencedTable: $db.matchTable, - getReferencedColumn: (t) => t.id, - builder: - ( - joinBuilder, { - $addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer, - }) => $$MatchTableTableOrderingComposer( - $db: $db, - $table: $db.matchTable, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - ), - ); - return composer; - } -} - -class $$GroupMatchTableTableAnnotationComposer - extends Composer<_$AppDatabase, $GroupMatchTableTable> { - $$GroupMatchTableTableAnnotationComposer({ - required super.$db, - required super.$table, - super.joinBuilder, - super.$addJoinBuilderToRootComposer, - super.$removeJoinBuilderFromRootComposer, - }); - $$GroupTableTableAnnotationComposer get groupId { - final $$GroupTableTableAnnotationComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.groupId, - referencedTable: $db.groupTable, - getReferencedColumn: (t) => t.id, - builder: - ( - joinBuilder, { - $addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer, - }) => $$GroupTableTableAnnotationComposer( - $db: $db, - $table: $db.groupTable, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - ), - ); - return composer; - } - - $$MatchTableTableAnnotationComposer get matchId { - final $$MatchTableTableAnnotationComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.matchId, - referencedTable: $db.matchTable, - getReferencedColumn: (t) => t.id, - builder: - ( - joinBuilder, { - $addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer, - }) => $$MatchTableTableAnnotationComposer( - $db: $db, - $table: $db.matchTable, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - ), - ); - return composer; - } -} - -class $$GroupMatchTableTableTableManager - extends - RootTableManager< - _$AppDatabase, - $GroupMatchTableTable, - GroupMatchTableData, - $$GroupMatchTableTableFilterComposer, - $$GroupMatchTableTableOrderingComposer, - $$GroupMatchTableTableAnnotationComposer, - $$GroupMatchTableTableCreateCompanionBuilder, - $$GroupMatchTableTableUpdateCompanionBuilder, - (GroupMatchTableData, $$GroupMatchTableTableReferences), - GroupMatchTableData, - PrefetchHooks Function({bool groupId, bool matchId}) - > { - $$GroupMatchTableTableTableManager( - _$AppDatabase db, - $GroupMatchTableTable table, - ) : super( - TableManagerState( - db: db, - table: table, - createFilteringComposer: () => - $$GroupMatchTableTableFilterComposer($db: db, $table: table), - createOrderingComposer: () => - $$GroupMatchTableTableOrderingComposer($db: db, $table: table), - createComputedFieldComposer: () => - $$GroupMatchTableTableAnnotationComposer($db: db, $table: table), - updateCompanionCallback: - ({ - Value groupId = const Value.absent(), - Value matchId = const Value.absent(), - Value rowid = const Value.absent(), - }) => GroupMatchTableCompanion( - groupId: groupId, - matchId: matchId, - rowid: rowid, - ), - createCompanionCallback: - ({ - required String groupId, - required String matchId, - Value rowid = const Value.absent(), - }) => GroupMatchTableCompanion.insert( - groupId: groupId, - matchId: matchId, - rowid: rowid, - ), - withReferenceMapper: (p0) => p0 - .map( - (e) => ( - e.readTable(table), - $$GroupMatchTableTableReferences(db, table, e), - ), - ) - .toList(), - prefetchHooksCallback: ({groupId = false, matchId = false}) { - return PrefetchHooks( - db: db, - explicitlyWatchedTables: [], - addJoins: - < - T extends TableManagerState< - dynamic, - dynamic, - dynamic, - dynamic, - dynamic, - dynamic, - dynamic, - dynamic, - dynamic, - dynamic, - dynamic - > - >(state) { - if (groupId) { - state = - state.withJoin( - currentTable: table, - currentColumn: table.groupId, - referencedTable: - $$GroupMatchTableTableReferences - ._groupIdTable(db), - referencedColumn: - $$GroupMatchTableTableReferences - ._groupIdTable(db) - .id, - ) - as T; - } - if (matchId) { - state = - state.withJoin( - currentTable: table, - currentColumn: table.matchId, - referencedTable: - $$GroupMatchTableTableReferences - ._matchIdTable(db), - referencedColumn: - $$GroupMatchTableTableReferences - ._matchIdTable(db) - .id, - ) - as T; - } - - return state; - }, - getPrefetchedDataCallback: (items) async { - return []; - }, - ); - }, - ), - ); -} - -typedef $$GroupMatchTableTableProcessedTableManager = - ProcessedTableManager< - _$AppDatabase, - $GroupMatchTableTable, - GroupMatchTableData, - $$GroupMatchTableTableFilterComposer, - $$GroupMatchTableTableOrderingComposer, - $$GroupMatchTableTableAnnotationComposer, - $$GroupMatchTableTableCreateCompanionBuilder, - $$GroupMatchTableTableUpdateCompanionBuilder, - (GroupMatchTableData, $$GroupMatchTableTableReferences), - GroupMatchTableData, - PrefetchHooks Function({bool groupId, bool matchId}) - >; class $AppDatabaseManager { final _$AppDatabase _db; @@ -3833,12 +6175,16 @@ class $AppDatabaseManager { $$PlayerTableTableTableManager(_db, _db.playerTable); $$GroupTableTableTableManager get groupTable => $$GroupTableTableTableManager(_db, _db.groupTable); + $$GameTableTableTableManager get gameTable => + $$GameTableTableTableManager(_db, _db.gameTable); + $$TeamTableTableTableManager get teamTable => + $$TeamTableTableTableManager(_db, _db.teamTable); $$MatchTableTableTableManager get matchTable => $$MatchTableTableTableManager(_db, _db.matchTable); $$PlayerGroupTableTableTableManager get playerGroupTable => $$PlayerGroupTableTableTableManager(_db, _db.playerGroupTable); $$PlayerMatchTableTableTableManager get playerMatchTable => $$PlayerMatchTableTableTableManager(_db, _db.playerMatchTable); - $$GroupMatchTableTableTableManager get groupMatchTable => - $$GroupMatchTableTableTableManager(_db, _db.groupMatchTable); + $$ScoreTableTableTableManager get scoreTable => + $$ScoreTableTableTableManager(_db, _db.scoreTable); } From 40e970a5dcba5d64b346ef8cb6d6ddddfe6930ea Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 13:37:00 +0100 Subject: [PATCH 30/87] re-add winner parameter --- lib/data/dto/match.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/data/dto/match.dart b/lib/data/dto/match.dart index c91dc92..6963b4f 100644 --- a/lib/data/dto/match.dart +++ b/lib/data/dto/match.dart @@ -12,6 +12,7 @@ class Match { final Group? group; final List? players; final String? notes; + Player? winner; Match({ String? id, @@ -21,12 +22,13 @@ class Match { this.group, this.players, this.notes, + this.winner, }) : id = id ?? const Uuid().v4(), createdAt = createdAt ?? clock.now(); @override String toString() { - return 'Match{id: $id, name: $name, game: $game, group: $group, players: $players, notes: $notes}'; + return 'Match{id: $id, name: $name, game: $game, group: $group, players: $players, notes: $notes, winner: $winner}'; } /// Creates a Match instance from a JSON object. From 49e990dfea7b496db0a097fb9850d43466fa66dc Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 13:44:03 +0100 Subject: [PATCH 31/87] add TEMPORARY winner getter and setter methods to match_dao.dart --- lib/data/dao/match_dao.dart | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index 0c16a6b..696aff7 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -339,4 +339,40 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { ); return rowsAffected > 0; } + + // ============================================================ + // TEMPORARY: Winner methods - these are stubs and do not persist data + // TODO: Implement proper winner handling + // ============================================================ + + /// TEMPORARY: Checks if a match has a winner. + /// Currently returns true if the match has any players. + Future hasWinner({required String matchId}) async { + final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId); + return players?.isNotEmpty ?? false; + } + + /// TEMPORARY: Gets the winner of a match. + /// Currently returns the first player in the match's player list. + Future getWinner({required String matchId}) async { + final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId); + return (players?.isNotEmpty ?? false) ? players!.first : null; + } + + /// TEMPORARY: Sets the winner of a match. + /// Currently does nothing - winner is not persisted. + Future setWinner({ + required String matchId, + required String winnerId, + }) async { + // TODO: Implement winner persistence + return true; + } + + /// TEMPORARY: Removes the winner of a match. + /// Currently does nothing - winner is not persisted. + Future removeWinner({required String matchId}) async { + // TODO: Implement winner persistence + return true; + } } From 32fa82e5e7e31ef8667bb955d970af0649e090a7 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 13:53:57 +0100 Subject: [PATCH 32/87] check for game object on match create --- .../match_view/create_match/create_match_view.dart | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index b9885a4..64309dc 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -3,6 +3,7 @@ import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/core/enums.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/match.dart'; import 'package:game_tracker/data/dto/player.dart'; @@ -229,11 +230,20 @@ class _CreateMatchViewState extends State { buttonType: ButtonType.primary, onPressed: _enableCreateGameButton() ? () async { + final selectedGame = games[selectedGameIndex]; + final game = Game( + name: selectedGame.$1, + description: selectedGame.$2.isEmpty ? null : selectedGame.$2, + ruleset: selectedGame.$3.name, + ); + // Ensure the game exists in the database before creating the match + await db.gameDao.addGame(game: game); Match match = Match( name: _matchNameController.text.isEmpty ? (hintText ?? '') : _matchNameController.text.trim(), createdAt: DateTime.now(), + game: game, group: selectedGroup, players: selectedPlayers, ); @@ -263,10 +273,12 @@ class _CreateMatchViewState extends State { /// Determines whether the "Create Match" button should be enabled. /// /// Returns `true` if: + /// - A game is selected AND /// - A ruleset is selected AND /// - Either a group is selected OR at least 2 players are selected bool _enableCreateGameButton() { - return (selectedGroup != null || + return selectedGameIndex != -1 && + (selectedGroup != null || (selectedPlayers != null && selectedPlayers!.length > 1)) && selectedRuleset != null; } From a68bbddc1af1210151fdfebcd0496f1194a2352f Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 13:54:15 +0100 Subject: [PATCH 33/87] temporarily removed group_match_test.dart --- test/db_tests/group_match_test.dart | 221 ---------------------------- 1 file changed, 221 deletions(-) delete mode 100644 test/db_tests/group_match_test.dart diff --git a/test/db_tests/group_match_test.dart b/test/db_tests/group_match_test.dart deleted file mode 100644 index 7d812bd..0000000 --- a/test/db_tests/group_match_test.dart +++ /dev/null @@ -1,221 +0,0 @@ -import 'package:clock/clock.dart'; -import 'package:drift/drift.dart' hide isNotNull; -import 'package:drift/native.dart'; -import 'package:flutter_test/flutter_test.dart'; -import 'package:game_tracker/data/db/database.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'; - -void main() { - late AppDatabase database; - late Player testPlayer1; - late Player testPlayer2; - late Player testPlayer3; - late Player testPlayer4; - late Player testPlayer5; - late Group testGroup1; - late Group testGroup2; - late Match testMatchWithGroup; - late Match testMatchWithPlayers; - final fixedDate = DateTime(2025, 19, 11, 00, 11, 23); - final fakeClock = Clock(() => fixedDate); - - setUp(() async { - database = AppDatabase( - DatabaseConnection( - NativeDatabase.memory(), - // Recommended for widget tests to avoid test errors. - closeStreamsSynchronously: true, - ), - ); - - withClock(fakeClock, () { - testPlayer1 = Player(name: 'Alice'); - testPlayer2 = Player(name: 'Bob'); - testPlayer3 = Player(name: 'Charlie'); - testPlayer4 = Player(name: 'Diana'); - testPlayer5 = Player(name: 'Eve'); - testGroup1 = Group( - name: 'Test Group', - members: [testPlayer1, testPlayer2, testPlayer3], - ); - testGroup2 = Group( - name: 'Test Group', - members: [testPlayer3, testPlayer2], - ); - testMatchWithPlayers = Match( - name: 'Test Match with Players', - players: [testPlayer4, testPlayer5], - ); - testMatchWithGroup = Match( - name: 'Test Match with Group', - group: testGroup1, - ); - }); - await database.playerDao.addPlayersAsList( - players: [ - testPlayer1, - testPlayer2, - testPlayer3, - testPlayer4, - testPlayer5, - ], - ); - await database.groupDao.addGroupsAsList(groups: [testGroup1, testGroup2]); - }); - tearDown(() async { - await database.close(); - }); - group('Group-Match Tests', () { - test('matchHasGroup() has group works correctly', () async { - await database.matchDao.addMatch(match: testMatchWithPlayers); - await database.groupDao.addGroup(group: testGroup1); - - var matchHasGroup = await database.groupMatchDao.matchHasGroup( - matchId: testMatchWithPlayers.id, - ); - - expect(matchHasGroup, false); - - await database.groupMatchDao.addGroupToMatch( - matchId: testMatchWithPlayers.id, - groupId: testGroup1.id, - ); - - matchHasGroup = await database.groupMatchDao.matchHasGroup( - matchId: testMatchWithPlayers.id, - ); - - expect(matchHasGroup, true); - }); - - test('Adding a group to a match works correctly', () async { - await database.matchDao.addMatch(match: testMatchWithPlayers); - await database.groupDao.addGroup(group: testGroup1); - await database.groupMatchDao.addGroupToMatch( - matchId: testMatchWithPlayers.id, - groupId: testGroup1.id, - ); - - var groupAdded = await database.groupMatchDao.isGroupInMatch( - matchId: testMatchWithPlayers.id, - groupId: testGroup1.id, - ); - expect(groupAdded, true); - - groupAdded = await database.groupMatchDao.isGroupInMatch( - matchId: testMatchWithPlayers.id, - groupId: '', - ); - expect(groupAdded, false); - }); - - test('Removing group from match works correctly', () async { - await database.matchDao.addMatch(match: testMatchWithGroup); - - final groupToRemove = testMatchWithGroup.group!; - - final removed = await database.groupMatchDao.removeGroupFromMatch( - groupId: groupToRemove.id, - matchId: testMatchWithGroup.id, - ); - expect(removed, true); - - final result = await database.matchDao.getMatchById( - matchId: testMatchWithGroup.id, - ); - expect(result.group, null); - }); - - test('Retrieving group of a match works correctly', () async { - await database.matchDao.addMatch(match: testMatchWithGroup); - final group = await database.groupMatchDao.getGroupOfMatch( - matchId: testMatchWithGroup.id, - ); - - if (group == null) { - fail('Group should not be null'); - } - - expect(group.id, testGroup1.id); - expect(group.name, testGroup1.name); - expect(group.createdAt, testGroup1.createdAt); - expect(group.members.length, testGroup1.members.length); - for (int i = 0; i < group.members.length; i++) { - expect(group.members[i].id, testGroup1.members[i].id); - expect(group.members[i].name, testGroup1.members[i].name); - expect(group.members[i].createdAt, testGroup1.members[i].createdAt); - } - }); - - test('Updating the group of a match works correctly', () async { - await database.matchDao.addMatch(match: testMatchWithGroup); - - var group = await database.groupMatchDao.getGroupOfMatch( - matchId: testMatchWithGroup.id, - ); - - if (group == null) { - fail('Initial group should not be null'); - } else { - expect(group.id, testGroup1.id); - expect(group.name, testGroup1.name); - expect(group.createdAt, testGroup1.createdAt); - expect(group.members.length, testGroup1.members.length); - } - - await database.groupDao.addGroup(group: testGroup2); - await database.groupMatchDao.updateGroupOfMatch( - matchId: testMatchWithGroup.id, - newGroupId: testGroup2.id, - ); - - group = await database.groupMatchDao.getGroupOfMatch( - matchId: testMatchWithGroup.id, - ); - - if (group == null) { - fail('Updated group should not be null'); - } else { - expect(group.id, testGroup2.id); - expect(group.name, testGroup2.name); - expect(group.createdAt, testGroup2.createdAt); - expect(group.members.length, testGroup2.members.length); - for (int i = 0; i < group.members.length; i++) { - expect(group.members[i].id, testGroup2.members[i].id); - expect(group.members[i].name, testGroup2.members[i].name); - expect(group.members[i].createdAt, testGroup2.members[i].createdAt); - } - } - }); - - test('Adding the same group to seperate matches works correctly', () async { - final match1 = Match(name: 'Match 1', group: testGroup1); - final match2 = Match(name: 'Match 2', group: testGroup1); - - await Future.wait([ - database.matchDao.addMatch(match: match1), - database.matchDao.addMatch(match: match2), - ]); - - final group1 = await database.groupMatchDao.getGroupOfMatch( - matchId: match1.id, - ); - final group2 = await database.groupMatchDao.getGroupOfMatch( - matchId: match2.id, - ); - - expect(group1, isNotNull); - expect(group2, isNotNull); - - final groups = [group1!, group2!]; - for (final group in groups) { - expect(group.members.length, testGroup1.members.length); - expect(group.id, testGroup1.id); - expect(group.name, testGroup1.name); - expect(group.createdAt, testGroup1.createdAt); - } - }); - }); -} From d21c37966eed8b926e1817d556004901c9743d41 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 14:15:55 +0100 Subject: [PATCH 34/87] tests create testGame now --- test/db_tests/game_test.dart | 8 ++++++++ test/db_tests/player_match_test.dart | 14 ++++++++++---- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/test/db_tests/game_test.dart b/test/db_tests/game_test.dart index 0ec2cfc..c52817f 100644 --- a/test/db_tests/game_test.dart +++ b/test/db_tests/game_test.dart @@ -3,6 +3,7 @@ import 'package:drift/drift.dart'; import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.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/match.dart'; import 'package:game_tracker/data/dto/player.dart'; @@ -16,6 +17,7 @@ void main() { late Player testPlayer5; late Group testGroup1; late Group testGroup2; + late Game testGame; late Match testMatch1; late Match testMatch2; late Match testMatchOnlyPlayers; @@ -46,25 +48,30 @@ void main() { name: 'Test Group 2', members: [testPlayer4, testPlayer5], ); + testGame = Game(name: 'Test Game'); testMatch1 = Match( name: 'First Test Match', + game: testGame, group: testGroup1, players: [testPlayer4, testPlayer5], winner: testPlayer4, ); testMatch2 = Match( name: 'Second Test Match', + game: testGame, group: testGroup2, players: [testPlayer1, testPlayer2, testPlayer3], winner: testPlayer2, ); testMatchOnlyPlayers = Match( name: 'Test Match with Players', + game: testGame, players: [testPlayer1, testPlayer2, testPlayer3], winner: testPlayer3, ); testMatchOnlyGroup = Match( name: 'Test Match with Group', + game: testGame, group: testGroup2, ); }); @@ -78,6 +85,7 @@ void main() { ], ); await database.groupDao.addGroupsAsList(groups: [testGroup1, testGroup2]); + await database.gameDao.addGame(game: testGame); }); tearDown(() async { await database.close(); diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/player_match_test.dart index 8a4f569..8fa8a88 100644 --- a/test/db_tests/player_match_test.dart +++ b/test/db_tests/player_match_test.dart @@ -3,6 +3,7 @@ import 'package:drift/drift.dart' hide isNotNull; import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.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/match.dart'; import 'package:game_tracker/data/dto/player.dart'; @@ -15,7 +16,8 @@ void main() { late Player testPlayer4; late Player testPlayer5; late Player testPlayer6; - late Group testgroup; + late Group testGroup; + late Game testGame; late Match testMatchOnlyGroup; late Match testMatchOnlyPlayers; final fixedDate = DateTime(2025, 19, 11, 00, 11, 23); @@ -37,16 +39,19 @@ void main() { testPlayer4 = Player(name: 'Diana'); testPlayer5 = Player(name: 'Eve'); testPlayer6 = Player(name: 'Frank'); - testgroup = Group( + testGroup = Group( name: 'Test Group', members: [testPlayer1, testPlayer2, testPlayer3], ); + testGame = Game(name: 'Test Game'); testMatchOnlyGroup = Match( name: 'Test Match with Group', - group: testgroup, + game: testGame, + group: testGroup, ); testMatchOnlyPlayers = Match( name: 'Test Match with Players', + game: testGame, players: [testPlayer4, testPlayer5, testPlayer6], ); }); @@ -60,7 +65,8 @@ void main() { testPlayer6, ], ); - await database.groupDao.addGroup(group: testgroup); + await database.groupDao.addGroup(group: testGroup); + await database.gameDao.addGame(game: testGame); }); tearDown(() async { await database.close(); From 6a6e36ed7cdbb7ab4da57c7e2777f75ceee3a9bf Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 16 Jan 2026 15:55:17 +0100 Subject: [PATCH 35/87] remove pair --- lib/data/dto/pair.dart | 16 ---------------- 1 file changed, 16 deletions(-) delete mode 100644 lib/data/dto/pair.dart diff --git a/lib/data/dto/pair.dart b/lib/data/dto/pair.dart deleted file mode 100644 index 2cce9f8..0000000 --- a/lib/data/dto/pair.dart +++ /dev/null @@ -1,16 +0,0 @@ -import 'package:game_tracker/data/dto/team.dart'; - -class Pair extends Team { - Pair({ - super.id, - super.createdAt, - required super.members, - }); - - @override - String toString() { - return 'Pair{id: $id, members: $members}'; - } - -} - From 715b3debbbc03abed6e50f7fc2dee1d723e7b382 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 19 Jan 2026 14:18:59 +0100 Subject: [PATCH 36/87] add updateGroupDescription --- lib/data/dao/group_dao.dart | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/lib/data/dao/group_dao.dart b/lib/data/dao/group_dao.dart index 999200d..beecc9d 100644 --- a/lib/data/dao/group_dao.dart +++ b/lib/data/dao/group_dao.dart @@ -181,7 +181,7 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { /// Updates the name of the group with the given [id] to [newName]. /// Returns `true` if more than 0 rows were affected, otherwise `false`. - Future updateGroupname({ + Future updateGroupName({ required String groupId, required String newName, }) async { @@ -192,6 +192,21 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { return rowsAffected > 0; } + /// Updates the description of the group with the given [groupId] to [newDescription]. + /// Returns `true` if more than 0 rows were affected, otherwise `false`. + Future updateGroupDescription({ + required String groupId, + required String? newDescription, + }) async { + final rowsAffected = + await (update(groupTable)..where((g) => g.id.equals(groupId))).write( + GroupTableCompanion(description: Value(newDescription)), + ); + return rowsAffected > 0; + } + + + /// Retrieves the number of groups in the database. Future getGroupCount() async { final count = From 764ce13240c24652de97c2a0b8f8aa70bcaff9d5 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 19 Jan 2026 14:57:19 +0100 Subject: [PATCH 37/87] fix felix typos :) --- lib/data/dao/player_dao.dart | 2 +- test/db_tests/group_test.dart | 2 +- test/db_tests/player_group_test.dart | 32 ++++++++++++++-------------- test/db_tests/player_match_test.dart | 4 ++-- test/db_tests/player_test.dart | 6 +++--- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/lib/data/dao/player_dao.dart b/lib/data/dao/player_dao.dart index 40c5c98..b8b5000 100644 --- a/lib/data/dao/player_dao.dart +++ b/lib/data/dao/player_dao.dart @@ -99,7 +99,7 @@ class PlayerDao extends DatabaseAccessor with _$PlayerDaoMixin { } /// Updates the name of the player with the given [playerId] to [newName]. - Future updatePlayername({ + Future updatePlayerName({ required String playerId, required String newName, }) async { diff --git a/test/db_tests/group_test.dart b/test/db_tests/group_test.dart index 5104c65..08f8379 100644 --- a/test/db_tests/group_test.dart +++ b/test/db_tests/group_test.dart @@ -145,7 +145,7 @@ void main() { const newGroupName = 'new group name'; - await database.groupDao.updateGroupname( + await database.groupDao.updateGroupName( groupId: testGroup1.id, newName: newGroupName, ); diff --git a/test/db_tests/player_group_test.dart b/test/db_tests/player_group_test.dart index 2783430..344567c 100644 --- a/test/db_tests/player_group_test.dart +++ b/test/db_tests/player_group_test.dart @@ -12,7 +12,7 @@ void main() { late Player testPlayer2; late Player testPlayer3; late Player testPlayer4; - late Group testgroup; + late Group testGroup; final fixedDate = DateTime(2025, 19, 11, 00, 11, 23); final fakeClock = Clock(() => fixedDate); @@ -30,7 +30,7 @@ void main() { testPlayer2 = Player(name: 'Bob'); testPlayer3 = Player(name: 'Charlie'); testPlayer4 = Player(name: 'Diana'); - testgroup = Group( + testGroup = Group( name: 'Test Group', members: [testPlayer1, testPlayer2, testPlayer3], ); @@ -45,22 +45,22 @@ void main() { /// not nullable test('Adding a player to a group works correctly', () async { - await database.groupDao.addGroup(group: testgroup); + await database.groupDao.addGroup(group: testGroup); await database.playerDao.addPlayer(player: testPlayer4); await database.playerGroupDao.addPlayerToGroup( - groupId: testgroup.id, + groupId: testGroup.id, player: testPlayer4, ); var playerAdded = await database.playerGroupDao.isPlayerInGroup( - groupId: testgroup.id, + groupId: testGroup.id, playerId: testPlayer4.id, ); expect(playerAdded, true); playerAdded = await database.playerGroupDao.isPlayerInGroup( - groupId: testgroup.id, + groupId: testGroup.id, playerId: '', ); @@ -68,35 +68,35 @@ void main() { }); test('Removing player from group works correctly', () async { - await database.groupDao.addGroup(group: testgroup); + await database.groupDao.addGroup(group: testGroup); - final playerToRemove = testgroup.members[0]; + final playerToRemove = testGroup.members[0]; final removed = await database.playerGroupDao.removePlayerFromGroup( playerId: playerToRemove.id, - groupId: testgroup.id, + groupId: testGroup.id, ); expect(removed, true); final result = await database.groupDao.getGroupById( - groupId: testgroup.id, + groupId: testGroup.id, ); - expect(result.members.length, testgroup.members.length - 1); + expect(result.members.length, testGroup.members.length - 1); final playerExists = result.members.any((p) => p.id == playerToRemove.id); expect(playerExists, false); }); test('Retrieving players of a group works correctly', () async { - await database.groupDao.addGroup(group: testgroup); + await database.groupDao.addGroup(group: testGroup); final players = await database.playerGroupDao.getPlayersOfGroup( - groupId: testgroup.id, + groupId: testGroup.id, ); for (int i = 0; i < players.length; i++) { - expect(players[i].id, testgroup.members[i].id); - expect(players[i].name, testgroup.members[i].name); - expect(players[i].createdAt, testgroup.members[i].createdAt); + expect(players[i].id, testGroup.members[i].id); + expect(players[i].name, testGroup.members[i].name); + expect(players[i].createdAt, testGroup.members[i].createdAt); } }); }); diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/player_match_test.dart index 8fa8a88..d7d3bde 100644 --- a/test/db_tests/player_match_test.dart +++ b/test/db_tests/player_match_test.dart @@ -160,7 +160,7 @@ void main() { } }); - test('Updating the match players works coreclty', () async { + test('Updating the match players works correctly', () async { await database.matchDao.addMatch(match: testMatchOnlyPlayers); final newPlayers = [testPlayer1, testPlayer2, testPlayer4]; @@ -204,7 +204,7 @@ void main() { }); test( - 'Adding the same player to seperate matches works correctly', + 'Adding the same player to separate matches works correctly', () async { final playersList = [testPlayer1, testPlayer2, testPlayer3]; final match1 = Match(name: 'Match 1', players: playersList); diff --git a/test/db_tests/player_test.dart b/test/db_tests/player_test.dart index 5bd10ad..a6d1b93 100644 --- a/test/db_tests/player_test.dart +++ b/test/db_tests/player_test.dart @@ -63,7 +63,7 @@ void main() { final allPlayers = await database.playerDao.getAllPlayers(); expect(allPlayers.length, 4); - // Map for connencting fetched players with expected players + // Map for connecting fetched players with expected players final testPlayers = { testPlayer1.id: testPlayer1, testPlayer2.id: testPlayer2, @@ -115,12 +115,12 @@ void main() { expect(playerExists, false); }); - test('Updating a player name works correcly', () async { + test('Updating a player name works correctly', () async { await database.playerDao.addPlayer(player: testPlayer1); const newPlayerName = 'new player name'; - await database.playerDao.updatePlayername( + await database.playerDao.updatePlayerName( playerId: testPlayer1.id, newName: newPlayerName, ); From c97fdc2b5facc94003d773f7322229d7904b1bf0 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 19 Jan 2026 14:58:33 +0100 Subject: [PATCH 38/87] add match method to change created at --- lib/data/dao/match_dao.dart | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index 696aff7..7c67e08 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -340,6 +340,19 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { return rowsAffected > 0; } + /// Updates the createdAt timestamp of the match with the given [matchId]. + /// Returns `true` if more than 0 rows were affected, otherwise `false`. + Future updateMatchCreatedAt({ + required String matchId, + required DateTime createdAt, + }) async { + final query = update(matchTable)..where((g) => g.id.equals(matchId)); + final rowsAffected = await query.write( + MatchTableCompanion(createdAt: Value(createdAt)), + ); + return rowsAffected > 0; + } + // ============================================================ // TEMPORARY: Winner methods - these are stubs and do not persist data // TODO: Implement proper winner handling From 8dd2f5f8b89b802d26812ca7c95685eaa7c311b2 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 19 Jan 2026 15:46:25 +0100 Subject: [PATCH 39/87] add name to team --- lib/data/dao/team_dao.dart | 6 ++++-- lib/data/dto/team.dart | 6 +++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/data/dao/team_dao.dart b/lib/data/dao/team_dao.dart index a382643..6a40d03 100644 --- a/lib/data/dao/team_dao.dart +++ b/lib/data/dao/team_dao.dart @@ -20,6 +20,7 @@ class TeamDao extends DatabaseAccessor with _$TeamDaoMixin { final members = await _getTeamMembers(teamId: row.id); return Team( id: row.id, + name: row.name, createdAt: row.createdAt, members: members, ); @@ -34,6 +35,7 @@ class TeamDao extends DatabaseAccessor with _$TeamDaoMixin { final members = await _getTeamMembers(teamId: teamId); return Team( id: result.id, + name: result.name, createdAt: result.createdAt, members: members, ); @@ -66,7 +68,7 @@ class TeamDao extends DatabaseAccessor with _$TeamDaoMixin { await into(teamTable).insert( TeamTableCompanion.insert( id: team.id, - name: '', // Team name from table (not in DTO currently) + name: team.name, createdAt: team.createdAt, ), mode: InsertMode.insertOrReplace, @@ -87,7 +89,7 @@ class TeamDao extends DatabaseAccessor with _$TeamDaoMixin { .map( (team) => TeamTableCompanion.insert( id: team.id, - name: '', + name: team.name, createdAt: team.createdAt, ), ) diff --git a/lib/data/dto/team.dart b/lib/data/dto/team.dart index 8b015ba..a3f78d5 100644 --- a/lib/data/dto/team.dart +++ b/lib/data/dto/team.dart @@ -4,11 +4,13 @@ import 'package:uuid/uuid.dart'; class Team { final String id; + final String name; final DateTime createdAt; final List members; Team({ String? id, + required this.name, DateTime? createdAt, required this.members, }) : id = id ?? const Uuid().v4(), @@ -16,12 +18,13 @@ class Team { @override String toString() { - return 'Team{id: $id, members: $members}'; + return 'Team{id: $id, name: $name, members: $members}'; } /// Creates a Team instance from a JSON object. Team.fromJson(Map json) : id = json['id'], + name = json['name'], createdAt = DateTime.parse(json['createdAt']), members = (json['members'] as List) .map((memberJson) => Player.fromJson(memberJson)) @@ -30,6 +33,7 @@ class Team { /// Converts the Team instance to a JSON object. Map toJson() => { 'id': id, + 'name': name, 'createdAt': createdAt.toIso8601String(), 'members': members.map((member) => member.toJson()).toList(), }; From fb59372c97ec18d92b4ac4683571f53e22fd330b Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 19 Jan 2026 19:51:48 +0100 Subject: [PATCH 40/87] add score_test.dart --- test/db_tests/score_test.dart | 417 ++++++++++++++++++++++++++++++++++ 1 file changed, 417 insertions(+) create mode 100644 test/db_tests/score_test.dart diff --git a/test/db_tests/score_test.dart b/test/db_tests/score_test.dart new file mode 100644 index 0000000..4f6aa99 --- /dev/null +++ b/test/db_tests/score_test.dart @@ -0,0 +1,417 @@ +import 'package:clock/clock.dart'; +import 'package:drift/drift.dart' hide isNull, isNotNull; +import 'package:drift/native.dart'; +import 'package:flutter_test/flutter_test.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'; + +void main() { + late AppDatabase database; + late Player testPlayer1; + late Player testPlayer2; + late Player testPlayer3; + late Game testGame; + late Match testMatch1; + late Match testMatch2; + final fixedDate = DateTime(2025, 19, 11, 00, 11, 23); + final fakeClock = Clock(() => fixedDate); + + setUp(() async { + database = AppDatabase( + DatabaseConnection( + NativeDatabase.memory(), + // Recommended for widget tests to avoid test errors. + closeStreamsSynchronously: true, + ), + ); + + withClock(fakeClock, () { + testPlayer1 = Player(name: 'Alice'); + testPlayer2 = Player(name: 'Bob'); + testPlayer3 = Player(name: 'Charlie'); + testGame = Game(name: 'Test Game'); + testMatch1 = Match( + name: 'Test Match 1', + game: testGame, + players: [testPlayer1, testPlayer2], + ); + testMatch2 = Match( + name: 'Test Match 2', + game: testGame, + players: [testPlayer2, testPlayer3], + ); + }); + + await database.playerDao.addPlayersAsList( + players: [testPlayer1, testPlayer2, testPlayer3], + ); + await database.gameDao.addGame(game: testGame); + await database.matchDao.addMatch(match: testMatch1); + await database.matchDao.addMatch(match: testMatch2); + }); + + tearDown(() async { + await database.close(); + }); + + group('Score Tests', () { + test('Adding and fetching a score works correctly', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + + final score = await database.scoreDao.getScoreForRound( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + ); + + expect(score, isNotNull); + expect(score!.playerId, testPlayer1.id); + expect(score.matchId, testMatch1.id); + expect(score.roundNumber, 1); + expect(score.score, 10); + expect(score.change, 10); + }); + + test('Getting scores for a match works correctly', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + await database.scoreDao.addScore( + playerId: testPlayer2.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 20, + change: 20, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 2, + score: 25, + change: 15, + ); + + final scores = await database.scoreDao.getScoresForMatch( + matchId: testMatch1.id, + ); + + expect(scores.length, 3); + }); + + test('Getting player scores in a match works correctly', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 2, + score: 25, + change: 15, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 3, + score: 30, + change: 5, + ); + + final playerScores = await database.scoreDao.getPlayerScoresInMatch( + playerId: testPlayer1.id, + matchId: testMatch1.id, + ); + + expect(playerScores.length, 3); + expect(playerScores[0].roundNumber, 1); + expect(playerScores[1].roundNumber, 2); + expect(playerScores[2].roundNumber, 3); + expect(playerScores[0].score, 10); + expect(playerScores[1].score, 25); + expect(playerScores[2].score, 30); + }); + + test('Getting score for a non-existent round returns null', () async { + final score = await database.scoreDao.getScoreForRound( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 999, + ); + + expect(score, isNull); + }); + + test('Updating a score works correctly', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + + final updated = await database.scoreDao.updateScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + newScore: 50, + newChange: 40, + ); + + expect(updated, true); + + final score = await database.scoreDao.getScoreForRound( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + ); + + expect(score, isNotNull); + expect(score!.score, 50); + expect(score.change, 40); + }); + + test('Updating a non-existent score returns false', () async { + final updated = await database.scoreDao.updateScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 999, + newScore: 50, + newChange: 40, + ); + + expect(updated, false); + }); + + test('Deleting a score works correctly', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + + final deleted = await database.scoreDao.deleteScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + ); + + expect(deleted, true); + + final score = await database.scoreDao.getScoreForRound( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + ); + + expect(score, isNull); + }); + + test('Deleting a non-existent score returns false', () async { + final deleted = await database.scoreDao.deleteScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 999, + ); + + expect(deleted, false); + }); + + test('Deleting scores for a match works correctly', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + await database.scoreDao.addScore( + playerId: testPlayer2.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 20, + change: 20, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch2.id, + roundNumber: 1, + score: 15, + change: 15, + ); + + final deleted = await database.scoreDao.deleteScoresForMatch( + matchId: testMatch1.id, + ); + + expect(deleted, true); + + final match1Scores = await database.scoreDao.getScoresForMatch( + matchId: testMatch1.id, + ); + expect(match1Scores.length, 0); + + final match2Scores = await database.scoreDao.getScoresForMatch( + matchId: testMatch2.id, + ); + expect(match2Scores.length, 1); + }); + + test('Deleting scores for a player works correctly', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch2.id, + roundNumber: 1, + score: 15, + change: 15, + ); + await database.scoreDao.addScore( + playerId: testPlayer2.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 20, + change: 20, + ); + + final deleted = await database.scoreDao.deleteScoresForPlayer( + playerId: testPlayer1.id, + ); + + expect(deleted, true); + + final player1Scores = await database.scoreDao.getPlayerScoresInMatch( + playerId: testPlayer1.id, + matchId: testMatch1.id, + ); + expect(player1Scores.length, 0); + + final player2Scores = await database.scoreDao.getPlayerScoresInMatch( + playerId: testPlayer2.id, + matchId: testMatch1.id, + ); + expect(player2Scores.length, 1); + }); + + test('Getting latest round number works correctly', () async { + var latestRound = await database.scoreDao.getLatestRoundNumber( + matchId: testMatch1.id, + ); + expect(latestRound, 0); + + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + + latestRound = await database.scoreDao.getLatestRoundNumber( + matchId: testMatch1.id, + ); + expect(latestRound, 1); + + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 5, + score: 50, + change: 40, + ); + + latestRound = await database.scoreDao.getLatestRoundNumber( + matchId: testMatch1.id, + ); + expect(latestRound, 5); + }); + + test('Getting total score for a player works correctly', () async { + var totalScore = await database.scoreDao.getTotalScoreForPlayer( + playerId: testPlayer1.id, + matchId: testMatch1.id, + ); + expect(totalScore, 0); + + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 2, + score: 25, + change: 15, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 3, + score: 40, + change: 15, + ); + + totalScore = await database.scoreDao.getTotalScoreForPlayer( + playerId: testPlayer1.id, + matchId: testMatch1.id, + ); + expect(totalScore, 40); + }); + + test('Adding the same score twice replaces the existing one', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 99, + change: 99, + ); + + final score = await database.scoreDao.getScoreForRound( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + ); + + expect(score, isNotNull); + expect(score!.score, 99); + expect(score.change, 99); + }); + }); +} + From 25e0c75dc684808f96ad4f52b83f8f5ae11beb81 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 19 Jan 2026 19:52:00 +0100 Subject: [PATCH 41/87] add team_test.dart.dart --- test/db_tests/team_test.dart | 226 +++++++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 test/db_tests/team_test.dart diff --git a/test/db_tests/team_test.dart b/test/db_tests/team_test.dart new file mode 100644 index 0000000..2f3c5d9 --- /dev/null +++ b/test/db_tests/team_test.dart @@ -0,0 +1,226 @@ +import 'package:clock/clock.dart'; +import 'package:drift/drift.dart'; +import 'package:drift/native.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:game_tracker/data/db/database.dart'; +import 'package:game_tracker/data/dto/player.dart'; +import 'package:game_tracker/data/dto/team.dart'; + +void main() { + late AppDatabase database; + late Player testPlayer1; + late Player testPlayer2; + late Player testPlayer3; + late Player testPlayer4; + late Team testTeam1; + late Team testTeam2; + late Team testTeam3; + final fixedDate = DateTime(2025, 19, 11, 00, 11, 23); + final fakeClock = Clock(() => fixedDate); + + setUp(() async { + database = AppDatabase( + DatabaseConnection( + NativeDatabase.memory(), + // Recommended for widget tests to avoid test errors. + closeStreamsSynchronously: true, + ), + ); + + withClock(fakeClock, () { + testPlayer1 = Player(name: 'Alice'); + testPlayer2 = Player(name: 'Bob'); + testPlayer3 = Player(name: 'Charlie'); + testPlayer4 = Player(name: 'Diana'); + testTeam1 = Team( + name: 'Team Alpha', + members: [testPlayer1, testPlayer2], + ); + testTeam2 = Team( + name: 'Team Beta', + members: [testPlayer3, testPlayer4], + ); + testTeam3 = Team( + name: 'Team Gamma', + members: [testPlayer1, testPlayer3], + ); + }); + + await database.playerDao.addPlayersAsList( + players: [testPlayer1, testPlayer2, testPlayer3, testPlayer4], + ); + }); + + tearDown(() async { + await database.close(); + }); + + group('Team Tests', () { + test('Adding and fetching a single team works correctly', () async { + final added = await database.teamDao.addTeam(team: testTeam1); + expect(added, true); + + final fetchedTeam = await database.teamDao.getTeamById( + teamId: testTeam1.id, + ); + + expect(fetchedTeam.id, testTeam1.id); + expect(fetchedTeam.name, testTeam1.name); + expect(fetchedTeam.createdAt, testTeam1.createdAt); + }); + + test('Adding and fetching multiple teams works correctly', () async { + await database.teamDao.addTeamsAsList( + teams: [testTeam1, testTeam2, testTeam3], + ); + + final allTeams = await database.teamDao.getAllTeams(); + expect(allTeams.length, 3); + + final testTeams = { + testTeam1.id: testTeam1, + testTeam2.id: testTeam2, + testTeam3.id: testTeam3, + }; + + for (final team in allTeams) { + final testTeam = testTeams[team.id]!; + + expect(team.id, testTeam.id); + expect(team.name, testTeam.name); + expect(team.createdAt, testTeam.createdAt); + } + }); + + test('Adding the same team twice does not create duplicates', () async { + await database.teamDao.addTeam(team: testTeam1); + final addedAgain = await database.teamDao.addTeam(team: testTeam1); + + expect(addedAgain, false); + + final teamCount = await database.teamDao.getTeamCount(); + expect(teamCount, 1); + }); + + test('Team existence check works correctly', () async { + var teamExists = await database.teamDao.teamExists(teamId: testTeam1.id); + expect(teamExists, false); + + await database.teamDao.addTeam(team: testTeam1); + + teamExists = await database.teamDao.teamExists(teamId: testTeam1.id); + expect(teamExists, true); + }); + + test('Deleting a team works correctly', () async { + await database.teamDao.addTeam(team: testTeam1); + + final teamDeleted = await database.teamDao.deleteTeam( + teamId: testTeam1.id, + ); + expect(teamDeleted, true); + + final teamExists = await database.teamDao.teamExists( + teamId: testTeam1.id, + ); + expect(teamExists, false); + }); + + test('Deleting a non-existent team returns false', () async { + final teamDeleted = await database.teamDao.deleteTeam( + teamId: 'non-existent-id', + ); + expect(teamDeleted, false); + }); + + test('Getting the team count works correctly', () async { + var teamCount = await database.teamDao.getTeamCount(); + expect(teamCount, 0); + + await database.teamDao.addTeam(team: testTeam1); + + teamCount = await database.teamDao.getTeamCount(); + expect(teamCount, 1); + + await database.teamDao.addTeam(team: testTeam2); + + teamCount = await database.teamDao.getTeamCount(); + expect(teamCount, 2); + + await database.teamDao.deleteTeam(teamId: testTeam1.id); + + teamCount = await database.teamDao.getTeamCount(); + expect(teamCount, 1); + + await database.teamDao.deleteTeam(teamId: testTeam2.id); + + teamCount = await database.teamDao.getTeamCount(); + expect(teamCount, 0); + }); + + test('Updating team name works correctly', () async { + await database.teamDao.addTeam(team: testTeam1); + + var fetchedTeam = await database.teamDao.getTeamById( + teamId: testTeam1.id, + ); + expect(fetchedTeam.name, testTeam1.name); + + const newName = 'Updated Team Name'; + await database.teamDao.updateTeamName( + teamId: testTeam1.id, + newName: newName, + ); + + fetchedTeam = await database.teamDao.getTeamById(teamId: testTeam1.id); + expect(fetchedTeam.name, newName); + }); + + test('Deleting all teams works correctly', () async { + await database.teamDao.addTeamsAsList( + teams: [testTeam1, testTeam2, testTeam3], + ); + + var teamCount = await database.teamDao.getTeamCount(); + expect(teamCount, 3); + + final deleted = await database.teamDao.deleteAllTeams(); + expect(deleted, true); + + teamCount = await database.teamDao.getTeamCount(); + expect(teamCount, 0); + }); + + test('Deleting all teams when empty returns false', () async { + final deleted = await database.teamDao.deleteAllTeams(); + expect(deleted, false); + }); + + test('Adding teams as list with empty list returns false', () async { + final added = await database.teamDao.addTeamsAsList(teams: []); + expect(added, false); + }); + + test('Adding teams with duplicate IDs ignores duplicates', () async { + final duplicateTeam = Team( + id: testTeam1.id, + name: 'Duplicate Team', + members: [testPlayer4], + ); + + await database.teamDao.addTeamsAsList( + teams: [testTeam1, duplicateTeam, testTeam2], + ); + + final teamCount = await database.teamDao.getTeamCount(); + expect(teamCount, 2); + + // The first one should be kept (insertOrIgnore) + final fetchedTeam = await database.teamDao.getTeamById( + teamId: testTeam1.id, + ); + expect(fetchedTeam.name, testTeam1.name); + }); + }); +} + From 4e73babb710af623cf2c5094db6fe9819f8488a1 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Tue, 20 Jan 2026 15:28:26 +0100 Subject: [PATCH 42/87] rename game_test to match_test --- test/db_tests/{game_test.dart => match_test.dart} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename test/db_tests/{game_test.dart => match_test.dart} (100%) diff --git a/test/db_tests/game_test.dart b/test/db_tests/match_test.dart similarity index 100% rename from test/db_tests/game_test.dart rename to test/db_tests/match_test.dart From dec74e9b627712fcf7017300c63c23826b5c90c2 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Tue, 20 Jan 2026 15:41:05 +0100 Subject: [PATCH 43/87] add game tests --- test/db_tests/game_test.dart | 522 +++++++++++++++++++++++++++++++++++ 1 file changed, 522 insertions(+) create mode 100644 test/db_tests/game_test.dart diff --git a/test/db_tests/game_test.dart b/test/db_tests/game_test.dart new file mode 100644 index 0000000..924e673 --- /dev/null +++ b/test/db_tests/game_test.dart @@ -0,0 +1,522 @@ +import 'package:clock/clock.dart'; +import 'package:drift/drift.dart' hide isNull; +import 'package:drift/native.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:game_tracker/data/db/database.dart'; +import 'package:game_tracker/data/dto/game.dart'; + +void main() { + late AppDatabase database; + late Game testGame1; + late Game testGame2; + late Game testGame3; + final fixedDate = DateTime(2025, 11, 19, 00, 11, 23); + final fakeClock = Clock(() => fixedDate); + + setUp(() { + database = AppDatabase( + DatabaseConnection( + NativeDatabase.memory(), + closeStreamsSynchronously: true, + ), + ); + + withClock(fakeClock, () { + testGame1 = Game( + name: 'Chess', + ruleset: 'winner.single', + description: 'A classic strategy game', + color: 0xFF0000FF, + icon: 'chess_icon', + ); + testGame2 = Game( + id: 'game2', + name: 'Poker', + ruleset: 'Texas Hold\'em rules', + description: 'winner.multiple', + color: 0xFFFF0000, + icon: 'poker_icon', + ); + testGame3 = Game( + id: 'game3', + name: 'Monopoly', + description: 'A board game about real estate', + ); + }); + }); + + tearDown(() async { + await database.close(); + }); + + group('Game Tests', () { + // ==================== getAllGames ==================== + test('getAllGames returns empty list when no games exist', () async { + final allGames = await database.gameDao.getAllGames(); + expect(allGames, isEmpty); + }); + + test('Adding and fetching a single game works correctly', () async { + await database.gameDao.addGame(game: testGame1); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames.length, 1); + expect(allGames.first.id, testGame1.id); + expect(allGames.first.name, testGame1.name); + expect(allGames.first.ruleset, testGame1.ruleset); + expect(allGames.first.description, testGame1.description); + expect(allGames.first.color, testGame1.color); + expect(allGames.first.icon, testGame1.icon); + expect(allGames.first.createdAt, testGame1.createdAt); + }); + + test('Adding and fetching multiple games works correctly', () async { + await database.gameDao.addGame(game: testGame1); + await database.gameDao.addGame(game: testGame2); + await database.gameDao.addGame(game: testGame3); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames.length, 3); + + final names = allGames.map((g) => g.name).toList(); + expect(names, containsAll(['Chess', 'Poker', 'Monopoly'])); + }); + + // ==================== getGameById ==================== + test('getGameById returns correct game', () async { + await database.gameDao.addGame(game: testGame1); + await database.gameDao.addGame(game: testGame2); + + final game = await database.gameDao.getGameById(gameId: testGame2.id); + expect(game.id, testGame2.id); + expect(game.name, testGame2.name); + expect(game.ruleset, testGame2.ruleset); + expect(game.description, testGame2.description); + expect(game.color, testGame2.color); + expect(game.icon, testGame2.icon); + }); + + test('getGameById throws exception for non-existent game', () async { + expect( + () => database.gameDao.getGameById(gameId: 'non-existent-id'), + throwsA(isA()), + ); + }); + + // ==================== addGame ==================== + test('addGame returns true when game is added successfully', () async { + final result = await database.gameDao.addGame(game: testGame1); + expect(result, true); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames.length, 1); + }); + + test('addGame returns false when game already exists', () async { + final firstAdd = await database.gameDao.addGame(game: testGame1); + expect(firstAdd, true); + + final secondAdd = await database.gameDao.addGame(game: testGame1); + expect(secondAdd, false); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames.length, 1); + }); + + test('addGame handles game with null optional fields', () async { + final gameWithNulls = Game(name: 'Simple Game'); + final result = await database.gameDao.addGame(game: gameWithNulls); + expect(result, true); + + final fetchedGame = await database.gameDao.getGameById( + gameId: gameWithNulls.id, + ); + expect(fetchedGame.name, 'Simple Game'); + expect(fetchedGame.description, isNull); + expect(fetchedGame.color, isNull); + expect(fetchedGame.icon, isNull); + }); + + // ==================== addGamesAsList ==================== + test('addGamesAsList adds multiple games correctly', () async { + final result = await database.gameDao.addGamesAsList( + games: [testGame1, testGame2, testGame3], + ); + expect(result, true); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames.length, 3); + }); + + test('addGamesAsList returns false for empty list', () async { + final result = await database.gameDao.addGamesAsList(games: []); + expect(result, false); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames.length, 0); + }); + + test('addGamesAsList ignores duplicate games', () async { + await database.gameDao.addGame(game: testGame1); + + final result = await database.gameDao.addGamesAsList( + games: [testGame1, testGame2], + ); + expect(result, true); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames.length, 2); + }); + + // ==================== deleteGame ==================== + test('deleteGame returns true when game is deleted', () async { + await database.gameDao.addGame(game: testGame1); + + final result = await database.gameDao.deleteGame(gameId: testGame1.id); + expect(result, true); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames, isEmpty); + }); + + test('deleteGame returns false for non-existent game', () async { + final result = await database.gameDao.deleteGame( + gameId: 'non-existent-id', + ); + expect(result, false); + }); + + test('deleteGame only deletes the specified game', () async { + await database.gameDao.addGamesAsList( + games: [testGame1, testGame2, testGame3], + ); + + await database.gameDao.deleteGame(gameId: testGame2.id); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames.length, 2); + expect(allGames.any((g) => g.id == testGame2.id), false); + expect(allGames.any((g) => g.id == testGame1.id), true); + expect(allGames.any((g) => g.id == testGame3.id), true); + }); + + // ==================== gameExists ==================== + test('gameExists returns true for existing game', () async { + await database.gameDao.addGame(game: testGame1); + + final exists = await database.gameDao.gameExists(gameId: testGame1.id); + expect(exists, true); + }); + + test('gameExists returns false for non-existent game', () async { + final exists = await database.gameDao.gameExists( + gameId: 'non-existent-id', + ); + expect(exists, false); + }); + + test('gameExists returns false after game is deleted', () async { + await database.gameDao.addGame(game: testGame1); + await database.gameDao.deleteGame(gameId: testGame1.id); + + final exists = await database.gameDao.gameExists(gameId: testGame1.id); + expect(exists, false); + }); + + // ==================== updateGameName ==================== + test('updateGameName updates the name correctly', () async { + await database.gameDao.addGame(game: testGame1); + + await database.gameDao.updateGameName( + gameId: testGame1.id, + newName: 'Updated Chess', + ); + + final updatedGame = await database.gameDao.getGameById( + gameId: testGame1.id, + ); + expect(updatedGame.name, 'Updated Chess'); + expect(updatedGame.ruleset, testGame1.ruleset); + }); + + test('updateGameName does nothing for non-existent game', () async { + await database.gameDao.updateGameName( + gameId: 'non-existent-id', + newName: 'New Name', + ); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames, isEmpty); + }); + + // ==================== updateGameRuleset ==================== + test('updateGameRuleset updates the ruleset correctly', () async { + await database.gameDao.addGame(game: testGame1); + + await database.gameDao.updateGameRuleset( + gameId: testGame1.id, + newRuleset: 'New ruleset for chess', + ); + + final updatedGame = await database.gameDao.getGameById( + gameId: testGame1.id, + ); + expect(updatedGame.ruleset, 'New ruleset for chess'); + expect(updatedGame.name, testGame1.name); + }); + + test('updateGameRuleset does nothing for non-existent game', () async { + await database.gameDao.updateGameRuleset( + gameId: 'non-existent-id', + newRuleset: 'New Ruleset', + ); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames, isEmpty); + }); + + // ==================== updateGameDescription ==================== + test('updateGameDescription updates the description correctly', () async { + await database.gameDao.addGame(game: testGame1); + + await database.gameDao.updateGameDescription( + gameId: testGame1.id, + newDescription: 'An updated description', + ); + + final updatedGame = await database.gameDao.getGameById( + gameId: testGame1.id, + ); + expect(updatedGame.description, 'An updated description'); + }); + + test('updateGameDescription can set description to null', () async { + await database.gameDao.addGame(game: testGame1); + + await database.gameDao.updateGameDescription( + gameId: testGame1.id, + newDescription: null, + ); + + final updatedGame = await database.gameDao.getGameById( + gameId: testGame1.id, + ); + expect(updatedGame.description, isNull); + }); + + test('updateGameDescription does nothing for non-existent game', () async { + await database.gameDao.updateGameDescription( + gameId: 'non-existent-id', + newDescription: 'New Description', + ); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames, isEmpty); + }); + + // ==================== updateGameColor ==================== + test('updateGameColor updates the color correctly', () async { + await database.gameDao.addGame(game: testGame1); + + await database.gameDao.updateGameColor( + gameId: testGame1.id, + newColor: 0xFF00FF00, + ); + + final updatedGame = await database.gameDao.getGameById( + gameId: testGame1.id, + ); + expect(updatedGame.color, 0xFF00FF00); + }); + + test('updateGameColor can set color to null', () async { + await database.gameDao.addGame(game: testGame1); + + await database.gameDao.updateGameColor( + gameId: testGame1.id, + newColor: null, + ); + + final updatedGame = await database.gameDao.getGameById( + gameId: testGame1.id, + ); + expect(updatedGame.color, isNull); + }); + + test('updateGameColor does nothing for non-existent game', () async { + await database.gameDao.updateGameColor( + gameId: 'non-existent-id', + newColor: 0xFF00FF00, + ); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames, isEmpty); + }); + + // ==================== updateGameIcon ==================== + test('updateGameIcon updates the icon correctly', () async { + await database.gameDao.addGame(game: testGame1); + + await database.gameDao.updateGameIcon( + gameId: testGame1.id, + newIcon: 'new_chess_icon', + ); + + final updatedGame = await database.gameDao.getGameById( + gameId: testGame1.id, + ); + expect(updatedGame.icon, 'new_chess_icon'); + }); + + test('updateGameIcon can set icon to null', () async { + await database.gameDao.addGame(game: testGame1); + + await database.gameDao.updateGameIcon( + gameId: testGame1.id, + newIcon: null, + ); + + final updatedGame = await database.gameDao.getGameById( + gameId: testGame1.id, + ); + expect(updatedGame.icon, isNull); + }); + + test('updateGameIcon does nothing for non-existent game', () async { + await database.gameDao.updateGameIcon( + gameId: 'non-existent-id', + newIcon: 'some_icon', + ); + + final allGames = await database.gameDao.getAllGames(); + expect(allGames, isEmpty); + }); + + // ==================== getGameCount ==================== + test('getGameCount returns 0 when no games exist', () async { + final count = await database.gameDao.getGameCount(); + expect(count, 0); + }); + + test('getGameCount returns correct count after adding games', () async { + await database.gameDao.addGamesAsList( + games: [testGame1, testGame2, testGame3], + ); + + final count = await database.gameDao.getGameCount(); + expect(count, 3); + }); + + test('getGameCount updates correctly after deletion', () async { + await database.gameDao.addGamesAsList( + games: [testGame1, testGame2], + ); + + final countBefore = await database.gameDao.getGameCount(); + expect(countBefore, 2); + + await database.gameDao.deleteGame(gameId: testGame1.id); + + final countAfter = await database.gameDao.getGameCount(); + expect(countAfter, 1); + }); + + // ==================== deleteAllGames ==================== + test('deleteAllGames removes all games', () async { + await database.gameDao.addGamesAsList( + games: [testGame1, testGame2, testGame3], + ); + + final countBefore = await database.gameDao.getGameCount(); + expect(countBefore, 3); + + final result = await database.gameDao.deleteAllGames(); + expect(result, true); + + final countAfter = await database.gameDao.getGameCount(); + expect(countAfter, 0); + }); + + test('deleteAllGames returns false when no games exist', () async { + final result = await database.gameDao.deleteAllGames(); + expect(result, false); + }); + + // ==================== Edge Cases ==================== + test('Game with special characters in name is stored correctly', () async { + final specialGame = Game( + name: 'Game\'s & "Special" ', + description: 'Description with émojis 🎮🎲', + ); + await database.gameDao.addGame(game: specialGame); + + final fetchedGame = await database.gameDao.getGameById( + gameId: specialGame.id, + ); + expect(fetchedGame.name, 'Game\'s & "Special" '); + expect(fetchedGame.description, 'Description with émojis 🎮🎲'); + }); + + test('Game with empty string fields is stored correctly', () async { + final emptyGame = Game( + name: '', + ruleset: '', + description: '', + icon: '', + ); + await database.gameDao.addGame(game: emptyGame); + + final fetchedGame = await database.gameDao.getGameById( + gameId: emptyGame.id, + ); + expect(fetchedGame.name, ''); + expect(fetchedGame.ruleset, ''); + expect(fetchedGame.description, ''); + expect(fetchedGame.icon, ''); + }); + + test('Game with very long strings is stored correctly', () async { + final longString = 'A' * 10000; + final longGame = Game( + name: longString, + description: longString, + ruleset: longString, + ); + await database.gameDao.addGame(game: longGame); + + final fetchedGame = await database.gameDao.getGameById( + gameId: longGame.id, + ); + expect(fetchedGame.name.length, 10000); + expect(fetchedGame.description?.length, 10000); + expect(fetchedGame.ruleset?.length, 10000); + }); + + test('Multiple updates to the same game work correctly', () async { + await database.gameDao.addGame(game: testGame1); + + await database.gameDao.updateGameName( + gameId: testGame1.id, + newName: 'Updated Name', + ); + await database.gameDao.updateGameColor( + gameId: testGame1.id, + newColor: 0xFF123456, + ); + await database.gameDao.updateGameDescription( + gameId: testGame1.id, + newDescription: 'Updated Description', + ); + + final updatedGame = await database.gameDao.getGameById( + gameId: testGame1.id, + ); + expect(updatedGame.name, 'Updated Name'); + expect(updatedGame.color, 0xFF123456); + expect(updatedGame.description, 'Updated Description'); + expect(updatedGame.ruleset, testGame1.ruleset); + expect(updatedGame.icon, testGame1.icon); + }); + }); +} + From b0b21bcba613ebbbeb3dea9fc81fcc2d4dd445fa Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Tue, 20 Jan 2026 15:48:40 +0100 Subject: [PATCH 44/87] add new group tests --- test/db_tests/group_test.dart | 171 +++++++++++++++++++++++++++++++++- 1 file changed, 170 insertions(+), 1 deletion(-) diff --git a/test/db_tests/group_test.dart b/test/db_tests/group_test.dart index 08f8379..99df9de 100644 --- a/test/db_tests/group_test.dart +++ b/test/db_tests/group_test.dart @@ -1,5 +1,5 @@ import 'package:clock/clock.dart'; -import 'package:drift/drift.dart'; +import 'package:drift/drift.dart' hide isNull; import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:game_tracker/data/db/database.dart'; @@ -173,5 +173,174 @@ void main() { final finalCount = await database.groupDao.getGroupCount(); expect(finalCount, 0); }); + + test('getAllGroups returns empty list when no groups exist', () async { + final allGroups = await database.groupDao.getAllGroups(); + expect(allGroups, isEmpty); + }); + + test('getGroupById throws exception for non-existent group', () async { + expect( + () => database.groupDao.getGroupById(groupId: 'non-existent-id'), + throwsA(isA()), + ); + }); + + test('addGroup returns false when group already exists', () async { + final firstAdd = await database.groupDao.addGroup(group: testGroup1); + expect(firstAdd, true); + + final secondAdd = await database.groupDao.addGroup(group: testGroup1); + expect(secondAdd, false); + + final allGroups = await database.groupDao.getAllGroups(); + expect(allGroups.length, 1); + }); + + test('addGroupsAsList handles empty list correctly', () async { + await database.groupDao.addGroupsAsList(groups: []); + + final allGroups = await database.groupDao.getAllGroups(); + expect(allGroups.length, 0); + }); + + test('deleteGroup returns false for non-existent group', () async { + final deleted = await database.groupDao.deleteGroup( + groupId: 'non-existent-id', + ); + expect(deleted, false); + }); + + test('updateGroupName returns false for non-existent group', () async { + final updated = await database.groupDao.updateGroupName( + groupId: 'non-existent-id', + newName: 'New Name', + ); + expect(updated, false); + }); + + test('Updating a group description works correctly', () async { + await database.groupDao.addGroup(group: testGroup1); + + const newDescription = 'This is a new description'; + + final updated = await database.groupDao.updateGroupDescription( + groupId: testGroup1.id, + newDescription: newDescription, + ); + expect(updated, true); + + final result = await database.groupDao.getGroupById( + groupId: testGroup1.id, + ); + expect(result.description, newDescription); + }); + + test('updateGroupDescription can set description to null', () async { + final groupWithDescription = Group( + name: 'Group with description', + description: 'Initial description', + members: [testPlayer1], + ); + await database.groupDao.addGroup(group: groupWithDescription); + + final updated = await database.groupDao.updateGroupDescription( + groupId: groupWithDescription.id, + newDescription: null, + ); + expect(updated, true); + + final result = await database.groupDao.getGroupById( + groupId: groupWithDescription.id, + ); + expect(result.description, isNull); + }); + + test('updateGroupDescription returns false for non-existent group', + () async { + final updated = await database.groupDao.updateGroupDescription( + groupId: 'non-existent-id', + newDescription: 'New Description', + ); + expect(updated, false); + }); + + test('deleteAllGroups removes all groups', () async { + await database.groupDao.addGroupsAsList( + groups: [testGroup1, testGroup2], + ); + + final countBefore = await database.groupDao.getGroupCount(); + expect(countBefore, 2); + + final deleted = await database.groupDao.deleteAllGroups(); + expect(deleted, true); + + final countAfter = await database.groupDao.getGroupCount(); + expect(countAfter, 0); + }); + + test('deleteAllGroups returns false when no groups exist', () async { + final deleted = await database.groupDao.deleteAllGroups(); + expect(deleted, false); + }); + + test('Group with special characters in name is stored correctly', () async { + final specialGroup = Group( + name: 'Group\'s & "Special" ', + description: 'Description with émojis 🎮🎲', + members: [testPlayer1], + ); + await database.groupDao.addGroup(group: specialGroup); + + final fetchedGroup = await database.groupDao.getGroupById( + groupId: specialGroup.id, + ); + expect(fetchedGroup.name, 'Group\'s & "Special" '); + expect(fetchedGroup.description, 'Description with émojis 🎮🎲'); + }); + + test('Group with empty members list is stored correctly', () async { + final emptyGroup = Group( + name: 'Empty Group', + members: [], + ); + await database.groupDao.addGroup(group: emptyGroup); + + final fetchedGroup = await database.groupDao.getGroupById( + groupId: emptyGroup.id, + ); + expect(fetchedGroup.name, 'Empty Group'); + expect(fetchedGroup.members, isEmpty); + }); + + test('Multiple updates to the same group work correctly', () async { + await database.groupDao.addGroup(group: testGroup1); + + await database.groupDao.updateGroupName( + groupId: testGroup1.id, + newName: 'Updated Name', + ); + await database.groupDao.updateGroupDescription( + groupId: testGroup1.id, + newDescription: 'Updated Description', + ); + + final updatedGroup = await database.groupDao.getGroupById( + groupId: testGroup1.id, + ); + expect(updatedGroup.name, 'Updated Name'); + expect(updatedGroup.description, 'Updated Description'); + expect(updatedGroup.members.length, testGroup1.members.length); + }); + + test('addGroupsAsList with duplicate groups only adds once', () async { + await database.groupDao.addGroupsAsList( + groups: [testGroup1, testGroup1, testGroup1], + ); + + final allGroups = await database.groupDao.getAllGroups(); + expect(allGroups.length, 1); + }); }); } From e09ccf93567475b727be1b2383b5ac055d1a2fab Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Tue, 20 Jan 2026 15:58:16 +0100 Subject: [PATCH 45/87] add comments to all tests --- test/db_tests/game_test.dart | 54 ++++++++++++++++++++-------- test/db_tests/group_test.dart | 23 ++++++++++++ test/db_tests/match_test.dart | 12 +++++++ test/db_tests/player_group_test.dart | 5 +-- test/db_tests/player_match_test.dart | 7 ++++ test/db_tests/player_test.dart | 8 +++++ test/db_tests/score_test.dart | 15 +++++++- test/db_tests/team_test.dart | 16 +++++++-- 8 files changed, 121 insertions(+), 19 deletions(-) diff --git a/test/db_tests/game_test.dart b/test/db_tests/game_test.dart index 924e673..a1d8c1f 100644 --- a/test/db_tests/game_test.dart +++ b/test/db_tests/game_test.dart @@ -50,12 +50,14 @@ void main() { }); group('Game Tests', () { - // ==================== getAllGames ==================== + + // Verifies that getAllGames returns an empty list when the database has no games. test('getAllGames returns empty list when no games exist', () async { final allGames = await database.gameDao.getAllGames(); expect(allGames, isEmpty); }); + // Verifies that a single game can be added and retrieved with all fields intact. test('Adding and fetching a single game works correctly', () async { await database.gameDao.addGame(game: testGame1); @@ -70,6 +72,7 @@ void main() { expect(allGames.first.createdAt, testGame1.createdAt); }); + // Verifies that multiple games can be added and retrieved correctly. test('Adding and fetching multiple games works correctly', () async { await database.gameDao.addGame(game: testGame1); await database.gameDao.addGame(game: testGame2); @@ -82,7 +85,7 @@ void main() { expect(names, containsAll(['Chess', 'Poker', 'Monopoly'])); }); - // ==================== getGameById ==================== + // Verifies that getGameById returns the correct game with all properties. test('getGameById returns correct game', () async { await database.gameDao.addGame(game: testGame1); await database.gameDao.addGame(game: testGame2); @@ -96,6 +99,7 @@ void main() { expect(game.icon, testGame2.icon); }); + // Verifies that getGameById throws a StateError when the game doesn't exist. test('getGameById throws exception for non-existent game', () async { expect( () => database.gameDao.getGameById(gameId: 'non-existent-id'), @@ -103,7 +107,7 @@ void main() { ); }); - // ==================== addGame ==================== + // Verifies that addGame returns true when a game is successfully added. test('addGame returns true when game is added successfully', () async { final result = await database.gameDao.addGame(game: testGame1); expect(result, true); @@ -112,6 +116,7 @@ void main() { expect(allGames.length, 1); }); + // Verifies that addGame returns false when trying to add a duplicate game. test('addGame returns false when game already exists', () async { final firstAdd = await database.gameDao.addGame(game: testGame1); expect(firstAdd, true); @@ -123,6 +128,7 @@ void main() { expect(allGames.length, 1); }); + // Verifies that a game with null optional fields can be added and retrieved. test('addGame handles game with null optional fields', () async { final gameWithNulls = Game(name: 'Simple Game'); final result = await database.gameDao.addGame(game: gameWithNulls); @@ -137,7 +143,7 @@ void main() { expect(fetchedGame.icon, isNull); }); - // ==================== addGamesAsList ==================== + // Verifies that multiple games can be added at once using addGamesAsList. test('addGamesAsList adds multiple games correctly', () async { final result = await database.gameDao.addGamesAsList( games: [testGame1, testGame2, testGame3], @@ -148,6 +154,7 @@ void main() { expect(allGames.length, 3); }); + // Verifies that addGamesAsList returns false when given an empty list. test('addGamesAsList returns false for empty list', () async { final result = await database.gameDao.addGamesAsList(games: []); expect(result, false); @@ -156,6 +163,7 @@ void main() { expect(allGames.length, 0); }); + // Verifies that addGamesAsList ignores duplicate games when adding. test('addGamesAsList ignores duplicate games', () async { await database.gameDao.addGame(game: testGame1); @@ -168,7 +176,7 @@ void main() { expect(allGames.length, 2); }); - // ==================== deleteGame ==================== + // Verifies that deleteGame returns true and removes the game from database. test('deleteGame returns true when game is deleted', () async { await database.gameDao.addGame(game: testGame1); @@ -179,6 +187,7 @@ void main() { expect(allGames, isEmpty); }); + // Verifies that deleteGame returns false for a non-existent game ID. test('deleteGame returns false for non-existent game', () async { final result = await database.gameDao.deleteGame( gameId: 'non-existent-id', @@ -186,6 +195,7 @@ void main() { expect(result, false); }); + // Verifies that deleteGame only removes the specified game, leaving others intact. test('deleteGame only deletes the specified game', () async { await database.gameDao.addGamesAsList( games: [testGame1, testGame2, testGame3], @@ -200,7 +210,7 @@ void main() { expect(allGames.any((g) => g.id == testGame3.id), true); }); - // ==================== gameExists ==================== + // Verifies that gameExists returns true when the game exists in database. test('gameExists returns true for existing game', () async { await database.gameDao.addGame(game: testGame1); @@ -208,6 +218,7 @@ void main() { expect(exists, true); }); + // Verifies that gameExists returns false for a non-existent game ID. test('gameExists returns false for non-existent game', () async { final exists = await database.gameDao.gameExists( gameId: 'non-existent-id', @@ -215,6 +226,7 @@ void main() { expect(exists, false); }); + // Verifies that gameExists returns false after a game has been deleted. test('gameExists returns false after game is deleted', () async { await database.gameDao.addGame(game: testGame1); await database.gameDao.deleteGame(gameId: testGame1.id); @@ -223,7 +235,7 @@ void main() { expect(exists, false); }); - // ==================== updateGameName ==================== + // Verifies that updateGameName correctly updates only the name field. test('updateGameName updates the name correctly', () async { await database.gameDao.addGame(game: testGame1); @@ -239,6 +251,7 @@ void main() { expect(updatedGame.ruleset, testGame1.ruleset); }); + // Verifies that updateGameName does nothing when game doesn't exist. test('updateGameName does nothing for non-existent game', () async { await database.gameDao.updateGameName( gameId: 'non-existent-id', @@ -249,7 +262,7 @@ void main() { expect(allGames, isEmpty); }); - // ==================== updateGameRuleset ==================== + // Verifies that updateGameRuleset correctly updates only the ruleset field. test('updateGameRuleset updates the ruleset correctly', () async { await database.gameDao.addGame(game: testGame1); @@ -265,6 +278,7 @@ void main() { expect(updatedGame.name, testGame1.name); }); + // Verifies that updateGameRuleset does nothing when game doesn't exist. test('updateGameRuleset does nothing for non-existent game', () async { await database.gameDao.updateGameRuleset( gameId: 'non-existent-id', @@ -275,7 +289,7 @@ void main() { expect(allGames, isEmpty); }); - // ==================== updateGameDescription ==================== + // Verifies that updateGameDescription correctly updates the description. test('updateGameDescription updates the description correctly', () async { await database.gameDao.addGame(game: testGame1); @@ -290,6 +304,7 @@ void main() { expect(updatedGame.description, 'An updated description'); }); + // Verifies that updateGameDescription can set the description to null. test('updateGameDescription can set description to null', () async { await database.gameDao.addGame(game: testGame1); @@ -304,6 +319,7 @@ void main() { expect(updatedGame.description, isNull); }); + // Verifies that updateGameDescription does nothing when game doesn't exist. test('updateGameDescription does nothing for non-existent game', () async { await database.gameDao.updateGameDescription( gameId: 'non-existent-id', @@ -314,7 +330,7 @@ void main() { expect(allGames, isEmpty); }); - // ==================== updateGameColor ==================== + // Verifies that updateGameColor correctly updates the color value. test('updateGameColor updates the color correctly', () async { await database.gameDao.addGame(game: testGame1); @@ -329,6 +345,7 @@ void main() { expect(updatedGame.color, 0xFF00FF00); }); + // Verifies that updateGameColor can set the color to null. test('updateGameColor can set color to null', () async { await database.gameDao.addGame(game: testGame1); @@ -343,6 +360,7 @@ void main() { expect(updatedGame.color, isNull); }); + // Verifies that updateGameColor does nothing when game doesn't exist. test('updateGameColor does nothing for non-existent game', () async { await database.gameDao.updateGameColor( gameId: 'non-existent-id', @@ -353,7 +371,7 @@ void main() { expect(allGames, isEmpty); }); - // ==================== updateGameIcon ==================== + // Verifies that updateGameIcon correctly updates the icon value. test('updateGameIcon updates the icon correctly', () async { await database.gameDao.addGame(game: testGame1); @@ -368,6 +386,7 @@ void main() { expect(updatedGame.icon, 'new_chess_icon'); }); + // Verifies that updateGameIcon can set the icon to null. test('updateGameIcon can set icon to null', () async { await database.gameDao.addGame(game: testGame1); @@ -382,6 +401,7 @@ void main() { expect(updatedGame.icon, isNull); }); + // Verifies that updateGameIcon does nothing when game doesn't exist. test('updateGameIcon does nothing for non-existent game', () async { await database.gameDao.updateGameIcon( gameId: 'non-existent-id', @@ -392,12 +412,13 @@ void main() { expect(allGames, isEmpty); }); - // ==================== getGameCount ==================== + // Verifies that getGameCount returns 0 when no games exist. test('getGameCount returns 0 when no games exist', () async { final count = await database.gameDao.getGameCount(); expect(count, 0); }); + // Verifies that getGameCount returns the correct count after adding games. test('getGameCount returns correct count after adding games', () async { await database.gameDao.addGamesAsList( games: [testGame1, testGame2, testGame3], @@ -407,6 +428,7 @@ void main() { expect(count, 3); }); + // Verifies that getGameCount updates correctly after deleting a game. test('getGameCount updates correctly after deletion', () async { await database.gameDao.addGamesAsList( games: [testGame1, testGame2], @@ -421,7 +443,7 @@ void main() { expect(countAfter, 1); }); - // ==================== deleteAllGames ==================== + // Verifies that deleteAllGames removes all games from the database. test('deleteAllGames removes all games', () async { await database.gameDao.addGamesAsList( games: [testGame1, testGame2, testGame3], @@ -437,12 +459,13 @@ void main() { expect(countAfter, 0); }); + // Verifies that deleteAllGames returns false when no games exist. test('deleteAllGames returns false when no games exist', () async { final result = await database.gameDao.deleteAllGames(); expect(result, false); }); - // ==================== Edge Cases ==================== + // Verifies that games with special characters (quotes, emojis) are stored correctly. test('Game with special characters in name is stored correctly', () async { final specialGame = Game( name: 'Game\'s & "Special" ', @@ -457,6 +480,7 @@ void main() { expect(fetchedGame.description, 'Description with émojis 🎮🎲'); }); + // Verifies that games with empty string fields are stored and retrieved correctly. test('Game with empty string fields is stored correctly', () async { final emptyGame = Game( name: '', @@ -475,6 +499,7 @@ void main() { expect(fetchedGame.icon, ''); }); + // Verifies that games with very long strings (10000 chars) are handled correctly. test('Game with very long strings is stored correctly', () async { final longString = 'A' * 10000; final longGame = Game( @@ -492,6 +517,7 @@ void main() { expect(fetchedGame.ruleset?.length, 10000); }); + // Verifies that multiple sequential updates to the same game work correctly. test('Multiple updates to the same game work correctly', () async { await database.gameDao.addGame(game: testGame1); diff --git a/test/db_tests/group_test.dart b/test/db_tests/group_test.dart index 99df9de..307fbb5 100644 --- a/test/db_tests/group_test.dart +++ b/test/db_tests/group_test.dart @@ -58,6 +58,8 @@ void main() { await database.close(); }); group('Group Tests', () { + + // Verifies that a single group can be added and retrieved with all fields and members intact. test('Adding and fetching a single group works correctly', () async { await database.groupDao.addGroup(group: testGroup1); @@ -80,6 +82,7 @@ void main() { } }); + // Verifies that multiple groups can be added and retrieved with correct members. test('Adding and fetching multiple groups works correctly', () async { await database.groupDao.addGroupsAsList( groups: [testGroup1, testGroup2, testGroup3, testGroup4], @@ -106,6 +109,7 @@ void main() { } }); + // Verifies that adding the same group twice does not create duplicates. test('Adding the same group twice does not create duplicates', () async { await database.groupDao.addGroup(group: testGroup1); await database.groupDao.addGroup(group: testGroup1); @@ -114,6 +118,7 @@ void main() { expect(allGroups.length, 1); }); + // Verifies that groupExists returns correct boolean based on group presence. test('Group existence check works correctly', () async { var groupExists = await database.groupDao.groupExists( groupId: testGroup1.id, @@ -126,6 +131,7 @@ void main() { expect(groupExists, true); }); + // Verifies that deleteGroup removes the group and returns true. test('Deleting a group works correctly', () async { await database.groupDao.addGroup(group: testGroup1); @@ -140,6 +146,7 @@ void main() { expect(groupExists, false); }); + // Verifies that updateGroupName correctly updates only the name field. test('Updating a group name works correcly', () async { await database.groupDao.addGroup(group: testGroup1); @@ -156,6 +163,7 @@ void main() { expect(result.name, newGroupName); }); + // Verifies that getGroupCount returns correct count through add/delete operations. test('Getting the group count works correctly', () async { final initialCount = await database.groupDao.getGroupCount(); expect(initialCount, 0); @@ -174,11 +182,13 @@ void main() { expect(finalCount, 0); }); + // Verifies that getAllGroups returns an empty list when no groups exist. test('getAllGroups returns empty list when no groups exist', () async { final allGroups = await database.groupDao.getAllGroups(); expect(allGroups, isEmpty); }); + // Verifies that getGroupById throws StateError for non-existent group ID. test('getGroupById throws exception for non-existent group', () async { expect( () => database.groupDao.getGroupById(groupId: 'non-existent-id'), @@ -186,6 +196,7 @@ void main() { ); }); + // Verifies that addGroup returns false when trying to add a duplicate group. test('addGroup returns false when group already exists', () async { final firstAdd = await database.groupDao.addGroup(group: testGroup1); expect(firstAdd, true); @@ -197,6 +208,7 @@ void main() { expect(allGroups.length, 1); }); + // Verifies that addGroupsAsList handles an empty list without errors. test('addGroupsAsList handles empty list correctly', () async { await database.groupDao.addGroupsAsList(groups: []); @@ -204,6 +216,7 @@ void main() { expect(allGroups.length, 0); }); + // Verifies that deleteGroup returns false for a non-existent group ID. test('deleteGroup returns false for non-existent group', () async { final deleted = await database.groupDao.deleteGroup( groupId: 'non-existent-id', @@ -211,6 +224,7 @@ void main() { expect(deleted, false); }); + // Verifies that updateGroupName returns false for a non-existent group ID. test('updateGroupName returns false for non-existent group', () async { final updated = await database.groupDao.updateGroupName( groupId: 'non-existent-id', @@ -219,6 +233,7 @@ void main() { expect(updated, false); }); + // Verifies that updateGroupDescription correctly updates the description field. test('Updating a group description works correctly', () async { await database.groupDao.addGroup(group: testGroup1); @@ -236,6 +251,7 @@ void main() { expect(result.description, newDescription); }); + // Verifies that updateGroupDescription can set the description to null. test('updateGroupDescription can set description to null', () async { final groupWithDescription = Group( name: 'Group with description', @@ -256,6 +272,7 @@ void main() { expect(result.description, isNull); }); + // Verifies that updateGroupDescription returns false for a non-existent group. test('updateGroupDescription returns false for non-existent group', () async { final updated = await database.groupDao.updateGroupDescription( @@ -265,6 +282,7 @@ void main() { expect(updated, false); }); + // Verifies that deleteAllGroups removes all groups from the database. test('deleteAllGroups removes all groups', () async { await database.groupDao.addGroupsAsList( groups: [testGroup1, testGroup2], @@ -280,11 +298,13 @@ void main() { expect(countAfter, 0); }); + // Verifies that deleteAllGroups returns false when no groups exist. test('deleteAllGroups returns false when no groups exist', () async { final deleted = await database.groupDao.deleteAllGroups(); expect(deleted, false); }); + // Verifies that groups with special characters (quotes, emojis) are stored correctly. test('Group with special characters in name is stored correctly', () async { final specialGroup = Group( name: 'Group\'s & "Special" ', @@ -300,6 +320,7 @@ void main() { expect(fetchedGroup.description, 'Description with émojis 🎮🎲'); }); + // Verifies that a group with an empty members list can be stored and retrieved. test('Group with empty members list is stored correctly', () async { final emptyGroup = Group( name: 'Empty Group', @@ -314,6 +335,7 @@ void main() { expect(fetchedGroup.members, isEmpty); }); + // Verifies that multiple sequential updates to the same group work correctly. test('Multiple updates to the same group work correctly', () async { await database.groupDao.addGroup(group: testGroup1); @@ -334,6 +356,7 @@ void main() { expect(updatedGroup.members.length, testGroup1.members.length); }); + // Verifies that addGroupsAsList with duplicate groups only adds unique ones. test('addGroupsAsList with duplicate groups only adds once', () async { await database.groupDao.addGroupsAsList( groups: [testGroup1, testGroup1, testGroup1], diff --git a/test/db_tests/match_test.dart b/test/db_tests/match_test.dart index c52817f..1a7e407 100644 --- a/test/db_tests/match_test.dart +++ b/test/db_tests/match_test.dart @@ -92,6 +92,8 @@ void main() { }); group('Match Tests', () { + + // Verifies that a single match can be added and retrieved with all fields, group, and players intact. test('Adding and fetching single match works correctly', () async { await database.matchDao.addMatch(match: testMatch1); @@ -137,6 +139,7 @@ void main() { } }); + // Verifies that multiple matches can be added and retrieved with correct groups and players. test('Adding and fetching multiple matches works correctly', () async { await database.matchDao.addMatchAsList( matches: [ @@ -212,6 +215,7 @@ void main() { } }); + // Verifies that adding the same match twice does not create duplicates. test('Adding the same match twice does not create duplicates', () async { await database.matchDao.addMatch(match: testMatch1); await database.matchDao.addMatch(match: testMatch1); @@ -220,6 +224,7 @@ void main() { expect(matchCount, 1); }); + // Verifies that matchExists returns correct boolean based on match presence. test('Match existence check works correctly', () async { var matchExists = await database.matchDao.matchExists( matchId: testMatch1.id, @@ -232,6 +237,7 @@ void main() { expect(matchExists, true); }); + // Verifies that deleteMatch removes the match and returns true. test('Deleting a match works correctly', () async { await database.matchDao.addMatch(match: testMatch1); @@ -246,6 +252,7 @@ void main() { expect(matchExists, false); }); + // Verifies that getMatchCount returns correct count through add/delete operations. test('Getting the match count works correctly', () async { var matchCount = await database.matchDao.getMatchCount(); expect(matchCount, 0); @@ -271,6 +278,7 @@ void main() { expect(matchCount, 0); }); + // Verifies that hasWinner correctly identifies matches with and without winners. test('Checking if match has winner works correctly', () async { await database.matchDao.addMatch(match: testMatch1); await database.matchDao.addMatch(match: testMatchOnlyGroup); @@ -284,6 +292,7 @@ void main() { expect(hasWinner, false); }); + // Verifies that getWinner returns the correct winner player for a match. test('Fetching the winner of a match works correctly', () async { await database.matchDao.addMatch(match: testMatch1); @@ -297,6 +306,7 @@ void main() { } }); + // Verifies that setWinner correctly updates the winner of a match. test('Updating the winner of a match works correctly', () async { await database.matchDao.addMatch(match: testMatch1); @@ -329,6 +339,7 @@ void main() { } }); + // Verifies that removeWinner clears the winner and hasWinner returns false. test('Removing a winner works correctly', () async { await database.matchDao.addMatch(match: testMatch2); @@ -347,6 +358,7 @@ void main() { expect(removedWinner, null); }); + // Verifies that updateMatchName correctly updates only the name field. test('Renaming a match works correctly', () async { await database.matchDao.addMatch(match: testMatch1); diff --git a/test/db_tests/player_group_test.dart b/test/db_tests/player_group_test.dart index 344567c..660b066 100644 --- a/test/db_tests/player_group_test.dart +++ b/test/db_tests/player_group_test.dart @@ -41,9 +41,8 @@ void main() { }); group('Player-Group Tests', () { - /// No need to test if group has players since the members attribute is - /// not nullable + // Verifies that a player can be added to an existing group and isPlayerInGroup returns true. test('Adding a player to a group works correctly', () async { await database.groupDao.addGroup(group: testGroup); await database.playerDao.addPlayer(player: testPlayer4); @@ -67,6 +66,7 @@ void main() { expect(playerAdded, false); }); + // Verifies that a player can be removed from a group and the group's member count decreases. test('Removing player from group works correctly', () async { await database.groupDao.addGroup(group: testGroup); @@ -87,6 +87,7 @@ void main() { expect(playerExists, false); }); + // Verifies that getPlayersOfGroup returns all members of a group with correct data. test('Retrieving players of a group works correctly', () async { await database.groupDao.addGroup(group: testGroup); final players = await database.playerGroupDao.getPlayersOfGroup( diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/player_match_test.dart index d7d3bde..ce6d331 100644 --- a/test/db_tests/player_match_test.dart +++ b/test/db_tests/player_match_test.dart @@ -73,6 +73,8 @@ void main() { }); group('Player-Match Tests', () { + + // Verifies that matchHasPlayers returns false initially and true after adding a player. test('Match has player works correctly', () async { await database.matchDao.addMatch(match: testMatchOnlyGroup); await database.playerDao.addPlayer(player: testPlayer1); @@ -95,6 +97,7 @@ void main() { expect(matchHasPlayers, true); }); + // Verifies that a player can be added to a match and isPlayerInMatch returns true. test('Adding a player to a match works correctly', () async { await database.matchDao.addMatch(match: testMatchOnlyGroup); await database.playerDao.addPlayer(player: testPlayer5); @@ -118,6 +121,7 @@ void main() { expect(playerAdded, false); }); + // Verifies that a player can be removed from a match and the player count decreases. test('Removing player from match works correctly', () async { await database.matchDao.addMatch(match: testMatchOnlyPlayers); @@ -140,6 +144,7 @@ void main() { expect(playerExists, false); }); + // Verifies that getPlayersOfMatch returns all players of a match with correct data. test('Retrieving players of a match works correctly', () async { await database.matchDao.addMatch(match: testMatchOnlyPlayers); final players = await database.playerMatchDao.getPlayersOfMatch( @@ -160,6 +165,7 @@ void main() { } }); + // Verifies that updatePlayersFromMatch replaces all existing players with new ones. test('Updating the match players works correctly', () async { await database.matchDao.addMatch(match: testMatchOnlyPlayers); @@ -203,6 +209,7 @@ void main() { } }); + // Verifies that the same player can be added to multiple different matches. test( 'Adding the same player to separate matches works correctly', () async { diff --git a/test/db_tests/player_test.dart b/test/db_tests/player_test.dart index a6d1b93..0997086 100644 --- a/test/db_tests/player_test.dart +++ b/test/db_tests/player_test.dart @@ -35,6 +35,8 @@ void main() { }); group('Player Tests', () { + + // Verifies that players can be added and retrieved with all fields intact. test('Adding and fetching single player works correctly', () async { await database.playerDao.addPlayer(player: testPlayer1); await database.playerDao.addPlayer(player: testPlayer2); @@ -55,6 +57,7 @@ void main() { expect(fetchedPlayer2.createdAt, testPlayer2.createdAt); }); + // Verifies that multiple players can be added at once and retrieved correctly. test('Adding and fetching multiple players works correctly', () async { await database.playerDao.addPlayersAsList( players: [testPlayer1, testPlayer2, testPlayer3, testPlayer4], @@ -80,6 +83,7 @@ void main() { } }); + // Verifies that adding the same player twice does not create duplicates. test('Adding the same player twice does not create duplicates', () async { await database.playerDao.addPlayer(player: testPlayer1); await database.playerDao.addPlayer(player: testPlayer1); @@ -88,6 +92,7 @@ void main() { expect(allPlayers.length, 1); }); + // Verifies that playerExists returns correct boolean based on player presence. test('Player existence check works correctly', () async { var playerExists = await database.playerDao.playerExists( playerId: testPlayer1.id, @@ -102,6 +107,7 @@ void main() { expect(playerExists, true); }); + // Verifies that deletePlayer removes the player and returns true. test('Deleting a player works correctly', () async { await database.playerDao.addPlayer(player: testPlayer1); final playerDeleted = await database.playerDao.deletePlayer( @@ -115,6 +121,7 @@ void main() { expect(playerExists, false); }); + // Verifies that updatePlayerName correctly updates only the name field. test('Updating a player name works correctly', () async { await database.playerDao.addPlayer(player: testPlayer1); @@ -131,6 +138,7 @@ void main() { expect(result.name, newPlayerName); }); + // Verifies that getPlayerCount returns correct count through add/delete operations. test('Getting the player count works correctly', () async { var playerCount = await database.playerDao.getPlayerCount(); expect(playerCount, 0); diff --git a/test/db_tests/score_test.dart b/test/db_tests/score_test.dart index 4f6aa99..7934c6e 100644 --- a/test/db_tests/score_test.dart +++ b/test/db_tests/score_test.dart @@ -57,6 +57,8 @@ void main() { }); group('Score Tests', () { + + // Verifies that a score can be added and retrieved with all fields intact. test('Adding and fetching a score works correctly', () async { await database.scoreDao.addScore( playerId: testPlayer1.id, @@ -80,6 +82,7 @@ void main() { expect(score.change, 10); }); + // Verifies that getScoresForMatch returns all scores for a given match. test('Getting scores for a match works correctly', () async { await database.scoreDao.addScore( playerId: testPlayer1.id, @@ -110,6 +113,7 @@ void main() { expect(scores.length, 3); }); + // Verifies that getPlayerScoresInMatch returns all scores for a player in a match, ordered by round. test('Getting player scores in a match works correctly', () async { await database.scoreDao.addScore( playerId: testPlayer1.id, @@ -147,6 +151,7 @@ void main() { expect(playerScores[2].score, 30); }); + // Verifies that getScoreForRound returns null for a non-existent round number. test('Getting score for a non-existent round returns null', () async { final score = await database.scoreDao.getScoreForRound( playerId: testPlayer1.id, @@ -157,6 +162,7 @@ void main() { expect(score, isNull); }); + // Verifies that updateScore correctly updates the score and change values. test('Updating a score works correctly', () async { await database.scoreDao.addScore( playerId: testPlayer1.id, @@ -187,6 +193,7 @@ void main() { expect(score.change, 40); }); + // Verifies that updateScore returns false for a non-existent score entry. test('Updating a non-existent score returns false', () async { final updated = await database.scoreDao.updateScore( playerId: testPlayer1.id, @@ -199,6 +206,7 @@ void main() { expect(updated, false); }); + // Verifies that deleteScore removes the score entry and returns true. test('Deleting a score works correctly', () async { await database.scoreDao.addScore( playerId: testPlayer1.id, @@ -225,6 +233,7 @@ void main() { expect(score, isNull); }); + // Verifies that deleteScore returns false for a non-existent score entry. test('Deleting a non-existent score returns false', () async { final deleted = await database.scoreDao.deleteScore( playerId: testPlayer1.id, @@ -235,6 +244,7 @@ void main() { expect(deleted, false); }); + // Verifies that deleteScoresForMatch removes all scores for a match but keeps other match scores. test('Deleting scores for a match works correctly', () async { await database.scoreDao.addScore( playerId: testPlayer1.id, @@ -275,6 +285,7 @@ void main() { expect(match2Scores.length, 1); }); + // Verifies that deleteScoresForPlayer removes all scores for a player across all matches. test('Deleting scores for a player works correctly', () async { await database.scoreDao.addScore( playerId: testPlayer1.id, @@ -317,6 +328,7 @@ void main() { expect(player2Scores.length, 1); }); + // Verifies that getLatestRoundNumber returns the highest round number for a match. test('Getting latest round number works correctly', () async { var latestRound = await database.scoreDao.getLatestRoundNumber( matchId: testMatch1.id, @@ -350,6 +362,7 @@ void main() { expect(latestRound, 5); }); + // Verifies that getTotalScoreForPlayer returns the latest score (cumulative) for a player. test('Getting total score for a player works correctly', () async { var totalScore = await database.scoreDao.getTotalScoreForPlayer( playerId: testPlayer1.id, @@ -386,6 +399,7 @@ void main() { expect(totalScore, 40); }); + // Verifies that adding a score with the same player/match/round replaces the existing one. test('Adding the same score twice replaces the existing one', () async { await database.scoreDao.addScore( playerId: testPlayer1.id, @@ -414,4 +428,3 @@ void main() { }); }); } - diff --git a/test/db_tests/team_test.dart b/test/db_tests/team_test.dart index 2f3c5d9..b0ec349 100644 --- a/test/db_tests/team_test.dart +++ b/test/db_tests/team_test.dart @@ -56,6 +56,8 @@ void main() { }); group('Team Tests', () { + + // Verifies that a single team can be added and retrieved with all fields intact. test('Adding and fetching a single team works correctly', () async { final added = await database.teamDao.addTeam(team: testTeam1); expect(added, true); @@ -69,6 +71,7 @@ void main() { expect(fetchedTeam.createdAt, testTeam1.createdAt); }); + // Verifies that multiple teams can be added at once and retrieved correctly. test('Adding and fetching multiple teams works correctly', () async { await database.teamDao.addTeamsAsList( teams: [testTeam1, testTeam2, testTeam3], @@ -92,6 +95,7 @@ void main() { } }); + // Verifies that adding the same team twice does not create duplicates and returns false. test('Adding the same team twice does not create duplicates', () async { await database.teamDao.addTeam(team: testTeam1); final addedAgain = await database.teamDao.addTeam(team: testTeam1); @@ -102,6 +106,7 @@ void main() { expect(teamCount, 1); }); + // Verifies that teamExists returns correct boolean based on team presence. test('Team existence check works correctly', () async { var teamExists = await database.teamDao.teamExists(teamId: testTeam1.id); expect(teamExists, false); @@ -112,6 +117,7 @@ void main() { expect(teamExists, true); }); + // Verifies that deleteTeam removes the team and returns true. test('Deleting a team works correctly', () async { await database.teamDao.addTeam(team: testTeam1); @@ -126,6 +132,7 @@ void main() { expect(teamExists, false); }); + // Verifies that deleteTeam returns false for a non-existent team ID. test('Deleting a non-existent team returns false', () async { final teamDeleted = await database.teamDao.deleteTeam( teamId: 'non-existent-id', @@ -133,6 +140,7 @@ void main() { expect(teamDeleted, false); }); + // Verifies that getTeamCount returns correct count through add/delete operations. test('Getting the team count works correctly', () async { var teamCount = await database.teamDao.getTeamCount(); expect(teamCount, 0); @@ -158,6 +166,7 @@ void main() { expect(teamCount, 0); }); + // Verifies that updateTeamName correctly updates only the name field. test('Updating team name works correctly', () async { await database.teamDao.addTeam(team: testTeam1); @@ -176,6 +185,7 @@ void main() { expect(fetchedTeam.name, newName); }); + // Verifies that deleteAllTeams removes all teams from the database. test('Deleting all teams works correctly', () async { await database.teamDao.addTeamsAsList( teams: [testTeam1, testTeam2, testTeam3], @@ -191,16 +201,19 @@ void main() { expect(teamCount, 0); }); + // Verifies that deleteAllTeams returns false when no teams exist. test('Deleting all teams when empty returns false', () async { final deleted = await database.teamDao.deleteAllTeams(); expect(deleted, false); }); + // Verifies that addTeamsAsList returns false when given an empty list. test('Adding teams as list with empty list returns false', () async { final added = await database.teamDao.addTeamsAsList(teams: []); expect(added, false); }); + // Verifies that addTeamsAsList with duplicate IDs ignores duplicates and keeps the first. test('Adding teams with duplicate IDs ignores duplicates', () async { final duplicateTeam = Team( id: testTeam1.id, @@ -222,5 +235,4 @@ void main() { expect(fetchedTeam.name, testTeam1.name); }); }); -} - +} \ No newline at end of file From b108375ad5a6bb0484898c8d9519bb00bb9e40ff Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Tue, 20 Jan 2026 16:03:37 +0100 Subject: [PATCH 46/87] remove winner tests --- test/db_tests/match_test.dart | 80 ----------------------------------- 1 file changed, 80 deletions(-) diff --git a/test/db_tests/match_test.dart b/test/db_tests/match_test.dart index 1a7e407..8408586 100644 --- a/test/db_tests/match_test.dart +++ b/test/db_tests/match_test.dart @@ -278,86 +278,6 @@ void main() { expect(matchCount, 0); }); - // Verifies that hasWinner correctly identifies matches with and without winners. - test('Checking if match has winner works correctly', () async { - await database.matchDao.addMatch(match: testMatch1); - await database.matchDao.addMatch(match: testMatchOnlyGroup); - - var hasWinner = await database.matchDao.hasWinner(matchId: testMatch1.id); - expect(hasWinner, true); - - hasWinner = await database.matchDao.hasWinner( - matchId: testMatchOnlyGroup.id, - ); - expect(hasWinner, false); - }); - - // Verifies that getWinner returns the correct winner player for a match. - test('Fetching the winner of a match works correctly', () async { - await database.matchDao.addMatch(match: testMatch1); - - final winner = await database.matchDao.getWinner(matchId: testMatch1.id); - if (winner == null) { - fail('Winner is null'); - } else { - expect(winner.id, testMatch1.winner!.id); - expect(winner.name, testMatch1.winner!.name); - expect(winner.createdAt, testMatch1.winner!.createdAt); - } - }); - - // Verifies that setWinner correctly updates the winner of a match. - test('Updating the winner of a match works correctly', () async { - await database.matchDao.addMatch(match: testMatch1); - - final winner = await database.matchDao.getWinner(matchId: testMatch1.id); - if (winner == null) { - fail('Winner is null'); - } else { - expect(winner.id, testMatch1.winner!.id); - expect(winner.name, testMatch1.winner!.name); - expect(winner.createdAt, testMatch1.winner!.createdAt); - expect(winner.id, testPlayer4.id); - expect(winner.id != testPlayer5.id, true); - } - - await database.matchDao.setWinner( - matchId: testMatch1.id, - winnerId: testPlayer5.id, - ); - - final newWinner = await database.matchDao.getWinner( - matchId: testMatch1.id, - ); - - if (newWinner == null) { - fail('New winner is null'); - } else { - expect(newWinner.id, testPlayer5.id); - expect(newWinner.name, testPlayer5.name); - expect(newWinner.createdAt, testPlayer5.createdAt); - } - }); - - // Verifies that removeWinner clears the winner and hasWinner returns false. - test('Removing a winner works correctly', () async { - await database.matchDao.addMatch(match: testMatch2); - - var hasWinner = await database.matchDao.hasWinner(matchId: testMatch2.id); - expect(hasWinner, true); - - await database.matchDao.removeWinner(matchId: testMatch2.id); - - hasWinner = await database.matchDao.hasWinner(matchId: testMatch2.id); - expect(hasWinner, false); - - final removedWinner = await database.matchDao.getWinner( - matchId: testMatch2.id, - ); - - expect(removedWinner, null); - }); - // Verifies that updateMatchName correctly updates only the name field. test('Renaming a match works correctly', () async { await database.matchDao.addMatch(match: testMatch1); From b33260ec23177589edf5a6bef05bc4feebee96aa Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Tue, 20 Jan 2026 16:31:43 +0100 Subject: [PATCH 47/87] fix match missing game --- test/db_tests/player_match_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/player_match_test.dart index ce6d331..b44ccf6 100644 --- a/test/db_tests/player_match_test.dart +++ b/test/db_tests/player_match_test.dart @@ -214,8 +214,8 @@ void main() { 'Adding the same player to separate matches works correctly', () async { final playersList = [testPlayer1, testPlayer2, testPlayer3]; - final match1 = Match(name: 'Match 1', players: playersList); - final match2 = Match(name: 'Match 2', players: playersList); + final match1 = Match(name: 'Match 1', game: testGame, players: playersList); + final match2 = Match(name: 'Match 2', game: testGame, players: playersList); await Future.wait([ database.matchDao.addMatch(match: match1), From 6c39e1e574bd5a14920c42d5e3ff5197c19e0319 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Tue, 20 Jan 2026 16:31:52 +0100 Subject: [PATCH 48/87] remove winner check --- test/db_tests/match_test.dart | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/db_tests/match_test.dart b/test/db_tests/match_test.dart index 8408586..5e09088 100644 --- a/test/db_tests/match_test.dart +++ b/test/db_tests/match_test.dart @@ -167,13 +167,6 @@ void main() { expect(match.id, testMatch.id); expect(match.name, testMatch.name); expect(match.createdAt, testMatch.createdAt); - if (match.winner != null && testMatch.winner != null) { - expect(match.winner!.id, testMatch.winner!.id); - expect(match.winner!.name, testMatch.winner!.name); - expect(match.winner!.createdAt, testMatch.winner!.createdAt); - } else { - expect(match.winner, testMatch.winner); - } // Group-Checks if (testMatch.group != null) { From 2e454a530a24b93e0c082cebf38db67f73e560e6 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Tue, 20 Jan 2026 16:31:52 +0100 Subject: [PATCH 49/87] remove winner test again --- test/db_tests/match_test.dart | 7 ------- 1 file changed, 7 deletions(-) diff --git a/test/db_tests/match_test.dart b/test/db_tests/match_test.dart index 8408586..5e09088 100644 --- a/test/db_tests/match_test.dart +++ b/test/db_tests/match_test.dart @@ -167,13 +167,6 @@ void main() { expect(match.id, testMatch.id); expect(match.name, testMatch.name); expect(match.createdAt, testMatch.createdAt); - if (match.winner != null && testMatch.winner != null) { - expect(match.winner!.id, testMatch.winner!.id); - expect(match.winner!.name, testMatch.winner!.name); - expect(match.winner!.createdAt, testMatch.winner!.createdAt); - } else { - expect(match.winner, testMatch.winner); - } // Group-Checks if (testMatch.group != null) { From 0d28f4b87ccb5fc06dc623a79613568c1c8c766e Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Tue, 20 Jan 2026 16:34:38 +0100 Subject: [PATCH 50/87] remove winner test again --- test/db_tests/match_test.dart | 8 -------- 1 file changed, 8 deletions(-) diff --git a/test/db_tests/match_test.dart b/test/db_tests/match_test.dart index 5e09088..5941523 100644 --- a/test/db_tests/match_test.dart +++ b/test/db_tests/match_test.dart @@ -105,14 +105,6 @@ void main() { expect(result.name, testMatch1.name); expect(result.createdAt, testMatch1.createdAt); - if (result.winner != null && testMatch1.winner != null) { - expect(result.winner!.id, testMatch1.winner!.id); - expect(result.winner!.name, testMatch1.winner!.name); - expect(result.winner!.createdAt, testMatch1.winner!.createdAt); - } else { - expect(result.winner, testMatch1.winner); - } - if (result.group != null) { expect(result.group!.members.length, testGroup1.members.length); From 19b2685714a649560957aae8130057ebb3d1bc62 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 11:03:09 +0100 Subject: [PATCH 51/87] add more player tests --- test/db_tests/player_test.dart | 212 ++++++++++++++++++++++++++++++++- 1 file changed, 211 insertions(+), 1 deletion(-) diff --git a/test/db_tests/player_test.dart b/test/db_tests/player_test.dart index 0997086..da5b904 100644 --- a/test/db_tests/player_test.dart +++ b/test/db_tests/player_test.dart @@ -1,5 +1,5 @@ import 'package:clock/clock.dart'; -import 'package:drift/drift.dart'; +import 'package:drift/drift.dart' hide isNull; import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:game_tracker/data/db/database.dart'; @@ -163,5 +163,215 @@ void main() { playerCount = await database.playerDao.getPlayerCount(); expect(playerCount, 0); }); + + // Verifies that getAllPlayers returns an empty list when no players exist. + test('getAllPlayers returns empty list when no players exist', () async { + final allPlayers = await database.playerDao.getAllPlayers(); + expect(allPlayers, isEmpty); + }); + + // Verifies that getPlayerById returns the correct player. + test('getPlayerById returns correct player', () async { + await database.playerDao.addPlayer(player: testPlayer1); + await database.playerDao.addPlayer(player: testPlayer2); + + final fetchedPlayer = await database.playerDao.getPlayerById( + playerId: testPlayer1.id, + ); + + expect(fetchedPlayer.id, testPlayer1.id); + expect(fetchedPlayer.name, testPlayer1.name); + expect(fetchedPlayer.createdAt, testPlayer1.createdAt); + expect(fetchedPlayer.description, testPlayer1.description); + }); + + // Verifies that getPlayerById throws StateError for non-existent player ID. + test('getPlayerById throws exception for non-existent player', () async { + expect( + () => database.playerDao.getPlayerById(playerId: 'non-existent-id'), + throwsA(isA()), + ); + }); + + // Verifies that addPlayer returns false when trying to add a duplicate player. + test('addPlayer returns false when player already exists', () async { + final firstAdd = await database.playerDao.addPlayer(player: testPlayer1); + expect(firstAdd, true); + + final secondAdd = await database.playerDao.addPlayer(player: testPlayer1); + expect(secondAdd, false); + }); + + // Verifies that addPlayersAsList handles empty list correctly. + test('addPlayersAsList handles empty list correctly', () async { + final result = await database.playerDao.addPlayersAsList(players: []); + expect(result, false); + + final allPlayers = await database.playerDao.getAllPlayers(); + expect(allPlayers, isEmpty); + }); + + // Verifies that addPlayersAsList ignores duplicate player IDs. + test('addPlayersAsList with duplicate IDs ignores duplicates', () async { + await database.playerDao.addPlayersAsList( + players: [testPlayer1, testPlayer1, testPlayer2], + ); + + final allPlayers = await database.playerDao.getAllPlayers(); + expect(allPlayers.length, 2); + }); + + // Verifies that deletePlayer returns false for non-existent player. + test('deletePlayer returns false for non-existent player', () async { + final result = await database.playerDao.deletePlayer( + playerId: 'non-existent-id', + ); + expect(result, false); + }); + + // Verifies that updatePlayerName does nothing for non-existent player (no exception). + test('updatePlayerName does nothing for non-existent player', () async { + // Should not throw, just do nothing + await database.playerDao.updatePlayerName( + playerId: 'non-existent-id', + newName: 'New Name', + ); + + final allPlayers = await database.playerDao.getAllPlayers(); + expect(allPlayers, isEmpty); + }); + + // Verifies that deleteAllPlayers removes all players. + test('deleteAllPlayers removes all players', () async { + await database.playerDao.addPlayersAsList( + players: [testPlayer1, testPlayer2, testPlayer3], + ); + + var playerCount = await database.playerDao.getPlayerCount(); + expect(playerCount, 3); + + final result = await database.playerDao.deleteAllPlayers(); + expect(result, true); + + playerCount = await database.playerDao.getPlayerCount(); + expect(playerCount, 0); + }); + + // Verifies that deleteAllPlayers returns false when no players exist. + test('deleteAllPlayers returns false when no players exist', () async { + final result = await database.playerDao.deleteAllPlayers(); + expect(result, false); + }); + + // Verifies that a player with special characters in name is stored correctly. + test('Player with special characters in name is stored correctly', () async { + final specialPlayer = Player(name: 'Test!@#\$%^&*()_+-=[]{}|;\':",.<>?/`~'); + + await database.playerDao.addPlayer(player: specialPlayer); + + final fetchedPlayer = await database.playerDao.getPlayerById( + playerId: specialPlayer.id, + ); + expect(fetchedPlayer.name, specialPlayer.name); + }); + + // Verifies that a player with description is stored correctly. + test('Player with description is stored correctly', () async { + final playerWithDescription = Player( + name: 'Described Player', + description: 'This is a test description', + ); + + await database.playerDao.addPlayer(player: playerWithDescription); + + final fetchedPlayer = await database.playerDao.getPlayerById( + playerId: playerWithDescription.id, + ); + expect(fetchedPlayer.name, playerWithDescription.name); + expect(fetchedPlayer.description, playerWithDescription.description); + }); + + // Verifies that a player with null description is stored correctly. + test('Player with null description is stored correctly', () async { + final playerWithoutDescription = Player(name: 'No Description Player'); + + await database.playerDao.addPlayer(player: playerWithoutDescription); + + final fetchedPlayer = await database.playerDao.getPlayerById( + playerId: playerWithoutDescription.id, + ); + expect(fetchedPlayer.description, isNull); + }); + + // Verifies that multiple updates to the same player work correctly. + test('Multiple updates to the same player work correctly', () async { + await database.playerDao.addPlayer(player: testPlayer1); + + await database.playerDao.updatePlayerName( + playerId: testPlayer1.id, + newName: 'First Update', + ); + + var fetchedPlayer = await database.playerDao.getPlayerById( + playerId: testPlayer1.id, + ); + expect(fetchedPlayer.name, 'First Update'); + + await database.playerDao.updatePlayerName( + playerId: testPlayer1.id, + newName: 'Second Update', + ); + + fetchedPlayer = await database.playerDao.getPlayerById( + playerId: testPlayer1.id, + ); + expect(fetchedPlayer.name, 'Second Update'); + + await database.playerDao.updatePlayerName( + playerId: testPlayer1.id, + newName: 'Third Update', + ); + + fetchedPlayer = await database.playerDao.getPlayerById( + playerId: testPlayer1.id, + ); + expect(fetchedPlayer.name, 'Third Update'); + }); + + // Verifies that a player with empty string name is stored correctly. + test('Player with empty string name is stored correctly', () async { + final emptyNamePlayer = Player(name: ''); + + await database.playerDao.addPlayer(player: emptyNamePlayer); + + final fetchedPlayer = await database.playerDao.getPlayerById( + playerId: emptyNamePlayer.id, + ); + expect(fetchedPlayer.name, ''); + }); + + // Verifies that a player with very long name is stored correctly. + test('Player with very long name is stored correctly', () async { + final longName = 'A' * 1000; + final longNamePlayer = Player(name: longName); + + await database.playerDao.addPlayer(player: longNamePlayer); + + final fetchedPlayer = await database.playerDao.getPlayerById( + playerId: longNamePlayer.id, + ); + expect(fetchedPlayer.name, longName); + }); + + // Verifies that addPlayer returns true on first add. + test('addPlayer returns true when player is added successfully', () async { + final result = await database.playerDao.addPlayer(player: testPlayer1); + expect(result, true); + + final playerExists = await database.playerDao.playerExists( + playerId: testPlayer1.id, + ); + expect(playerExists, true); + }); }); } From d488eac3ae673ac47e5f6c3de1eceb84d470e15b Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 11:11:37 +0100 Subject: [PATCH 52/87] add more group tests --- test/db_tests/player_group_test.dart | 207 +++++++++++++++++++++++++++ 1 file changed, 207 insertions(+) diff --git a/test/db_tests/player_group_test.dart b/test/db_tests/player_group_test.dart index 660b066..8959092 100644 --- a/test/db_tests/player_group_test.dart +++ b/test/db_tests/player_group_test.dart @@ -100,5 +100,212 @@ void main() { expect(players[i].createdAt, testGroup.members[i].createdAt); } }); + + // Verifies that isPlayerInGroup returns false for non-existent player. + test('isPlayerInGroup returns false for non-existent player', () async { + await database.groupDao.addGroup(group: testGroup); + + final result = await database.playerGroupDao.isPlayerInGroup( + playerId: 'non-existent-player-id', + groupId: testGroup.id, + ); + + expect(result, false); + }); + + // Verifies that isPlayerInGroup returns false for non-existent group. + test('isPlayerInGroup returns false for non-existent group', () async { + await database.playerDao.addPlayer(player: testPlayer1); + + final result = await database.playerGroupDao.isPlayerInGroup( + playerId: testPlayer1.id, + groupId: 'non-existent-group-id', + ); + + expect(result, false); + }); + + // Verifies that addPlayerToGroup returns false when player already in group. + test('addPlayerToGroup returns false when player already in group', () async { + await database.groupDao.addGroup(group: testGroup); + + // testPlayer1 is already in testGroup via group creation + final result = await database.playerGroupDao.addPlayerToGroup( + player: testPlayer1, + groupId: testGroup.id, + ); + + expect(result, false); + }); + + // Verifies that addPlayerToGroup adds player to player table if not exists. + test('addPlayerToGroup adds player to player table if not exists', () async { + await database.groupDao.addGroup(group: testGroup); + + // testPlayer4 is not in the database yet + var playerExists = await database.playerDao.playerExists( + playerId: testPlayer4.id, + ); + expect(playerExists, false); + + await database.playerGroupDao.addPlayerToGroup( + player: testPlayer4, + groupId: testGroup.id, + ); + + // Now player should exist in player table + playerExists = await database.playerDao.playerExists( + playerId: testPlayer4.id, + ); + expect(playerExists, true); + }); + + // Verifies that removePlayerFromGroup returns false for non-existent player. + test('removePlayerFromGroup returns false for non-existent player', () async { + await database.groupDao.addGroup(group: testGroup); + + final result = await database.playerGroupDao.removePlayerFromGroup( + playerId: 'non-existent-player-id', + groupId: testGroup.id, + ); + + expect(result, false); + }); + + // Verifies that removePlayerFromGroup returns false for non-existent group. + test('removePlayerFromGroup returns false for non-existent group', () async { + await database.playerDao.addPlayer(player: testPlayer1); + + final result = await database.playerGroupDao.removePlayerFromGroup( + playerId: testPlayer1.id, + groupId: 'non-existent-group-id', + ); + + expect(result, false); + }); + + // Verifies that getPlayersOfGroup returns empty list for group with no members. + test('getPlayersOfGroup returns empty list for empty group', () async { + final emptyGroup = Group(name: 'Empty Group', members: []); + await database.groupDao.addGroup(group: emptyGroup); + + final players = await database.playerGroupDao.getPlayersOfGroup( + groupId: emptyGroup.id, + ); + + expect(players, isEmpty); + }); + + // Verifies that getPlayersOfGroup returns empty list for non-existent group. + test('getPlayersOfGroup returns empty list for non-existent group', () async { + final players = await database.playerGroupDao.getPlayersOfGroup( + groupId: 'non-existent-group-id', + ); + + expect(players, isEmpty); + }); + + // Verifies that removing all players from a group leaves the group empty. + test('Removing all players from a group leaves group empty', () async { + await database.groupDao.addGroup(group: testGroup); + + for (final player in testGroup.members) { + await database.playerGroupDao.removePlayerFromGroup( + playerId: player.id, + groupId: testGroup.id, + ); + } + + final players = await database.playerGroupDao.getPlayersOfGroup( + groupId: testGroup.id, + ); + expect(players, isEmpty); + + // Group should still exist + final groupExists = await database.groupDao.groupExists( + groupId: testGroup.id, + ); + expect(groupExists, true); + }); + + // Verifies that a player can be in multiple groups. + test('Player can be in multiple groups', () async { + final secondGroup = Group(name: 'Second Group', members: []); + await database.groupDao.addGroup(group: testGroup); + await database.groupDao.addGroup(group: secondGroup); + + // Add testPlayer1 to second group (already in testGroup) + await database.playerGroupDao.addPlayerToGroup( + player: testPlayer1, + groupId: secondGroup.id, + ); + + final inFirstGroup = await database.playerGroupDao.isPlayerInGroup( + playerId: testPlayer1.id, + groupId: testGroup.id, + ); + final inSecondGroup = await database.playerGroupDao.isPlayerInGroup( + playerId: testPlayer1.id, + groupId: secondGroup.id, + ); + + expect(inFirstGroup, true); + expect(inSecondGroup, true); + }); + + // Verifies that removing player from one group doesn't affect other groups. + test('Removing player from one group does not affect other groups', () async { + final secondGroup = Group(name: 'Second Group', members: [testPlayer1]); + await database.groupDao.addGroup(group: testGroup); + await database.groupDao.addGroup(group: secondGroup); + + // Remove testPlayer1 from testGroup + await database.playerGroupDao.removePlayerFromGroup( + playerId: testPlayer1.id, + groupId: testGroup.id, + ); + + final inFirstGroup = await database.playerGroupDao.isPlayerInGroup( + playerId: testPlayer1.id, + groupId: testGroup.id, + ); + final inSecondGroup = await database.playerGroupDao.isPlayerInGroup( + playerId: testPlayer1.id, + groupId: secondGroup.id, + ); + + expect(inFirstGroup, false); + expect(inSecondGroup, true); + }); + + // Verifies that addPlayerToGroup returns true on successful addition. + test('addPlayerToGroup returns true on successful addition', () async { + await database.groupDao.addGroup(group: testGroup); + await database.playerDao.addPlayer(player: testPlayer4); + + final result = await database.playerGroupDao.addPlayerToGroup( + player: testPlayer4, + groupId: testGroup.id, + ); + + expect(result, true); + }); + + // Verifies that removing the same player twice returns false on second attempt. + test('Removing same player twice returns false on second attempt', () async { + await database.groupDao.addGroup(group: testGroup); + + final firstRemoval = await database.playerGroupDao.removePlayerFromGroup( + playerId: testPlayer1.id, + groupId: testGroup.id, + ); + expect(firstRemoval, true); + + final secondRemoval = await database.playerGroupDao.removePlayerFromGroup( + playerId: testPlayer1.id, + groupId: testGroup.id, + ); + expect(secondRemoval, false); + }); }); } From 15894096f33b99eb48805c3897b635fda5d628ee Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 11:11:46 +0100 Subject: [PATCH 53/87] fix missing await error --- lib/data/dao/player_group_dao.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/data/dao/player_group_dao.dart b/lib/data/dao/player_group_dao.dart index db45735..03e26f2 100644 --- a/lib/data/dao/player_group_dao.dart +++ b/lib/data/dao/player_group_dao.dart @@ -27,7 +27,7 @@ class PlayerGroupDao extends DatabaseAccessor } if (!await db.playerDao.playerExists(playerId: player.id)) { - db.playerDao.addPlayer(player: player); + await db.playerDao.addPlayer(player: player); } await into(playerGroupTable).insert( From 2e6a2b8e55d1e2ac460ee1f7a13b13bb45e295fe Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 11:26:46 +0100 Subject: [PATCH 54/87] add more player_match tests --- test/db_tests/player_match_test.dart | 638 ++++++++++++++++++++++++++- 1 file changed, 636 insertions(+), 2 deletions(-) diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/player_match_test.dart index b44ccf6..d6fca6d 100644 --- a/test/db_tests/player_match_test.dart +++ b/test/db_tests/player_match_test.dart @@ -1,5 +1,5 @@ import 'package:clock/clock.dart'; -import 'package:drift/drift.dart' hide isNotNull; +import 'package:drift/drift.dart' hide isNotNull, isNull; import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:game_tracker/data/db/database.dart'; @@ -7,6 +7,7 @@ import 'package:game_tracker/data/dto/game.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/team.dart'; void main() { late AppDatabase database; @@ -20,7 +21,9 @@ void main() { late Game testGame; late Match testMatchOnlyGroup; late Match testMatchOnlyPlayers; - final fixedDate = DateTime(2025, 19, 11, 00, 11, 23); + late Team testTeam1; + late Team testTeam2; + final fixedDate = DateTime(2025, 11, 19, 00, 11, 23); final fakeClock = Clock(() => fixedDate); setUp(() async { @@ -54,6 +57,14 @@ void main() { game: testGame, players: [testPlayer4, testPlayer5, testPlayer6], ); + testTeam1 = Team( + name: 'Team Alpha', + members: [testPlayer1, testPlayer2], + ); + testTeam2 = Team( + name: 'Team Beta', + members: [testPlayer3, testPlayer4], + ); }); await database.playerDao.addPlayersAsList( players: [ @@ -246,5 +257,628 @@ void main() { ); }, ); + + // Verifies that getPlayersOfMatch returns null for a non-existent match. + test('getPlayersOfMatch returns null for non-existent match', () async { + final players = await database.playerMatchDao.getPlayersOfMatch( + matchId: 'non-existent-match-id', + ); + + expect(players, isNull); + }); + + // Verifies that adding a player with initial score works correctly. + test('Adding player with initial score works correctly', () async { + await database.matchDao.addMatch(match: testMatchOnlyGroup); + + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + score: 100, + ); + + final score = await database.playerMatchDao.getPlayerScore( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + ); + + expect(score, 100); + }); + + // Verifies that getPlayerScore returns the correct score. + test('getPlayerScore returns correct score', () async { + await database.matchDao.addMatch(match: testMatchOnlyPlayers); + + // Default score should be 0 when added through match + final score = await database.playerMatchDao.getPlayerScore( + matchId: testMatchOnlyPlayers.id, + playerId: testPlayer4.id, + ); + + expect(score, 0); + }); + + // Verifies that getPlayerScore returns null for non-existent player-match combination. + test('getPlayerScore returns null for non-existent player in match', () async { + await database.matchDao.addMatch(match: testMatchOnlyGroup); + + final score = await database.playerMatchDao.getPlayerScore( + matchId: testMatchOnlyGroup.id, + playerId: 'non-existent-player-id', + ); + + expect(score, isNull); + }); + + // Verifies that updatePlayerScore updates the score correctly. + test('updatePlayerScore updates score correctly', () async { + await database.matchDao.addMatch(match: testMatchOnlyPlayers); + + final updated = await database.playerMatchDao.updatePlayerScore( + matchId: testMatchOnlyPlayers.id, + playerId: testPlayer4.id, + newScore: 50, + ); + + expect(updated, true); + + final score = await database.playerMatchDao.getPlayerScore( + matchId: testMatchOnlyPlayers.id, + playerId: testPlayer4.id, + ); + + expect(score, 50); + }); + + // Verifies that updatePlayerScore returns false for non-existent player-match. + test('updatePlayerScore returns false for non-existent player-match', () async { + await database.matchDao.addMatch(match: testMatchOnlyGroup); + + final updated = await database.playerMatchDao.updatePlayerScore( + matchId: testMatchOnlyGroup.id, + playerId: 'non-existent-player-id', + newScore: 50, + ); + + expect(updated, false); + }); + + // Verifies that adding a player with teamId works correctly. + test('Adding player with teamId works correctly', () async { + await database.matchDao.addMatch(match: testMatchOnlyGroup); + await database.teamDao.addTeam(team: testTeam1); + + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + teamId: testTeam1.id, + ); + + final playersInTeam = await database.playerMatchDao.getPlayersInTeam( + matchId: testMatchOnlyGroup.id, + teamId: testTeam1.id, + ); + + expect(playersInTeam.length, 1); + expect(playersInTeam[0].id, testPlayer1.id); + }); + + // Verifies that updatePlayerTeam updates the team correctly. + test('updatePlayerTeam updates team correctly', () async { + await database.matchDao.addMatch(match: testMatchOnlyGroup); + await database.teamDao.addTeam(team: testTeam1); + await database.teamDao.addTeam(team: testTeam2); + + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + teamId: testTeam1.id, + ); + + // Update player's team + final updated = await database.playerMatchDao.updatePlayerTeam( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + teamId: testTeam2.id, + ); + + expect(updated, true); + + // Verify player is now in testTeam2 + final playersInTeam2 = await database.playerMatchDao.getPlayersInTeam( + matchId: testMatchOnlyGroup.id, + teamId: testTeam2.id, + ); + + expect(playersInTeam2.length, 1); + expect(playersInTeam2[0].id, testPlayer1.id); + + // Verify player is no longer in testTeam1 + final playersInTeam1 = await database.playerMatchDao.getPlayersInTeam( + matchId: testMatchOnlyGroup.id, + teamId: testTeam1.id, + ); + + expect(playersInTeam1.isEmpty, true); + }); + + // Verifies that updatePlayerTeam can set team to null. + test('updatePlayerTeam can remove player from team', () async { + await database.matchDao.addMatch(match: testMatchOnlyGroup); + await database.teamDao.addTeam(team: testTeam1); + + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + teamId: testTeam1.id, + ); + + // Remove player from team by setting teamId to null + final updated = await database.playerMatchDao.updatePlayerTeam( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + teamId: null, + ); + + expect(updated, true); + + final playersInTeam = await database.playerMatchDao.getPlayersInTeam( + matchId: testMatchOnlyGroup.id, + teamId: testTeam1.id, + ); + + expect(playersInTeam.isEmpty, true); + }); + + // Verifies that updatePlayerTeam returns false for non-existent player-match. + test('updatePlayerTeam returns false for non-existent player-match', () async { + await database.matchDao.addMatch(match: testMatchOnlyGroup); + + final updated = await database.playerMatchDao.updatePlayerTeam( + matchId: testMatchOnlyGroup.id, + playerId: 'non-existent-player-id', + teamId: testTeam1.id, + ); + + expect(updated, false); + }); + + // Verifies that getPlayersInTeam returns empty list for non-existent team. + test('getPlayersInTeam returns empty list for non-existent team', () async { + await database.matchDao.addMatch(match: testMatchOnlyPlayers); + + final players = await database.playerMatchDao.getPlayersInTeam( + matchId: testMatchOnlyPlayers.id, + teamId: 'non-existent-team-id', + ); + + expect(players.isEmpty, true); + }); + + // Verifies that getPlayersInTeam returns all players of a team. + test('getPlayersInTeam returns all players of a team', () async { + await database.matchDao.addMatch(match: testMatchOnlyGroup); + await database.teamDao.addTeam(team: testTeam1); + + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + teamId: testTeam1.id, + ); + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer2.id, + teamId: testTeam1.id, + ); + + final playersInTeam = await database.playerMatchDao.getPlayersInTeam( + matchId: testMatchOnlyGroup.id, + teamId: testTeam1.id, + ); + + expect(playersInTeam.length, 2); + final playerIds = playersInTeam.map((p) => p.id).toSet(); + expect(playerIds.contains(testPlayer1.id), true); + expect(playerIds.contains(testPlayer2.id), true); + }); + + // Verifies that removePlayerFromMatch returns false for non-existent player. + test('removePlayerFromMatch returns false for non-existent player', () async { + await database.matchDao.addMatch(match: testMatchOnlyPlayers); + + final removed = await database.playerMatchDao.removePlayerFromMatch( + playerId: 'non-existent-player-id', + matchId: testMatchOnlyPlayers.id, + ); + + expect(removed, false); + }); + + // Verifies that adding the same player twice to the same match is ignored. + test('Adding same player twice to same match is ignored', () async { + await database.matchDao.addMatch(match: testMatchOnlyGroup); + + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + score: 10, + ); + + // Try to add the same player again with different score + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + score: 100, + ); + + // Score should still be 10 because insert was ignored + final score = await database.playerMatchDao.getPlayerScore( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + ); + + expect(score, 10); + + // Verify player count is still 1 + final players = await database.playerMatchDao.getPlayersOfMatch( + matchId: testMatchOnlyGroup.id, + ); + + expect(players?.length, 1); + }); + + // Verifies that updatePlayersFromMatch with empty list removes all players. + test('updatePlayersFromMatch with empty list removes all players', () async { + await database.matchDao.addMatch(match: testMatchOnlyPlayers); + + // Verify players exist initially + var players = await database.playerMatchDao.getPlayersOfMatch( + matchId: testMatchOnlyPlayers.id, + ); + expect(players?.length, 3); + + // Update with empty list + await database.playerMatchDao.updatePlayersFromMatch( + matchId: testMatchOnlyPlayers.id, + newPlayer: [], + ); + + // Verify all players are removed + players = await database.playerMatchDao.getPlayersOfMatch( + matchId: testMatchOnlyPlayers.id, + ); + expect(players, isNull); + }); + + // Verifies that updatePlayersFromMatch with same players makes no changes. + test('updatePlayersFromMatch with same players makes no changes', () async { + await database.matchDao.addMatch(match: testMatchOnlyPlayers); + + final originalPlayers = [testPlayer4, testPlayer5, testPlayer6]; + + await database.playerMatchDao.updatePlayersFromMatch( + matchId: testMatchOnlyPlayers.id, + newPlayer: originalPlayers, + ); + + final players = await database.playerMatchDao.getPlayersOfMatch( + matchId: testMatchOnlyPlayers.id, + ); + + expect(players?.length, originalPlayers.length); + final playerIds = players!.map((p) => p.id).toSet(); + for (final originalPlayer in originalPlayers) { + expect(playerIds.contains(originalPlayer.id), true); + } + }); + + // Verifies that matchHasPlayers returns false for non-existent match. + test('matchHasPlayers returns false for non-existent match', () async { + final hasPlayers = await database.playerMatchDao.matchHasPlayers( + matchId: 'non-existent-match-id', + ); + + expect(hasPlayers, false); + }); + + // Verifies that isPlayerInMatch returns false for non-existent match. + test('isPlayerInMatch returns false for non-existent match', () async { + final isInMatch = await database.playerMatchDao.isPlayerInMatch( + matchId: 'non-existent-match-id', + playerId: testPlayer1.id, + ); + + expect(isInMatch, false); + }); + + // Verifies that updatePlayersFromMatch preserves scores for existing players. + test('updatePlayersFromMatch only modifies player associations', () async { + await database.matchDao.addMatch(match: testMatchOnlyPlayers); + + // Update score for existing player + await database.playerMatchDao.updatePlayerScore( + matchId: testMatchOnlyPlayers.id, + playerId: testPlayer4.id, + newScore: 75, + ); + + // Update players, keeping testPlayer4 and adding testPlayer1 + await database.playerMatchDao.updatePlayersFromMatch( + matchId: testMatchOnlyPlayers.id, + newPlayer: [testPlayer4, testPlayer1], + ); + + // Verify testPlayer4's score is preserved + final score = await database.playerMatchDao.getPlayerScore( + matchId: testMatchOnlyPlayers.id, + playerId: testPlayer4.id, + ); + + expect(score, 75); + + // Verify testPlayer1 was added with default score + final newPlayerScore = await database.playerMatchDao.getPlayerScore( + matchId: testMatchOnlyPlayers.id, + playerId: testPlayer1.id, + ); + + expect(newPlayerScore, 0); + }); + + // Verifies that adding a player with both score and teamId works correctly. + test('Adding player with score and teamId works correctly', () async { + await database.matchDao.addMatch(match: testMatchOnlyGroup); + await database.teamDao.addTeam(team: testTeam1); + + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + teamId: testTeam1.id, + score: 150, + ); + + // Verify score + final score = await database.playerMatchDao.getPlayerScore( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + ); + expect(score, 150); + + // Verify team assignment + final playersInTeam = await database.playerMatchDao.getPlayersInTeam( + matchId: testMatchOnlyGroup.id, + teamId: testTeam1.id, + ); + expect(playersInTeam.length, 1); + expect(playersInTeam[0].id, testPlayer1.id); + }); + + // Verifies that updating score with negative value works. + test('updatePlayerScore with negative score works', () async { + await database.matchDao.addMatch(match: testMatchOnlyPlayers); + + final updated = await database.playerMatchDao.updatePlayerScore( + matchId: testMatchOnlyPlayers.id, + playerId: testPlayer4.id, + newScore: -10, + ); + + expect(updated, true); + + final score = await database.playerMatchDao.getPlayerScore( + matchId: testMatchOnlyPlayers.id, + playerId: testPlayer4.id, + ); + + expect(score, -10); + }); + + // Verifies that updating score with zero value works. + test('updatePlayerScore with zero score works', () async { + await database.matchDao.addMatch(match: testMatchOnlyPlayers); + + // First set a non-zero score + await database.playerMatchDao.updatePlayerScore( + matchId: testMatchOnlyPlayers.id, + playerId: testPlayer4.id, + newScore: 100, + ); + + // Then update to zero + final updated = await database.playerMatchDao.updatePlayerScore( + matchId: testMatchOnlyPlayers.id, + playerId: testPlayer4.id, + newScore: 0, + ); + + expect(updated, true); + + final score = await database.playerMatchDao.getPlayerScore( + matchId: testMatchOnlyPlayers.id, + playerId: testPlayer4.id, + ); + + expect(score, 0); + }); + + // Verifies that getPlayersInTeam returns empty list for non-existent match. + test('getPlayersInTeam returns empty list for non-existent match', () async { + await database.teamDao.addTeam(team: testTeam1); + + final players = await database.playerMatchDao.getPlayersInTeam( + matchId: 'non-existent-match-id', + teamId: testTeam1.id, + ); + + expect(players.isEmpty, true); + }); + + // Verifies that players in different teams within the same match are returned correctly. + test('Players in different teams within same match are separate', () async { + await database.matchDao.addMatch(match: testMatchOnlyGroup); + await database.teamDao.addTeam(team: testTeam1); + await database.teamDao.addTeam(team: testTeam2); + + // Add players to different teams + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + teamId: testTeam1.id, + ); + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer2.id, + teamId: testTeam1.id, + ); + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer3.id, + teamId: testTeam2.id, + ); + + // Verify team 1 players + final playersInTeam1 = await database.playerMatchDao.getPlayersInTeam( + matchId: testMatchOnlyGroup.id, + teamId: testTeam1.id, + ); + expect(playersInTeam1.length, 2); + final team1Ids = playersInTeam1.map((p) => p.id).toSet(); + expect(team1Ids.contains(testPlayer1.id), true); + expect(team1Ids.contains(testPlayer2.id), true); + expect(team1Ids.contains(testPlayer3.id), false); + + // Verify team 2 players + final playersInTeam2 = await database.playerMatchDao.getPlayersInTeam( + matchId: testMatchOnlyGroup.id, + teamId: testTeam2.id, + ); + expect(playersInTeam2.length, 1); + expect(playersInTeam2[0].id, testPlayer3.id); + }); + + // Verifies that removePlayerFromMatch does not affect other matches. + test('removePlayerFromMatch does not affect other matches', () async { + final playersList = [testPlayer1, testPlayer2]; + final match1 = Match(name: 'Match 1', game: testGame, players: playersList); + final match2 = Match(name: 'Match 2', game: testGame, players: playersList); + + await Future.wait([ + database.matchDao.addMatch(match: match1), + database.matchDao.addMatch(match: match2), + ]); + + // Remove player from match1 + final removed = await database.playerMatchDao.removePlayerFromMatch( + playerId: testPlayer1.id, + matchId: match1.id, + ); + expect(removed, true); + + // Verify player is removed from match1 + final isInMatch1 = await database.playerMatchDao.isPlayerInMatch( + matchId: match1.id, + playerId: testPlayer1.id, + ); + expect(isInMatch1, false); + + // Verify player still exists in match2 + final isInMatch2 = await database.playerMatchDao.isPlayerInMatch( + matchId: match2.id, + playerId: testPlayer1.id, + ); + expect(isInMatch2, true); + }); + + // Verifies that updating scores for players in different matches are independent. + test('Player scores are independent across matches', () async { + final playersList = [testPlayer1]; + final match1 = Match(name: 'Match 1', game: testGame, players: playersList); + final match2 = Match(name: 'Match 2', game: testGame, players: playersList); + + await Future.wait([ + database.matchDao.addMatch(match: match1), + database.matchDao.addMatch(match: match2), + ]); + + // Update score in match1 + await database.playerMatchDao.updatePlayerScore( + matchId: match1.id, + playerId: testPlayer1.id, + newScore: 100, + ); + + // Update score in match2 + await database.playerMatchDao.updatePlayerScore( + matchId: match2.id, + playerId: testPlayer1.id, + newScore: 50, + ); + + // Verify scores are independent + final scoreInMatch1 = await database.playerMatchDao.getPlayerScore( + matchId: match1.id, + playerId: testPlayer1.id, + ); + final scoreInMatch2 = await database.playerMatchDao.getPlayerScore( + matchId: match2.id, + playerId: testPlayer1.id, + ); + + expect(scoreInMatch1, 100); + expect(scoreInMatch2, 50); + }); + + // Verifies that updatePlayersFromMatch on non-existent match fails with constraint error. + test('updatePlayersFromMatch on non-existent match fails with foreign key constraint', () async { + // Should throw due to foreign key constraint - match doesn't exist + await expectLater( + database.playerMatchDao.updatePlayersFromMatch( + matchId: 'non-existent-match-id', + newPlayer: [testPlayer1, testPlayer2], + ), + throwsA(anything), + ); + }, skip: 'Skipped: transaction callback is not awaited in the DAO, causing unhandled error'); + + // Verifies that a player can be in a match without being assigned to a team. + test('Player can exist in match without team assignment', () async { + await database.matchDao.addMatch(match: testMatchOnlyGroup); + await database.teamDao.addTeam(team: testTeam1); + + // Add player to match without team + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + ); + + // Add another player to match with team + await database.playerMatchDao.addPlayerToMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer2.id, + teamId: testTeam1.id, + ); + + // Verify both players are in the match + final isPlayer1InMatch = await database.playerMatchDao.isPlayerInMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer1.id, + ); + final isPlayer2InMatch = await database.playerMatchDao.isPlayerInMatch( + matchId: testMatchOnlyGroup.id, + playerId: testPlayer2.id, + ); + + expect(isPlayer1InMatch, true); + expect(isPlayer2InMatch, true); + + // Verify only player2 is in the team + final playersInTeam = await database.playerMatchDao.getPlayersInTeam( + matchId: testMatchOnlyGroup.id, + teamId: testTeam1.id, + ); + + expect(playersInTeam.length, 1); + expect(playersInTeam[0].id, testPlayer2.id); + }); }); } From 748361d04f0701c43fe3bda0c15061357e813bf9 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 11:33:37 +0100 Subject: [PATCH 55/87] add new score tests --- test/db_tests/score_test.dart | 308 +++++++++++++++++++++++++++++++++- 1 file changed, 307 insertions(+), 1 deletion(-) diff --git a/test/db_tests/score_test.dart b/test/db_tests/score_test.dart index 7934c6e..109febf 100644 --- a/test/db_tests/score_test.dart +++ b/test/db_tests/score_test.dart @@ -15,7 +15,7 @@ void main() { late Game testGame; late Match testMatch1; late Match testMatch2; - final fixedDate = DateTime(2025, 19, 11, 00, 11, 23); + final fixedDate = DateTime(2025, 11, 19, 00, 11, 23); final fakeClock = Clock(() => fixedDate); setUp(() async { @@ -426,5 +426,311 @@ void main() { expect(score!.score, 99); expect(score.change, 99); }); + + // Verifies that getScoresForMatch returns empty list for match with no scores. + test('Getting scores for match with no scores returns empty list', () async { + final scores = await database.scoreDao.getScoresForMatch( + matchId: testMatch1.id, + ); + + expect(scores.isEmpty, true); + }); + + // Verifies that getPlayerScoresInMatch returns empty list when player has no scores. + test('Getting player scores with no scores returns empty list', () async { + final playerScores = await database.scoreDao.getPlayerScoresInMatch( + playerId: testPlayer1.id, + matchId: testMatch1.id, + ); + + expect(playerScores.isEmpty, true); + }); + + // Verifies that scores can have negative values. + test('Score can have negative values', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: -10, + change: -10, + ); + + final score = await database.scoreDao.getScoreForRound( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + ); + + expect(score, isNotNull); + expect(score!.score, -10); + expect(score.change, -10); + }); + + // Verifies that scores can have zero values. + test('Score can have zero values', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 0, + change: 0, + ); + + final score = await database.scoreDao.getScoreForRound( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + ); + + expect(score, isNotNull); + expect(score!.score, 0); + expect(score.change, 0); + }); + + // Verifies that very large round numbers are supported. + test('Score supports very large round numbers', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 999999, + score: 100, + change: 100, + ); + + final score = await database.scoreDao.getScoreForRound( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 999999, + ); + + expect(score, isNotNull); + expect(score!.roundNumber, 999999); + }); + + // Verifies that getLatestRoundNumber returns max correctly for non-consecutive rounds. + test('Getting latest round number with non-consecutive rounds', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 5, + score: 50, + change: 40, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 3, + score: 30, + change: 20, + ); + + final latestRound = await database.scoreDao.getLatestRoundNumber( + matchId: testMatch1.id, + ); + + expect(latestRound, 5); + }); + + // Verifies that deleteScoresForMatch returns false when no scores exist. + test('Deleting scores for empty match returns false', () async { + final deleted = await database.scoreDao.deleteScoresForMatch( + matchId: testMatch1.id, + ); + + expect(deleted, false); + }); + + // Verifies that deleteScoresForPlayer returns false when player has no scores. + test('Deleting scores for player with no scores returns false', () async { + final deleted = await database.scoreDao.deleteScoresForPlayer( + playerId: testPlayer1.id, + ); + + expect(deleted, false); + }); + + // Verifies that multiple players in same match can have independent score updates. + test('Multiple players in same match have independent scores', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + await database.scoreDao.addScore( + playerId: testPlayer2.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 20, + change: 20, + ); + + await database.scoreDao.updateScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + newScore: 100, + newChange: 90, + ); + + final player1Score = await database.scoreDao.getScoreForRound( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + ); + final player2Score = await database.scoreDao.getScoreForRound( + playerId: testPlayer2.id, + matchId: testMatch1.id, + roundNumber: 1, + ); + + expect(player1Score!.score, 100); + expect(player2Score!.score, 20); + }); + + // Verifies that scores are isolated across different matches. + test('Scores are isolated across different matches', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch2.id, + roundNumber: 1, + score: 50, + change: 50, + ); + + final match1Scores = await database.scoreDao.getPlayerScoresInMatch( + playerId: testPlayer1.id, + matchId: testMatch1.id, + ); + final match2Scores = await database.scoreDao.getPlayerScoresInMatch( + playerId: testPlayer1.id, + matchId: testMatch2.id, + ); + + expect(match1Scores.length, 1); + expect(match2Scores.length, 1); + expect(match1Scores[0].score, 10); + expect(match2Scores[0].score, 50); + }); + + // Verifies that getTotalScoreForPlayer returns latest score across multiple rounds. + test('Total score for player returns latest cumulative score', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 2, + score: 25, + change: 25, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 3, + score: 50, + change: 25, + ); + + final totalScore = await database.scoreDao.getTotalScoreForPlayer( + playerId: testPlayer1.id, + matchId: testMatch1.id, + ); + + // Should return the highest round's score + expect(totalScore, 50); + }); + + // Verifies that updating one player's score doesn't affect another player's score in same round. + test('Updating one player score does not affect other players in same round', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + await database.scoreDao.addScore( + playerId: testPlayer2.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 20, + change: 20, + ); + await database.scoreDao.addScore( + playerId: testPlayer3.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 30, + change: 30, + ); + + await database.scoreDao.updateScore( + playerId: testPlayer2.id, + matchId: testMatch1.id, + roundNumber: 1, + newScore: 99, + newChange: 89, + ); + + final scores = await database.scoreDao.getScoresForMatch( + matchId: testMatch1.id, + ); + + expect(scores.length, 3); + expect(scores.where((s) => s.playerId == testPlayer1.id).first.score, 10); + expect(scores.where((s) => s.playerId == testPlayer2.id).first.score, 99); + expect(scores.where((s) => s.playerId == testPlayer3.id).first.score, 30); + }); + + // Verifies that deleting a player's scores only affects that specific player. + test('Deleting player scores only affects target player', () async { + await database.scoreDao.addScore( + playerId: testPlayer1.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 10, + change: 10, + ); + await database.scoreDao.addScore( + playerId: testPlayer2.id, + matchId: testMatch1.id, + roundNumber: 1, + score: 20, + change: 20, + ); + + await database.scoreDao.deleteScoresForPlayer( + playerId: testPlayer1.id, + ); + + final match1Scores = await database.scoreDao.getScoresForMatch( + matchId: testMatch1.id, + ); + + expect(match1Scores.length, 1); + expect(match1Scores[0].playerId, testPlayer2.id); + }); }); } From 0b778210efb4732d7b61aad70ed1914930ada943 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 11:36:23 +0100 Subject: [PATCH 56/87] add new team tests --- test/db_tests/team_test.dart | 247 ++++++++++++++++++++++++++++++++++- 1 file changed, 246 insertions(+), 1 deletion(-) diff --git a/test/db_tests/team_test.dart b/test/db_tests/team_test.dart index b0ec349..e3150f5 100644 --- a/test/db_tests/team_test.dart +++ b/test/db_tests/team_test.dart @@ -15,7 +15,7 @@ void main() { late Team testTeam1; late Team testTeam2; late Team testTeam3; - final fixedDate = DateTime(2025, 19, 11, 00, 11, 23); + final fixedDate = DateTime(2025, 11, 19, 00, 11, 23); final fakeClock = Clock(() => fixedDate); setUp(() async { @@ -234,5 +234,250 @@ void main() { ); expect(fetchedTeam.name, testTeam1.name); }); + + // Verifies that getAllTeams returns empty list when no teams exist. + test('Getting all teams when empty returns empty list', () async { + final allTeams = await database.teamDao.getAllTeams(); + expect(allTeams.isEmpty, true); + }); + + // Verifies that getTeamById throws exception for non-existent team. + test('Getting non-existent team throws exception', () async { + expect( + () => database.teamDao.getTeamById(teamId: 'non-existent-id'), + throwsA(isA()), + ); + }); + + // Verifies that updating team name preserves other fields. + test('Updating team name preserves other team fields', () async { + await database.teamDao.addTeam(team: testTeam1); + final originalTeam = await database.teamDao.getTeamById( + teamId: testTeam1.id, + ); + final originalCreatedAt = originalTeam.createdAt; + + const newName = 'Brand New Team Name'; + await database.teamDao.updateTeamName( + teamId: testTeam1.id, + newName: newName, + ); + + final updatedTeam = await database.teamDao.getTeamById( + teamId: testTeam1.id, + ); + + expect(updatedTeam.name, newName); + expect(updatedTeam.id, testTeam1.id); + expect(updatedTeam.createdAt, originalCreatedAt); + }); + + // Verifies that team name can be updated to an empty string. + test('Updating team name to empty string works', () async { + await database.teamDao.addTeam(team: testTeam1); + + await database.teamDao.updateTeamName( + teamId: testTeam1.id, + newName: '', + ); + + final updatedTeam = await database.teamDao.getTeamById( + teamId: testTeam1.id, + ); + + expect(updatedTeam.name, ''); + }); + + // Verifies that team name can be updated to a very long string. + test('Updating team name to long string works', () async { + await database.teamDao.addTeam(team: testTeam1); + final longName = 'A' * 500; // 500 character name + + await database.teamDao.updateTeamName( + teamId: testTeam1.id, + newName: longName, + ); + + final updatedTeam = await database.teamDao.getTeamById( + teamId: testTeam1.id, + ); + + expect(updatedTeam.name, longName); + expect(updatedTeam.name.length, 500); + }); + + // Verifies that updating non-existent team name doesn't throw error. + test('Updating non-existent team name completes without error', () async { + expect( + () => database.teamDao.updateTeamName( + teamId: 'non-existent-id', + newName: 'New Name', + ), + returnsNormally, + ); + }); + + // Verifies that deleteTeam only affects the specified team. + test('Deleting one team does not affect other teams', () async { + await database.teamDao.addTeamsAsList( + teams: [testTeam1, testTeam2, testTeam3], + ); + + await database.teamDao.deleteTeam(teamId: testTeam2.id); + + final allTeams = await database.teamDao.getAllTeams(); + expect(allTeams.length, 2); + expect(allTeams.any((t) => t.id == testTeam1.id), true); + expect(allTeams.any((t) => t.id == testTeam2.id), false); + expect(allTeams.any((t) => t.id == testTeam3.id), true); + }); + + // Verifies that teams with overlapping members are independent. + test('Teams with overlapping members are independent', () async { + // testTeam1 has [player1, player2] + // testTeam3 has [player1, player3] + await database.teamDao.addTeamsAsList( + teams: [testTeam1, testTeam3], + ); + + final team1 = await database.teamDao.getTeamById(teamId: testTeam1.id); + final team3 = await database.teamDao.getTeamById(teamId: testTeam3.id); + + expect(team1.members.length, 2); + expect(team3.members.length, 2); + expect(team1.members.any((p) => p.id == testPlayer1.id), true); + expect(team3.members.any((p) => p.id == testPlayer1.id), true); + }); + + // Verifies that adding teams sequentially works correctly. + test('Adding teams sequentially maintains correct count', () async { + var count = await database.teamDao.getTeamCount(); + expect(count, 0); + + await database.teamDao.addTeam(team: testTeam1); + count = await database.teamDao.getTeamCount(); + expect(count, 1); + + await database.teamDao.addTeam(team: testTeam2); + count = await database.teamDao.getTeamCount(); + expect(count, 2); + + await database.teamDao.addTeam(team: testTeam3); + count = await database.teamDao.getTeamCount(); + expect(count, 3); + }); + + // Verifies that getAllTeams returns all teams with correct data. + test('Getting all teams returns all teams with correct data', () async { + await database.teamDao.addTeamsAsList( + teams: [testTeam1, testTeam2, testTeam3], + ); + + final allTeams = await database.teamDao.getAllTeams(); + + expect(allTeams.length, 3); + expect( + allTeams.map((t) => t.id).toSet(), + {testTeam1.id, testTeam2.id, testTeam3.id}, + ); + }); + + // Verifies that teamExists returns false for deleted teams. + test('Team existence returns false after deletion', () async { + await database.teamDao.addTeam(team: testTeam1); + expect(await database.teamDao.teamExists(teamId: testTeam1.id), true); + + await database.teamDao.deleteTeam(teamId: testTeam1.id); + expect(await database.teamDao.teamExists(teamId: testTeam1.id), false); + }); + + // Verifies that adding multiple teams in batch then deleting returns correct count. + test('Batch add then partial delete maintains correct count', () async { + await database.teamDao.addTeamsAsList( + teams: [testTeam1, testTeam2, testTeam3], + ); + + expect(await database.teamDao.getTeamCount(), 3); + + await database.teamDao.deleteTeam(teamId: testTeam1.id); + expect(await database.teamDao.getTeamCount(), 2); + + await database.teamDao.deleteTeam(teamId: testTeam3.id); + expect(await database.teamDao.getTeamCount(), 1); + }); + + // Verifies that deleteAllTeams with single team works. + test('Deleting all teams with single team returns true', () async { + await database.teamDao.addTeam(team: testTeam1); + expect(await database.teamDao.getTeamCount(), 1); + + final deleted = await database.teamDao.deleteAllTeams(); + expect(deleted, true); + expect(await database.teamDao.getTeamCount(), 0); + }); + + // Verifies that addTeam after deleteAllTeams works correctly. + test('Adding team after deleteAllTeams works correctly', () async { + await database.teamDao.addTeamsAsList( + teams: [testTeam1, testTeam2], + ); + expect(await database.teamDao.getTeamCount(), 2); + + await database.teamDao.deleteAllTeams(); + expect(await database.teamDao.getTeamCount(), 0); + + final added = await database.teamDao.addTeam(team: testTeam3); + expect(added, true); + expect(await database.teamDao.getTeamCount(), 1); + + final fetchedTeam = await database.teamDao.getTeamById( + teamId: testTeam3.id, + ); + expect(fetchedTeam.name, testTeam3.name); + }); + + // Verifies that addTeamsAsList with partial duplicates ignores duplicates. + test('Adding teams with some duplicates ignores only duplicates', () async { + await database.teamDao.addTeam(team: testTeam1); + + final duplicateTeam1 = Team( + id: testTeam1.id, + name: 'Different Name', + members: [testPlayer3], + ); + + await database.teamDao.addTeamsAsList( + teams: [duplicateTeam1, testTeam2, testTeam3], + ); + + final allTeams = await database.teamDao.getAllTeams(); + expect(allTeams.length, 3); + + // Verify testTeam1 retained original name (was inserted first) + final team1 = await database.teamDao.getTeamById(teamId: testTeam1.id); + expect(team1.name, testTeam1.name); + }); + + // Verifies that team IDs are preserved correctly. + test('Team IDs are preserved through add and retrieve', () async { + await database.teamDao.addTeam(team: testTeam1); + + final fetchedTeam = await database.teamDao.getTeamById( + teamId: testTeam1.id, + ); + + expect(fetchedTeam.id, testTeam1.id); + }); + + // Verifies that createdAt timestamps are preserved. + test('Team createdAt timestamps are preserved', () async { + await database.teamDao.addTeam(team: testTeam1); + + final fetchedTeam = await database.teamDao.getTeamById( + teamId: testTeam1.id, + ); + + expect(fetchedTeam.createdAt, testTeam1.createdAt); + }); }); } \ No newline at end of file From f142169371371e256bafe1916c0dd1394441ea76 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 11:54:00 +0100 Subject: [PATCH 57/87] fix overlapping members in teams test --- test/db_tests/team_test.dart | 47 ++++++++++++++++++++++++++++++++++-- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/test/db_tests/team_test.dart b/test/db_tests/team_test.dart index e3150f5..2725411 100644 --- a/test/db_tests/team_test.dart +++ b/test/db_tests/team_test.dart @@ -3,6 +3,8 @@ import 'package:drift/drift.dart'; import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.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/team.dart'; @@ -15,6 +17,8 @@ void main() { late Team testTeam1; late Team testTeam2; late Team testTeam3; + late Game testGame1; + late Game testGame2; final fixedDate = DateTime(2025, 11, 19, 00, 11, 23); final fakeClock = Clock(() => fixedDate); @@ -44,11 +48,15 @@ void main() { name: 'Team Gamma', members: [testPlayer1, testPlayer3], ); + testGame1 = Game(name: 'Game 1'); + testGame2 = Game(name: 'Game 2'); }); await database.playerDao.addPlayersAsList( players: [testPlayer1, testPlayer2, testPlayer3, testPlayer4], ); + await database.gameDao.addGame(game: testGame1); + await database.gameDao.addGame(game: testGame2); }); tearDown(() async { @@ -334,12 +342,47 @@ void main() { // Verifies that teams with overlapping members are independent. test('Teams with overlapping members are independent', () async { - // testTeam1 has [player1, player2] - // testTeam3 has [player1, player3] + // Create two matches since player_match has primary key {playerId, matchId} + final match1 = Match(name: 'Match 1', game: testGame1); + final match2 = Match(name: 'Match 2', game: testGame2); + await database.matchDao.addMatch(match: match1); + await database.matchDao.addMatch(match: match2); + + // Add teams to database await database.teamDao.addTeamsAsList( teams: [testTeam1, testTeam3], ); + // Associate players with teams through match1 + // testTeam1: player1, player2 + await database.playerMatchDao.addPlayerToMatch( + playerId: testPlayer1.id, + matchId: match1.id, + teamId: testTeam1.id, + score: 0, + ); + await database.playerMatchDao.addPlayerToMatch( + playerId: testPlayer2.id, + matchId: match1.id, + teamId: testTeam1.id, + score: 0, + ); + + // Associate players with teams through match2 + // testTeam3: player1, player3 (overlapping player1) + await database.playerMatchDao.addPlayerToMatch( + playerId: testPlayer1.id, + matchId: match2.id, + teamId: testTeam3.id, + score: 0, + ); + await database.playerMatchDao.addPlayerToMatch( + playerId: testPlayer3.id, + matchId: match2.id, + teamId: testTeam3.id, + score: 0, + ); + final team1 = await database.teamDao.getTeamById(teamId: testTeam1.id); final team3 = await database.teamDao.getTeamById(teamId: testTeam3.id); From b2a3a0cf7513629c65409cc941306e78ac71549b Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 11:55:15 +0100 Subject: [PATCH 58/87] fix getting non-existent team throws exception test --- test/db_tests/team_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/db_tests/team_test.dart b/test/db_tests/team_test.dart index 2725411..df2c93c 100644 --- a/test/db_tests/team_test.dart +++ b/test/db_tests/team_test.dart @@ -253,7 +253,7 @@ void main() { test('Getting non-existent team throws exception', () async { expect( () => database.teamDao.getTeamById(teamId: 'non-existent-id'), - throwsA(isA()), + throwsA(isA()), ); }); From e55cea0dcc0aade506bb1a4822c8376811361611 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 12:04:00 +0100 Subject: [PATCH 59/87] fix missing await --- lib/data/dao/player_match_dao.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/data/dao/player_match_dao.dart b/lib/data/dao/player_match_dao.dart index a2185e6..7de22a4 100644 --- a/lib/data/dao/player_match_dao.dart +++ b/lib/data/dao/player_match_dao.dart @@ -148,7 +148,7 @@ class PlayerMatchDao extends DatabaseAccessor final playersToAdd = newPlayerIdsSet.difference(currentPlayerIds); final playersToRemove = currentPlayerIds.difference(newPlayerIdsSet); - db.transaction(() async { + await db.transaction(() async { // Remove old players if (playersToRemove.isNotEmpty) { await (delete(playerMatchTable)..where( From 12b713bb707b3c2564d1b3e98564f0bed23579c7 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 12:04:13 +0100 Subject: [PATCH 60/87] remove skip from test --- test/db_tests/player_match_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/player_match_test.dart index d6fca6d..8c68395 100644 --- a/test/db_tests/player_match_test.dart +++ b/test/db_tests/player_match_test.dart @@ -838,7 +838,7 @@ void main() { ), throwsA(anything), ); - }, skip: 'Skipped: transaction callback is not awaited in the DAO, causing unhandled error'); + }); // Verifies that a player can be in a match without being assigned to a team. test('Player can exist in match without team assignment', () async { From bd5e38a3cad87e6e3aab4c3f2da51a582a27e272 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 15:42:47 +0100 Subject: [PATCH 61/87] save game to database on create --- .../create_match/create_match_view.dart | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index 2f512bb..eb630df 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -4,6 +4,7 @@ import 'package:game_tracker/core/constants.dart'; import 'package:game_tracker/core/custom_theme.dart'; import 'package:game_tracker/core/enums.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/match.dart'; import 'package:game_tracker/data/dto/player.dart'; @@ -192,11 +193,34 @@ class _CreateMatchViewState extends State { buttonType: ButtonType.primary, onPressed: _enableCreateGameButton() ? () async { + // Use a game from the games list + Game? gameToUse; + if (selectedGameIndex == -1) { + // Use the first game as default if none selected + final selectedGame = games[0]; + gameToUse = Game( + name: selectedGame.$1, + description: selectedGame.$2, + ruleset: selectedGame.$3.name, + ); + } else { + // Use the selected game from the list + final selectedGame = games[selectedGameIndex]; + gameToUse = Game( + name: selectedGame.$1, + description: selectedGame.$2, + ruleset: selectedGame.$3.name, + ); + } + // Add the game to the database if it doesn't exist + await db.gameDao.addGame(game: gameToUse); + Match match = Match( name: _matchNameController.text.isEmpty ? (hintText ?? '') : _matchNameController.text.trim(), createdAt: DateTime.now(), + game: gameToUse, group: selectedGroup, players: selectedPlayers, ); From 7339194ba04fc2f0bb90fe0f997de810528e8950 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 15:43:56 +0100 Subject: [PATCH 62/87] fix data import and export --- assets/schema.json | 80 ++++++++++++++++++- lib/data/dto/group.dart | 11 ++- lib/data/dto/match.dart | 23 +++--- lib/data/dto/team.dart | 11 ++- lib/services/data_transfer_service.dart | 101 ++++++++++++++++++------ 5 files changed, 176 insertions(+), 50 deletions(-) diff --git a/assets/schema.json b/assets/schema.json index b3a8a2c..3aab588 100644 --- a/assets/schema.json +++ b/assets/schema.json @@ -15,6 +15,43 @@ }, "name": { "type": "string" + }, + "description": { + "type": ["string", "null"] + } + }, + "required": [ + "id", + "createdAt", + "name" + ] + } + }, + "games": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "name": { + "type": "string" + }, + "ruleset": { + "type": ["string", "null"] + }, + "description": { + "type": ["string", "null"] + }, + "color": { + "type": ["integer", "null"] + }, + "icon": { + "type": ["string", "null"] } }, "required": [ @@ -25,6 +62,38 @@ } }, "groups": { + "type": "array", + "items": { + "type": "object", + "properties": { + "id": { + "type": "string" + }, + "name": { + "type": "string" + }, + "createdAt": { + "type": "string" + }, + "description": { + "type": ["string", "null"] + }, + "memberIds": { + "type": "array", + "items": { + "type": "string" + } + } + }, + "required": [ + "id", + "name", + "createdAt", + "memberIds" + ] + } + }, + "teams": { "type": "array", "items": { "type": "object", @@ -67,6 +136,12 @@ "createdAt": { "type": "string" }, + "gameId": { + "anyOf": [ + {"type": "string"}, + {"type": "null"} + ] + }, "groupId": { "anyOf": [ {"type": "string"}, @@ -79,7 +154,7 @@ "type": "string" } }, - "winnerId": { + "notes": { "anyOf": [ {"type": "string"}, {"type": "null"} @@ -90,7 +165,6 @@ "id", "name", "createdAt", - "groupId", "playerIds" ] } @@ -98,7 +172,9 @@ }, "required": [ "players", + "games", "groups", + "teams", "matches" ] } \ No newline at end of file diff --git a/lib/data/dto/group.dart b/lib/data/dto/group.dart index 4a6f7cd..a69c982 100644 --- a/lib/data/dto/group.dart +++ b/lib/data/dto/group.dart @@ -23,22 +23,21 @@ class Group { return 'Group{id: $id, name: $name, description: $description, members: $members}'; } - /// Creates a Group instance from a JSON object. + /// Creates a Group instance from a JSON object (memberIds format). + /// Player objects are reconstructed from memberIds by the DataTransferService. Group.fromJson(Map json) : id = json['id'], createdAt = DateTime.parse(json['createdAt']), name = json['name'], description = json['description'], - members = (json['members'] as List) - .map((memberJson) => Player.fromJson(memberJson)) - .toList(); + members = []; // Populated during import via DataTransferService - /// Converts the Group instance to a JSON object. + /// Converts the Group instance to a JSON object using normalized format (memberIds only). Map toJson() => { 'id': id, 'createdAt': createdAt.toIso8601String(), 'name': name, 'description': description, - 'members': members.map((member) => member.toJson()).toList(), + 'memberIds': members.map((member) => member.id).toList(), }; } diff --git a/lib/data/dto/match.dart b/lib/data/dto/match.dart index 6963b4f..b71757a 100644 --- a/lib/data/dto/match.dart +++ b/lib/data/dto/match.dart @@ -28,31 +28,28 @@ class Match { @override String toString() { - return 'Match{id: $id, name: $name, game: $game, group: $group, players: $players, notes: $notes, winner: $winner}'; + return 'Match{id: $id, name: $name, game: $game, group: $group, players: $players, notes: $notes}'; } - /// Creates a Match instance from a JSON object. + /// Creates a Match instance from a JSON object (ID references format). + /// Related objects are reconstructed from IDs by the DataTransferService. Match.fromJson(Map json) : id = json['id'], createdAt = DateTime.parse(json['createdAt']), name = json['name'], - game = json['game'] != null ? Game.fromJson(json['game']) : null, - group = json['group'] != null ? Group.fromJson(json['group']) : null, - players = json['players'] != null - ? (json['players'] as List) - .map((playerJson) => Player.fromJson(playerJson)) - .toList() - : null, + game = null, // Populated during import via DataTransferService + group = null, // Populated during import via DataTransferService + players = [], // Populated during import via DataTransferService notes = json['notes']; - /// Converts the Match instance to a JSON object. + /// Converts the Match instance to a JSON object using normalized format (ID references only). Map toJson() => { 'id': id, 'createdAt': createdAt.toIso8601String(), 'name': name, - 'game': game?.toJson(), - 'group': group?.toJson(), - 'players': players?.map((player) => player.toJson()).toList(), + 'gameId': game?.id, + 'groupId': group?.id, + 'playerIds': (players ?? []).map((player) => player.id).toList(), 'notes': notes, }; } diff --git a/lib/data/dto/team.dart b/lib/data/dto/team.dart index a3f78d5..46eb5ca 100644 --- a/lib/data/dto/team.dart +++ b/lib/data/dto/team.dart @@ -21,21 +21,20 @@ class Team { return 'Team{id: $id, name: $name, members: $members}'; } - /// Creates a Team instance from a JSON object. + /// Creates a Team instance from a JSON object (memberIds format). + /// Player objects are reconstructed from memberIds by the DataTransferService. Team.fromJson(Map json) : id = json['id'], name = json['name'], createdAt = DateTime.parse(json['createdAt']), - members = (json['members'] as List) - .map((memberJson) => Player.fromJson(memberJson)) - .toList(); + members = []; // Populated during import via DataTransferService - /// Converts the Team instance to a JSON object. + /// Converts the Team instance to a JSON object using normalized format (memberIds only). Map toJson() => { 'id': id, 'name': name, 'createdAt': createdAt.toIso8601String(), - 'members': members.map((member) => member.toJson()).toList(), + 'memberIds': members.map((member) => member.id).toList(), }; } diff --git a/lib/services/data_transfer_service.dart b/lib/services/data_transfer_service.dart index 8767c59..801fd96 100644 --- a/lib/services/data_transfer_service.dart +++ b/lib/services/data_transfer_service.dart @@ -6,9 +6,11 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:game_tracker/core/enums.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/match.dart'; import 'package:game_tracker/data/dto/player.dart'; +import 'package:game_tracker/data/dto/team.dart'; import 'package:json_schema/json_schema.dart'; import 'package:provider/provider.dart'; @@ -17,39 +19,54 @@ class DataTransferService { static Future deleteAllData(BuildContext context) async { final db = Provider.of(context, listen: false); await db.matchDao.deleteAllMatches(); + await db.teamDao.deleteAllTeams(); await db.groupDao.deleteAllGroups(); + await db.gameDao.deleteAllGames(); await db.playerDao.deleteAllPlayers(); } /// Retrieves all application data and converts it to a JSON string. - /// Returns the JSON string representation of the data. + /// Returns the JSON string representation of the data in normalized format. static Future getAppDataAsJson(BuildContext context) async { final db = Provider.of(context, listen: false); final matches = await db.matchDao.getAllMatches(); final groups = await db.groupDao.getAllGroups(); final players = await db.playerDao.getAllPlayers(); + final games = await db.gameDao.getAllGames(); + final teams = await db.teamDao.getAllTeams(); - // Construct a JSON representation of the data + // Construct a JSON representation of the data in normalized format final Map jsonMap = { 'players': players.map((p) => p.toJson()).toList(), - + 'games': games.map((g) => g.toJson()).toList(), 'groups': groups .map((g) => { - 'id': g.id, - 'name': g.name, - 'createdAt': g.createdAt.toIso8601String(), - 'memberIds': (g.members).map((m) => m.id).toList(), - }).toList(), - + 'id': g.id, + 'name': g.name, + 'description': g.description, + 'createdAt': g.createdAt.toIso8601String(), + 'memberIds': (g.members).map((m) => m.id).toList(), + }) + .toList(), + 'teams': teams + .map((t) => { + 'id': t.id, + 'name': t.name, + 'createdAt': t.createdAt.toIso8601String(), + 'memberIds': (t.members).map((m) => m.id).toList(), + }) + .toList(), 'matches': matches .map((m) => { - 'id': m.id, - 'name': m.name, - 'createdAt': m.createdAt.toIso8601String(), - 'groupId': m.group?.id, - 'playerIds': (m.players ?? []).map((p) => p.id).toList(), - 'winnerId': m.winner?.id, - }).toList(), + 'id': m.id, + 'name': m.name, + 'createdAt': m.createdAt.toIso8601String(), + 'gameId': m.game?.id, + 'groupId': m.group?.id, + 'playerIds': (m.players ?? []).map((p) => p.id).toList(), + 'notes': m.notes, + }) + .toList(), }; return json.encode(jsonMap); @@ -107,10 +124,12 @@ class DataTransferService { final Map decoded = json.decode(jsonString) as Map; final List playersJson = (decoded['players'] as List?) ?? []; + final List gamesJson = (decoded['games'] as List?) ?? []; final List groupsJson = (decoded['groups'] as List?) ?? []; + final List teamsJson = (decoded['teams'] as List?) ?? []; final List matchesJson = (decoded['matches'] as List?) ?? []; - // Players + // Import Players final List importedPlayers = playersJson .map((p) => Player.fromJson(p as Map)) .toList(); @@ -119,7 +138,16 @@ class DataTransferService { for (final p in importedPlayers) p.id: p, }; - // Groups + // Import Games + final List importedGames = gamesJson + .map((g) => Game.fromJson(g as Map)) + .toList(); + + final Map gameById = { + for (final g in importedGames) g.id: g, + }; + + // Import Groups final List importedGroups = groupsJson.map((g) { final map = g as Map; final memberIds = (map['memberIds'] as List? ?? []).cast(); @@ -132,6 +160,7 @@ class DataTransferService { return Group( id: map['id'] as String, name: map['name'] as String, + description: map['description'] as String?, members: members, createdAt: DateTime.parse(map['createdAt'] as String), ); @@ -141,33 +170,59 @@ class DataTransferService { for (final g in importedGroups) g.id: g, }; - // Matches + // Import Teams + final List importedTeams = teamsJson.map((t) { + final map = t as Map; + final memberIds = (map['memberIds'] as List? ?? []).cast(); + + final members = memberIds + .map((id) => playerById[id]) + .whereType() + .toList(); + + return Team( + id: map['id'] as String, + name: map['name'] as String, + members: members, + createdAt: DateTime.parse(map['createdAt'] as String), + ); + }).toList(); + + final Map teamById = { + for (final t in importedTeams) t.id: t, + }; + + // Import Matches final List importedMatches = matchesJson.map((m) { final map = m as Map; + final String? gameId = map['gameId'] as String?; final String? groupId = map['groupId'] as String?; final List playerIds = (map['playerIds'] as List? ?? []).cast(); - final String? winnerId = map['winnerId'] as String?; + final game = (gameId == null) ? null : gameById[gameId]; final group = (groupId == null) ? null : groupById[groupId]; final players = playerIds .map((id) => playerById[id]) .whereType() .toList(); - final winner = (winnerId == null) ? null : playerById[winnerId]; return Match( id: map['id'] as String, name: map['name'] as String, + game: game, group: group, - players: players, + players: players.isNotEmpty ? players : null, createdAt: DateTime.parse(map['createdAt'] as String), - winner: winner, + notes: map['notes'] as String?, ); }).toList(); + // Import all data into the database await db.playerDao.addPlayersAsList(players: importedPlayers); + await db.gameDao.addGamesAsList(games: importedGames); await db.groupDao.addGroupsAsList(groups: importedGroups); + await db.teamDao.addTeamsAsList(teams: importedTeams); await db.matchDao.addMatchAsList(matches: importedMatches); return ImportResult.success; From 0ddb4edbc94ab53aa8df32295db0e38e47f417b9 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 21 Jan 2026 16:08:21 +0100 Subject: [PATCH 63/87] remove unused variable --- lib/services/data_transfer_service.dart | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/services/data_transfer_service.dart b/lib/services/data_transfer_service.dart index 801fd96..e659e45 100644 --- a/lib/services/data_transfer_service.dart +++ b/lib/services/data_transfer_service.dart @@ -188,10 +188,6 @@ class DataTransferService { ); }).toList(); - final Map teamById = { - for (final t in importedTeams) t.id: t, - }; - // Import Matches final List importedMatches = matchesJson.map((m) { final map = m as Map; From 55f5aac4e2e7f6648f92098816cb89f4b0679932 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 23 Jan 2026 11:08:11 +0100 Subject: [PATCH 64/87] color is now a required game parameter --- lib/data/dao/game_dao.dart | 12 +++--- lib/data/dao/match_dao.dart | 2 +- lib/data/db/database.g.dart | 43 +++++++++---------- lib/data/db/tables/game_table.dart | 2 +- lib/data/dto/game.dart | 4 +- .../create_match/create_match_view.dart | 2 + test/db_tests/game_test.dart | 37 ++++++---------- test/db_tests/match_test.dart | 2 +- test/db_tests/player_match_test.dart | 2 +- test/db_tests/score_test.dart | 2 +- test/db_tests/team_test.dart | 4 +- 11 files changed, 51 insertions(+), 61 deletions(-) diff --git a/lib/data/dao/game_dao.dart b/lib/data/dao/game_dao.dart index 4b99dfa..1d8af98 100644 --- a/lib/data/dao/game_dao.dart +++ b/lib/data/dao/game_dao.dart @@ -20,7 +20,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { name: row.name, ruleset: row.ruleset, description: row.description, - color: row.color != null ? int.tryParse(row.color!) : null, + color: row.color, icon: row.icon, createdAt: row.createdAt, ), @@ -37,7 +37,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { name: result.name, ruleset: result.ruleset, description: result.description, - color: result.color != null ? int.tryParse(result.color!) : null, + color: result.color, icon: result.icon, createdAt: result.createdAt, ); @@ -54,7 +54,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { name: game.name, ruleset: game.ruleset ?? '', description: Value(game.description), - color: Value(game.color?.toString()), + color: game.color, icon: Value(game.icon), createdAt: game.createdAt, ), @@ -80,7 +80,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { name: game.name, ruleset: game.ruleset ?? '', description: Value(game.description), - color: Value(game.color?.toString()), + color: game.color, icon: Value(game.icon), createdAt: game.createdAt, ), @@ -142,10 +142,10 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { /// Updates the color of the game with the given [gameId]. Future updateGameColor({ required String gameId, - required int? newColor, + required String newColor, }) async { await (update(gameTable)..where((g) => g.id.equals(gameId))).write( - GameTableCompanion(color: Value(newColor?.toString())), + GameTableCompanion(color: Value(newColor)), ); } diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index 7c67e08..af6d602 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -129,7 +129,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { name: game.name, ruleset: game.ruleset ?? '', description: Value(game.description), - color: Value(game.color?.toString()), + color: game.color, icon: Value(game.icon), createdAt: game.createdAt, ), diff --git a/lib/data/db/database.g.dart b/lib/data/db/database.g.dart index fbc76f0..a2d99c1 100644 --- a/lib/data/db/database.g.dart +++ b/lib/data/db/database.g.dart @@ -682,9 +682,9 @@ class $GameTableTable extends GameTable late final GeneratedColumn color = GeneratedColumn( 'color', aliasedName, - true, + false, type: DriftSqlType.string, - requiredDuringInsert: false, + requiredDuringInsert: true, ); static const VerificationMeta _iconMeta = const VerificationMeta('icon'); @override @@ -763,6 +763,8 @@ class $GameTableTable extends GameTable _colorMeta, color.isAcceptableOrUnknown(data['color']!, _colorMeta), ); + } else if (isInserting) { + context.missing(_colorMeta); } if (data.containsKey('icon')) { context.handle( @@ -806,7 +808,7 @@ class $GameTableTable extends GameTable color: attachedDatabase.typeMapping.read( DriftSqlType.string, data['${effectivePrefix}color'], - ), + )!, icon: attachedDatabase.typeMapping.read( DriftSqlType.string, data['${effectivePrefix}icon'], @@ -829,7 +831,7 @@ class GameTableData extends DataClass implements Insertable { final String name; final String ruleset; final String? description; - final String? color; + final String color; final String? icon; final DateTime createdAt; const GameTableData({ @@ -837,7 +839,7 @@ class GameTableData extends DataClass implements Insertable { required this.name, required this.ruleset, this.description, - this.color, + required this.color, this.icon, required this.createdAt, }); @@ -850,9 +852,7 @@ class GameTableData extends DataClass implements Insertable { if (!nullToAbsent || description != null) { map['description'] = Variable(description); } - if (!nullToAbsent || color != null) { - map['color'] = Variable(color); - } + map['color'] = Variable(color); if (!nullToAbsent || icon != null) { map['icon'] = Variable(icon); } @@ -868,9 +868,7 @@ class GameTableData extends DataClass implements Insertable { description: description == null && nullToAbsent ? const Value.absent() : Value(description), - color: color == null && nullToAbsent - ? const Value.absent() - : Value(color), + color: Value(color), icon: icon == null && nullToAbsent ? const Value.absent() : Value(icon), createdAt: Value(createdAt), ); @@ -886,7 +884,7 @@ class GameTableData extends DataClass implements Insertable { name: serializer.fromJson(json['name']), ruleset: serializer.fromJson(json['ruleset']), description: serializer.fromJson(json['description']), - color: serializer.fromJson(json['color']), + color: serializer.fromJson(json['color']), icon: serializer.fromJson(json['icon']), createdAt: serializer.fromJson(json['createdAt']), ); @@ -899,7 +897,7 @@ class GameTableData extends DataClass implements Insertable { 'name': serializer.toJson(name), 'ruleset': serializer.toJson(ruleset), 'description': serializer.toJson(description), - 'color': serializer.toJson(color), + 'color': serializer.toJson(color), 'icon': serializer.toJson(icon), 'createdAt': serializer.toJson(createdAt), }; @@ -910,7 +908,7 @@ class GameTableData extends DataClass implements Insertable { String? name, String? ruleset, Value description = const Value.absent(), - Value color = const Value.absent(), + String? color, Value icon = const Value.absent(), DateTime? createdAt, }) => GameTableData( @@ -918,7 +916,7 @@ class GameTableData extends DataClass implements Insertable { name: name ?? this.name, ruleset: ruleset ?? this.ruleset, description: description.present ? description.value : this.description, - color: color.present ? color.value : this.color, + color: color ?? this.color, icon: icon.present ? icon.value : this.icon, createdAt: createdAt ?? this.createdAt, ); @@ -971,7 +969,7 @@ class GameTableCompanion extends UpdateCompanion { final Value name; final Value ruleset; final Value description; - final Value color; + final Value color; final Value icon; final Value createdAt; final Value rowid; @@ -990,13 +988,14 @@ class GameTableCompanion extends UpdateCompanion { required String name, required String ruleset, this.description = const Value.absent(), - this.color = const Value.absent(), + required String color, this.icon = const Value.absent(), required DateTime createdAt, this.rowid = const Value.absent(), }) : id = Value(id), name = Value(name), ruleset = Value(ruleset), + color = Value(color), createdAt = Value(createdAt); static Insertable custom({ Expression? id, @@ -1025,7 +1024,7 @@ class GameTableCompanion extends UpdateCompanion { Value? name, Value? ruleset, Value? description, - Value? color, + Value? color, Value? icon, Value? createdAt, Value? rowid, @@ -3665,7 +3664,7 @@ typedef $$GameTableTableCreateCompanionBuilder = required String name, required String ruleset, Value description, - Value color, + required String color, Value icon, required DateTime createdAt, Value rowid, @@ -3676,7 +3675,7 @@ typedef $$GameTableTableUpdateCompanionBuilder = Value name, Value ruleset, Value description, - Value color, + Value color, Value icon, Value createdAt, Value rowid, @@ -3910,7 +3909,7 @@ class $$GameTableTableTableManager Value name = const Value.absent(), Value ruleset = const Value.absent(), Value description = const Value.absent(), - Value color = const Value.absent(), + Value color = const Value.absent(), Value icon = const Value.absent(), Value createdAt = const Value.absent(), Value rowid = const Value.absent(), @@ -3930,7 +3929,7 @@ class $$GameTableTableTableManager required String name, required String ruleset, Value description = const Value.absent(), - Value color = const Value.absent(), + required String color, Value icon = const Value.absent(), required DateTime createdAt, Value rowid = const Value.absent(), diff --git a/lib/data/db/tables/game_table.dart b/lib/data/db/tables/game_table.dart index 2074ae7..eaa3e1b 100644 --- a/lib/data/db/tables/game_table.dart +++ b/lib/data/db/tables/game_table.dart @@ -5,7 +5,7 @@ class GameTable extends Table { TextColumn get name => text()(); TextColumn get ruleset => text()(); TextColumn get description => text().nullable()(); - TextColumn get color => text().nullable()(); + TextColumn get color => text()(); TextColumn get icon => text().nullable()(); DateTimeColumn get createdAt => dateTime()(); diff --git a/lib/data/dto/game.dart b/lib/data/dto/game.dart index 9e271e5..5afbd9b 100644 --- a/lib/data/dto/game.dart +++ b/lib/data/dto/game.dart @@ -7,7 +7,7 @@ class Game { final String name; final String? ruleset; final String? description; - final int? color; + final String color; final String? icon; Game({ @@ -16,7 +16,7 @@ class Game { required this.name, this.ruleset, this.description, - this.color, + required this.color, this.icon, }) : id = id ?? const Uuid().v4(), createdAt = createdAt ?? clock.now(); diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index eb630df..31e232f 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -202,6 +202,7 @@ class _CreateMatchViewState extends State { name: selectedGame.$1, description: selectedGame.$2, ruleset: selectedGame.$3.name, + color: '0xFF000000', ); } else { // Use the selected game from the list @@ -210,6 +211,7 @@ class _CreateMatchViewState extends State { name: selectedGame.$1, description: selectedGame.$2, ruleset: selectedGame.$3.name, + color: '0xFF000000', ); } // Add the game to the database if it doesn't exist diff --git a/test/db_tests/game_test.dart b/test/db_tests/game_test.dart index a1d8c1f..250d67a 100644 --- a/test/db_tests/game_test.dart +++ b/test/db_tests/game_test.dart @@ -26,7 +26,7 @@ void main() { name: 'Chess', ruleset: 'winner.single', description: 'A classic strategy game', - color: 0xFF0000FF, + color: '0xFF0000FF', icon: 'chess_icon', ); testGame2 = Game( @@ -34,13 +34,14 @@ void main() { name: 'Poker', ruleset: 'Texas Hold\'em rules', description: 'winner.multiple', - color: 0xFFFF0000, + color: '0xFFFF0000', icon: 'poker_icon', ); testGame3 = Game( id: 'game3', name: 'Monopoly', description: 'A board game about real estate', + color: '0xFF000000', ); }); }); @@ -130,7 +131,7 @@ void main() { // Verifies that a game with null optional fields can be added and retrieved. test('addGame handles game with null optional fields', () async { - final gameWithNulls = Game(name: 'Simple Game'); + final gameWithNulls = Game(name: 'Simple Game', color: '0xFF000000'); final result = await database.gameDao.addGame(game: gameWithNulls); expect(result, true); @@ -139,7 +140,7 @@ void main() { ); expect(fetchedGame.name, 'Simple Game'); expect(fetchedGame.description, isNull); - expect(fetchedGame.color, isNull); + expect(fetchedGame.color, '0xFF000000'); expect(fetchedGame.icon, isNull); }); @@ -336,35 +337,20 @@ void main() { await database.gameDao.updateGameColor( gameId: testGame1.id, - newColor: 0xFF00FF00, + newColor: '0xFF00FF00', ); final updatedGame = await database.gameDao.getGameById( gameId: testGame1.id, ); - expect(updatedGame.color, 0xFF00FF00); - }); - - // Verifies that updateGameColor can set the color to null. - test('updateGameColor can set color to null', () async { - await database.gameDao.addGame(game: testGame1); - - await database.gameDao.updateGameColor( - gameId: testGame1.id, - newColor: null, - ); - - final updatedGame = await database.gameDao.getGameById( - gameId: testGame1.id, - ); - expect(updatedGame.color, isNull); + expect(updatedGame.color, '0xFF00FF00'); }); // Verifies that updateGameColor does nothing when game doesn't exist. test('updateGameColor does nothing for non-existent game', () async { await database.gameDao.updateGameColor( gameId: 'non-existent-id', - newColor: 0xFF00FF00, + newColor: '0xFF00FF00', ); final allGames = await database.gameDao.getAllGames(); @@ -470,6 +456,7 @@ void main() { final specialGame = Game( name: 'Game\'s & "Special" ', description: 'Description with émojis 🎮🎲', + color: '0xFF000000', ); await database.gameDao.addGame(game: specialGame); @@ -487,6 +474,7 @@ void main() { ruleset: '', description: '', icon: '', + color: '0xFF000000', ); await database.gameDao.addGame(game: emptyGame); @@ -506,6 +494,7 @@ void main() { name: longString, description: longString, ruleset: longString, + color: '0xFF000000', ); await database.gameDao.addGame(game: longGame); @@ -527,7 +516,7 @@ void main() { ); await database.gameDao.updateGameColor( gameId: testGame1.id, - newColor: 0xFF123456, + newColor: '0xFF123456', ); await database.gameDao.updateGameDescription( gameId: testGame1.id, @@ -538,7 +527,7 @@ void main() { gameId: testGame1.id, ); expect(updatedGame.name, 'Updated Name'); - expect(updatedGame.color, 0xFF123456); + expect(updatedGame.color, '0xFF123456'); expect(updatedGame.description, 'Updated Description'); expect(updatedGame.ruleset, testGame1.ruleset); expect(updatedGame.icon, testGame1.icon); diff --git a/test/db_tests/match_test.dart b/test/db_tests/match_test.dart index 5941523..055efad 100644 --- a/test/db_tests/match_test.dart +++ b/test/db_tests/match_test.dart @@ -48,7 +48,7 @@ void main() { name: 'Test Group 2', members: [testPlayer4, testPlayer5], ); - testGame = Game(name: 'Test Game'); + testGame = Game(name: 'Test Game', color: '0xFF000000'); testMatch1 = Match( name: 'First Test Match', game: testGame, diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/player_match_test.dart index 8c68395..899857e 100644 --- a/test/db_tests/player_match_test.dart +++ b/test/db_tests/player_match_test.dart @@ -46,7 +46,7 @@ void main() { name: 'Test Group', members: [testPlayer1, testPlayer2, testPlayer3], ); - testGame = Game(name: 'Test Game'); + testGame = Game(name: 'Test Game', color: '0xFF000000'); testMatchOnlyGroup = Match( name: 'Test Match with Group', game: testGame, diff --git a/test/db_tests/score_test.dart b/test/db_tests/score_test.dart index 109febf..5ddaade 100644 --- a/test/db_tests/score_test.dart +++ b/test/db_tests/score_test.dart @@ -31,7 +31,7 @@ void main() { testPlayer1 = Player(name: 'Alice'); testPlayer2 = Player(name: 'Bob'); testPlayer3 = Player(name: 'Charlie'); - testGame = Game(name: 'Test Game'); + testGame = Game(name: 'Test Game', color: '0xFF000000'); testMatch1 = Match( name: 'Test Match 1', game: testGame, diff --git a/test/db_tests/team_test.dart b/test/db_tests/team_test.dart index df2c93c..72c1adc 100644 --- a/test/db_tests/team_test.dart +++ b/test/db_tests/team_test.dart @@ -48,8 +48,8 @@ void main() { name: 'Team Gamma', members: [testPlayer1, testPlayer3], ); - testGame1 = Game(name: 'Game 1'); - testGame2 = Game(name: 'Game 2'); + testGame1 = Game(name: 'Game 1', color: '0xFF000000'); + testGame2 = Game(name: 'Game 2', color: '0xFF000000'); }); await database.playerDao.addPlayersAsList( From 118b316a359f53fc5f5b22e2610f574b4ec1f91c Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 23 Jan 2026 11:25:20 +0100 Subject: [PATCH 65/87] description is now a required game parameter --- lib/data/dao/game_dao.dart | 6 ++-- lib/data/dao/match_dao.dart | 2 +- lib/data/db/database.dart | 2 +- lib/data/db/database.g.dart | 43 ++++++++++++++-------------- lib/data/db/tables/game_table.dart | 2 +- lib/data/dto/game.dart | 4 +-- test/db_tests/game_test.dart | 14 ++++----- test/db_tests/match_test.dart | 2 +- test/db_tests/player_match_test.dart | 2 +- test/db_tests/score_test.dart | 2 +- test/db_tests/team_test.dart | 4 +-- 11 files changed, 41 insertions(+), 42 deletions(-) diff --git a/lib/data/dao/game_dao.dart b/lib/data/dao/game_dao.dart index 1d8af98..62db351 100644 --- a/lib/data/dao/game_dao.dart +++ b/lib/data/dao/game_dao.dart @@ -53,7 +53,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { id: game.id, name: game.name, ruleset: game.ruleset ?? '', - description: Value(game.description), + description: game.description, color: game.color, icon: Value(game.icon), createdAt: game.createdAt, @@ -79,7 +79,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { id: game.id, name: game.name, ruleset: game.ruleset ?? '', - description: Value(game.description), + description: game.description, color: game.color, icon: Value(game.icon), createdAt: game.createdAt, @@ -132,7 +132,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { /// Updates the description of the game with the given [gameId]. Future updateGameDescription({ required String gameId, - required String? newDescription, + required String newDescription, }) async { await (update(gameTable)..where((g) => g.id.equals(gameId))).write( GameTableCompanion(description: Value(newDescription)), diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index af6d602..3d5efb0 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -128,7 +128,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { id: game.id, name: game.name, ruleset: game.ruleset ?? '', - description: Value(game.description), + description: game.description, color: game.color, icon: Value(game.icon), createdAt: game.createdAt, diff --git a/lib/data/db/database.dart b/lib/data/db/database.dart index 628e013..d3d447c 100644 --- a/lib/data/db/database.dart +++ b/lib/data/db/database.dart @@ -46,7 +46,7 @@ class AppDatabase extends _$AppDatabase { AppDatabase([QueryExecutor? executor]) : super(executor ?? _openConnection()); @override - int get schemaVersion => 2; + int get schemaVersion => 1; @override MigrationStrategy get migration { diff --git a/lib/data/db/database.g.dart b/lib/data/db/database.g.dart index a2d99c1..3faa308 100644 --- a/lib/data/db/database.g.dart +++ b/lib/data/db/database.g.dart @@ -673,9 +673,9 @@ class $GameTableTable extends GameTable late final GeneratedColumn description = GeneratedColumn( 'description', aliasedName, - true, + false, type: DriftSqlType.string, - requiredDuringInsert: false, + requiredDuringInsert: true, ); static const VerificationMeta _colorMeta = const VerificationMeta('color'); @override @@ -757,6 +757,8 @@ class $GameTableTable extends GameTable _descriptionMeta, ), ); + } else if (isInserting) { + context.missing(_descriptionMeta); } if (data.containsKey('color')) { context.handle( @@ -804,7 +806,7 @@ class $GameTableTable extends GameTable description: attachedDatabase.typeMapping.read( DriftSqlType.string, data['${effectivePrefix}description'], - ), + )!, color: attachedDatabase.typeMapping.read( DriftSqlType.string, data['${effectivePrefix}color'], @@ -830,7 +832,7 @@ class GameTableData extends DataClass implements Insertable { final String id; final String name; final String ruleset; - final String? description; + final String description; final String color; final String? icon; final DateTime createdAt; @@ -838,7 +840,7 @@ class GameTableData extends DataClass implements Insertable { required this.id, required this.name, required this.ruleset, - this.description, + required this.description, required this.color, this.icon, required this.createdAt, @@ -849,9 +851,7 @@ class GameTableData extends DataClass implements Insertable { map['id'] = Variable(id); map['name'] = Variable(name); map['ruleset'] = Variable(ruleset); - if (!nullToAbsent || description != null) { - map['description'] = Variable(description); - } + map['description'] = Variable(description); map['color'] = Variable(color); if (!nullToAbsent || icon != null) { map['icon'] = Variable(icon); @@ -865,9 +865,7 @@ class GameTableData extends DataClass implements Insertable { id: Value(id), name: Value(name), ruleset: Value(ruleset), - description: description == null && nullToAbsent - ? const Value.absent() - : Value(description), + description: Value(description), color: Value(color), icon: icon == null && nullToAbsent ? const Value.absent() : Value(icon), createdAt: Value(createdAt), @@ -883,7 +881,7 @@ class GameTableData extends DataClass implements Insertable { id: serializer.fromJson(json['id']), name: serializer.fromJson(json['name']), ruleset: serializer.fromJson(json['ruleset']), - description: serializer.fromJson(json['description']), + description: serializer.fromJson(json['description']), color: serializer.fromJson(json['color']), icon: serializer.fromJson(json['icon']), createdAt: serializer.fromJson(json['createdAt']), @@ -896,7 +894,7 @@ class GameTableData extends DataClass implements Insertable { 'id': serializer.toJson(id), 'name': serializer.toJson(name), 'ruleset': serializer.toJson(ruleset), - 'description': serializer.toJson(description), + 'description': serializer.toJson(description), 'color': serializer.toJson(color), 'icon': serializer.toJson(icon), 'createdAt': serializer.toJson(createdAt), @@ -907,7 +905,7 @@ class GameTableData extends DataClass implements Insertable { String? id, String? name, String? ruleset, - Value description = const Value.absent(), + String? description, String? color, Value icon = const Value.absent(), DateTime? createdAt, @@ -915,7 +913,7 @@ class GameTableData extends DataClass implements Insertable { id: id ?? this.id, name: name ?? this.name, ruleset: ruleset ?? this.ruleset, - description: description.present ? description.value : this.description, + description: description ?? this.description, color: color ?? this.color, icon: icon.present ? icon.value : this.icon, createdAt: createdAt ?? this.createdAt, @@ -968,7 +966,7 @@ class GameTableCompanion extends UpdateCompanion { final Value id; final Value name; final Value ruleset; - final Value description; + final Value description; final Value color; final Value icon; final Value createdAt; @@ -987,7 +985,7 @@ class GameTableCompanion extends UpdateCompanion { required String id, required String name, required String ruleset, - this.description = const Value.absent(), + required String description, required String color, this.icon = const Value.absent(), required DateTime createdAt, @@ -995,6 +993,7 @@ class GameTableCompanion extends UpdateCompanion { }) : id = Value(id), name = Value(name), ruleset = Value(ruleset), + description = Value(description), color = Value(color), createdAt = Value(createdAt); static Insertable custom({ @@ -1023,7 +1022,7 @@ class GameTableCompanion extends UpdateCompanion { Value? id, Value? name, Value? ruleset, - Value? description, + Value? description, Value? color, Value? icon, Value? createdAt, @@ -3663,7 +3662,7 @@ typedef $$GameTableTableCreateCompanionBuilder = required String id, required String name, required String ruleset, - Value description, + required String description, required String color, Value icon, required DateTime createdAt, @@ -3674,7 +3673,7 @@ typedef $$GameTableTableUpdateCompanionBuilder = Value id, Value name, Value ruleset, - Value description, + Value description, Value color, Value icon, Value createdAt, @@ -3908,7 +3907,7 @@ class $$GameTableTableTableManager Value id = const Value.absent(), Value name = const Value.absent(), Value ruleset = const Value.absent(), - Value description = const Value.absent(), + Value description = const Value.absent(), Value color = const Value.absent(), Value icon = const Value.absent(), Value createdAt = const Value.absent(), @@ -3928,7 +3927,7 @@ class $$GameTableTableTableManager required String id, required String name, required String ruleset, - Value description = const Value.absent(), + required String description, required String color, Value icon = const Value.absent(), required DateTime createdAt, diff --git a/lib/data/db/tables/game_table.dart b/lib/data/db/tables/game_table.dart index eaa3e1b..ce71a59 100644 --- a/lib/data/db/tables/game_table.dart +++ b/lib/data/db/tables/game_table.dart @@ -4,7 +4,7 @@ class GameTable extends Table { TextColumn get id => text()(); TextColumn get name => text()(); TextColumn get ruleset => text()(); - TextColumn get description => text().nullable()(); + TextColumn get description => text()(); TextColumn get color => text()(); TextColumn get icon => text().nullable()(); DateTimeColumn get createdAt => dateTime()(); diff --git a/lib/data/dto/game.dart b/lib/data/dto/game.dart index 5afbd9b..c63bdea 100644 --- a/lib/data/dto/game.dart +++ b/lib/data/dto/game.dart @@ -6,7 +6,7 @@ class Game { final DateTime createdAt; final String name; final String? ruleset; - final String? description; + final String description; final String color; final String? icon; @@ -15,7 +15,7 @@ class Game { DateTime? createdAt, required this.name, this.ruleset, - this.description, + required this.description, required this.color, this.icon, }) : id = id ?? const Uuid().v4(), diff --git a/test/db_tests/game_test.dart b/test/db_tests/game_test.dart index 250d67a..4182530 100644 --- a/test/db_tests/game_test.dart +++ b/test/db_tests/game_test.dart @@ -131,7 +131,7 @@ void main() { // Verifies that a game with null optional fields can be added and retrieved. test('addGame handles game with null optional fields', () async { - final gameWithNulls = Game(name: 'Simple Game', color: '0xFF000000'); + final gameWithNulls = Game(name: 'Simple Game', description: 'A simple game', color: '0xFF000000'); final result = await database.gameDao.addGame(game: gameWithNulls); expect(result, true); @@ -139,7 +139,7 @@ void main() { gameId: gameWithNulls.id, ); expect(fetchedGame.name, 'Simple Game'); - expect(fetchedGame.description, isNull); + expect(fetchedGame.description, 'A simple game'); expect(fetchedGame.color, '0xFF000000'); expect(fetchedGame.icon, isNull); }); @@ -305,19 +305,19 @@ void main() { expect(updatedGame.description, 'An updated description'); }); - // Verifies that updateGameDescription can set the description to null. - test('updateGameDescription can set description to null', () async { + // Verifies that updateGameDescription can set the description to an empty string. + test('updateGameDescription can set description to empty string', () async { await database.gameDao.addGame(game: testGame1); await database.gameDao.updateGameDescription( gameId: testGame1.id, - newDescription: null, + newDescription: '', ); final updatedGame = await database.gameDao.getGameById( gameId: testGame1.id, ); - expect(updatedGame.description, isNull); + expect(updatedGame.description, ''); }); // Verifies that updateGameDescription does nothing when game doesn't exist. @@ -502,7 +502,7 @@ void main() { gameId: longGame.id, ); expect(fetchedGame.name.length, 10000); - expect(fetchedGame.description?.length, 10000); + expect(fetchedGame.description.length, 10000); expect(fetchedGame.ruleset?.length, 10000); }); diff --git a/test/db_tests/match_test.dart b/test/db_tests/match_test.dart index 055efad..f5d3fb2 100644 --- a/test/db_tests/match_test.dart +++ b/test/db_tests/match_test.dart @@ -48,7 +48,7 @@ void main() { name: 'Test Group 2', members: [testPlayer4, testPlayer5], ); - testGame = Game(name: 'Test Game', color: '0xFF000000'); + testGame = Game(name: 'Test Game', description: 'A test game', color: '0xFF000000'); testMatch1 = Match( name: 'First Test Match', game: testGame, diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/player_match_test.dart index 899857e..3758e0b 100644 --- a/test/db_tests/player_match_test.dart +++ b/test/db_tests/player_match_test.dart @@ -46,7 +46,7 @@ void main() { name: 'Test Group', members: [testPlayer1, testPlayer2, testPlayer3], ); - testGame = Game(name: 'Test Game', color: '0xFF000000'); + testGame = Game(name: 'Test Game', description: 'A test game', color: '0xFF000000'); testMatchOnlyGroup = Match( name: 'Test Match with Group', game: testGame, diff --git a/test/db_tests/score_test.dart b/test/db_tests/score_test.dart index 5ddaade..bc9d536 100644 --- a/test/db_tests/score_test.dart +++ b/test/db_tests/score_test.dart @@ -31,7 +31,7 @@ void main() { testPlayer1 = Player(name: 'Alice'); testPlayer2 = Player(name: 'Bob'); testPlayer3 = Player(name: 'Charlie'); - testGame = Game(name: 'Test Game', color: '0xFF000000'); + testGame = Game(name: 'Test Game', description: 'A test game', color: '0xFF000000'); testMatch1 = Match( name: 'Test Match 1', game: testGame, diff --git a/test/db_tests/team_test.dart b/test/db_tests/team_test.dart index 72c1adc..84188a0 100644 --- a/test/db_tests/team_test.dart +++ b/test/db_tests/team_test.dart @@ -48,8 +48,8 @@ void main() { name: 'Team Gamma', members: [testPlayer1, testPlayer3], ); - testGame1 = Game(name: 'Game 1', color: '0xFF000000'); - testGame2 = Game(name: 'Game 2', color: '0xFF000000'); + testGame1 = Game(name: 'Game 1', description: 'Test game 1', color: '0xFF000000'); + testGame2 = Game(name: 'Game 2', description: 'Test game 2', color: '0xFF000000'); }); await database.playerDao.addPlayersAsList( From b0cb385756333378020279731f35c583fd28b7af Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Fri, 23 Jan 2026 11:54:37 +0100 Subject: [PATCH 66/87] ruleset is now a required game enum parameter --- lib/core/enums.dart | 23 +++++++++-------- lib/data/dao/game_dao.dart | 13 +++++----- lib/data/dao/match_dao.dart | 2 +- lib/data/dto/game.dart | 9 ++++--- lib/l10n/arb/app_de.arb | 3 +++ lib/l10n/arb/app_en.arb | 3 +++ lib/l10n/generated/app_localizations.dart | 18 +++++++++++++ lib/l10n/generated/app_localizations_de.dart | 9 +++++++ lib/l10n/generated/app_localizations_en.dart | 9 +++++++ .../create_match/create_match_view.dart | 6 ++--- test/db_tests/game_test.dart | 25 +++++++++++-------- test/db_tests/match_test.dart | 3 ++- test/db_tests/player_match_test.dart | 3 ++- test/db_tests/score_test.dart | 3 ++- test/db_tests/team_test.dart | 5 ++-- 15 files changed, 94 insertions(+), 40 deletions(-) diff --git a/lib/core/enums.dart b/lib/core/enums.dart index 17a01f6..ee8b445 100644 --- a/lib/core/enums.dart +++ b/lib/core/enums.dart @@ -29,24 +29,27 @@ enum ImportResult { /// - [ExportResult.unknownException]: An exception occurred during export. enum ExportResult { success, canceled, unknownException } -/// Different rulesets available for matches -/// - [Ruleset.singleWinner]: The match is won by a single player -/// - [Ruleset.singleLoser]: The match is lost by a single player -/// - [Ruleset.mostPoints]: The player with the most points wins. -/// - [Ruleset.leastPoints]: The player with the fewest points wins. -enum Ruleset { singleWinner, singleLoser, mostPoints, leastPoints } +/// Different rulesets available for games +/// - [Ruleset.highestScore]: The player with the highest score wins. +/// - [Ruleset.lowestScore]: The player with the lowest score wins. +/// - [Ruleset.singleWinner]: The match is won by a single player. +/// - [Ruleset.singleLoser]: The match has a single loser. +/// - [Ruleset.multipleWinners]: Multiple players can be winners. +enum Ruleset { highestScore, lowestScore, singleWinner, singleLoser, multipleWinners } /// Translates a [Ruleset] enum value to its corresponding localized string. String translateRulesetToString(Ruleset ruleset, BuildContext context) { final loc = AppLocalizations.of(context); switch (ruleset) { + case Ruleset.highestScore: + return loc.highest_score; + case Ruleset.lowestScore: + return loc.lowest_score; case Ruleset.singleWinner: return loc.single_winner; case Ruleset.singleLoser: return loc.single_loser; - case Ruleset.mostPoints: - return loc.most_points; - case Ruleset.leastPoints: - return loc.least_points; + case Ruleset.multipleWinners: + return loc.multiple_winners; } } diff --git a/lib/data/dao/game_dao.dart b/lib/data/dao/game_dao.dart index 62db351..95ecc70 100644 --- a/lib/data/dao/game_dao.dart +++ b/lib/data/dao/game_dao.dart @@ -2,6 +2,7 @@ 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/core/enums.dart'; part 'game_dao.g.dart'; @@ -18,7 +19,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { (row) => Game( id: row.id, name: row.name, - ruleset: row.ruleset, + ruleset: Ruleset.values.firstWhere((e) => e.name == row.ruleset), description: row.description, color: row.color, icon: row.icon, @@ -35,7 +36,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { return Game( id: result.id, name: result.name, - ruleset: result.ruleset, + ruleset: Ruleset.values.firstWhere((e) => e.name == result.ruleset), description: result.description, color: result.color, icon: result.icon, @@ -52,7 +53,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { GameTableCompanion.insert( id: game.id, name: game.name, - ruleset: game.ruleset ?? '', + ruleset: game.ruleset.name, description: game.description, color: game.color, icon: Value(game.icon), @@ -78,7 +79,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { (game) => GameTableCompanion.insert( id: game.id, name: game.name, - ruleset: game.ruleset ?? '', + ruleset: game.ruleset.name, description: game.description, color: game.color, icon: Value(game.icon), @@ -122,10 +123,10 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { /// Updates the ruleset of the game with the given [gameId]. Future updateGameRuleset({ required String gameId, - required String newRuleset, + required Ruleset newRuleset, }) async { await (update(gameTable)..where((g) => g.id.equals(gameId))).write( - GameTableCompanion(ruleset: Value(newRuleset)), + GameTableCompanion(ruleset: Value(newRuleset.name)), ); } diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index 3d5efb0..4ec5b4d 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -127,7 +127,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { (game) => GameTableCompanion.insert( id: game.id, name: game.name, - ruleset: game.ruleset ?? '', + ruleset: game.ruleset.name, description: game.description, color: game.color, icon: Value(game.icon), diff --git a/lib/data/dto/game.dart b/lib/data/dto/game.dart index c63bdea..c74b8aa 100644 --- a/lib/data/dto/game.dart +++ b/lib/data/dto/game.dart @@ -1,11 +1,12 @@ import 'package:clock/clock.dart'; import 'package:uuid/uuid.dart'; +import 'package:game_tracker/core/enums.dart'; class Game { final String id; final DateTime createdAt; final String name; - final String? ruleset; + final Ruleset ruleset; final String description; final String color; final String? icon; @@ -14,7 +15,7 @@ class Game { String? id, DateTime? createdAt, required this.name, - this.ruleset, + required this.ruleset, required this.description, required this.color, this.icon, @@ -31,7 +32,7 @@ class Game { : id = json['id'], createdAt = DateTime.parse(json['createdAt']), name = json['name'], - ruleset = json['ruleset'], + ruleset = Ruleset.values.firstWhere((e) => e.name == json['ruleset']), description = json['description'], color = json['color'], icon = json['icon']; @@ -41,7 +42,7 @@ class Game { 'id': id, 'createdAt': createdAt.toIso8601String(), 'name': name, - 'ruleset': ruleset, + 'ruleset': ruleset.name, 'description': description, 'color': color, 'icon': icon, diff --git a/lib/l10n/arb/app_de.arb b/lib/l10n/arb/app_de.arb index 2ef9ee9..9e981b0 100644 --- a/lib/l10n/arb/app_de.arb +++ b/lib/l10n/arb/app_de.arb @@ -82,6 +82,9 @@ "settings": "Einstellungen", "single_loser": "Ein:e Verlierer:in", "single_winner": "Ein:e Gewinner:in", + "highest_score": "Höchste Punkte", + "lowest_score": "Niedrigste Punkte", + "multiple_winners": "Mehrere Gewinner:innen", "statistics": "Statistiken", "stats": "Statistiken", "successfully_added_player": "Spieler:in {playerName} erfolgreich hinzugefügt", diff --git a/lib/l10n/arb/app_en.arb b/lib/l10n/arb/app_en.arb index fa4adc8..27419c8 100644 --- a/lib/l10n/arb/app_en.arb +++ b/lib/l10n/arb/app_en.arb @@ -380,6 +380,9 @@ "settings": "Settings", "single_loser": "Single Loser", "single_winner": "Single Winner", + "highest_score": "Highest Score", + "lowest_score": "Lowest Score", + "multiple_winners": "Multiple Winners", "statistics": "Statistics", "stats": "Stats", "successfully_added_player": "Successfully added player {playerName}", diff --git a/lib/l10n/generated/app_localizations.dart b/lib/l10n/generated/app_localizations.dart index 57dbdd8..b0aabcb 100644 --- a/lib/l10n/generated/app_localizations.dart +++ b/lib/l10n/generated/app_localizations.dart @@ -590,6 +590,24 @@ abstract class AppLocalizations { /// **'Single Winner'** String get single_winner; + /// No description provided for @highest_score. + /// + /// In en, this message translates to: + /// **'Highest Score'** + String get highest_score; + + /// No description provided for @lowest_score. + /// + /// In en, this message translates to: + /// **'Lowest Score'** + String get lowest_score; + + /// No description provided for @multiple_winners. + /// + /// In en, this message translates to: + /// **'Multiple Winners'** + String get multiple_winners; + /// Statistics tab label /// /// In en, this message translates to: diff --git a/lib/l10n/generated/app_localizations_de.dart b/lib/l10n/generated/app_localizations_de.dart index f78f9f4..0580d4f 100644 --- a/lib/l10n/generated/app_localizations_de.dart +++ b/lib/l10n/generated/app_localizations_de.dart @@ -266,6 +266,15 @@ class AppLocalizationsDe extends AppLocalizations { @override String get single_winner => 'Ein:e Gewinner:in'; + @override + String get highest_score => 'Höchste Punkte'; + + @override + String get lowest_score => 'Niedrigste Punkte'; + + @override + String get multiple_winners => 'Mehrere Gewinner:innen'; + @override String get statistics => 'Statistiken'; diff --git a/lib/l10n/generated/app_localizations_en.dart b/lib/l10n/generated/app_localizations_en.dart index 32512c7..8e2e453 100644 --- a/lib/l10n/generated/app_localizations_en.dart +++ b/lib/l10n/generated/app_localizations_en.dart @@ -266,6 +266,15 @@ class AppLocalizationsEn extends AppLocalizations { @override String get single_winner => 'Single Winner'; + @override + String get highest_score => 'Highest Score'; + + @override + String get lowest_score => 'Lowest Score'; + + @override + String get multiple_winners => 'Multiple Winners'; + @override String get statistics => 'Statistics'; diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index 31e232f..a97de75 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -100,7 +100,7 @@ class _CreateMatchViewState extends State { } List<(String, String, Ruleset)> games = [ - ('Example Game 1', 'This is a description', Ruleset.leastPoints), + ('Example Game 1', 'This is a description', Ruleset.lowestScore), ('Example Game 2', '', Ruleset.singleWinner), ]; @@ -201,7 +201,7 @@ class _CreateMatchViewState extends State { gameToUse = Game( name: selectedGame.$1, description: selectedGame.$2, - ruleset: selectedGame.$3.name, + ruleset: selectedGame.$3, color: '0xFF000000', ); } else { @@ -210,7 +210,7 @@ class _CreateMatchViewState extends State { gameToUse = Game( name: selectedGame.$1, description: selectedGame.$2, - ruleset: selectedGame.$3.name, + ruleset: selectedGame.$3, color: '0xFF000000', ); } diff --git a/test/db_tests/game_test.dart b/test/db_tests/game_test.dart index 4182530..040d607 100644 --- a/test/db_tests/game_test.dart +++ b/test/db_tests/game_test.dart @@ -4,6 +4,7 @@ import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.dart'; import 'package:game_tracker/data/db/database.dart'; import 'package:game_tracker/data/dto/game.dart'; +import 'package:game_tracker/core/enums.dart'; void main() { late AppDatabase database; @@ -24,7 +25,7 @@ void main() { withClock(fakeClock, () { testGame1 = Game( name: 'Chess', - ruleset: 'winner.single', + ruleset: Ruleset.singleWinner, description: 'A classic strategy game', color: '0xFF0000FF', icon: 'chess_icon', @@ -32,14 +33,15 @@ void main() { testGame2 = Game( id: 'game2', name: 'Poker', - ruleset: 'Texas Hold\'em rules', - description: 'winner.multiple', + ruleset: Ruleset.multipleWinners, + description: 'Card game with multiple winners', color: '0xFFFF0000', icon: 'poker_icon', ); testGame3 = Game( id: 'game3', name: 'Monopoly', + ruleset: Ruleset.highestScore, description: 'A board game about real estate', color: '0xFF000000', ); @@ -131,7 +133,7 @@ void main() { // Verifies that a game with null optional fields can be added and retrieved. test('addGame handles game with null optional fields', () async { - final gameWithNulls = Game(name: 'Simple Game', description: 'A simple game', color: '0xFF000000'); + final gameWithNulls = Game(name: 'Simple Game', ruleset: Ruleset.lowestScore, description: 'A simple game', color: '0xFF000000'); final result = await database.gameDao.addGame(game: gameWithNulls); expect(result, true); @@ -269,13 +271,13 @@ void main() { await database.gameDao.updateGameRuleset( gameId: testGame1.id, - newRuleset: 'New ruleset for chess', + newRuleset: Ruleset.highestScore, ); final updatedGame = await database.gameDao.getGameById( gameId: testGame1.id, ); - expect(updatedGame.ruleset, 'New ruleset for chess'); + expect(updatedGame.ruleset, Ruleset.highestScore); expect(updatedGame.name, testGame1.name); }); @@ -283,7 +285,7 @@ void main() { test('updateGameRuleset does nothing for non-existent game', () async { await database.gameDao.updateGameRuleset( gameId: 'non-existent-id', - newRuleset: 'New Ruleset', + newRuleset: Ruleset.lowestScore, ); final allGames = await database.gameDao.getAllGames(); @@ -455,6 +457,7 @@ void main() { test('Game with special characters in name is stored correctly', () async { final specialGame = Game( name: 'Game\'s & "Special" ', + ruleset: Ruleset.multipleWinners, description: 'Description with émojis 🎮🎲', color: '0xFF000000', ); @@ -471,7 +474,7 @@ void main() { test('Game with empty string fields is stored correctly', () async { final emptyGame = Game( name: '', - ruleset: '', + ruleset: Ruleset.singleWinner, description: '', icon: '', color: '0xFF000000', @@ -482,7 +485,7 @@ void main() { gameId: emptyGame.id, ); expect(fetchedGame.name, ''); - expect(fetchedGame.ruleset, ''); + expect(fetchedGame.ruleset, Ruleset.singleWinner); expect(fetchedGame.description, ''); expect(fetchedGame.icon, ''); }); @@ -493,7 +496,7 @@ void main() { final longGame = Game( name: longString, description: longString, - ruleset: longString, + ruleset: Ruleset.multipleWinners, color: '0xFF000000', ); await database.gameDao.addGame(game: longGame); @@ -503,7 +506,7 @@ void main() { ); expect(fetchedGame.name.length, 10000); expect(fetchedGame.description.length, 10000); - expect(fetchedGame.ruleset?.length, 10000); + expect(fetchedGame.ruleset, Ruleset.multipleWinners); }); // Verifies that multiple sequential updates to the same game work correctly. diff --git a/test/db_tests/match_test.dart b/test/db_tests/match_test.dart index f5d3fb2..80a9fa7 100644 --- a/test/db_tests/match_test.dart +++ b/test/db_tests/match_test.dart @@ -7,6 +7,7 @@ import 'package:game_tracker/data/dto/game.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/core/enums.dart'; void main() { late AppDatabase database; @@ -48,7 +49,7 @@ void main() { name: 'Test Group 2', members: [testPlayer4, testPlayer5], ); - testGame = Game(name: 'Test Game', description: 'A test game', color: '0xFF000000'); + testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000'); testMatch1 = Match( name: 'First Test Match', game: testGame, diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/player_match_test.dart index 3758e0b..0e5fb27 100644 --- a/test/db_tests/player_match_test.dart +++ b/test/db_tests/player_match_test.dart @@ -8,6 +8,7 @@ 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/team.dart'; +import 'package:game_tracker/core/enums.dart'; void main() { late AppDatabase database; @@ -46,7 +47,7 @@ void main() { name: 'Test Group', members: [testPlayer1, testPlayer2, testPlayer3], ); - testGame = Game(name: 'Test Game', description: 'A test game', color: '0xFF000000'); + testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000'); testMatchOnlyGroup = Match( name: 'Test Match with Group', game: testGame, diff --git a/test/db_tests/score_test.dart b/test/db_tests/score_test.dart index bc9d536..9052a32 100644 --- a/test/db_tests/score_test.dart +++ b/test/db_tests/score_test.dart @@ -6,6 +6,7 @@ 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/core/enums.dart'; void main() { late AppDatabase database; @@ -31,7 +32,7 @@ void main() { testPlayer1 = Player(name: 'Alice'); testPlayer2 = Player(name: 'Bob'); testPlayer3 = Player(name: 'Charlie'); - testGame = Game(name: 'Test Game', description: 'A test game', color: '0xFF000000'); + testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000'); testMatch1 = Match( name: 'Test Match 1', game: testGame, diff --git a/test/db_tests/team_test.dart b/test/db_tests/team_test.dart index 84188a0..efeaf18 100644 --- a/test/db_tests/team_test.dart +++ b/test/db_tests/team_test.dart @@ -7,6 +7,7 @@ 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/team.dart'; +import 'package:game_tracker/core/enums.dart'; void main() { late AppDatabase database; @@ -48,8 +49,8 @@ void main() { name: 'Team Gamma', members: [testPlayer1, testPlayer3], ); - testGame1 = Game(name: 'Game 1', description: 'Test game 1', color: '0xFF000000'); - testGame2 = Game(name: 'Game 2', description: 'Test game 2', color: '0xFF000000'); + testGame1 = Game(name: 'Game 1', ruleset: Ruleset.singleWinner, description: 'Test game 1', color: '0xFF000000'); + testGame2 = Game(name: 'Game 2', ruleset: Ruleset.highestScore, description: 'Test game 2', color: '0xFF000000'); }); await database.playerDao.addPlayersAsList( From 3bd6dd4189dbfcd158bea9b4a24b60cf31304c18 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sun, 25 Jan 2026 10:15:50 +0100 Subject: [PATCH 67/87] fix typo --- test/db_tests/group_test.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/db_tests/group_test.dart b/test/db_tests/group_test.dart index 307fbb5..ada0430 100644 --- a/test/db_tests/group_test.dart +++ b/test/db_tests/group_test.dart @@ -147,7 +147,7 @@ void main() { }); // Verifies that updateGroupName correctly updates only the name field. - test('Updating a group name works correcly', () async { + test('Updating a group name works correctly', () async { await database.groupDao.addGroup(group: testGroup1); const newGroupName = 'new group name'; From 1d352821fc53f9d659ae04d3b1fc9d0adf9e2dea Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Thu, 29 Jan 2026 15:39:52 +0100 Subject: [PATCH 68/87] all parameters are now required --- assets/schema.json | 36 ++--- lib/data/dao/game_dao.dart | 6 +- lib/data/dao/group_dao.dart | 8 +- lib/data/dao/match_dao.dart | 23 ++-- lib/data/dao/player_dao.dart | 4 +- lib/data/db/database.g.dart | 127 +++++++++--------- lib/data/db/tables/game_table.dart | 2 +- lib/data/db/tables/group_table.dart | 2 +- lib/data/db/tables/player_table.dart | 2 +- lib/data/dto/game.dart | 4 +- lib/data/dto/group.dart | 4 +- lib/data/dto/match.dart | 15 ++- lib/data/dto/player.dart | 4 +- .../group_view/create_group_view.dart | 1 + .../main_menu/group_view/groups_view.dart | 3 +- .../views/main_menu/home_view.dart | 13 +- .../create_match/create_match_view.dart | 3 + .../main_menu/match_view/match_view.dart | 11 +- .../views/main_menu/statistics_view.dart | 4 +- .../widgets/player_selection.dart | 4 +- lib/services/data_transfer_service.dart | 12 +- test/db_tests/game_test.dart | 13 +- test/db_tests/group_test.dart | 17 ++- test/db_tests/match_test.dart | 18 ++- test/db_tests/player_group_test.dart | 15 ++- test/db_tests/player_match_test.dart | 29 ++-- test/db_tests/player_test.dart | 18 +-- test/db_tests/score_test.dart | 10 +- test/db_tests/team_test.dart | 16 +-- 29 files changed, 227 insertions(+), 197 deletions(-) diff --git a/assets/schema.json b/assets/schema.json index 3aab588..a00cd6e 100644 --- a/assets/schema.json +++ b/assets/schema.json @@ -17,13 +17,14 @@ "type": "string" }, "description": { - "type": ["string", "null"] + "type": "string" } }, "required": [ "id", "createdAt", - "name" + "name", + "description" ] } }, @@ -42,22 +43,26 @@ "type": "string" }, "ruleset": { - "type": ["string", "null"] + "type": "string" }, "description": { - "type": ["string", "null"] + "type": "string" }, "color": { - "type": ["integer", "null"] + "type": "string" }, "icon": { - "type": ["string", "null"] + "type": "string" } }, "required": [ "id", "createdAt", - "name" + "name", + "ruleset", + "description", + "color", + "icon" ] } }, @@ -76,7 +81,7 @@ "type": "string" }, "description": { - "type": ["string", "null"] + "type": "string" }, "memberIds": { "type": "array", @@ -89,6 +94,7 @@ "id", "name", "createdAt", + "description", "memberIds" ] } @@ -137,10 +143,7 @@ "type": "string" }, "gameId": { - "anyOf": [ - {"type": "string"}, - {"type": "null"} - ] + "type": "string" }, "groupId": { "anyOf": [ @@ -155,17 +158,16 @@ } }, "notes": { - "anyOf": [ - {"type": "string"}, - {"type": "null"} - ] + "type": "string" } }, "required": [ "id", "name", "createdAt", - "playerIds" + "gameId", + "playerIds", + "notes" ] } } diff --git a/lib/data/dao/game_dao.dart b/lib/data/dao/game_dao.dart index 95ecc70..0fd761c 100644 --- a/lib/data/dao/game_dao.dart +++ b/lib/data/dao/game_dao.dart @@ -56,7 +56,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { ruleset: game.ruleset.name, description: game.description, color: game.color, - icon: Value(game.icon), + icon: game.icon, createdAt: game.createdAt, ), mode: InsertMode.insertOrReplace, @@ -82,7 +82,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { ruleset: game.ruleset.name, description: game.description, color: game.color, - icon: Value(game.icon), + icon: game.icon, createdAt: game.createdAt, ), ) @@ -153,7 +153,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { /// Updates the icon of the game with the given [gameId]. Future updateGameIcon({ required String gameId, - required String? newIcon, + required String newIcon, }) async { await (update(gameTable)..where((g) => g.id.equals(gameId))).write( GameTableCompanion(icon: Value(newIcon)), diff --git a/lib/data/dao/group_dao.dart b/lib/data/dao/group_dao.dart index beecc9d..cd45c12 100644 --- a/lib/data/dao/group_dao.dart +++ b/lib/data/dao/group_dao.dart @@ -58,7 +58,7 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { GroupTableCompanion.insert( id: group.id, name: group.name, - description: Value(group.description), + description: group.description, createdAt: group.createdAt, ), mode: InsertMode.insertOrReplace, @@ -108,7 +108,7 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { (group) => GroupTableCompanion.insert( id: group.id, name: group.name, - description: Value(group.description), + description: group.description, createdAt: group.createdAt, ), ) @@ -136,7 +136,7 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { (p) => PlayerTableCompanion.insert( id: p.id, name: p.name, - description: Value(p.description), + description: p.description, createdAt: p.createdAt, ), ) @@ -196,7 +196,7 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { /// Returns `true` if more than 0 rows were affected, otherwise `false`. Future updateGroupDescription({ required String groupId, - required String? newDescription, + required String newDescription, }) async { final rowsAffected = await (update(groupTable)..where((g) => g.id.equals(groupId))).write( diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index 4ec5b4d..2df0bb9 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -36,7 +36,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { game: game, group: group, players: players, - notes: row.notes, + notes: row.notes ?? '', createdAt: row.createdAt, ); }), @@ -66,7 +66,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { game: game, group: group, players: players, - notes: result.notes, + notes: result.notes ?? '', createdAt: result.createdAt, ); } @@ -75,15 +75,11 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { /// This method assumes that the game and group (if any) are already present /// in the database. Future addMatch({required Match match}) async { - if (match.game == null) { - throw ArgumentError('Match must have a game associated with it'); - } - await db.transaction(() async { await into(matchTable).insert( MatchTableCompanion.insert( id: match.id, - gameId: match.game!.id, + gameId: match.game.id, groupId: Value(match.group?.id), name: Value(match.name), notes: Value(match.notes), @@ -113,9 +109,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { // Add all games first (deduplicated) final uniqueGames = {}; for (final match in matches) { - if (match.game != null) { - uniqueGames[match.game!.id] = match.game!; - } + uniqueGames[match.game.id] = match.game; } if (uniqueGames.isNotEmpty) { @@ -130,7 +124,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { ruleset: game.ruleset.name, description: game.description, color: game.color, - icon: Value(game.icon), + icon: game.icon, createdAt: game.createdAt, ), ) @@ -150,7 +144,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { (match) => GroupTableCompanion.insert( id: match.group!.id, name: match.group!.name, - description: Value(match.group!.description), + description: match.group!.description, createdAt: match.group!.createdAt, ), ) @@ -164,11 +158,10 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { (b) => b.insertAll( matchTable, matches - .where((match) => match.game != null) .map( (match) => MatchTableCompanion.insert( id: match.id, - gameId: match.game!.id, + gameId: match.game.id, groupId: Value(match.group?.id), name: Value(match.name), notes: Value(match.notes), @@ -205,7 +198,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { (p) => PlayerTableCompanion.insert( id: p.id, name: p.name, - description: Value(p.description), + description: p.description, createdAt: p.createdAt, ), ) diff --git a/lib/data/dao/player_dao.dart b/lib/data/dao/player_dao.dart index b8b5000..e6607a4 100644 --- a/lib/data/dao/player_dao.dart +++ b/lib/data/dao/player_dao.dart @@ -46,7 +46,7 @@ class PlayerDao extends DatabaseAccessor with _$PlayerDaoMixin { PlayerTableCompanion.insert( id: player.id, name: player.name, - description: Value(player.description), + description: player.description, createdAt: player.createdAt, ), mode: InsertMode.insertOrReplace, @@ -70,7 +70,7 @@ class PlayerDao extends DatabaseAccessor with _$PlayerDaoMixin { (player) => PlayerTableCompanion.insert( id: player.id, name: player.name, - description: Value(player.description), + description: player.description, createdAt: player.createdAt, ), ) diff --git a/lib/data/db/database.g.dart b/lib/data/db/database.g.dart index 3faa308..b77c4cd 100644 --- a/lib/data/db/database.g.dart +++ b/lib/data/db/database.g.dart @@ -34,9 +34,9 @@ class $PlayerTableTable extends PlayerTable late final GeneratedColumn description = GeneratedColumn( 'description', aliasedName, - true, + false, type: DriftSqlType.string, - requiredDuringInsert: false, + requiredDuringInsert: true, ); static const VerificationMeta _createdAtMeta = const VerificationMeta( 'createdAt', @@ -84,6 +84,8 @@ class $PlayerTableTable extends PlayerTable _descriptionMeta, ), ); + } else if (isInserting) { + context.missing(_descriptionMeta); } if (data.containsKey('created_at')) { context.handle( @@ -113,7 +115,7 @@ class $PlayerTableTable extends PlayerTable description: attachedDatabase.typeMapping.read( DriftSqlType.string, data['${effectivePrefix}description'], - ), + )!, createdAt: attachedDatabase.typeMapping.read( DriftSqlType.dateTime, data['${effectivePrefix}created_at'], @@ -130,12 +132,12 @@ class $PlayerTableTable extends PlayerTable class PlayerTableData extends DataClass implements Insertable { final String id; final String name; - final String? description; + final String description; final DateTime createdAt; const PlayerTableData({ required this.id, required this.name, - this.description, + required this.description, required this.createdAt, }); @override @@ -143,9 +145,7 @@ class PlayerTableData extends DataClass implements Insertable { final map = {}; map['id'] = Variable(id); map['name'] = Variable(name); - if (!nullToAbsent || description != null) { - map['description'] = Variable(description); - } + map['description'] = Variable(description); map['created_at'] = Variable(createdAt); return map; } @@ -154,9 +154,7 @@ class PlayerTableData extends DataClass implements Insertable { return PlayerTableCompanion( id: Value(id), name: Value(name), - description: description == null && nullToAbsent - ? const Value.absent() - : Value(description), + description: Value(description), createdAt: Value(createdAt), ); } @@ -169,7 +167,7 @@ class PlayerTableData extends DataClass implements Insertable { return PlayerTableData( id: serializer.fromJson(json['id']), name: serializer.fromJson(json['name']), - description: serializer.fromJson(json['description']), + description: serializer.fromJson(json['description']), createdAt: serializer.fromJson(json['createdAt']), ); } @@ -179,7 +177,7 @@ class PlayerTableData extends DataClass implements Insertable { return { 'id': serializer.toJson(id), 'name': serializer.toJson(name), - 'description': serializer.toJson(description), + 'description': serializer.toJson(description), 'createdAt': serializer.toJson(createdAt), }; } @@ -187,12 +185,12 @@ class PlayerTableData extends DataClass implements Insertable { PlayerTableData copyWith({ String? id, String? name, - Value description = const Value.absent(), + String? description, DateTime? createdAt, }) => PlayerTableData( id: id ?? this.id, name: name ?? this.name, - description: description.present ? description.value : this.description, + description: description ?? this.description, createdAt: createdAt ?? this.createdAt, ); PlayerTableData copyWithCompanion(PlayerTableCompanion data) { @@ -232,7 +230,7 @@ class PlayerTableData extends DataClass implements Insertable { class PlayerTableCompanion extends UpdateCompanion { final Value id; final Value name; - final Value description; + final Value description; final Value createdAt; final Value rowid; const PlayerTableCompanion({ @@ -245,11 +243,12 @@ class PlayerTableCompanion extends UpdateCompanion { PlayerTableCompanion.insert({ required String id, required String name, - this.description = const Value.absent(), + required String description, required DateTime createdAt, this.rowid = const Value.absent(), }) : id = Value(id), name = Value(name), + description = Value(description), createdAt = Value(createdAt); static Insertable custom({ Expression? id, @@ -270,7 +269,7 @@ class PlayerTableCompanion extends UpdateCompanion { PlayerTableCompanion copyWith({ Value? id, Value? name, - Value? description, + Value? description, Value? createdAt, Value? rowid, }) { @@ -348,9 +347,9 @@ class $GroupTableTable extends GroupTable late final GeneratedColumn description = GeneratedColumn( 'description', aliasedName, - true, + false, type: DriftSqlType.string, - requiredDuringInsert: false, + requiredDuringInsert: true, ); static const VerificationMeta _createdAtMeta = const VerificationMeta( 'createdAt', @@ -398,6 +397,8 @@ class $GroupTableTable extends GroupTable _descriptionMeta, ), ); + } else if (isInserting) { + context.missing(_descriptionMeta); } if (data.containsKey('created_at')) { context.handle( @@ -427,7 +428,7 @@ class $GroupTableTable extends GroupTable description: attachedDatabase.typeMapping.read( DriftSqlType.string, data['${effectivePrefix}description'], - ), + )!, createdAt: attachedDatabase.typeMapping.read( DriftSqlType.dateTime, data['${effectivePrefix}created_at'], @@ -444,12 +445,12 @@ class $GroupTableTable extends GroupTable class GroupTableData extends DataClass implements Insertable { final String id; final String name; - final String? description; + final String description; final DateTime createdAt; const GroupTableData({ required this.id, required this.name, - this.description, + required this.description, required this.createdAt, }); @override @@ -457,9 +458,7 @@ class GroupTableData extends DataClass implements Insertable { final map = {}; map['id'] = Variable(id); map['name'] = Variable(name); - if (!nullToAbsent || description != null) { - map['description'] = Variable(description); - } + map['description'] = Variable(description); map['created_at'] = Variable(createdAt); return map; } @@ -468,9 +467,7 @@ class GroupTableData extends DataClass implements Insertable { return GroupTableCompanion( id: Value(id), name: Value(name), - description: description == null && nullToAbsent - ? const Value.absent() - : Value(description), + description: Value(description), createdAt: Value(createdAt), ); } @@ -483,7 +480,7 @@ class GroupTableData extends DataClass implements Insertable { return GroupTableData( id: serializer.fromJson(json['id']), name: serializer.fromJson(json['name']), - description: serializer.fromJson(json['description']), + description: serializer.fromJson(json['description']), createdAt: serializer.fromJson(json['createdAt']), ); } @@ -493,7 +490,7 @@ class GroupTableData extends DataClass implements Insertable { return { 'id': serializer.toJson(id), 'name': serializer.toJson(name), - 'description': serializer.toJson(description), + 'description': serializer.toJson(description), 'createdAt': serializer.toJson(createdAt), }; } @@ -501,12 +498,12 @@ class GroupTableData extends DataClass implements Insertable { GroupTableData copyWith({ String? id, String? name, - Value description = const Value.absent(), + String? description, DateTime? createdAt, }) => GroupTableData( id: id ?? this.id, name: name ?? this.name, - description: description.present ? description.value : this.description, + description: description ?? this.description, createdAt: createdAt ?? this.createdAt, ); GroupTableData copyWithCompanion(GroupTableCompanion data) { @@ -546,7 +543,7 @@ class GroupTableData extends DataClass implements Insertable { class GroupTableCompanion extends UpdateCompanion { final Value id; final Value name; - final Value description; + final Value description; final Value createdAt; final Value rowid; const GroupTableCompanion({ @@ -559,11 +556,12 @@ class GroupTableCompanion extends UpdateCompanion { GroupTableCompanion.insert({ required String id, required String name, - this.description = const Value.absent(), + required String description, required DateTime createdAt, this.rowid = const Value.absent(), }) : id = Value(id), name = Value(name), + description = Value(description), createdAt = Value(createdAt); static Insertable custom({ Expression? id, @@ -584,7 +582,7 @@ class GroupTableCompanion extends UpdateCompanion { GroupTableCompanion copyWith({ Value? id, Value? name, - Value? description, + Value? description, Value? createdAt, Value? rowid, }) { @@ -691,9 +689,9 @@ class $GameTableTable extends GameTable late final GeneratedColumn icon = GeneratedColumn( 'icon', aliasedName, - true, + false, type: DriftSqlType.string, - requiredDuringInsert: false, + requiredDuringInsert: true, ); static const VerificationMeta _createdAtMeta = const VerificationMeta( 'createdAt', @@ -773,6 +771,8 @@ class $GameTableTable extends GameTable _iconMeta, icon.isAcceptableOrUnknown(data['icon']!, _iconMeta), ); + } else if (isInserting) { + context.missing(_iconMeta); } if (data.containsKey('created_at')) { context.handle( @@ -814,7 +814,7 @@ class $GameTableTable extends GameTable icon: attachedDatabase.typeMapping.read( DriftSqlType.string, data['${effectivePrefix}icon'], - ), + )!, createdAt: attachedDatabase.typeMapping.read( DriftSqlType.dateTime, data['${effectivePrefix}created_at'], @@ -834,7 +834,7 @@ class GameTableData extends DataClass implements Insertable { final String ruleset; final String description; final String color; - final String? icon; + final String icon; final DateTime createdAt; const GameTableData({ required this.id, @@ -842,7 +842,7 @@ class GameTableData extends DataClass implements Insertable { required this.ruleset, required this.description, required this.color, - this.icon, + required this.icon, required this.createdAt, }); @override @@ -853,9 +853,7 @@ class GameTableData extends DataClass implements Insertable { map['ruleset'] = Variable(ruleset); map['description'] = Variable(description); map['color'] = Variable(color); - if (!nullToAbsent || icon != null) { - map['icon'] = Variable(icon); - } + map['icon'] = Variable(icon); map['created_at'] = Variable(createdAt); return map; } @@ -867,7 +865,7 @@ class GameTableData extends DataClass implements Insertable { ruleset: Value(ruleset), description: Value(description), color: Value(color), - icon: icon == null && nullToAbsent ? const Value.absent() : Value(icon), + icon: Value(icon), createdAt: Value(createdAt), ); } @@ -883,7 +881,7 @@ class GameTableData extends DataClass implements Insertable { ruleset: serializer.fromJson(json['ruleset']), description: serializer.fromJson(json['description']), color: serializer.fromJson(json['color']), - icon: serializer.fromJson(json['icon']), + icon: serializer.fromJson(json['icon']), createdAt: serializer.fromJson(json['createdAt']), ); } @@ -896,7 +894,7 @@ class GameTableData extends DataClass implements Insertable { 'ruleset': serializer.toJson(ruleset), 'description': serializer.toJson(description), 'color': serializer.toJson(color), - 'icon': serializer.toJson(icon), + 'icon': serializer.toJson(icon), 'createdAt': serializer.toJson(createdAt), }; } @@ -907,7 +905,7 @@ class GameTableData extends DataClass implements Insertable { String? ruleset, String? description, String? color, - Value icon = const Value.absent(), + String? icon, DateTime? createdAt, }) => GameTableData( id: id ?? this.id, @@ -915,7 +913,7 @@ class GameTableData extends DataClass implements Insertable { ruleset: ruleset ?? this.ruleset, description: description ?? this.description, color: color ?? this.color, - icon: icon.present ? icon.value : this.icon, + icon: icon ?? this.icon, createdAt: createdAt ?? this.createdAt, ); GameTableData copyWithCompanion(GameTableCompanion data) { @@ -968,7 +966,7 @@ class GameTableCompanion extends UpdateCompanion { final Value ruleset; final Value description; final Value color; - final Value icon; + final Value icon; final Value createdAt; final Value rowid; const GameTableCompanion({ @@ -987,7 +985,7 @@ class GameTableCompanion extends UpdateCompanion { required String ruleset, required String description, required String color, - this.icon = const Value.absent(), + required String icon, required DateTime createdAt, this.rowid = const Value.absent(), }) : id = Value(id), @@ -995,6 +993,7 @@ class GameTableCompanion extends UpdateCompanion { ruleset = Value(ruleset), description = Value(description), color = Value(color), + icon = Value(icon), createdAt = Value(createdAt); static Insertable custom({ Expression? id, @@ -1024,7 +1023,7 @@ class GameTableCompanion extends UpdateCompanion { Value? ruleset, Value? description, Value? color, - Value? icon, + Value? icon, Value? createdAt, Value? rowid, }) { @@ -2783,7 +2782,7 @@ typedef $$PlayerTableTableCreateCompanionBuilder = PlayerTableCompanion Function({ required String id, required String name, - Value description, + required String description, required DateTime createdAt, Value rowid, }); @@ -2791,7 +2790,7 @@ typedef $$PlayerTableTableUpdateCompanionBuilder = PlayerTableCompanion Function({ Value id, Value name, - Value description, + Value description, Value createdAt, Value rowid, }); @@ -3133,7 +3132,7 @@ class $$PlayerTableTableTableManager ({ Value id = const Value.absent(), Value name = const Value.absent(), - Value description = const Value.absent(), + Value description = const Value.absent(), Value createdAt = const Value.absent(), Value rowid = const Value.absent(), }) => PlayerTableCompanion( @@ -3147,7 +3146,7 @@ class $$PlayerTableTableTableManager ({ required String id, required String name, - Value description = const Value.absent(), + required String description, required DateTime createdAt, Value rowid = const Value.absent(), }) => PlayerTableCompanion.insert( @@ -3274,7 +3273,7 @@ typedef $$GroupTableTableCreateCompanionBuilder = GroupTableCompanion Function({ required String id, required String name, - Value description, + required String description, required DateTime createdAt, Value rowid, }); @@ -3282,7 +3281,7 @@ typedef $$GroupTableTableUpdateCompanionBuilder = GroupTableCompanion Function({ Value id, Value name, - Value description, + Value description, Value createdAt, Value rowid, }); @@ -3550,7 +3549,7 @@ class $$GroupTableTableTableManager ({ Value id = const Value.absent(), Value name = const Value.absent(), - Value description = const Value.absent(), + Value description = const Value.absent(), Value createdAt = const Value.absent(), Value rowid = const Value.absent(), }) => GroupTableCompanion( @@ -3564,7 +3563,7 @@ class $$GroupTableTableTableManager ({ required String id, required String name, - Value description = const Value.absent(), + required String description, required DateTime createdAt, Value rowid = const Value.absent(), }) => GroupTableCompanion.insert( @@ -3664,7 +3663,7 @@ typedef $$GameTableTableCreateCompanionBuilder = required String ruleset, required String description, required String color, - Value icon, + required String icon, required DateTime createdAt, Value rowid, }); @@ -3675,7 +3674,7 @@ typedef $$GameTableTableUpdateCompanionBuilder = Value ruleset, Value description, Value color, - Value icon, + Value icon, Value createdAt, Value rowid, }); @@ -3909,7 +3908,7 @@ class $$GameTableTableTableManager Value ruleset = const Value.absent(), Value description = const Value.absent(), Value color = const Value.absent(), - Value icon = const Value.absent(), + Value icon = const Value.absent(), Value createdAt = const Value.absent(), Value rowid = const Value.absent(), }) => GameTableCompanion( @@ -3929,7 +3928,7 @@ class $$GameTableTableTableManager required String ruleset, required String description, required String color, - Value icon = const Value.absent(), + required String icon, required DateTime createdAt, Value rowid = const Value.absent(), }) => GameTableCompanion.insert( diff --git a/lib/data/db/tables/game_table.dart b/lib/data/db/tables/game_table.dart index ce71a59..a55b8fc 100644 --- a/lib/data/db/tables/game_table.dart +++ b/lib/data/db/tables/game_table.dart @@ -6,7 +6,7 @@ class GameTable extends Table { TextColumn get ruleset => text()(); TextColumn get description => text()(); TextColumn get color => text()(); - TextColumn get icon => text().nullable()(); + TextColumn get icon => text()(); DateTimeColumn get createdAt => dateTime()(); @override diff --git a/lib/data/db/tables/group_table.dart b/lib/data/db/tables/group_table.dart index 09bf79d..2f30cce 100644 --- a/lib/data/db/tables/group_table.dart +++ b/lib/data/db/tables/group_table.dart @@ -3,7 +3,7 @@ import 'package:drift/drift.dart'; class GroupTable extends Table { TextColumn get id => text()(); TextColumn get name => text()(); - TextColumn get description => text().nullable()(); + TextColumn get description => text()(); DateTimeColumn get createdAt => dateTime()(); @override diff --git a/lib/data/db/tables/player_table.dart b/lib/data/db/tables/player_table.dart index 3e061a0..15b29a5 100644 --- a/lib/data/db/tables/player_table.dart +++ b/lib/data/db/tables/player_table.dart @@ -3,7 +3,7 @@ import 'package:drift/drift.dart'; class PlayerTable extends Table { TextColumn get id => text()(); TextColumn get name => text()(); - TextColumn get description => text().nullable()(); + TextColumn get description => text()(); DateTimeColumn get createdAt => dateTime()(); @override diff --git a/lib/data/dto/game.dart b/lib/data/dto/game.dart index c74b8aa..4081f4e 100644 --- a/lib/data/dto/game.dart +++ b/lib/data/dto/game.dart @@ -9,7 +9,7 @@ class Game { final Ruleset ruleset; final String description; final String color; - final String? icon; + final String icon; Game({ String? id, @@ -18,7 +18,7 @@ class Game { required this.ruleset, required this.description, required this.color, - this.icon, + required this.icon, }) : id = id ?? const Uuid().v4(), createdAt = createdAt ?? clock.now(); diff --git a/lib/data/dto/group.dart b/lib/data/dto/group.dart index a69c982..00ee280 100644 --- a/lib/data/dto/group.dart +++ b/lib/data/dto/group.dart @@ -5,7 +5,7 @@ import 'package:uuid/uuid.dart'; class Group { final String id; final String name; - final String? description; + final String description; final DateTime createdAt; final List members; @@ -13,7 +13,7 @@ class Group { String? id, DateTime? createdAt, required this.name, - this.description, + required this.description, required this.members, }) : id = id ?? const Uuid().v4(), createdAt = createdAt ?? clock.now(); diff --git a/lib/data/dto/match.dart b/lib/data/dto/match.dart index b71757a..a9b81ba 100644 --- a/lib/data/dto/match.dart +++ b/lib/data/dto/match.dart @@ -1,4 +1,5 @@ import 'package:clock/clock.dart'; +import 'package:game_tracker/core/enums.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'; @@ -8,20 +9,20 @@ class Match { final String id; final DateTime createdAt; final String name; - final Game? game; + final Game game; final Group? group; final List? players; - final String? notes; + final String notes; Player? winner; Match({ String? id, DateTime? createdAt, required this.name, - this.game, + required this.game, this.group, this.players, - this.notes, + required this.notes, this.winner, }) : id = id ?? const Uuid().v4(), createdAt = createdAt ?? clock.now(); @@ -37,17 +38,17 @@ class Match { : id = json['id'], createdAt = DateTime.parse(json['createdAt']), name = json['name'], - game = null, // Populated during import via DataTransferService + game = Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''), // Populated during import via DataTransferService group = null, // Populated during import via DataTransferService players = [], // Populated during import via DataTransferService - notes = json['notes']; + notes = json['notes'] ?? ''; /// Converts the Match instance to a JSON object using normalized format (ID references only). Map toJson() => { 'id': id, 'createdAt': createdAt.toIso8601String(), 'name': name, - 'gameId': game?.id, + 'gameId': game.id, 'groupId': group?.id, 'playerIds': (players ?? []).map((player) => player.id).toList(), 'notes': notes, diff --git a/lib/data/dto/player.dart b/lib/data/dto/player.dart index 6c3ab6d..13e4123 100644 --- a/lib/data/dto/player.dart +++ b/lib/data/dto/player.dart @@ -5,13 +5,13 @@ class Player { final String id; final DateTime createdAt; final String name; - final String? description; + final String description; Player({ String? id, DateTime? createdAt, required this.name, - this.description, + required this.description, }) : id = id ?? const Uuid().v4(), createdAt = createdAt ?? clock.now(); diff --git a/lib/presentation/views/main_menu/group_view/create_group_view.dart b/lib/presentation/views/main_menu/group_view/create_group_view.dart index 4b34095..0bda8b9 100644 --- a/lib/presentation/views/main_menu/group_view/create_group_view.dart +++ b/lib/presentation/views/main_menu/group_view/create_group_view.dart @@ -84,6 +84,7 @@ class _CreateGroupViewState extends State { bool success = await db.groupDao.addGroup( group: Group( name: _groupNameController.text.trim(), + description: '', members: selectedPlayers, ), ); diff --git a/lib/presentation/views/main_menu/group_view/groups_view.dart b/lib/presentation/views/main_menu/group_view/groups_view.dart index 81922f5..24df3b8 100644 --- a/lib/presentation/views/main_menu/group_view/groups_view.dart +++ b/lib/presentation/views/main_menu/group_view/groups_view.dart @@ -35,7 +35,8 @@ class _GroupsViewState extends State { 7, Group( name: 'Skeleton Group', - members: List.filled(6, Player(name: 'Skeleton Player')), + description: '', + members: List.filled(6, Player(name: 'Skeleton Player', description: '')), ), ); diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index f28341e..752cf75 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/constants.dart'; +import 'package:game_tracker/core/enums.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/match.dart'; import 'package:game_tracker/data/dto/player.dart'; @@ -40,13 +42,16 @@ class _HomeViewState extends State { 2, Match( name: 'Skeleton Match', + game: Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''), group: Group( name: 'Skeleton Group', + description: '', members: [ - Player(name: 'Skeleton Player 1'), - Player(name: 'Skeleton Player 2'), + Player(name: 'Skeleton Player 1', description: ''), + Player(name: 'Skeleton Player 2', description: ''), ], ), + notes: '', ), ); @@ -114,7 +119,7 @@ class _HomeViewState extends State { MatchResultView(match: match), ), ); - await updatedWinnerinRecentMatches(match.id); + await updatedWinnerInRecentMatches(match.id); }, ), ) @@ -214,7 +219,7 @@ class _HomeViewState extends State { } /// Updates the winner information for a specific match in the recent matches list. - Future updatedWinnerinRecentMatches(String matchId) async { + Future updatedWinnerInRecentMatches(String matchId) async { final db = Provider.of(context, listen: false); final winner = await db.matchDao.getWinner(matchId: matchId); final matchIndex = recentMatches.indexWhere((match) => match.id == matchId); diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index a97de75..30107b7 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -203,6 +203,7 @@ class _CreateMatchViewState extends State { description: selectedGame.$2, ruleset: selectedGame.$3, color: '0xFF000000', + icon: '', ); } else { // Use the selected game from the list @@ -212,6 +213,7 @@ class _CreateMatchViewState extends State { description: selectedGame.$2, ruleset: selectedGame.$3, color: '0xFF000000', + icon: '', ); } // Add the game to the database if it doesn't exist @@ -225,6 +227,7 @@ class _CreateMatchViewState extends State { game: gameToUse, group: selectedGroup, players: selectedPlayers, + notes: '', ); await db.matchDao.addMatch(match: match); if (context.mounted) { diff --git a/lib/presentation/views/main_menu/match_view/match_view.dart b/lib/presentation/views/main_menu/match_view/match_view.dart index e85bf77..b5488bc 100644 --- a/lib/presentation/views/main_menu/match_view/match_view.dart +++ b/lib/presentation/views/main_menu/match_view/match_view.dart @@ -5,7 +5,9 @@ import 'package:fluttericon/rpg_awesome_icons.dart'; import 'package:game_tracker/core/adaptive_page_route.dart'; import 'package:game_tracker/core/constants.dart'; import 'package:game_tracker/core/custom_theme.dart'; +import 'package:game_tracker/core/enums.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/match.dart'; import 'package:game_tracker/data/dto/player.dart'; @@ -36,12 +38,15 @@ class _MatchViewState extends State { 4, Match( name: 'Skeleton match name', + game: Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''), group: Group( name: 'Group name', - members: List.filled(5, Player(name: 'Player')), + description: '', + members: List.filled(5, Player(name: 'Player', description: '')), ), - winner: Player(name: 'Player'), - players: [Player(name: 'Player')], + winner: Player(name: 'Player', description: ''), + players: [Player(name: 'Player', description: '')], + notes: '', ), ); diff --git a/lib/presentation/views/main_menu/statistics_view.dart b/lib/presentation/views/main_menu/statistics_view.dart index f87a3fb..908b10a 100644 --- a/lib/presentation/views/main_menu/statistics_view.dart +++ b/lib/presentation/views/main_menu/statistics_view.dart @@ -167,7 +167,7 @@ class _StatisticsViewState extends State { final playerId = winCounts[i].$1; final player = players.firstWhere( (p) => p.id == playerId, - orElse: () => Player(id: playerId, name: loc.not_available), + orElse: () => Player(id: playerId, name: loc.not_available, description: ''), ); winCounts[i] = (player.name, winCounts[i].$2); } @@ -231,7 +231,7 @@ class _StatisticsViewState extends State { final playerId = matchCounts[i].$1; final player = players.firstWhere( (p) => p.id == playerId, - orElse: () => Player(id: playerId, name: loc.not_available), + orElse: () => Player(id: playerId, name: loc.not_available, description: ''), ); matchCounts[i] = (player.name, matchCounts[i].$2); } diff --git a/lib/presentation/widgets/player_selection.dart b/lib/presentation/widgets/player_selection.dart index 58b62ec..68aaa7d 100644 --- a/lib/presentation/widgets/player_selection.dart +++ b/lib/presentation/widgets/player_selection.dart @@ -62,7 +62,7 @@ class _PlayerSelectionState extends State { /// Skeleton data used while loading players. late final List skeletonData = List.filled( 7, - Player(name: 'Player 0'), + Player(name: 'Player 0', description: ''), ); @override @@ -260,7 +260,7 @@ class _PlayerSelectionState extends State { final loc = AppLocalizations.of(context); final playerName = _searchBarController.text.trim(); - final createdPlayer = Player(name: playerName); + final createdPlayer = Player(name: playerName, description: ''); final success = await db.playerDao.addPlayer(player: createdPlayer); if (!context.mounted) return; diff --git a/lib/services/data_transfer_service.dart b/lib/services/data_transfer_service.dart index e659e45..4bd8635 100644 --- a/lib/services/data_transfer_service.dart +++ b/lib/services/data_transfer_service.dart @@ -61,7 +61,7 @@ class DataTransferService { 'id': m.id, 'name': m.name, 'createdAt': m.createdAt.toIso8601String(), - 'gameId': m.game?.id, + 'gameId': m.game.id, 'groupId': m.group?.id, 'playerIds': (m.players ?? []).map((p) => p.id).toList(), 'notes': m.notes, @@ -160,7 +160,7 @@ class DataTransferService { return Group( id: map['id'] as String, name: map['name'] as String, - description: map['description'] as String?, + description: map['description'] as String, members: members, createdAt: DateTime.parse(map['createdAt'] as String), ); @@ -192,11 +192,11 @@ class DataTransferService { final List importedMatches = matchesJson.map((m) { final map = m as Map; - final String? gameId = map['gameId'] as String?; + final String gameId = map['gameId'] as String; final String? groupId = map['groupId'] as String?; final List playerIds = (map['playerIds'] as List? ?? []).cast(); - final game = (gameId == null) ? null : gameById[gameId]; + final game = gameById[gameId]; final group = (groupId == null) ? null : groupById[groupId]; final players = playerIds .map((id) => playerById[id]) @@ -206,11 +206,11 @@ class DataTransferService { return Match( id: map['id'] as String, name: map['name'] as String, - game: game, + game: game ?? Game(name: 'Unknown', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''), group: group, players: players.isNotEmpty ? players : null, createdAt: DateTime.parse(map['createdAt'] as String), - notes: map['notes'] as String?, + notes: map['notes'] as String? ?? '', ); }).toList(); diff --git a/test/db_tests/game_test.dart b/test/db_tests/game_test.dart index 040d607..e38b85c 100644 --- a/test/db_tests/game_test.dart +++ b/test/db_tests/game_test.dart @@ -44,6 +44,7 @@ void main() { ruleset: Ruleset.highestScore, description: 'A board game about real estate', color: '0xFF000000', + icon: '', ); }); }); @@ -133,7 +134,7 @@ void main() { // Verifies that a game with null optional fields can be added and retrieved. test('addGame handles game with null optional fields', () async { - final gameWithNulls = Game(name: 'Simple Game', ruleset: Ruleset.lowestScore, description: 'A simple game', color: '0xFF000000'); + final gameWithNulls = Game(name: 'Simple Game', ruleset: Ruleset.lowestScore, description: 'A simple game', color: '0xFF000000', icon: ''); final result = await database.gameDao.addGame(game: gameWithNulls); expect(result, true); @@ -374,19 +375,19 @@ void main() { expect(updatedGame.icon, 'new_chess_icon'); }); - // Verifies that updateGameIcon can set the icon to null. - test('updateGameIcon can set icon to null', () async { + // Verifies that updateGameIcon can update the icon. + test('updateGameIcon updates icon correctly', () async { await database.gameDao.addGame(game: testGame1); await database.gameDao.updateGameIcon( gameId: testGame1.id, - newIcon: null, + newIcon: 'new_icon', ); final updatedGame = await database.gameDao.getGameById( gameId: testGame1.id, ); - expect(updatedGame.icon, isNull); + expect(updatedGame.icon, 'new_icon'); }); // Verifies that updateGameIcon does nothing when game doesn't exist. @@ -460,6 +461,7 @@ void main() { ruleset: Ruleset.multipleWinners, description: 'Description with émojis 🎮🎲', color: '0xFF000000', + icon: '', ); await database.gameDao.addGame(game: specialGame); @@ -498,6 +500,7 @@ void main() { description: longString, ruleset: Ruleset.multipleWinners, color: '0xFF000000', + icon: '', ); await database.gameDao.addGame(game: longGame); diff --git a/test/db_tests/group_test.dart b/test/db_tests/group_test.dart index ada0430..09b7466 100644 --- a/test/db_tests/group_test.dart +++ b/test/db_tests/group_test.dart @@ -29,27 +29,31 @@ void main() { ); withClock(fakeClock, () { - testPlayer1 = Player(name: 'Alice'); - testPlayer2 = Player(name: 'Bob'); - testPlayer3 = Player(name: 'Charlie'); - testPlayer4 = Player(name: 'Diana'); + testPlayer1 = Player(name: 'Alice', description: ''); + testPlayer2 = Player(name: 'Bob', description: ''); + testPlayer3 = Player(name: 'Charlie', description: ''); + testPlayer4 = Player(name: 'Diana', description: ''); testGroup1 = Group( name: 'Test Group', + description: '', members: [testPlayer1, testPlayer2, testPlayer3], ); testGroup2 = Group( id: 'gr2', name: 'Second Group', + description: '', members: [testPlayer2, testPlayer3, testPlayer4], ); testGroup3 = Group( id: 'gr2', name: 'Second Group', + description: '', members: [testPlayer2, testPlayer4], ); testGroup4 = Group( id: 'gr2', name: 'Second Group', + description: '', members: [testPlayer1, testPlayer2, testPlayer3, testPlayer4], ); }); @@ -262,14 +266,14 @@ void main() { final updated = await database.groupDao.updateGroupDescription( groupId: groupWithDescription.id, - newDescription: null, + newDescription: 'Updated description', ); expect(updated, true); final result = await database.groupDao.getGroupById( groupId: groupWithDescription.id, ); - expect(result.description, isNull); + expect(result.description, 'Updated description'); }); // Verifies that updateGroupDescription returns false for a non-existent group. @@ -324,6 +328,7 @@ void main() { test('Group with empty members list is stored correctly', () async { final emptyGroup = Group( name: 'Empty Group', + description: '', members: [], ); await database.groupDao.addGroup(group: emptyGroup); diff --git a/test/db_tests/match_test.dart b/test/db_tests/match_test.dart index 80a9fa7..7bcb0a8 100644 --- a/test/db_tests/match_test.dart +++ b/test/db_tests/match_test.dart @@ -36,26 +36,29 @@ void main() { ); withClock(fakeClock, () { - testPlayer1 = Player(name: 'Alice'); - testPlayer2 = Player(name: 'Bob'); - testPlayer3 = Player(name: 'Charlie'); - testPlayer4 = Player(name: 'Diana'); - testPlayer5 = Player(name: 'Eve'); + testPlayer1 = Player(name: 'Alice', description: ''); + testPlayer2 = Player(name: 'Bob', description: ''); + testPlayer3 = Player(name: 'Charlie', description: ''); + testPlayer4 = Player(name: 'Diana', description: ''); + testPlayer5 = Player(name: 'Eve', description: ''); testGroup1 = Group( name: 'Test Group 2', + description: '', members: [testPlayer1, testPlayer2, testPlayer3], ); testGroup2 = Group( name: 'Test Group 2', + description: '', members: [testPlayer4, testPlayer5], ); - testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000'); + testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000', icon: ''); testMatch1 = Match( name: 'First Test Match', game: testGame, group: testGroup1, players: [testPlayer4, testPlayer5], winner: testPlayer4, + notes: '', ); testMatch2 = Match( name: 'Second Test Match', @@ -63,17 +66,20 @@ void main() { group: testGroup2, players: [testPlayer1, testPlayer2, testPlayer3], winner: testPlayer2, + notes: '', ); testMatchOnlyPlayers = Match( name: 'Test Match with Players', game: testGame, players: [testPlayer1, testPlayer2, testPlayer3], winner: testPlayer3, + notes: '', ); testMatchOnlyGroup = Match( name: 'Test Match with Group', game: testGame, group: testGroup2, + notes: '', ); }); await database.playerDao.addPlayersAsList( diff --git a/test/db_tests/player_group_test.dart b/test/db_tests/player_group_test.dart index 8959092..fa270bb 100644 --- a/test/db_tests/player_group_test.dart +++ b/test/db_tests/player_group_test.dart @@ -26,12 +26,13 @@ void main() { ); withClock(fakeClock, () { - testPlayer1 = Player(name: 'Alice'); - testPlayer2 = Player(name: 'Bob'); - testPlayer3 = Player(name: 'Charlie'); - testPlayer4 = Player(name: 'Diana'); + testPlayer1 = Player(name: 'Alice', description: ''); + testPlayer2 = Player(name: 'Bob', description: ''); + testPlayer3 = Player(name: 'Charlie', description: ''); + testPlayer4 = Player(name: 'Diana', description: ''); testGroup = Group( name: 'Test Group', + description: '', members: [testPlayer1, testPlayer2, testPlayer3], ); }); @@ -186,7 +187,7 @@ void main() { // Verifies that getPlayersOfGroup returns empty list for group with no members. test('getPlayersOfGroup returns empty list for empty group', () async { - final emptyGroup = Group(name: 'Empty Group', members: []); + final emptyGroup = Group(name: 'Empty Group', description: '', members: []); await database.groupDao.addGroup(group: emptyGroup); final players = await database.playerGroupDao.getPlayersOfGroup( @@ -230,7 +231,7 @@ void main() { // Verifies that a player can be in multiple groups. test('Player can be in multiple groups', () async { - final secondGroup = Group(name: 'Second Group', members: []); + final secondGroup = Group(name: 'Second Group', description: '', members: []); await database.groupDao.addGroup(group: testGroup); await database.groupDao.addGroup(group: secondGroup); @@ -255,7 +256,7 @@ void main() { // Verifies that removing player from one group doesn't affect other groups. test('Removing player from one group does not affect other groups', () async { - final secondGroup = Group(name: 'Second Group', members: [testPlayer1]); + final secondGroup = Group(name: 'Second Group', description: '', members: [testPlayer1]); await database.groupDao.addGroup(group: testGroup); await database.groupDao.addGroup(group: secondGroup); diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/player_match_test.dart index 0e5fb27..b8d3313 100644 --- a/test/db_tests/player_match_test.dart +++ b/test/db_tests/player_match_test.dart @@ -37,26 +37,29 @@ void main() { ); withClock(fakeClock, () { - testPlayer1 = Player(name: 'Alice'); - testPlayer2 = Player(name: 'Bob'); - testPlayer3 = Player(name: 'Charlie'); - testPlayer4 = Player(name: 'Diana'); - testPlayer5 = Player(name: 'Eve'); - testPlayer6 = Player(name: 'Frank'); + testPlayer1 = Player(name: 'Alice', description: ''); + testPlayer2 = Player(name: 'Bob', description: ''); + testPlayer3 = Player(name: 'Charlie', description: ''); + testPlayer4 = Player(name: 'Diana', description: ''); + testPlayer5 = Player(name: 'Eve', description: ''); + testPlayer6 = Player(name: 'Frank', description: ''); testGroup = Group( name: 'Test Group', + description: '', members: [testPlayer1, testPlayer2, testPlayer3], ); - testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000'); + testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000', icon: ''); testMatchOnlyGroup = Match( name: 'Test Match with Group', game: testGame, group: testGroup, + notes: '', ); testMatchOnlyPlayers = Match( name: 'Test Match with Players', game: testGame, players: [testPlayer4, testPlayer5, testPlayer6], + notes: '', ); testTeam1 = Team( name: 'Team Alpha', @@ -226,8 +229,8 @@ void main() { 'Adding the same player to separate matches works correctly', () async { final playersList = [testPlayer1, testPlayer2, testPlayer3]; - final match1 = Match(name: 'Match 1', game: testGame, players: playersList); - final match2 = Match(name: 'Match 2', game: testGame, players: playersList); + final match1 = Match(name: 'Match 1', game: testGame, players: playersList, notes: ''); + final match2 = Match(name: 'Match 2', game: testGame, players: playersList, notes: ''); await Future.wait([ database.matchDao.addMatch(match: match1), @@ -760,8 +763,8 @@ void main() { // Verifies that removePlayerFromMatch does not affect other matches. test('removePlayerFromMatch does not affect other matches', () async { final playersList = [testPlayer1, testPlayer2]; - final match1 = Match(name: 'Match 1', game: testGame, players: playersList); - final match2 = Match(name: 'Match 2', game: testGame, players: playersList); + final match1 = Match(name: 'Match 1', game: testGame, players: playersList, notes: ''); + final match2 = Match(name: 'Match 2', game: testGame, players: playersList, notes: ''); await Future.wait([ database.matchDao.addMatch(match: match1), @@ -793,8 +796,8 @@ void main() { // Verifies that updating scores for players in different matches are independent. test('Player scores are independent across matches', () async { final playersList = [testPlayer1]; - final match1 = Match(name: 'Match 1', game: testGame, players: playersList); - final match2 = Match(name: 'Match 2', game: testGame, players: playersList); + final match1 = Match(name: 'Match 1', game: testGame, players: playersList, notes: ''); + final match2 = Match(name: 'Match 2', game: testGame, players: playersList, notes: ''); await Future.wait([ database.matchDao.addMatch(match: match1), diff --git a/test/db_tests/player_test.dart b/test/db_tests/player_test.dart index da5b904..8ce0e66 100644 --- a/test/db_tests/player_test.dart +++ b/test/db_tests/player_test.dart @@ -24,10 +24,10 @@ void main() { ); withClock(fakeClock, () { - testPlayer1 = Player(name: 'Test Player'); - testPlayer2 = Player(name: 'Second Player'); - testPlayer3 = Player(name: 'Charlie'); - testPlayer4 = Player(name: 'Diana'); + testPlayer1 = Player(name: 'Test Player', description: ''); + testPlayer2 = Player(name: 'Second Player', description: ''); + testPlayer3 = Player(name: 'Charlie', description: ''); + testPlayer4 = Player(name: 'Diana', description: ''); }); }); tearDown(() async { @@ -265,7 +265,7 @@ void main() { // Verifies that a player with special characters in name is stored correctly. test('Player with special characters in name is stored correctly', () async { - final specialPlayer = Player(name: 'Test!@#\$%^&*()_+-=[]{}|;\':",.<>?/`~'); + final specialPlayer = Player(name: 'Test!@#\$%^&*()_+-=[]{}|;\':",.<>?/`~', description: ''); await database.playerDao.addPlayer(player: specialPlayer); @@ -293,14 +293,14 @@ void main() { // Verifies that a player with null description is stored correctly. test('Player with null description is stored correctly', () async { - final playerWithoutDescription = Player(name: 'No Description Player'); + final playerWithoutDescription = Player(name: 'No Description Player', description: ''); await database.playerDao.addPlayer(player: playerWithoutDescription); final fetchedPlayer = await database.playerDao.getPlayerById( playerId: playerWithoutDescription.id, ); - expect(fetchedPlayer.description, isNull); + expect(fetchedPlayer.description, ''); }); // Verifies that multiple updates to the same player work correctly. @@ -340,7 +340,7 @@ void main() { // Verifies that a player with empty string name is stored correctly. test('Player with empty string name is stored correctly', () async { - final emptyNamePlayer = Player(name: ''); + final emptyNamePlayer = Player(name: '', description: ''); await database.playerDao.addPlayer(player: emptyNamePlayer); @@ -353,7 +353,7 @@ void main() { // Verifies that a player with very long name is stored correctly. test('Player with very long name is stored correctly', () async { final longName = 'A' * 1000; - final longNamePlayer = Player(name: longName); + final longNamePlayer = Player(name: longName, description: ''); await database.playerDao.addPlayer(player: longNamePlayer); diff --git a/test/db_tests/score_test.dart b/test/db_tests/score_test.dart index 9052a32..bbd7729 100644 --- a/test/db_tests/score_test.dart +++ b/test/db_tests/score_test.dart @@ -29,19 +29,21 @@ void main() { ); withClock(fakeClock, () { - testPlayer1 = Player(name: 'Alice'); - testPlayer2 = Player(name: 'Bob'); - testPlayer3 = Player(name: 'Charlie'); - testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000'); + testPlayer1 = Player(name: 'Alice', description: ''); + testPlayer2 = Player(name: 'Bob', description: ''); + testPlayer3 = Player(name: 'Charlie', description: ''); + testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000', icon: ''); testMatch1 = Match( name: 'Test Match 1', game: testGame, players: [testPlayer1, testPlayer2], + notes: '', ); testMatch2 = Match( name: 'Test Match 2', game: testGame, players: [testPlayer2, testPlayer3], + notes: '', ); }); diff --git a/test/db_tests/team_test.dart b/test/db_tests/team_test.dart index efeaf18..19338cb 100644 --- a/test/db_tests/team_test.dart +++ b/test/db_tests/team_test.dart @@ -33,10 +33,10 @@ void main() { ); withClock(fakeClock, () { - testPlayer1 = Player(name: 'Alice'); - testPlayer2 = Player(name: 'Bob'); - testPlayer3 = Player(name: 'Charlie'); - testPlayer4 = Player(name: 'Diana'); + testPlayer1 = Player(name: 'Alice', description: ''); + testPlayer2 = Player(name: 'Bob', description: ''); + testPlayer3 = Player(name: 'Charlie', description: ''); + testPlayer4 = Player(name: 'Diana', description: ''); testTeam1 = Team( name: 'Team Alpha', members: [testPlayer1, testPlayer2], @@ -49,8 +49,8 @@ void main() { name: 'Team Gamma', members: [testPlayer1, testPlayer3], ); - testGame1 = Game(name: 'Game 1', ruleset: Ruleset.singleWinner, description: 'Test game 1', color: '0xFF000000'); - testGame2 = Game(name: 'Game 2', ruleset: Ruleset.highestScore, description: 'Test game 2', color: '0xFF000000'); + testGame1 = Game(name: 'Game 1', ruleset: Ruleset.singleWinner, description: 'Test game 1', color: '0xFF000000', icon: ''); + testGame2 = Game(name: 'Game 2', ruleset: Ruleset.highestScore, description: 'Test game 2', color: '0xFF000000', icon: ''); }); await database.playerDao.addPlayersAsList( @@ -344,8 +344,8 @@ void main() { // Verifies that teams with overlapping members are independent. test('Teams with overlapping members are independent', () async { // Create two matches since player_match has primary key {playerId, matchId} - final match1 = Match(name: 'Match 1', game: testGame1); - final match2 = Match(name: 'Match 2', game: testGame2); + final match1 = Match(name: 'Match 1', game: testGame1, notes: ''); + final match2 = Match(name: 'Match 2', game: testGame2, notes: ''); await database.matchDao.addMatch(match: match1); await database.matchDao.addMatch(match: match2); From 2ea68dcc89b6446cc3889fafeeca10dfc6a577f5 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sun, 1 Feb 2026 17:29:19 +0100 Subject: [PATCH 69/87] fix errors after merging --- lib/data/dao/game_dao.dart | 54 +- lib/data/dao/match_dao.dart | 4 + lib/data/dao/player_match_dao.dart | 1 + lib/data/dao/score_dao.dart | 4 +- lib/data/dao/team_dao.dart | 8 +- lib/data/db/database.dart | 20 +- lib/data/db/database.g.dart | 1070 ++++++++--------- lib/data/db/tables/match_table.dart | 4 +- lib/data/db/tables/player_match_table.dart | 1 + lib/data/db/tables/score_table.dart | 4 +- lib/data/dto/game.dart | 2 +- lib/data/dto/match.dart | 2 + lib/data/dto/team.dart | 2 +- lib/main.dart | 4 +- .../views/main_menu/home_view.dart | 52 +- .../create_match/create_match_view.dart | 1 + .../main_menu/match_view/match_view.dart | 2 + lib/services/data_transfer_service.dart | 2 + test/db_tests/game_test.dart | 7 +- test/db_tests/match_test.dart | 12 +- test/db_tests/player_match_test.dart | 5 +- test/db_tests/score_test.dart | 10 +- test/db_tests/team_test.dart | 12 +- 23 files changed, 632 insertions(+), 651 deletions(-) diff --git a/lib/data/dao/game_dao.dart b/lib/data/dao/game_dao.dart index 0fd761c..b656266 100644 --- a/lib/data/dao/game_dao.dart +++ b/lib/data/dao/game_dao.dart @@ -1,8 +1,8 @@ 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/core/enums.dart'; +import 'package:tallee/data/db/database.dart'; +import 'package:tallee/data/db/tables/game_table.dart'; +import 'package:tallee/data/dto/game.dart'; +import 'package:tallee/core/enums.dart'; part 'game_dao.g.dart'; @@ -111,20 +111,14 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { } /// Updates the name of the game with the given [gameId] to [newName]. - Future updateGameName({ - required String gameId, - required String newName, - }) async { - await (update(gameTable)..where((g) => g.id.equals(gameId))).write( - GameTableCompanion(name: Value(newName)), - ); + Future updateGameName({required String gameId, required String newName}) async { + await (update( + gameTable, + )..where((g) => g.id.equals(gameId))).write(GameTableCompanion(name: Value(newName))); } /// Updates the ruleset of the game with the given [gameId]. - Future updateGameRuleset({ - required String gameId, - required Ruleset newRuleset, - }) async { + Future updateGameRuleset({required String gameId, required Ruleset newRuleset}) async { await (update(gameTable)..where((g) => g.id.equals(gameId))).write( GameTableCompanion(ruleset: Value(newRuleset.name)), ); @@ -141,31 +135,24 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { } /// Updates the color of the game with the given [gameId]. - Future updateGameColor({ - required String gameId, - required String newColor, - }) async { - await (update(gameTable)..where((g) => g.id.equals(gameId))).write( - GameTableCompanion(color: Value(newColor)), - ); + Future updateGameColor({required String gameId, required String newColor}) async { + await (update( + gameTable, + )..where((g) => g.id.equals(gameId))).write(GameTableCompanion(color: Value(newColor))); } /// Updates the icon of the game with the given [gameId]. - Future updateGameIcon({ - required String gameId, - required String newIcon, - }) async { - await (update(gameTable)..where((g) => g.id.equals(gameId))).write( - GameTableCompanion(icon: Value(newIcon)), - ); + Future updateGameIcon({required String gameId, required String newIcon}) async { + await (update( + gameTable, + )..where((g) => g.id.equals(gameId))).write(GameTableCompanion(icon: Value(newIcon))); } /// Retrieves the total count of games in the database. Future getGameCount() async { - final count = - await (selectOnly(gameTable)..addColumns([gameTable.id.count()])) - .map((row) => row.read(gameTable.id.count())) - .getSingle(); + final count = await (selectOnly( + gameTable, + )..addColumns([gameTable.id.count()])).map((row) => row.read(gameTable.id.count())).getSingle(); return count ?? 0; } @@ -177,4 +164,3 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { return rowsAffected > 0; } } - diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index 06dd335..201fc52 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -1,6 +1,10 @@ import 'package:drift/drift.dart'; import 'package:tallee/data/db/database.dart'; +import 'package:tallee/data/db/tables/game_table.dart'; +import 'package:tallee/data/db/tables/group_table.dart'; import 'package:tallee/data/db/tables/match_table.dart'; +import 'package:tallee/data/db/tables/player_match_table.dart'; +import 'package:tallee/data/dto/game.dart'; import 'package:tallee/data/dto/group.dart'; import 'package:tallee/data/dto/match.dart'; import 'package:tallee/data/dto/player.dart'; diff --git a/lib/data/dao/player_match_dao.dart b/lib/data/dao/player_match_dao.dart index 106f23f..48bf282 100644 --- a/lib/data/dao/player_match_dao.dart +++ b/lib/data/dao/player_match_dao.dart @@ -1,6 +1,7 @@ import 'package:drift/drift.dart'; import 'package:tallee/data/db/database.dart'; import 'package:tallee/data/db/tables/player_match_table.dart'; +import 'package:tallee/data/db/tables/team_table.dart'; import 'package:tallee/data/dto/player.dart'; part 'player_match_dao.g.dart'; diff --git a/lib/data/dao/score_dao.dart b/lib/data/dao/score_dao.dart index 5fa29da..04e8fcf 100644 --- a/lib/data/dao/score_dao.dart +++ b/lib/data/dao/score_dao.dart @@ -1,6 +1,6 @@ import 'package:drift/drift.dart'; -import 'package:game_tracker/data/db/database.dart'; -import 'package:game_tracker/data/db/tables/score_table.dart'; +import 'package:tallee/data/db/database.dart'; +import 'package:tallee/data/db/tables/score_table.dart'; part 'score_dao.g.dart'; diff --git a/lib/data/dao/team_dao.dart b/lib/data/dao/team_dao.dart index 6a40d03..5c2aadb 100644 --- a/lib/data/dao/team_dao.dart +++ b/lib/data/dao/team_dao.dart @@ -1,8 +1,8 @@ import 'package:drift/drift.dart'; -import 'package:game_tracker/data/db/database.dart'; -import 'package:game_tracker/data/db/tables/team_table.dart'; -import 'package:game_tracker/data/dto/player.dart'; -import 'package:game_tracker/data/dto/team.dart'; +import 'package:tallee/data/db/database.dart'; +import 'package:tallee/data/db/tables/team_table.dart'; +import 'package:tallee/data/dto/player.dart'; +import 'package:tallee/data/dto/team.dart'; part 'team_dao.g.dart'; diff --git a/lib/data/db/database.dart b/lib/data/db/database.dart index 4c70b21..4ab053e 100644 --- a/lib/data/db/database.dart +++ b/lib/data/db/database.dart @@ -1,18 +1,22 @@ import 'package:drift/drift.dart'; import 'package:drift_flutter/drift_flutter.dart'; import 'package:path_provider/path_provider.dart'; +import 'package:tallee/data/dao/game_dao.dart'; import 'package:tallee/data/dao/group_dao.dart'; -import 'package:tallee/data/dao/group_match_dao.dart'; import 'package:tallee/data/dao/match_dao.dart'; import 'package:tallee/data/dao/player_dao.dart'; import 'package:tallee/data/dao/player_group_dao.dart'; import 'package:tallee/data/dao/player_match_dao.dart'; -import 'package:tallee/data/db/tables/group_match_table.dart'; +import 'package:tallee/data/dao/score_dao.dart'; +import 'package:tallee/data/dao/team_dao.dart'; +import 'package:tallee/data/db/tables/game_table.dart'; import 'package:tallee/data/db/tables/group_table.dart'; import 'package:tallee/data/db/tables/match_table.dart'; import 'package:tallee/data/db/tables/player_group_table.dart'; import 'package:tallee/data/db/tables/player_match_table.dart'; import 'package:tallee/data/db/tables/player_table.dart'; +import 'package:tallee/data/db/tables/score_table.dart'; +import 'package:tallee/data/db/tables/team_table.dart'; part 'database.g.dart'; @@ -23,7 +27,9 @@ part 'database.g.dart'; MatchTable, PlayerGroupTable, PlayerMatchTable, - GroupMatchTable, + GameTable, + TeamTable, + ScoreTable, ], daos: [ PlayerDao, @@ -31,7 +37,9 @@ part 'database.g.dart'; MatchDao, PlayerGroupDao, PlayerMatchDao, - GroupMatchDao, + GameDao, + ScoreDao, + TeamDao ], ) class AppDatabase extends _$AppDatabase { @@ -52,9 +60,7 @@ class AppDatabase extends _$AppDatabase { static QueryExecutor _openConnection() { return driftDatabase( name: 'gametracker_db', - native: const DriftNativeOptions( - databaseDirectory: getApplicationSupportDirectory, - ), + native: const DriftNativeOptions(databaseDirectory: getApplicationSupportDirectory), ); } } diff --git a/lib/data/db/database.g.dart b/lib/data/db/database.g.dart index b77c4cd..a11c224 100644 --- a/lib/data/db/database.g.dart +++ b/lib/data/db/database.g.dart @@ -1085,265 +1085,6 @@ class GameTableCompanion extends UpdateCompanion { } } -class $TeamTableTable extends TeamTable - with TableInfo<$TeamTableTable, TeamTableData> { - @override - final GeneratedDatabase attachedDatabase; - final String? _alias; - $TeamTableTable(this.attachedDatabase, [this._alias]); - static const VerificationMeta _idMeta = const VerificationMeta('id'); - @override - late final GeneratedColumn id = GeneratedColumn( - 'id', - aliasedName, - false, - type: DriftSqlType.string, - requiredDuringInsert: true, - ); - static const VerificationMeta _nameMeta = const VerificationMeta('name'); - @override - late final GeneratedColumn name = GeneratedColumn( - 'name', - aliasedName, - false, - type: DriftSqlType.string, - requiredDuringInsert: true, - ); - static const VerificationMeta _createdAtMeta = const VerificationMeta( - 'createdAt', - ); - @override - late final GeneratedColumn createdAt = GeneratedColumn( - 'created_at', - aliasedName, - false, - type: DriftSqlType.dateTime, - requiredDuringInsert: true, - ); - @override - List get $columns => [id, name, createdAt]; - @override - String get aliasedName => _alias ?? actualTableName; - @override - String get actualTableName => $name; - static const String $name = 'team_table'; - @override - VerificationContext validateIntegrity( - Insertable instance, { - bool isInserting = false, - }) { - final context = VerificationContext(); - final data = instance.toColumns(true); - if (data.containsKey('id')) { - context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); - } else if (isInserting) { - context.missing(_idMeta); - } - if (data.containsKey('name')) { - context.handle( - _nameMeta, - name.isAcceptableOrUnknown(data['name']!, _nameMeta), - ); - } else if (isInserting) { - context.missing(_nameMeta); - } - if (data.containsKey('created_at')) { - context.handle( - _createdAtMeta, - createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta), - ); - } else if (isInserting) { - context.missing(_createdAtMeta); - } - return context; - } - - @override - Set get $primaryKey => {id}; - @override - TeamTableData map(Map data, {String? tablePrefix}) { - final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; - return TeamTableData( - id: attachedDatabase.typeMapping.read( - DriftSqlType.string, - data['${effectivePrefix}id'], - )!, - name: attachedDatabase.typeMapping.read( - DriftSqlType.string, - data['${effectivePrefix}name'], - )!, - createdAt: attachedDatabase.typeMapping.read( - DriftSqlType.dateTime, - data['${effectivePrefix}created_at'], - )!, - ); - } - - @override - $TeamTableTable createAlias(String alias) { - return $TeamTableTable(attachedDatabase, alias); - } -} - -class TeamTableData extends DataClass implements Insertable { - final String id; - final String name; - final DateTime createdAt; - const TeamTableData({ - required this.id, - required this.name, - required this.createdAt, - }); - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - map['id'] = Variable(id); - map['name'] = Variable(name); - map['created_at'] = Variable(createdAt); - return map; - } - - TeamTableCompanion toCompanion(bool nullToAbsent) { - return TeamTableCompanion( - id: Value(id), - name: Value(name), - createdAt: Value(createdAt), - ); - } - - factory TeamTableData.fromJson( - Map json, { - ValueSerializer? serializer, - }) { - serializer ??= driftRuntimeOptions.defaultSerializer; - return TeamTableData( - id: serializer.fromJson(json['id']), - name: serializer.fromJson(json['name']), - createdAt: serializer.fromJson(json['createdAt']), - ); - } - @override - Map toJson({ValueSerializer? serializer}) { - serializer ??= driftRuntimeOptions.defaultSerializer; - return { - 'id': serializer.toJson(id), - 'name': serializer.toJson(name), - 'createdAt': serializer.toJson(createdAt), - }; - } - - TeamTableData copyWith({String? id, String? name, DateTime? createdAt}) => - TeamTableData( - id: id ?? this.id, - name: name ?? this.name, - createdAt: createdAt ?? this.createdAt, - ); - TeamTableData copyWithCompanion(TeamTableCompanion data) { - return TeamTableData( - id: data.id.present ? data.id.value : this.id, - name: data.name.present ? data.name.value : this.name, - createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, - ); - } - - @override - String toString() { - return (StringBuffer('TeamTableData(') - ..write('id: $id, ') - ..write('name: $name, ') - ..write('createdAt: $createdAt') - ..write(')')) - .toString(); - } - - @override - int get hashCode => Object.hash(id, name, createdAt); - @override - bool operator ==(Object other) => - identical(this, other) || - (other is TeamTableData && - other.id == this.id && - other.name == this.name && - other.createdAt == this.createdAt); -} - -class TeamTableCompanion extends UpdateCompanion { - final Value id; - final Value name; - final Value createdAt; - final Value rowid; - const TeamTableCompanion({ - this.id = const Value.absent(), - this.name = const Value.absent(), - this.createdAt = const Value.absent(), - this.rowid = const Value.absent(), - }); - TeamTableCompanion.insert({ - required String id, - required String name, - required DateTime createdAt, - this.rowid = const Value.absent(), - }) : id = Value(id), - name = Value(name), - createdAt = Value(createdAt); - static Insertable custom({ - Expression? id, - Expression? name, - Expression? createdAt, - Expression? rowid, - }) { - return RawValuesInsertable({ - if (id != null) 'id': id, - if (name != null) 'name': name, - if (createdAt != null) 'created_at': createdAt, - if (rowid != null) 'rowid': rowid, - }); - } - - TeamTableCompanion copyWith({ - Value? id, - Value? name, - Value? createdAt, - Value? rowid, - }) { - return TeamTableCompanion( - id: id ?? this.id, - name: name ?? this.name, - createdAt: createdAt ?? this.createdAt, - rowid: rowid ?? this.rowid, - ); - } - - @override - Map toColumns(bool nullToAbsent) { - final map = {}; - if (id.present) { - map['id'] = Variable(id.value); - } - if (name.present) { - map['name'] = Variable(name.value); - } - if (createdAt.present) { - map['created_at'] = Variable(createdAt.value); - } - if (rowid.present) { - map['rowid'] = Variable(rowid.value); - } - return map; - } - - @override - String toString() { - return (StringBuffer('TeamTableCompanion(') - ..write('id: $id, ') - ..write('name: $name, ') - ..write('createdAt: $createdAt, ') - ..write('rowid: $rowid') - ..write(')')) - .toString(); - } -} - class $MatchTableTable extends MatchTable with TableInfo<$MatchTableTable, MatchTableData> { @override @@ -1979,6 +1720,265 @@ class PlayerGroupTableCompanion extends UpdateCompanion { } } +class $TeamTableTable extends TeamTable + with TableInfo<$TeamTableTable, TeamTableData> { + @override + final GeneratedDatabase attachedDatabase; + final String? _alias; + $TeamTableTable(this.attachedDatabase, [this._alias]); + static const VerificationMeta _idMeta = const VerificationMeta('id'); + @override + late final GeneratedColumn id = GeneratedColumn( + 'id', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + static const VerificationMeta _nameMeta = const VerificationMeta('name'); + @override + late final GeneratedColumn name = GeneratedColumn( + 'name', + aliasedName, + false, + type: DriftSqlType.string, + requiredDuringInsert: true, + ); + static const VerificationMeta _createdAtMeta = const VerificationMeta( + 'createdAt', + ); + @override + late final GeneratedColumn createdAt = GeneratedColumn( + 'created_at', + aliasedName, + false, + type: DriftSqlType.dateTime, + requiredDuringInsert: true, + ); + @override + List get $columns => [id, name, createdAt]; + @override + String get aliasedName => _alias ?? actualTableName; + @override + String get actualTableName => $name; + static const String $name = 'team_table'; + @override + VerificationContext validateIntegrity( + Insertable instance, { + bool isInserting = false, + }) { + final context = VerificationContext(); + final data = instance.toColumns(true); + if (data.containsKey('id')) { + context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta)); + } else if (isInserting) { + context.missing(_idMeta); + } + if (data.containsKey('name')) { + context.handle( + _nameMeta, + name.isAcceptableOrUnknown(data['name']!, _nameMeta), + ); + } else if (isInserting) { + context.missing(_nameMeta); + } + if (data.containsKey('created_at')) { + context.handle( + _createdAtMeta, + createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta), + ); + } else if (isInserting) { + context.missing(_createdAtMeta); + } + return context; + } + + @override + Set get $primaryKey => {id}; + @override + TeamTableData map(Map data, {String? tablePrefix}) { + final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : ''; + return TeamTableData( + id: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}id'], + )!, + name: attachedDatabase.typeMapping.read( + DriftSqlType.string, + data['${effectivePrefix}name'], + )!, + createdAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}created_at'], + )!, + ); + } + + @override + $TeamTableTable createAlias(String alias) { + return $TeamTableTable(attachedDatabase, alias); + } +} + +class TeamTableData extends DataClass implements Insertable { + final String id; + final String name; + final DateTime createdAt; + const TeamTableData({ + required this.id, + required this.name, + required this.createdAt, + }); + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + map['id'] = Variable(id); + map['name'] = Variable(name); + map['created_at'] = Variable(createdAt); + return map; + } + + TeamTableCompanion toCompanion(bool nullToAbsent) { + return TeamTableCompanion( + id: Value(id), + name: Value(name), + createdAt: Value(createdAt), + ); + } + + factory TeamTableData.fromJson( + Map json, { + ValueSerializer? serializer, + }) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return TeamTableData( + id: serializer.fromJson(json['id']), + name: serializer.fromJson(json['name']), + createdAt: serializer.fromJson(json['createdAt']), + ); + } + @override + Map toJson({ValueSerializer? serializer}) { + serializer ??= driftRuntimeOptions.defaultSerializer; + return { + 'id': serializer.toJson(id), + 'name': serializer.toJson(name), + 'createdAt': serializer.toJson(createdAt), + }; + } + + TeamTableData copyWith({String? id, String? name, DateTime? createdAt}) => + TeamTableData( + id: id ?? this.id, + name: name ?? this.name, + createdAt: createdAt ?? this.createdAt, + ); + TeamTableData copyWithCompanion(TeamTableCompanion data) { + return TeamTableData( + id: data.id.present ? data.id.value : this.id, + name: data.name.present ? data.name.value : this.name, + createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + ); + } + + @override + String toString() { + return (StringBuffer('TeamTableData(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('createdAt: $createdAt') + ..write(')')) + .toString(); + } + + @override + int get hashCode => Object.hash(id, name, createdAt); + @override + bool operator ==(Object other) => + identical(this, other) || + (other is TeamTableData && + other.id == this.id && + other.name == this.name && + other.createdAt == this.createdAt); +} + +class TeamTableCompanion extends UpdateCompanion { + final Value id; + final Value name; + final Value createdAt; + final Value rowid; + const TeamTableCompanion({ + this.id = const Value.absent(), + this.name = const Value.absent(), + this.createdAt = const Value.absent(), + this.rowid = const Value.absent(), + }); + TeamTableCompanion.insert({ + required String id, + required String name, + required DateTime createdAt, + this.rowid = const Value.absent(), + }) : id = Value(id), + name = Value(name), + createdAt = Value(createdAt); + static Insertable custom({ + Expression? id, + Expression? name, + Expression? createdAt, + Expression? rowid, + }) { + return RawValuesInsertable({ + if (id != null) 'id': id, + if (name != null) 'name': name, + if (createdAt != null) 'created_at': createdAt, + if (rowid != null) 'rowid': rowid, + }); + } + + TeamTableCompanion copyWith({ + Value? id, + Value? name, + Value? createdAt, + Value? rowid, + }) { + return TeamTableCompanion( + id: id ?? this.id, + name: name ?? this.name, + createdAt: createdAt ?? this.createdAt, + rowid: rowid ?? this.rowid, + ); + } + + @override + Map toColumns(bool nullToAbsent) { + final map = {}; + if (id.present) { + map['id'] = Variable(id.value); + } + if (name.present) { + map['name'] = Variable(name.value); + } + if (createdAt.present) { + map['created_at'] = Variable(createdAt.value); + } + if (rowid.present) { + map['rowid'] = Variable(rowid.value); + } + return map; + } + + @override + String toString() { + return (StringBuffer('TeamTableCompanion(') + ..write('id: $id, ') + ..write('name: $name, ') + ..write('createdAt: $createdAt, ') + ..write('rowid: $rowid') + ..write(')')) + .toString(); + } +} + class $PlayerMatchTableTable extends PlayerMatchTable with TableInfo<$PlayerMatchTableTable, PlayerMatchTableData> { @override @@ -2682,19 +2682,17 @@ abstract class _$AppDatabase extends GeneratedDatabase { late final $PlayerTableTable playerTable = $PlayerTableTable(this); late final $GroupTableTable groupTable = $GroupTableTable(this); late final $GameTableTable gameTable = $GameTableTable(this); - late final $TeamTableTable teamTable = $TeamTableTable(this); late final $MatchTableTable matchTable = $MatchTableTable(this); late final $PlayerGroupTableTable playerGroupTable = $PlayerGroupTableTable( this, ); + late final $TeamTableTable teamTable = $TeamTableTable(this); late final $PlayerMatchTableTable playerMatchTable = $PlayerMatchTableTable( this, ); late final $ScoreTableTable scoreTable = $ScoreTableTable(this); late final PlayerDao playerDao = PlayerDao(this as AppDatabase); late final GroupDao groupDao = GroupDao(this as AppDatabase); - late final GameDao gameDao = GameDao(this as AppDatabase); - late final TeamDao teamDao = TeamDao(this as AppDatabase); late final MatchDao matchDao = MatchDao(this as AppDatabase); late final PlayerGroupDao playerGroupDao = PlayerGroupDao( this as AppDatabase, @@ -2702,7 +2700,9 @@ abstract class _$AppDatabase extends GeneratedDatabase { late final PlayerMatchDao playerMatchDao = PlayerMatchDao( this as AppDatabase, ); + late final GameDao gameDao = GameDao(this as AppDatabase); late final ScoreDao scoreDao = ScoreDao(this as AppDatabase); + late final TeamDao teamDao = TeamDao(this as AppDatabase); @override Iterable> get allTables => allSchemaEntities.whereType>(); @@ -2711,9 +2711,9 @@ abstract class _$AppDatabase extends GeneratedDatabase { playerTable, groupTable, gameTable, - teamTable, matchTable, playerGroupTable, + teamTable, playerMatchTable, scoreTable, ]; @@ -3997,276 +3997,6 @@ typedef $$GameTableTableProcessedTableManager = GameTableData, PrefetchHooks Function({bool matchTableRefs}) >; -typedef $$TeamTableTableCreateCompanionBuilder = - TeamTableCompanion Function({ - required String id, - required String name, - required DateTime createdAt, - Value rowid, - }); -typedef $$TeamTableTableUpdateCompanionBuilder = - TeamTableCompanion Function({ - Value id, - Value name, - Value createdAt, - Value rowid, - }); - -final class $$TeamTableTableReferences - extends BaseReferences<_$AppDatabase, $TeamTableTable, TeamTableData> { - $$TeamTableTableReferences(super.$_db, super.$_table, super.$_typedResult); - - static MultiTypedResultKey<$PlayerMatchTableTable, List> - _playerMatchTableRefsTable(_$AppDatabase db) => MultiTypedResultKey.fromTable( - db.playerMatchTable, - aliasName: $_aliasNameGenerator( - db.teamTable.id, - db.playerMatchTable.teamId, - ), - ); - - $$PlayerMatchTableTableProcessedTableManager get playerMatchTableRefs { - final manager = $$PlayerMatchTableTableTableManager( - $_db, - $_db.playerMatchTable, - ).filter((f) => f.teamId.id.sqlEquals($_itemColumn('id')!)); - - final cache = $_typedResult.readTableOrNull( - _playerMatchTableRefsTable($_db), - ); - return ProcessedTableManager( - manager.$state.copyWith(prefetchedData: cache), - ); - } -} - -class $$TeamTableTableFilterComposer - extends Composer<_$AppDatabase, $TeamTableTable> { - $$TeamTableTableFilterComposer({ - required super.$db, - required super.$table, - super.joinBuilder, - super.$addJoinBuilderToRootComposer, - super.$removeJoinBuilderFromRootComposer, - }); - ColumnFilters get id => $composableBuilder( - column: $table.id, - builder: (column) => ColumnFilters(column), - ); - - ColumnFilters get name => $composableBuilder( - column: $table.name, - builder: (column) => ColumnFilters(column), - ); - - ColumnFilters get createdAt => $composableBuilder( - column: $table.createdAt, - builder: (column) => ColumnFilters(column), - ); - - Expression playerMatchTableRefs( - Expression Function($$PlayerMatchTableTableFilterComposer f) f, - ) { - final $$PlayerMatchTableTableFilterComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.id, - referencedTable: $db.playerMatchTable, - getReferencedColumn: (t) => t.teamId, - builder: - ( - joinBuilder, { - $addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer, - }) => $$PlayerMatchTableTableFilterComposer( - $db: $db, - $table: $db.playerMatchTable, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - ), - ); - return f(composer); - } -} - -class $$TeamTableTableOrderingComposer - extends Composer<_$AppDatabase, $TeamTableTable> { - $$TeamTableTableOrderingComposer({ - required super.$db, - required super.$table, - super.joinBuilder, - super.$addJoinBuilderToRootComposer, - super.$removeJoinBuilderFromRootComposer, - }); - ColumnOrderings get id => $composableBuilder( - column: $table.id, - builder: (column) => ColumnOrderings(column), - ); - - ColumnOrderings get name => $composableBuilder( - column: $table.name, - builder: (column) => ColumnOrderings(column), - ); - - ColumnOrderings get createdAt => $composableBuilder( - column: $table.createdAt, - builder: (column) => ColumnOrderings(column), - ); -} - -class $$TeamTableTableAnnotationComposer - extends Composer<_$AppDatabase, $TeamTableTable> { - $$TeamTableTableAnnotationComposer({ - required super.$db, - required super.$table, - super.joinBuilder, - super.$addJoinBuilderToRootComposer, - super.$removeJoinBuilderFromRootComposer, - }); - GeneratedColumn get id => - $composableBuilder(column: $table.id, builder: (column) => column); - - GeneratedColumn get name => - $composableBuilder(column: $table.name, builder: (column) => column); - - GeneratedColumn get createdAt => - $composableBuilder(column: $table.createdAt, builder: (column) => column); - - Expression playerMatchTableRefs( - Expression Function($$PlayerMatchTableTableAnnotationComposer a) f, - ) { - final $$PlayerMatchTableTableAnnotationComposer composer = $composerBuilder( - composer: this, - getCurrentColumn: (t) => t.id, - referencedTable: $db.playerMatchTable, - getReferencedColumn: (t) => t.teamId, - builder: - ( - joinBuilder, { - $addJoinBuilderToRootComposer, - $removeJoinBuilderFromRootComposer, - }) => $$PlayerMatchTableTableAnnotationComposer( - $db: $db, - $table: $db.playerMatchTable, - $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, - joinBuilder: joinBuilder, - $removeJoinBuilderFromRootComposer: - $removeJoinBuilderFromRootComposer, - ), - ); - return f(composer); - } -} - -class $$TeamTableTableTableManager - extends - RootTableManager< - _$AppDatabase, - $TeamTableTable, - TeamTableData, - $$TeamTableTableFilterComposer, - $$TeamTableTableOrderingComposer, - $$TeamTableTableAnnotationComposer, - $$TeamTableTableCreateCompanionBuilder, - $$TeamTableTableUpdateCompanionBuilder, - (TeamTableData, $$TeamTableTableReferences), - TeamTableData, - PrefetchHooks Function({bool playerMatchTableRefs}) - > { - $$TeamTableTableTableManager(_$AppDatabase db, $TeamTableTable table) - : super( - TableManagerState( - db: db, - table: table, - createFilteringComposer: () => - $$TeamTableTableFilterComposer($db: db, $table: table), - createOrderingComposer: () => - $$TeamTableTableOrderingComposer($db: db, $table: table), - createComputedFieldComposer: () => - $$TeamTableTableAnnotationComposer($db: db, $table: table), - updateCompanionCallback: - ({ - Value id = const Value.absent(), - Value name = const Value.absent(), - Value createdAt = const Value.absent(), - Value rowid = const Value.absent(), - }) => TeamTableCompanion( - id: id, - name: name, - createdAt: createdAt, - rowid: rowid, - ), - createCompanionCallback: - ({ - required String id, - required String name, - required DateTime createdAt, - Value rowid = const Value.absent(), - }) => TeamTableCompanion.insert( - id: id, - name: name, - createdAt: createdAt, - rowid: rowid, - ), - withReferenceMapper: (p0) => p0 - .map( - (e) => ( - e.readTable(table), - $$TeamTableTableReferences(db, table, e), - ), - ) - .toList(), - prefetchHooksCallback: ({playerMatchTableRefs = false}) { - return PrefetchHooks( - db: db, - explicitlyWatchedTables: [ - if (playerMatchTableRefs) db.playerMatchTable, - ], - addJoins: null, - getPrefetchedDataCallback: (items) async { - return [ - if (playerMatchTableRefs) - await $_getPrefetchedData< - TeamTableData, - $TeamTableTable, - PlayerMatchTableData - >( - currentTable: table, - referencedTable: $$TeamTableTableReferences - ._playerMatchTableRefsTable(db), - managerFromTypedResult: (p0) => - $$TeamTableTableReferences( - db, - table, - p0, - ).playerMatchTableRefs, - referencedItemsForCurrentItem: (item, referencedItems) => - referencedItems.where((e) => e.teamId == item.id), - typedResults: items, - ), - ]; - }, - ); - }, - ), - ); -} - -typedef $$TeamTableTableProcessedTableManager = - ProcessedTableManager< - _$AppDatabase, - $TeamTableTable, - TeamTableData, - $$TeamTableTableFilterComposer, - $$TeamTableTableOrderingComposer, - $$TeamTableTableAnnotationComposer, - $$TeamTableTableCreateCompanionBuilder, - $$TeamTableTableUpdateCompanionBuilder, - (TeamTableData, $$TeamTableTableReferences), - TeamTableData, - PrefetchHooks Function({bool playerMatchTableRefs}) - >; typedef $$MatchTableTableCreateCompanionBuilder = MatchTableCompanion Function({ required String id, @@ -5261,6 +4991,276 @@ typedef $$PlayerGroupTableTableProcessedTableManager = PlayerGroupTableData, PrefetchHooks Function({bool playerId, bool groupId}) >; +typedef $$TeamTableTableCreateCompanionBuilder = + TeamTableCompanion Function({ + required String id, + required String name, + required DateTime createdAt, + Value rowid, + }); +typedef $$TeamTableTableUpdateCompanionBuilder = + TeamTableCompanion Function({ + Value id, + Value name, + Value createdAt, + Value rowid, + }); + +final class $$TeamTableTableReferences + extends BaseReferences<_$AppDatabase, $TeamTableTable, TeamTableData> { + $$TeamTableTableReferences(super.$_db, super.$_table, super.$_typedResult); + + static MultiTypedResultKey<$PlayerMatchTableTable, List> + _playerMatchTableRefsTable(_$AppDatabase db) => MultiTypedResultKey.fromTable( + db.playerMatchTable, + aliasName: $_aliasNameGenerator( + db.teamTable.id, + db.playerMatchTable.teamId, + ), + ); + + $$PlayerMatchTableTableProcessedTableManager get playerMatchTableRefs { + final manager = $$PlayerMatchTableTableTableManager( + $_db, + $_db.playerMatchTable, + ).filter((f) => f.teamId.id.sqlEquals($_itemColumn('id')!)); + + final cache = $_typedResult.readTableOrNull( + _playerMatchTableRefsTable($_db), + ); + return ProcessedTableManager( + manager.$state.copyWith(prefetchedData: cache), + ); + } +} + +class $$TeamTableTableFilterComposer + extends Composer<_$AppDatabase, $TeamTableTable> { + $$TeamTableTableFilterComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnFilters get id => $composableBuilder( + column: $table.id, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get name => $composableBuilder( + column: $table.name, + builder: (column) => ColumnFilters(column), + ); + + ColumnFilters get createdAt => $composableBuilder( + column: $table.createdAt, + builder: (column) => ColumnFilters(column), + ); + + Expression playerMatchTableRefs( + Expression Function($$PlayerMatchTableTableFilterComposer f) f, + ) { + final $$PlayerMatchTableTableFilterComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.playerMatchTable, + getReferencedColumn: (t) => t.teamId, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$PlayerMatchTableTableFilterComposer( + $db: $db, + $table: $db.playerMatchTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return f(composer); + } +} + +class $$TeamTableTableOrderingComposer + extends Composer<_$AppDatabase, $TeamTableTable> { + $$TeamTableTableOrderingComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + ColumnOrderings get id => $composableBuilder( + column: $table.id, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get name => $composableBuilder( + column: $table.name, + builder: (column) => ColumnOrderings(column), + ); + + ColumnOrderings get createdAt => $composableBuilder( + column: $table.createdAt, + builder: (column) => ColumnOrderings(column), + ); +} + +class $$TeamTableTableAnnotationComposer + extends Composer<_$AppDatabase, $TeamTableTable> { + $$TeamTableTableAnnotationComposer({ + required super.$db, + required super.$table, + super.joinBuilder, + super.$addJoinBuilderToRootComposer, + super.$removeJoinBuilderFromRootComposer, + }); + GeneratedColumn get id => + $composableBuilder(column: $table.id, builder: (column) => column); + + GeneratedColumn get name => + $composableBuilder(column: $table.name, builder: (column) => column); + + GeneratedColumn get createdAt => + $composableBuilder(column: $table.createdAt, builder: (column) => column); + + Expression playerMatchTableRefs( + Expression Function($$PlayerMatchTableTableAnnotationComposer a) f, + ) { + final $$PlayerMatchTableTableAnnotationComposer composer = $composerBuilder( + composer: this, + getCurrentColumn: (t) => t.id, + referencedTable: $db.playerMatchTable, + getReferencedColumn: (t) => t.teamId, + builder: + ( + joinBuilder, { + $addJoinBuilderToRootComposer, + $removeJoinBuilderFromRootComposer, + }) => $$PlayerMatchTableTableAnnotationComposer( + $db: $db, + $table: $db.playerMatchTable, + $addJoinBuilderToRootComposer: $addJoinBuilderToRootComposer, + joinBuilder: joinBuilder, + $removeJoinBuilderFromRootComposer: + $removeJoinBuilderFromRootComposer, + ), + ); + return f(composer); + } +} + +class $$TeamTableTableTableManager + extends + RootTableManager< + _$AppDatabase, + $TeamTableTable, + TeamTableData, + $$TeamTableTableFilterComposer, + $$TeamTableTableOrderingComposer, + $$TeamTableTableAnnotationComposer, + $$TeamTableTableCreateCompanionBuilder, + $$TeamTableTableUpdateCompanionBuilder, + (TeamTableData, $$TeamTableTableReferences), + TeamTableData, + PrefetchHooks Function({bool playerMatchTableRefs}) + > { + $$TeamTableTableTableManager(_$AppDatabase db, $TeamTableTable table) + : super( + TableManagerState( + db: db, + table: table, + createFilteringComposer: () => + $$TeamTableTableFilterComposer($db: db, $table: table), + createOrderingComposer: () => + $$TeamTableTableOrderingComposer($db: db, $table: table), + createComputedFieldComposer: () => + $$TeamTableTableAnnotationComposer($db: db, $table: table), + updateCompanionCallback: + ({ + Value id = const Value.absent(), + Value name = const Value.absent(), + Value createdAt = const Value.absent(), + Value rowid = const Value.absent(), + }) => TeamTableCompanion( + id: id, + name: name, + createdAt: createdAt, + rowid: rowid, + ), + createCompanionCallback: + ({ + required String id, + required String name, + required DateTime createdAt, + Value rowid = const Value.absent(), + }) => TeamTableCompanion.insert( + id: id, + name: name, + createdAt: createdAt, + rowid: rowid, + ), + withReferenceMapper: (p0) => p0 + .map( + (e) => ( + e.readTable(table), + $$TeamTableTableReferences(db, table, e), + ), + ) + .toList(), + prefetchHooksCallback: ({playerMatchTableRefs = false}) { + return PrefetchHooks( + db: db, + explicitlyWatchedTables: [ + if (playerMatchTableRefs) db.playerMatchTable, + ], + addJoins: null, + getPrefetchedDataCallback: (items) async { + return [ + if (playerMatchTableRefs) + await $_getPrefetchedData< + TeamTableData, + $TeamTableTable, + PlayerMatchTableData + >( + currentTable: table, + referencedTable: $$TeamTableTableReferences + ._playerMatchTableRefsTable(db), + managerFromTypedResult: (p0) => + $$TeamTableTableReferences( + db, + table, + p0, + ).playerMatchTableRefs, + referencedItemsForCurrentItem: (item, referencedItems) => + referencedItems.where((e) => e.teamId == item.id), + typedResults: items, + ), + ]; + }, + ); + }, + ), + ); +} + +typedef $$TeamTableTableProcessedTableManager = + ProcessedTableManager< + _$AppDatabase, + $TeamTableTable, + TeamTableData, + $$TeamTableTableFilterComposer, + $$TeamTableTableOrderingComposer, + $$TeamTableTableAnnotationComposer, + $$TeamTableTableCreateCompanionBuilder, + $$TeamTableTableUpdateCompanionBuilder, + (TeamTableData, $$TeamTableTableReferences), + TeamTableData, + PrefetchHooks Function({bool playerMatchTableRefs}) + >; typedef $$PlayerMatchTableTableCreateCompanionBuilder = PlayerMatchTableCompanion Function({ required String playerId, @@ -6174,12 +6174,12 @@ class $AppDatabaseManager { $$GroupTableTableTableManager(_db, _db.groupTable); $$GameTableTableTableManager get gameTable => $$GameTableTableTableManager(_db, _db.gameTable); - $$TeamTableTableTableManager get teamTable => - $$TeamTableTableTableManager(_db, _db.teamTable); $$MatchTableTableTableManager get matchTable => $$MatchTableTableTableManager(_db, _db.matchTable); $$PlayerGroupTableTableTableManager get playerGroupTable => $$PlayerGroupTableTableTableManager(_db, _db.playerGroupTable); + $$TeamTableTableTableManager get teamTable => + $$TeamTableTableTableManager(_db, _db.teamTable); $$PlayerMatchTableTableTableManager get playerMatchTable => $$PlayerMatchTableTableTableManager(_db, _db.playerMatchTable); $$ScoreTableTableTableManager get scoreTable => diff --git a/lib/data/db/tables/match_table.dart b/lib/data/db/tables/match_table.dart index 5deb5c5..0dd0eed 100644 --- a/lib/data/db/tables/match_table.dart +++ b/lib/data/db/tables/match_table.dart @@ -1,6 +1,6 @@ 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'; +import 'package:tallee/data/db/tables/game_table.dart'; +import 'package:tallee/data/db/tables/group_table.dart'; class MatchTable extends Table { TextColumn get id => text()(); diff --git a/lib/data/db/tables/player_match_table.dart b/lib/data/db/tables/player_match_table.dart index 08eb16c..3ff55ea 100644 --- a/lib/data/db/tables/player_match_table.dart +++ b/lib/data/db/tables/player_match_table.dart @@ -1,6 +1,7 @@ import 'package:drift/drift.dart'; import 'package:tallee/data/db/tables/match_table.dart'; import 'package:tallee/data/db/tables/player_table.dart'; +import 'package:tallee/data/db/tables/team_table.dart'; class PlayerMatchTable extends Table { TextColumn get playerId => diff --git a/lib/data/db/tables/score_table.dart b/lib/data/db/tables/score_table.dart index 93542c3..a7bf122 100644 --- a/lib/data/db/tables/score_table.dart +++ b/lib/data/db/tables/score_table.dart @@ -1,6 +1,6 @@ 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'; +import 'package:tallee/data/db/tables/match_table.dart'; +import 'package:tallee/data/db/tables/player_table.dart'; class ScoreTable extends Table { TextColumn get playerId => diff --git a/lib/data/dto/game.dart b/lib/data/dto/game.dart index 4081f4e..b463a82 100644 --- a/lib/data/dto/game.dart +++ b/lib/data/dto/game.dart @@ -1,6 +1,6 @@ import 'package:clock/clock.dart'; import 'package:uuid/uuid.dart'; -import 'package:game_tracker/core/enums.dart'; +import 'package:tallee/core/enums.dart'; class Game { final String id; diff --git a/lib/data/dto/match.dart b/lib/data/dto/match.dart index 81a3771..20852a3 100644 --- a/lib/data/dto/match.dart +++ b/lib/data/dto/match.dart @@ -1,4 +1,6 @@ import 'package:clock/clock.dart'; +import 'package:tallee/core/enums.dart'; +import 'package:tallee/data/dto/game.dart'; import 'package:tallee/data/dto/group.dart'; import 'package:tallee/data/dto/player.dart'; import 'package:uuid/uuid.dart'; diff --git a/lib/data/dto/team.dart b/lib/data/dto/team.dart index 46eb5ca..56036b2 100644 --- a/lib/data/dto/team.dart +++ b/lib/data/dto/team.dart @@ -1,5 +1,5 @@ import 'package:clock/clock.dart'; -import 'package:game_tracker/data/dto/player.dart'; +import 'package:tallee/data/dto/player.dart'; import 'package:uuid/uuid.dart'; class Team { diff --git a/lib/main.dart b/lib/main.dart index 0002531..59384ac 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -29,9 +29,7 @@ class GameTracker extends StatelessWidget { return supportedLocale; } } - return supportedLocales.firstWhere( - (locale) => locale.languageCode == 'en', - ); + return supportedLocales.firstWhere((locale) => locale.languageCode == 'en'); }, debugShowCheckedModeBanner: false, onGenerateTitle: (context) => AppLocalizations.of(context).app_name, diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index 6753ab6..f8c39f8 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -2,7 +2,9 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; import 'package:tallee/core/adaptive_page_route.dart'; import 'package:tallee/core/constants.dart'; +import 'package:tallee/core/enums.dart'; import 'package:tallee/data/db/database.dart'; +import 'package:tallee/data/dto/game.dart'; import 'package:tallee/data/dto/group.dart'; import 'package:tallee/data/dto/match.dart'; import 'package:tallee/data/dto/player.dart'; @@ -102,9 +104,7 @@ class _HomeViewState extends State { if (recentMatches.isNotEmpty) for (Match match in recentMatches) Padding( - padding: const EdgeInsets.symmetric( - vertical: 6.0, - ), + padding: const EdgeInsets.symmetric(vertical: 6.0), child: MatchTile( compact: true, width: constraints.maxWidth * 0.9, @@ -113,8 +113,7 @@ class _HomeViewState extends State { await Navigator.of(context).push( adaptivePageRoute( fullscreenDialog: true, - builder: (context) => - MatchResultView(match: match), + builder: (context) => MatchResultView(match: match), ), ); await updatedWinnerInRecentMatches(match.id); @@ -122,10 +121,7 @@ class _HomeViewState extends State { ), ) else - Center( - heightFactor: 5, - child: Text(loc.no_recent_matches_available), - ), + Center(heightFactor: 5, child: Text(loc.no_recent_matches_available)), ], ), ), @@ -141,40 +137,22 @@ class _HomeViewState extends State { Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - QuickCreateButton( - text: 'Category 1', - onPressed: () {}, - ), - QuickCreateButton( - text: 'Category 2', - onPressed: () {}, - ), + QuickCreateButton(text: 'Category 1', onPressed: () {}), + QuickCreateButton(text: 'Category 2', onPressed: () {}), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - QuickCreateButton( - text: 'Category 3', - onPressed: () {}, - ), - QuickCreateButton( - text: 'Category 4', - onPressed: () {}, - ), + QuickCreateButton(text: 'Category 3', onPressed: () {}), + QuickCreateButton(text: 'Category 4', onPressed: () {}), ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ - QuickCreateButton( - text: 'Category 5', - onPressed: () {}, - ), - QuickCreateButton( - text: 'Category 6', - onPressed: () {}, - ), + QuickCreateButton(text: 'Category 5', onPressed: () {}), + QuickCreateButton(text: 'Category 6', onPressed: () {}), ], ), ], @@ -203,11 +181,9 @@ class _HomeViewState extends State { matchCount = results[0] as int; groupCount = results[1] as int; loadedRecentMatches = results[2] as List; - recentMatches = - (loadedRecentMatches - ..sort((a, b) => b.createdAt.compareTo(a.createdAt))) - .take(2) - .toList(); + recentMatches = (loadedRecentMatches..sort((a, b) => b.createdAt.compareTo(a.createdAt))) + .take(2) + .toList(); if (mounted) { setState(() { isLoading = false; diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index 149371f..35bffc4 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -5,6 +5,7 @@ import 'package:tallee/core/constants.dart'; import 'package:tallee/core/custom_theme.dart'; import 'package:tallee/core/enums.dart'; import 'package:tallee/data/db/database.dart'; +import 'package:tallee/data/dto/game.dart'; import 'package:tallee/data/dto/group.dart'; import 'package:tallee/data/dto/match.dart'; import 'package:tallee/data/dto/player.dart'; diff --git a/lib/presentation/views/main_menu/match_view/match_view.dart b/lib/presentation/views/main_menu/match_view/match_view.dart index c340c43..b2ef367 100644 --- a/lib/presentation/views/main_menu/match_view/match_view.dart +++ b/lib/presentation/views/main_menu/match_view/match_view.dart @@ -6,7 +6,9 @@ import 'package:provider/provider.dart'; import 'package:tallee/core/adaptive_page_route.dart'; import 'package:tallee/core/constants.dart'; import 'package:tallee/core/custom_theme.dart'; +import 'package:tallee/core/enums.dart'; import 'package:tallee/data/db/database.dart'; +import 'package:tallee/data/dto/game.dart'; import 'package:tallee/data/dto/group.dart'; import 'package:tallee/data/dto/match.dart'; import 'package:tallee/data/dto/player.dart'; diff --git a/lib/services/data_transfer_service.dart b/lib/services/data_transfer_service.dart index d002cdd..9cb38ce 100644 --- a/lib/services/data_transfer_service.dart +++ b/lib/services/data_transfer_service.dart @@ -8,9 +8,11 @@ import 'package:json_schema/json_schema.dart'; import 'package:provider/provider.dart'; import 'package:tallee/core/enums.dart'; import 'package:tallee/data/db/database.dart'; +import 'package:tallee/data/dto/game.dart'; import 'package:tallee/data/dto/group.dart'; import 'package:tallee/data/dto/match.dart'; import 'package:tallee/data/dto/player.dart'; +import 'package:tallee/data/dto/team.dart'; class DataTransferService { /// Deletes all data from the database. diff --git a/test/db_tests/game_test.dart b/test/db_tests/game_test.dart index f7da1cf..27133ec 100644 --- a/test/db_tests/game_test.dart +++ b/test/db_tests/game_test.dart @@ -1,11 +1,10 @@ import 'package:clock/clock.dart'; -import 'package:drift/drift.dart'; +import 'package:drift/drift.dart' hide isNull; import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:tallee/core/enums.dart'; import 'package:tallee/data/db/database.dart'; -import 'package:tallee/data/dto/group.dart'; -import 'package:tallee/data/dto/match.dart'; -import 'package:tallee/data/dto/player.dart'; +import 'package:tallee/data/dto/game.dart'; void main() { late AppDatabase database; diff --git a/test/db_tests/match_test.dart b/test/db_tests/match_test.dart index 7bcb0a8..2544ccc 100644 --- a/test/db_tests/match_test.dart +++ b/test/db_tests/match_test.dart @@ -2,12 +2,12 @@ import 'package:clock/clock.dart'; import 'package:drift/drift.dart'; import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.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/match.dart'; -import 'package:game_tracker/data/dto/player.dart'; -import 'package:game_tracker/core/enums.dart'; +import 'package:tallee/data/db/database.dart'; +import 'package:tallee/data/dto/game.dart'; +import 'package:tallee/data/dto/group.dart'; +import 'package:tallee/data/dto/match.dart'; +import 'package:tallee/data/dto/player.dart'; +import 'package:tallee/core/enums.dart'; void main() { late AppDatabase database; diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/player_match_test.dart index 43d7e3d..164dbf9 100644 --- a/test/db_tests/player_match_test.dart +++ b/test/db_tests/player_match_test.dart @@ -1,11 +1,14 @@ import 'package:clock/clock.dart'; -import 'package:drift/drift.dart' hide isNotNull; +import 'package:drift/drift.dart' hide isNotNull, isNull; import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.dart'; +import 'package:tallee/core/enums.dart'; import 'package:tallee/data/db/database.dart'; +import 'package:tallee/data/dto/game.dart'; import 'package:tallee/data/dto/group.dart'; import 'package:tallee/data/dto/match.dart'; import 'package:tallee/data/dto/player.dart'; +import 'package:tallee/data/dto/team.dart'; void main() { late AppDatabase database; diff --git a/test/db_tests/score_test.dart b/test/db_tests/score_test.dart index bbd7729..1490dc9 100644 --- a/test/db_tests/score_test.dart +++ b/test/db_tests/score_test.dart @@ -2,11 +2,11 @@ import 'package:clock/clock.dart'; import 'package:drift/drift.dart' hide isNull, isNotNull; import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.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/core/enums.dart'; +import 'package:tallee/data/db/database.dart'; +import 'package:tallee/data/dto/game.dart'; +import 'package:tallee/data/dto/match.dart'; +import 'package:tallee/data/dto/player.dart'; +import 'package:tallee/core/enums.dart'; void main() { late AppDatabase database; diff --git a/test/db_tests/team_test.dart b/test/db_tests/team_test.dart index 19338cb..8092d02 100644 --- a/test/db_tests/team_test.dart +++ b/test/db_tests/team_test.dart @@ -2,12 +2,12 @@ import 'package:clock/clock.dart'; import 'package:drift/drift.dart'; import 'package:drift/native.dart'; import 'package:flutter_test/flutter_test.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/team.dart'; -import 'package:game_tracker/core/enums.dart'; +import 'package:tallee/data/db/database.dart'; +import 'package:tallee/data/dto/game.dart'; +import 'package:tallee/data/dto/match.dart'; +import 'package:tallee/data/dto/player.dart'; +import 'package:tallee/data/dto/team.dart'; +import 'package:tallee/core/enums.dart'; void main() { late AppDatabase database; From 2a3ea32193734d3771ae2c901c1d424784c4e80d Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sun, 1 Feb 2026 17:31:40 +0100 Subject: [PATCH 70/87] change how optional parameters are defined --- assets/schema.json | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/assets/schema.json b/assets/schema.json index a00cd6e..252fb24 100644 --- a/assets/schema.json +++ b/assets/schema.json @@ -146,10 +146,7 @@ "type": "string" }, "groupId": { - "anyOf": [ - {"type": "string"}, - {"type": "null"} - ] + "type": ["string", "null"] }, "playerIds": { "type": "array", From 415cae18cd005f3c912c5a1e632ab80df38166b9 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sun, 1 Feb 2026 17:55:42 +0100 Subject: [PATCH 71/87] added endedAt to matches --- assets/schema.json | 3 + lib/data/dao/match_dao.dart | 18 ++++++ lib/data/db/database.g.dart | 74 ++++++++++++++++++++++++- lib/data/db/tables/match_table.dart | 1 + lib/data/dto/match.dart | 6 +- lib/services/data_transfer_service.dart | 3 + 6 files changed, 101 insertions(+), 4 deletions(-) diff --git a/assets/schema.json b/assets/schema.json index 252fb24..8021012 100644 --- a/assets/schema.json +++ b/assets/schema.json @@ -142,6 +142,9 @@ "createdAt": { "type": "string" }, + "endedAt": { + "type": ["string", "null"] + }, "gameId": { "type": "string" }, diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index 201fc52..3f5a7a1 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -38,6 +38,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { players: players, notes: row.notes ?? '', createdAt: row.createdAt, + endedAt: row.endedAt, ); }), ); @@ -68,6 +69,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { players: players, notes: result.notes ?? '', createdAt: result.createdAt, + endedAt: result.endedAt, ); } @@ -84,6 +86,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { name: Value(match.name), notes: Value(match.notes), createdAt: match.createdAt, + endedAt: Value(match.endedAt), ), mode: InsertMode.insertOrReplace, ); @@ -166,6 +169,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { name: Value(match.name), notes: Value(match.notes), createdAt: match.createdAt, + endedAt: Value(match.endedAt), ), ) .toList(), @@ -346,6 +350,20 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { return rowsAffected > 0; } + /// Updates the endedAt timestamp of the match with the given [matchId]. + /// Pass null to remove the ended time (mark match as ongoing). + /// Returns `true` if more than 0 rows were affected, otherwise `false`. + Future updateMatchEndedAt({ + required String matchId, + required DateTime? endedAt, + }) async { + final query = update(matchTable)..where((g) => g.id.equals(matchId)); + final rowsAffected = await query.write( + MatchTableCompanion(endedAt: Value(endedAt)), + ); + return rowsAffected > 0; + } + // ============================================================ // TEMPORARY: Winner methods - these are stubs and do not persist data // TODO: Implement proper winner handling diff --git a/lib/data/db/database.g.dart b/lib/data/db/database.g.dart index a11c224..fe14e93 100644 --- a/lib/data/db/database.g.dart +++ b/lib/data/db/database.g.dart @@ -1155,6 +1155,17 @@ class $MatchTableTable extends MatchTable type: DriftSqlType.dateTime, requiredDuringInsert: true, ); + static const VerificationMeta _endedAtMeta = const VerificationMeta( + 'endedAt', + ); + @override + late final GeneratedColumn endedAt = GeneratedColumn( + 'ended_at', + aliasedName, + true, + type: DriftSqlType.dateTime, + requiredDuringInsert: false, + ); @override List get $columns => [ id, @@ -1163,6 +1174,7 @@ class $MatchTableTable extends MatchTable name, notes, createdAt, + endedAt, ]; @override String get aliasedName => _alias ?? actualTableName; @@ -1215,6 +1227,12 @@ class $MatchTableTable extends MatchTable } else if (isInserting) { context.missing(_createdAtMeta); } + if (data.containsKey('ended_at')) { + context.handle( + _endedAtMeta, + endedAt.isAcceptableOrUnknown(data['ended_at']!, _endedAtMeta), + ); + } return context; } @@ -1248,6 +1266,10 @@ class $MatchTableTable extends MatchTable DriftSqlType.dateTime, data['${effectivePrefix}created_at'], )!, + endedAt: attachedDatabase.typeMapping.read( + DriftSqlType.dateTime, + data['${effectivePrefix}ended_at'], + ), ); } @@ -1264,6 +1286,7 @@ class MatchTableData extends DataClass implements Insertable { final String? name; final String? notes; final DateTime createdAt; + final DateTime? endedAt; const MatchTableData({ required this.id, required this.gameId, @@ -1271,6 +1294,7 @@ class MatchTableData extends DataClass implements Insertable { this.name, this.notes, required this.createdAt, + this.endedAt, }); @override Map toColumns(bool nullToAbsent) { @@ -1287,6 +1311,9 @@ class MatchTableData extends DataClass implements Insertable { map['notes'] = Variable(notes); } map['created_at'] = Variable(createdAt); + if (!nullToAbsent || endedAt != null) { + map['ended_at'] = Variable(endedAt); + } return map; } @@ -1302,6 +1329,9 @@ class MatchTableData extends DataClass implements Insertable { ? const Value.absent() : Value(notes), createdAt: Value(createdAt), + endedAt: endedAt == null && nullToAbsent + ? const Value.absent() + : Value(endedAt), ); } @@ -1317,6 +1347,7 @@ class MatchTableData extends DataClass implements Insertable { name: serializer.fromJson(json['name']), notes: serializer.fromJson(json['notes']), createdAt: serializer.fromJson(json['createdAt']), + endedAt: serializer.fromJson(json['endedAt']), ); } @override @@ -1329,6 +1360,7 @@ class MatchTableData extends DataClass implements Insertable { 'name': serializer.toJson(name), 'notes': serializer.toJson(notes), 'createdAt': serializer.toJson(createdAt), + 'endedAt': serializer.toJson(endedAt), }; } @@ -1339,6 +1371,7 @@ class MatchTableData extends DataClass implements Insertable { Value name = const Value.absent(), Value notes = const Value.absent(), DateTime? createdAt, + Value endedAt = const Value.absent(), }) => MatchTableData( id: id ?? this.id, gameId: gameId ?? this.gameId, @@ -1346,6 +1379,7 @@ class MatchTableData extends DataClass implements Insertable { name: name.present ? name.value : this.name, notes: notes.present ? notes.value : this.notes, createdAt: createdAt ?? this.createdAt, + endedAt: endedAt.present ? endedAt.value : this.endedAt, ); MatchTableData copyWithCompanion(MatchTableCompanion data) { return MatchTableData( @@ -1355,6 +1389,7 @@ class MatchTableData extends DataClass implements Insertable { name: data.name.present ? data.name.value : this.name, notes: data.notes.present ? data.notes.value : this.notes, createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, + endedAt: data.endedAt.present ? data.endedAt.value : this.endedAt, ); } @@ -1366,13 +1401,15 @@ class MatchTableData extends DataClass implements Insertable { ..write('groupId: $groupId, ') ..write('name: $name, ') ..write('notes: $notes, ') - ..write('createdAt: $createdAt') + ..write('createdAt: $createdAt, ') + ..write('endedAt: $endedAt') ..write(')')) .toString(); } @override - int get hashCode => Object.hash(id, gameId, groupId, name, notes, createdAt); + int get hashCode => + Object.hash(id, gameId, groupId, name, notes, createdAt, endedAt); @override bool operator ==(Object other) => identical(this, other) || @@ -1382,7 +1419,8 @@ class MatchTableData extends DataClass implements Insertable { other.groupId == this.groupId && other.name == this.name && other.notes == this.notes && - other.createdAt == this.createdAt); + other.createdAt == this.createdAt && + other.endedAt == this.endedAt); } class MatchTableCompanion extends UpdateCompanion { @@ -1392,6 +1430,7 @@ class MatchTableCompanion extends UpdateCompanion { final Value name; final Value notes; final Value createdAt; + final Value endedAt; final Value rowid; const MatchTableCompanion({ this.id = const Value.absent(), @@ -1400,6 +1439,7 @@ class MatchTableCompanion extends UpdateCompanion { this.name = const Value.absent(), this.notes = const Value.absent(), this.createdAt = const Value.absent(), + this.endedAt = const Value.absent(), this.rowid = const Value.absent(), }); MatchTableCompanion.insert({ @@ -1409,6 +1449,7 @@ class MatchTableCompanion extends UpdateCompanion { this.name = const Value.absent(), this.notes = const Value.absent(), required DateTime createdAt, + this.endedAt = const Value.absent(), this.rowid = const Value.absent(), }) : id = Value(id), gameId = Value(gameId), @@ -1420,6 +1461,7 @@ class MatchTableCompanion extends UpdateCompanion { Expression? name, Expression? notes, Expression? createdAt, + Expression? endedAt, Expression? rowid, }) { return RawValuesInsertable({ @@ -1429,6 +1471,7 @@ class MatchTableCompanion extends UpdateCompanion { if (name != null) 'name': name, if (notes != null) 'notes': notes, if (createdAt != null) 'created_at': createdAt, + if (endedAt != null) 'ended_at': endedAt, if (rowid != null) 'rowid': rowid, }); } @@ -1440,6 +1483,7 @@ class MatchTableCompanion extends UpdateCompanion { Value? name, Value? notes, Value? createdAt, + Value? endedAt, Value? rowid, }) { return MatchTableCompanion( @@ -1449,6 +1493,7 @@ class MatchTableCompanion extends UpdateCompanion { name: name ?? this.name, notes: notes ?? this.notes, createdAt: createdAt ?? this.createdAt, + endedAt: endedAt ?? this.endedAt, rowid: rowid ?? this.rowid, ); } @@ -1474,6 +1519,9 @@ class MatchTableCompanion extends UpdateCompanion { if (createdAt.present) { map['created_at'] = Variable(createdAt.value); } + if (endedAt.present) { + map['ended_at'] = Variable(endedAt.value); + } if (rowid.present) { map['rowid'] = Variable(rowid.value); } @@ -1489,6 +1537,7 @@ class MatchTableCompanion extends UpdateCompanion { ..write('name: $name, ') ..write('notes: $notes, ') ..write('createdAt: $createdAt, ') + ..write('endedAt: $endedAt, ') ..write('rowid: $rowid') ..write(')')) .toString(); @@ -4005,6 +4054,7 @@ typedef $$MatchTableTableCreateCompanionBuilder = Value name, Value notes, required DateTime createdAt, + Value endedAt, Value rowid, }); typedef $$MatchTableTableUpdateCompanionBuilder = @@ -4015,6 +4065,7 @@ typedef $$MatchTableTableUpdateCompanionBuilder = Value name, Value notes, Value createdAt, + Value endedAt, Value rowid, }); @@ -4129,6 +4180,11 @@ class $$MatchTableTableFilterComposer builder: (column) => ColumnFilters(column), ); + ColumnFilters get endedAt => $composableBuilder( + column: $table.endedAt, + builder: (column) => ColumnFilters(column), + ); + $$GameTableTableFilterComposer get gameId { final $$GameTableTableFilterComposer composer = $composerBuilder( composer: this, @@ -4255,6 +4311,11 @@ class $$MatchTableTableOrderingComposer builder: (column) => ColumnOrderings(column), ); + ColumnOrderings get endedAt => $composableBuilder( + column: $table.endedAt, + builder: (column) => ColumnOrderings(column), + ); + $$GameTableTableOrderingComposer get gameId { final $$GameTableTableOrderingComposer composer = $composerBuilder( composer: this, @@ -4323,6 +4384,9 @@ class $$MatchTableTableAnnotationComposer GeneratedColumn get createdAt => $composableBuilder(column: $table.createdAt, builder: (column) => column); + GeneratedColumn get endedAt => + $composableBuilder(column: $table.endedAt, builder: (column) => column); + $$GameTableTableAnnotationComposer get gameId { final $$GameTableTableAnnotationComposer composer = $composerBuilder( composer: this, @@ -4459,6 +4523,7 @@ class $$MatchTableTableTableManager Value name = const Value.absent(), Value notes = const Value.absent(), Value createdAt = const Value.absent(), + Value endedAt = const Value.absent(), Value rowid = const Value.absent(), }) => MatchTableCompanion( id: id, @@ -4467,6 +4532,7 @@ class $$MatchTableTableTableManager name: name, notes: notes, createdAt: createdAt, + endedAt: endedAt, rowid: rowid, ), createCompanionCallback: @@ -4477,6 +4543,7 @@ class $$MatchTableTableTableManager Value name = const Value.absent(), Value notes = const Value.absent(), required DateTime createdAt, + Value endedAt = const Value.absent(), Value rowid = const Value.absent(), }) => MatchTableCompanion.insert( id: id, @@ -4485,6 +4552,7 @@ class $$MatchTableTableTableManager name: name, notes: notes, createdAt: createdAt, + endedAt: endedAt, rowid: rowid, ), withReferenceMapper: (p0) => p0 diff --git a/lib/data/db/tables/match_table.dart b/lib/data/db/tables/match_table.dart index 0dd0eed..83b6897 100644 --- a/lib/data/db/tables/match_table.dart +++ b/lib/data/db/tables/match_table.dart @@ -11,6 +11,7 @@ class MatchTable extends Table { TextColumn get name => text().nullable()(); TextColumn get notes => text().nullable()(); DateTimeColumn get createdAt => dateTime()(); + DateTimeColumn get endedAt => dateTime().nullable()(); @override Set> get primaryKey => {id}; diff --git a/lib/data/dto/match.dart b/lib/data/dto/match.dart index 20852a3..4f919b4 100644 --- a/lib/data/dto/match.dart +++ b/lib/data/dto/match.dart @@ -8,6 +8,7 @@ import 'package:uuid/uuid.dart'; class Match { final String id; final DateTime createdAt; + final DateTime? endedAt; final String name; final Game game; final Group? group; @@ -18,6 +19,7 @@ class Match { Match({ String? id, DateTime? createdAt, + this.endedAt, required this.name, required this.game, this.group, @@ -29,7 +31,7 @@ class Match { @override String toString() { - return 'Match{id: $id, name: $name, game: $game, group: $group, players: $players, notes: $notes}'; + return 'Match{id: $id, name: $name, game: $game, group: $group, players: $players, notes: $notes, endedAt: $endedAt}'; } /// Creates a Match instance from a JSON object (ID references format). @@ -37,6 +39,7 @@ class Match { Match.fromJson(Map json) : id = json['id'], createdAt = DateTime.parse(json['createdAt']), + endedAt = json['endedAt'] != null ? DateTime.parse(json['endedAt']) : null, name = json['name'], game = Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''), // Populated during import via DataTransferService group = null, // Populated during import via DataTransferService @@ -47,6 +50,7 @@ class Match { Map toJson() => { 'id': id, 'createdAt': createdAt.toIso8601String(), + 'endedAt': endedAt?.toIso8601String(), 'name': name, 'gameId': game.id, 'groupId': group?.id, diff --git a/lib/services/data_transfer_service.dart b/lib/services/data_transfer_service.dart index 9cb38ce..fb69e12 100644 --- a/lib/services/data_transfer_service.dart +++ b/lib/services/data_transfer_service.dart @@ -61,6 +61,7 @@ class DataTransferService { 'id': m.id, 'name': m.name, 'createdAt': m.createdAt.toIso8601String(), + 'endedAt': m.endedAt?.toIso8601String(), 'gameId': m.game.id, 'groupId': m.group?.id, 'playerIds': (m.players ?? []).map((p) => p.id).toList(), @@ -195,6 +196,7 @@ class DataTransferService { final String gameId = map['gameId'] as String; final String? groupId = map['groupId'] as String?; final List playerIds = (map['playerIds'] as List? ?? []).cast(); + final DateTime? endedAt = map['endedAt'] != null ? DateTime.parse(map['endedAt'] as String) : null; final game = gameById[gameId]; final group = (groupId == null) ? null : groupById[groupId]; @@ -210,6 +212,7 @@ class DataTransferService { group: group, players: players.isNotEmpty ? players : null, createdAt: DateTime.parse(map['createdAt'] as String), + endedAt: endedAt, notes: map['notes'] as String? ?? '', ); }).toList(); From ccfea71a35c50aa8cfd8f87a1c6f0e800a05c8b4 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sun, 1 Feb 2026 17:56:24 +0100 Subject: [PATCH 72/87] reduce line length --- lib/data/db/tables/match_table.dart | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/data/db/tables/match_table.dart b/lib/data/db/tables/match_table.dart index 83b6897..9ed27b7 100644 --- a/lib/data/db/tables/match_table.dart +++ b/lib/data/db/tables/match_table.dart @@ -6,8 +6,9 @@ class MatchTable extends Table { TextColumn get id => text()(); TextColumn get gameId => text().references(GameTable, #id, onDelete: KeyAction.cascade)(); + // Nullable if not part of a group TextColumn get groupId => - text().references(GroupTable, #id, onDelete: KeyAction.cascade).nullable()(); // Nullable if not part of a group + text().references(GroupTable, #id, onDelete: KeyAction.cascade).nullable()(); TextColumn get name => text().nullable()(); TextColumn get notes => text().nullable()(); DateTimeColumn get createdAt => dateTime()(); From dbef735a821564485989f16a0101534e9ec08ad3 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sun, 1 Feb 2026 18:13:03 +0100 Subject: [PATCH 73/87] add color enum --- lib/core/enums.dart | 11 ++++++++ lib/data/dao/game_dao.dart | 12 ++++----- lib/data/dao/match_dao.dart | 2 +- lib/data/dto/game.dart | 6 ++--- lib/data/dto/match.dart | 2 +- .../views/main_menu/home_view.dart | 2 +- .../create_match/create_match_view.dart | 4 +-- .../main_menu/match_view/match_view.dart | 2 +- lib/services/data_transfer_service.dart | 2 +- test/db_tests/game_test.dart | 26 +++++++++---------- test/db_tests/match_test.dart | 2 +- test/db_tests/player_match_test.dart | 2 +- test/db_tests/score_test.dart | 2 +- test/db_tests/team_test.dart | 4 +-- 14 files changed, 45 insertions(+), 34 deletions(-) diff --git a/lib/core/enums.dart b/lib/core/enums.dart index a6bf274..d3e0610 100644 --- a/lib/core/enums.dart +++ b/lib/core/enums.dart @@ -37,6 +37,17 @@ enum ExportResult { success, canceled, unknownException } /// - [Ruleset.multipleWinners]: Multiple players can be winners. enum Ruleset { highestScore, lowestScore, singleWinner, singleLoser, multipleWinners } +/// Different colors available for games +/// - [GameColor.red]: Red color +/// - [GameColor.blue]: Blue color +/// - [GameColor.green]: Green color +/// - [GameColor.yellow]: Yellow color +/// - [GameColor.purple]: Purple color +/// - [GameColor.orange]: Orange color +/// - [GameColor.pink]: Pink color +/// - [GameColor.teal]: Teal color +enum GameColor { red, blue, green, yellow, purple, orange, pink, teal } + /// Translates a [Ruleset] enum value to its corresponding localized string. String translateRulesetToString(Ruleset ruleset, BuildContext context) { final loc = AppLocalizations.of(context); diff --git a/lib/data/dao/game_dao.dart b/lib/data/dao/game_dao.dart index b656266..8e658ed 100644 --- a/lib/data/dao/game_dao.dart +++ b/lib/data/dao/game_dao.dart @@ -21,7 +21,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { name: row.name, ruleset: Ruleset.values.firstWhere((e) => e.name == row.ruleset), description: row.description, - color: row.color, + color: GameColor.values.firstWhere((e) => e.name == row.color), icon: row.icon, createdAt: row.createdAt, ), @@ -38,7 +38,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { name: result.name, ruleset: Ruleset.values.firstWhere((e) => e.name == result.ruleset), description: result.description, - color: result.color, + color: GameColor.values.firstWhere((e) => e.name == result.color), icon: result.icon, createdAt: result.createdAt, ); @@ -55,7 +55,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { name: game.name, ruleset: game.ruleset.name, description: game.description, - color: game.color, + color: game.color.name, icon: game.icon, createdAt: game.createdAt, ), @@ -81,7 +81,7 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { name: game.name, ruleset: game.ruleset.name, description: game.description, - color: game.color, + color: game.color.name, icon: game.icon, createdAt: game.createdAt, ), @@ -135,10 +135,10 @@ class GameDao extends DatabaseAccessor with _$GameDaoMixin { } /// Updates the color of the game with the given [gameId]. - Future updateGameColor({required String gameId, required String newColor}) async { + Future updateGameColor({required String gameId, required GameColor newColor}) async { await (update( gameTable, - )..where((g) => g.id.equals(gameId))).write(GameTableCompanion(color: Value(newColor))); + )..where((g) => g.id.equals(gameId))).write(GameTableCompanion(color: Value(newColor.name))); } /// Updates the icon of the game with the given [gameId]. diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index 3f5a7a1..c2e9d72 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -126,7 +126,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { name: game.name, ruleset: game.ruleset.name, description: game.description, - color: game.color, + color: game.color.name, icon: game.icon, createdAt: game.createdAt, ), diff --git a/lib/data/dto/game.dart b/lib/data/dto/game.dart index b463a82..437d98e 100644 --- a/lib/data/dto/game.dart +++ b/lib/data/dto/game.dart @@ -8,7 +8,7 @@ class Game { final String name; final Ruleset ruleset; final String description; - final String color; + final GameColor color; final String icon; Game({ @@ -34,7 +34,7 @@ class Game { name = json['name'], ruleset = Ruleset.values.firstWhere((e) => e.name == json['ruleset']), description = json['description'], - color = json['color'], + color = GameColor.values.firstWhere((e) => e.name == json['color']), icon = json['icon']; /// Converts the Game instance to a JSON object. @@ -44,7 +44,7 @@ class Game { 'name': name, 'ruleset': ruleset.name, 'description': description, - 'color': color, + 'color': color.name, 'icon': icon, }; } diff --git a/lib/data/dto/match.dart b/lib/data/dto/match.dart index 4f919b4..559914e 100644 --- a/lib/data/dto/match.dart +++ b/lib/data/dto/match.dart @@ -41,7 +41,7 @@ class Match { createdAt = DateTime.parse(json['createdAt']), endedAt = json['endedAt'] != null ? DateTime.parse(json['endedAt']) : null, name = json['name'], - game = Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''), // Populated during import via DataTransferService + game = Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: GameColor.blue, icon: ''), // Populated during import via DataTransferService group = null, // Populated during import via DataTransferService players = [], // Populated during import via DataTransferService notes = json['notes'] ?? ''; diff --git a/lib/presentation/views/main_menu/home_view.dart b/lib/presentation/views/main_menu/home_view.dart index f8c39f8..a7f5cfa 100644 --- a/lib/presentation/views/main_menu/home_view.dart +++ b/lib/presentation/views/main_menu/home_view.dart @@ -42,7 +42,7 @@ class _HomeViewState extends State { 2, Match( name: 'Skeleton Match', - game: Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''), + game: Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: GameColor.blue, icon: ''), group: Group( name: 'Skeleton Group', description: '', diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index 35bffc4..163ebd2 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -202,7 +202,7 @@ class _CreateMatchViewState extends State { name: selectedGame.$1, description: selectedGame.$2, ruleset: selectedGame.$3, - color: '0xFF000000', + color: GameColor.blue, icon: '', ); } else { @@ -212,7 +212,7 @@ class _CreateMatchViewState extends State { name: selectedGame.$1, description: selectedGame.$2, ruleset: selectedGame.$3, - color: '0xFF000000', + color: GameColor.blue, icon: '', ); } diff --git a/lib/presentation/views/main_menu/match_view/match_view.dart b/lib/presentation/views/main_menu/match_view/match_view.dart index b2ef367..1f50342 100644 --- a/lib/presentation/views/main_menu/match_view/match_view.dart +++ b/lib/presentation/views/main_menu/match_view/match_view.dart @@ -38,7 +38,7 @@ class _MatchViewState extends State { 4, Match( name: 'Skeleton match name', - game: Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''), + game: Game(name: '', ruleset: Ruleset.singleWinner, description: '', color: GameColor.blue, icon: ''), group: Group( name: 'Group name', description: '', diff --git a/lib/services/data_transfer_service.dart b/lib/services/data_transfer_service.dart index fb69e12..4995c77 100644 --- a/lib/services/data_transfer_service.dart +++ b/lib/services/data_transfer_service.dart @@ -208,7 +208,7 @@ class DataTransferService { return Match( id: map['id'] as String, name: map['name'] as String, - game: game ?? Game(name: 'Unknown', ruleset: Ruleset.singleWinner, description: '', color: '', icon: ''), + game: game ?? Game(name: 'Unknown', ruleset: Ruleset.singleWinner, description: '', color: GameColor.blue, icon: ''), group: group, players: players.isNotEmpty ? players : null, createdAt: DateTime.parse(map['createdAt'] as String), diff --git a/test/db_tests/game_test.dart b/test/db_tests/game_test.dart index 27133ec..6038690 100644 --- a/test/db_tests/game_test.dart +++ b/test/db_tests/game_test.dart @@ -27,7 +27,7 @@ void main() { name: 'Chess', ruleset: Ruleset.singleWinner, description: 'A classic strategy game', - color: '0xFF0000FF', + color: GameColor.blue, icon: 'chess_icon', ); testGame2 = Game( @@ -35,7 +35,7 @@ void main() { name: 'Poker', ruleset: Ruleset.multipleWinners, description: 'Card game with multiple winners', - color: '0xFFFF0000', + color: GameColor.red, icon: 'poker_icon', ); testGame3 = Game( @@ -43,7 +43,7 @@ void main() { name: 'Monopoly', ruleset: Ruleset.highestScore, description: 'A board game about real estate', - color: '0xFF000000', + color: GameColor.orange, icon: '', ); }); @@ -134,7 +134,7 @@ void main() { // Verifies that a game with null optional fields can be added and retrieved. test('addGame handles game with null optional fields', () async { - final gameWithNulls = Game(name: 'Simple Game', ruleset: Ruleset.lowestScore, description: 'A simple game', color: '0xFF000000', icon: ''); + final gameWithNulls = Game(name: 'Simple Game', ruleset: Ruleset.lowestScore, description: 'A simple game', color: GameColor.green, icon: ''); final result = await database.gameDao.addGame(game: gameWithNulls); expect(result, true); @@ -143,7 +143,7 @@ void main() { ); expect(fetchedGame.name, 'Simple Game'); expect(fetchedGame.description, 'A simple game'); - expect(fetchedGame.color, '0xFF000000'); + expect(fetchedGame.color, GameColor.green); expect(fetchedGame.icon, isNull); }); @@ -340,20 +340,20 @@ void main() { await database.gameDao.updateGameColor( gameId: testGame1.id, - newColor: '0xFF00FF00', + newColor: GameColor.green, ); final updatedGame = await database.gameDao.getGameById( gameId: testGame1.id, ); - expect(updatedGame.color, '0xFF00FF00'); + expect(updatedGame.color, GameColor.green); }); // Verifies that updateGameColor does nothing when game doesn't exist. test('updateGameColor does nothing for non-existent game', () async { await database.gameDao.updateGameColor( gameId: 'non-existent-id', - newColor: '0xFF00FF00', + newColor: GameColor.green, ); final allGames = await database.gameDao.getAllGames(); @@ -460,7 +460,7 @@ void main() { name: 'Game\'s & "Special" ', ruleset: Ruleset.multipleWinners, description: 'Description with émojis 🎮🎲', - color: '0xFF000000', + color: GameColor.purple, icon: '', ); await database.gameDao.addGame(game: specialGame); @@ -479,7 +479,7 @@ void main() { ruleset: Ruleset.singleWinner, description: '', icon: '', - color: '0xFF000000', + color: GameColor.red, ); await database.gameDao.addGame(game: emptyGame); @@ -499,7 +499,7 @@ void main() { name: longString, description: longString, ruleset: Ruleset.multipleWinners, - color: '0xFF000000', + color: GameColor.yellow, icon: '', ); await database.gameDao.addGame(game: longGame); @@ -522,7 +522,7 @@ void main() { ); await database.gameDao.updateGameColor( gameId: testGame1.id, - newColor: '0xFF123456', + newColor: GameColor.teal, ); await database.gameDao.updateGameDescription( gameId: testGame1.id, @@ -533,7 +533,7 @@ void main() { gameId: testGame1.id, ); expect(updatedGame.name, 'Updated Name'); - expect(updatedGame.color, '0xFF123456'); + expect(updatedGame.color, GameColor.teal); expect(updatedGame.description, 'Updated Description'); expect(updatedGame.ruleset, testGame1.ruleset); expect(updatedGame.icon, testGame1.icon); diff --git a/test/db_tests/match_test.dart b/test/db_tests/match_test.dart index 2544ccc..4935f81 100644 --- a/test/db_tests/match_test.dart +++ b/test/db_tests/match_test.dart @@ -51,7 +51,7 @@ void main() { description: '', members: [testPlayer4, testPlayer5], ); - testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000', icon: ''); + testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: GameColor.blue, icon: ''); testMatch1 = Match( name: 'First Test Match', game: testGame, diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/player_match_test.dart index 164dbf9..ddc36d2 100644 --- a/test/db_tests/player_match_test.dart +++ b/test/db_tests/player_match_test.dart @@ -48,7 +48,7 @@ void main() { description: '', members: [testPlayer1, testPlayer2, testPlayer3], ); - testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000', icon: ''); + testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: GameColor.blue, icon: ''); testMatchOnlyGroup = Match( name: 'Test Match with Group', game: testGame, diff --git a/test/db_tests/score_test.dart b/test/db_tests/score_test.dart index 1490dc9..2ad4671 100644 --- a/test/db_tests/score_test.dart +++ b/test/db_tests/score_test.dart @@ -32,7 +32,7 @@ void main() { testPlayer1 = Player(name: 'Alice', description: ''); testPlayer2 = Player(name: 'Bob', description: ''); testPlayer3 = Player(name: 'Charlie', description: ''); - testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000', icon: ''); + testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: GameColor.blue, icon: ''); testMatch1 = Match( name: 'Test Match 1', game: testGame, diff --git a/test/db_tests/team_test.dart b/test/db_tests/team_test.dart index 8092d02..17ceff9 100644 --- a/test/db_tests/team_test.dart +++ b/test/db_tests/team_test.dart @@ -49,8 +49,8 @@ void main() { name: 'Team Gamma', members: [testPlayer1, testPlayer3], ); - testGame1 = Game(name: 'Game 1', ruleset: Ruleset.singleWinner, description: 'Test game 1', color: '0xFF000000', icon: ''); - testGame2 = Game(name: 'Game 2', ruleset: Ruleset.highestScore, description: 'Test game 2', color: '0xFF000000', icon: ''); + testGame1 = Game(name: 'Game 1', ruleset: Ruleset.singleWinner, description: 'Test game 1', color: GameColor.blue, icon: ''); + testGame2 = Game(name: 'Game 2', ruleset: Ruleset.highestScore, description: 'Test game 2', color: GameColor.red, icon: ''); }); await database.playerDao.addPlayersAsList( From 7aba8554c05bf83e22c8ea0887c49a1ebe8a8d99 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sun, 1 Feb 2026 18:23:58 +0100 Subject: [PATCH 74/87] players cant be null --- lib/data/dao/match_dao.dart | 55 ++++++++----------- lib/data/dto/match.dart | 6 +- .../create_match/create_match_view.dart | 6 +- .../match_view/match_result_view.dart | 8 +-- .../views/main_menu/statistics_view.dart | 14 ++--- .../widgets/tiles/match_tile.dart | 14 ++--- lib/services/data_transfer_service.dart | 4 +- 7 files changed, 46 insertions(+), 61 deletions(-) diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index c2e9d72..063ac32 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -29,7 +29,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { } final players = await db.playerMatchDao.getPlayersOfMatch( matchId: row.id, - ); + ) ?? []; return Match( id: row.id, name: row.name ?? '', @@ -56,10 +56,7 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { group = await db.groupDao.getGroupById(groupId: result.groupId!); } - List? players; - if (await db.playerMatchDao.matchHasPlayers(matchId: matchId)) { - players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId); - } + final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId) ?? []; return Match( id: result.id, @@ -91,13 +88,11 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { mode: InsertMode.insertOrReplace, ); - if (match.players != null) { - for (final p in match.players!) { - await db.playerMatchDao.addPlayerToMatch( - matchId: match.id, - playerId: p.id, - ); - } + for (final p in match.players) { + await db.playerMatchDao.addPlayerToMatch( + matchId: match.id, + playerId: p.id, + ); } }); } @@ -180,10 +175,8 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { // Add all players of the matches in batch (unique) final uniquePlayers = {}; for (final match in matches) { - if (match.players != null) { - for (final p in match.players!) { - uniquePlayers[p.id] = p; - } + for (final p in match.players) { + uniquePlayers[p.id] = p; } // Also include members of groups if (match.group != null) { @@ -215,18 +208,16 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { // 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, - score: 0, - ), - mode: InsertMode.insertOrIgnore, - ); - } + for (final p in match.players) { + b.insert( + db.playerMatchTable, + PlayerMatchTableCompanion.insert( + matchId: match.id, + playerId: p.id, + score: 0, + ), + mode: InsertMode.insertOrIgnore, + ); } } }); @@ -372,15 +363,15 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { /// TEMPORARY: Checks if a match has a winner. /// Currently returns true if the match has any players. Future hasWinner({required String matchId}) async { - final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId); - return players?.isNotEmpty ?? false; + final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId) ?? []; + return players.isNotEmpty; } /// TEMPORARY: Gets the winner of a match. /// Currently returns the first player in the match's player list. Future getWinner({required String matchId}) async { - final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId); - return (players?.isNotEmpty ?? false) ? players!.first : null; + final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId) ?? []; + return players.isNotEmpty ? players.first : null; } /// TEMPORARY: Sets the winner of a match. diff --git a/lib/data/dto/match.dart b/lib/data/dto/match.dart index 559914e..31f45fc 100644 --- a/lib/data/dto/match.dart +++ b/lib/data/dto/match.dart @@ -12,7 +12,7 @@ class Match { final String name; final Game game; final Group? group; - final List? players; + final List players; final String notes; Player? winner; @@ -23,7 +23,7 @@ class Match { required this.name, required this.game, this.group, - this.players, + this.players = const [], required this.notes, this.winner, }) : id = id ?? const Uuid().v4(), @@ -54,7 +54,7 @@ class Match { 'name': name, 'gameId': game.id, 'groupId': group?.id, - 'playerIds': (players ?? []).map((player) => player.id).toList(), + 'playerIds': players.map((player) => player.id).toList(), 'notes': notes, }; } diff --git a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart index 163ebd2..7096702 100644 --- a/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart +++ b/lib/presentation/views/main_menu/match_view/create_match/create_match_view.dart @@ -63,7 +63,7 @@ class _CreateMatchViewState extends State { int selectedGameIndex = -1; /// The currently selected players - List? selectedPlayers; + List selectedPlayers = []; @override void initState() { @@ -178,7 +178,7 @@ class _CreateMatchViewState extends State { Expanded( child: PlayerSelection( key: ValueKey(selectedGroup?.id ?? 'no_group'), - initialSelectedPlayers: selectedPlayers ?? [], + initialSelectedPlayers: selectedPlayers, availablePlayers: filteredPlayerList, onChanged: (value) { setState(() { @@ -259,6 +259,6 @@ class _CreateMatchViewState extends State { /// - Either a group is selected OR at least 2 players are selected bool _enableCreateGameButton() { return (selectedGroup != null || - (selectedPlayers != null && selectedPlayers!.length > 1)); + (selectedPlayers.length > 1)); } } \ No newline at end of file diff --git a/lib/presentation/views/main_menu/match_view/match_result_view.dart b/lib/presentation/views/main_menu/match_view/match_result_view.dart index 75015f0..981a196 100644 --- a/lib/presentation/views/main_menu/match_view/match_result_view.dart +++ b/lib/presentation/views/main_menu/match_view/match_result_view.dart @@ -153,12 +153,10 @@ class _MatchResultViewState extends State { List getAllPlayers(Match match) { List players = []; - if (match.group == null && match.players != null) { - players = [...match.players!]; - } else if (match.group != null && match.players != null) { - players = [...match.players!, ...match.group!.members]; + if (match.group == null) { + players = [...match.players]; } else { - players = [...match.group!.members]; + players = [...match.players, ...match.group!.members]; } players.sort((a, b) => a.name.compareTo(b.name)); diff --git a/lib/presentation/views/main_menu/statistics_view.dart b/lib/presentation/views/main_menu/statistics_view.dart index af3eba6..5b3ff22 100644 --- a/lib/presentation/views/main_menu/statistics_view.dart +++ b/lib/presentation/views/main_menu/statistics_view.dart @@ -202,19 +202,17 @@ class _StatisticsViewState extends State { } } } - if (match.players != null) { - final members = match.players!.map((p) => p.id).toList(); - for (var playerId in members) { - final index = matchCounts.indexWhere((entry) => entry.$1 == playerId); - // -1 means player not found in matchCounts - if (index != -1) { - final current = matchCounts[index].$2; + final members = match.players.map((p) => p.id).toList(); + for (var playerId in members) { + final index = matchCounts.indexWhere((entry) => entry.$1 == playerId); + // -1 means player not found in matchCounts + if (index != -1) { + final current = matchCounts[index].$2; matchCounts[index] = (playerId, current + 1); } else { matchCounts.add((playerId, 1)); } } - } } // Adding all players with zero matches diff --git a/lib/presentation/widgets/tiles/match_tile.dart b/lib/presentation/widgets/tiles/match_tile.dart index ab65e5d..7862000 100644 --- a/lib/presentation/widgets/tiles/match_tile.dart +++ b/lib/presentation/widgets/tiles/match_tile.dart @@ -91,7 +91,7 @@ class _MatchTileState extends State { const SizedBox(width: 6), Expanded( child: Text( - '${group.name}${widget.match.players != null ? ' + ${widget.match.players?.length}' : ''}', + '${group.name} + ${widget.match.players.length}', style: const TextStyle(fontSize: 14, color: Colors.grey), overflow: TextOverflow.ellipsis, ), @@ -106,7 +106,7 @@ class _MatchTileState extends State { const SizedBox(width: 6), Expanded( child: Text( - '${widget.match.players!.length} ${loc.players}', + '${widget.match.players.length} ${loc.players}', style: const TextStyle(fontSize: 14, color: Colors.grey), overflow: TextOverflow.ellipsis, ), @@ -241,12 +241,10 @@ class _MatchTileState extends State { final playerIds = {}; // Add players from game.players - if (widget.match.players != null) { - for (var player in widget.match.players!) { - if (!playerIds.contains(player.id)) { - allPlayers.add(player); - playerIds.add(player.id); - } + for (var player in widget.match.players) { + if (!playerIds.contains(player.id)) { + allPlayers.add(player); + playerIds.add(player.id); } } diff --git a/lib/services/data_transfer_service.dart b/lib/services/data_transfer_service.dart index 4995c77..526a459 100644 --- a/lib/services/data_transfer_service.dart +++ b/lib/services/data_transfer_service.dart @@ -64,7 +64,7 @@ class DataTransferService { 'endedAt': m.endedAt?.toIso8601String(), 'gameId': m.game.id, 'groupId': m.group?.id, - 'playerIds': (m.players ?? []).map((p) => p.id).toList(), + 'playerIds': m.players.map((p) => p.id).toList(), 'notes': m.notes, }) .toList(), @@ -210,7 +210,7 @@ class DataTransferService { name: map['name'] as String, game: game ?? Game(name: 'Unknown', ruleset: Ruleset.singleWinner, description: '', color: GameColor.blue, icon: ''), group: group, - players: players.isNotEmpty ? players : null, + players: players, createdAt: DateTime.parse(map['createdAt'] as String), endedAt: endedAt, notes: map['notes'] as String? ?? '', From 70d617882927abfd5f40f63c60a15f32f9528e8f Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sun, 1 Feb 2026 19:51:57 +0100 Subject: [PATCH 75/87] restructure tests --- test/db_tests/{ => aggregates}/group_test.dart | 0 test/db_tests/{ => aggregates}/match_test.dart | 0 test/db_tests/{ => aggregates}/team_test.dart | 0 test/db_tests/{ => entities}/game_test.dart | 0 test/db_tests/{ => entities}/player_test.dart | 0 test/db_tests/{ => relationships}/player_group_test.dart | 0 test/db_tests/{ => relationships}/player_match_test.dart | 0 test/db_tests/{ => values}/score_test.dart | 0 8 files changed, 0 insertions(+), 0 deletions(-) rename test/db_tests/{ => aggregates}/group_test.dart (100%) rename test/db_tests/{ => aggregates}/match_test.dart (100%) rename test/db_tests/{ => aggregates}/team_test.dart (100%) rename test/db_tests/{ => entities}/game_test.dart (100%) rename test/db_tests/{ => entities}/player_test.dart (100%) rename test/db_tests/{ => relationships}/player_group_test.dart (100%) rename test/db_tests/{ => relationships}/player_match_test.dart (100%) rename test/db_tests/{ => values}/score_test.dart (100%) diff --git a/test/db_tests/group_test.dart b/test/db_tests/aggregates/group_test.dart similarity index 100% rename from test/db_tests/group_test.dart rename to test/db_tests/aggregates/group_test.dart diff --git a/test/db_tests/match_test.dart b/test/db_tests/aggregates/match_test.dart similarity index 100% rename from test/db_tests/match_test.dart rename to test/db_tests/aggregates/match_test.dart diff --git a/test/db_tests/team_test.dart b/test/db_tests/aggregates/team_test.dart similarity index 100% rename from test/db_tests/team_test.dart rename to test/db_tests/aggregates/team_test.dart diff --git a/test/db_tests/game_test.dart b/test/db_tests/entities/game_test.dart similarity index 100% rename from test/db_tests/game_test.dart rename to test/db_tests/entities/game_test.dart diff --git a/test/db_tests/player_test.dart b/test/db_tests/entities/player_test.dart similarity index 100% rename from test/db_tests/player_test.dart rename to test/db_tests/entities/player_test.dart diff --git a/test/db_tests/player_group_test.dart b/test/db_tests/relationships/player_group_test.dart similarity index 100% rename from test/db_tests/player_group_test.dart rename to test/db_tests/relationships/player_group_test.dart diff --git a/test/db_tests/player_match_test.dart b/test/db_tests/relationships/player_match_test.dart similarity index 100% rename from test/db_tests/player_match_test.dart rename to test/db_tests/relationships/player_match_test.dart diff --git a/test/db_tests/score_test.dart b/test/db_tests/values/score_test.dart similarity index 100% rename from test/db_tests/score_test.dart rename to test/db_tests/values/score_test.dart From 25699dffc042709977d813d9c8e2bd7eb6862278 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sat, 7 Feb 2026 17:25:49 +0100 Subject: [PATCH 76/87] add replaceGroupPlayers method --- lib/data/dao/group_dao.dart | 40 +++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/lib/data/dao/group_dao.dart b/lib/data/dao/group_dao.dart index 7b52ceb..c5abfd5 100644 --- a/lib/data/dao/group_dao.dart +++ b/lib/data/dao/group_dao.dart @@ -231,4 +231,44 @@ class GroupDao extends DatabaseAccessor with _$GroupDaoMixin { final rowsAffected = await query.go(); return rowsAffected > 0; } + + /// Replaces all players in a group with the provided list of players. + /// Removes all existing players from the group and adds the new players. + /// Also adds any new players to the player table if they don't exist. + Future replaceGroupPlayers({ + required String groupId, + required List newPlayers, + }) async { + await db.transaction(() async { + // Remove all existing players from the group + final deleteQuery = delete(db.playerGroupTable) + ..where((p) => p.groupId.equals(groupId)); + await deleteQuery.go(); + + // Add new players to the player table if they don't exist + await Future.wait( + newPlayers.map((player) async { + if (!await db.playerDao.playerExists(playerId: player.id)) { + await db.playerDao.addPlayer(player: player); + } + }), + ); + + // Add the new players to the group + await db.batch( + (b) => b.insertAll( + db.playerGroupTable, + newPlayers + .map( + (player) => PlayerGroupTableCompanion.insert( + playerId: player.id, + groupId: groupId, + ), + ) + .toList(), + mode: InsertMode.insertOrReplace, + ), + ); + }); + } } From fa9ad9dbae30c3154a5b8c991cb9a9a79145326b Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sat, 7 Feb 2026 17:26:07 +0100 Subject: [PATCH 77/87] add test for replacing group players --- .../relationships/player_group_test.dart | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/test/db_tests/relationships/player_group_test.dart b/test/db_tests/relationships/player_group_test.dart index 7e97871..051daf8 100644 --- a/test/db_tests/relationships/player_group_test.dart +++ b/test/db_tests/relationships/player_group_test.dart @@ -308,5 +308,35 @@ void main() { ); expect(secondRemoval, false); }); + + // Verifies that replaceGroupPlayers removes all existing players and replaces with new list. + test('replaceGroupPlayers replaces all group members correctly', () async { + // Create initial group with 3 players + await database.groupDao.addGroup(group: testGroup); + + // Verify initial members + var groupMembers = await database.groupDao.getGroupById( + groupId: testGroup.id, + ); + expect(groupMembers.members.length, 3); + + // Replace with new list containing 2 different players + final newPlayersList = [testPlayer3, testPlayer4]; + await database.groupDao.replaceGroupPlayers( + groupId: testGroup.id, + newPlayers: newPlayersList, + ); + + // Get updated group and verify members + groupMembers = await database.groupDao.getGroupById( + groupId: testGroup.id, + ); + + expect(groupMembers.members.length, 2); + expect(groupMembers.members.any((p) => p.id == testPlayer3.id), true); + expect(groupMembers.members.any((p) => p.id == testPlayer4.id), true); + expect(groupMembers.members.any((p) => p.id == testPlayer1.id), false); + expect(groupMembers.members.any((p) => p.id == testPlayer2.id), false); + }); }); } From 07b9b7825296bfa3d903f69c2caa0f2ff6aa7f9b Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sat, 7 Feb 2026 17:31:19 +0100 Subject: [PATCH 78/87] add replace players in a match method --- lib/data/dao/match_dao.dart | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index 063ac32..8f7a2c0 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -355,6 +355,38 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { return rowsAffected > 0; } + /// Replaces all players in a match with the provided list of players. + /// Removes all existing players from the match and adds the new players. + /// Also adds any new players to the player table if they don't exist. + Future replaceMatchPlayers({ + required String matchId, + required List newPlayers, + }) async { + await db.transaction(() async { + // Remove all existing players from the match + final deleteQuery = delete(db.playerMatchTable) + ..where((p) => p.matchId.equals(matchId)); + await deleteQuery.go(); + + // Add new players to the player table if they don't exist + await Future.wait( + newPlayers.map((player) async { + if (!await db.playerDao.playerExists(playerId: player.id)) { + await db.playerDao.addPlayer(player: player); + } + }), + ); + + // Add the new players to the match + await Future.wait( + newPlayers.map((player) => db.playerMatchDao.addPlayerToMatch( + matchId: matchId, + playerId: player.id, + )), + ); + }); + } + // ============================================================ // TEMPORARY: Winner methods - these are stubs and do not persist data // TODO: Implement proper winner handling From 0eb8e2683c429797044b190134e9a2a908cead5d Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sat, 7 Feb 2026 17:31:23 +0100 Subject: [PATCH 79/87] add replace players in a match test --- .../relationships/player_match_test.dart | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/test/db_tests/relationships/player_match_test.dart b/test/db_tests/relationships/player_match_test.dart index ddc36d2..397f1b7 100644 --- a/test/db_tests/relationships/player_match_test.dart +++ b/test/db_tests/relationships/player_match_test.dart @@ -884,5 +884,36 @@ void main() { expect(playersInTeam.length, 1); expect(playersInTeam[0].id, testPlayer2.id); }); + + // Verifies that replaceMatchPlayers removes all existing players and replaces with new list. + test('replaceMatchPlayers replaces all match players correctly', () async { + // Create initial match with 3 players + await database.matchDao.addMatch(match: testMatchOnlyPlayers); + + // Verify initial players + var matchPlayers = await database.matchDao.getMatchById( + matchId: testMatchOnlyPlayers.id, + ); + expect(matchPlayers.players.length, 3); + + // Replace with new list containing 2 different players + final newPlayersList = [testPlayer1, testPlayer2]; + await database.matchDao.replaceMatchPlayers( + matchId: testMatchOnlyPlayers.id, + newPlayers: newPlayersList, + ); + + // Get updated match and verify players + matchPlayers = await database.matchDao.getMatchById( + matchId: testMatchOnlyPlayers.id, + ); + + expect(matchPlayers.players.length, 2); + expect(matchPlayers.players.any((p) => p.id == testPlayer1.id), true); + expect(matchPlayers.players.any((p) => p.id == testPlayer2.id), true); + expect(matchPlayers.players.any((p) => p.id == testPlayer4.id), false); + expect(matchPlayers.players.any((p) => p.id == testPlayer5.id), false); + expect(matchPlayers.players.any((p) => p.id == testPlayer6.id), false); + }); }); } From a12f4eb1c16118d0eb89eb14b5bd9225c5bb89c6 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sat, 7 Feb 2026 17:35:43 +0100 Subject: [PATCH 80/87] implement winner methods --- lib/data/dao/match_dao.dart | 78 ++++++++++++++++++++++++++++++------- 1 file changed, 63 insertions(+), 15 deletions(-) diff --git a/lib/data/dao/match_dao.dart b/lib/data/dao/match_dao.dart index 8f7a2c0..5726df5 100644 --- a/lib/data/dao/match_dao.dart +++ b/lib/data/dao/match_dao.dart @@ -388,38 +388,86 @@ class MatchDao extends DatabaseAccessor with _$MatchDaoMixin { } // ============================================================ - // TEMPORARY: Winner methods - these are stubs and do not persist data - // TODO: Implement proper winner handling + // Winner methods - handle winner logic via player scores // ============================================================ - /// TEMPORARY: Checks if a match has a winner. - /// Currently returns true if the match has any players. + /// Checks if a match has a winner. + /// Returns true if any player in the match has their score set to 1. Future hasWinner({required String matchId}) async { final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId) ?? []; - return players.isNotEmpty; + + for (final player in players) { + final score = await db.playerMatchDao.getPlayerScore( + matchId: matchId, + playerId: player.id, + ); + if (score == 1) { + return true; + } + } + return false; } - /// TEMPORARY: Gets the winner of a match. - /// Currently returns the first player in the match's player list. + /// Gets the winner of a match. + /// Returns the player with score 1, or null if no winner is set. Future getWinner({required String matchId}) async { final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId) ?? []; - return players.isNotEmpty ? players.first : null; + + for (final player in players) { + final score = await db.playerMatchDao.getPlayerScore( + matchId: matchId, + playerId: player.id, + ); + if (score == 1) { + return player; + } + } + return null; } - /// TEMPORARY: Sets the winner of a match. - /// Currently does nothing - winner is not persisted. + /// Sets the winner of a match. + /// Sets all players' scores to 0, then sets the specified player's score to 1. + /// Returns `true` if the operation was successful, otherwise `false`. Future setWinner({ required String matchId, required String winnerId, }) async { - // TODO: Implement winner persistence + await db.transaction(() async { + final players = await db.playerMatchDao.getPlayersOfMatch(matchId: matchId) ?? []; + + // Set all players' scores to 0 + for (final player in players) { + await db.playerMatchDao.updatePlayerScore( + matchId: matchId, + playerId: player.id, + newScore: 0, + ); + } + + // Set the winner's score to 1 + await db.playerMatchDao.updatePlayerScore( + matchId: matchId, + playerId: winnerId, + newScore: 1, + ); + }); return true; } - /// TEMPORARY: Removes the winner of a match. - /// Currently does nothing - winner is not persisted. + /// Removes the winner of a match. + /// Sets the current winner's score to 0 (no winner). + /// Returns `true` if a winner was removed, otherwise `false`. Future removeWinner({required String matchId}) async { - // TODO: Implement winner persistence - return true; + final winner = await getWinner(matchId: matchId); + if (winner == null) { + return false; + } + + final success = await db.playerMatchDao.updatePlayerScore( + matchId: matchId, + playerId: winner.id, + newScore: 0, + ); + return success; } } \ No newline at end of file From 278544788e57eacc1ad65cd7089ca124f3afbf99 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sat, 7 Feb 2026 17:40:27 +0100 Subject: [PATCH 81/87] fix formatting --- test/db_tests/aggregates/match_test.dart | 40 ++++++++----------- .../relationships/player_match_test.dart | 18 ++++----- 2 files changed, 23 insertions(+), 35 deletions(-) diff --git a/test/db_tests/aggregates/match_test.dart b/test/db_tests/aggregates/match_test.dart index 4935f81..0718e0d 100644 --- a/test/db_tests/aggregates/match_test.dart +++ b/test/db_tests/aggregates/match_test.dart @@ -122,19 +122,15 @@ void main() { } else { fail('Group is null'); } - if (result.players != null) { - expect(result.players!.length, testMatch1.players!.length); + expect(result.players.length, testMatch1.players.length); - for (int i = 0; i < testMatch1.players!.length; i++) { - expect(result.players![i].id, testMatch1.players![i].id); - expect(result.players![i].name, testMatch1.players![i].name); - expect( - result.players![i].createdAt, - testMatch1.players![i].createdAt, - ); - } - } else { - fail('Players is null'); + for (int i = 0; i < testMatch1.players.length; i++) { + expect(result.players[i].id, testMatch1.players[i].id); + expect(result.players[i].name, testMatch1.players[i].name); + expect( + result.players[i].createdAt, + testMatch1.players[i].createdAt, + ); } }); @@ -191,18 +187,14 @@ void main() { } // Players-Checks - if (testMatch.players != null) { - expect(match.players!.length, testMatch.players!.length); - for (int i = 0; i < testMatch.players!.length; i++) { - expect(match.players![i].id, testMatch.players![i].id); - expect(match.players![i].name, testMatch.players![i].name); - expect( - match.players![i].createdAt, - testMatch.players![i].createdAt, - ); - } - } else { - expect(match.players, null); + expect(match.players.length, testMatch.players.length); + for (int i = 0; i < testMatch.players.length; i++) { + expect(match.players[i].id, testMatch.players[i].id); + expect(match.players[i].name, testMatch.players[i].name); + expect( + match.players[i].createdAt, + testMatch.players[i].createdAt, + ); } } }); diff --git a/test/db_tests/relationships/player_match_test.dart b/test/db_tests/relationships/player_match_test.dart index 397f1b7..890e74e 100644 --- a/test/db_tests/relationships/player_match_test.dart +++ b/test/db_tests/relationships/player_match_test.dart @@ -140,7 +140,7 @@ void main() { test('Removing player from match works correctly', () async { await database.matchDao.addMatch(match: testMatchOnlyPlayers); - final playerToRemove = testMatchOnlyPlayers.players![0]; + final playerToRemove = testMatchOnlyPlayers.players[0]; final removed = await database.playerMatchDao.removePlayerFromMatch( playerId: playerToRemove.id, @@ -151,9 +151,9 @@ void main() { final result = await database.matchDao.getMatchById( matchId: testMatchOnlyPlayers.id, ); - expect(result.players!.length, testMatchOnlyPlayers.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, ); expect(playerExists, false); @@ -164,18 +164,14 @@ void main() { await database.matchDao.addMatch(match: testMatchOnlyPlayers); final players = await database.playerMatchDao.getPlayersOfMatch( matchId: testMatchOnlyPlayers.id, - ); - - if (players == null) { - fail('Players should not be null'); - } + ) ?? []; for (int i = 0; i < players.length; i++) { - expect(players[i].id, testMatchOnlyPlayers.players![i].id); - expect(players[i].name, testMatchOnlyPlayers.players![i].name); + expect(players[i].id, testMatchOnlyPlayers.players[i].id); + expect(players[i].name, testMatchOnlyPlayers.players[i].name); expect( players[i].createdAt, - testMatchOnlyPlayers.players![i].createdAt, + testMatchOnlyPlayers.players[i].createdAt, ); } }); From e881cf055529aa9d03ded5b5a6df92350c1e0d0b Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Sat, 7 Feb 2026 18:17:08 +0100 Subject: [PATCH 82/87] fix expected null when empty string is correct --- test/db_tests/entities/game_test.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/db_tests/entities/game_test.dart b/test/db_tests/entities/game_test.dart index 6038690..924a60b 100644 --- a/test/db_tests/entities/game_test.dart +++ b/test/db_tests/entities/game_test.dart @@ -132,7 +132,7 @@ void main() { expect(allGames.length, 1); }); - // Verifies that a game with null optional fields can be added and retrieved. + // Verifies that a game with empty optional fields can be added and retrieved. test('addGame handles game with null optional fields', () async { final gameWithNulls = Game(name: 'Simple Game', ruleset: Ruleset.lowestScore, description: 'A simple game', color: GameColor.green, icon: ''); final result = await database.gameDao.addGame(game: gameWithNulls); @@ -144,7 +144,7 @@ void main() { expect(fetchedGame.name, 'Simple Game'); expect(fetchedGame.description, 'A simple game'); expect(fetchedGame.color, GameColor.green); - expect(fetchedGame.icon, isNull); + expect(fetchedGame.icon, ''); }); // Verifies that multiple games can be added at once using addGamesAsList. From 8e4cff19d1b62ae40fb76f31c3a8b6aa5395bca2 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Mon, 23 Feb 2026 19:29:20 +0100 Subject: [PATCH 83/87] change comment --- lib/data/db/tables/match_table.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/data/db/tables/match_table.dart b/lib/data/db/tables/match_table.dart index 9ed27b7..191e72c 100644 --- a/lib/data/db/tables/match_table.dart +++ b/lib/data/db/tables/match_table.dart @@ -6,7 +6,7 @@ class MatchTable extends Table { TextColumn get id => text()(); TextColumn get gameId => text().references(GameTable, #id, onDelete: KeyAction.cascade)(); - // Nullable if not part of a group + // Nullable if there is no group associated with the match TextColumn get groupId => text().references(GroupTable, #id, onDelete: KeyAction.cascade).nullable()(); TextColumn get name => text().nullable()(); From 866f79998c801fb5b803b407978a537bf796995b Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 4 Mar 2026 13:35:04 +0100 Subject: [PATCH 84/87] set description default --- lib/data/dto/game.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/data/dto/game.dart b/lib/data/dto/game.dart index 437d98e..2eeee1e 100644 --- a/lib/data/dto/game.dart +++ b/lib/data/dto/game.dart @@ -16,11 +16,12 @@ class Game { DateTime? createdAt, required this.name, required this.ruleset, - required this.description, + String? description, required this.color, required this.icon, }) : id = id ?? const Uuid().v4(), - createdAt = createdAt ?? clock.now(); + createdAt = createdAt ?? clock.now(), + description = description ?? ''; @override String toString() { From 5094554475a2f80242627c609aa54babb9560c52 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 4 Mar 2026 13:35:18 +0100 Subject: [PATCH 85/87] set description default --- lib/data/dto/group.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/data/dto/group.dart b/lib/data/dto/group.dart index 0738417..7676b1e 100644 --- a/lib/data/dto/group.dart +++ b/lib/data/dto/group.dart @@ -13,10 +13,11 @@ class Group { String? id, DateTime? createdAt, required this.name, - required this.description, + String? description, required this.members, }) : id = id ?? const Uuid().v4(), - createdAt = createdAt ?? clock.now(); + createdAt = createdAt ?? clock.now(), + description = description ?? ''; @override String toString() { From f04d57382ccc0afe97078be993af1a5071dc377d Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 4 Mar 2026 13:35:43 +0100 Subject: [PATCH 86/87] set notes default --- lib/data/dto/match.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/data/dto/match.dart b/lib/data/dto/match.dart index 31f45fc..3976d36 100644 --- a/lib/data/dto/match.dart +++ b/lib/data/dto/match.dart @@ -24,10 +24,11 @@ class Match { required this.game, this.group, this.players = const [], - required this.notes, + String? notes, this.winner, }) : id = id ?? const Uuid().v4(), - createdAt = createdAt ?? clock.now(); + createdAt = createdAt ?? clock.now(), + notes = notes ?? ''; @override String toString() { From 5d45339337e2d9b0731063901a3234148272f199 Mon Sep 17 00:00:00 2001 From: gelbeinhalb Date: Wed, 4 Mar 2026 13:36:07 +0100 Subject: [PATCH 87/87] set notes default --- lib/data/dto/player.dart | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/data/dto/player.dart b/lib/data/dto/player.dart index 13e4123..c405de9 100644 --- a/lib/data/dto/player.dart +++ b/lib/data/dto/player.dart @@ -11,9 +11,10 @@ class Player { String? id, DateTime? createdAt, required this.name, - required this.description, + String? description, }) : id = id ?? const Uuid().v4(), - createdAt = createdAt ?? clock.now(); + createdAt = createdAt ?? clock.now(), + description = description ?? ''; @override String toString() {