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": {
"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": {
"type": "string"
},

View File

@@ -38,6 +38,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
players: players,
notes: row.notes ?? '',
createdAt: row.createdAt,
endedAt: row.endedAt,
);
}),
);
@@ -68,6 +69,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> with _$MatchDaoMixin {
players: players,
notes: result.notes ?? '',
createdAt: result.createdAt,
endedAt: result.endedAt,
);
}
@@ -84,6 +86,7 @@ class MatchDao extends DatabaseAccessor<AppDatabase> 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<AppDatabase> 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<AppDatabase> 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<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
// TODO: Implement proper winner handling

View File

@@ -1155,6 +1155,17 @@ class $MatchTableTable extends MatchTable
type: DriftSqlType.dateTime,
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
List<GeneratedColumn> 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<MatchTableData> {
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<MatchTableData> {
this.name,
this.notes,
required this.createdAt,
this.endedAt,
});
@override
Map<String, Expression> toColumns(bool nullToAbsent) {
@@ -1287,6 +1311,9 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
map['notes'] = Variable<String>(notes);
}
map['created_at'] = Variable<DateTime>(createdAt);
if (!nullToAbsent || endedAt != null) {
map['ended_at'] = Variable<DateTime>(endedAt);
}
return map;
}
@@ -1302,6 +1329,9 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
? 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<MatchTableData> {
name: serializer.fromJson<String?>(json['name']),
notes: serializer.fromJson<String?>(json['notes']),
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
endedAt: serializer.fromJson<DateTime?>(json['endedAt']),
);
}
@override
@@ -1329,6 +1360,7 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
'name': serializer.toJson<String?>(name),
'notes': serializer.toJson<String?>(notes),
'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?> notes = const Value.absent(),
DateTime? createdAt,
Value<DateTime?> endedAt = const Value.absent(),
}) => MatchTableData(
id: id ?? this.id,
gameId: gameId ?? this.gameId,
@@ -1346,6 +1379,7 @@ class MatchTableData extends DataClass implements Insertable<MatchTableData> {
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<MatchTableData> {
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<MatchTableData> {
..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<MatchTableData> {
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<MatchTableData> {
@@ -1392,6 +1430,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
final Value<String?> name;
final Value<String?> notes;
final Value<DateTime> createdAt;
final Value<DateTime?> endedAt;
final Value<int> rowid;
const MatchTableCompanion({
this.id = const Value.absent(),
@@ -1400,6 +1439,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
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<MatchTableData> {
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<MatchTableData> {
Expression<String>? name,
Expression<String>? notes,
Expression<DateTime>? createdAt,
Expression<DateTime>? endedAt,
Expression<int>? rowid,
}) {
return RawValuesInsertable({
@@ -1429,6 +1471,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
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<MatchTableData> {
Value<String?>? name,
Value<String?>? notes,
Value<DateTime>? createdAt,
Value<DateTime?>? endedAt,
Value<int>? rowid,
}) {
return MatchTableCompanion(
@@ -1449,6 +1493,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
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<MatchTableData> {
if (createdAt.present) {
map['created_at'] = Variable<DateTime>(createdAt.value);
}
if (endedAt.present) {
map['ended_at'] = Variable<DateTime>(endedAt.value);
}
if (rowid.present) {
map['rowid'] = Variable<int>(rowid.value);
}
@@ -1489,6 +1537,7 @@ class MatchTableCompanion extends UpdateCompanion<MatchTableData> {
..write('name: $name, ')
..write('notes: $notes, ')
..write('createdAt: $createdAt, ')
..write('endedAt: $endedAt, ')
..write('rowid: $rowid')
..write(')'))
.toString();
@@ -4005,6 +4054,7 @@ typedef $$MatchTableTableCreateCompanionBuilder =
Value<String?> name,
Value<String?> notes,
required DateTime createdAt,
Value<DateTime?> endedAt,
Value<int> rowid,
});
typedef $$MatchTableTableUpdateCompanionBuilder =
@@ -4015,6 +4065,7 @@ typedef $$MatchTableTableUpdateCompanionBuilder =
Value<String?> name,
Value<String?> notes,
Value<DateTime> createdAt,
Value<DateTime?> endedAt,
Value<int> rowid,
});
@@ -4129,6 +4180,11 @@ class $$MatchTableTableFilterComposer
builder: (column) => ColumnFilters(column),
);
ColumnFilters<DateTime> 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<DateTime> 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<DateTime> get createdAt =>
$composableBuilder(column: $table.createdAt, builder: (column) => column);
GeneratedColumn<DateTime> 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<String?> name = const Value.absent(),
Value<String?> notes = const Value.absent(),
Value<DateTime> createdAt = const Value.absent(),
Value<DateTime?> endedAt = const Value.absent(),
Value<int> 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<String?> name = const Value.absent(),
Value<String?> notes = const Value.absent(),
required DateTime createdAt,
Value<DateTime?> endedAt = const Value.absent(),
Value<int> 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

View File

@@ -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<Column<Object>> get primaryKey => {id};

View File

@@ -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<String, dynamic> 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<String, dynamic> toJson() => {
'id': id,
'createdAt': createdAt.toIso8601String(),
'endedAt': endedAt?.toIso8601String(),
'name': name,
'gameId': game.id,
'groupId': group?.id,

View File

@@ -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<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 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();