Neue Datenbank Struktur #156

Open
gelbeinhalb wants to merge 88 commits from feature/88-neue-datenbank-struktur into development
6 changed files with 101 additions and 4 deletions
Showing only changes of commit 415cae18cd - Show all commits

View File

@@ -142,6 +142,9 @@
"createdAt": { "createdAt": {
gelbeinhalb marked this conversation as resolved Outdated

Wenn es hier um ein Match und nicht um ein Game geht, darf Match(Game) nicht null sein, weil ein Spiel immer eine Spielvorlage haben muss

Wenn es hier um ein `Match` und nicht um ein `Game` geht, darf `Match`(`Game`) nicht `null` sein, weil ein Spiel immer eine Spielvorlage haben muss
"type": "string" "type": "string"
}, },
"endedAt": {
flixcoo marked this conversation as resolved
Review

Was soll endedAt für einen Sinn haben? Also wozu brauche ich den Endzeitpunkt eines Spiels? Und vor allem wie lege ich den Fest? Wenn ich denn Winner setze?

Was soll `endedAt` für einen Sinn haben? Also wozu brauche ich den Endzeitpunkt eines Spiels? Und vor allem wie lege ich den Fest? Wenn ich denn Winner setze?
Review

Ich dachte, dass man den Zeitpunkt später braucht, wenn das Winner Attribut entfernt wird. Später soll das ja nur calculated werden basierend auf den scores der Spieler und nicht extra gespeichert werden. Dann braucht man ja einen Weg zu sagen, ob das Spiel fertig ist oder nicht. Einen endedAt Timestamp fand ich besser als einen einfachen finished boolean

Ich dachte, dass man den Zeitpunkt später braucht, wenn das Winner Attribut entfernt wird. Später soll das ja nur calculated werden basierend auf den scores der Spieler und nicht extra gespeichert werden. Dann braucht man ja einen Weg zu sagen, ob das Spiel fertig ist oder nicht. Einen `endedAt` Timestamp fand ich besser als einen einfachen `finished` boolean
Review

ah okay, ja fair

ah okay, ja fair
"type": ["string", "null"]
},
"gameId": { "gameId": {
"type": "string" "type": "string"
}, },

View File

@@ -38,6 +38,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
players: players, players: players,
notes: row.notes ?? '', notes: row.notes ?? '',
createdAt: row.createdAt, createdAt: row.createdAt,
endedAt: row.endedAt,
); );
}), }),
); );
@@ -68,6 +69,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
players: players, players: players,
notes: result.notes ?? '', notes: result.notes ?? '',
createdAt: result.createdAt, createdAt: result.createdAt,
endedAt: result.endedAt,
); );
} }
@@ -84,6 +86,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
name: Value(match.name), name: Value(match.name),
notes: Value(match.notes), notes: Value(match.notes),
createdAt: match.createdAt, createdAt: match.createdAt,
endedAt: Value(match.endedAt),
), ),
mode: InsertMode.insertOrReplace, mode: InsertMode.insertOrReplace,
); );
@@ -166,6 +169,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
name: Value(match.name), name: Value(match.name),
notes: Value(match.notes), notes: Value(match.notes),
createdAt: match.createdAt, createdAt: match.createdAt,
endedAt: Value(match.endedAt),
), ),
) )
.toList(), .toList(),
@@ -346,6 +350,20 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
return rowsAffected > 0; return rowsAffected > 0;
} }
/// Updates the endedAt timestamp of the match with the given [matchId].
/// Pass null to remove the ended time (mark match as ongoing).
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
Future<bool> updateMatchEndedAt({
required String matchId,
required DateTime? endedAt,
}) 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 // TEMPORARY: Winner methods - these are stubs and do not persist data
// TODO: Implement proper winner handling // TODO: Implement proper winner handling

View File

