Graph + new eTR formula + bugfix + new flutter ver
This commit is contained in:
parent
f058919fd2
commit
a996a0b356
|
@ -535,7 +535,30 @@ class EstTr {
|
|||
double temp = (1500 - estglicko) * pi;
|
||||
double temp2 = pow((15.9056943314 * (pow(_rd, 2)) + 3527584.25978), 0.5) as double;
|
||||
double temp3 = 1 + pow(10, (temp / temp2)) as double;
|
||||
esttr = 25000 / temp3;
|
||||
//esttr = 25000 / temp3;
|
||||
double ntemp = _pps*(150+(((_vs/_apm) - 1.66)*35))+_app*290+_dsp*700;
|
||||
esttr = 25000 /
|
||||
(
|
||||
1 + pow(10, (
|
||||
(
|
||||
(
|
||||
1500-(
|
||||
0.000013*pow(ntemp, 3) - 0.0196 *pow(ntemp, 2) + (12.645*ntemp)-1005.4
|
||||
)
|
||||
)*pi
|
||||
)/sqrt(
|
||||
(
|
||||
(
|
||||
3*pow(ln10, 2)
|
||||
)*pow(60, 2)
|
||||
)+(
|
||||
2500*(
|
||||
(64*pow(pi,2))+(147*pow(ln10, 2))
|
||||
)
|
||||
)
|
||||
)
|
||||
))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -3,15 +3,46 @@ import 'dart:math';
|
|||
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';
|
||||
//import 'package:tetra_stats/data_objects/tetrio.dart';
|
||||
import 'package:tetra_stats/gen/strings.g.dart';
|
||||
import 'package:tetra_stats/views/main_view.dart';
|
||||
import 'package:tetra_stats/views/main_view.dart' show MainView, f4, f2;
|
||||
import 'package:tetra_stats/widgets/stat_sell_num.dart';
|
||||
import 'package:tetra_stats/widgets/tl_thingy.dart';
|
||||
//import 'package:tetra_stats/widgets/tl_thingy.dart';
|
||||
|
||||
final DateFormat dateFormat =
|
||||
DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
|
||||
List chartsShortTitles = [
|
||||
"TR",
|
||||
"Glicko",
|
||||
"RD",
|
||||
"GP",
|
||||
"GW",
|
||||
"WR%",
|
||||
"APM",
|
||||
"PPS",
|
||||
"VS",
|
||||
"APP",
|
||||
"DS/S",
|
||||
"DS/P",
|
||||
"APP + DS/P",
|
||||
"VS/APM",
|
||||
"Cheese",
|
||||
"GbE",
|
||||
"wAPP",
|
||||
"Area",
|
||||
"eTR",
|
||||
"±eTR",
|
||||
"Opener",
|
||||
"Plonk",
|
||||
"Inf. DS",
|
||||
"Stride",
|
||||
"Stride - Plonk",
|
||||
"Opener - Inf. DS"
|
||||
];
|
||||
var chartsShortTitlesDropdowns = <DropdownMenuItem>[for (String e in chartsShortTitles) DropdownMenuItem(child: Text(e), value: e,)];
|
||||
int chartsIndexX = 0;
|
||||
int chartsIndexY = 6;
|
||||
//final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
|
||||
double pfpHeight = 128;
|
||||
|
||||
class RankView extends StatefulWidget {
|
||||
|
@ -141,11 +172,6 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
|
|||
body: TabBarView(
|
||||
controller: _tabController,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
LayoutBuilder(builder: (context, constraints) {
|
||||
return true ?
|
||||
Column(
|
||||
children: [
|
||||
Row(
|
||||
|
@ -158,10 +184,10 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
|
|||
padding: const EdgeInsets.all(8.0),
|
||||
child: Text("X axis:", style: const TextStyle(fontSize: 22))),
|
||||
DropdownButton(
|
||||
items: chartsData,
|
||||
value: chartsData[chartsIndex].value,
|
||||
items: chartsShortTitlesDropdowns,
|
||||
value: chartsShortTitlesDropdowns[chartsIndexX].value,
|
||||
onChanged: (value) {
|
||||
chartsIndex = chartsData.indexWhere((element) => element.value == value);
|
||||
chartsIndexX = chartsShortTitlesDropdowns.indexWhere((element) => element.value == value);
|
||||
_justUpdate();
|
||||
}
|
||||
),
|
||||
|
@ -177,10 +203,10 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
|
|||
child: Text("Y axis:", style: const TextStyle(fontSize: 22)),
|
||||
),
|
||||
DropdownButton(
|
||||
items: chartsData,
|
||||
value: chartsData[chartsIndex].value,
|
||||
items: chartsShortTitlesDropdowns,
|
||||
value: chartsShortTitlesDropdowns[chartsIndexY].value,
|
||||
onChanged: (value) {
|
||||
chartsIndex = chartsData.indexWhere((element) => element.value == value);
|
||||
chartsIndexY = chartsShortTitlesDropdowns.indexWhere((element) => element.value == value);
|
||||
_justUpdate();
|
||||
}
|
||||
),
|
||||
|
@ -188,11 +214,43 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
|
|||
),
|
||||
],
|
||||
),],),
|
||||
if(chartsData[chartsIndex].value!.length > 1) _ChartThigy(data: chartsData[chartsIndex].value!, title: "ss", yAxisTitle: chartsShortTitles[chartsIndex], bigScreen: bigScreen, leftSpace: bigScreen? 80 : 45, yFormat: bigScreen? f2 : NumberFormat.compact(),)
|
||||
else Center(child: Text(t.notEnoughData, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))
|
||||
if(widget.rank[1]["entries"].length > 1) SizedBox(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height - 104,
|
||||
child: Stack(
|
||||
children: [
|
||||
Padding(
|
||||
padding: bigScreen
|
||||
? const EdgeInsets.fromLTRB(40, 40, 40, 48)
|
||||
: const EdgeInsets.fromLTRB(0, 40, 16, 48),
|
||||
child: ScatterChart(
|
||||
ScatterChartData(
|
||||
scatterSpots: [ for (TetrioPlayerFromLeaderboard entry in widget.rank[1]["entries"]) MyScatterSpot(takeStat(entry, chartsShortTitles[chartsIndexX]), takeStat(entry, chartsShortTitles[chartsIndexY]), entry.userId, entry.username, color: rankColors[entry.rank])],
|
||||
scatterTouchData: ScatterTouchData(touchTooltipData: ScatterTouchTooltipData(
|
||||
fitInsideHorizontally: true, fitInsideVertically: true, getTooltipItems: (touchedSpot) {
|
||||
touchedSpot as MyScatterSpot;
|
||||
return ScatterTooltipItem("${touchedSpot.nickname}\n", textStyle: TextStyle(fontFamily: "Eurostile Round Extended"), children: [TextSpan(text: "${f4.format(touchedSpot.x)} ${chartsShortTitles[chartsIndexX]}\n${f4.format(touchedSpot.y)} ${chartsShortTitles[chartsIndexY]}", style: TextStyle(fontFamily: "Eurostile Round"))]);
|
||||
}),
|
||||
touchCallback:(event, response) {
|
||||
if (event.runtimeType == FlTapDownEvent && response?.touchedSpot?.spot != null){
|
||||
var spot = response?.touchedSpot?.spot as MyScatterSpot;
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => MainView(player: spot.nickname),
|
||||
maintainState: false,
|
||||
),
|
||||
);
|
||||
}
|
||||
},),
|
||||
),
|
||||
swapAnimationDuration: Duration(milliseconds: 150), // Optional
|
||||
swapAnimationCurve: Curves.linear, // Optional
|
||||
),
|
||||
),
|
||||
],
|
||||
) : Center(child: Text(t.noHistorySaved, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)));
|
||||
})
|
||||
))
|
||||
else Center(child: Text(t.notEnoughData, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))
|
||||
],
|
||||
),
|
||||
Column(
|
||||
|
@ -235,7 +293,7 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
|
|||
builder: (context) => MainView(
|
||||
player: widget
|
||||
.rank[1]["entries"][index]
|
||||
.userId),
|
||||
.username),
|
||||
maintainState: false,
|
||||
),
|
||||
);
|
||||
|
@ -912,94 +970,69 @@ class _ListEntry extends StatelessWidget {
|
|||
}
|
||||
}
|
||||
|
||||
class _ChartThigy extends StatelessWidget {
|
||||
final List<FlSpot> data;
|
||||
final String title;
|
||||
final String yAxisTitle;
|
||||
final bool bigScreen;
|
||||
final double leftSpace;
|
||||
final NumberFormat yFormat;
|
||||
const _ChartThigy(
|
||||
{required this.data,
|
||||
required this.title,
|
||||
required this.yAxisTitle,
|
||||
required this.bigScreen,
|
||||
required this.leftSpace,
|
||||
required this.yFormat});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double xInterval = bigScreen
|
||||
? max(1, (data.last.x - data.first.x) / 6)
|
||||
: max(1, (data.last.x - data.first.x) / 3);
|
||||
return SizedBox(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height: MediaQuery.of(context).size.height - 104,
|
||||
child: Stack(
|
||||
children: [
|
||||
Padding(
|
||||
padding: bigScreen
|
||||
? const EdgeInsets.fromLTRB(40, 40, 40, 48)
|
||||
: const EdgeInsets.fromLTRB(0, 40, 16, 48),
|
||||
child: LineChart(LineChartData(
|
||||
lineBarsData: [LineChartBarData(spots: data)],
|
||||
borderData: FlBorderData(show: false),
|
||||
gridData: FlGridData(verticalInterval: xInterval),
|
||||
titlesData: FlTitlesData(
|
||||
topTitles:
|
||||
AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
rightTitles:
|
||||
AxisTitles(sideTitles: SideTitles(showTitles: false)),
|
||||
bottomTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
interval: xInterval,
|
||||
showTitles: true,
|
||||
reservedSize: 30,
|
||||
getTitlesWidget: (double value, TitleMeta meta) {
|
||||
return value != meta.min && value != meta.max
|
||||
? SideTitleWidget(
|
||||
axisSide: meta.axisSide,
|
||||
child: Text(DateFormat.yMMMd(
|
||||
LocaleSettings
|
||||
.currentLocale.languageCode)
|
||||
.format(DateTime
|
||||
.fromMillisecondsSinceEpoch(
|
||||
value.floor()))),
|
||||
)
|
||||
: Container();
|
||||
})),
|
||||
leftTitles: AxisTitles(
|
||||
sideTitles: SideTitles(
|
||||
showTitles: true,
|
||||
reservedSize: leftSpace,
|
||||
getTitlesWidget: (double value, TitleMeta meta) {
|
||||
return value != meta.min && value != meta.max
|
||||
? SideTitleWidget(
|
||||
axisSide: meta.axisSide,
|
||||
child: Text(yFormat.format(value)),
|
||||
)
|
||||
: Container();
|
||||
}))),
|
||||
lineTouchData: LineTouchData(
|
||||
touchTooltipData: LineTouchTooltipData(
|
||||
fitInsideHorizontally: true,
|
||||
fitInsideVertically: true,
|
||||
getTooltipItems: (touchedSpots) {
|
||||
return [
|
||||
for (var v in touchedSpots)
|
||||
LineTooltipItem("${f4.format(v.y)} $yAxisTitle \n",
|
||||
const TextStyle(),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: dateFormat.format(
|
||||
DateTime.fromMillisecondsSinceEpoch(
|
||||
v.x.floor())))
|
||||
])
|
||||
];
|
||||
},
|
||||
)))),
|
||||
),
|
||||
],
|
||||
));
|
||||
double takeStat(TetrioPlayerFromLeaderboard entry, String stat) {
|
||||
switch (stat) {
|
||||
case "TR":
|
||||
return entry.rating;
|
||||
case "Glicko":
|
||||
return entry.glicko;
|
||||
case "RD":
|
||||
return entry.rd;
|
||||
case "GP":
|
||||
return entry.gamesPlayed.toDouble();
|
||||
case "GW":
|
||||
return entry.gamesWon.toDouble();
|
||||
case "WR%":
|
||||
return entry.winrate*100;
|
||||
case "APM":
|
||||
return entry.apm;
|
||||
case "PPS":
|
||||
return entry.pps;
|
||||
case "VS":
|
||||
return entry.vs;
|
||||
case "APP":
|
||||
return entry.nerdStats.app;
|
||||
case "DS/S":
|
||||
return entry.nerdStats.dss;
|
||||
case "DS/P":
|
||||
return entry.nerdStats.dsp;
|
||||
case "APP + DS/P":
|
||||
return entry.nerdStats.appdsp;
|
||||
case "VS/APM":
|
||||
return entry.nerdStats.vsapm;
|
||||
case "Cheese":
|
||||
return entry.nerdStats.cheese;
|
||||
case "GbE":
|
||||
return entry.nerdStats.gbe;
|
||||
case "wAPP":
|
||||
return entry.nerdStats.nyaapp;
|
||||
case "Area":
|
||||
return entry.nerdStats.area;
|
||||
case "eTR":
|
||||
return entry.estTr.esttr;
|
||||
case "±eTR":
|
||||
return entry.esttracc;
|
||||
case "Opener":
|
||||
return entry.playstyle.opener;
|
||||
case "Plonk":
|
||||
return entry.playstyle.plonk;
|
||||
case "Inf. DS":
|
||||
return entry.playstyle.infds;
|
||||
case "Stride":
|
||||
return entry.playstyle.stride;
|
||||
case "Stride - Plonk":
|
||||
return entry.playstyle.stride - entry.playstyle.plonk;
|
||||
case "Opener - Inf. DS":
|
||||
return entry.playstyle.opener - entry.playstyle.infds;
|
||||
default:
|
||||
throw ArgumentError.value(stat, "Incorrect stat", "We don't have that stat");
|
||||
}
|
||||
}
|
||||
|
||||
class MyScatterSpot extends ScatterSpot{
|
||||
String id;
|
||||
String nickname;
|
||||
|
||||
MyScatterSpot(super.x, super.y, this.id, this.nickname, {super.color});
|
||||
|
||||
}
|
42
pubspec.lock
42
pubspec.lock
|
@ -93,10 +93,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: collection
|
||||
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c"
|
||||
sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.17.1"
|
||||
version: "1.17.2"
|
||||
convert:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -361,10 +361,10 @@ packages:
|
|||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6
|
||||
sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.18.0"
|
||||
version: "0.18.1"
|
||||
io:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -417,18 +417,18 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: matcher
|
||||
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb"
|
||||
sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.12.15"
|
||||
version: "0.12.16"
|
||||
material_color_utilities:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: material_color_utilities
|
||||
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724
|
||||
sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.2.0"
|
||||
version: "0.5.0"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -718,10 +718,10 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: source_span
|
||||
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250
|
||||
sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
version: "1.10.0"
|
||||
sqflite:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
|
@ -830,26 +830,26 @@ packages:
|
|||
dependency: transitive
|
||||
description:
|
||||
name: test
|
||||
sha256: "3dac9aecf2c3991d09b9cdde4f98ded7b30804a88a0d7e4e7e1678e78d6b97f4"
|
||||
sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.24.1"
|
||||
version: "1.24.3"
|
||||
test_api:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_api
|
||||
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb
|
||||
sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
version: "0.6.0"
|
||||
test_core:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: test_core
|
||||
sha256: "5138dbffb77b2289ecb12b81c11ba46036590b72a64a7a90d6ffb880f1a29e93"
|
||||
sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.5.1"
|
||||
version: "0.5.3"
|
||||
typed_data:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -946,6 +946,14 @@ packages:
|
|||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: web
|
||||
sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.1.4-beta"
|
||||
web_socket_channel:
|
||||
dependency: transitive
|
||||
description:
|
||||
|
@ -995,5 +1003,5 @@ packages:
|
|||
source: hosted
|
||||
version: "3.1.2"
|
||||
sdks:
|
||||
dart: ">=3.0.0 <4.0.0"
|
||||
dart: ">=3.1.0-185.0.dev <4.0.0"
|
||||
flutter: ">=3.10.0"
|
||||
|
|
Loading…
Reference in New Issue