diff --git a/lib/data_objects/tetrio.dart b/lib/data_objects/tetrio.dart index 74de230..9ba703d 100644 --- a/lib/data_objects/tetrio.dart +++ b/lib/data_objects/tetrio.dart @@ -460,7 +460,7 @@ class NerdStats { dss = (_vs / 100) - (_apm / 60); dsp = ((_vs / 100) - (_apm / 60)) / _pps; appdsp = app + dsp; - cheese = (dsp * 150) + (((_vs / _apm) - 2) * 50) + (0.6 - app) * 125; + cheese = (dsp * 150) + ((vsapm - 2) * 50) + (0.6 - app) * 125; gbe = ((app * dss) / _pps) * 2; nyaapp = app - 5 * tan(radians((cheese / -30) + 1)); area = _apm * 1 + _pps * 45 + _vs * 0.444 + app * 185 + dss * 175 + dsp * 450 + gbe * 315; diff --git a/lib/views/main_view.dart b/lib/views/main_view.dart index d24c8b8..0290353 100644 --- a/lib/views/main_view.dart +++ b/lib/views/main_view.dart @@ -1,5 +1,4 @@ import 'dart:io'; - import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'dart:math'; diff --git a/lib/widgets/stat_sell_num.dart b/lib/widgets/stat_sell_num.dart index 667f7a9..fa5ec29 100644 --- a/lib/widgets/stat_sell_num.dart +++ b/lib/widgets/stat_sell_num.dart @@ -2,17 +2,24 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; class StatCellNum extends StatelessWidget { - const StatCellNum({super.key, required this.playerStat, required this.playerStatLabel, required this.isScreenBig, this.snackBar, this.fractionDigits}); + const StatCellNum( + {super.key, + required this.playerStat, + required this.playerStatLabel, + required this.isScreenBig, + this.alertWidgets, + this.fractionDigits}); final num playerStat; final String playerStatLabel; final bool isScreenBig; - final String? snackBar; + final List? alertWidgets; final int? fractionDigits; @override Widget build(BuildContext context) { - NumberFormat f = NumberFormat.decimalPatternDigits(decimalDigits: fractionDigits ?? 0); + NumberFormat f = + NumberFormat.decimalPatternDigits(decimalDigits: fractionDigits ?? 0); return Column( children: [ Text( @@ -22,7 +29,7 @@ class StatCellNum extends StatelessWidget { fontSize: isScreenBig ? 32 : 24, ), ), - snackBar == null + alertWidgets == null ? Text( playerStatLabel, textAlign: TextAlign.center, @@ -33,9 +40,27 @@ class StatCellNum extends StatelessWidget { ) : TextButton( onPressed: () { - ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(snackBar!))); + showDialog( + context: context, + builder: (BuildContext context) => AlertDialog( + title: Text(playerStatLabel, + style: const TextStyle( + fontFamily: "Eurostile Round Extended")), + content: SingleChildScrollView( + child: ListBody(children: alertWidgets!), + ), + actions: [ + TextButton( + child: const Text('OK'), + onPressed: () { + Navigator.of(context).pop(); + }, + ) + ], + )); }, - style: ButtonStyle(padding: MaterialStateProperty.all(EdgeInsets.zero)), + style: ButtonStyle( + padding: MaterialStateProperty.all(EdgeInsets.zero)), child: Text( playerStatLabel, textAlign: TextAlign.center, diff --git a/lib/widgets/tl_thingy.dart b/lib/widgets/tl_thingy.dart index 00e0b26..5670567 100644 --- a/lib/widgets/tl_thingy.dart +++ b/lib/widgets/tl_thingy.dart @@ -2,10 +2,12 @@ import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:tetra_stats/data_objects/tetrio.dart'; import 'package:fl_chart/fl_chart.dart'; +import 'package:syncfusion_flutter_gauges/gauges.dart'; import 'package:tetra_stats/widgets/stat_sell_num.dart'; var fDiff = NumberFormat("+#,###.###;-#,###.###"); final NumberFormat f2 = NumberFormat.decimalPatternDigits(decimalDigits: 2); +final NumberFormat f3 = NumberFormat.decimalPatternDigits(decimalDigits: 3); class TLThingy extends StatelessWidget { final TetraLeagueAlpha tl; @@ -44,8 +46,22 @@ class TLThingy extends StatelessWidget { ], ), ], - ) - else + ), + if (tl.gamesPlayed >= 10 && tl.rd! < 100) Padding( + padding: const EdgeInsets.all(8.0), + child: SfLinearGauge( + minimum: tl.nextAt.toDouble(), + maximum: tl.prevAt.toDouble(), + interval: tl.prevAt.toDouble() - tl.nextAt.toDouble(), + ranges: [LinearGaugeRange(startValue: tl.standing.toDouble(), endValue: tl.prevAt.toDouble(), color: Colors.cyanAccent,)], + //barPointers: [LinearBarPointer(value: 80)], + isAxisInversed: true, + isMirrored: true, + showTicks: true, + showLabels: true + ), + ), + if (tl.gamesPlayed < 10) Text("${10 - tl.gamesPlayed} games until being ranked", softWrap: true, textAlign: TextAlign.center, @@ -81,27 +97,120 @@ class TLThingy extends StatelessWidget { children: [ Text("Nerd Stats", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), Padding( - padding: const EdgeInsets.fromLTRB(0, 16, 0, 48), + padding: const EdgeInsets.fromLTRB(0, 40, 0, 0), child: Wrap( direction: Axis.horizontal, alignment: WrapAlignment.center, - spacing: 25, + spacing: 35, crossAxisAlignment: WrapCrossAlignment.start, clipBehavior: Clip.hardEdge, children: [ - StatCellNum(playerStat: tl.nerdStats!.app, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Attack\nPer Piece"), - StatCellNum(playerStat: tl.nerdStats!.vsapm, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "VS/APM"), - StatCellNum( - playerStat: tl.nerdStats!.dss, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Downstack\nPer Second"), - StatCellNum( - playerStat: tl.nerdStats!.dsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Downstack\nPer Piece"), - StatCellNum(playerStat: tl.nerdStats!.appdsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "APP + DS/P"), - StatCellNum(playerStat: tl.nerdStats!.cheese, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: "Cheese\nIndex"), - StatCellNum(playerStat: tl.nerdStats!.gbe, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Garbage\nEfficiency"), - StatCellNum(playerStat: tl.nerdStats!.nyaapp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Weighted\nAPP"), - StatCellNum(playerStat: tl.nerdStats!.area, isScreenBig: bigScreen, fractionDigits: 1, playerStatLabel: "Area") - ]), - ) + SizedBox( + width: 200, + height: 120, + child: SfRadialGauge( + title: const GaugeTitle(text: "Attack Per Piece"), + axes: [RadialAxis( + startAngle: 180, + endAngle: 360, + showLabels: false, + showTicks: false, + radiusFactor: 2.1, + centerY: 0.3, + minimum: 0, + maximum: 1, + ranges: [ + GaugeRange(startValue: 0, endValue: 0.2, color: Colors.red), + GaugeRange(startValue: 0.2, endValue: 0.4, color: Colors.yellow), + GaugeRange(startValue: 0.4, endValue: 0.6, color: Colors.green), + GaugeRange(startValue: 0.6, endValue: 0.8, color: Colors.blue), + GaugeRange(startValue: 0.8, endValue: 1, color: Colors.purple), + ], + pointers: [ + NeedlePointer( + value: tl.nerdStats!.app, + enableAnimation: true, + needleLength: 0.9, + needleStartWidth: 2, + needleEndWidth: 15, + knobStyle: const KnobStyle(color: Colors.transparent), + gradient: const LinearGradient(colors: [Colors.transparent, Colors.white], begin: Alignment.bottomCenter, end: Alignment.topCenter, stops: [0.5, 1]),) + ], + annotations: [GaugeAnnotation(widget: Text(f3.format(tl.nerdStats!.app), style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36)))], + )],), + ), + SizedBox( + width: 200, + height: 120, + child: SfRadialGauge( + title: const GaugeTitle(text: "VS / APM"), + axes: [RadialAxis( + startAngle: 180, + endAngle: 360, + showTicks: false, + showLabels: false, + radiusFactor: 2.1, + centerY: 0.3, + 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), + GaugeRange(startValue: 2.2, endValue: 2.4, color: Colors.purple), + ], + pointers: [ + NeedlePointer( + value: tl.nerdStats!.vsapm, + enableAnimation: true, + needleLength: 0.9, + needleStartWidth: 2, + needleEndWidth: 15, + knobStyle: const KnobStyle(color: Colors.transparent), + gradient: const LinearGradient(colors: [Colors.transparent, Colors.white], begin: Alignment.bottomCenter, end: Alignment.topCenter, stops: [0.5, 1]),) + ], + annotations: [GaugeAnnotation(widget: Text(f3.format(tl.nerdStats!.vsapm), style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36)))], + )],), + ),]), + ), + Wrap( + direction: Axis.horizontal, + alignment: WrapAlignment.center, + spacing: 25, + crossAxisAlignment: WrapCrossAlignment.start, + clipBehavior: Clip.hardEdge, + children: [ + //StatCellNum(playerStat: tl.nerdStats!.app, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Attack\nPer Piece"), + //StatCellNum(playerStat: tl.nerdStats!.vsapm, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "VS/APM"), + StatCellNum(playerStat: tl.nerdStats!.dss, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Downstack\nPer Second", + alertWidgets: [const Text("Downstack per Second measures how many garbage lines you clear in a second."), + const Text("Formula: (VS / 100) - (APM / 60)"), + Text("(${tl.vs} / 100) - (${tl.apm} / 60) = ${tl.nerdStats!.dss}"),], + ), + StatCellNum(playerStat: tl.nerdStats!.dsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Downstack\nPer Piece", + alertWidgets: [const Text("Downstack per Piece measures how many garbage lines you clear per piece."), + const Text("Formula: DS/S / PPS"), + Text("${tl.nerdStats!.dss} / ${tl.pps} = ${tl.nerdStats!.dsp}"),],), + StatCellNum(playerStat: tl.nerdStats!.appdsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "APP + DS/P", + alertWidgets: [const Text("Just a sum of Attack per Piece and Downstack per Piece."), + const Text("Formula: APP + DS/P"), + Text("${tl.nerdStats!.app} + ${tl.nerdStats!.dsp} = ${tl.nerdStats!.appdsp}"),]), + StatCellNum(playerStat: tl.nerdStats!.cheese, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: "Cheese\nIndex", + alertWidgets: [const Text("Cheese Index is an approximation how much clean / cheese garbage player sends. Lower = more clean. Higher = more cheese.\nInvented by kerrmunism"), + const Text("Formula: (DS/P * 150) + ((VS/APM - 2) * 50) + (0.6 - APP) * 125"), + Text("(${tl.nerdStats!.dsp} * 150) + ((${tl.nerdStats!.vsapm} - 2) * 50) + (0.6 - ${tl.nerdStats!.app}) * 125 = ${tl.nerdStats!.cheese}"),]), + StatCellNum(playerStat: tl.nerdStats!.gbe, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Garbage\nEfficiency", + alertWidgets: [const Text("Garbage Efficiency measures how well player uses their garbage. Higher = better or they use their garbage more. Lower = they mostly send their garbage back at cheese or rarely clear garbage.\nInvented by Zepheniah and Dragonboy."), + const Text("Formula: ((APP * DS/S) / PPS) * 2"), + Text("((${tl.nerdStats!.app} * ${tl.nerdStats!.dss}) / ${tl.pps}) * 2 = ${tl.nerdStats!.gbe}"),]), + StatCellNum(playerStat: tl.nerdStats!.nyaapp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Weighted\nAPP", + alertWidgets: [const Text("Essentially, a measure of your ability to send cheese while still maintaining a high APP.\nInvented by Wertj."), + const Text("Formula: APP - 5 * tan(radians((Cheese Index / -30) + 1))"), + Text("${tl.nerdStats!.app} - 5 * tan(radians((${tl.nerdStats!.cheese} / -30) + 1)) = ${tl.nerdStats!.nyaapp}"),]), + StatCellNum(playerStat: tl.nerdStats!.area, isScreenBig: bigScreen, fractionDigits: 1, playerStatLabel: "Area", + alertWidgets: [const Text("How much space your shape takes up on the graph, if you exclude the cheese and vs/apm sections"), + const Text("Formula: APM * 1 + PPS * 45 + VS * 0.444 + APP * 185 + DS/S * 175 + DS/P * 450 + Garbage Effi * 315"), + Text("${tl.apm} * 1 + ${tl.pps} * 45 + ${tl.vs} * 0.444 + ${tl.nerdStats!.app} * 185 + ${tl.nerdStats!.dss} * 175 + ${tl.nerdStats!.dsp} * 450 + ${tl.nerdStats!.gbe} * 315 = ${tl.nerdStats!.area}"),]) + ]) ], ), if (tl.estTr != null) diff --git a/lib/widgets/user_thingy.dart b/lib/widgets/user_thingy.dart index 0f2f808..cf3469a 100644 --- a/lib/widgets/user_thingy.dart +++ b/lib/widgets/user_thingy.dart @@ -175,11 +175,11 @@ class UserThingy extends StatelessWidget { playerStat: player.level, playerStatLabel: "XP Level", isScreenBig: bigScreen, - snackBar: "${player.xp.floor().toString()} XP, ${((player.level - player.level.floor()) * 100).toStringAsFixed(2)} % until next level", + alertWidgets: [Text("${NumberFormat.decimalPatternDigits(decimalDigits: 2).format(player.xp)} XP", style: const TextStyle(fontFamily: "Eurostile Round Extended"),), Text("Progress to next level: ${((player.level - player.level.floor()) * 100).toStringAsFixed(2)} %"), Text("Progress from 0 XP to level 5000: ${((player.xp / 67009017.7589378) * 100).toStringAsFixed(2)} %")], ), if (player.gameTime >= Duration.zero) StatCellNum( - playerStat: player.gameTime.inHours, playerStatLabel: "Hours\nPlayed", isScreenBig: bigScreen, snackBar: player.gameTime.toString()), + playerStat: player.gameTime.inHours, playerStatLabel: "Hours\nPlayed", isScreenBig: bigScreen, alertWidgets: [Text("Exact gametime: ${player.gameTime.toString()}")]), if (player.gamesPlayed >= 0) StatCellNum(playerStat: player.gamesPlayed, isScreenBig: bigScreen, playerStatLabel: "Online\nGames"), if (player.gamesWon >= 0) StatCellNum(playerStat: player.gamesWon, isScreenBig: bigScreen, playerStatLabel: "Games\nWon"), if (player.friendCount > 0) StatCellNum(playerStat: player.friendCount, isScreenBig: bigScreen, playerStatLabel: "Friends"), diff --git a/pubspec.lock b/pubspec.lock index a69fe72..31e7132 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -405,6 +405,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.0" + syncfusion_flutter_core: + dependency: transitive + description: + name: syncfusion_flutter_core + sha256: "952f5ee970bc3fba2db95a8dac71a295d9a70ad2c0993c7279e3a883c3e1459f" + url: "https://pub.dev" + source: hosted + version: "22.1.34" + syncfusion_flutter_gauges: + dependency: "direct main" + description: + name: syncfusion_flutter_gauges + sha256: "623c61387a425755819a659bb20b64845328bdbb60130c13c37896a7f61db8a7" + url: "https://pub.dev" + source: hosted + version: "22.1.34" synchronized: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index c9f1b7f..a8d4a65 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,6 +40,7 @@ dependencies: package_info_plus: ^4.0.2 shared_preferences: ^2.1.1 intl: ^0.18.1 + syncfusion_flutter_gauges: ^22.1.34 dev_dependencies: flutter_test: