diff --git a/lib/presentation/views/main_menu/statistics_view.dart b/lib/presentation/views/main_menu/statistics_view.dart index 3a55115..221ffee 100644 --- a/lib/presentation/views/main_menu/statistics_view.dart +++ b/lib/presentation/views/main_menu/statistics_view.dart @@ -18,9 +18,18 @@ class StatisticsView extends StatefulWidget { } class _StatisticsViewState extends State { - List<(String, int)> winCounts = List.filled(6, ('Skeleton Player', 1)); - List<(String, int)> matchCounts = List.filled(6, ('Skeleton Player', 1)); - List<(String, double)> winRates = List.filled(6, ('Skeleton Player', 1)); + List<(Player, int)> winCounts = List.filled(6, ( + Player(name: 'Skeleton Player'), + 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; @override @@ -121,7 +130,10 @@ class _StatisticsViewState extends State { players: players, context: context, ); - winRates = computeWinRatePercent(wins: winCounts, matches: matchCounts); + winRates = computeWinRatePercent( + winCounts: winCounts, + matchCounts: matchCounts, + ); setState(() { isLoading = false; }); @@ -130,47 +142,47 @@ class _StatisticsViewState extends State { /// Calculates the number of wins for each player /// and returns a sorted list of tuples (playerName, winCount) - List<(String, int)> _calculateWinsForAllPlayers({ + List<(Player, int)> _calculateWinsForAllPlayers({ required List matches, required List players, required BuildContext context, }) { - List<(String, int)> winCounts = []; + List<(Player, int)> winCounts = []; final loc = AppLocalizations.of(context); // Getting the winners for (var match in matches) { final winner = match.winner; if (winner != null) { - 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 if (index != -1) { final current = winCounts[index].$2; - winCounts[index] = (winner.id, current + 1); + winCounts[index] = (winner, current + 1); } else { - winCounts.add((winner.id, 1)); + winCounts.add((winner, 1)); } } } // Adding all players with zero wins 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 if (index == -1) { - winCounts.add((player.id, 0)); + winCounts.add((player, 0)); } } // Replace player IDs with names for (int i = 0; i < winCounts.length; i++) { - final playerId = winCounts[i].$1; + final playerId = winCounts[i].$1.id; final player = players.firstWhere( (p) => p.id == playerId, orElse: () => Player(id: playerId, name: loc.not_available, description: ''), ); - winCounts[i] = (player.name, winCounts[i].$2); + winCounts[i] = (player, winCounts[i].$2); } winCounts.sort((a, b) => b.$2.compareTo(a.$2)); @@ -180,60 +192,51 @@ class _StatisticsViewState extends State { /// Calculates the number of matches played for each player /// and returns a sorted list of tuples (playerName, matchCount) - List<(String, int)> _calculateMatchAmountsForAllPlayers({ + List<(Player, int)> _calculateMatchAmountsForAllPlayers({ required List matches, required List players, required BuildContext context, }) { - List<(String, int)> matchCounts = []; + List<(Player, int)> matchCounts = []; final loc = AppLocalizations.of(context); // Counting matches for each player for (var match in matches) { - if (match.group != null) { - final members = match.group!.members.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)); - } - } - } - 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); + for (Player player in match.players) { + // Check if the player is already in matchCounts + final index = matchCounts.indexWhere( + (entry) => entry.$1.id == player.id, + ); + + // -1 -> not found + if (index == -1) { + // Add new entry + matchCounts.add((player, 1)); } else { - matchCounts.add((playerId, 1)); + // Update existing entry + final currentMatchAmount = matchCounts[index].$2; + matchCounts[index] = (player, currentMatchAmount + 1); } } } // Adding all players with zero matches 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 if (index == -1) { - matchCounts.add((player.id, 0)); + matchCounts.add((player, 0)); } } // Replace player IDs with names for (int i = 0; i < matchCounts.length; i++) { - final playerId = matchCounts[i].$1; + final playerId = matchCounts[i].$1.id; final player = players.firstWhere( (p) => p.id == playerId, - orElse: () => - Player(id: playerId, name: loc.not_available, description: ''), + 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)); @@ -241,25 +244,24 @@ class _StatisticsViewState extends State { return matchCounts; } - // dart - List<(String, double)> computeWinRatePercent({ - required List<(String, int)> wins, - required List<(String, int)> matches, + List<(Player, double)> computeWinRatePercent({ + required List<(Player, int)> winCounts, + required List<(Player, int)> matchCounts, }) { - final Map winsMap = {for (var e in wins) e.$1: e.$2}; - final Map matchesMap = {for (var e in matches) e.$1: e.$2}; + final Map winsMap = {for (var e in winCounts) e.$1: e.$2}; + final Map matchesMap = {for (var e in matchCounts) e.$1: e.$2}; // Get all unique player names - final names = {...winsMap.keys, ...matchesMap.keys}; + final player = {...matchesMap.keys}; // Calculate win rates - final result = names.map((name) { + final result = player.map((name) { 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 // Avoid division by zero - final double percent = (g > 0) - ? double.parse(((w / g)).toStringAsFixed(2)) + final double percent = (m > 0) + ? double.parse(((w / m)).toStringAsFixed(2)) : 0; return (name, percent); }).toList(); diff --git a/lib/presentation/widgets/tiles/statistics_tile.dart b/lib/presentation/widgets/tiles/statistics_tile.dart index bc2f7b6..ea9cb49 100644 --- a/lib/presentation/widgets/tiles/statistics_tile.dart +++ b/lib/presentation/widgets/tiles/statistics_tile.dart @@ -1,6 +1,9 @@ import 'dart:math'; 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/presentation/widgets/tiles/info_tile.dart'; @@ -32,7 +35,7 @@ class StatisticsTile extends StatelessWidget { final double width; /// 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. final int itemCount; @@ -89,11 +92,29 @@ class StatisticsTile extends StatelessWidget { ), Padding( padding: const EdgeInsets.only(left: 4.0), - child: Text( - values[index].$1, - style: const TextStyle( - fontSize: 16, - fontWeight: FontWeight.bold, + child: RichText( + overflow: TextOverflow.ellipsis, + text: TextSpan( + style: DefaultTextStyle.of(context).style, + children: [ + TextSpan( + text: values[index].$1.name, + style: const TextStyle( + fontSize: 16, + fontWeight: FontWeight.bold, + ), + ), + TextSpan( + text: getNameCountText(values[index].$1), + style: TextStyle( + fontSize: 14, + fontWeight: FontWeight.bold, + color: CustomTheme.textColor.withAlpha( + 150, + ), + ), + ), + ], ), ), ),