Merge branch 'development' into feature/132-verschiedene-regelsaetze-implementieren
# Conflicts: # lib/core/common.dart # lib/presentation/views/main_menu/statistics_view.dart # lib/presentation/widgets/player_selection.dart
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
import 'package:flutter/cupertino.dart';
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:tallee/core/enums.dart';
|
import 'package:tallee/core/enums.dart';
|
||||||
import 'package:tallee/data/models/match.dart';
|
import 'package:tallee/data/models/match.dart';
|
||||||
|
import 'package:tallee/data/models/player.dart';
|
||||||
import 'package:tallee/l10n/generated/app_localizations.dart';
|
import 'package:tallee/l10n/generated/app_localizations.dart';
|
||||||
|
|
||||||
/// Translates a [Ruleset] enum value to its corresponding localized string.
|
/// Translates a [Ruleset] enum value to its corresponding localized string.
|
||||||
@@ -44,6 +45,13 @@ String getExtraPlayerCount(Match match) {
|
|||||||
return ' + ${count.toString()}';
|
return ' + ${count.toString()}';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String getNameCountText(Player player) {
|
||||||
|
if (player.nameCount >= 1) {
|
||||||
|
return ' #${player.nameCount}';
|
||||||
|
}
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
String getPointLabel(AppLocalizations loc, int points) {
|
String getPointLabel(AppLocalizations loc, int points) {
|
||||||
if (points == 1) {
|
if (points == 1) {
|
||||||
return '$points ${loc.point}';
|
return '$points ${loc.point}';
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
import 'package:tallee/data/db/database.dart';
|
import 'package:tallee/data/db/database.dart';
|
||||||
import 'package:tallee/data/db/tables/player_table.dart';
|
import 'package:tallee/data/db/tables/player_table.dart';
|
||||||
import 'package:tallee/data/models/player.dart';
|
import 'package:tallee/data/models/player.dart';
|
||||||
@@ -20,6 +21,7 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
|
|||||||
name: row.name,
|
name: row.name,
|
||||||
description: row.description,
|
description: row.description,
|
||||||
createdAt: row.createdAt,
|
createdAt: row.createdAt,
|
||||||
|
nameCount: row.nameCount,
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
@@ -34,6 +36,7 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
|
|||||||
name: result.name,
|
name: result.name,
|
||||||
description: result.description,
|
description: result.description,
|
||||||
createdAt: result.createdAt,
|
createdAt: result.createdAt,
|
||||||
|
nameCount: result.nameCount,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,12 +45,15 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
|
|||||||
/// the new one.
|
/// the new one.
|
||||||
Future<bool> addPlayer({required Player player}) async {
|
Future<bool> addPlayer({required Player player}) async {
|
||||||
if (!await playerExists(playerId: player.id)) {
|
if (!await playerExists(playerId: player.id)) {
|
||||||
|
final int nameCount = await calculateNameCount(name: player.name);
|
||||||
|
|
||||||
await into(playerTable).insert(
|
await into(playerTable).insert(
|
||||||
PlayerTableCompanion.insert(
|
PlayerTableCompanion.insert(
|
||||||
id: player.id,
|
id: player.id,
|
||||||
name: player.name,
|
name: player.name,
|
||||||
description: player.description,
|
description: player.description,
|
||||||
createdAt: player.createdAt,
|
createdAt: player.createdAt,
|
||||||
|
nameCount: Value(nameCount),
|
||||||
),
|
),
|
||||||
mode: InsertMode.insertOrReplace,
|
mode: InsertMode.insertOrReplace,
|
||||||
);
|
);
|
||||||
@@ -62,20 +68,67 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
|
|||||||
Future<bool> addPlayersAsList({required List<Player> players}) async {
|
Future<bool> addPlayersAsList({required List<Player> players}) async {
|
||||||
if (players.isEmpty) return false;
|
if (players.isEmpty) return false;
|
||||||
|
|
||||||
await db.batch(
|
// Filter out players that already exist
|
||||||
(b) => b.insertAll(
|
final newPlayers = <Player>[];
|
||||||
playerTable,
|
for (final player in players) {
|
||||||
players
|
if (!await playerExists(playerId: player.id)) {
|
||||||
.map(
|
newPlayers.add(player);
|
||||||
(player) => PlayerTableCompanion.insert(
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newPlayers.isEmpty) return false;
|
||||||
|
|
||||||
|
// Group players by name
|
||||||
|
final nameGroups = <String, List<Player>>{};
|
||||||
|
for (final player in newPlayers) {
|
||||||
|
nameGroups.putIfAbsent(player.name, () => []).add(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
final playersToInsert = <PlayerTableCompanion>[];
|
||||||
|
|
||||||
|
// Process each group of players with the same name
|
||||||
|
for (final entry in nameGroups.entries) {
|
||||||
|
final name = entry.key;
|
||||||
|
final playersWithName = entry.value;
|
||||||
|
|
||||||
|
// Get the current nameCount
|
||||||
|
var nameCount = await calculateNameCount(name: name);
|
||||||
|
|
||||||
|
// One player with the same name
|
||||||
|
if (playersWithName.length == 1) {
|
||||||
|
final player = playersWithName[0];
|
||||||
|
playersToInsert.add(
|
||||||
|
PlayerTableCompanion.insert(
|
||||||
id: player.id,
|
id: player.id,
|
||||||
name: player.name,
|
name: player.name,
|
||||||
description: player.description,
|
description: player.description,
|
||||||
createdAt: player.createdAt,
|
createdAt: player.createdAt,
|
||||||
|
nameCount: Value(nameCount),
|
||||||
),
|
),
|
||||||
)
|
);
|
||||||
.toList(),
|
} else {
|
||||||
mode: InsertMode.insertOrIgnore,
|
if (nameCount == 0) nameCount++;
|
||||||
|
// Multiple players with the same name
|
||||||
|
for (var i = 0; i < playersWithName.length; i++) {
|
||||||
|
final player = playersWithName[i];
|
||||||
|
playersToInsert.add(
|
||||||
|
PlayerTableCompanion.insert(
|
||||||
|
id: player.id,
|
||||||
|
name: player.name,
|
||||||
|
description: player.description,
|
||||||
|
createdAt: player.createdAt,
|
||||||
|
nameCount: Value(nameCount + i),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
await db.batch(
|
||||||
|
(b) => b.insertAll(
|
||||||
|
playerTable,
|
||||||
|
playersToInsert,
|
||||||
|
mode: InsertMode.insertOrReplace,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -90,7 +143,7 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
|
|||||||
return rowsAffected > 0;
|
return rowsAffected > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if a player with the given [id] exists in the database.
|
/// Checks if a player with the given [playerId] exists in the database.
|
||||||
/// Returns `true` if the player exists, `false` otherwise.
|
/// Returns `true` if the player exists, `false` otherwise.
|
||||||
Future<bool> playerExists({required String playerId}) async {
|
Future<bool> playerExists({required String playerId}) async {
|
||||||
final query = select(playerTable)..where((p) => p.id.equals(playerId));
|
final query = select(playerTable)..where((p) => p.id.equals(playerId));
|
||||||
@@ -103,9 +156,38 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
|
|||||||
required String playerId,
|
required String playerId,
|
||||||
required String newName,
|
required String newName,
|
||||||
}) async {
|
}) async {
|
||||||
|
// Get previous name and name count for the player before updating
|
||||||
|
final previousPlayerName =
|
||||||
|
await (select(playerTable)..where((p) => p.id.equals(playerId)))
|
||||||
|
.map((row) => row.name)
|
||||||
|
.getSingleOrNull() ??
|
||||||
|
'';
|
||||||
|
final previousNameCount = await getNameCount(name: previousPlayerName);
|
||||||
|
|
||||||
await (update(playerTable)..where((p) => p.id.equals(playerId))).write(
|
await (update(playerTable)..where((p) => p.id.equals(playerId))).write(
|
||||||
PlayerTableCompanion(name: Value(newName)),
|
PlayerTableCompanion(name: Value(newName)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Update name count for the new name
|
||||||
|
final count = await calculateNameCount(name: newName);
|
||||||
|
if (count > 0) {
|
||||||
|
await (update(playerTable)..where((p) => p.name.equals(newName))).write(
|
||||||
|
PlayerTableCompanion(nameCount: Value(count)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (previousNameCount > 0) {
|
||||||
|
// Get the player with that name and the hightest nameCount, and update their nameCount to previousNameCount
|
||||||
|
final player = await getPlayerWithHighestNameCount(
|
||||||
|
name: previousPlayerName,
|
||||||
|
);
|
||||||
|
if (player != null) {
|
||||||
|
await updateNameCount(
|
||||||
|
playerId: player.id,
|
||||||
|
nameCount: previousNameCount,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Retrieves the total count of players in the database.
|
/// Retrieves the total count of players in the database.
|
||||||
@@ -117,6 +199,76 @@ class PlayerDao extends DatabaseAccessor<AppDatabase> with _$PlayerDaoMixin {
|
|||||||
return count ?? 0;
|
return count ?? 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves the count of players with the given [name].
|
||||||
|
Future<int> getNameCount({required String name}) async {
|
||||||
|
final query = select(playerTable)..where((p) => p.name.equals(name));
|
||||||
|
final result = await query.get();
|
||||||
|
return result.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Updates the nameCount for the player with the given [playerId] to [nameCount].
|
||||||
|
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
||||||
|
Future<bool> updateNameCount({
|
||||||
|
required String playerId,
|
||||||
|
required int nameCount,
|
||||||
|
}) async {
|
||||||
|
final query = update(playerTable)..where((p) => p.id.equals(playerId));
|
||||||
|
final rowsAffected = await query.write(
|
||||||
|
PlayerTableCompanion(nameCount: Value(nameCount)),
|
||||||
|
);
|
||||||
|
return rowsAffected > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@visibleForTesting
|
||||||
|
Future<Player?> getPlayerWithHighestNameCount({required String name}) async {
|
||||||
|
final query = select(playerTable)
|
||||||
|
..where((p) => p.name.equals(name))
|
||||||
|
..orderBy([(p) => OrderingTerm.desc(p.nameCount)])
|
||||||
|
..limit(1);
|
||||||
|
final result = await query.getSingleOrNull();
|
||||||
|
if (result != null) {
|
||||||
|
return Player(
|
||||||
|
id: result.id,
|
||||||
|
name: result.name,
|
||||||
|
description: result.description,
|
||||||
|
createdAt: result.createdAt,
|
||||||
|
nameCount: result.nameCount,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@visibleForTesting
|
||||||
|
Future<int> calculateNameCount({required String name}) async {
|
||||||
|
final count = await getNameCount(name: name);
|
||||||
|
final int nameCount;
|
||||||
|
|
||||||
|
if (count == 1) {
|
||||||
|
// If one other player exists with the same name, initialize the nameCount
|
||||||
|
await initializeNameCount(name: name);
|
||||||
|
// And for the new player, set nameCount to 2
|
||||||
|
nameCount = 2;
|
||||||
|
} else if (count > 1) {
|
||||||
|
// If more than one player exists with the same name, just increment
|
||||||
|
// the nameCount for the new player
|
||||||
|
nameCount = count + 1;
|
||||||
|
} else {
|
||||||
|
// If no other players exist with the same name, set nameCount to 0
|
||||||
|
nameCount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nameCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
@visibleForTesting
|
||||||
|
Future<bool> initializeNameCount({required String name}) async {
|
||||||
|
final rowsAffected =
|
||||||
|
await (update(playerTable)..where((p) => p.name.equals(name))).write(
|
||||||
|
const PlayerTableCompanion(nameCount: Value(1)),
|
||||||
|
);
|
||||||
|
return rowsAffected > 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// Deletes all players from the database.
|
/// Deletes all players from the database.
|
||||||
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
/// Returns `true` if more than 0 rows were affected, otherwise `false`.
|
||||||
Future<bool> deleteAllPlayers() async {
|
Future<bool> deleteAllPlayers() async {
|
||||||
|
|||||||
@@ -18,6 +18,17 @@ class $PlayerTableTable extends PlayerTable
|
|||||||
type: DriftSqlType.string,
|
type: DriftSqlType.string,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
);
|
);
|
||||||
|
static const VerificationMeta _createdAtMeta = const VerificationMeta(
|
||||||
|
'createdAt',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<DateTime> createdAt = GeneratedColumn<DateTime>(
|
||||||
|
'created_at',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: DriftSqlType.dateTime,
|
||||||
|
requiredDuringInsert: true,
|
||||||
|
);
|
||||||
static const VerificationMeta _nameMeta = const VerificationMeta('name');
|
static const VerificationMeta _nameMeta = const VerificationMeta('name');
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumn<String> name = GeneratedColumn<String>(
|
late final GeneratedColumn<String> name = GeneratedColumn<String>(
|
||||||
@@ -27,6 +38,18 @@ class $PlayerTableTable extends PlayerTable
|
|||||||
type: DriftSqlType.string,
|
type: DriftSqlType.string,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
);
|
);
|
||||||
|
static const VerificationMeta _nameCountMeta = const VerificationMeta(
|
||||||
|
'nameCount',
|
||||||
|
);
|
||||||
|
@override
|
||||||
|
late final GeneratedColumn<int> nameCount = GeneratedColumn<int>(
|
||||||
|
'name_count',
|
||||||
|
aliasedName,
|
||||||
|
false,
|
||||||
|
type: DriftSqlType.int,
|
||||||
|
requiredDuringInsert: false,
|
||||||
|
defaultValue: const Constant(0),
|
||||||
|
);
|
||||||
static const VerificationMeta _descriptionMeta = const VerificationMeta(
|
static const VerificationMeta _descriptionMeta = const VerificationMeta(
|
||||||
'description',
|
'description',
|
||||||
);
|
);
|
||||||
@@ -38,19 +61,14 @@ class $PlayerTableTable extends PlayerTable
|
|||||||
type: DriftSqlType.string,
|
type: DriftSqlType.string,
|
||||||
requiredDuringInsert: true,
|
requiredDuringInsert: true,
|
||||||
);
|
);
|
||||||
static const VerificationMeta _createdAtMeta = const VerificationMeta(
|
|
||||||
'createdAt',
|
|
||||||
);
|
|
||||||
@override
|
@override
|
||||||
late final GeneratedColumn<DateTime> createdAt = GeneratedColumn<DateTime>(
|
List<GeneratedColumn> get $columns => [
|
||||||
'created_at',
|
id,
|
||||||
aliasedName,
|
createdAt,
|
||||||
false,
|
name,
|
||||||
type: DriftSqlType.dateTime,
|
nameCount,
|
||||||
requiredDuringInsert: true,
|
description,
|
||||||
);
|
];
|
||||||
@override
|
|
||||||
List<GeneratedColumn> get $columns => [id, name, description, createdAt];
|
|
||||||
@override
|
@override
|
||||||
String get aliasedName => _alias ?? actualTableName;
|
String get aliasedName => _alias ?? actualTableName;
|
||||||
@override
|
@override
|
||||||
@@ -68,6 +86,14 @@ class $PlayerTableTable extends PlayerTable
|
|||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_idMeta);
|
context.missing(_idMeta);
|
||||||
}
|
}
|
||||||
|
if (data.containsKey('created_at')) {
|
||||||
|
context.handle(
|
||||||
|
_createdAtMeta,
|
||||||
|
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta),
|
||||||
|
);
|
||||||
|
} else if (isInserting) {
|
||||||
|
context.missing(_createdAtMeta);
|
||||||
|
}
|
||||||
if (data.containsKey('name')) {
|
if (data.containsKey('name')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_nameMeta,
|
_nameMeta,
|
||||||
@@ -76,6 +102,12 @@ class $PlayerTableTable extends PlayerTable
|
|||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_nameMeta);
|
context.missing(_nameMeta);
|
||||||
}
|
}
|
||||||
|
if (data.containsKey('name_count')) {
|
||||||
|
context.handle(
|
||||||
|
_nameCountMeta,
|
||||||
|
nameCount.isAcceptableOrUnknown(data['name_count']!, _nameCountMeta),
|
||||||
|
);
|
||||||
|
}
|
||||||
if (data.containsKey('description')) {
|
if (data.containsKey('description')) {
|
||||||
context.handle(
|
context.handle(
|
||||||
_descriptionMeta,
|
_descriptionMeta,
|
||||||
@@ -87,14 +119,6 @@ class $PlayerTableTable extends PlayerTable
|
|||||||
} else if (isInserting) {
|
} else if (isInserting) {
|
||||||
context.missing(_descriptionMeta);
|
context.missing(_descriptionMeta);
|
||||||
}
|
}
|
||||||
if (data.containsKey('created_at')) {
|
|
||||||
context.handle(
|
|
||||||
_createdAtMeta,
|
|
||||||
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta),
|
|
||||||
);
|
|
||||||
} else if (isInserting) {
|
|
||||||
context.missing(_createdAtMeta);
|
|
||||||
}
|
|
||||||
return context;
|
return context;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -108,18 +132,22 @@ class $PlayerTableTable extends PlayerTable
|
|||||||
DriftSqlType.string,
|
DriftSqlType.string,
|
||||||
data['${effectivePrefix}id'],
|
data['${effectivePrefix}id'],
|
||||||
)!,
|
)!,
|
||||||
|
createdAt: attachedDatabase.typeMapping.read(
|
||||||
|
DriftSqlType.dateTime,
|
||||||
|
data['${effectivePrefix}created_at'],
|
||||||
|
)!,
|
||||||
name: attachedDatabase.typeMapping.read(
|
name: attachedDatabase.typeMapping.read(
|
||||||
DriftSqlType.string,
|
DriftSqlType.string,
|
||||||
data['${effectivePrefix}name'],
|
data['${effectivePrefix}name'],
|
||||||
)!,
|
)!,
|
||||||
|
nameCount: attachedDatabase.typeMapping.read(
|
||||||
|
DriftSqlType.int,
|
||||||
|
data['${effectivePrefix}name_count'],
|
||||||
|
)!,
|
||||||
description: attachedDatabase.typeMapping.read(
|
description: attachedDatabase.typeMapping.read(
|
||||||
DriftSqlType.string,
|
DriftSqlType.string,
|
||||||
data['${effectivePrefix}description'],
|
data['${effectivePrefix}description'],
|
||||||
)!,
|
)!,
|
||||||
createdAt: attachedDatabase.typeMapping.read(
|
|
||||||
DriftSqlType.dateTime,
|
|
||||||
data['${effectivePrefix}created_at'],
|
|
||||||
)!,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,31 +159,35 @@ class $PlayerTableTable extends PlayerTable
|
|||||||
|
|
||||||
class PlayerTableData extends DataClass implements Insertable<PlayerTableData> {
|
class PlayerTableData extends DataClass implements Insertable<PlayerTableData> {
|
||||||
final String id;
|
final String id;
|
||||||
final String name;
|
|
||||||
final String description;
|
|
||||||
final DateTime createdAt;
|
final DateTime createdAt;
|
||||||
|
final String name;
|
||||||
|
final int nameCount;
|
||||||
|
final String description;
|
||||||
const PlayerTableData({
|
const PlayerTableData({
|
||||||
required this.id,
|
required this.id,
|
||||||
required this.name,
|
|
||||||
required this.description,
|
|
||||||
required this.createdAt,
|
required this.createdAt,
|
||||||
|
required this.name,
|
||||||
|
required this.nameCount,
|
||||||
|
required this.description,
|
||||||
});
|
});
|
||||||
@override
|
@override
|
||||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||||
final map = <String, Expression>{};
|
final map = <String, Expression>{};
|
||||||
map['id'] = Variable<String>(id);
|
map['id'] = Variable<String>(id);
|
||||||
map['name'] = Variable<String>(name);
|
|
||||||
map['description'] = Variable<String>(description);
|
|
||||||
map['created_at'] = Variable<DateTime>(createdAt);
|
map['created_at'] = Variable<DateTime>(createdAt);
|
||||||
|
map['name'] = Variable<String>(name);
|
||||||
|
map['name_count'] = Variable<int>(nameCount);
|
||||||
|
map['description'] = Variable<String>(description);
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerTableCompanion toCompanion(bool nullToAbsent) {
|
PlayerTableCompanion toCompanion(bool nullToAbsent) {
|
||||||
return PlayerTableCompanion(
|
return PlayerTableCompanion(
|
||||||
id: Value(id),
|
id: Value(id),
|
||||||
name: Value(name),
|
|
||||||
description: Value(description),
|
|
||||||
createdAt: Value(createdAt),
|
createdAt: Value(createdAt),
|
||||||
|
name: Value(name),
|
||||||
|
nameCount: Value(nameCount),
|
||||||
|
description: Value(description),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,9 +198,10 @@ class PlayerTableData extends DataClass implements Insertable<PlayerTableData> {
|
|||||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||||
return PlayerTableData(
|
return PlayerTableData(
|
||||||
id: serializer.fromJson<String>(json['id']),
|
id: serializer.fromJson<String>(json['id']),
|
||||||
name: serializer.fromJson<String>(json['name']),
|
|
||||||
description: serializer.fromJson<String>(json['description']),
|
|
||||||
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
|
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
|
||||||
|
name: serializer.fromJson<String>(json['name']),
|
||||||
|
nameCount: serializer.fromJson<int>(json['nameCount']),
|
||||||
|
description: serializer.fromJson<String>(json['description']),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@override
|
@override
|
||||||
@@ -176,31 +209,35 @@ class PlayerTableData extends DataClass implements Insertable<PlayerTableData> {
|
|||||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||||
return <String, dynamic>{
|
return <String, dynamic>{
|
||||||
'id': serializer.toJson<String>(id),
|
'id': serializer.toJson<String>(id),
|
||||||
'name': serializer.toJson<String>(name),
|
|
||||||
'description': serializer.toJson<String>(description),
|
|
||||||
'createdAt': serializer.toJson<DateTime>(createdAt),
|
'createdAt': serializer.toJson<DateTime>(createdAt),
|
||||||
|
'name': serializer.toJson<String>(name),
|
||||||
|
'nameCount': serializer.toJson<int>(nameCount),
|
||||||
|
'description': serializer.toJson<String>(description),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerTableData copyWith({
|
PlayerTableData copyWith({
|
||||||
String? id,
|
String? id,
|
||||||
String? name,
|
|
||||||
String? description,
|
|
||||||
DateTime? createdAt,
|
DateTime? createdAt,
|
||||||
|
String? name,
|
||||||
|
int? nameCount,
|
||||||
|
String? description,
|
||||||
}) => PlayerTableData(
|
}) => PlayerTableData(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
name: name ?? this.name,
|
|
||||||
description: description ?? this.description,
|
|
||||||
createdAt: createdAt ?? this.createdAt,
|
createdAt: createdAt ?? this.createdAt,
|
||||||
|
name: name ?? this.name,
|
||||||
|
nameCount: nameCount ?? this.nameCount,
|
||||||
|
description: description ?? this.description,
|
||||||
);
|
);
|
||||||
PlayerTableData copyWithCompanion(PlayerTableCompanion data) {
|
PlayerTableData copyWithCompanion(PlayerTableCompanion data) {
|
||||||
return PlayerTableData(
|
return PlayerTableData(
|
||||||
id: data.id.present ? data.id.value : this.id,
|
id: data.id.present ? data.id.value : this.id,
|
||||||
|
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
|
||||||
name: data.name.present ? data.name.value : this.name,
|
name: data.name.present ? data.name.value : this.name,
|
||||||
|
nameCount: data.nameCount.present ? data.nameCount.value : this.nameCount,
|
||||||
description: data.description.present
|
description: data.description.present
|
||||||
? data.description.value
|
? data.description.value
|
||||||
: this.description,
|
: this.description,
|
||||||
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,76 +245,85 @@ class PlayerTableData extends DataClass implements Insertable<PlayerTableData> {
|
|||||||
String toString() {
|
String toString() {
|
||||||
return (StringBuffer('PlayerTableData(')
|
return (StringBuffer('PlayerTableData(')
|
||||||
..write('id: $id, ')
|
..write('id: $id, ')
|
||||||
|
..write('createdAt: $createdAt, ')
|
||||||
..write('name: $name, ')
|
..write('name: $name, ')
|
||||||
..write('description: $description, ')
|
..write('nameCount: $nameCount, ')
|
||||||
..write('createdAt: $createdAt')
|
..write('description: $description')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(id, name, description, createdAt);
|
int get hashCode => Object.hash(id, createdAt, name, nameCount, description);
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) =>
|
bool operator ==(Object other) =>
|
||||||
identical(this, other) ||
|
identical(this, other) ||
|
||||||
(other is PlayerTableData &&
|
(other is PlayerTableData &&
|
||||||
other.id == this.id &&
|
other.id == this.id &&
|
||||||
|
other.createdAt == this.createdAt &&
|
||||||
other.name == this.name &&
|
other.name == this.name &&
|
||||||
other.description == this.description &&
|
other.nameCount == this.nameCount &&
|
||||||
other.createdAt == this.createdAt);
|
other.description == this.description);
|
||||||
}
|
}
|
||||||
|
|
||||||
class PlayerTableCompanion extends UpdateCompanion<PlayerTableData> {
|
class PlayerTableCompanion extends UpdateCompanion<PlayerTableData> {
|
||||||
final Value<String> id;
|
final Value<String> id;
|
||||||
final Value<String> name;
|
|
||||||
final Value<String> description;
|
|
||||||
final Value<DateTime> createdAt;
|
final Value<DateTime> createdAt;
|
||||||
|
final Value<String> name;
|
||||||
|
final Value<int> nameCount;
|
||||||
|
final Value<String> description;
|
||||||
final Value<int> rowid;
|
final Value<int> rowid;
|
||||||
const PlayerTableCompanion({
|
const PlayerTableCompanion({
|
||||||
this.id = const Value.absent(),
|
this.id = const Value.absent(),
|
||||||
this.name = const Value.absent(),
|
|
||||||
this.description = const Value.absent(),
|
|
||||||
this.createdAt = const Value.absent(),
|
this.createdAt = const Value.absent(),
|
||||||
|
this.name = const Value.absent(),
|
||||||
|
this.nameCount = const Value.absent(),
|
||||||
|
this.description = const Value.absent(),
|
||||||
this.rowid = const Value.absent(),
|
this.rowid = const Value.absent(),
|
||||||
});
|
});
|
||||||
PlayerTableCompanion.insert({
|
PlayerTableCompanion.insert({
|
||||||
required String id,
|
required String id,
|
||||||
required String name,
|
|
||||||
required String description,
|
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
|
required String name,
|
||||||
|
this.nameCount = const Value.absent(),
|
||||||
|
required String description,
|
||||||
this.rowid = const Value.absent(),
|
this.rowid = const Value.absent(),
|
||||||
}) : id = Value(id),
|
}) : id = Value(id),
|
||||||
|
createdAt = Value(createdAt),
|
||||||
name = Value(name),
|
name = Value(name),
|
||||||
description = Value(description),
|
description = Value(description);
|
||||||
createdAt = Value(createdAt);
|
|
||||||
static Insertable<PlayerTableData> custom({
|
static Insertable<PlayerTableData> custom({
|
||||||
Expression<String>? id,
|
Expression<String>? id,
|
||||||
Expression<String>? name,
|
|
||||||
Expression<String>? description,
|
|
||||||
Expression<DateTime>? createdAt,
|
Expression<DateTime>? createdAt,
|
||||||
|
Expression<String>? name,
|
||||||
|
Expression<int>? nameCount,
|
||||||
|
Expression<String>? description,
|
||||||
Expression<int>? rowid,
|
Expression<int>? rowid,
|
||||||
}) {
|
}) {
|
||||||
return RawValuesInsertable({
|
return RawValuesInsertable({
|
||||||
if (id != null) 'id': id,
|
if (id != null) 'id': id,
|
||||||
if (name != null) 'name': name,
|
|
||||||
if (description != null) 'description': description,
|
|
||||||
if (createdAt != null) 'created_at': createdAt,
|
if (createdAt != null) 'created_at': createdAt,
|
||||||
|
if (name != null) 'name': name,
|
||||||
|
if (nameCount != null) 'name_count': nameCount,
|
||||||
|
if (description != null) 'description': description,
|
||||||
if (rowid != null) 'rowid': rowid,
|
if (rowid != null) 'rowid': rowid,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerTableCompanion copyWith({
|
PlayerTableCompanion copyWith({
|
||||||
Value<String>? id,
|
Value<String>? id,
|
||||||
Value<String>? name,
|
|
||||||
Value<String>? description,
|
|
||||||
Value<DateTime>? createdAt,
|
Value<DateTime>? createdAt,
|
||||||
|
Value<String>? name,
|
||||||
|
Value<int>? nameCount,
|
||||||
|
Value<String>? description,
|
||||||
Value<int>? rowid,
|
Value<int>? rowid,
|
||||||
}) {
|
}) {
|
||||||
return PlayerTableCompanion(
|
return PlayerTableCompanion(
|
||||||
id: id ?? this.id,
|
id: id ?? this.id,
|
||||||
name: name ?? this.name,
|
|
||||||
description: description ?? this.description,
|
|
||||||
createdAt: createdAt ?? this.createdAt,
|
createdAt: createdAt ?? this.createdAt,
|
||||||
|
name: name ?? this.name,
|
||||||
|
nameCount: nameCount ?? this.nameCount,
|
||||||
|
description: description ?? this.description,
|
||||||
rowid: rowid ?? this.rowid,
|
rowid: rowid ?? this.rowid,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -288,15 +334,18 @@ class PlayerTableCompanion extends UpdateCompanion<PlayerTableData> {
|
|||||||
if (id.present) {
|
if (id.present) {
|
||||||
map['id'] = Variable<String>(id.value);
|
map['id'] = Variable<String>(id.value);
|
||||||
}
|
}
|
||||||
|
if (createdAt.present) {
|
||||||
|
map['created_at'] = Variable<DateTime>(createdAt.value);
|
||||||
|
}
|
||||||
if (name.present) {
|
if (name.present) {
|
||||||
map['name'] = Variable<String>(name.value);
|
map['name'] = Variable<String>(name.value);
|
||||||
}
|
}
|
||||||
|
if (nameCount.present) {
|
||||||
|
map['name_count'] = Variable<int>(nameCount.value);
|
||||||
|
}
|
||||||
if (description.present) {
|
if (description.present) {
|
||||||
map['description'] = Variable<String>(description.value);
|
map['description'] = Variable<String>(description.value);
|
||||||
}
|
}
|
||||||
if (createdAt.present) {
|
|
||||||
map['created_at'] = Variable<DateTime>(createdAt.value);
|
|
||||||
}
|
|
||||||
if (rowid.present) {
|
if (rowid.present) {
|
||||||
map['rowid'] = Variable<int>(rowid.value);
|
map['rowid'] = Variable<int>(rowid.value);
|
||||||
}
|
}
|
||||||
@@ -307,9 +356,10 @@ class PlayerTableCompanion extends UpdateCompanion<PlayerTableData> {
|
|||||||
String toString() {
|
String toString() {
|
||||||
return (StringBuffer('PlayerTableCompanion(')
|
return (StringBuffer('PlayerTableCompanion(')
|
||||||
..write('id: $id, ')
|
..write('id: $id, ')
|
||||||
..write('name: $name, ')
|
|
||||||
..write('description: $description, ')
|
|
||||||
..write('createdAt: $createdAt, ')
|
..write('createdAt: $createdAt, ')
|
||||||
|
..write('name: $name, ')
|
||||||
|
..write('nameCount: $nameCount, ')
|
||||||
|
..write('description: $description, ')
|
||||||
..write('rowid: $rowid')
|
..write('rowid: $rowid')
|
||||||
..write(')'))
|
..write(')'))
|
||||||
.toString();
|
.toString();
|
||||||
@@ -2790,17 +2840,19 @@ abstract class _$AppDatabase extends GeneratedDatabase {
|
|||||||
typedef $$PlayerTableTableCreateCompanionBuilder =
|
typedef $$PlayerTableTableCreateCompanionBuilder =
|
||||||
PlayerTableCompanion Function({
|
PlayerTableCompanion Function({
|
||||||
required String id,
|
required String id,
|
||||||
required String name,
|
|
||||||
required String description,
|
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
|
required String name,
|
||||||
|
Value<int> nameCount,
|
||||||
|
required String description,
|
||||||
Value<int> rowid,
|
Value<int> rowid,
|
||||||
});
|
});
|
||||||
typedef $$PlayerTableTableUpdateCompanionBuilder =
|
typedef $$PlayerTableTableUpdateCompanionBuilder =
|
||||||
PlayerTableCompanion Function({
|
PlayerTableCompanion Function({
|
||||||
Value<String> id,
|
Value<String> id,
|
||||||
Value<String> name,
|
|
||||||
Value<String> description,
|
|
||||||
Value<DateTime> createdAt,
|
Value<DateTime> createdAt,
|
||||||
|
Value<String> name,
|
||||||
|
Value<int> nameCount,
|
||||||
|
Value<String> description,
|
||||||
Value<int> rowid,
|
Value<int> rowid,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -2892,18 +2944,23 @@ class $$PlayerTableTableFilterComposer
|
|||||||
builder: (column) => ColumnFilters(column),
|
builder: (column) => ColumnFilters(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ColumnFilters<DateTime> get createdAt => $composableBuilder(
|
||||||
|
column: $table.createdAt,
|
||||||
|
builder: (column) => ColumnFilters(column),
|
||||||
|
);
|
||||||
|
|
||||||
ColumnFilters<String> get name => $composableBuilder(
|
ColumnFilters<String> get name => $composableBuilder(
|
||||||
column: $table.name,
|
column: $table.name,
|
||||||
builder: (column) => ColumnFilters(column),
|
builder: (column) => ColumnFilters(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
ColumnFilters<String> get description => $composableBuilder(
|
ColumnFilters<int> get nameCount => $composableBuilder(
|
||||||
column: $table.description,
|
column: $table.nameCount,
|
||||||
builder: (column) => ColumnFilters(column),
|
builder: (column) => ColumnFilters(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
ColumnFilters<DateTime> get createdAt => $composableBuilder(
|
ColumnFilters<String> get description => $composableBuilder(
|
||||||
column: $table.createdAt,
|
column: $table.description,
|
||||||
builder: (column) => ColumnFilters(column),
|
builder: (column) => ColumnFilters(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -2997,18 +3054,23 @@ class $$PlayerTableTableOrderingComposer
|
|||||||
builder: (column) => ColumnOrderings(column),
|
builder: (column) => ColumnOrderings(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
ColumnOrderings<DateTime> get createdAt => $composableBuilder(
|
||||||
|
column: $table.createdAt,
|
||||||
|
builder: (column) => ColumnOrderings(column),
|
||||||
|
);
|
||||||
|
|
||||||
ColumnOrderings<String> get name => $composableBuilder(
|
ColumnOrderings<String> get name => $composableBuilder(
|
||||||
column: $table.name,
|
column: $table.name,
|
||||||
builder: (column) => ColumnOrderings(column),
|
builder: (column) => ColumnOrderings(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
ColumnOrderings<String> get description => $composableBuilder(
|
ColumnOrderings<int> get nameCount => $composableBuilder(
|
||||||
column: $table.description,
|
column: $table.nameCount,
|
||||||
builder: (column) => ColumnOrderings(column),
|
builder: (column) => ColumnOrderings(column),
|
||||||
);
|
);
|
||||||
|
|
||||||
ColumnOrderings<DateTime> get createdAt => $composableBuilder(
|
ColumnOrderings<String> get description => $composableBuilder(
|
||||||
column: $table.createdAt,
|
column: $table.description,
|
||||||
builder: (column) => ColumnOrderings(column),
|
builder: (column) => ColumnOrderings(column),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -3025,17 +3087,20 @@ class $$PlayerTableTableAnnotationComposer
|
|||||||
GeneratedColumn<String> get id =>
|
GeneratedColumn<String> get id =>
|
||||||
$composableBuilder(column: $table.id, builder: (column) => column);
|
$composableBuilder(column: $table.id, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumn<DateTime> get createdAt =>
|
||||||
|
$composableBuilder(column: $table.createdAt, builder: (column) => column);
|
||||||
|
|
||||||
GeneratedColumn<String> get name =>
|
GeneratedColumn<String> get name =>
|
||||||
$composableBuilder(column: $table.name, builder: (column) => column);
|
$composableBuilder(column: $table.name, builder: (column) => column);
|
||||||
|
|
||||||
|
GeneratedColumn<int> get nameCount =>
|
||||||
|
$composableBuilder(column: $table.nameCount, builder: (column) => column);
|
||||||
|
|
||||||
GeneratedColumn<String> get description => $composableBuilder(
|
GeneratedColumn<String> get description => $composableBuilder(
|
||||||
column: $table.description,
|
column: $table.description,
|
||||||
builder: (column) => column,
|
builder: (column) => column,
|
||||||
);
|
);
|
||||||
|
|
||||||
GeneratedColumn<DateTime> get createdAt =>
|
|
||||||
$composableBuilder(column: $table.createdAt, builder: (column) => column);
|
|
||||||
|
|
||||||
Expression<T> playerGroupTableRefs<T extends Object>(
|
Expression<T> playerGroupTableRefs<T extends Object>(
|
||||||
Expression<T> Function($$PlayerGroupTableTableAnnotationComposer a) f,
|
Expression<T> Function($$PlayerGroupTableTableAnnotationComposer a) f,
|
||||||
) {
|
) {
|
||||||
@@ -3145,29 +3210,33 @@ class $$PlayerTableTableTableManager
|
|||||||
updateCompanionCallback:
|
updateCompanionCallback:
|
||||||
({
|
({
|
||||||
Value<String> id = const Value.absent(),
|
Value<String> id = const Value.absent(),
|
||||||
Value<String> name = const Value.absent(),
|
|
||||||
Value<String> description = const Value.absent(),
|
|
||||||
Value<DateTime> createdAt = const Value.absent(),
|
Value<DateTime> createdAt = const Value.absent(),
|
||||||
|
Value<String> name = const Value.absent(),
|
||||||
|
Value<int> nameCount = const Value.absent(),
|
||||||
|
Value<String> description = const Value.absent(),
|
||||||
Value<int> rowid = const Value.absent(),
|
Value<int> rowid = const Value.absent(),
|
||||||
}) => PlayerTableCompanion(
|
}) => PlayerTableCompanion(
|
||||||
id: id,
|
id: id,
|
||||||
name: name,
|
|
||||||
description: description,
|
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
|
name: name,
|
||||||
|
nameCount: nameCount,
|
||||||
|
description: description,
|
||||||
rowid: rowid,
|
rowid: rowid,
|
||||||
),
|
),
|
||||||
createCompanionCallback:
|
createCompanionCallback:
|
||||||
({
|
({
|
||||||
required String id,
|
required String id,
|
||||||
required String name,
|
|
||||||
required String description,
|
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
|
required String name,
|
||||||
|
Value<int> nameCount = const Value.absent(),
|
||||||
|
required String description,
|
||||||
Value<int> rowid = const Value.absent(),
|
Value<int> rowid = const Value.absent(),
|
||||||
}) => PlayerTableCompanion.insert(
|
}) => PlayerTableCompanion.insert(
|
||||||
id: id,
|
id: id,
|
||||||
name: name,
|
|
||||||
description: description,
|
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
|
name: name,
|
||||||
|
nameCount: nameCount,
|
||||||
|
description: description,
|
||||||
rowid: rowid,
|
rowid: rowid,
|
||||||
),
|
),
|
||||||
withReferenceMapper: (p0) => p0
|
withReferenceMapper: (p0) => p0
|
||||||
|
|||||||
@@ -2,9 +2,10 @@ import 'package:drift/drift.dart';
|
|||||||
|
|
||||||
class PlayerTable extends Table {
|
class PlayerTable extends Table {
|
||||||
TextColumn get id => text()();
|
TextColumn get id => text()();
|
||||||
TextColumn get name => text()();
|
|
||||||
TextColumn get description => text()();
|
|
||||||
DateTimeColumn get createdAt => dateTime()();
|
DateTimeColumn get createdAt => dateTime()();
|
||||||
|
TextColumn get name => text()();
|
||||||
|
IntColumn get nameCount => integer().withDefault(const Constant(0))();
|
||||||
|
TextColumn get description => text()();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Set<Column<Object>> get primaryKey => {id};
|
Set<Column<Object>> get primaryKey => {id};
|
||||||
|
|||||||
@@ -5,12 +5,14 @@ class Player {
|
|||||||
final String id;
|
final String id;
|
||||||
final DateTime createdAt;
|
final DateTime createdAt;
|
||||||
final String name;
|
final String name;
|
||||||
|
int nameCount;
|
||||||
final String description;
|
final String description;
|
||||||
|
|
||||||
Player({
|
Player({
|
||||||
String? id,
|
String? id,
|
||||||
DateTime? createdAt,
|
DateTime? createdAt,
|
||||||
required this.name,
|
required this.name,
|
||||||
|
this.nameCount = 0,
|
||||||
String? description,
|
String? description,
|
||||||
}) : id = id ?? const Uuid().v4(),
|
}) : id = id ?? const Uuid().v4(),
|
||||||
createdAt = createdAt ?? clock.now(),
|
createdAt = createdAt ?? clock.now(),
|
||||||
@@ -18,7 +20,7 @@ class Player {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'Player{id: $id, name: $name, description: $description}';
|
return 'Player{id: $id, createdAt: $createdAt, name: $name, nameCount: $nameCount, description: $description}';
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a Player instance from a JSON object.
|
/// Creates a Player instance from a JSON object.
|
||||||
@@ -26,6 +28,7 @@ class Player {
|
|||||||
: id = json['id'],
|
: id = json['id'],
|
||||||
createdAt = DateTime.parse(json['createdAt']),
|
createdAt = DateTime.parse(json['createdAt']),
|
||||||
name = json['name'],
|
name = json['name'],
|
||||||
|
nameCount = 0,
|
||||||
description = json['description'];
|
description = json['description'];
|
||||||
|
|
||||||
/// Converts the Player instance to a JSON object.
|
/// Converts the Player instance to a JSON object.
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:tallee/core/adaptive_page_route.dart';
|
import 'package:tallee/core/adaptive_page_route.dart';
|
||||||
|
import 'package:tallee/core/common.dart';
|
||||||
import 'package:tallee/core/custom_theme.dart';
|
import 'package:tallee/core/custom_theme.dart';
|
||||||
import 'package:tallee/core/enums.dart';
|
import 'package:tallee/core/enums.dart';
|
||||||
import 'package:tallee/data/db/database.dart';
|
import 'package:tallee/data/db/database.dart';
|
||||||
@@ -147,6 +148,7 @@ class _GroupDetailViewState extends State<GroupDetailView> {
|
|||||||
children: _group.members.map((member) {
|
children: _group.members.map((member) {
|
||||||
return TextIconTile(
|
return TextIconTile(
|
||||||
text: member.name,
|
text: member.name,
|
||||||
|
suffixText: getNameCountText(member),
|
||||||
iconEnabled: false,
|
iconEnabled: false,
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
|
|||||||
@@ -155,6 +155,7 @@ class _MatchDetailViewState extends State<MatchDetailView> {
|
|||||||
children: match.players.map((player) {
|
children: match.players.map((player) {
|
||||||
return TextIconTile(
|
return TextIconTile(
|
||||||
text: player.name,
|
text: player.name,
|
||||||
|
suffixText: getNameCountText(player),
|
||||||
iconEnabled: false,
|
iconEnabled: false,
|
||||||
);
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
|
|||||||
@@ -30,7 +30,6 @@ const allDependencies = <Package>[
|
|||||||
_cli_util,
|
_cli_util,
|
||||||
_clock,
|
_clock,
|
||||||
_code_assets,
|
_code_assets,
|
||||||
_code_builder,
|
|
||||||
_collection,
|
_collection,
|
||||||
_convert,
|
_convert,
|
||||||
_coverage,
|
_coverage,
|
||||||
@@ -109,6 +108,7 @@ const allDependencies = <Package>[
|
|||||||
_pubspec_parse,
|
_pubspec_parse,
|
||||||
_quiver,
|
_quiver,
|
||||||
_recase,
|
_recase,
|
||||||
|
_record_use,
|
||||||
_retry,
|
_retry,
|
||||||
_rfc_6901,
|
_rfc_6901,
|
||||||
_safe_url_check,
|
_safe_url_check,
|
||||||
@@ -567,17 +567,17 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
|
||||||
);
|
);
|
||||||
|
|
||||||
/// build_runner 2.13.1
|
/// build_runner 2.14.0
|
||||||
const _build_runner = Package(
|
const _build_runner = Package(
|
||||||
name: 'build_runner',
|
name: 'build_runner',
|
||||||
description: 'A build system for Dart code generation and modular compilation.',
|
description: 'A build system for Dart code generation and modular compilation.',
|
||||||
repository: 'https://github.com/dart-lang/build/tree/master/build_runner',
|
repository: 'https://github.com/dart-lang/build/tree/master/build_runner',
|
||||||
authors: [],
|
authors: [],
|
||||||
version: '2.13.1',
|
version: '2.14.0',
|
||||||
spdxIdentifiers: ['BSD-3-Clause'],
|
spdxIdentifiers: ['BSD-3-Clause'],
|
||||||
isMarkdown: false,
|
isMarkdown: false,
|
||||||
isSdk: false,
|
isSdk: false,
|
||||||
dependencies: [PackageRef('analyzer'), PackageRef('args'), PackageRef('async'), PackageRef('build'), PackageRef('build_config'), PackageRef('build_daemon'), PackageRef('built_collection'), PackageRef('built_value'), PackageRef('code_builder'), PackageRef('collection'), PackageRef('convert'), PackageRef('crypto'), PackageRef('dart_style'), PackageRef('glob'), PackageRef('graphs'), PackageRef('http_multi_server'), PackageRef('io'), PackageRef('json_annotation'), PackageRef('logging'), PackageRef('meta'), PackageRef('mime'), PackageRef('package_config'), PackageRef('path'), PackageRef('pool'), PackageRef('pub_semver'), PackageRef('shelf'), PackageRef('shelf_web_socket'), PackageRef('stream_transform'), PackageRef('watcher'), PackageRef('web_socket_channel'), PackageRef('yaml')],
|
dependencies: [PackageRef('analyzer'), PackageRef('args'), PackageRef('async'), PackageRef('build'), PackageRef('build_config'), PackageRef('build_daemon'), PackageRef('built_collection'), PackageRef('built_value'), PackageRef('collection'), PackageRef('convert'), PackageRef('crypto'), PackageRef('dart_style'), PackageRef('glob'), PackageRef('graphs'), PackageRef('http_multi_server'), PackageRef('io'), PackageRef('json_annotation'), PackageRef('logging'), PackageRef('meta'), PackageRef('mime'), PackageRef('package_config'), PackageRef('path'), PackageRef('pool'), PackageRef('pub_semver'), PackageRef('shelf'), PackageRef('shelf_web_socket'), PackageRef('stream_transform'), PackageRef('watcher'), PackageRef('web_socket_channel'), PackageRef('yaml')],
|
||||||
devDependencies: [PackageRef('stream_channel'), PackageRef('test')],
|
devDependencies: [PackageRef('stream_channel'), PackageRef('test')],
|
||||||
license: '''Copyright 2016, the Dart project authors.
|
license: '''Copyright 2016, the Dart project authors.
|
||||||
|
|
||||||
@@ -1153,47 +1153,6 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
|
||||||
);
|
);
|
||||||
|
|
||||||
/// code_builder 4.11.1
|
|
||||||
const _code_builder = Package(
|
|
||||||
name: 'code_builder',
|
|
||||||
description: 'A fluent, builder-based library for generating valid Dart code.',
|
|
||||||
repository: 'https://github.com/dart-lang/tools/tree/main/pkgs/code_builder',
|
|
||||||
authors: [],
|
|
||||||
version: '4.11.1',
|
|
||||||
spdxIdentifiers: ['BSD-3-Clause'],
|
|
||||||
isMarkdown: false,
|
|
||||||
isSdk: false,
|
|
||||||
dependencies: [PackageRef('built_collection'), PackageRef('built_value'), PackageRef('collection'), PackageRef('matcher'), PackageRef('meta')],
|
|
||||||
devDependencies: [PackageRef('build'), PackageRef('build_runner'), PackageRef('dart_style'), PackageRef('source_gen'), PackageRef('test')],
|
|
||||||
license: '''Copyright 2016, the Dart project authors.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are
|
|
||||||
met:
|
|
||||||
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above
|
|
||||||
copyright notice, this list of conditions and the following
|
|
||||||
disclaimer in the documentation and/or other materials provided
|
|
||||||
with the distribution.
|
|
||||||
* Neither the name of Google LLC nor the names of its
|
|
||||||
contributors may be used to endorse or promote products derived
|
|
||||||
from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
|
||||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
|
||||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
|
||||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
|
||||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
|
|
||||||
);
|
|
||||||
|
|
||||||
/// collection 1.19.1
|
/// collection 1.19.1
|
||||||
const _collection = Package(
|
const _collection = Package(
|
||||||
name: 'collection',
|
name: 'collection',
|
||||||
@@ -2892,17 +2851,17 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|||||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
|
||||||
);
|
);
|
||||||
|
|
||||||
/// hooks 1.0.2
|
/// hooks 1.0.3
|
||||||
const _hooks = Package(
|
const _hooks = Package(
|
||||||
name: 'hooks',
|
name: 'hooks',
|
||||||
description: 'A library that contains a Dart API for the JSON-based protocol for `hook/build.dart` and `hook/link.dart`.',
|
description: 'A library that contains a Dart API for the JSON-based protocol for `hook/build.dart` and `hook/link.dart`.',
|
||||||
repository: 'https://github.com/dart-lang/native/tree/main/pkgs/hooks',
|
repository: 'https://github.com/dart-lang/native/tree/main/pkgs/hooks',
|
||||||
authors: [],
|
authors: [],
|
||||||
version: '1.0.2',
|
version: '1.0.3',
|
||||||
spdxIdentifiers: ['BSD-3-Clause'],
|
spdxIdentifiers: ['BSD-3-Clause'],
|
||||||
isMarkdown: false,
|
isMarkdown: false,
|
||||||
isSdk: false,
|
isSdk: false,
|
||||||
dependencies: [PackageRef('collection'), PackageRef('crypto'), PackageRef('logging'), PackageRef('meta'), PackageRef('pub_semver'), PackageRef('yaml')],
|
dependencies: [PackageRef('collection'), PackageRef('crypto'), PackageRef('logging'), PackageRef('meta'), PackageRef('pub_semver'), PackageRef('record_use'), PackageRef('yaml')],
|
||||||
devDependencies: [PackageRef('args'), PackageRef('code_assets'), PackageRef('glob'), PackageRef('json_schema'), PackageRef('path'), PackageRef('test')],
|
devDependencies: [PackageRef('args'), PackageRef('code_assets'), PackageRef('glob'), PackageRef('json_schema'), PackageRef('path'), PackageRef('test')],
|
||||||
license: '''Copyright 2025, the Dart project authors.
|
license: '''Copyright 2025, the Dart project authors.
|
||||||
|
|
||||||
@@ -5106,6 +5065,48 @@ Redistribution and use in source and binary forms, with or without modification,
|
|||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// record_use 0.6.0
|
||||||
|
const _record_use = Package(
|
||||||
|
name: 'record_use',
|
||||||
|
description: '''The serialization logic and API for the usage recording SDK feature.
|
||||||
|
''',
|
||||||
|
repository: 'https://github.com/dart-lang/native/tree/main/pkgs/record_use',
|
||||||
|
authors: [],
|
||||||
|
version: '0.6.0',
|
||||||
|
spdxIdentifiers: ['BSD-3-Clause'],
|
||||||
|
isMarkdown: false,
|
||||||
|
isSdk: false,
|
||||||
|
dependencies: [PackageRef('collection'), PackageRef('meta'), PackageRef('pub_semver')],
|
||||||
|
devDependencies: [PackageRef('json_schema'), PackageRef('test')],
|
||||||
|
license: '''Copyright 2024, the Dart project authors.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are
|
||||||
|
met:
|
||||||
|
|
||||||
|
* Redistributions of source code must retain the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer.
|
||||||
|
* Redistributions in binary form must reproduce the above
|
||||||
|
copyright notice, this list of conditions and the following
|
||||||
|
disclaimer in the documentation and/or other materials provided
|
||||||
|
with the distribution.
|
||||||
|
* Neither the name of Google LLC nor the names of its
|
||||||
|
contributors may be used to endorse or promote products derived
|
||||||
|
from this software without specific prior written permission.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||||
|
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||||
|
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||||
|
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||||
|
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||||
|
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||||
|
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||||
|
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.''',
|
||||||
|
);
|
||||||
|
|
||||||
/// retry 3.1.2
|
/// retry 3.1.2
|
||||||
const _retry = Package(
|
const _retry = Package(
|
||||||
name: 'retry',
|
name: 'retry',
|
||||||
@@ -37880,12 +37881,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||||||
SOFTWARE.''',
|
SOFTWARE.''',
|
||||||
);
|
);
|
||||||
|
|
||||||
/// tallee 0.0.21+255
|
/// tallee 0.0.22+256
|
||||||
const _tallee = Package(
|
const _tallee = Package(
|
||||||
name: 'tallee',
|
name: 'tallee',
|
||||||
description: 'Tracking App for Card Games',
|
description: 'Tracking App for Card Games',
|
||||||
authors: [],
|
authors: [],
|
||||||
version: '0.0.21+255',
|
version: '0.0.22+256',
|
||||||
spdxIdentifiers: ['LGPL-3.0'],
|
spdxIdentifiers: ['LGPL-3.0'],
|
||||||
isMarkdown: false,
|
isMarkdown: false,
|
||||||
isSdk: false,
|
isSdk: false,
|
||||||
|
|||||||
@@ -18,9 +18,18 @@ class StatisticsView extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _StatisticsViewState extends State<StatisticsView> {
|
class _StatisticsViewState extends State<StatisticsView> {
|
||||||
List<(String, int)> winCounts = List.filled(6, ('Skeleton Player', 1));
|
List<(Player, int)> winCounts = List.filled(6, (
|
||||||
List<(String, int)> matchCounts = List.filled(6, ('Skeleton Player', 1));
|
Player(name: 'Skeleton Player'),
|
||||||
List<(String, double)> winRates = List.filled(6, ('Skeleton Player', 1));
|
1,
|
||||||
|
));
|
||||||
|
List<(Player, int)> matchCounts = List.filled(6, (
|
||||||
|
Player(name: 'Skeleton Player'),
|
||||||
|
1,
|
||||||
|
));
|
||||||
|
List<(Player, double)> winRates = List.filled(6, (
|
||||||
|
Player(name: 'Skeleton Player'),
|
||||||
|
1,
|
||||||
|
));
|
||||||
bool isLoading = true;
|
bool isLoading = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -121,7 +130,10 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
players: players,
|
players: players,
|
||||||
context: context,
|
context: context,
|
||||||
);
|
);
|
||||||
winRates = computeWinRatePercent(wins: winCounts, matches: matchCounts);
|
winRates = computeWinRatePercent(
|
||||||
|
winCounts: winCounts,
|
||||||
|
matchCounts: matchCounts,
|
||||||
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
});
|
});
|
||||||
@@ -130,46 +142,46 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
|
|
||||||
/// Calculates the number of wins for each player
|
/// Calculates the number of wins for each player
|
||||||
/// and returns a sorted list of tuples (playerName, winCount)
|
/// and returns a sorted list of tuples (playerName, winCount)
|
||||||
List<(String, int)> _calculateWinsForAllPlayers({
|
List<(Player, int)> _calculateWinsForAllPlayers({
|
||||||
required List<Match> matches,
|
required List<Match> matches,
|
||||||
required List<Player> players,
|
required List<Player> players,
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
}) {
|
}) {
|
||||||
List<(String, int)> winCounts = [];
|
List<(Player, int)> winCounts = [];
|
||||||
final loc = AppLocalizations.of(context);
|
final loc = AppLocalizations.of(context);
|
||||||
|
|
||||||
// Getting the winners
|
// Getting the winners
|
||||||
for (var match in matches) {
|
for (var match in matches) {
|
||||||
final mvps = match.mvp;
|
final mvps = match.mvp;
|
||||||
for (var winner in mvps) {
|
for (var winner in mvps) {
|
||||||
final index = winCounts.indexWhere((entry) => entry.$1 == winner.id);
|
final index = winCounts.indexWhere((entry) => entry.$1.id == winner.id);
|
||||||
// -1 means winner not found in winCounts
|
// -1 means winner not found in winCounts
|
||||||
if (index != -1) {
|
if (index != -1) {
|
||||||
final current = winCounts[index].$2;
|
final current = winCounts[index].$2;
|
||||||
winCounts[index] = (winner.id, current + 1);
|
winCounts[index] = (winner, current + 1);
|
||||||
} else {
|
} else {
|
||||||
winCounts.add((winner.id, 1));
|
winCounts.add((winner, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adding all players with zero wins
|
// Adding all players with zero wins
|
||||||
for (var player in players) {
|
for (var player in players) {
|
||||||
final index = winCounts.indexWhere((entry) => entry.$1 == player.id);
|
final index = winCounts.indexWhere((entry) => entry.$1.id == player.id);
|
||||||
// -1 means player not found in winCounts
|
// -1 means player not found in winCounts
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
winCounts.add((player.id, 0));
|
winCounts.add((player, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace player IDs with names
|
// Replace player IDs with names
|
||||||
for (int i = 0; i < winCounts.length; i++) {
|
for (int i = 0; i < winCounts.length; i++) {
|
||||||
final playerId = winCounts[i].$1;
|
final playerId = winCounts[i].$1.id;
|
||||||
final player = players.firstWhere(
|
final player = players.firstWhere(
|
||||||
(p) => p.id == playerId,
|
(p) => p.id == playerId,
|
||||||
orElse: () => Player(id: playerId, name: loc.not_available),
|
orElse: () => Player(id: playerId, name: loc.not_available),
|
||||||
);
|
);
|
||||||
winCounts[i] = (player.name, winCounts[i].$2);
|
winCounts[i] = (player, winCounts[i].$2);
|
||||||
}
|
}
|
||||||
|
|
||||||
winCounts.sort((a, b) => b.$2.compareTo(a.$2));
|
winCounts.sort((a, b) => b.$2.compareTo(a.$2));
|
||||||
@@ -179,59 +191,51 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
|
|
||||||
/// Calculates the number of matches played for each player
|
/// Calculates the number of matches played for each player
|
||||||
/// and returns a sorted list of tuples (playerName, matchCount)
|
/// and returns a sorted list of tuples (playerName, matchCount)
|
||||||
List<(String, int)> _calculateMatchAmountsForAllPlayers({
|
List<(Player, int)> _calculateMatchAmountsForAllPlayers({
|
||||||
required List<Match> matches,
|
required List<Match> matches,
|
||||||
required List<Player> players,
|
required List<Player> players,
|
||||||
required BuildContext context,
|
required BuildContext context,
|
||||||
}) {
|
}) {
|
||||||
List<(String, int)> matchCounts = [];
|
List<(Player, int)> matchCounts = [];
|
||||||
final loc = AppLocalizations.of(context);
|
final loc = AppLocalizations.of(context);
|
||||||
|
|
||||||
// Counting matches for each player
|
// Counting matches for each player
|
||||||
for (var match in matches) {
|
for (var match in matches) {
|
||||||
if (match.group != null) {
|
for (Player player in match.players) {
|
||||||
final members = match.group!.members.map((p) => p.id).toList();
|
// Check if the player is already in matchCounts
|
||||||
for (var playerId in members) {
|
final index = matchCounts.indexWhere(
|
||||||
final index = matchCounts.indexWhere((entry) => entry.$1 == playerId);
|
(entry) => entry.$1.id == player.id,
|
||||||
// -1 means player not found in matchCounts
|
);
|
||||||
if (index != -1) {
|
|
||||||
final current = matchCounts[index].$2;
|
// -1 -> not found
|
||||||
matchCounts[index] = (playerId, current + 1);
|
if (index == -1) {
|
||||||
|
// Add new entry
|
||||||
|
matchCounts.add((player, 1));
|
||||||
} else {
|
} else {
|
||||||
matchCounts.add((playerId, 1));
|
// Update existing entry
|
||||||
}
|
final currentMatchAmount = matchCounts[index].$2;
|
||||||
}
|
matchCounts[index] = (player, currentMatchAmount + 1);
|
||||||
}
|
|
||||||
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
|
// Adding all players with zero matches
|
||||||
for (var player in players) {
|
for (var player in players) {
|
||||||
final index = matchCounts.indexWhere((entry) => entry.$1 == player.id);
|
final index = matchCounts.indexWhere((entry) => entry.$1.id == player.id);
|
||||||
// -1 means player not found in matchCounts
|
// -1 means player not found in matchCounts
|
||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
matchCounts.add((player.id, 0));
|
matchCounts.add((player, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Replace player IDs with names
|
// Replace player IDs with names
|
||||||
for (int i = 0; i < matchCounts.length; i++) {
|
for (int i = 0; i < matchCounts.length; i++) {
|
||||||
final playerId = matchCounts[i].$1;
|
final playerId = matchCounts[i].$1.id;
|
||||||
final player = players.firstWhere(
|
final player = players.firstWhere(
|
||||||
(p) => p.id == playerId,
|
(p) => p.id == playerId,
|
||||||
orElse: () => Player(id: playerId, name: loc.not_available),
|
orElse: () => Player(id: playerId, name: loc.not_available),
|
||||||
);
|
);
|
||||||
matchCounts[i] = (player.name, matchCounts[i].$2);
|
matchCounts[i] = (player, matchCounts[i].$2);
|
||||||
}
|
}
|
||||||
|
|
||||||
matchCounts.sort((a, b) => b.$2.compareTo(a.$2));
|
matchCounts.sort((a, b) => b.$2.compareTo(a.$2));
|
||||||
@@ -239,25 +243,24 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
return matchCounts;
|
return matchCounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
// dart
|
List<(Player, double)> computeWinRatePercent({
|
||||||
List<(String, double)> computeWinRatePercent({
|
required List<(Player, int)> winCounts,
|
||||||
required List<(String, int)> wins,
|
required List<(Player, int)> matchCounts,
|
||||||
required List<(String, int)> matches,
|
|
||||||
}) {
|
}) {
|
||||||
final Map<String, int> winsMap = {for (var e in wins) e.$1: e.$2};
|
final Map<Player, int> winsMap = {for (var e in winCounts) e.$1: e.$2};
|
||||||
final Map<String, int> matchesMap = {for (var e in matches) e.$1: e.$2};
|
final Map<Player, int> matchesMap = {for (var e in matchCounts) e.$1: e.$2};
|
||||||
|
|
||||||
// Get all unique player names
|
// Get all unique player names
|
||||||
final names = {...winsMap.keys, ...matchesMap.keys};
|
final player = {...matchesMap.keys};
|
||||||
|
|
||||||
// Calculate win rates
|
// Calculate win rates
|
||||||
final result = names.map((name) {
|
final result = player.map((name) {
|
||||||
final int w = winsMap[name] ?? 0;
|
final int w = winsMap[name] ?? 0;
|
||||||
final int g = matchesMap[name] ?? 0;
|
final int m = matchesMap[name] ?? 0;
|
||||||
// Calculate percentage and round to 2 decimal places
|
// Calculate percentage and round to 2 decimal places
|
||||||
// Avoid division by zero
|
// Avoid division by zero
|
||||||
final double percent = (g > 0)
|
final double percent = (m > 0)
|
||||||
? double.parse(((w / g)).toStringAsFixed(2))
|
? double.parse(((w / m)).toStringAsFixed(2))
|
||||||
: 0;
|
: 0;
|
||||||
return (name, percent);
|
return (name, percent);
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
|
import 'package:tallee/core/common.dart';
|
||||||
import 'package:tallee/core/constants.dart';
|
import 'package:tallee/core/constants.dart';
|
||||||
import 'package:tallee/core/custom_theme.dart';
|
import 'package:tallee/core/custom_theme.dart';
|
||||||
import 'package:tallee/data/db/database.dart';
|
import 'package:tallee/data/db/database.dart';
|
||||||
@@ -140,6 +141,7 @@ class _PlayerSelectionState extends State<PlayerSelection> {
|
|||||||
padding: const EdgeInsets.only(right: 8.0),
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
child: TextIconTile(
|
child: TextIconTile(
|
||||||
text: player.name,
|
text: player.name,
|
||||||
|
suffixText: getNameCountText(player),
|
||||||
onIconTap: () {
|
onIconTap: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
// Removes the player from the selection and notifies the parent.
|
// Removes the player from the selection and notifies the parent.
|
||||||
@@ -193,6 +195,7 @@ class _PlayerSelectionState extends State<PlayerSelection> {
|
|||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
return TextIconListTile(
|
return TextIconListTile(
|
||||||
text: suggestedPlayers[index].name,
|
text: suggestedPlayers[index].name,
|
||||||
|
suffixText: getNameCountText(suggestedPlayers[index]),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
setState(() {
|
setState(() {
|
||||||
// If the player is not already selected
|
// If the player is not already selected
|
||||||
@@ -282,7 +285,8 @@ class _PlayerSelectionState extends State<PlayerSelection> {
|
|||||||
final loc = AppLocalizations.of(context);
|
final loc = AppLocalizations.of(context);
|
||||||
final playerName = _searchBarController.text.trim();
|
final playerName = _searchBarController.text.trim();
|
||||||
|
|
||||||
final createdPlayer = Player(name: playerName);
|
int nameCount = _calculateNameCount(playerName);
|
||||||
|
final createdPlayer = Player(name: playerName, nameCount: nameCount);
|
||||||
final success = await db.playerDao.addPlayer(player: createdPlayer);
|
final success = await db.playerDao.addPlayer(player: createdPlayer);
|
||||||
|
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
@@ -295,6 +299,22 @@ class _PlayerSelectionState extends State<PlayerSelection> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int _calculateNameCount(String playerName) {
|
||||||
|
final playersWithSameName =
|
||||||
|
allPlayers.where((player) => player.name == playerName).toList()
|
||||||
|
..sort((a, b) => a.nameCount.compareTo(b.nameCount));
|
||||||
|
|
||||||
|
if (playersWithSameName.isEmpty) {
|
||||||
|
return 0;
|
||||||
|
} else if (playersWithSameName.length == 1) {
|
||||||
|
// Initialize nameCount
|
||||||
|
playersWithSameName[0].nameCount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return following count
|
||||||
|
return playersWithSameName.length + 1;
|
||||||
|
}
|
||||||
|
|
||||||
/// Updates the state after successfully adding a new player.
|
/// Updates the state after successfully adding a new player.
|
||||||
void _handleSuccessfulPlayerCreation(Player player) {
|
void _handleSuccessfulPlayerCreation(Player player) {
|
||||||
selectedPlayers.insert(0, player);
|
selectedPlayers.insert(0, player);
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tallee/core/common.dart';
|
||||||
import 'package:tallee/core/custom_theme.dart';
|
import 'package:tallee/core/custom_theme.dart';
|
||||||
import 'package:tallee/data/models/group.dart';
|
import 'package:tallee/data/models/group.dart';
|
||||||
import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart';
|
import 'package:tallee/presentation/widgets/tiles/text_icon_tile.dart';
|
||||||
@@ -81,7 +82,11 @@ class _GroupTileState extends State<GroupTile> {
|
|||||||
for (var member in [
|
for (var member in [
|
||||||
...widget.group.members,
|
...widget.group.members,
|
||||||
]..sort((a, b) => a.name.compareTo(b.name)))
|
]..sort((a, b) => a.name.compareTo(b.name)))
|
||||||
TextIconTile(text: member.name, iconEnabled: false),
|
TextIconTile(
|
||||||
|
text: member.name,
|
||||||
|
suffixText: getNameCountText(member),
|
||||||
|
iconEnabled: false,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 2.5),
|
const SizedBox(height: 2.5),
|
||||||
|
|||||||
@@ -258,7 +258,11 @@ class _MatchTileState extends State<MatchTile> {
|
|||||||
spacing: 6,
|
spacing: 6,
|
||||||
runSpacing: 6,
|
runSpacing: 6,
|
||||||
children: players.map((player) {
|
children: players.map((player) {
|
||||||
return TextIconTile(text: player.name, iconEnabled: false);
|
return TextIconTile(
|
||||||
|
text: player.name,
|
||||||
|
suffixText: getNameCountText(player),
|
||||||
|
iconEnabled: false,
|
||||||
|
);
|
||||||
}).toList(),
|
}).toList(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tallee/core/common.dart';
|
||||||
|
import 'package:tallee/core/custom_theme.dart';
|
||||||
|
import 'package:tallee/data/models/player.dart';
|
||||||
import 'package:tallee/l10n/generated/app_localizations.dart';
|
import 'package:tallee/l10n/generated/app_localizations.dart';
|
||||||
import 'package:tallee/presentation/widgets/tiles/info_tile.dart';
|
import 'package:tallee/presentation/widgets/tiles/info_tile.dart';
|
||||||
|
|
||||||
@@ -32,7 +35,7 @@ class StatisticsTile extends StatelessWidget {
|
|||||||
final double width;
|
final double width;
|
||||||
|
|
||||||
/// A list of tuples containing labels and their corresponding numeric values.
|
/// A list of tuples containing labels and their corresponding numeric values.
|
||||||
final List<(String, num)> values;
|
final List<(Player, num)> values;
|
||||||
|
|
||||||
/// The maximum number of items to display.
|
/// The maximum number of items to display.
|
||||||
final int itemCount;
|
final int itemCount;
|
||||||
@@ -89,13 +92,31 @@ class StatisticsTile extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 4.0),
|
padding: const EdgeInsets.only(left: 4.0),
|
||||||
child: Text(
|
child: RichText(
|
||||||
values[index].$1,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
text: TextSpan(
|
||||||
|
style: DefaultTextStyle.of(context).style,
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: values[index].$1.name,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.bold,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: getNameCountText(values[index].$1),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
color: CustomTheme.textColor.withAlpha(
|
||||||
|
150,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ class TextIconListTile extends StatelessWidget {
|
|||||||
const TextIconListTile({
|
const TextIconListTile({
|
||||||
super.key,
|
super.key,
|
||||||
required this.text,
|
required this.text,
|
||||||
|
this.suffixText = '',
|
||||||
this.iconEnabled = true,
|
this.iconEnabled = true,
|
||||||
this.onPressed,
|
this.onPressed,
|
||||||
});
|
});
|
||||||
@@ -16,6 +17,9 @@ class TextIconListTile extends StatelessWidget {
|
|||||||
/// The text to display in the tile.
|
/// The text to display in the tile.
|
||||||
final String text;
|
final String text;
|
||||||
|
|
||||||
|
/// An optional suffix text to display after the main text.
|
||||||
|
final String suffixText;
|
||||||
|
|
||||||
/// A boolean to determine if the icon should be displayed.
|
/// A boolean to determine if the icon should be displayed.
|
||||||
final bool iconEnabled;
|
final bool iconEnabled;
|
||||||
|
|
||||||
@@ -35,14 +39,29 @@ class TextIconListTile extends StatelessWidget {
|
|||||||
Flexible(
|
Flexible(
|
||||||
child: Container(
|
child: Container(
|
||||||
padding: const EdgeInsets.symmetric(vertical: 12.5),
|
padding: const EdgeInsets.symmetric(vertical: 12.5),
|
||||||
child: Text(
|
child: RichText(
|
||||||
text,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
|
text: TextSpan(
|
||||||
|
style: DefaultTextStyle.of(context).style,
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: text,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 16,
|
fontSize: 16,
|
||||||
fontWeight: FontWeight.w500,
|
fontWeight: FontWeight.w500,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: suffixText,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: CustomTheme.textColor.withAlpha(100),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (iconEnabled)
|
if (iconEnabled)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ class TextIconTile extends StatelessWidget {
|
|||||||
const TextIconTile({
|
const TextIconTile({
|
||||||
super.key,
|
super.key,
|
||||||
required this.text,
|
required this.text,
|
||||||
|
this.suffixText = '',
|
||||||
this.iconEnabled = true,
|
this.iconEnabled = true,
|
||||||
this.onIconTap,
|
this.onIconTap,
|
||||||
});
|
});
|
||||||
@@ -16,6 +17,8 @@ class TextIconTile extends StatelessWidget {
|
|||||||
/// The text to display in the tile.
|
/// The text to display in the tile.
|
||||||
final String text;
|
final String text;
|
||||||
|
|
||||||
|
final String suffixText;
|
||||||
|
|
||||||
/// A boolean to determine if the icon should be displayed.
|
/// A boolean to determine if the icon should be displayed.
|
||||||
final bool iconEnabled;
|
final bool iconEnabled;
|
||||||
|
|
||||||
@@ -36,10 +39,28 @@ class TextIconTile extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
if (iconEnabled) const SizedBox(width: 3),
|
if (iconEnabled) const SizedBox(width: 3),
|
||||||
Flexible(
|
Flexible(
|
||||||
child: Text(
|
child: RichText(
|
||||||
text,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
|
text: TextSpan(
|
||||||
|
style: DefaultTextStyle.of(context).style,
|
||||||
|
children: [
|
||||||
|
TextSpan(
|
||||||
|
text: text,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TextSpan(
|
||||||
|
text: suffixText,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 13,
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
color: CustomTheme.textColor.withAlpha(120),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (iconEnabled) ...<Widget>[
|
if (iconEnabled) ...<Widget>[
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: tallee
|
name: tallee
|
||||||
description: "Tracking App for Card Games"
|
description: "Tracking App for Card Games"
|
||||||
publish_to: 'none'
|
publish_to: 'none'
|
||||||
version: 0.0.21+255
|
version: 0.0.22+256
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.8.1
|
sdk: ^3.8.1
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import 'package:clock/clock.dart';
|
import 'package:clock/clock.dart';
|
||||||
import 'package:drift/drift.dart' hide isNull;
|
import 'package:drift/drift.dart' hide isNull, isNotNull;
|
||||||
import 'package:drift/native.dart';
|
import 'package:drift/native.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:tallee/data/db/database.dart';
|
import 'package:tallee/data/db/database.dart';
|
||||||
@@ -381,5 +381,160 @@ void main() {
|
|||||||
);
|
);
|
||||||
expect(playerExists, true);
|
expect(playerExists, true);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('Name Count Tests', () {
|
||||||
|
test('Single player gets initialized wih name count 0', () async {
|
||||||
|
await database.playerDao.addPlayer(player: testPlayer1);
|
||||||
|
|
||||||
|
final player = await database.playerDao.getPlayerById(
|
||||||
|
playerId: testPlayer1.id,
|
||||||
|
);
|
||||||
|
expect(player.nameCount, 0);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('Multiple players get initialized wih name count 0', () async {
|
||||||
|
await database.playerDao.addPlayersAsList(
|
||||||
|
players: [testPlayer1, testPlayer2],
|
||||||
|
);
|
||||||
|
|
||||||
|
final players = await database.playerDao.getAllPlayers();
|
||||||
|
|
||||||
|
expect(players.length, 2);
|
||||||
|
for (Player p in players) {
|
||||||
|
expect(p.nameCount, 0);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
test(
|
||||||
|
'Seperatly added players nameCount gets increased correctly',
|
||||||
|
() async {
|
||||||
|
await database.playerDao.addPlayer(player: testPlayer1);
|
||||||
|
|
||||||
|
final player1 = Player(name: testPlayer1.name, description: '');
|
||||||
|
await database.playerDao.addPlayer(player: player1);
|
||||||
|
|
||||||
|
var players = await database.playerDao.getAllPlayers();
|
||||||
|
|
||||||
|
expect(players.length, 2);
|
||||||
|
players.sort((a, b) => a.nameCount.compareTo(b.nameCount));
|
||||||
|
|
||||||
|
for (int i = 0; i < players.length - 1; i++) {
|
||||||
|
expect(players[i].nameCount, i + 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test(
|
||||||
|
'Together added players nameCount gets increased correctly',
|
||||||
|
() async {
|
||||||
|
final player1 = Player(name: testPlayer1.name, description: '');
|
||||||
|
final player2 = Player(name: testPlayer1.name, description: '');
|
||||||
|
final player3 = Player(name: testPlayer1.name, description: '');
|
||||||
|
|
||||||
|
// addPlayersAsList() with multiple players and with one player
|
||||||
|
await database.playerDao.addPlayersAsList(players: [testPlayer1]);
|
||||||
|
await database.playerDao.addPlayersAsList(
|
||||||
|
players: [player1, player2, player3],
|
||||||
|
);
|
||||||
|
|
||||||
|
var players = await database.playerDao.getAllPlayers();
|
||||||
|
|
||||||
|
expect(players.length, 4);
|
||||||
|
players.sort((a, b) => a.nameCount.compareTo(b.nameCount));
|
||||||
|
|
||||||
|
for (int i = 0; i < players.length - 1; i++) {
|
||||||
|
expect(players[i].nameCount, i + 1);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
test('getNameCount works correctly', () async {
|
||||||
|
final player2 = Player(name: testPlayer1.name);
|
||||||
|
final player3 = Player(name: testPlayer1.name);
|
||||||
|
|
||||||
|
await database.playerDao.addPlayersAsList(
|
||||||
|
players: [testPlayer1, player2, player3],
|
||||||
|
);
|
||||||
|
|
||||||
|
final nameCount = await database.playerDao.getNameCount(
|
||||||
|
name: testPlayer1.name,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(nameCount, 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('updateNameCount works correctly', () async {
|
||||||
|
await database.playerDao.addPlayer(player: testPlayer1);
|
||||||
|
|
||||||
|
final success = await database.playerDao.updateNameCount(
|
||||||
|
playerId: testPlayer1.id,
|
||||||
|
nameCount: 2,
|
||||||
|
);
|
||||||
|
expect(success, true);
|
||||||
|
|
||||||
|
final player = await database.playerDao.getPlayerById(
|
||||||
|
playerId: testPlayer1.id,
|
||||||
|
);
|
||||||
|
expect(player.nameCount, 2);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('getPlayerWithHighestNameCount works correctly', () async {
|
||||||
|
final player2 = Player(name: testPlayer1.name, description: '');
|
||||||
|
final player3 = Player(name: testPlayer1.name, description: '');
|
||||||
|
|
||||||
|
await database.playerDao.addPlayersAsList(
|
||||||
|
players: [testPlayer1, player2, player3],
|
||||||
|
);
|
||||||
|
|
||||||
|
final player = await database.playerDao.getPlayerWithHighestNameCount(
|
||||||
|
name: testPlayer1.name,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(player, isNotNull);
|
||||||
|
expect(player!.nameCount, 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('getPlayerWithHighestNameCount with non existing player', () async {
|
||||||
|
final player = await database.playerDao.getPlayerWithHighestNameCount(
|
||||||
|
name: 'non-existing-name',
|
||||||
|
);
|
||||||
|
expect(player, isNull);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('calculateNameCount works correctly', () async {
|
||||||
|
// Case 1: No existing players with the name
|
||||||
|
var count = await database.playerDao.calculateNameCount(
|
||||||
|
name: testPlayer1.name,
|
||||||
|
);
|
||||||
|
expect(count, 0);
|
||||||
|
|
||||||
|
// Case 2: One existing player with the name. Should update that
|
||||||
|
// player's nameCount to 1 and return 2 for the new player
|
||||||
|
await database.playerDao.addPlayer(player: testPlayer1);
|
||||||
|
|
||||||
|
count = await database.playerDao.calculateNameCount(
|
||||||
|
name: testPlayer1.name,
|
||||||
|
);
|
||||||
|
expect(count, 2);
|
||||||
|
|
||||||
|
// Case 3: Multiple existing players with the name.
|
||||||
|
final player2 = Player(name: testPlayer1.name, nameCount: count);
|
||||||
|
await database.playerDao.addPlayer(player: player2);
|
||||||
|
|
||||||
|
count = await database.playerDao.calculateNameCount(
|
||||||
|
name: testPlayer1.name,
|
||||||
|
);
|
||||||
|
expect(count, 3);
|
||||||
|
});
|
||||||
|
|
||||||
|
test('getPlayerWithHighestNameCount with non existing player', () async {
|
||||||
|
await database.playerDao.addPlayer(player: testPlayer1);
|
||||||
|
await database.playerDao.initializeNameCount(name: testPlayer1.name);
|
||||||
|
final player = await database.playerDao.getPlayerById(
|
||||||
|
playerId: testPlayer1.id,
|
||||||
|
);
|
||||||
|
expect(player.nameCount, 1);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user