@@ -1155,6 +1155,17 @@ class $MatchTableTable extends MatchTable
type: DriftSqlType.dateTime, type: DriftSqlType.dateTime,
requiredDuringInsert: true, requiredDuringInsert: true,
); );
static const VerificationMeta _endedAtMeta = const VerificationMeta(
'endedAt',
);
@override
late final GeneratedColumn<DateTime> endedAt = GeneratedColumn<DateTime>(
'ended_at',
aliasedName,
true,
type: DriftSqlType.dateTime,
requiredDuringInsert: false,
);
@override @override
List<GeneratedColumn> get $columns => [ List<GeneratedColumn> get $columns => [
id, id,
@@ -1163,6 +1174,7 @@ class $MatchTableTable extends MatchTable
name, name,
notes, notes,
createdAt, createdAt,
endedAt,
]; ];
@override @override
String get aliasedName => _alias ?? actualTableName; String get aliasedName => _alias ?? actualTableName;
@@ -1215,6 +1227,12 @@ class $MatchTableTable extends MatchTable
} else if (isInserting) { } else if (isInserting) {
context.missing(_createdAtMeta); context.missing(_createdAtMeta);
} }
if (data.containsKey('ended_at')) {
context.handle(
_endedAtMeta,
endedAt.isAcceptableOrUnknown(data['ended_at']!, _endedAtMeta),
);
}
return context; return context;
} }
@@ -1248,6 +1266,10 @@ class $MatchTableTable extends MatchTable
DriftSqlType.dateTime, DriftSqlType.dateTime,
data['${effectivePrefix}created_at'], data['${effectivePrefix}created_at'],
)!, )!,
endedAt: attachedDatabase.typeMapping.read(
DriftSqlType.dateTime,
data['${effectivePrefix}ended_at'],
),
); );
} }
@@ -1264,6 +1286,7 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
final String? name; final String? name;
final String? notes; final String? notes;
final DateTime createdAt; final DateTime createdAt;
final DateTime? endedAt;
const MatchTableData({ const MatchTableData({
required this.id, required this.id,
required this.gameId, required this.gameId,
@@ -1271,6 +1294,7 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
this.name, this.name,
this.notes, this.notes,
required this.createdAt, required this.createdAt,
this.endedAt,
}); });
@override @override
Map<String, Expression> toColumns(bool nullToAbsent) { Map<String, Expression> toColumns(bool nullToAbsent) {
@@ -1287,6 +1311,9 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
map['notes'] = Variable<String>(notes); map['notes'] = Variable<String>(notes);
} }
map['created_at'] = Variable<DateTime>(createdAt); map['created_at'] = Variable<DateTime>(createdAt);
if (!nullToAbsent || endedAt != null) {
map['ended_at'] = Variable<DateTime>(endedAt);
}
return map; return map;
} }
@@ -1302,6 +1329,9 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
? const Value.absent() ? const Value.absent()
: Value(notes), : Value(notes),
createdAt: Value(createdAt), createdAt: Value(createdAt),
endedAt: endedAt == null && nullToAbsent
? const Value.absent()
: Value(endedAt),
); );
} }
@@ -1317,6 +1347,7 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
name: serializer.fromJson<String?>(json['name']), name: serializer.fromJson<String?>(json['name']),
notes: serializer.fromJson<String?>(json['notes']), notes: serializer.fromJson<String?>(json['notes']),
createdAt: serializer.fromJson<DateTime>(json['createdAt']), createdAt: serializer.fromJson<DateTime>(json['createdAt']),
endedAt: serializer.fromJson<DateTime?>(json['endedAt']),
); );
} }
@override @override
@@ -1329,6 +1360,7 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
'name': serializer.toJson<String?>(name), 'name': serializer.toJson<String?>(name),
'notes': serializer.toJson<String?>(notes), 'notes': serializer.toJson<String?>(notes),
'createdAt': serializer.toJson<DateTime>(createdAt), 'createdAt': serializer.toJson<DateTime>(createdAt),
'endedAt': serializer.toJson<DateTime?>(endedAt),
}; };
} }
@@ -1339,6 +1371,7 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
Value<String?> name = const Value.absent(), Value<String?> name = const Value.absent(),
Value<String?> notes = const Value.absent(), Value<String?> notes = const Value.absent(),
DateTime? createdAt, DateTime? createdAt,
Value<DateTime?> endedAt = const Value.absent(),
}) => MatchTableData( }) => MatchTableData(
id: id ?? this.id, id: id ?? this.id,
gameId: gameId ?? this.gameId, gameId: gameId ?? this.gameId,
@@ -1346,6 +1379,7 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
name: name.present ? name.value : this.name, name: name.present ? name.value : this.name,
notes: notes.present ? notes.value : this.notes, notes: notes.present ? notes.value : this.notes,
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
endedAt: endedAt.present ? endedAt.value : this.endedAt,
); );
MatchTableData copyWithCompanion(MatchTableCompanion data) { MatchTableData copyWithCompanion(MatchTableCompanion data) {
return MatchTableData( return MatchTableData(
@@ -1355,6 +1389,7 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
name: data.name.present ? data.name.value : this.name, name: data.name.present ? data.name.value : this.name,
notes: data.notes.present ? data.notes.value : this.notes, notes: data.notes.present ? data.notes.value : this.notes,
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt, 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<MatchTableData> {
..write('groupId: $groupId, ') ..write('groupId: $groupId, ')
..write('name: $name, ') ..write('name: $name, ')
..write('notes: $notes, ') ..write('notes: $notes, ')
..write('createdAt: $createdAt') ..write('createdAt: $createdAt, ')
..write('endedAt: $endedAt')
..write(')')) ..write(')'))
.toString(); .toString();
} }
@override @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 @override
bool operator ==(Object other) => bool operator ==(Object other) =>
identical(this, other) || identical(this, other) ||
@@ -1382,7 +1419,8 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
other.groupId == this.groupId && other.groupId == this.groupId &&
other.name == this.name && other.name == this.name &&
other.notes == this.notes && other.notes == this.notes &&
other.createdAt == this.createdAt); other.createdAt == this.createdAt &&
other.endedAt == this.endedAt);
} }
class MatchTableCompanion extends UpdateCompanion<MatchTableData> { class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
@@ -1392,6 +1430,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
final Value<String?> name; final Value<String?> name;
final Value<String?> notes; final Value<String?> notes;
final Value<DateTime> createdAt; final Value<DateTime> createdAt;
final Value<DateTime?> endedAt;
final Value<int> rowid; final Value<int> rowid;
const MatchTableCompanion({ const MatchTableCompanion({
this.id = const Value.absent(), this.id = const Value.absent(),
@@ -1400,6 +1439,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
this.name = const Value.absent(), this.name = const Value.absent(),
this.notes = const Value.absent(), this.notes = const Value.absent(),
this.createdAt = const Value.absent(), this.createdAt = const Value.absent(),
this.endedAt = const Value.absent(),
this.rowid = const Value.absent(), this.rowid = const Value.absent(),
}); });
MatchTableCompanion.insert({ MatchTableCompanion.insert({
@@ -1409,6 +1449,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
this.name = const Value.absent(), this.name = const Value.absent(),
this.notes = const Value.absent(), this.notes = const Value.absent(),
required DateTime createdAt, required DateTime createdAt,
this.endedAt = const Value.absent(),
this.rowid = const Value.absent(), this.rowid = const Value.absent(),
}) : id = Value(id), }) : id = Value(id),
gameId = Value(gameId), gameId = Value(gameId),
@@ -1420,6 +1461,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
Expression<String>? name, Expression<String>? name,
Expression<String>? notes, Expression<String>? notes,
Expression<DateTime>? createdAt, Expression<DateTime>? createdAt,
Expression<DateTime>? endedAt,
Expression<int>? rowid, Expression<int>? rowid,
}) { }) {
return RawValuesInsertable({ return RawValuesInsertable({
@@ -1429,6 +1471,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
if (name != null) 'name': name, if (name != null) 'name': name,
if (notes != null) 'notes': notes, if (notes != null) 'notes': notes,
if (createdAt != null) 'created_at': createdAt, if (createdAt != null) 'created_at': createdAt,
if (endedAt != null) 'ended_at': endedAt,
if (rowid != null) 'rowid': rowid, if (rowid != null) 'rowid': rowid,
}); });
} }
@@ -1440,6 +1483,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
Value<String?>? name, Value<String?>? name,
Value<String?>? notes, Value<String?>? notes,
Value<DateTime>? createdAt, Value<DateTime>? createdAt,
Value<DateTime?>? endedAt,
Value<int>? rowid, Value<int>? rowid,
}) { }) {
return MatchTableCompanion( return MatchTableCompanion(
@@ -1449,6 +1493,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
name: name ?? this.name, name: name ?? this.name,
notes: notes ?? this.notes, notes: notes ?? this.notes,
createdAt: createdAt ?? this.createdAt, createdAt: createdAt ?? this.createdAt,
endedAt: endedAt ?? this.endedAt,
rowid: rowid ?? this.rowid, rowid: rowid ?? this.rowid,
); );
} }
@@ -1474,6 +1519,9 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
if (createdAt.present) { if (createdAt.present) {
map['created_at'] = Variable<DateTime>(createdAt.value); map['created_at'] = Variable<DateTime>(createdAt.value);
} }
if (endedAt.present) {
map['ended_at'] = Variable<DateTime>(endedAt.value);
}
if (rowid.present) { if (rowid.present) {
map['rowid'] = Variable<int>(rowid.value); map['rowid'] = Variable<int>(rowid.value);
} }
@@ -1489,6 +1537,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
..write('name: $name, ') ..write('name: $name, ')
..write('notes: $notes, ') ..write('notes: $notes, ')
..write('createdAt: $createdAt, ') ..write('createdAt: $createdAt, ')
..write('endedAt: $endedAt, ')
..write('rowid: $rowid') ..write('rowid: $rowid')
..write(')')) ..write(')'))
.toString(); .toString();
@@ -4005,6 +4054,7 @@ typedef $$MatchTableTableCreateCompanionBuilder =
Value<String?> name, Value<String?> name,
Value<String?> notes, Value<String?> notes,
required DateTime createdAt, required DateTime createdAt,
Value<DateTime?> endedAt,
Value<int> rowid, Value<int> rowid,
}); });
typedef $$MatchTableTableUpdateCompanionBuilder = typedef $$MatchTableTableUpdateCompanionBuilder =
@@ -4015,6 +4065,7 @@ typedef $$MatchTableTableUpdateCompanionBuilder =
Value<String?> name, Value<String?> name,
Value<String?> notes, Value<String?> notes,
Value<DateTime> createdAt, Value<DateTime> createdAt,
Value<DateTime?> endedAt,
Value<int> rowid, Value<int> rowid,
}); });
@@ -4129,6 +4180,11 @@ class $$MatchTableTableFilterComposer
builder: (column) => ColumnFilters(column), builder: (column) => ColumnFilters(column),
); );
ColumnFilters<DateTime> get endedAt => $composableBuilder(
column: $table.endedAt,
builder: (column) => ColumnFilters(column),
);
$$GameTableTableFilterComposer get gameId { $$GameTableTableFilterComposer get gameId {
final $$GameTableTableFilterComposer composer = $composerBuilder( final $$GameTableTableFilterComposer composer = $composerBuilder(
composer: this, composer: this,
@@ -4255,6 +4311,11 @@ class $$MatchTableTableOrderingComposer
builder: (column) => ColumnOrderings(column), builder: (column) => ColumnOrderings(column),
); );
ColumnOrderings<DateTime> get endedAt => $composableBuilder(
column: $table.endedAt,
builder: (column) => ColumnOrderings(column),
);
$$GameTableTableOrderingComposer get gameId { $$GameTableTableOrderingComposer get gameId {
final $$GameTableTableOrderingComposer composer = $composerBuilder( final $$GameTableTableOrderingComposer composer = $composerBuilder(
composer: this, composer: this,
@@ -4323,6 +4384,9 @@ class $$MatchTableTableAnnotationComposer
GeneratedColumn<DateTime> get createdAt => GeneratedColumn<DateTime> get createdAt =>
$composableBuilder(column: $table.createdAt, builder: (column) => column); $composableBuilder(column: $table.createdAt, builder: (column) => column);
GeneratedColumn<DateTime> get endedAt =>
$composableBuilder(column: $table.endedAt, builder: (column) => column);
$$GameTableTableAnnotationComposer get gameId { $$GameTableTableAnnotationComposer get gameId {
final $$GameTableTableAnnotationComposer composer = $composerBuilder( final $$GameTableTableAnnotationComposer composer = $composerBuilder(
composer: this, composer: this,
@@ -4459,6 +4523,7 @@ class $$MatchTableTableTableManager
Value<String?> name = const Value.absent(), Value<String?> name = const Value.absent(),
Value<String?> notes = const Value.absent(), Value<String?> notes = const Value.absent(),
Value<DateTime> createdAt = const Value.absent(), Value<DateTime> createdAt = const Value.absent(),
Value<DateTime?> endedAt = const Value.absent(),
Value<int> rowid = const Value.absent(), Value<int> rowid = const Value.absent(),
}) => MatchTableCompanion( }) => MatchTableCompanion(
id: id, id: id,
@@ -4467,6 +4532,7 @@ class $$MatchTableTableTableManager
name: name, name: name,
notes: notes, notes: notes,
createdAt: createdAt, createdAt: createdAt,
endedAt: endedAt,
rowid: rowid, rowid: rowid,
), ),
createCompanionCallback: createCompanionCallback:
@@ -4477,6 +4543,7 @@ class $$MatchTableTableTableManager
Value<String?> name = const Value.absent(), Value<String?> name = const Value.absent(),
Value<String?> notes = const Value.absent(), Value<String?> notes = const Value.absent(),
required DateTime createdAt, required DateTime createdAt,
Value<DateTime?> endedAt = const Value.absent(),
Value<int> rowid = const Value.absent(), Value<int> rowid = const Value.absent(),
}) => MatchTableCompanion.insert( }) => MatchTableCompanion.insert(
id: id, id: id,
@@ -4485,6 +4552,7 @@ class $$MatchTableTableTableManager
name: name, name: name,
notes: notes, notes: notes,
createdAt: createdAt, createdAt: createdAt,
endedAt: endedAt,
rowid: rowid, rowid: rowid,
), ),
withReferenceMapper: (p0) => p0 withReferenceMapper: (p0) => p0

View File

@@ -11,6 +11,7 @@ class MatchTable extends Table {
TextColumn get name => text().nullable()(); TextColumn get name => text().nullable()();
gelbeinhalb marked this conversation as resolved Outdated

Name ist sollte nicht nullable sein, der wird im Frontend doch gesetzt wenn man keinen eigenen eingibt

Name ist sollte nicht nullable sein, der wird im Frontend doch gesetzt wenn man keinen eigenen eingibt
TextColumn get notes => text().nullable()(); TextColumn get notes => text().nullable()();
gelbeinhalb marked this conversation as resolved Outdated

Hier auch nicht nullable, sondern empty string

Hier auch nicht nullable, sondern empty string
DateTimeColumn get createdAt => dateTime()(); DateTimeColumn get createdAt => dateTime()();
DateTimeColumn get endedAt => dateTime().nullable()();
@override @override
Set<Column<Object>> get primaryKey => {id}; Set<Column<Object>> get primaryKey => {id};

View File

@@ -8,6 +8,7 @@ import 'package:uuid/uuid.dart';
class Match { class Match {
final String id; final String id;
final DateTime createdAt; final DateTime createdAt;
final DateTime? endedAt;
gelbeinhalb marked this conversation as resolved Outdated

Game nicht optional sondern required

Game nicht optional sondern required
final String name; final String name;
final Game game; final Game game;
gelbeinhalb marked this conversation as resolved Outdated

Spielerliste auch nicht optional

Spielerliste auch nicht optional
final Group? group; final Group? group;
@@ -18,6 +19,7 @@ class Match {
Match({ Match({
String? id, String? id,
DateTime? createdAt, DateTime? createdAt,
this.endedAt,
required this.name, required this.name,
required this.game, required this.game,
this.group, this.group,
@@ -29,7 +31,7 @@ class Match {
@override @override
String toString() { 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). /// Creates a Match instance from a JSON object (ID references format).
@@ -37,6 +39,7 @@ class Match {
Match.fromJson(Map<String, dynamic> json) Match.fromJson(Map<String, dynamic> json)
: id = json['id'], : id = json['id'],
createdAt = DateTime.parse(json['createdAt']), createdAt = DateTime.parse(json['createdAt']),
endedAt = json['endedAt'] != null ? DateTime.parse(json['endedAt']) : null,
name = json['name'], 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: '', icon: ''), // Populated during import via DataTransferService
group = null, // Populated during import via DataTransferService group = null, // Populated during import via DataTransferService
@@ -47,6 +50,7 @@ class Match {
Map<String, dynamic> toJson() => { Map<String, dynamic> toJson() => {
'id': id, 'id': id,
'createdAt': createdAt.toIso8601String(), 'createdAt': createdAt.toIso8601String(),
'endedAt': endedAt?.toIso8601String(),
'name': name, 'name': name,
'gameId': game.id, 'gameId': game.id,
'groupId': group?.id, 'groupId': group?.id,

View File

@@ -61,6 +61,7 @@ class DataTransferService {
'id': m.id, 'id': m.id,
'name': m.name, 'name': m.name,
'createdAt': m.createdAt.toIso8601String(), 'createdAt': m.createdAt.toIso8601String(),
'endedAt': m.endedAt?.toIso8601String(),
'gameId': m.game.id, 'gameId': m.game.id,
'groupId': m.group?.id, 'groupId': m.group?.id,
'playerIds': (m.players ?? []).map((p) => p.id).toList(), 'playerIds': (m.players ?? []).map((p) => p.id).toList(),
@@ -195,6 +196,7 @@ class DataTransferService {
final String gameId = map['gameId'] as String; final String gameId = map['gameId'] as String;
final String? groupId = map['groupId'] as String?; final String? groupId = map['groupId'] as String?;
final List<String> playerIds = (map['playerIds'] as List<dynamic>? ?? []).cast<String>(); final List<String> playerIds = (map['playerIds'] as List<dynamic>? ?? []).cast<String>();
final DateTime? endedAt = map['endedAt'] != null ? DateTime.parse(map['endedAt'] as String) : null;
final game = gameById[gameId]; final game = gameById[gameId];
final group = (groupId == null) ? null : groupById[groupId]; final group = (groupId == null) ? null : groupById[groupId];
@@ -210,6 +212,7 @@ class DataTransferService {
group: group, group: group,
players: players.isNotEmpty ? players : null, players: players.isNotEmpty ? players : null,
createdAt: DateTime.parse(map['createdAt'] as String), createdAt: DateTime.parse(map['createdAt'] as String),
endedAt: endedAt,
notes: map['notes'] as String? ?? '', notes: map['notes'] as String? ?? '',
); );
}).toList(); }).toList();