New gauges + info for stats

This commit is contained in:
dan63047 2023-06-27 23:55:59 +03:00
parent 041b70a86c
commit 3199bd26ec
7 changed files with 177 additions and 27 deletions

View File

@ -460,7 +460,7 @@ class NerdStats {
dss = (_vs / 100) - (_apm / 60); dss = (_vs / 100) - (_apm / 60);
dsp = ((_vs / 100) - (_apm / 60)) / _pps; dsp = ((_vs / 100) - (_apm / 60)) / _pps;
appdsp = app + dsp; 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; gbe = ((app * dss) / _pps) * 2;
nyaapp = app - 5 * tan(radians((cheese / -30) + 1)); nyaapp = app - 5 * tan(radians((cheese / -30) + 1));
area = _apm * 1 + _pps * 45 + _vs * 0.444 + app * 185 + dss * 175 + dsp * 450 + gbe * 315; area = _apm * 1 + _pps * 45 + _vs * 0.444 + app * 185 + dss * 175 + dsp * 450 + gbe * 315;

View File

@ -1,5 +1,4 @@
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'dart:math'; import 'dart:math';

View File

@ -2,17 +2,24 @@ import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
class StatCellNum extends StatelessWidget { 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 num playerStat;
final String playerStatLabel; final String playerStatLabel;
final bool isScreenBig; final bool isScreenBig;
final String? snackBar; final List<Widget>? alertWidgets;
final int? fractionDigits; final int? fractionDigits;
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
NumberFormat f = NumberFormat.decimalPatternDigits(decimalDigits: fractionDigits ?? 0); NumberFormat f =
NumberFormat.decimalPatternDigits(decimalDigits: fractionDigits ?? 0);
return Column( return Column(
children: [ children: [
Text( Text(
@ -22,7 +29,7 @@ class StatCellNum extends StatelessWidget {
fontSize: isScreenBig ? 32 : 24, fontSize: isScreenBig ? 32 : 24,
), ),
), ),
snackBar == null alertWidgets == null
? Text( ? Text(
playerStatLabel, playerStatLabel,
textAlign: TextAlign.center, textAlign: TextAlign.center,
@ -33,9 +40,27 @@ class StatCellNum extends StatelessWidget {
) )
: TextButton( : TextButton(
onPressed: () { 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: <Widget>[
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( child: Text(
playerStatLabel, playerStatLabel,
textAlign: TextAlign.center, textAlign: TextAlign.center,

View File

@ -2,10 +2,12 @@ import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:tetra_stats/data_objects/tetrio.dart'; import 'package:tetra_stats/data_objects/tetrio.dart';
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:syncfusion_flutter_gauges/gauges.dart';
import 'package:tetra_stats/widgets/stat_sell_num.dart'; import 'package:tetra_stats/widgets/stat_sell_num.dart';
var fDiff = NumberFormat("+#,###.###;-#,###.###"); var fDiff = NumberFormat("+#,###.###;-#,###.###");
final NumberFormat f2 = NumberFormat.decimalPatternDigits(decimalDigits: 2); final NumberFormat f2 = NumberFormat.decimalPatternDigits(decimalDigits: 2);
final NumberFormat f3 = NumberFormat.decimalPatternDigits(decimalDigits: 3);
class TLThingy extends StatelessWidget { class TLThingy extends StatelessWidget {
final TetraLeagueAlpha tl; 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", Text("${10 - tl.gamesPlayed} games until being ranked",
softWrap: true, softWrap: true,
textAlign: TextAlign.center, textAlign: TextAlign.center,
@ -81,27 +97,120 @@ class TLThingy extends StatelessWidget {
children: [ children: [
Text("Nerd Stats", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), Text("Nerd Stats", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
Padding( Padding(
padding: const EdgeInsets.fromLTRB(0, 16, 0, 48), padding: const EdgeInsets.fromLTRB(0, 40, 0, 0),
child: Wrap( child: Wrap(
direction: Axis.horizontal, direction: Axis.horizontal,
alignment: WrapAlignment.center, alignment: WrapAlignment.center,
spacing: 25, spacing: 35,
crossAxisAlignment: WrapCrossAlignment.start, crossAxisAlignment: WrapCrossAlignment.start,
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
children: [ children: [
StatCellNum(playerStat: tl.nerdStats!.app, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Attack\nPer Piece"), SizedBox(
StatCellNum(playerStat: tl.nerdStats!.vsapm, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "VS/APM"), width: 200,
StatCellNum( height: 120,
playerStat: tl.nerdStats!.dss, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Downstack\nPer Second"), child: SfRadialGauge(
StatCellNum( title: const GaugeTitle(text: "Attack Per Piece"),
playerStat: tl.nerdStats!.dsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Downstack\nPer Piece"), axes: [RadialAxis(
StatCellNum(playerStat: tl.nerdStats!.appdsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "APP + DS/P"), startAngle: 180,
StatCellNum(playerStat: tl.nerdStats!.cheese, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: "Cheese\nIndex"), endAngle: 360,
StatCellNum(playerStat: tl.nerdStats!.gbe, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Garbage\nEfficiency"), showLabels: false,
StatCellNum(playerStat: tl.nerdStats!.nyaapp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Weighted\nAPP"), showTicks: false,
StatCellNum(playerStat: tl.nerdStats!.area, isScreenBig: bigScreen, fractionDigits: 1, playerStatLabel: "Area") 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) if (tl.estTr != null)

View File

@ -175,11 +175,11 @@ class UserThingy extends StatelessWidget {
playerStat: player.level, playerStat: player.level,
playerStatLabel: "XP Level", playerStatLabel: "XP Level",
isScreenBig: bigScreen, 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) if (player.gameTime >= Duration.zero)
StatCellNum( 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.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.gamesWon >= 0) StatCellNum(playerStat: player.gamesWon, isScreenBig: bigScreen, playerStatLabel: "Games\nWon"),
if (player.friendCount > 0) StatCellNum(playerStat: player.friendCount, isScreenBig: bigScreen, playerStatLabel: "Friends"), if (player.friendCount > 0) StatCellNum(playerStat: player.friendCount, isScreenBig: bigScreen, playerStatLabel: "Friends"),

View File

@ -405,6 +405,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" 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: synchronized:
dependency: transitive dependency: transitive
description: description:

View File

@ -40,6 +40,7 @@ dependencies:
package_info_plus: ^4.0.2 package_info_plus: ^4.0.2
shared_preferences: ^2.1.1 shared_preferences: ^2.1.1
intl: ^0.18.1 intl: ^0.18.1
syncfusion_flutter_gauges: ^22.1.34
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: