From a726357f6956cd56a9ce863aa2c2820538c6f622 Mon Sep 17 00:00:00 2001 From: dan63047 Date: Tue, 12 Mar 2024 02:14:49 +0300 Subject: [PATCH] Time weighted stats --- .../tetrio_multiplayer_replay.dart | 47 +- lib/views/tl_match_view.dart | 823 +++++++++--------- lib/widgets/gauget_num.dart | 15 +- lib/widgets/tl_thingy.dart | 8 +- 4 files changed, 489 insertions(+), 404 deletions(-) diff --git a/lib/data_objects/tetrio_multiplayer_replay.dart b/lib/data_objects/tetrio_multiplayer_replay.dart index 81a3d08..03207c9 100644 --- a/lib/data_objects/tetrio_multiplayer_replay.dart +++ b/lib/data_objects/tetrio_multiplayer_replay.dart @@ -1,4 +1,3 @@ -import 'dart:convert'; import 'dart:math'; import 'package:vector_math/vector_math_64.dart'; @@ -151,10 +150,29 @@ class ReplayStats{ } } +class AggregateStats{ + double apm; + double pps; + double vs; + late NerdStats nerdStats; + late EstTr estTr; + late Playstyle playstyle; + double spp; + double kpp; + double kps; + + AggregateStats(this.apm, this.pps, this.vs, this.spp, this.kpp, this.kps){ + nerdStats = NerdStats(apm, pps, vs); + estTr = EstTr(apm, pps, vs, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe); + playstyle = Playstyle(apm, pps, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank); + } +} + class ReplayData{ late String id; late Map rawJson; late List endcontext; + late List timeWeightedStats; late List> stats; late List totalStats; late List> roundWinners; @@ -181,20 +199,45 @@ class ReplayData{ totalLength = 0; stats = []; roundWinners = []; + int roundID = 0; + List APMmultipliedByWeights = [0, 0]; + List PPSmultipliedByWeights = [0, 0]; + List VSmultipliedByWeights = [0, 0]; + List SPPmultipliedByWeights = [0, 0]; + List KPPmultipliedByWeights = [0, 0]; + List KPSmultipliedByWeights = [0, 0]; totalStats = [ReplayStats.createEmpty(), ReplayStats.createEmpty()]; for(var round in json['data']) { int firstInEndContext = round['replays'][0]["events"].last['data']['export']['options']['gameid'].startsWith(endcontext[0].userId) ? 0 : 1; int secondInEndContext = round['replays'][1]["events"].last['data']['export']['options']['gameid'].startsWith(endcontext[1].userId) ? 1 : 0; - roundLengths.add(max(round['replays'][0]['frames'], round['replays'][1]['frames'])); + int roundLength = max(round['replays'][0]['frames'], round['replays'][1]['frames']); + roundLengths.add(roundLength); totalLength = totalLength + max(round['replays'][0]['frames'], round['replays'][1]['frames']); + APMmultipliedByWeights[0] += endcontext[0].secondaryTracking[roundID]*roundLength; + APMmultipliedByWeights[1] += endcontext[1].secondaryTracking[roundID]*roundLength; + PPSmultipliedByWeights[0] += endcontext[0].tertiaryTracking[roundID]*roundLength; + PPSmultipliedByWeights[1] += endcontext[1].tertiaryTracking[roundID]*roundLength; + VSmultipliedByWeights[0] += endcontext[0].extraTracking[roundID]*roundLength; + VSmultipliedByWeights[1] += endcontext[1].extraTracking[roundID]*roundLength; int winner = round['board'].indexWhere((element) => element['success'] == true); roundWinners.add([round['board'][winner]['id'], round['board'][winner]['username']]); ReplayStats playerOne = ReplayStats.fromJson(round['replays'][firstInEndContext]['events'].last['data']['export']['stats'], biggestSpikeFromReplay(round['replays'][secondInEndContext]['events']), round['replays'][firstInEndContext]['frames']); // (events contain recived attacks) ReplayStats playerTwo = ReplayStats.fromJson(round['replays'][secondInEndContext]['events'].last['data']['export']['stats'], biggestSpikeFromReplay(round['replays'][firstInEndContext]['events']), round['replays'][secondInEndContext]['frames']); + SPPmultipliedByWeights[0] += playerOne.spp*roundLength; + SPPmultipliedByWeights[1] += playerTwo.spp*roundLength; + KPPmultipliedByWeights[0] += playerOne.kpp*roundLength; + KPPmultipliedByWeights[1] += playerTwo.kpp*roundLength; + KPSmultipliedByWeights[0] += playerOne.kps*roundLength; + KPSmultipliedByWeights[1] += playerTwo.kps*roundLength; stats.add([playerOne, playerTwo]); totalStats[0] = totalStats[0] + playerOne; totalStats[1] = totalStats[1] + playerTwo; + roundID ++; } + timeWeightedStats = [ + AggregateStats(APMmultipliedByWeights[0]/totalLength, PPSmultipliedByWeights[0]/totalLength, VSmultipliedByWeights[0]/totalLength, SPPmultipliedByWeights[0]/totalLength, KPPmultipliedByWeights[0]/totalLength, KPSmultipliedByWeights[0]/totalLength), + AggregateStats(APMmultipliedByWeights[1]/totalLength, PPSmultipliedByWeights[1]/totalLength, VSmultipliedByWeights[1]/totalLength, SPPmultipliedByWeights[1]/totalLength, KPPmultipliedByWeights[1]/totalLength, KPSmultipliedByWeights[1]/totalLength) + ]; } Map toJson(){ diff --git a/lib/views/tl_match_view.dart b/lib/views/tl_match_view.dart index 373441e..660dc44 100644 --- a/lib/views/tl_match_view.dart +++ b/lib/views/tl_match_view.dart @@ -22,6 +22,9 @@ import 'package:window_manager/window_manager.dart'; final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms(); int roundSelector = -1; // -1 = match averages, otherwise round number-1 List rounds = []; // index zero will be match stats +bool timeWeightedStatsAvaliable = true; +int greenSidePlayer = 0; +int redSidePlayer = 1; late String oldWindowTitle; Duration framesToTime(int frames){ @@ -60,403 +63,427 @@ class TlMatchResultState extends State { } Widget buildComparison(bool bigScreen, bool showMobileSelector){ - return NestedScrollView( - headerSliverBuilder: (context, value) { - return [ - SliverToBoxAdapter( - child: Padding( - padding: const EdgeInsets.fromLTRB(16, 16, 16, 32), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Expanded( - child: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: const [Colors.green, Colors.transparent], - begin: Alignment.bottomCenter, - end: Alignment.topCenter, - stops: [0.0, widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).success ? 0.4 : 0.0], - )), - child: Padding( - padding: const EdgeInsets.fromLTRB(8, 0, 8, 0), - child: Column(children: [ - Text(widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).username, style: bigScreen ? const TextStyle( - fontFamily: "Eurostile Round Extended", - fontSize: 28) : const TextStyle()), - Text(widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).points.toString(), style: const TextStyle( - fontFamily: "Eurostile Round Extended", - fontSize: 42)) - ]), + return FutureBuilder(future: replayData, builder: (context, snapshot){ + late Duration time; + late String readableTime; + late String reason; + timeWeightedStatsAvaliable = true; + if (snapshot.connectionState != ConnectionState.done) return const LinearProgressIndicator(); + if (!snapshot.hasError){ + if (rounds.indexWhere((element) => element.value == -2) == -1) rounds.insert(1, const DropdownMenuItem(value: -2, child: Text("timeWeightedStats"))); + greenSidePlayer = snapshot.data!.endcontext.indexWhere((element) => element.userId == widget.initPlayerId); + redSidePlayer = snapshot.data!.endcontext.indexWhere((element) => element.userId != widget.initPlayerId); + if (roundSelector.isNegative){ + time = framesToTime(snapshot.data!.totalLength); + readableTime = "${t.matchLength}: ${time.inMinutes}:${secs.format(time.inMicroseconds /1000000 % 60)}"; + }else{ + time = framesToTime(snapshot.data!.roundLengths[roundSelector]); + readableTime = "${t.roundLength}: ${time.inMinutes}:${secs.format(time.inMicroseconds /1000000 % 60)}\n${t.winner}: ${snapshot.data!.roundWinners[roundSelector][1]}"; + } + }else{ + timeWeightedStatsAvaliable = false; + switch (snapshot.error.runtimeType){ + case ReplayNotAvalable: + reason = t.matchIsTooOld; + break; + case SzyNotFound: + reason = t.matchIsTooOld; + break; + case SzyForbidden: + reason = t.errors.replayRejected; + break; + case SzyTooManyRequests: + reason = t.errors.tooManyRequests; + break; + default: + reason = snapshot.error.toString(); + break; + } + } + return NestedScrollView( + headerSliverBuilder: (context, value) { + return [ + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 16, 16, 32), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Expanded( + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: const [Colors.green, Colors.transparent], + begin: Alignment.bottomCenter, + end: Alignment.topCenter, + stops: [0.0, widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).success ? 0.4 : 0.0], + )), + child: Padding( + padding: const EdgeInsets.fromLTRB(8, 0, 8, 0), + child: Column(children: [ + Text(widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).username, style: bigScreen ? const TextStyle( + fontFamily: "Eurostile Round Extended", + fontSize: 28) : const TextStyle()), + Text(widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).points.toString(), style: const TextStyle( + fontFamily: "Eurostile Round Extended", + fontSize: 42)) + ]), + ), ), ), - ), - const Padding( - padding: EdgeInsets.only(top: 16), - child: Text("VS"), - ), - Expanded( - child: Container( - decoration: BoxDecoration( - gradient: LinearGradient( - colors: const [Colors.red, Colors.transparent], - begin: Alignment.bottomCenter, - end: Alignment.topCenter, - stops: [0.0, widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).success ? 0.4 : 0.0], - )), - child: Padding( - padding: const EdgeInsets.fromLTRB(8, 0, 8, 0), - child: Column(children: [ - Text(widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).username, style: bigScreen ? const TextStyle( - fontFamily: "Eurostile Round Extended", - fontSize: 28) : const TextStyle()), - Text(widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).points.toString(), style: const TextStyle( - fontFamily: "Eurostile Round Extended", - fontSize: 42)) - ]), + const Padding( + padding: EdgeInsets.only(top: 16), + child: Text("VS"), + ), + Expanded( + child: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: const [Colors.red, Colors.transparent], + begin: Alignment.bottomCenter, + end: Alignment.topCenter, + stops: [0.0, widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).success ? 0.4 : 0.0], + )), + child: Padding( + padding: const EdgeInsets.fromLTRB(8, 0, 8, 0), + child: Column(children: [ + Text(widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).username, style: bigScreen ? const TextStyle( + fontFamily: "Eurostile Round Extended", + fontSize: 28) : const TextStyle()), + Text(widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).points.toString(), style: const TextStyle( + fontFamily: "Eurostile Round Extended", + fontSize: 42)) + ]), + ), ), ), - ), - ], + ], + ), ), ), - ), - if (showMobileSelector) SliverToBoxAdapter( - child: Center( - child: Row( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.baseline, - textBaseline: TextBaseline.alphabetic, - children: [ - Text("${t.statsFor}: ", - style: const TextStyle(color: Colors.white, fontSize: 25)), - DropdownButton(items: rounds, value: roundSelector, onChanged: ((value) { - roundSelector = value; - setState(() {}); - }),), - ], + if (showMobileSelector) SliverToBoxAdapter( + child: Center( + child: Row( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.baseline, + textBaseline: TextBaseline.alphabetic, + children: [ + Text("${t.statsFor}: ", + style: const TextStyle(color: Colors.white, fontSize: 25)), + DropdownButton(items: rounds, value: roundSelector, onChanged: ((value) { + roundSelector = value; + setState(() {}); + }),), + ], + ), ), ), - ), - if (widget.record.ownId == widget.record.replayId && showMobileSelector) SliverToBoxAdapter( - child: Center(child: Text(t.p1nkl0bst3rAlert, textAlign: TextAlign.center)), - ), - if (showMobileSelector) SliverToBoxAdapter(child: FutureBuilder(future: replayData, builder: (context, snapshot) { - switch(snapshot.connectionState){ - case ConnectionState.none: - case ConnectionState.waiting: - case ConnectionState.active: - return const LinearProgressIndicator(); - case ConnectionState.done: - if (!snapshot.hasError){ - if (roundSelector.isNegative){ - var time = framesToTime(snapshot.data!.totalLength); - return Center(child: Text("${t.matchLength}: ${time.inMinutes}:${secs.format(time.inMicroseconds /1000000 % 60)}", textAlign: TextAlign.center)); - }else{ - var time = framesToTime(snapshot.data!.roundLengths[roundSelector]); - return Center(child: Text("${t.roundLength}: ${time.inMinutes}:${secs.format(time.inMicroseconds /1000000 % 60)}\n${t.winner}: ${snapshot.data!.roundWinners[roundSelector][1]}", textAlign: TextAlign.center,)); - } - }else{ - String reason; - switch (snapshot.error.runtimeType){ - case ReplayNotAvalable: - reason = t.matchIsTooOld; - break; - case SzyNotFound: - reason = t.matchIsTooOld; - break; - case SzyForbidden: - reason = t.errors.replayRejected; - break; - case SzyTooManyRequests: - reason = t.errors.tooManyRequests; - break; - default: - reason = snapshot.error.toString(); - break; - } - return Text("${t.replayIssue}: $reason", textAlign: TextAlign.center); - } - - } - },),), - const SliverToBoxAdapter( - child: Divider(), - ) - ]; - }, - body: ListView( - children: [ - Column( - children: [ - CompareThingy( - label: "APM", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).secondary : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).secondaryTracking[roundSelector], - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).secondary : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).secondaryTracking[roundSelector], - fractionDigits: 2, - higherIsBetter: true, - ), - CompareThingy( - label: "PPS", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).tertiary : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).tertiaryTracking[roundSelector], - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).tertiary : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).tertiaryTracking[roundSelector], - fractionDigits: 2, - higherIsBetter: true, - ), - CompareThingy( - label: "VS", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).extra : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).extraTracking[roundSelector], - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).extra : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).extraTracking[roundSelector], - fractionDigits: 2, - higherIsBetter: true, - ), - FutureBuilder(future: replayData, builder: (BuildContext context, AsyncSnapshot snapshot){ - switch(snapshot.connectionState){ - case ConnectionState.none: - case ConnectionState.waiting: - case ConnectionState.active: - return const LinearProgressIndicator(); - case ConnectionState.done: - if (!snapshot.hasError){ - var greenSidePlayer = snapshot.data!.endcontext.indexWhere((element) => element.userId == widget.initPlayerId); - var redSidePlayer = snapshot.data!.endcontext.indexWhere((element) => element.userId != widget.initPlayerId); - return Column(children: [ - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].inputs : snapshot.data!.stats[roundSelector][greenSidePlayer].inputs, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].inputs : snapshot.data!.stats[roundSelector][redSidePlayer].inputs, - label: "Inputs", higherIsBetter: true), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].piecesPlaced : snapshot.data!.stats[roundSelector][greenSidePlayer].piecesPlaced, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].piecesPlaced : snapshot.data!.stats[roundSelector][redSidePlayer].piecesPlaced, - label: "Pieces Placed", higherIsBetter: true), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].kpp : snapshot.data!.stats[roundSelector][greenSidePlayer].kpp, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].kpp : snapshot.data!.stats[roundSelector][redSidePlayer].kpp, - label: "KpP", higherIsBetter: false, fractionDigits: 2,), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].kps : snapshot.data!.stats[roundSelector][greenSidePlayer].kps, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].kps : snapshot.data!.stats[roundSelector][redSidePlayer].kps, - label: "KpS", higherIsBetter: true, fractionDigits: 2,), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].linesCleared : snapshot.data!.stats[roundSelector][greenSidePlayer].linesCleared, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].linesCleared : snapshot.data!.stats[roundSelector][redSidePlayer].linesCleared, - label: "Lines Cleared", higherIsBetter: true), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].score : snapshot.data!.stats[roundSelector][greenSidePlayer].score, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].score : snapshot.data!.stats[roundSelector][redSidePlayer].score, - label: "Score", higherIsBetter: true), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].spp : snapshot.data!.stats[roundSelector][greenSidePlayer].spp, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].spp : snapshot.data!.stats[roundSelector][redSidePlayer].spp, - label: "SpP", higherIsBetter: true, fractionDigits: 2,), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].finessePercentage * 100 : snapshot.data!.stats[roundSelector][greenSidePlayer].finessePercentage * 100, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].finessePercentage * 100 : snapshot.data!.stats[roundSelector][redSidePlayer].finessePercentage * 100, - label: "Finnese", postfix: "%", fractionDigits: 2, higherIsBetter: true), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].topSpike : snapshot.data!.stats[roundSelector][greenSidePlayer].topSpike, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].topSpike : snapshot.data!.stats[roundSelector][redSidePlayer].topSpike, - label: "Best Spike", higherIsBetter: true), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].topCombo : snapshot.data!.stats[roundSelector][greenSidePlayer].topCombo, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].topCombo : snapshot.data!.stats[roundSelector][redSidePlayer].topCombo, - label: "Best Combo", higherIsBetter: true), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].topBtB : snapshot.data!.stats[roundSelector][greenSidePlayer].topBtB, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].topBtB : snapshot.data!.stats[roundSelector][redSidePlayer].topBtB, - label: "Best BtB", higherIsBetter: true), - const Divider(), - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Text("Garbage", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), - ), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].garbage.sent : snapshot.data!.stats[roundSelector][greenSidePlayer].garbage.sent, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].garbage.sent : snapshot.data!.stats[roundSelector][redSidePlayer].garbage.sent, - label: "Sent", higherIsBetter: true), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].garbage.recived : snapshot.data!.stats[roundSelector][greenSidePlayer].garbage.recived, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].garbage.recived : snapshot.data!.stats[roundSelector][redSidePlayer].garbage.recived, - label: "Recived", higherIsBetter: true), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].garbage.attack : snapshot.data!.stats[roundSelector][greenSidePlayer].garbage.attack, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].garbage.attack : snapshot.data!.stats[roundSelector][redSidePlayer].garbage.attack, - label: "Attack", higherIsBetter: true), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].garbage.cleared : snapshot.data!.stats[roundSelector][greenSidePlayer].garbage.cleared, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].garbage.cleared : snapshot.data!.stats[roundSelector][redSidePlayer].garbage.cleared, - label: "Cleared", higherIsBetter: true), - const Divider(), - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Text("Line Clears", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), - ), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].clears.allClears : snapshot.data!.stats[roundSelector][greenSidePlayer].clears.allClears, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].clears.allClears : snapshot.data!.stats[roundSelector][redSidePlayer].clears.allClears, - label: "PC", higherIsBetter: true), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].tspins : snapshot.data!.stats[roundSelector][greenSidePlayer].tspins, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].tspins : snapshot.data!.stats[roundSelector][redSidePlayer].tspins, - label: "T-spins", higherIsBetter: true), - CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].clears.quads : snapshot.data!.stats[roundSelector][greenSidePlayer].clears.quads, - redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].clears.quads : snapshot.data!.stats[roundSelector][redSidePlayer].clears.quads, - label: "Quads", higherIsBetter: true), - ],); - }else{ - return Container(); - } - - } - }) - ], - ), - const Divider(), - Column( - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Text(t.nerdStats, - style: TextStyle( - fontFamily: "Eurostile Round Extended", - fontSize: bigScreen ? 42 : 28)), - ), - CompareThingy( - label: "APP", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.app : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].app, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.app : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].app, - fractionDigits: 3, - higherIsBetter: true, - ), - CompareThingy( - label: "VS/APM", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.vsapm : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].vsapm, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.vsapm : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].vsapm, - fractionDigits: 3, - higherIsBetter: true, - ), - CompareThingy( - label: "DS/S", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.dss : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].dss, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.dss : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].dss, - fractionDigits: 3, - higherIsBetter: true, - ), - CompareThingy( - label: "DS/P", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.dsp : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].dsp, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.dsp : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].dsp, - fractionDigits: 3, - higherIsBetter: true, - ), - CompareThingy( - label: "APP + DS/P", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.appdsp : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].appdsp, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.appdsp : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].appdsp, - fractionDigits: 3, - higherIsBetter: true, - ), - CompareThingy( - label: t.statCellNum.cheese.replaceAll(RegExp(r'\n'), " "), - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.cheese : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].cheese, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.cheese : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].cheese, - fractionDigits: 2, - higherIsBetter: true, - ), - CompareThingy( - label: "Gb Eff.", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.gbe : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].gbe, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.gbe : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].gbe, - fractionDigits: 3, - higherIsBetter: true, - ), - CompareThingy( - label: "wAPP", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.nyaapp : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].nyaapp, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.nyaapp : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].nyaapp, - fractionDigits: 3, - higherIsBetter: true, - ), - CompareThingy( - label: "Area", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.area : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].area, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.area : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].area, - fractionDigits: 2, - higherIsBetter: true, - ), - CompareThingy( - label: t.statCellNum.estOfTRShort, - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).estTr.esttr : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).estTrTracking[roundSelector].esttr, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).estTr.esttr : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).estTrTracking[roundSelector].esttr, - fractionDigits: 2, - higherIsBetter: true, - ), - CompareThingy( - label: "Opener", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyle.opener : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyleTracking[roundSelector].opener, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyle.opener : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyleTracking[roundSelector].opener, - fractionDigits: 3, - higherIsBetter: true, - ), - CompareThingy( - label: "Plonk", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyle.plonk : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyleTracking[roundSelector].plonk, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyle.plonk : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyleTracking[roundSelector].plonk, - fractionDigits: 3, - higherIsBetter: true, - ), - CompareThingy( - label: "Stride", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyle.stride : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyleTracking[roundSelector].stride, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyle.stride : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyleTracking[roundSelector].stride, - fractionDigits: 3, - higherIsBetter: true, - ), - CompareThingy( - label: "Inf. DS", - greenSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyle.infds : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyleTracking[roundSelector].infds, - redSide: roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyle.infds : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyleTracking[roundSelector].infds, - fractionDigits: 3, - higherIsBetter: true, - ), - VsGraphs( - roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).secondary : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).secondaryTracking[roundSelector], - roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).tertiary : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).tertiaryTracking[roundSelector], - roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).extra : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).extraTracking[roundSelector], - roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector], - roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyle : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyleTracking[roundSelector], - roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).secondary : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).secondaryTracking[roundSelector], - roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).tertiary : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).tertiaryTracking[roundSelector], - roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).extra : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).extraTracking[roundSelector], - roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector], - roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyle : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyleTracking[roundSelector] - ) - ], - ), - if (widget.record.ownId != widget.record.replayId) const Divider(), - if (widget.record.ownId != widget.record.replayId) Column( - children: [ - Padding( - padding: const EdgeInsets.only(bottom: 16), - child: Text("Handling", - style: TextStyle( - fontFamily: "Eurostile Round Extended", - fontSize: bigScreen ? 42 : 28)), - ), - CompareThingy( - greenSide: widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).handling.das, - redSide: widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).handling.das, - label: "DAS", fractionDigits: 1, postfix: "F", - higherIsBetter: false), - CompareThingy( - greenSide: widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).handling.arr, - redSide: widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).handling.arr, - label: "ARR", fractionDigits: 1, postfix: "F", - higherIsBetter: false), - CompareThingy( - greenSide: widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).handling.sdf, - redSide: widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).handling.sdf, - label: "SDF", prefix: "x", - higherIsBetter: true), - CompareBoolThingy( - greenSide: widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).handling.safeLock, - redSide: widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).handling.safeLock, - label: "Safe HD", - trueIsBetter: true) - ], - ) - ], + if (widget.record.ownId == widget.record.replayId && showMobileSelector) SliverToBoxAdapter( + child: Center(child: Text(t.p1nkl0bst3rAlert, textAlign: TextAlign.center)), + ), + if (showMobileSelector) SliverToBoxAdapter(child: Center(child: Text(snapshot.hasError ? reason : readableTime, textAlign: TextAlign.center))), + const SliverToBoxAdapter( + child: Divider(), ) - ); + ]; + }, + body: ListView( + children: [ + Column( + children: [ + CompareThingy( + label: "APM", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].apm : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).secondary : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).secondaryTracking[roundSelector], + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].apm : + roundSelector == -1 ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).secondary : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).secondaryTracking[roundSelector], + fractionDigits: 2, + higherIsBetter: true, + ), + CompareThingy( + label: "PPS", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].pps: + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).tertiary : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).tertiaryTracking[roundSelector], + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].pps : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).tertiary: widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).tertiaryTracking[roundSelector], + fractionDigits: 2, + higherIsBetter: true, + ), + CompareThingy( + label: "VS", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].vs : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).extra : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).extraTracking[roundSelector], + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].vs : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).extra : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).extraTracking[roundSelector], + fractionDigits: 2, + higherIsBetter: true, + ), + if (snapshot.hasData) Column(children: [ + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].inputs : snapshot.data!.stats[roundSelector][greenSidePlayer].inputs, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].inputs : snapshot.data!.stats[roundSelector][redSidePlayer].inputs, + label: "Inputs", higherIsBetter: true), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].piecesPlaced : snapshot.data!.stats[roundSelector][greenSidePlayer].piecesPlaced, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].piecesPlaced : snapshot.data!.stats[roundSelector][redSidePlayer].piecesPlaced, + label: "Pieces Placed", higherIsBetter: true), + CompareThingy(greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].kpp : + roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].kpp : snapshot.data!.stats[roundSelector][greenSidePlayer].kpp, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].kpp : + roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].kpp : snapshot.data!.stats[roundSelector][redSidePlayer].kpp, + label: "KpP", higherIsBetter: false, fractionDigits: 2,), + CompareThingy(greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].kps : + roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].kps : snapshot.data!.stats[roundSelector][greenSidePlayer].kps, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].kps : + roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].kps : snapshot.data!.stats[roundSelector][redSidePlayer].kps, + label: "KpS", higherIsBetter: true, fractionDigits: 2,), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].linesCleared : snapshot.data!.stats[roundSelector][greenSidePlayer].linesCleared, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].linesCleared : snapshot.data!.stats[roundSelector][redSidePlayer].linesCleared, + label: "Lines Cleared", higherIsBetter: true), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].score : snapshot.data!.stats[roundSelector][greenSidePlayer].score, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].score : snapshot.data!.stats[roundSelector][redSidePlayer].score, + label: "Score", higherIsBetter: true), + CompareThingy(greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].spp : + roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].spp : snapshot.data!.stats[roundSelector][greenSidePlayer].spp, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].spp : + roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].spp : snapshot.data!.stats[roundSelector][redSidePlayer].spp, + label: "SpP", higherIsBetter: true, fractionDigits: 2,), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].finessePercentage * 100 : snapshot.data!.stats[roundSelector][greenSidePlayer].finessePercentage * 100, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].finessePercentage * 100 : snapshot.data!.stats[roundSelector][redSidePlayer].finessePercentage * 100, + label: "Finnese", postfix: "%", fractionDigits: 2, higherIsBetter: true), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].topSpike : snapshot.data!.stats[roundSelector][greenSidePlayer].topSpike, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].topSpike : snapshot.data!.stats[roundSelector][redSidePlayer].topSpike, + label: "Best Spike", higherIsBetter: true), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].topCombo : snapshot.data!.stats[roundSelector][greenSidePlayer].topCombo, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].topCombo : snapshot.data!.stats[roundSelector][redSidePlayer].topCombo, + label: "Best Combo", higherIsBetter: true), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].topBtB : snapshot.data!.stats[roundSelector][greenSidePlayer].topBtB, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].topBtB : snapshot.data!.stats[roundSelector][redSidePlayer].topBtB, + label: "Best BtB", higherIsBetter: true), + const Divider(), + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Text("Garbage", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), + ), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].garbage.sent : snapshot.data!.stats[roundSelector][greenSidePlayer].garbage.sent, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].garbage.sent : snapshot.data!.stats[roundSelector][redSidePlayer].garbage.sent, + label: "Sent", higherIsBetter: true), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].garbage.recived : snapshot.data!.stats[roundSelector][greenSidePlayer].garbage.recived, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].garbage.recived : snapshot.data!.stats[roundSelector][redSidePlayer].garbage.recived, + label: "Recived", higherIsBetter: true), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].garbage.attack : snapshot.data!.stats[roundSelector][greenSidePlayer].garbage.attack, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].garbage.attack : snapshot.data!.stats[roundSelector][redSidePlayer].garbage.attack, + label: "Attack", higherIsBetter: true), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].garbage.cleared : snapshot.data!.stats[roundSelector][greenSidePlayer].garbage.cleared, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].garbage.cleared : snapshot.data!.stats[roundSelector][redSidePlayer].garbage.cleared, + label: "Cleared", higherIsBetter: true), + const Divider(), + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Text("Line Clears", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), + ), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].clears.allClears : snapshot.data!.stats[roundSelector][greenSidePlayer].clears.allClears, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].clears.allClears : snapshot.data!.stats[roundSelector][redSidePlayer].clears.allClears, + label: "PC", higherIsBetter: true), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].tspins : snapshot.data!.stats[roundSelector][greenSidePlayer].tspins, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].tspins : snapshot.data!.stats[roundSelector][redSidePlayer].tspins, + label: "T-spins", higherIsBetter: true), + CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].clears.quads : snapshot.data!.stats[roundSelector][greenSidePlayer].clears.quads, + redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].clears.quads : snapshot.data!.stats[roundSelector][redSidePlayer].clears.quads, + label: "Quads", higherIsBetter: true), + ],), + ], + ), + const Divider(), + Column( + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Text(t.nerdStats, + style: TextStyle( + fontFamily: "Eurostile Round Extended", + fontSize: bigScreen ? 42 : 28)), + ), + CompareThingy( + label: "APP", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].nerdStats.app : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.app : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].app, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].nerdStats.app : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.app : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].app, + fractionDigits: 3, + higherIsBetter: true, + ), + CompareThingy( + label: "VS/APM", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].nerdStats.vsapm : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.vsapm : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].vsapm, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].nerdStats.vsapm : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.vsapm : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].vsapm, + fractionDigits: 3, + higherIsBetter: true, + ), + CompareThingy( + label: "DS/S", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].nerdStats.dss : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.dss : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].dss, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].nerdStats.dss : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.dss : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].dss, + fractionDigits: 3, + higherIsBetter: true, + ), + CompareThingy( + label: "DS/P", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].nerdStats.dsp : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.dsp : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].dsp, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].nerdStats.dsp : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.dsp : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].dsp, + fractionDigits: 3, + higherIsBetter: true, + ), + CompareThingy( + label: "APP + DS/P", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].nerdStats.appdsp : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.appdsp : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].appdsp, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].nerdStats.appdsp : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.appdsp : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].appdsp, + fractionDigits: 3, + higherIsBetter: true, + ), + CompareThingy( + label: t.statCellNum.cheese.replaceAll(RegExp(r'\n'), " "), + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].nerdStats.cheese : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.cheese : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].cheese, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].nerdStats.cheese : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.cheese : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].cheese, + fractionDigits: 2, + higherIsBetter: false, + ), + CompareThingy( + label: "Gb Eff.", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].nerdStats.gbe : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.gbe : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].gbe, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].nerdStats.gbe : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.gbe : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].gbe, + fractionDigits: 3, + higherIsBetter: true, + ), + CompareThingy( + label: "wAPP", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].nerdStats.nyaapp : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.nyaapp : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].nyaapp, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].nerdStats.nyaapp : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.nyaapp : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].nyaapp, + fractionDigits: 3, + higherIsBetter: true, + ), + CompareThingy( + label: "Area", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].nerdStats.area : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats.area : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector].area, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].nerdStats.area : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats.area : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector].area, + fractionDigits: 2, + higherIsBetter: true, + ), + CompareThingy( + label: t.statCellNum.estOfTRShort, + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].estTr.esttr : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).estTr.esttr : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).estTrTracking[roundSelector].esttr, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].estTr.esttr : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).estTr.esttr : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).estTrTracking[roundSelector].esttr, + fractionDigits: 2, + higherIsBetter: true, + ), + CompareThingy( + label: "Opener", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].playstyle.opener : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyle.opener : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyleTracking[roundSelector].opener, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].playstyle.opener : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyle.opener : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyleTracking[roundSelector].opener, + fractionDigits: 3, + higherIsBetter: true, + ), + CompareThingy( + label: "Plonk", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].playstyle.plonk : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyle.plonk : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyleTracking[roundSelector].plonk, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].playstyle.plonk : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyle.plonk : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyleTracking[roundSelector].plonk, + fractionDigits: 3, + higherIsBetter: true, + ), + CompareThingy( + label: "Stride", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].playstyle.stride : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyle.stride : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyleTracking[roundSelector].stride, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].playstyle.stride : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyle.stride : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyleTracking[roundSelector].stride, + fractionDigits: 3, + higherIsBetter: true, + ), + CompareThingy( + label: "Inf. DS", + greenSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].playstyle.infds : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyle.infds : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyleTracking[roundSelector].infds, + redSide: (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].playstyle.infds : + roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyle.infds : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyleTracking[roundSelector].infds, + fractionDigits: 3, + higherIsBetter: true, + ), + VsGraphs( + (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].apm : roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).secondary : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).secondaryTracking[roundSelector], + (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].pps : roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).tertiary : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).tertiaryTracking[roundSelector], + (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].vs : roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).extra : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).extraTracking[roundSelector], + (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].nerdStats : roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStats : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).nerdStatsTracking[roundSelector], + (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[greenSidePlayer].playstyle : roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyle : widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).playstyleTracking[roundSelector], + (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].apm : roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).secondary : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).secondaryTracking[roundSelector], + (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].pps : roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).tertiary : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).tertiaryTracking[roundSelector], + (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].vs : roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).extra : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).extraTracking[roundSelector], + (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].nerdStats : roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStats : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).nerdStatsTracking[roundSelector], + (roundSelector == -2 && snapshot.hasData) ? snapshot.data!.timeWeightedStats[redSidePlayer].playstyle : roundSelector.isNegative ? widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyle : widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).playstyleTracking[roundSelector] + ) + ], + ), + if (widget.record.ownId != widget.record.replayId) const Divider(), + if (widget.record.ownId != widget.record.replayId) Column( + children: [ + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Text("Handling", + style: TextStyle( + fontFamily: "Eurostile Round Extended", + fontSize: bigScreen ? 42 : 28)), + ), + CompareThingy( + greenSide: widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).handling.das, + redSide: widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).handling.das, + label: "DAS", fractionDigits: 1, postfix: "F", + higherIsBetter: false), + CompareThingy( + greenSide: widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).handling.arr, + redSide: widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).handling.arr, + label: "ARR", fractionDigits: 1, postfix: "F", + higherIsBetter: false), + CompareThingy( + greenSide: widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).handling.sdf, + redSide: widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).handling.sdf, + label: "SDF", prefix: "x", + higherIsBetter: true), + CompareBoolThingy( + greenSide: widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).handling.safeLock, + redSide: widget.record.endContext.firstWhere((element) => element.userId != widget.initPlayerId).handling.safeLock, + label: "Safe HD", + trueIsBetter: true) + ], + ) + ], + ) + ); + }); } Widget buildRoundSelector(double width){ return Padding( - padding: EdgeInsets.all(8.0000000), + padding: const EdgeInsets.all(8.000000), child: SizedBox( width: width, child: NestedScrollView( @@ -482,8 +509,8 @@ class TlMatchResultState extends State { RichText( text: TextSpan( text: "${time.inMinutes}:${NumberFormat("00", LocaleSettings.currentLocale.languageCode).format(time.inSeconds%60)}", - style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28, fontWeight: FontWeight.w500), - children: [TextSpan(text: ".${NumberFormat("000", LocaleSettings.currentLocale.languageCode).format(time.inMilliseconds%1000)}", style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))] + style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28, fontWeight: FontWeight.w500), + children: [TextSpan(text: ".${NumberFormat("000", LocaleSettings.currentLocale.languageCode).format(time.inMilliseconds%1000)}", style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))] ), ) ],); @@ -512,7 +539,7 @@ class TlMatchResultState extends State { if (widget.record.ownId != widget.record.replayId) Text("${t.replayIssue}: $reason"), if (widget.record.ownId == widget.record.replayId) Center(child: Text(t.p1nkl0bst3rAlert, textAlign: TextAlign.center)), if (widget.record.ownId != widget.record.replayId) RichText( - text: TextSpan( + text: const TextSpan( text: "-:--", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.grey), children: [TextSpan(text: ".---", style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))] @@ -526,7 +553,7 @@ class TlMatchResultState extends State { if (widget.record.ownId != widget.record.replayId) Column( crossAxisAlignment: CrossAxisAlignment.end, children: [ - Text("Number of rounds"), + const Text("Number of rounds"), RichText( text: TextSpan( text: widget.record.endContext.first.secondaryTracking.length > 0 ? widget.record.endContext.first.secondaryTracking.length.toString() : "---", @@ -549,10 +576,12 @@ class TlMatchResultState extends State { roundSelector = -1; setState(() {}); }), - TextButton( child: const Text('Time-weighted match stats'), onPressed: () { - roundSelector = -1; + TextButton( child: const Text('Time-weighted match stats'), + style: roundSelector == -2 ? ButtonStyle(backgroundColor: MaterialStatePropertyAll(Colors.grey.shade900)) : null, + onPressed: timeWeightedStatsAvaliable ? () { + roundSelector = -2; setState(() {}); - }), + } : null) , //TextButton( child: const Text('Button 3'), onPressed: () {}), ], ) @@ -595,8 +624,8 @@ class TlMatchResultState extends State { leading:RichText( text: TextSpan( text: "${time.inMinutes}:${NumberFormat("00", LocaleSettings.currentLocale.languageCode).format(time.inSeconds%60)}", - style: TextStyle(fontFamily: "Eurostile Round", fontSize: 22, fontWeight: FontWeight.w500), - children: [TextSpan(text: ".${NumberFormat("000", LocaleSettings.currentLocale.languageCode).format(time.inMilliseconds%1000)}", style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))] + style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 22, fontWeight: FontWeight.w500), + children: [TextSpan(text: ".${NumberFormat("000", LocaleSettings.currentLocale.languageCode).format(time.inMilliseconds%1000)}", style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))] ), ), title: Text(snapshot.data!.roundWinners[index][1], textAlign: TextAlign.center), @@ -621,13 +650,13 @@ class TlMatchResultState extends State { ), child: ListTile( leading: RichText( - text: TextSpan( + text: const TextSpan( text: "-:--", style: TextStyle(fontFamily: "Eurostile Round", fontSize: 22, fontWeight: FontWeight.w500, color: Colors.grey), children: [TextSpan(text: ".---", style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))] ), ), - title: Text("---", style: TextStyle(color: Colors.grey), textAlign: TextAlign.center), + title: const Text("---", style: TextStyle(color: Colors.grey), textAlign: TextAlign.center), trailing: TrailingStats( widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).secondaryTracking[index], widget.record.endContext.firstWhere((element) => element.userId == widget.initPlayerId).tertiaryTracking[index], @@ -656,7 +685,7 @@ class TlMatchResultState extends State { if (viewportWidth <= 1024) { return Center( child: Container( - constraints: BoxConstraints(maxWidth: 768), + constraints: const BoxConstraints(maxWidth: 768), child: buildComparison(viewportWidth > 768, true) ), ); @@ -670,7 +699,7 @@ class TlMatchResultState extends State { child: buildComparison(true, false) ), Container( - constraints: BoxConstraints(maxWidth: 768), + constraints: const BoxConstraints(maxWidth: 768), child: buildRoundSelector(max(viewportWidth-768-16, 200)), ) ], diff --git a/lib/widgets/gauget_num.dart b/lib/widgets/gauget_num.dart index 17295ed..ef83515 100644 --- a/lib/widgets/gauget_num.dart +++ b/lib/widgets/gauget_num.dart @@ -17,6 +17,7 @@ class GaugetNum extends StatelessWidget { final String? alertTitle; final List? alertWidgets; final LeaderboardPosition? pos; + final num? averageStat; const GaugetNum( {super.key, @@ -28,7 +29,17 @@ class GaugetNum extends StatelessWidget { required this.minimum, required this.maximum, required this.ranges, - this.okText, this.alertTitle, this.pos}); + this.okText, this.alertTitle, this.pos, this.averageStat}); + + Color getStatColor(){ + if (averageStat == null) return Colors.white; + num percentile = (higherIsBetter ? playerStat / averageStat! : averageStat! / playerStat).abs(); + if (percentile > 1.50) return Colors.purpleAccent; + else if (percentile > 1.20) return Colors.blueAccent; + else if (percentile > 0.90) return Colors.greenAccent; + else if (percentile > 0.70) return Colors.yellowAccent; + else return Colors.redAccent; + } @override Widget build(BuildContext context) { @@ -59,7 +70,7 @@ class GaugetNum extends StatelessWidget { ], annotations: [GaugeAnnotation( widget: TextButton(child: Text(f3.format(playerStat), - style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, color: Colors.white)), + style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, color: getStatColor())), onPressed: (){ showDialog( context: context, diff --git a/lib/widgets/tl_thingy.dart b/lib/widgets/tl_thingy.dart index 6db515d..437253f 100644 --- a/lib/widgets/tl_thingy.dart +++ b/lib/widgets/tl_thingy.dart @@ -197,7 +197,8 @@ class _TLThingyState extends State { ], alertWidgets: [ Text(t.statCellNum.appDescription), Text("${t.exactValue}: ${currentTl.nerdStats!.app}") - ], oldPlayerStat: oldTl?.nerdStats?.app, pos: widget.lbPositions?.app), + ], oldPlayerStat: oldTl?.nerdStats?.app, pos: widget.lbPositions?.app, + averageStat: rankAverages?.nerdStats?.app), GaugetNum(playerStat: currentTl.nerdStats!.vsapm, playerStatLabel: "VS / APM", higherIsBetter: true, minimum: 1.8, maximum: 2.4, ranges: [ GaugeRange(startValue: 1.8, endValue: 2.0, color: Colors.green), GaugeRange(startValue: 2.0, endValue: 2.2, color: Colors.blue), @@ -205,7 +206,8 @@ class _TLThingyState extends State { ], alertWidgets: [ Text(t.statCellNum.vsapmDescription), Text("${t.exactValue}: ${currentTl.nerdStats!.vsapm}") - ], oldPlayerStat: oldTl?.nerdStats?.vsapm, pos: widget.lbPositions?.vsapm) + ], oldPlayerStat: oldTl?.nerdStats?.vsapm, pos: widget.lbPositions?.vsapm, + averageStat: rankAverages?.nerdStats?.vsapm) ]), ), Wrap( @@ -244,7 +246,7 @@ class _TLThingyState extends State { oldPlayerStat: oldTl?.nerdStats?.appdsp,), StatCellNum(playerStat: currentTl.nerdStats!.cheese, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.cheese, pos: widget.lbPositions?.cheese, - averageStat: rankAverages?.nerdStats?.cheese, + //averageStat: rankAverages?.nerdStats?.cheese, TODO: questonable alertWidgets: [Text(t.statCellNum.cheeseDescription), Text("${t.formula}: (DS/P * 150) + ((VS/APM - 2) * 50) + (0.6 - APP) * 125"), Text("${t.exactValue}: ${currentTl.nerdStats!.cheese}"),],