diff --git a/README.md b/README.md index 78542a4..9c656d3 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,8 @@ - ~~Ability to compare player with himself in past~~ - ~~Tetra League matches history~~ - ~~Tetra League historic charts for tracked players~~ -- ~~Better UI with delta and hints for stats~~ *v0.2.0, we are here* *dev build are here* -- Ability to compare player with APM-PPS-VS stats +- ~~Better UI with delta and hints for stats~~ *v0.2.0, we are here* +- ~~Ability to compare player with APM-PPS-VS stats~~ *dev build are here* - Ability to fetch Tetra League leaderboard - Average stats for ranks - Ability to compare player with avgRank diff --git a/lib/data_objects/tetrio.dart b/lib/data_objects/tetrio.dart index dfbd642..01d92fa 100644 --- a/lib/data_objects/tetrio.dart +++ b/lib/data_objects/tetrio.dart @@ -690,7 +690,11 @@ class TetraLeagueAlpha { this.apm, this.pps, this.vs, - this.records}); + this.records}){ + nerdStats = (apm != null && pps != null && apm != null) ? NerdStats(apm!, pps!, vs!) : null; + estTr = (nerdStats != null) ? EstTr(apm!, pps!, vs!, (rd != null) ? rd! : 69, nerdStats!.app, nerdStats!.dss, nerdStats!.dsp, nerdStats!.gbe) : null; + playstyle =(nerdStats != null) ? Playstyle(apm!, pps!, nerdStats!.app, nerdStats!.vsapm, nerdStats!.dsp, nerdStats!.gbe, estTr!.srarea, estTr!.statrank) : null; + } double get winrate => gamesWon / gamesPlayed; diff --git a/lib/views/compare_view.dart b/lib/views/compare_view.dart index 0f1a3be..1960d0c 100644 --- a/lib/views/compare_view.dart +++ b/lib/views/compare_view.dart @@ -1,21 +1,35 @@ import 'dart:math'; import 'package:fl_chart/fl_chart.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:tetra_stats/data_objects/tetrio.dart'; import 'package:tetra_stats/services/tetrio_crud.dart'; -TetrioPlayer? theGreenSide; -List>? greenSideStates; -TetrioPlayer? theRedSide; -List>? redSideStates; +enum Mode{ + player, + stats, + averages +} +Mode greenSideMode = Mode.player; +List theGreenSide = [null, null, null]; // TetrioPlayer?, List>?, TetraLeagueAlpha? +//TetrioPlayer? theGreenSide; +//List>? greenSideStates; +Mode redSideMode = Mode.player; +List theRedSide = [null, null, null]; +//TetrioPlayer? theRedSide; +//List>? redSideStates; final TetrioService teto = TetrioService(); final DateFormat dateFormat = DateFormat.yMd().add_Hm(); +// ignore: unnecessary_string_escapes +var numbersReg = RegExp(r'\d+(\.\d*)*'); class CompareView extends StatefulWidget { - final TetrioPlayer greenSide; - final TetrioPlayer? redSide; - const CompareView({Key? key, required this.greenSide, required this.redSide}) + final List greenSide; + final List redSide; + final Mode greenMode; + final Mode redMode; + const CompareView({Key? key, required this.greenSide, required this.redSide, required this.greenMode, required this.redMode}) : super(key: key); @override @@ -28,42 +42,71 @@ class CompareState extends State { @override void initState() { theGreenSide = widget.greenSide; - fetchGreenSide(widget.greenSide.userId); - if (widget.redSide != null) fetchRedSide(widget.redSide!.userId); + fetchGreenSide(widget.greenSide[0].userId); + if (widget.redSide[0] != null) fetchRedSide(widget.redSide[0].userId); _scrollController = ScrollController(); super.initState(); } @override void dispose(){ - greenSideStates = null; - theGreenSide = null; - redSideStates = null; - theRedSide = null; + theGreenSide = [null, null, null]; + theRedSide = [null, null, null]; super.dispose(); } void fetchRedSide(String user) async { try { - theRedSide = await teto.fetchPlayer(user); + var tearDownToNumbers = numbersReg.allMatches(user); + if (tearDownToNumbers.length == 3) { + redSideMode = Mode.stats; + var threeNumbers = tearDownToNumbers.toList(); + double apm = double.parse(threeNumbers[0][0]!); + double pps = double.parse(threeNumbers[1][0]!); + double vs = double.parse(threeNumbers[2][0]!); + theRedSide = [null, + null, + TetraLeagueAlpha( + apm: apm, + pps: pps, + vs: vs, + rd: noTrRd, + gamesPlayed: -1, + gamesWon: -1, + bestRank: "z", + decaying: true, + rating: -1, + rank: "z", + percentileRank: "z", + percentile: 1, + standing: -1, + standingLocal: -1, + nextAt: -1, + prevAt: -1) + ]; + return setState(() {}); + } + var player = await teto.fetchPlayer(user); + //theRedSide + redSideMode = Mode.player; late List states; + List>? dStates = >[]; try{ - states = await teto.getPlayer(theRedSide!.userId); - redSideStates = >[]; + states = await teto.getPlayer(player.userId); for (final TetrioPlayer state in states) { - redSideStates!.add(DropdownMenuItem( + dStates.add(DropdownMenuItem( value: state, child: Text(dateFormat.format(state.state)))); } - redSideStates!.firstWhere((element) => element.value == theRedSide, orElse: () { - redSideStates!.add(DropdownMenuItem( - value: theRedSide!, child: const Text("Most recent one"))); + dStates.firstWhere((element) => element.value == player, orElse: () { + dStates?.add(DropdownMenuItem( + value: player, child: const Text("Most recent one"))); return DropdownMenuItem( - value: theRedSide!, child: const Text("Most recent one")); + value: player, child: const Text("Most recent one")); },); }on Exception { - states = []; - redSideStates = null; + dStates = null; } + theRedSide = [player, dStates, player.tlSeason1]; } on Exception { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text("Falied to assign $user"))); @@ -72,31 +115,61 @@ class CompareState extends State { } void changeRedSide(TetrioPlayer user) { - setState(() {theRedSide = user;}); + setState(() {theRedSide[0] = user; + theRedSide[2] = user.tlSeason1;}); } void fetchGreenSide(String user) async { try { - theGreenSide = await teto.fetchPlayer(user); + var tearDownToNumbers = numbersReg.allMatches(user); + if (tearDownToNumbers.length == 3) { + greenSideMode = Mode.stats; + var threeNumbers = tearDownToNumbers.toList(); + double apm = double.parse(threeNumbers[0][0]!); + double pps = double.parse(threeNumbers[1][0]!); + double vs = double.parse(threeNumbers[2][0]!); + theGreenSide = theRedSide = [null, + null, + TetraLeagueAlpha( + apm: apm, + pps: pps, + vs: vs, + rd: noTrRd, + gamesPlayed: -1, + gamesWon: -1, + bestRank: "z", + decaying: true, + rating: -1, + rank: "z", + percentileRank: "z", + percentile: 1, + standing: -1, + standingLocal: -1, + nextAt: -1, + prevAt: -1) + ]; + return setState(() {}); + } + var player = await teto.fetchPlayer(user); + greenSideMode = Mode.player; late List states; - greenSideStates = null; + List>? dStates = >[]; try{ - states = await teto.getPlayer(theGreenSide!.userId); - greenSideStates = >[]; + states = await teto.getPlayer(player.userId); for (final TetrioPlayer state in states) { - greenSideStates!.add(DropdownMenuItem( + dStates.add(DropdownMenuItem( value: state, child: Text(dateFormat.format(state.state)))); } - greenSideStates!.firstWhere((element) => element.value == theGreenSide, orElse: () { - greenSideStates!.add(DropdownMenuItem( - value: theGreenSide!, child: const Text("Most recent one"))); + dStates.firstWhere((element) => element.value == player, orElse: () { + dStates?.add(DropdownMenuItem( + value: player, child: const Text("Most recent one"))); return DropdownMenuItem( - value: theGreenSide!, child: const Text("Most recent one")); + value: player, child: const Text("Most recent one")); },); }on Exception { - states = []; - greenSideStates = null; + dStates = null; } + theGreenSide = [player, dStates, player.tlSeason1]; } on Exception { ScaffoldMessenger.of(context) .showSnackBar(SnackBar(content: Text("Falied to assign $user"))); @@ -105,7 +178,8 @@ class CompareState extends State { } void changeGreenSide(TetrioPlayer user) { - setState(() {theGreenSide = user;}); + setState(() {theGreenSide[0] = user; + theGreenSide[2] = user.tlSeason1;}); } double getWinrateByTR(double yourGlicko, double yourRD, double notyourGlicko, @@ -130,11 +204,32 @@ class CompareState extends State { @override Widget build(BuildContext context) { bool bigScreen = MediaQuery.of(context).size.width > 768; + String titleGreenSide; + String titleRedSide; + switch (greenSideMode){ + case Mode.player: + titleGreenSide = theGreenSide[0] != null ? theGreenSide[0].username.toUpperCase() : "???"; + break; + case Mode.stats: + titleGreenSide = "${theGreenSide[2].apm} APM, ${theGreenSide[2].pps} PPS, ${theGreenSide[2].vs} VS"; + break; + case Mode.averages: + titleGreenSide = "average"; + break; + } + switch (redSideMode){ + case Mode.player: + titleRedSide = theRedSide[0] != null ? theRedSide[0].username.toUpperCase() : "???"; + break; + case Mode.stats: + titleRedSide = "${theRedSide[2].apm} APM, ${theRedSide[2].pps} PPS, ${theRedSide[2].vs} VS"; + break; + case Mode.averages: + titleRedSide = "average"; + break; + } return Scaffold( - appBar: AppBar( - title: Text( - "${theGreenSide != null ? theGreenSide!.username.toUpperCase() : "???"} vs ${theRedSide != null ? theRedSide!.username.toUpperCase() : "???"}"), - ), + appBar: AppBar(title: Text("$titleGreenSide vs $titleRedSide")), backgroundColor: Colors.black, body: SafeArea( child: NestedScrollView( @@ -160,8 +255,8 @@ class CompareState extends State { child: Padding( padding: const EdgeInsets.fromLTRB(8, 0, 8, 0), child: PlayerSelector( - player: theGreenSide, - states: greenSideStates, + data: theGreenSide, + mode: greenSideMode, fetch: fetchGreenSide, change: changeGreenSide, updateState: _justUpdate, @@ -185,8 +280,8 @@ class CompareState extends State { child: Padding( padding: const EdgeInsets.fromLTRB(8, 0, 8, 0), child: PlayerSelector( - player: theRedSide, - states: redSideStates, + data: theRedSide, + mode: redSideMode, fetch: fetchRedSide, change: changeRedSide, updateState: _justUpdate, @@ -203,32 +298,33 @@ class CompareState extends State { ) ]; }, - body: theGreenSide != null && theRedSide != null - ? ListView( - children: [ - if (theGreenSide!.role != "banned" && - theRedSide!.role != "banned") + body: ListView( + children: !listEquals(theGreenSide, [null, null, null]) && !listEquals(theRedSide, [null, null, null])? [ + if (theGreenSide[0] != null && + theRedSide[0] != null && + theGreenSide[0]!.role != "banned" && + theRedSide[0]!.role != "banned") Column( children: [ CompareRegTimeThingy( - greenSide: theGreenSide!.registrationTime, - redSide: theRedSide!.registrationTime, + greenSide: theGreenSide[0].registrationTime, + redSide: theRedSide[0].registrationTime, label: "Registred"), CompareThingy( label: "Level", - greenSide: theGreenSide!.level, - redSide: theRedSide!.level, + greenSide: theGreenSide[0].level, + redSide: theRedSide[0].level, higherIsBetter: true, fractionDigits: 2, ), - if (!theGreenSide!.gameTime.isNegative && - !theRedSide!.gameTime.isNegative) + if (!theGreenSide[0].gameTime.isNegative && + !theRedSide[0].gameTime.isNegative) CompareThingy( - greenSide: theGreenSide!.gameTime.inMicroseconds / + greenSide: theGreenSide[0].gameTime.inMicroseconds / 1000000 / 60 / 60, - redSide: theRedSide!.gameTime.inMicroseconds / + redSide: theRedSide[0].gameTime.inMicroseconds / 1000000 / 60 / 60, @@ -236,39 +332,42 @@ class CompareState extends State { higherIsBetter: true, fractionDigits: 2, ), - if (theGreenSide!.gamesPlayed >= 0 && - theRedSide!.gamesPlayed >= 0) + if (theGreenSide[0].gamesPlayed >= 0 && + theRedSide[0].gamesPlayed >= 0) CompareThingy( label: "Online Games", - greenSide: theGreenSide!.gamesPlayed, - redSide: theRedSide!.gamesPlayed, + greenSide: theGreenSide[0].gamesPlayed, + redSide: theRedSide[0].gamesPlayed, higherIsBetter: true, ), - if (theGreenSide!.gamesWon >= 0 && - theRedSide!.gamesWon >= 0) + if (theGreenSide[0].gamesWon >= 0 && + theRedSide[0].gamesWon >= 0) CompareThingy( label: "Games Won", - greenSide: theGreenSide!.gamesWon, - redSide: theRedSide!.gamesWon, + greenSide: theGreenSide[0].gamesWon, + redSide: theRedSide[0].gamesWon, higherIsBetter: true, ), CompareThingy( label: "Friends", - greenSide: theGreenSide!.friendCount, - redSide: theRedSide!.friendCount, + greenSide: theGreenSide[0].friendCount, + redSide: theRedSide[0].friendCount, higherIsBetter: true, ), + const Divider(), ], - ) - else + ), + if (theGreenSide[0] != null && + theRedSide[0] != null && + (theGreenSide[0]!.role == "banned" || + theRedSide[0]!.role == "banned")) CompareBoolThingy( - greenSide: theGreenSide!.role == "banned", - redSide: theRedSide!.role == "banned", + greenSide: theGreenSide[0].role == "banned", + redSide: theRedSide[0].role == "banned", label: "Banned", trueIsBetter: false), - const Divider(), - theGreenSide!.tlSeason1.gamesPlayed > 0 && - theRedSide!.tlSeason1.gamesPlayed > 0 + (theGreenSide[2].gamesPlayed > 0 || greenSideMode == Mode.stats) && + (theRedSide[2].gamesPlayed > 0 || redSideMode == Mode.stats) ? Column( children: [ Padding( @@ -278,111 +377,123 @@ class CompareState extends State { fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), ), - if (theGreenSide!.tlSeason1.gamesPlayed > 9 && - theRedSide!.tlSeason1.gamesPlayed > 9) + if (theGreenSide[2].gamesPlayed > 9 && + theRedSide[2].gamesPlayed > 9 && + greenSideMode == Mode.player && + redSideMode == Mode.player) CompareThingy( label: "TR", - greenSide: theGreenSide!.tlSeason1.rating, - redSide: theRedSide!.tlSeason1.rating, + greenSide: theGreenSide[2].rating, + redSide: theRedSide[2].rating, fractionDigits: 2, higherIsBetter: true, ), + if (greenSideMode == Mode.player && + redSideMode == Mode.player) CompareThingy( label: "Games Played", - greenSide: theGreenSide!.tlSeason1.gamesPlayed, - redSide: theRedSide!.tlSeason1.gamesPlayed, + greenSide: theGreenSide[2].gamesPlayed, + redSide: theRedSide[2].gamesPlayed, higherIsBetter: true, ), + if (greenSideMode == Mode.player && + redSideMode == Mode.player) CompareThingy( label: "Games Won", - greenSide: theGreenSide!.tlSeason1.gamesWon, - redSide: theRedSide!.tlSeason1.gamesWon, + greenSide: theGreenSide[2].gamesWon, + redSide: theRedSide[2].gamesWon, higherIsBetter: true, ), + if (greenSideMode == Mode.player && + redSideMode == Mode.player) CompareThingy( label: "WR %", greenSide: - theGreenSide!.tlSeason1.winrate * 100, - redSide: theRedSide!.tlSeason1.winrate * 100, + theGreenSide[2].winrate * 100, + redSide: theRedSide[2].winrate * 100, fractionDigits: 2, higherIsBetter: true, ), - if (theGreenSide!.tlSeason1.gamesPlayed > 9 && - theRedSide!.tlSeason1.gamesPlayed > 9) + if (theGreenSide[2].gamesPlayed > 9 && + theRedSide[2].gamesPlayed > 9 && + greenSideMode == Mode.player && + redSideMode == Mode.player) CompareThingy( label: "Glicko", - greenSide: theGreenSide!.tlSeason1.glicko!, - redSide: theRedSide!.tlSeason1.glicko!, + greenSide: theGreenSide[2].glicko!, + redSide: theRedSide[2].glicko!, fractionDigits: 2, higherIsBetter: true, ), - if (theGreenSide!.tlSeason1.gamesPlayed > 9 && - theRedSide!.tlSeason1.gamesPlayed > 9) + if (theGreenSide[2].gamesPlayed > 9 && + theRedSide[2].gamesPlayed > 9 && + greenSideMode == Mode.player && + redSideMode == Mode.player) CompareThingy( label: "RD", - greenSide: theGreenSide!.tlSeason1.rd!, - redSide: theRedSide!.tlSeason1.rd!, + greenSide: theGreenSide[2].rd!, + redSide: theRedSide[2].rd!, fractionDigits: 3, higherIsBetter: false, ), - if (theGreenSide!.tlSeason1.standing > 0 && - theRedSide!.tlSeason1.standing > 0) + if (theGreenSide[2].standing > 0 && + theRedSide[2].standing > 0 && + greenSideMode == Mode.player && + redSideMode == Mode.player) CompareThingy( label: "№ in LB", - greenSide: theGreenSide!.tlSeason1.standing, - redSide: theRedSide!.tlSeason1.standing, + greenSide: theGreenSide[2].standing, + redSide: theRedSide[2].standing, higherIsBetter: false, ), - if (theGreenSide!.tlSeason1.standingLocal > 0 && - theRedSide!.tlSeason1.standingLocal > 0) + if (theGreenSide[2].standingLocal > 0 && + theRedSide[2].standingLocal > 0 && + greenSideMode == Mode.player && + redSideMode == Mode.player) CompareThingy( label: "№ in local LB", greenSide: - theGreenSide!.tlSeason1.standingLocal, - redSide: theRedSide!.tlSeason1.standingLocal, + theGreenSide[2].standingLocal, + redSide: theRedSide[2].standingLocal, higherIsBetter: false, ), - if (theGreenSide!.tlSeason1.apm != null && - theRedSide!.tlSeason1.apm != null) + if (theGreenSide[2].apm != null && + theRedSide[2].apm != null) CompareThingy( label: "APM", - greenSide: theGreenSide!.tlSeason1.apm!, - redSide: theRedSide!.tlSeason1.apm!, + greenSide: theGreenSide[2].apm!, + redSide: theRedSide[2].apm!, fractionDigits: 2, higherIsBetter: true, ), - if (theGreenSide!.tlSeason1.pps != null && - theRedSide!.tlSeason1.pps != null) + if (theGreenSide[2].pps != null && + theRedSide[2].pps != null) CompareThingy( label: "PPS", - greenSide: theGreenSide!.tlSeason1.pps!, - redSide: theRedSide!.tlSeason1.pps!, + greenSide: theGreenSide[2].pps!, + redSide: theRedSide[2].pps!, fractionDigits: 2, higherIsBetter: true, ), - if (theGreenSide!.tlSeason1.vs != null && - theRedSide!.tlSeason1.vs != null) + if (theGreenSide[2].vs != null && + theRedSide[2].vs != null) CompareThingy( label: "VS", - greenSide: theGreenSide!.tlSeason1.vs!, - redSide: theRedSide!.tlSeason1.vs!, + greenSide: theGreenSide[2].vs!, + redSide: theRedSide[2].vs!, fractionDigits: 2, higherIsBetter: true, ), ], ) : CompareBoolThingy( - greenSide: theGreenSide!.tlSeason1.gamesPlayed > 0, - redSide: theRedSide!.tlSeason1.gamesPlayed > 0, + greenSide: theGreenSide[2].gamesPlayed > 0, + redSide: theRedSide[2].gamesPlayed > 0, label: "Played Tetra League", trueIsBetter: false), const Divider(), - if (theGreenSide!.tlSeason1.apm != null && - theRedSide!.tlSeason1.apm != null && - theGreenSide!.tlSeason1.pps != null && - theRedSide!.tlSeason1.pps != null && - theGreenSide!.tlSeason1.vs != null && - theRedSide!.tlSeason1.vs != null) + if (theGreenSide[2].nerdStats != null && + theRedSide[2].nerdStats != null) Column( children: [ Padding( @@ -394,83 +505,85 @@ class CompareState extends State { ), CompareThingy( label: "APP", - greenSide: theGreenSide!.tlSeason1.nerdStats!.app, - redSide: theRedSide!.tlSeason1.nerdStats!.app, + greenSide: theGreenSide[2].nerdStats!.app, + redSide: theRedSide[2].nerdStats!.app, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( label: "VS/APM", - greenSide: theGreenSide!.tlSeason1.nerdStats!.vsapm, - redSide: theRedSide!.tlSeason1.nerdStats!.vsapm, + greenSide: theGreenSide[2].nerdStats!.vsapm, + redSide: theRedSide[2].nerdStats!.vsapm, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( label: "DS/S", - greenSide: theGreenSide!.tlSeason1.nerdStats!.dss, - redSide: theRedSide!.tlSeason1.nerdStats!.dss, + greenSide: theGreenSide[2].nerdStats!.dss, + redSide: theRedSide[2].nerdStats!.dss, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( label: "DS/P", - greenSide: theGreenSide!.tlSeason1.nerdStats!.dsp, - redSide: theRedSide!.tlSeason1.nerdStats!.dsp, + greenSide: theGreenSide[2].nerdStats!.dsp, + redSide: theRedSide[2].nerdStats!.dsp, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( label: "APP + DS/P", greenSide: - theGreenSide!.tlSeason1.nerdStats!.appdsp, - redSide: theRedSide!.tlSeason1.nerdStats!.appdsp, + theGreenSide[2].nerdStats!.appdsp, + redSide: theRedSide[2].nerdStats!.appdsp, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( label: "Cheese", greenSide: - theGreenSide!.tlSeason1.nerdStats!.cheese, - redSide: theRedSide!.tlSeason1.nerdStats!.cheese, + theGreenSide[2].nerdStats!.cheese, + redSide: theRedSide[2].nerdStats!.cheese, fractionDigits: 2, higherIsBetter: true, ), CompareThingy( label: "Garbage Eff.", - greenSide: theGreenSide!.tlSeason1.nerdStats!.gbe, - redSide: theRedSide!.tlSeason1.nerdStats!.gbe, + greenSide: theGreenSide[2].nerdStats!.gbe, + redSide: theRedSide[2].nerdStats!.gbe, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( label: "Weighted APP", greenSide: - theGreenSide!.tlSeason1.nerdStats!.nyaapp, - redSide: theRedSide!.tlSeason1.nerdStats!.nyaapp, + theGreenSide[2].nerdStats!.nyaapp, + redSide: theRedSide[2].nerdStats!.nyaapp, fractionDigits: 3, higherIsBetter: true, ), CompareThingy( label: "Area", - greenSide: theGreenSide!.tlSeason1.nerdStats!.area, - redSide: theRedSide!.tlSeason1.nerdStats!.area, + greenSide: theGreenSide[2].nerdStats!.area, + redSide: theRedSide[2].nerdStats!.area, fractionDigits: 2, higherIsBetter: true, ), CompareThingy( label: "Est. of TR", - greenSide: theGreenSide!.tlSeason1.estTr!.esttr, - redSide: theRedSide!.tlSeason1.estTr!.esttr, + greenSide: theGreenSide[2].estTr!.esttr, + redSide: theRedSide[2].estTr!.esttr, fractionDigits: 2, higherIsBetter: true, ), - if (theGreenSide!.tlSeason1.gamesPlayed > 9 && - theGreenSide!.tlSeason1.gamesPlayed > 9) + if (theGreenSide[2].gamesPlayed > 9 && + theGreenSide[2].gamesPlayed > 9 && + greenSideMode == Mode.player && + redSideMode == Mode.player) CompareThingy( label: "Acc. of Est.", - greenSide: theGreenSide!.tlSeason1.esttracc!, - redSide: theRedSide!.tlSeason1.esttracc!, + greenSide: theGreenSide[2].esttracc!, + redSide: theRedSide[2].esttracc!, fractionDigits: 2, higherIsBetter: true, ), @@ -503,142 +616,60 @@ class CompareState extends State { getTitle: (index, angle) { switch (index) { case 0: - return RadarChartTitle( - text: 'APM', - angle: angle, - ); + return RadarChartTitle(text: 'APM', angle: angle); case 1: - return RadarChartTitle( - text: 'PPS', - angle: angle, - ); + return RadarChartTitle(text: 'PPS', angle: angle); case 2: - return RadarChartTitle( - text: 'VS', angle: angle); + return RadarChartTitle(text: 'VS', angle: angle); case 3: - return RadarChartTitle( - text: 'APP', - angle: angle + 180); + return RadarChartTitle(text: 'APP', angle: angle + 180); case 4: - return RadarChartTitle( - text: 'DS/S', - angle: angle + 180); + return RadarChartTitle(text: 'DS/S', angle: angle + 180); case 5: - return RadarChartTitle( - text: 'DS/P', - angle: angle + 180); + return RadarChartTitle(text: 'DS/P', angle: angle + 180); case 6: - return RadarChartTitle( - text: 'APP+DS/P', - angle: angle + 180); + return RadarChartTitle(text: 'APP+DS/P', angle: angle + 180); case 7: - return RadarChartTitle( - text: 'VS/APM', - angle: angle + 180); + return RadarChartTitle(text: 'VS/APM', angle: angle + 180); case 8: - return RadarChartTitle( - text: 'Cheese', angle: angle); + return RadarChartTitle(text: 'Cheese', angle: angle); case 9: - return RadarChartTitle( - text: 'Gb Eff.', angle: angle); + return RadarChartTitle(text: 'Gb Eff.', angle: angle); default: - return const RadarChartTitle( - text: ''); + return const RadarChartTitle(text: ''); } }, dataSets: [ RadarDataSet( - fillColor: const Color.fromARGB( - 115, 76, 175, 79), + fillColor: const Color.fromARGB(115, 76, 175, 79), borderColor: Colors.green, dataEntries: [ - RadarEntry( - value: theGreenSide! - .tlSeason1.apm! * - apmWeight), - RadarEntry( - value: theGreenSide! - .tlSeason1.pps! * - ppsWeight), - RadarEntry( - value: theGreenSide! - .tlSeason1.vs! * - vsWeight), - RadarEntry( - value: theGreenSide!.tlSeason1 - .nerdStats!.app * - appWeight), - RadarEntry( - value: theGreenSide!.tlSeason1 - .nerdStats!.dss * - dssWeight), - RadarEntry( - value: theGreenSide!.tlSeason1 - .nerdStats!.dsp * - dspWeight), - RadarEntry( - value: theGreenSide!.tlSeason1 - .nerdStats!.appdsp * - appdspWeight), - RadarEntry( - value: theGreenSide!.tlSeason1 - .nerdStats!.vsapm * - vsapmWeight), - RadarEntry( - value: theGreenSide!.tlSeason1 - .nerdStats!.cheese * - cheeseWeight), - RadarEntry( - value: theGreenSide!.tlSeason1 - .nerdStats!.gbe * - gbeWeight), + RadarEntry(value: theGreenSide[2].apm! * apmWeight), + RadarEntry(value: theGreenSide[2].pps! * ppsWeight), + RadarEntry(value: theGreenSide[2].vs! * vsWeight), + RadarEntry(value: theGreenSide[2].nerdStats!.app * appWeight), + RadarEntry(value: theGreenSide[2].nerdStats!.dss * dssWeight), + RadarEntry(value: theGreenSide[2].nerdStats!.dsp * dspWeight), + RadarEntry(value: theGreenSide[2].nerdStats!.appdsp * appdspWeight), + RadarEntry(value: theGreenSide[2].nerdStats!.vsapm * vsapmWeight), + RadarEntry(value: theGreenSide[2].nerdStats!.cheese * cheeseWeight), + RadarEntry(value: theGreenSide[2].nerdStats!.gbe * gbeWeight), ], ), RadarDataSet( - fillColor: const Color.fromARGB( - 115, 244, 67, 54), + fillColor: const Color.fromARGB(115, 244, 67, 54), borderColor: Colors.red, dataEntries: [ - RadarEntry( - value: - theRedSide!.tlSeason1.apm! * - 1), - RadarEntry( - value: - theRedSide!.tlSeason1.pps! * - 45), - RadarEntry( - value: - theRedSide!.tlSeason1.vs! * - 0.444), - RadarEntry( - value: theRedSide!.tlSeason1 - .nerdStats!.app * - 185), - RadarEntry( - value: theRedSide!.tlSeason1 - .nerdStats!.dss * - 175), - RadarEntry( - value: theRedSide!.tlSeason1 - .nerdStats!.dsp * - 450), - RadarEntry( - value: theRedSide!.tlSeason1 - .nerdStats!.appdsp * - 140), - RadarEntry( - value: theRedSide!.tlSeason1 - .nerdStats!.vsapm * - 60), - RadarEntry( - value: theRedSide!.tlSeason1 - .nerdStats!.cheese * - 1.25), - RadarEntry( - value: theRedSide!.tlSeason1 - .nerdStats!.gbe * - 315), + RadarEntry(value: theRedSide[2].apm! * apmWeight), + RadarEntry(value: theRedSide[2].pps! * ppsWeight), + RadarEntry(value: theRedSide[2].vs! * vsWeight), + RadarEntry(value: theRedSide[2].nerdStats!.app * appWeight), + RadarEntry(value: theRedSide[2].nerdStats!.dss * dssWeight), + RadarEntry(value: theRedSide[2].nerdStats!.dsp * dspWeight), + RadarEntry(value: theRedSide[2].nerdStats!.appdsp * appdspWeight), + RadarEntry(value: theRedSide[2].nerdStats!.vsapm * vsapmWeight), + RadarEntry(value: theRedSide[2].nerdStats!.cheese * cheeseWeight), + RadarEntry(value: theRedSide[2].nerdStats!.gbe * gbeWeight), ], ), RadarDataSet( @@ -659,10 +690,8 @@ class CompareState extends State { ) ], ), - swapAnimationDuration: const Duration( - milliseconds: 150), // Optional - swapAnimationCurve: - Curves.linear, // Optional + swapAnimationDuration: const Duration(milliseconds: 150), + swapAnimationCurve: Curves.linear, ), ), ), @@ -688,64 +717,36 @@ class CompareState extends State { getTitle: (index, angle) { switch (index) { case 0: - return RadarChartTitle( - text: 'Opener', - angle: angle, - ); + return RadarChartTitle(text: 'Opener',angle: angle); case 1: - return RadarChartTitle( - text: 'Stride', - angle: angle, - ); + return RadarChartTitle(text: 'Stride', angle: angle); case 2: - return RadarChartTitle( - text: 'Inf Ds', - angle: angle + 180); + return RadarChartTitle(text: 'Inf Ds', angle: angle + 180); case 3: - return RadarChartTitle( - text: 'Plonk', angle: angle); + return RadarChartTitle(text: 'Plonk', angle: angle); default: - return const RadarChartTitle( - text: ''); + return const RadarChartTitle(text: ''); } }, dataSets: [ RadarDataSet( - fillColor: const Color.fromARGB( - 115, 76, 175, 79), + fillColor: const Color.fromARGB(115, 76, 175, 79), borderColor: Colors.green, dataEntries: [ - RadarEntry( - value: theGreenSide!.tlSeason1 - .playstyle!.opener), - RadarEntry( - value: theGreenSide!.tlSeason1 - .playstyle!.stride), - RadarEntry( - value: theGreenSide!.tlSeason1 - .playstyle!.infds), - RadarEntry( - value: theGreenSide!.tlSeason1 - .playstyle!.plonk), + RadarEntry(value: theGreenSide[2].playstyle!.opener), + RadarEntry(value: theGreenSide[2].playstyle!.stride), + RadarEntry(value: theGreenSide[2].playstyle!.infds), + RadarEntry(value: theGreenSide[2].playstyle!.plonk), ], ), RadarDataSet( - fillColor: const Color.fromARGB( - 115, 244, 67, 54), + fillColor: const Color.fromARGB(115, 244, 67, 54), borderColor: Colors.red, dataEntries: [ - RadarEntry( - value: theRedSide!.tlSeason1 - .playstyle!.opener), - RadarEntry( - value: theRedSide!.tlSeason1 - .playstyle!.stride), - RadarEntry( - value: theRedSide!.tlSeason1 - .playstyle!.infds), - RadarEntry( - value: theRedSide!.tlSeason1 - .playstyle!.plonk), + RadarEntry(value: theRedSide[2].playstyle!.opener), + RadarEntry(value: theRedSide[2].playstyle!.stride), + RadarEntry(value: theRedSide[2].playstyle!.infds), + RadarEntry(value: theRedSide[2].playstyle!.plonk), ], ), RadarDataSet( @@ -770,10 +771,8 @@ class CompareState extends State { ) ], ), - swapAnimationDuration: const Duration( - milliseconds: 150), // Optional - swapAnimationCurve: - Curves.linear, // Optional + swapAnimationDuration: const Duration(milliseconds: 150), // Optional + swapAnimationCurve: Curves.linear, // Optional ), ), ), @@ -785,19 +784,20 @@ class CompareState extends State { fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), ), + if (greenSideMode == Mode.player && redSideMode == Mode.player) CompareThingy( label: "By Glicko", greenSide: getWinrateByTR( - theGreenSide!.tlSeason1.glicko!, - theGreenSide!.tlSeason1.rd!, - theRedSide!.tlSeason1.glicko!, - theRedSide!.tlSeason1.rd!) * + theGreenSide[2].glicko!, + theGreenSide[2].rd!, + theRedSide[2].glicko!, + theRedSide[2].rd!) * 100, redSide: getWinrateByTR( - theRedSide!.tlSeason1.glicko!, - theRedSide!.tlSeason1.rd!, - theGreenSide!.tlSeason1.glicko!, - theGreenSide!.tlSeason1.rd!) * + theRedSide[2].glicko!, + theRedSide[2].rd!, + theGreenSide[2].glicko!, + theGreenSide[2].rd!) * 100, fractionDigits: 2, higherIsBetter: true, @@ -805,16 +805,16 @@ class CompareState extends State { CompareThingy( label: "By Est. TR", greenSide: getWinrateByTR( - theGreenSide!.tlSeason1.estTr!.estglicko, - theGreenSide!.tlSeason1.rd!, - theRedSide!.tlSeason1.estTr!.estglicko, - theRedSide!.tlSeason1.rd!) * + theGreenSide[2].estTr!.estglicko, + theGreenSide[2].rd!, + theRedSide[2].estTr!.estglicko, + theRedSide[2].rd!) * 100, redSide: getWinrateByTR( - theRedSide!.tlSeason1.estTr!.estglicko, - theRedSide!.tlSeason1.rd!, - theGreenSide!.tlSeason1.estTr!.estglicko, - theGreenSide!.tlSeason1.rd!) * + theRedSide[2].estTr!.estglicko, + theRedSide[2].rd!, + theGreenSide[2].estTr!.estglicko, + theGreenSide[2].rd!) * 100, fractionDigits: 2, higherIsBetter: true, @@ -823,9 +823,8 @@ class CompareState extends State { ) ], ) - ], + ] : [Text("Please, enter username, user ID, or APM-PPS-VS values (divider doesn't matter) to both of fields")], ) - : const Text("Please enter valid nicknames"), ), ), ); @@ -833,21 +832,35 @@ class CompareState extends State { } class PlayerSelector extends StatelessWidget { - final TetrioPlayer? player; - final List>? states; + final List data; + final Mode mode; final Function fetch; final Function change; final Function updateState; const PlayerSelector( {super.key, - required this.player, + required this.data, + required this.mode, required this.updateState, - required this.fetch, this.states, required this.change, }); + required this.fetch, + required this.change}); @override Widget build(BuildContext context) { final TextEditingController playerController = TextEditingController(); - if (player != null) playerController.text = player!.username; + if (!listEquals(data, [null, null, null])){ + switch (mode){ + case Mode.player: + playerController.text = data[0] != null ? data[0].username : "???"; + break; + case Mode.stats: + playerController.text = "${data[2].apm} ${data[2].pps} ${data[2].vs}"; + break; + case Mode.averages: + playerController.text = "average"; + break; + } + } return Column( children: [ TextField( @@ -859,9 +872,9 @@ class PlayerSelector extends StatelessWidget { onSubmitted: (String value) { fetch(value); }), - if (player != null && states == null) + if (data[0] != null && data[1] == null) Text( - player!.toString(), + data[0].toString(), style: const TextStyle( shadows: [ Shadow( @@ -877,13 +890,12 @@ class PlayerSelector extends StatelessWidget { ], ), ), - if (player != null && states != null) + if (data[0] != null && data[1] != null) Padding( padding: const EdgeInsets.only(bottom: 8.0), child: DropdownButton( - items: states, - value: player, - //style: TextStyle(overflow: TextOverflow.clip), + items: data[1], + value: data[0], onChanged: (value) => change(value!), ), ) diff --git a/lib/views/settings_view.dart b/lib/views/settings_view.dart index 8ae3fbf..9f3b1ab 100644 --- a/lib/views/settings_view.dart +++ b/lib/views/settings_view.dart @@ -140,18 +140,18 @@ class SettingsState extends State { var newDB = value.paths[0]!; teto.close().then((value){ if(!newDB.endsWith("db")){ - return ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Wrong file type"))); + return ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Wrong file type"))); } getApplicationDocumentsDirectory().then((value){ var oldDB = File("${value.path}/TetraStats.db"); oldDB.writeAsBytes(File(newDB).readAsBytesSync(), flush: true).then((value){ teto.open(); - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Import successful"))); + ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Import successful"))); }); }); }); } else { - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Operation was cancelled"))); + ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Operation was cancelled"))); } }); }else{ @@ -167,12 +167,12 @@ class SettingsState extends State { var oldDB = File("${value.path}/TetraStats.db"); oldDB.writeAsBytes(File(newDB).readAsBytesSync()).then((value){ teto.open(); - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Import successful"))); + ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Import successful"))); }); }); }); } else { - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Operation was cancelled"))); + ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Operation was cancelled"))); } }); } diff --git a/lib/widgets/user_thingy.dart b/lib/widgets/user_thingy.dart index 9eff288..95227ef 100644 --- a/lib/widgets/user_thingy.dart +++ b/lib/widgets/user_thingy.dart @@ -152,7 +152,7 @@ class UserThingy extends StatelessWidget { Navigator.push( context, MaterialPageRoute( - builder: (context) => CompareView(greenSide: player, redSide: null), + builder: (context) => CompareView(greenSide: [player, null, player.tlSeason1], redSide: const [null, null, null], greenMode: Mode.player, redMode: Mode.player), ), ); },