diff --git a/lib/data/dao/team_dao.dart b/lib/data/dao/team_dao.dart index cb61e63..e6a1a0c 100644 --- a/lib/data/dao/team_dao.dart +++ b/lib/data/dao/team_dao.dart @@ -4,6 +4,7 @@ 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/models/player.dart'; +import 'package:tallee/data/models/score_entry.dart'; import 'package:tallee/data/models/team.dart'; part 'team_dao.g.dart'; @@ -186,15 +187,42 @@ class TeamDao extends DatabaseAccessor with _$TeamDaoMixin { /// Updates the score of the team with the given [teamId]. Future updateTeamScore({ required String teamId, + required String matchId, required int score, }) async { + await (update(teamTable)..where((t) => t.id.equals(teamId))).write( + const TeamTableCompanion(score: Value(null)), + ); + await db.scoreEntryDao.deleteAllScoresForMatch(matchId: matchId); + final rowsAffected = await (update(teamTable)..where((t) => t.id.equals(teamId))).write( TeamTableCompanion(score: Value(score)), ); + + final members = await _getTeamMembers(teamId: teamId); + for (final member in members) { + await db.scoreEntryDao.updateScore( + playerId: member.id, + matchId: matchId, + entry: ScoreEntry(score: score), + ); + } + return rowsAffected > 0; } + Future removeScoreForTeam({ + required String teamId, + required String matchId, + }) async { + await (update(teamTable)..where((t) => t.id.equals(teamId))).write( + const TeamTableCompanion(score: Value(null)), + ); + await db.scoreEntryDao.deleteAllScoresForMatch(matchId: matchId); + return true; + } + /* Delete */ /// Deletes all teams from the database. @@ -212,4 +240,50 @@ class TeamDao extends DatabaseAccessor with _$TeamDaoMixin { final rowsAffected = await query.go(); return rowsAffected > 0; } + + /* Score handling */ + + Future setWinnerTeam({ + required String teamId, + required String matchId, + }) async { + return await updateTeamScore(teamId: teamId, matchId: matchId, score: 1); + } + + Future removeWinnerTeam({ + required String teamId, + required String matchId, + }) async { + return await removeScoreForTeam(teamId: teamId, matchId: matchId); + } + + Future setLoserTeam({ + required String teamId, + required String matchId, + }) async { + return await updateTeamScore(teamId: teamId, matchId: matchId, score: 0); + } + + Future removeLoserTeam({ + required String teamId, + required String matchId, + }) async { + return await removeScoreForTeam(teamId: teamId, matchId: matchId); + } + + Future setTeamPlacements({ + required String teamId, + required String matchId, + required List teams, + }) async { + List success = List.generate(teams.length, (index) => null); + for (int i = 0; i < teams.length; i++) { + success[i] = await updateTeamScore( + matchId: matchId, + teamId: teams[i].id, + score: teams.length - i, + ); + } + return success.every((result) => result == true); + } } diff --git a/lib/data/db/database.g.dart b/lib/data/db/database.g.dart index 5827dfb..831aa92 100644 --- a/lib/data/db/database.g.dart +++ b/lib/data/db/database.g.dart @@ -1930,10 +1930,9 @@ class $TeamTableTable extends TeamTable late final GeneratedColumn score = GeneratedColumn( 'score', aliasedName, - false, + true, type: DriftSqlType.int, requiredDuringInsert: false, - defaultValue: const Constant(0), ); @override List get $columns => [id, name, createdAt, color, score]; @@ -2010,7 +2009,7 @@ class $TeamTableTable extends TeamTable score: attachedDatabase.typeMapping.read( DriftSqlType.int, data['${effectivePrefix}score'], - )!, + ), ); } @@ -2025,13 +2024,13 @@ class TeamTableData extends DataClass implements Insertable { final String name; final DateTime createdAt; final String color; - final int score; + final int? score; const TeamTableData({ required this.id, required this.name, required this.createdAt, required this.color, - required this.score, + this.score, }); @override Map toColumns(bool nullToAbsent) { @@ -2040,7 +2039,9 @@ class TeamTableData extends DataClass implements Insertable { map['name'] = Variable(name); map['created_at'] = Variable(createdAt); map['color'] = Variable(color); - map['score'] = Variable(score); + if (!nullToAbsent || score != null) { + map['score'] = Variable(score); + } return map; } @@ -2050,7 +2051,9 @@ class TeamTableData extends DataClass implements Insertable { name: Value(name), createdAt: Value(createdAt), color: Value(color), - score: Value(score), + score: score == null && nullToAbsent + ? const Value.absent() + : Value(score), ); } @@ -2064,7 +2067,7 @@ class TeamTableData extends DataClass implements Insertable { name: serializer.fromJson(json['name']), createdAt: serializer.fromJson(json['createdAt']), color: serializer.fromJson(json['color']), - score: serializer.fromJson(json['score']), + score: serializer.fromJson(json['score']), ); } @override @@ -2075,7 +2078,7 @@ class TeamTableData extends DataClass implements Insertable { 'name': serializer.toJson(name), 'createdAt': serializer.toJson(createdAt), 'color': serializer.toJson(color), - 'score': serializer.toJson(score), + 'score': serializer.toJson(score), }; } @@ -2084,13 +2087,13 @@ class TeamTableData extends DataClass implements Insertable { String? name, DateTime? createdAt, String? color, - int? score, + Value score = const Value.absent(), }) => TeamTableData( id: id ?? this.id, name: name ?? this.name, createdAt: createdAt ?? this.createdAt, color: color ?? this.color, - score: score ?? this.score, + score: score.present ? score.value : this.score, ); TeamTableData copyWithCompanion(TeamTableCompanion data) { return TeamTableData( @@ -2132,7 +2135,7 @@ class TeamTableCompanion extends UpdateCompanion { final Value name; final Value createdAt; final Value color; - final Value score; + final Value score; final Value rowid; const TeamTableCompanion({ this.id = const Value.absent(), @@ -2175,7 +2178,7 @@ class TeamTableCompanion extends UpdateCompanion { Value? name, Value? createdAt, Value? color, - Value? score, + Value? score, Value? rowid, }) { return TeamTableCompanion( @@ -5279,7 +5282,7 @@ typedef $$TeamTableTableCreateCompanionBuilder = required String name, required DateTime createdAt, Value color, - Value score, + Value score, Value rowid, }); typedef $$TeamTableTableUpdateCompanionBuilder = @@ -5288,7 +5291,7 @@ typedef $$TeamTableTableUpdateCompanionBuilder = Value name, Value createdAt, Value color, - Value score, + Value score, Value rowid, }); @@ -5497,7 +5500,7 @@ class $$TeamTableTableTableManager Value name = const Value.absent(), Value createdAt = const Value.absent(), Value color = const Value.absent(), - Value score = const Value.absent(), + Value score = const Value.absent(), Value rowid = const Value.absent(), }) => TeamTableCompanion( id: id, @@ -5513,7 +5516,7 @@ class $$TeamTableTableTableManager required String name, required DateTime createdAt, Value color = const Value.absent(), - Value score = const Value.absent(), + Value score = const Value.absent(), Value rowid = const Value.absent(), }) => TeamTableCompanion.insert( id: id, diff --git a/lib/data/db/tables/team_table.dart b/lib/data/db/tables/team_table.dart index 4f6ce21..e706381 100644 --- a/lib/data/db/tables/team_table.dart +++ b/lib/data/db/tables/team_table.dart @@ -5,7 +5,7 @@ class TeamTable extends Table { TextColumn get name => text()(); DateTimeColumn get createdAt => dateTime()(); TextColumn get color => text().withDefault(const Constant('blue'))(); - IntColumn get score => integer().withDefault(const Constant(0))(); + IntColumn get score => integer().nullable()(); @override Set> get primaryKey => {id}; diff --git a/lib/data/models/match.dart b/lib/data/models/match.dart index 895070f..f7c81a2 100644 --- a/lib/data/models/match.dart +++ b/lib/data/models/match.dart @@ -231,8 +231,13 @@ class Match { } List _getHighestScoreTeam() { + if (teams!.every((team) => team.score == null)) { + return []; + } + final int highestScore = teams! .map((team) => team.score) + .whereType() .reduce((max, score) => score > max ? score : max); return teams!.where((team) { @@ -241,8 +246,13 @@ class Match { } List _getLowestScoreTeam() { + if (teams!.every((team) => team.score == null)) { + return []; + } + final int lowestScore = teams! .map((team) => team.score) + .whereType() .reduce((min, score) => score < min ? score : min); return teams!.where((team) { diff --git a/lib/data/models/team.dart b/lib/data/models/team.dart index ac82425..aa78df7 100644 --- a/lib/data/models/team.dart +++ b/lib/data/models/team.dart @@ -9,7 +9,7 @@ class Team { final String name; final DateTime createdAt; final GameColor color; - final int score; + final int? score; final List members; Team({ @@ -17,7 +17,7 @@ class Team { required this.name, DateTime? createdAt, this.color = GameColor.blue, - this.score = 0, + this.score, required this.members, }) : id = id ?? const Uuid().v4(), createdAt = createdAt ?? clock.now(); 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 8a9ed02..296a9ef 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 @@ -198,20 +198,7 @@ class _MatchResultViewState extends State { } void initializeAsTeamMatch() { - allTeams = - widget.match.teams ?? - List.generate( - 4, - (index) => Team( - name: 'Team ${index + 1}', - members: [ - Player(name: 'Player ${index + 1}'), - Player(name: 'Player ${index + 2}'), - Player(name: 'Player ${index + 3}'), - Player(name: 'Player ${index + 4}'), - ], - ), - ); + allTeams = widget.match.teams ?? []; allTeams.sort((a, b) => a.name.compareTo(b.name)); controller = List.generate( @@ -220,7 +207,26 @@ class _MatchResultViewState extends State { ); // Prefill fields - //TODO + if (widget.match.mvt.isNotEmpty) { + if (rulesetSupportsWinnerSelection()) { + _selectedTeam = allTeams.firstWhere( + (p) => p.id == widget.match.mvt.first.id, + ); + } else if (rulesetSupportsScoreEntry()) { + for (int i = 0; i < allTeams.length; i++) { + final score = allTeams[i].score; + controller[i].text = score.toString(); + } + } else if (rulesetSupportsPlacement()) { + allTeams.sort((a, b) { + final scoreA = + allTeams.where((team) => a.id == team.id).first.score ?? 0; + final scoreB = + allTeams.where((team) => b.id == team.id).first.score ?? 0; + return scoreB.compareTo(scoreA); + }); + } + } } void inizializeAsNormalMatch() { @@ -282,41 +288,84 @@ class _MatchResultViewState extends State { /// Handles saving or removing the winner in the database. Future _handleWinner() async { - if (_selectedPlayer == null) { - return await db.scoreEntryDao.removeWinner(matchId: widget.match.id); + if (isTeamMatch) { + if (_selectedTeam == null) { + return await db.teamDao.setWinnerTeam( + matchId: widget.match.id, + teamId: _selectedTeam!.id, + ); + } else { + return await db.teamDao.setLoserTeam( + matchId: widget.match.id, + teamId: _selectedTeam!.id, + ); + } } else { - return await db.scoreEntryDao.setWinner( - matchId: widget.match.id, - playerId: _selectedPlayer!.id, - ); + if (_selectedPlayer == null) { + return await db.scoreEntryDao.removeWinner(matchId: widget.match.id); + } else { + return await db.scoreEntryDao.setWinner( + matchId: widget.match.id, + playerId: _selectedPlayer!.id, + ); + } } } /// Handles saving or removing the loser in the database. Future _handleLoser() async { - if (_selectedPlayer == null) { - return await db.scoreEntryDao.removeLoser(matchId: widget.match.id); + if (isTeamMatch) { + if (_selectedTeam == null) { + return await db.teamDao.removeLoserTeam( + matchId: widget.match.id, + teamId: _selectedTeam!.id, + ); + } else { + return await db.teamDao.setLoserTeam( + matchId: widget.match.id, + teamId: _selectedTeam!.id, + ); + } } else { - return await db.scoreEntryDao.setLoser( - matchId: widget.match.id, - playerId: _selectedPlayer!.id, - ); + if (_selectedPlayer == null) { + return await db.scoreEntryDao.removeLoser(matchId: widget.match.id); + } else { + return await db.scoreEntryDao.setLoser( + matchId: widget.match.id, + playerId: _selectedPlayer!.id, + ); + } } } /// Handles saving the scores for each player in the database. Future _handleScores() async { - for (int i = 0; i < allPlayers.length; i++) { - var text = controller[i].text; - if (text.isEmpty) { - text = '0'; + if (isTeamMatch) { + for (int i = 0; i < allTeams.length; i++) { + var text = controller[i].text; + if (text.isEmpty) { + text = '0'; + } + final score = int.parse(text); + await db.teamDao.updateTeamScore( + matchId: widget.match.id, + teamId: allTeams[i].id, + score: score, + ); + } + } else { + for (int i = 0; i < allPlayers.length; i++) { + var text = controller[i].text; + if (text.isEmpty) { + text = '0'; + } + final score = int.parse(text); + await db.scoreEntryDao.addScore( + matchId: widget.match.id, + playerId: allPlayers[i].id, + entry: ScoreEntry(roundNumber: 0, score: score, change: 0), + ); } - final score = int.parse(text); - await db.scoreEntryDao.addScore( - matchId: widget.match.id, - playerId: allPlayers[i].id, - entry: ScoreEntry(roundNumber: 0, score: score, change: 0), - ); } } diff --git a/pubspec.yaml b/pubspec.yaml index 14c7853..91bc4e4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: tallee description: "Tracking App for Card Games" publish_to: 'none' -version: 0.0.30+281 +version: 0.0.30+285 environment: sdk: ^3.8.1