diff --git a/lib/views/calc_view.dart b/lib/views/calc_view.dart index 6a6a9be..d5b981b 100644 --- a/lib/views/calc_view.dart +++ b/lib/views/calc_view.dart @@ -1,4 +1,11 @@ +import 'package:fl_chart/fl_chart.dart'; import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; +import 'package:tetra_stats/data_objects/tetrio.dart'; + +NerdStats? nerdStats; +EstTr? estTr; +Playstyle? playstyle; class CalcView extends StatefulWidget { const CalcView({Key? key}) : super(key: key); @@ -8,6 +15,31 @@ class CalcView extends StatefulWidget { } class CalcState extends State { + late ScrollController _scrollController; + TextEditingController ppsController = TextEditingController(); + TextEditingController apmController = TextEditingController(); + TextEditingController vsController = TextEditingController(); + + @override + void initState() { + _scrollController = ScrollController(); + super.initState(); + } + + void calc() { + double? apm = double.tryParse(apmController.text); + double? pps = double.tryParse(ppsController.text); + double? vs = double.tryParse(vsController.text); + if (apm != null && pps != null && vs != null) { + nerdStats = NerdStats(apm, pps, vs); + estTr = EstTr(apm, pps, vs, 60.9, nerdStats!.app, nerdStats!.dss, nerdStats!.dsp, nerdStats!.gbe); + playstyle = Playstyle(apm, pps, nerdStats!.app, nerdStats!.vsapm, nerdStats!.dsp, nerdStats!.gbe, estTr!.srarea, estTr!.statrank); + setState(() {}); + } else { + ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Please, enter valid values"))); + } + } + @override Widget build(BuildContext context) { return Scaffold( @@ -15,7 +47,248 @@ class CalcState extends State { title: const Text("Stats Calculator"), ), backgroundColor: Colors.black, - body: const SafeArea(child: Text("Next build")), + body: SafeArea( + child: NestedScrollView( + controller: _scrollController, + headerSliverBuilder: (context, value) { + return [ + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.fromLTRB(14, 16, 16, 32), + child: Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.only(right: 12), + child: TextField( + onSubmitted: (value) => calc(), + controller: apmController, + keyboardType: TextInputType.number, + decoration: const InputDecoration(label: Text("APM"), alignLabelWithHint: true), + ), + )), + Expanded( + child: TextField( + onSubmitted: (value) => calc(), + controller: ppsController, + keyboardType: TextInputType.number, + decoration: const InputDecoration(label: Text("PPS"), alignLabelWithHint: true), + )), + Expanded( + child: Padding( + padding: const EdgeInsets.only(left: 12), + child: TextField( + onSubmitted: (value) => calc(), + controller: vsController, + keyboardType: TextInputType.number, + decoration: const InputDecoration(label: Text("VS"), alignLabelWithHint: true), + ), + )), + TextButton( + onPressed: () => calc(), + child: const Text("Calc"), + ), + ], + ), + ), + ), + const SliverToBoxAdapter( + child: Divider(), + ) + ]; + }, + body: nerdStats == null + ? const Text("Enter values to calculate the stats") + : ListView( + children: [ + _ListEntry(value: nerdStats!.app, label: "Attack Per Piece", fractionDigits: 3), + _ListEntry(value: nerdStats!.vsapm, label: "VS/APM", fractionDigits: 3), + _ListEntry(value: nerdStats!.dss, label: "Downstack Per Second", fractionDigits: 3), + _ListEntry(value: nerdStats!.dsp, label: "Downstack Per Piece", fractionDigits: 3), + _ListEntry(value: nerdStats!.appdsp, label: "APP + DS/P", fractionDigits: 3), + _ListEntry(value: nerdStats!.cheese, label: "Cheese Index", fractionDigits: 3), + _ListEntry(value: nerdStats!.gbe, label: "Garbage Efficiency", fractionDigits: 3), + _ListEntry(value: nerdStats!.nyaapp, label: "Weighted APP", fractionDigits: 3), + _ListEntry(value: nerdStats!.area, label: "Area", fractionDigits: 3), + _ListEntry(value: estTr!.esttr, label: "Est. of TR", fractionDigits: 3), + Wrap( + direction: Axis.horizontal, + alignment: WrapAlignment.spaceAround, + spacing: 25, + crossAxisAlignment: WrapCrossAlignment.start, + clipBehavior: Clip.hardEdge, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(20, 0, 20, 48), + child: SizedBox( + height: 300, + width: 300, + child: RadarChart( + RadarChartData( + radarShape: RadarShape.polygon, + tickCount: 4, + ticksTextStyle: const TextStyle(color: Colors.transparent, fontSize: 10), + radarBorderData: const BorderSide(color: Colors.transparent, width: 1), + gridBorderData: const BorderSide(color: Colors.white24, width: 1), + tickBorderData: const BorderSide(color: Colors.transparent, width: 1), + getTitle: (index, angle) { + switch (index) { + case 0: + return RadarChartTitle( + text: 'APM', + angle: angle, + ); + case 1: + return RadarChartTitle( + text: 'PPS', + angle: angle, + ); + case 2: + return RadarChartTitle(text: 'VS', angle: angle); + case 3: + return RadarChartTitle(text: 'APP', angle: angle + 180); + case 4: + return RadarChartTitle(text: 'DS/S', angle: angle + 180); + case 5: + return RadarChartTitle(text: 'DS/P', angle: angle + 180); + case 6: + return RadarChartTitle(text: 'APP+DS/P', angle: angle + 180); + case 7: + return RadarChartTitle(text: 'VS/APM', angle: angle + 180); + case 8: + return RadarChartTitle(text: 'Cheese', angle: angle); + case 9: + return RadarChartTitle(text: 'Gb Eff.', angle: angle); + default: + return const RadarChartTitle(text: ''); + } + }, + dataSets: [ + RadarDataSet( + dataEntries: [ + RadarEntry(value: double.parse(apmController.text) * 1), + RadarEntry(value: double.parse(ppsController.text) * 45), + RadarEntry(value: double.parse(vsController.text) * 0.444), + RadarEntry(value: nerdStats!.app * 185), + RadarEntry(value: nerdStats!.dss * 175), + RadarEntry(value: nerdStats!.dsp * 450), + RadarEntry(value: nerdStats!.appdsp * 140), + RadarEntry(value: nerdStats!.vsapm * 60), + RadarEntry(value: nerdStats!.cheese * 1.25), + RadarEntry(value: nerdStats!.gbe * 315), + ], + ), + RadarDataSet( + fillColor: Colors.transparent, + borderColor: Colors.transparent, + dataEntries: [ + const RadarEntry(value: 0), + const RadarEntry(value: 0), + const RadarEntry(value: 0), + const RadarEntry(value: 0), + const RadarEntry(value: 0), + const RadarEntry(value: 0), + const RadarEntry(value: 0), + const RadarEntry(value: 0), + const RadarEntry(value: 0), + const RadarEntry(value: 0), + ], + ) + ], + ), + swapAnimationDuration: const Duration(milliseconds: 150), // Optional + swapAnimationCurve: Curves.linear, // Optional + ), + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(20, 0, 20, 48), + child: SizedBox( + height: 300, + width: 300, + child: RadarChart( + RadarChartData( + radarShape: RadarShape.polygon, + tickCount: 4, + ticksTextStyle: const TextStyle(color: Colors.transparent, fontSize: 10), + radarBorderData: const BorderSide(color: Colors.transparent, width: 1), + gridBorderData: const BorderSide(color: Colors.white24, width: 1), + tickBorderData: const BorderSide(color: Colors.transparent, width: 1), + getTitle: (index, angle) { + switch (index) { + case 0: + return RadarChartTitle( + text: 'Opener', + angle: angle, + ); + case 1: + return RadarChartTitle( + text: 'Stride', + angle: angle, + ); + case 2: + return RadarChartTitle(text: 'Inf Ds', angle: angle + 180); + case 3: + return RadarChartTitle(text: 'Plonk', angle: angle); + default: + return const RadarChartTitle(text: ''); + } + }, + dataSets: [ + RadarDataSet( + dataEntries: [ + RadarEntry(value: playstyle!.opener), + RadarEntry(value: playstyle!.stride), + RadarEntry(value: playstyle!.infds), + RadarEntry(value: playstyle!.plonk), + ], + ), + RadarDataSet( + fillColor: Colors.transparent, + borderColor: Colors.transparent, + dataEntries: [ + const RadarEntry(value: 0), + const RadarEntry(value: 0), + const RadarEntry(value: 0), + const RadarEntry(value: 0), + ], + ), + RadarDataSet( + fillColor: Colors.transparent, + borderColor: Colors.transparent, + dataEntries: [ + const RadarEntry(value: 1), + const RadarEntry(value: 1), + const RadarEntry(value: 1), + const RadarEntry(value: 1), + ], + ) + ], + ), + swapAnimationDuration: const Duration(milliseconds: 150), // Optional + swapAnimationCurve: Curves.linear, // Optional + ), + ), + ), + ], + ) + ], + )), + ), ); } } + +class _ListEntry extends StatelessWidget { + final double value; + final String label; + final int? fractionDigits; + const _ListEntry({required this.value, required this.label, this.fractionDigits}); + + @override + Widget build(BuildContext context) { + var f = NumberFormat("#,###.##"); + f.maximumFractionDigits = fractionDigits ?? 0; + return ListTile(title: Text(label), trailing: Text(f.format(value), style: const TextStyle(fontSize: 22))); + } +} diff --git a/lib/views/compare_view.dart b/lib/views/compare_view.dart index 6ecf9d7..59dc562 100644 --- a/lib/views/compare_view.dart +++ b/lib/views/compare_view.dart @@ -51,15 +51,10 @@ class CompareState extends State { } double getWinrateByTR(double yourGlicko, double yourRD, double notyourGlicko, double notyourRD) { - double q = 400 * sqrt(1 + 3 * pow(log(10) / (400 * pi), 2)); - double k = (notyourGlicko - yourGlicko) / (q * sqrt(pow(yourRD, 2) + pow(notyourRD, 2))); - //return 1 / (1 + pow(10, (notyourGlicko - yourGlicko)) / (400 * sqrt(1 + (3 * pow(0.00575646273, 2) * (pow(yourRD, 2) + pow(notyourRD, 2))) / pow(pi, 2)))); return ((1 / (1 + pow(10, (notyourGlicko - yourGlicko) / (400 * sqrt(1 + (3 * pow(0.0057564273, 2) * (pow(yourRD, 2) + pow(notyourRD, 2)) / pow(pi, 2)))))))); - //return 1 / (1 + pow(10, k)); } - // 1/(1+10^(rating[1]-rating[0])/(400*sqrt(1+(3*Q^2*(RD[0]^2+RD[1]^2))/PI^2)))) wtf where is void _justUpdate() { setState(() {}); } @@ -87,7 +82,7 @@ class CompareState extends State { children: [ Expanded( child: Container( - decoration: BoxDecoration( + decoration: const BoxDecoration( gradient: LinearGradient( colors: [Colors.green, Colors.transparent], begin: Alignment.bottomCenter, @@ -110,7 +105,7 @@ class CompareState extends State { ), Expanded( child: Container( - decoration: BoxDecoration( + decoration: const BoxDecoration( gradient: LinearGradient( colors: [Colors.red, Colors.transparent], begin: Alignment.bottomCenter, @@ -512,7 +507,7 @@ class CompareState extends State { }, dataSets: [ RadarDataSet( - fillColor: Color.fromARGB(115, 76, 175, 79), + fillColor: const Color.fromARGB(115, 76, 175, 79), borderColor: Colors.green, dataEntries: [ RadarEntry(value: theGreenSide!.tlSeason1.playstyle!.opener), @@ -522,7 +517,7 @@ class CompareState extends State { ], ), RadarDataSet( - fillColor: Color.fromARGB(115, 244, 67, 54), + fillColor: const Color.fromARGB(115, 244, 67, 54), borderColor: Colors.red, dataEntries: [ RadarEntry(value: theRedSide!.tlSeason1.playstyle!.opener), @@ -611,7 +606,7 @@ class PlayerSelector extends StatelessWidget { if (player != null) Text( player!.toString(), - style: TextStyle( + style: const TextStyle( shadows: [ Shadow( offset: Offset(0.0, 0.0), @@ -656,10 +651,10 @@ class CompareThingy extends StatelessWidget { children: [ Expanded( child: Container( - padding: EdgeInsets.all(4), + padding: const EdgeInsets.all(4), decoration: BoxDecoration( gradient: LinearGradient( - colors: [Colors.green, Colors.transparent], + colors: const [Colors.green, Colors.transparent], begin: Alignment.centerLeft, end: Alignment.centerRight, stops: [ @@ -709,10 +704,10 @@ class CompareThingy extends StatelessWidget { ), Expanded( child: Container( - padding: EdgeInsets.all(4), + padding: const EdgeInsets.all(4), decoration: BoxDecoration( gradient: LinearGradient( - colors: [Colors.red, Colors.transparent], + colors: const [Colors.red, Colors.transparent], begin: Alignment.centerRight, end: Alignment.centerLeft, stops: [ @@ -766,10 +761,10 @@ class CompareBoolThingy extends StatelessWidget { child: Row(children: [ Expanded( child: Container( - padding: EdgeInsets.all(4), + padding: const EdgeInsets.all(4), decoration: BoxDecoration( gradient: LinearGradient( - colors: [Colors.green, Colors.transparent], + colors: const [Colors.green, Colors.transparent], begin: Alignment.centerLeft, end: Alignment.centerRight, stops: [ @@ -819,10 +814,10 @@ class CompareBoolThingy extends StatelessWidget { ), Expanded( child: Container( - padding: EdgeInsets.all(4), + padding: const EdgeInsets.all(4), decoration: BoxDecoration( gradient: LinearGradient( - colors: [Colors.red, Colors.transparent], + colors: const [Colors.red, Colors.transparent], begin: Alignment.centerRight, end: Alignment.centerLeft, stops: [ @@ -951,10 +946,10 @@ class CompareRegTimeThingy extends StatelessWidget { children: [ Expanded( child: Container( - padding: EdgeInsets.all(4), + padding: const EdgeInsets.all(4), decoration: BoxDecoration( gradient: LinearGradient( - colors: [Colors.green, Colors.transparent], + colors: const [Colors.green, Colors.transparent], begin: Alignment.centerLeft, end: Alignment.centerRight, stops: [ @@ -1002,10 +997,10 @@ class CompareRegTimeThingy extends StatelessWidget { ), Expanded( child: Container( - padding: EdgeInsets.all(4), + padding: const EdgeInsets.all(4), decoration: BoxDecoration( gradient: LinearGradient( - colors: [Colors.red, Colors.transparent], + colors: const [Colors.red, Colors.transparent], begin: Alignment.centerRight, end: Alignment.centerLeft, stops: [