3 Commits

Author SHA1 Message Date
gelbeinhalb
b0cb385756 ruleset is now a required game enum parameter
All checks were successful
Pull Request Pipeline / test (pull_request) Successful in 2m1s
Pull Request Pipeline / lint (pull_request) Successful in 2m7s
2026-01-23 11:54:37 +01:00
gelbeinhalb
118b316a35 description is now a required game parameter 2026-01-23 11:25:20 +01:00
gelbeinhalb
55f5aac4e2 color is now a required game parameter 2026-01-23 11:08:11 +01:00
18 changed files with 174 additions and 131 deletions

View File

@@ -29,24 +29,27 @@ enum ImportResult {
/// - [ExportResult.unknownException]: An exception occurred during export. /// - [ExportResult.unknownException]: An exception occurred during export.
enum ExportResult { success, canceled, unknownException } enum ExportResult { success, canceled, unknownException }
/// Different rulesets available for matches /// Different rulesets available for games
/// - [Ruleset.singleWinner]: The match is won by a single player /// - [Ruleset.highestScore]: The player with the highest score wins.
/// - [Ruleset.singleLoser]: The match is lost by a single player /// - [Ruleset.lowestScore]: The player with the lowest score wins.
/// - [Ruleset.mostPoints]: The player with the most points wins. /// - [Ruleset.singleWinner]: The match is won by a single player.
/// - [Ruleset.leastPoints]: The player with the fewest points wins. /// - [Ruleset.singleLoser]: The match has a single loser.
enum Ruleset { singleWinner, singleLoser, mostPoints, leastPoints } /// - [Ruleset.multipleWinners]: Multiple players can be winners.
enum Ruleset { highestScore, lowestScore, singleWinner, singleLoser, multipleWinners }
/// Translates a [Ruleset] enum value to its corresponding localized string. /// Translates a [Ruleset] enum value to its corresponding localized string.
String translateRulesetToString(Ruleset ruleset, BuildContext context) { String translateRulesetToString(Ruleset ruleset, BuildContext context) {
final loc = AppLocalizations.of(context); final loc = AppLocalizations.of(context);
switch (ruleset) { switch (ruleset) {
case Ruleset.highestScore:
return loc.highest_score;
case Ruleset.lowestScore:
return loc.lowest_score;
case Ruleset.singleWinner: case Ruleset.singleWinner:
return loc.single_winner; return loc.single_winner;
case Ruleset.singleLoser: case Ruleset.singleLoser:
return loc.single_loser; return loc.single_loser;
case Ruleset.mostPoints: case Ruleset.multipleWinners:
return loc.most_points; return loc.multiple_winners;
case Ruleset.leastPoints:
return loc.least_points;
} }
} }

View File

@@ -2,6 +2,7 @@ import 'package:drift/drift.dart';
import 'package:game_tracker/data/db/database.dart'; import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/db/tables/game_table.dart'; import 'package:game_tracker/data/db/tables/game_table.dart';
import 'package:game_tracker/data/dto/game.dart'; import 'package:game_tracker/data/dto/game.dart';
import 'package:game_tracker/core/enums.dart';
part 'game_dao.g.dart'; part 'game_dao.g.dart';
@@ -18,9 +19,9 @@ class GameDao extends DatabaseAccessor<AppDatabase> with _$GameDaoMixin {
(row) => Game( (row) => Game(
id: row.id, id: row.id,
name: row.name, name: row.name,
ruleset: row.ruleset, ruleset: Ruleset.values.firstWhere((e) => e.name == row.ruleset),
description: row.description, description: row.description,
color: row.color != null ? int.tryParse(row.color!) : null, color: row.color,
icon: row.icon, icon: row.icon,
createdAt: row.createdAt, createdAt: row.createdAt,
), ),
@@ -35,9 +36,9 @@ class GameDao extends DatabaseAccessor<AppDatabase> with _$GameDaoMixin {
return Game( return Game(
id: result.id, id: result.id,
name: result.name, name: result.name,
ruleset: result.ruleset, ruleset: Ruleset.values.firstWhere((e) => e.name == result.ruleset),
description: result.description, description: result.description,
color: result.color != null ? int.tryParse(result.color!) : null, color: result.color,
icon: result.icon, icon: result.icon,
createdAt: result.createdAt, createdAt: result.createdAt,
); );
@@ -52,9 +53,9 @@ class GameDao extends DatabaseAccessor<AppDatabase> with _$GameDaoMixin {
GameTableCompanion.insert( GameTableCompanion.insert(
id: game.id, id: game.id,
name: game.name, name: game.name,
ruleset: game.ruleset ?? '', ruleset: game.ruleset.name,
description: Value(game.description), description: game.description,
color: Value(game.color?.toString()), color: game.color,
icon: Value(game.icon), icon: Value(game.icon),
createdAt: game.createdAt, createdAt: game.createdAt,
), ),
@@ -78,9 +79,9 @@ class GameDao extends DatabaseAccessor<AppDatabase> with _$GameDaoMixin {
(game) => GameTableCompanion.insert( (game) => GameTableCompanion.insert(
id: game.id, id: game.id,
name: game.name, name: game.name,
ruleset: game.ruleset ?? '', ruleset: game.ruleset.name,
description: Value(game.description), description: game.description,
color: Value(game.color?.toString()), color: game.color,
icon: Value(game.icon), icon: Value(game.icon),
createdAt: game.createdAt, createdAt: game.createdAt,
), ),
@@ -122,17 +123,17 @@ class GameDao extends DatabaseAccessor<AppDatabase> with _$GameDaoMixin {
/// Updates the ruleset of the game with the given [gameId]. /// Updates the ruleset of the game with the given [gameId].
Future<void> updateGameRuleset({ Future<void> updateGameRuleset({
required String gameId, required String gameId,
required String newRuleset, required Ruleset newRuleset,
}) async { }) async {
await (update(gameTable)..where((g) => g.id.equals(gameId))).write( await (update(gameTable)..where((g) => g.id.equals(gameId))).write(
GameTableCompanion(ruleset: Value(newRuleset)), GameTableCompanion(ruleset: Value(newRuleset.name)),
); );
} }
/// Updates the description of the game with the given [gameId]. /// Updates the description of the game with the given [gameId].
Future<void> updateGameDescription({ Future<void> updateGameDescription({
required String gameId, required String gameId,
required String? newDescription, required String newDescription,
}) async { }) async {
await (update(gameTable)..where((g) => g.id.equals(gameId))).write( await (update(gameTable)..where((g) => g.id.equals(gameId))).write(
GameTableCompanion(description: Value(newDescription)), GameTableCompanion(description: Value(newDescription)),
@@ -142,10 +143,10 @@ class GameDao extends DatabaseAccessor<AppDatabase> with _$GameDaoMixin {
/// Updates the color of the game with the given [gameId]. /// Updates the color of the game with the given [gameId].
Future<void> updateGameColor({ Future<void> updateGameColor({
required String gameId, required String gameId,
required int? newColor, required String newColor,
}) async { }) async {
await (update(gameTable)..where((g) => g.id.equals(gameId))).write( await (update(gameTable)..where((g) => g.id.equals(gameId))).write(
GameTableCompanion(color: Value(newColor?.toString())), GameTableCompanion(color: Value(newColor)),
); );
} }

View File

@@ -127,9 +127,9 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
(game) => GameTableCompanion.insert( (game) => GameTableCompanion.insert(
id: game.id, id: game.id,
name: game.name, name: game.name,
ruleset: game.ruleset ?? '', ruleset: game.ruleset.name,
description: Value(game.description), description: game.description,
color: Value(game.color?.toString()), color: game.color,
icon: Value(game.icon), icon: Value(game.icon),
createdAt: game.createdAt, createdAt: game.createdAt,
), ),

View File

@@ -46,7 +46,7 @@ class AppDatabase extends _$AppDatabase {
AppDatabase([QueryExecutor? executor]) : super(executor ?? _openConnection()); AppDatabase([QueryExecutor? executor]) : super(executor ?? _openConnection());
@override @override
int get schemaVersion => 2; int get schemaVersion => 1;
@override @override
MigrationStrategy get migration { MigrationStrategy get migration {

View File

@@ -673,18 +673,18 @@ class $GameTableTable extends GameTable
late final GeneratedColumn<String> description = GeneratedColumn<String>( late final GeneratedColumn<String> description = GeneratedColumn<String>(
'description', 'description',
aliasedName, aliasedName,
true, false,
type: DriftSqlType.string, type: DriftSqlType.string,
requiredDuringInsert: false, requiredDuringInsert: true,
); );
static const VerificationMeta _colorMeta = const VerificationMeta('color'); static const VerificationMeta _colorMeta = const VerificationMeta('color');
@override @override
late final GeneratedColumn<String> color = GeneratedColumn<String>( late final GeneratedColumn<String> color = GeneratedColumn<String>(
'color', 'color',
aliasedName, aliasedName,
true, false,
type: DriftSqlType.string, type: DriftSqlType.string,
requiredDuringInsert: false, requiredDuringInsert: true,
); );
static const VerificationMeta _iconMeta = const VerificationMeta('icon'); static const VerificationMeta _iconMeta = const VerificationMeta('icon');
@override @override
@@ -757,12 +757,16 @@ class $GameTableTable extends GameTable
_descriptionMeta, _descriptionMeta,
), ),
); );
} else if (isInserting) {
context.missing(_descriptionMeta);
} }
if (data.containsKey('color')) { if (data.containsKey('color')) {
context.handle( context.handle(
_colorMeta, _colorMeta,
color.isAcceptableOrUnknown(data['color']!, _colorMeta), color.isAcceptableOrUnknown(data['color']!, _colorMeta),
); );
} else if (isInserting) {
context.missing(_colorMeta);
} }
if (data.containsKey('icon')) { if (data.containsKey('icon')) {
context.handle( context.handle(
@@ -802,11 +806,11 @@ class $GameTableTable extends GameTable
description: attachedDatabase.typeMapping.read( description: attachedDatabase.typeMapping.read(
DriftSqlType.string, DriftSqlType.string,
data['${effectivePrefix}description'], data['${effectivePrefix}description'],
), )!,
color: attachedDatabase.typeMapping.read( color: attachedDatabase.typeMapping.read(
DriftSqlType.string, DriftSqlType.string,
data['${effectivePrefix}color'], data['${effectivePrefix}color'],
), )!,
icon: attachedDatabase.typeMapping.read( icon: attachedDatabase.typeMapping.read(
DriftSqlType.string, DriftSqlType.string,
data['${effectivePrefix}icon'], data['${effectivePrefix}icon'],
@@ -828,16 +832,16 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
final String id; final String id;
final String name; final String name;
final String ruleset; final String ruleset;
final String? description; final String description;
final String? color; final String color;
final String? icon; final String? icon;
final DateTime createdAt; final DateTime createdAt;
const GameTableData({ const GameTableData({
required this.id, required this.id,
required this.name, required this.name,
required this.ruleset, required this.ruleset,
this.description, required this.description,
this.color, required this.color,
this.icon, this.icon,
required this.createdAt, required this.createdAt,
}); });
@@ -847,12 +851,8 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
map['id'] = Variable<String>(id); map['id'] = Variable<String>(id);
map['name'] = Variable<String>(name); map['name'] = Variable<String>(name);
map['ruleset'] = Variable<String>(ruleset); map['ruleset'] = Variable<String>(ruleset);
if (!nullToAbsent || description != null) { map['description'] = Variable<String>(description);
map['description'] = Variable<String>(description); map['color'] = Variable<String>(color);
}
if (!nullToAbsent || color != null) {
map['color'] = Variable<String>(color);
}
if (!nullToAbsent || icon != null) { if (!nullToAbsent || icon != null) {
map['icon'] = Variable<String>(icon); map['icon'] = Variable<String>(icon);
} }
@@ -865,12 +865,8 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
id: Value(id), id: Value(id),
name: Value(name), name: Value(name),
ruleset: Value(ruleset), ruleset: Value(ruleset),
description: description == null && nullToAbsent description: Value(description),
? const Value.absent() color: Value(color),
: Value(description),
color: color == null && nullToAbsent
? const Value.absent()
: Value(color),
icon: icon == null && nullToAbsent ? const Value.absent() : Value(icon), icon: icon == null && nullToAbsent ? const Value.absent() : Value(icon),
createdAt: Value(createdAt), createdAt: Value(createdAt),
); );
@@ -885,8 +881,8 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
id: serializer.fromJson<String>(json['id']), id: serializer.fromJson<String>(json['id']),
name: serializer.fromJson<String>(json['name']), name: serializer.fromJson<String>(json['name']),
ruleset: serializer.fromJson<String>(json['ruleset']), ruleset: serializer.fromJson<String>(json['ruleset']),
description: serializer.fromJson<String?>(json['description']), description: serializer.fromJson<String>(json['description']),
color: serializer.fromJson<String?>(json['color']), color: serializer.fromJson<String>(json['color']),
icon: serializer.fromJson<String?>(json['icon']), icon: serializer.fromJson<String?>(json['icon']),
createdAt: serializer.fromJson<DateTime>(json['createdAt']), createdAt: serializer.fromJson<DateTime>(json['createdAt']),
); );
@@ -898,8 +894,8 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
'id': serializer.toJson<String>(id), 'id': serializer.toJson<String>(id),
'name': serializer.toJson<String>(name), 'name': serializer.toJson<String>(name),
'ruleset': serializer.toJson<String>(ruleset), 'ruleset': serializer.toJson<String>(ruleset),
'description': serializer.toJson<String?>(description), 'description': serializer.toJson<String>(description),
'color': serializer.toJson<String?>(color), 'color': serializer.toJson<String>(color),
'icon': serializer.toJson<String?>(icon), 'icon': serializer.toJson<String?>(icon),
'createdAt': serializer.toJson<DateTime>(createdAt), 'createdAt': serializer.toJson<DateTime>(createdAt),
}; };
@@ -909,16 +905,16 @@ class GameTableData extends DataClass implements Insertable<GameTableData> {
String? id, String? id,
String? name, String? name,
String? ruleset, String? ruleset,
Value<String?> description = const Value.absent(), String? description,
Value<String?> color = const Value.absent(), String? color,
Value<String?> icon = const Value.absent(), Value<String?> icon = const Value.absent(),
DateTime? createdAt, DateTime? createdAt,
}) => GameTableData( }) => GameTableData(
id: id ?? this.id, id: id ?? this.id,
name: name ?? this.name, name: name ?? this.name,
ruleset: ruleset ?? this.ruleset, ruleset: ruleset ?? this.ruleset,
description: description.present ? description.value : this.description, description: description ?? this.description,
color: color.present ? color.value : this.color, color: color ?? this.color,
icon: icon.present ? icon.value : this.icon, icon: icon.present ? icon.value : this.icon,
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
); );
@@ -970,8 +966,8 @@ class GameTableCompanion extends UpdateCompanion<GameTableData> {
final Value<String> id; final Value<String> id;
final Value<String> name; final Value<String> name;
final Value<String> ruleset; final Value<String> ruleset;
final Value<String?> description; final Value<String> description;
final Value<String?> color; final Value<String> color;
final Value<String?> icon; final Value<String?> icon;
final Value<DateTime> createdAt; final Value<DateTime> createdAt;
final Value<int> rowid; final Value<int> rowid;
@@ -989,14 +985,16 @@ class GameTableCompanion extends UpdateCompanion<GameTableData> {
required String id, required String id,
required String name, required String name,
required String ruleset, required String ruleset,
this.description = const Value.absent(), required String description,
this.color = const Value.absent(), required String color,
this.icon = const Value.absent(), this.icon = const Value.absent(),
required DateTime createdAt, required DateTime createdAt,
this.rowid = const Value.absent(), this.rowid = const Value.absent(),
}) : id = Value(id), }) : id = Value(id),
name = Value(name), name = Value(name),
ruleset = Value(ruleset), ruleset = Value(ruleset),
description = Value(description),
color = Value(color),
createdAt = Value(createdAt); createdAt = Value(createdAt);
static Insertable<GameTableData> custom({ static Insertable<GameTableData> custom({
Expression<String>? id, Expression<String>? id,
@@ -1024,8 +1022,8 @@ class GameTableCompanion extends UpdateCompanion<GameTableData> {
Value<String>? id, Value<String>? id,
Value<String>? name, Value<String>? name,
Value<String>? ruleset, Value<String>? ruleset,
Value<String?>? description, Value<String>? description,
Value<String?>? color, Value<String>? color,
Value<String?>? icon, Value<String?>? icon,
Value<DateTime>? createdAt, Value<DateTime>? createdAt,
Value<int>? rowid, Value<int>? rowid,
@@ -3664,8 +3662,8 @@ typedef $$GameTableTableCreateCompanionBuilder =
required String id, required String id,
required String name, required String name,
required String ruleset, required String ruleset,
Value<String?> description, required String description,
Value<String?> color, required String color,
Value<String?> icon, Value<String?> icon,
required DateTime createdAt, required DateTime createdAt,
Value<int> rowid, Value<int> rowid,
@@ -3675,8 +3673,8 @@ typedef $$GameTableTableUpdateCompanionBuilder =
Value<String> id, Value<String> id,
Value<String> name, Value<String> name,
Value<String> ruleset, Value<String> ruleset,
Value<String?> description, Value<String> description,
Value<String?> color, Value<String> color,
Value<String?> icon, Value<String?> icon,
Value<DateTime> createdAt, Value<DateTime> createdAt,
Value<int> rowid, Value<int> rowid,
@@ -3909,8 +3907,8 @@ class $$GameTableTableTableManager
Value<String> id = const Value.absent(), Value<String> id = const Value.absent(),
Value<String> name = const Value.absent(), Value<String> name = const Value.absent(),
Value<String> ruleset = const Value.absent(), Value<String> ruleset = const Value.absent(),
Value<String?> description = const Value.absent(), Value<String> description = const Value.absent(),
Value<String?> color = const Value.absent(), Value<String> color = const Value.absent(),
Value<String?> icon = const Value.absent(), Value<String?> icon = const Value.absent(),
Value<DateTime> createdAt = const Value.absent(), Value<DateTime> createdAt = const Value.absent(),
Value<int> rowid = const Value.absent(), Value<int> rowid = const Value.absent(),
@@ -3929,8 +3927,8 @@ class $$GameTableTableTableManager
required String id, required String id,
required String name, required String name,
required String ruleset, required String ruleset,
Value<String?> description = const Value.absent(), required String description,
Value<String?> color = const Value.absent(), required String color,
Value<String?> icon = const Value.absent(), Value<String?> icon = const Value.absent(),
required DateTime createdAt, required DateTime createdAt,
Value<int> rowid = const Value.absent(), Value<int> rowid = const Value.absent(),

View File

@@ -4,8 +4,8 @@ class GameTable extends Table {
TextColumn get id => text()(); TextColumn get id => text()();
TextColumn get name => text()(); TextColumn get name => text()();
TextColumn get ruleset => text()(); TextColumn get ruleset => text()();
TextColumn get description => text().nullable()(); TextColumn get description => text()();
TextColumn get color => text().nullable()(); TextColumn get color => text()();
TextColumn get icon => text().nullable()(); TextColumn get icon => text().nullable()();
DateTimeColumn get createdAt => dateTime()(); DateTimeColumn get createdAt => dateTime()();

View File

@@ -1,22 +1,23 @@
import 'package:clock/clock.dart'; import 'package:clock/clock.dart';
import 'package:uuid/uuid.dart'; import 'package:uuid/uuid.dart';
import 'package:game_tracker/core/enums.dart';
class Game { class Game {
final String id; final String id;
final DateTime createdAt; final DateTime createdAt;
final String name; final String name;
final String? ruleset; final Ruleset ruleset;
final String? description; final String description;
final int? color; final String color;
final String? icon; final String? icon;
Game({ Game({
String? id, String? id,
DateTime? createdAt, DateTime? createdAt,
required this.name, required this.name,
this.ruleset, required this.ruleset,
this.description, required this.description,
this.color, required this.color,
this.icon, this.icon,
}) : id = id ?? const Uuid().v4(), }) : id = id ?? const Uuid().v4(),
createdAt = createdAt ?? clock.now(); createdAt = createdAt ?? clock.now();
@@ -31,7 +32,7 @@ class Game {
: id = json['id'], : id = json['id'],
createdAt = DateTime.parse(json['createdAt']), createdAt = DateTime.parse(json['createdAt']),
name = json['name'], name = json['name'],
ruleset = json['ruleset'], ruleset = Ruleset.values.firstWhere((e) => e.name == json['ruleset']),
description = json['description'], description = json['description'],
color = json['color'], color = json['color'],
icon = json['icon']; icon = json['icon'];
@@ -41,7 +42,7 @@ class Game {
'id': id, 'id': id,
'createdAt': createdAt.toIso8601String(), 'createdAt': createdAt.toIso8601String(),
'name': name, 'name': name,
'ruleset': ruleset, 'ruleset': ruleset.name,
'description': description, 'description': description,
'color': color, 'color': color,
'icon': icon, 'icon': icon,

View File

@@ -82,6 +82,9 @@
"settings": "Einstellungen", "settings": "Einstellungen",
"single_loser": "Ein:e Verlierer:in", "single_loser": "Ein:e Verlierer:in",
"single_winner": "Ein:e Gewinner:in", "single_winner": "Ein:e Gewinner:in",
"highest_score": "Höchste Punkte",
"lowest_score": "Niedrigste Punkte",
"multiple_winners": "Mehrere Gewinner:innen",
"statistics": "Statistiken", "statistics": "Statistiken",
"stats": "Statistiken", "stats": "Statistiken",
"successfully_added_player": "Spieler:in {playerName} erfolgreich hinzugefügt", "successfully_added_player": "Spieler:in {playerName} erfolgreich hinzugefügt",

View File

@@ -380,6 +380,9 @@
"settings": "Settings", "settings": "Settings",
"single_loser": "Single Loser", "single_loser": "Single Loser",
"single_winner": "Single Winner", "single_winner": "Single Winner",
"highest_score": "Highest Score",
"lowest_score": "Lowest Score",
"multiple_winners": "Multiple Winners",
"statistics": "Statistics", "statistics": "Statistics",
"stats": "Stats", "stats": "Stats",
"successfully_added_player": "Successfully added player {playerName}", "successfully_added_player": "Successfully added player {playerName}",

View File

@@ -590,6 +590,24 @@ abstract class AppLocalizations {
/// **'Single Winner'** /// **'Single Winner'**
String get 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 /// Statistics tab label
/// ///
/// In en, this message translates to: /// In en, this message translates to:

View File

@@ -266,6 +266,15 @@ class AppLocalizationsDe extends AppLocalizations {
@override @override
String get single_winner => 'Ein:e Gewinner:in'; 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 @override
String get statistics => 'Statistiken'; String get statistics => 'Statistiken';

View File

@@ -266,6 +266,15 @@ class AppLocalizationsEn extends AppLocalizations {
@override @override
String get single_winner => 'Single Winner'; 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 @override
String get statistics => 'Statistics'; String get statistics => 'Statistics';

View File

@@ -100,7 +100,7 @@ class _CreateMatchViewState extends State<CreateMatchView> {
} }
List<(String, String, Ruleset)> games = [ 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), ('Example Game 2', '', Ruleset.singleWinner),
]; ];
@@ -201,7 +201,8 @@ class _CreateMatchViewState extends State<CreateMatchView> {
gameToUse = Game( gameToUse = Game(
name: selectedGame.$1, name: selectedGame.$1,
description: selectedGame.$2, description: selectedGame.$2,
ruleset: selectedGame.$3.name, ruleset: selectedGame.$3,
color: '0xFF000000',
); );
} else { } else {
// Use the selected game from the list // Use the selected game from the list
@@ -209,7 +210,8 @@ class _CreateMatchViewState extends State<CreateMatchView> {
gameToUse = Game( gameToUse = Game(
name: selectedGame.$1, name: selectedGame.$1,
description: selectedGame.$2, description: selectedGame.$2,
ruleset: selectedGame.$3.name, ruleset: selectedGame.$3,
color: '0xFF000000',
); );
} }
// Add the game to the database if it doesn't exist // Add the game to the database if it doesn't exist

View File

@@ -4,6 +4,7 @@ import 'package:drift/native.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:game_tracker/data/db/database.dart'; import 'package:game_tracker/data/db/database.dart';
import 'package:game_tracker/data/dto/game.dart'; import 'package:game_tracker/data/dto/game.dart';
import 'package:game_tracker/core/enums.dart';
void main() { void main() {
late AppDatabase database; late AppDatabase database;
@@ -24,23 +25,25 @@ void main() {
withClock(fakeClock, () { withClock(fakeClock, () {
testGame1 = Game( testGame1 = Game(
name: 'Chess', name: 'Chess',
ruleset: 'winner.single', ruleset: Ruleset.singleWinner,
description: 'A classic strategy game', description: 'A classic strategy game',
color: 0xFF0000FF, color: '0xFF0000FF',
icon: 'chess_icon', icon: 'chess_icon',
); );
testGame2 = Game( testGame2 = Game(
id: 'game2', id: 'game2',
name: 'Poker', name: 'Poker',
ruleset: 'Texas Hold\'em rules', ruleset: Ruleset.multipleWinners,
description: 'winner.multiple', description: 'Card game with multiple winners',
color: 0xFFFF0000, color: '0xFFFF0000',
icon: 'poker_icon', icon: 'poker_icon',
); );
testGame3 = Game( testGame3 = Game(
id: 'game3', id: 'game3',
name: 'Monopoly', name: 'Monopoly',
ruleset: Ruleset.highestScore,
description: 'A board game about real estate', description: 'A board game about real estate',
color: '0xFF000000',
); );
}); });
}); });
@@ -130,7 +133,7 @@ void main() {
// Verifies that a game with null optional fields can be added and retrieved. // Verifies that a game with null optional fields can be added and retrieved.
test('addGame handles game with null optional fields', () async { test('addGame handles game with null optional fields', () async {
final gameWithNulls = Game(name: 'Simple Game'); final gameWithNulls = Game(name: 'Simple Game', ruleset: Ruleset.lowestScore, description: 'A simple game', color: '0xFF000000');
final result = await database.gameDao.addGame(game: gameWithNulls); final result = await database.gameDao.addGame(game: gameWithNulls);
expect(result, true); expect(result, true);
@@ -138,8 +141,8 @@ void main() {
gameId: gameWithNulls.id, gameId: gameWithNulls.id,
); );
expect(fetchedGame.name, 'Simple Game'); expect(fetchedGame.name, 'Simple Game');
expect(fetchedGame.description, isNull); expect(fetchedGame.description, 'A simple game');
expect(fetchedGame.color, isNull); expect(fetchedGame.color, '0xFF000000');
expect(fetchedGame.icon, isNull); expect(fetchedGame.icon, isNull);
}); });
@@ -268,13 +271,13 @@ void main() {
await database.gameDao.updateGameRuleset( await database.gameDao.updateGameRuleset(
gameId: testGame1.id, gameId: testGame1.id,
newRuleset: 'New ruleset for chess', newRuleset: Ruleset.highestScore,
); );
final updatedGame = await database.gameDao.getGameById( final updatedGame = await database.gameDao.getGameById(
gameId: testGame1.id, gameId: testGame1.id,
); );
expect(updatedGame.ruleset, 'New ruleset for chess'); expect(updatedGame.ruleset, Ruleset.highestScore);
expect(updatedGame.name, testGame1.name); expect(updatedGame.name, testGame1.name);
}); });
@@ -282,7 +285,7 @@ void main() {
test('updateGameRuleset does nothing for non-existent game', () async { test('updateGameRuleset does nothing for non-existent game', () async {
await database.gameDao.updateGameRuleset( await database.gameDao.updateGameRuleset(
gameId: 'non-existent-id', gameId: 'non-existent-id',
newRuleset: 'New Ruleset', newRuleset: Ruleset.lowestScore,
); );
final allGames = await database.gameDao.getAllGames(); final allGames = await database.gameDao.getAllGames();
@@ -304,19 +307,19 @@ void main() {
expect(updatedGame.description, 'An updated description'); expect(updatedGame.description, 'An updated description');
}); });
// Verifies that updateGameDescription can set the description to null. // Verifies that updateGameDescription can set the description to an empty string.
test('updateGameDescription can set description to null', () async { test('updateGameDescription can set description to empty string', () async {
await database.gameDao.addGame(game: testGame1); await database.gameDao.addGame(game: testGame1);
await database.gameDao.updateGameDescription( await database.gameDao.updateGameDescription(
gameId: testGame1.id, gameId: testGame1.id,
newDescription: null, newDescription: '',
); );
final updatedGame = await database.gameDao.getGameById( final updatedGame = await database.gameDao.getGameById(
gameId: testGame1.id, gameId: testGame1.id,
); );
expect(updatedGame.description, isNull); expect(updatedGame.description, '');
}); });
// Verifies that updateGameDescription does nothing when game doesn't exist. // Verifies that updateGameDescription does nothing when game doesn't exist.
@@ -336,35 +339,20 @@ void main() {
await database.gameDao.updateGameColor( await database.gameDao.updateGameColor(
gameId: testGame1.id, gameId: testGame1.id,
newColor: 0xFF00FF00, newColor: '0xFF00FF00',
); );
final updatedGame = await database.gameDao.getGameById( final updatedGame = await database.gameDao.getGameById(
gameId: testGame1.id, gameId: testGame1.id,
); );
expect(updatedGame.color, 0xFF00FF00); 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);
}); });
// Verifies that updateGameColor does nothing when game doesn't exist. // Verifies that updateGameColor does nothing when game doesn't exist.
test('updateGameColor does nothing for non-existent game', () async { test('updateGameColor does nothing for non-existent game', () async {
await database.gameDao.updateGameColor( await database.gameDao.updateGameColor(
gameId: 'non-existent-id', gameId: 'non-existent-id',
newColor: 0xFF00FF00, newColor: '0xFF00FF00',
); );
final allGames = await database.gameDao.getAllGames(); final allGames = await database.gameDao.getAllGames();
@@ -469,7 +457,9 @@ void main() {
test('Game with special characters in name is stored correctly', () async { test('Game with special characters in name is stored correctly', () async {
final specialGame = Game( final specialGame = Game(
name: 'Game\'s & "Special" <Name>', name: 'Game\'s & "Special" <Name>',
ruleset: Ruleset.multipleWinners,
description: 'Description with émojis 🎮🎲', description: 'Description with émojis 🎮🎲',
color: '0xFF000000',
); );
await database.gameDao.addGame(game: specialGame); await database.gameDao.addGame(game: specialGame);
@@ -484,9 +474,10 @@ void main() {
test('Game with empty string fields is stored correctly', () async { test('Game with empty string fields is stored correctly', () async {
final emptyGame = Game( final emptyGame = Game(
name: '', name: '',
ruleset: '', ruleset: Ruleset.singleWinner,
description: '', description: '',
icon: '', icon: '',
color: '0xFF000000',
); );
await database.gameDao.addGame(game: emptyGame); await database.gameDao.addGame(game: emptyGame);
@@ -494,7 +485,7 @@ void main() {
gameId: emptyGame.id, gameId: emptyGame.id,
); );
expect(fetchedGame.name, ''); expect(fetchedGame.name, '');
expect(fetchedGame.ruleset, ''); expect(fetchedGame.ruleset, Ruleset.singleWinner);
expect(fetchedGame.description, ''); expect(fetchedGame.description, '');
expect(fetchedGame.icon, ''); expect(fetchedGame.icon, '');
}); });
@@ -505,7 +496,8 @@ void main() {
final longGame = Game( final longGame = Game(
name: longString, name: longString,
description: longString, description: longString,
ruleset: longString, ruleset: Ruleset.multipleWinners,
color: '0xFF000000',
); );
await database.gameDao.addGame(game: longGame); await database.gameDao.addGame(game: longGame);
@@ -513,8 +505,8 @@ void main() {
gameId: longGame.id, gameId: longGame.id,
); );
expect(fetchedGame.name.length, 10000); expect(fetchedGame.name.length, 10000);
expect(fetchedGame.description?.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. // Verifies that multiple sequential updates to the same game work correctly.
@@ -527,7 +519,7 @@ void main() {
); );
await database.gameDao.updateGameColor( await database.gameDao.updateGameColor(
gameId: testGame1.id, gameId: testGame1.id,
newColor: 0xFF123456, newColor: '0xFF123456',
); );
await database.gameDao.updateGameDescription( await database.gameDao.updateGameDescription(
gameId: testGame1.id, gameId: testGame1.id,
@@ -538,7 +530,7 @@ void main() {
gameId: testGame1.id, gameId: testGame1.id,
); );
expect(updatedGame.name, 'Updated Name'); expect(updatedGame.name, 'Updated Name');
expect(updatedGame.color, 0xFF123456); expect(updatedGame.color, '0xFF123456');
expect(updatedGame.description, 'Updated Description'); expect(updatedGame.description, 'Updated Description');
expect(updatedGame.ruleset, testGame1.ruleset); expect(updatedGame.ruleset, testGame1.ruleset);
expect(updatedGame.icon, testGame1.icon); expect(updatedGame.icon, testGame1.icon);

View File

@@ -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/group.dart';
import 'package:game_tracker/data/dto/match.dart'; import 'package:game_tracker/data/dto/match.dart';
import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/data/dto/player.dart';
import 'package:game_tracker/core/enums.dart';
void main() { void main() {
late AppDatabase database; late AppDatabase database;
@@ -48,7 +49,7 @@ void main() {
name: 'Test Group 2', name: 'Test Group 2',
members: [testPlayer4, testPlayer5], members: [testPlayer4, testPlayer5],
); );
testGame = Game(name: 'Test Game'); testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000');
testMatch1 = Match( testMatch1 = Match(
name: 'First Test Match', name: 'First Test Match',
game: testGame, game: testGame,

View File

@@ -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/match.dart';
import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/data/dto/player.dart';
import 'package:game_tracker/data/dto/team.dart'; import 'package:game_tracker/data/dto/team.dart';
import 'package:game_tracker/core/enums.dart';
void main() { void main() {
late AppDatabase database; late AppDatabase database;
@@ -46,7 +47,7 @@ void main() {
name: 'Test Group', name: 'Test Group',
members: [testPlayer1, testPlayer2, testPlayer3], members: [testPlayer1, testPlayer2, testPlayer3],
); );
testGame = Game(name: 'Test Game'); testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000');
testMatchOnlyGroup = Match( testMatchOnlyGroup = Match(
name: 'Test Match with Group', name: 'Test Match with Group',
game: testGame, game: testGame,

View File

@@ -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/game.dart';
import 'package:game_tracker/data/dto/match.dart'; import 'package:game_tracker/data/dto/match.dart';
import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/data/dto/player.dart';
import 'package:game_tracker/core/enums.dart';
void main() { void main() {
late AppDatabase database; late AppDatabase database;
@@ -31,7 +32,7 @@ void main() {
testPlayer1 = Player(name: 'Alice'); testPlayer1 = Player(name: 'Alice');
testPlayer2 = Player(name: 'Bob'); testPlayer2 = Player(name: 'Bob');
testPlayer3 = Player(name: 'Charlie'); testPlayer3 = Player(name: 'Charlie');
testGame = Game(name: 'Test Game'); testGame = Game(name: 'Test Game', ruleset: Ruleset.singleWinner, description: 'A test game', color: '0xFF000000');
testMatch1 = Match( testMatch1 = Match(
name: 'Test Match 1', name: 'Test Match 1',
game: testGame, game: testGame,

View File

@@ -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/match.dart';
import 'package:game_tracker/data/dto/player.dart'; import 'package:game_tracker/data/dto/player.dart';
import 'package:game_tracker/data/dto/team.dart'; import 'package:game_tracker/data/dto/team.dart';
import 'package:game_tracker/core/enums.dart';
void main() { void main() {
late AppDatabase database; late AppDatabase database;
@@ -48,8 +49,8 @@ void main() {
name: 'Team Gamma', name: 'Team Gamma',
members: [testPlayer1, testPlayer3], members: [testPlayer1, testPlayer3],
); );
testGame1 = Game(name: 'Game 1'); testGame1 = Game(name: 'Game 1', ruleset: Ruleset.singleWinner, description: 'Test game 1', color: '0xFF000000');
testGame2 = Game(name: 'Game 2'); testGame2 = Game(name: 'Game 2', ruleset: Ruleset.highestScore, description: 'Test game 2', color: '0xFF000000');
}); });
await database.playerDao.addPlayersAsList( await database.playerDao.addPlayersAsList(