Added new metric & changed layout builder of Skeletonizer
This commit is contained in:
@@ -16,9 +16,9 @@ class StatisticsView extends StatefulWidget {
|
|||||||
class _StatisticsViewState extends State<StatisticsView> {
|
class _StatisticsViewState extends State<StatisticsView> {
|
||||||
late Future<List<Game>> _gamesFuture;
|
late Future<List<Game>> _gamesFuture;
|
||||||
late Future<List<Player>> _playersFuture;
|
late Future<List<Player>> _playersFuture;
|
||||||
List<(String, int)> winCounts = List.filled(6, ('Skeleton Player', 5));
|
List<(String, int)> winCounts = List.filled(6, ('Skeleton Player', 1));
|
||||||
List<(String, int)> gameCounts = List.filled(6, ('Skeleton Player', 5));
|
List<(String, int)> gameCounts = List.filled(6, ('Skeleton Player', 1));
|
||||||
|
List<(String, double)> winRates = List.filled(6, ('Skeleton Player', 1));
|
||||||
bool isLoading = true;
|
bool isLoading = true;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -29,11 +29,12 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
_playersFuture = db.playerDao.getAllPlayers();
|
_playersFuture = db.playerDao.getAllPlayers();
|
||||||
|
|
||||||
Future.wait([_gamesFuture, _playersFuture]).then((results) async {
|
Future.wait([_gamesFuture, _playersFuture]).then((results) async {
|
||||||
await Future.delayed(const Duration(milliseconds: 500));
|
await Future.delayed(const Duration(milliseconds: 200));
|
||||||
final games = results[0] as List<Game>;
|
final games = results[0] as List<Game>;
|
||||||
final players = results[1] as List<Player>;
|
final players = results[1] as List<Player>;
|
||||||
winCounts = _calculateWinsForAllPlayers(games, players);
|
winCounts = _calculateWinsForAllPlayers(games, players);
|
||||||
gameCounts = _calculateGameAmountsForAllPlayers(games, players);
|
gameCounts = _calculateGameAmountsForAllPlayers(games, players);
|
||||||
|
winRates = computeWinRatePercent(wins: winCounts, games: gameCounts);
|
||||||
if (mounted) {
|
if (mounted) {
|
||||||
setState(() {
|
setState(() {
|
||||||
isLoading = false;
|
isLoading = false;
|
||||||
@@ -46,7 +47,8 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
builder: (BuildContext context, BoxConstraints constraints) {
|
builder: (BuildContext context, BoxConstraints constraints) {
|
||||||
return Skeletonizer(
|
return SingleChildScrollView(
|
||||||
|
child: Skeletonizer(
|
||||||
effect: PulseEffect(
|
effect: PulseEffect(
|
||||||
from: Colors.grey[800]!,
|
from: Colors.grey[800]!,
|
||||||
to: Colors.grey[600]!,
|
to: Colors.grey[600]!,
|
||||||
@@ -54,14 +56,22 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
),
|
),
|
||||||
enabled: isLoading,
|
enabled: isLoading,
|
||||||
enableSwitchAnimation: true,
|
enableSwitchAnimation: true,
|
||||||
switchAnimationConfig: const SwitchAnimationConfig(
|
switchAnimationConfig: SwitchAnimationConfig(
|
||||||
duration: Duration(milliseconds: 200),
|
duration: const Duration(milliseconds: 1000),
|
||||||
switchInCurve: Curves.linear,
|
switchInCurve: Curves.linear,
|
||||||
switchOutCurve: Curves.linear,
|
switchOutCurve: Curves.linear,
|
||||||
transitionBuilder: AnimatedSwitcher.defaultTransitionBuilder,
|
transitionBuilder: AnimatedSwitcher.defaultTransitionBuilder,
|
||||||
layoutBuilder: AnimatedSwitcher.defaultLayoutBuilder,
|
layoutBuilder:
|
||||||
|
(Widget? currentChild, List<Widget> previousChildren) {
|
||||||
|
return Stack(
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
children: [
|
||||||
|
...previousChildren,
|
||||||
|
if (currentChild != null) currentChild,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: BoxConstraints(minWidth: constraints.maxWidth),
|
constraints: BoxConstraints(minWidth: constraints.maxWidth),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -78,6 +88,15 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
barColor: Colors.blue,
|
barColor: Colors.blue,
|
||||||
),
|
),
|
||||||
SizedBox(height: constraints.maxHeight * 0.02),
|
SizedBox(height: constraints.maxHeight * 0.02),
|
||||||
|
StatisticsTile(
|
||||||
|
icon: Icons.casino,
|
||||||
|
title: 'Winrate per Player',
|
||||||
|
width: constraints.maxWidth * 0.95,
|
||||||
|
values: winRates,
|
||||||
|
itemCount: 6,
|
||||||
|
barColor: Colors.orange[700]!,
|
||||||
|
),
|
||||||
|
SizedBox(height: constraints.maxHeight * 0.02),
|
||||||
StatisticsTile(
|
StatisticsTile(
|
||||||
icon: Icons.casino,
|
icon: Icons.casino,
|
||||||
title: 'Games per Player',
|
title: 'Games per Player',
|
||||||
@@ -86,6 +105,7 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
itemCount: 6,
|
itemCount: 6,
|
||||||
barColor: Colors.green,
|
barColor: Colors.green,
|
||||||
),
|
),
|
||||||
|
|
||||||
SizedBox(height: MediaQuery.paddingOf(context).bottom),
|
SizedBox(height: MediaQuery.paddingOf(context).bottom),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -200,4 +220,36 @@ class _StatisticsViewState extends State<StatisticsView> {
|
|||||||
|
|
||||||
return gameCounts;
|
return gameCounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// dart
|
||||||
|
List<(String, double)> computeWinRatePercent({
|
||||||
|
required List<(String, int)> wins, // [(name, wins)]
|
||||||
|
required List<(String, int)> games, // [(name, games)]
|
||||||
|
}) {
|
||||||
|
final Map<String, int> winsMap = {for (var e in wins) e.$1: e.$2};
|
||||||
|
final Map<String, int> gamesMap = {for (var e in games) e.$1: e.$2};
|
||||||
|
|
||||||
|
final names = {...winsMap.keys, ...gamesMap.keys};
|
||||||
|
|
||||||
|
final result = names.map((name) {
|
||||||
|
final int w = winsMap[name] ?? 0;
|
||||||
|
final int g = gamesMap[name] ?? 0;
|
||||||
|
final double percent = (g > 0)
|
||||||
|
? double.parse(((w / g)).toStringAsFixed(2))
|
||||||
|
: 0;
|
||||||
|
return (name, percent);
|
||||||
|
}).toList();
|
||||||
|
|
||||||
|
// Sort the result: first by winrate descending,
|
||||||
|
// then by wins descending in case of a tie
|
||||||
|
result.sort((a, b) {
|
||||||
|
final cmp = b.$2.compareTo(a.$2);
|
||||||
|
if (cmp != 0) return cmp;
|
||||||
|
final wa = winsMap[a.$1] ?? 0;
|
||||||
|
final wb = winsMap[b.$1] ?? 0;
|
||||||
|
return wb.compareTo(wa);
|
||||||
|
});
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user