Graph + new eTR formula + bugfix + new flutter ver

This commit is contained in:
dan63047 2023-08-20 02:20:06 +03:00
parent f058919fd2
commit a996a0b356
3 changed files with 223 additions and 159 deletions

View File

@ -535,7 +535,30 @@ class EstTr {
double temp = (1500 - estglicko) * pi; double temp = (1500 - estglicko) * pi;
double temp2 = pow((15.9056943314 * (pow(_rd, 2)) + 3527584.25978), 0.5) as double; double temp2 = pow((15.9056943314 * (pow(_rd, 2)) + 3527584.25978), 0.5) as double;
double temp3 = 1 + pow(10, (temp / temp2)) 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))
)
)
)
))
);
} }
} }

View File

@ -3,15 +3,46 @@ import 'dart:math';
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/material.dart'; 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:tetra_stats/data_objects/tetrio.dart';
import 'package:tetra_stats/gen/strings.g.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/stat_sell_num.dart';
import 'package:tetra_stats/widgets/tl_thingy.dart'; import 'package:tetra_stats/widgets/tl_thingy.dart';
//import 'package:tetra_stats/widgets/tl_thingy.dart'; //import 'package:tetra_stats/widgets/tl_thingy.dart';
final DateFormat dateFormat = List chartsShortTitles = [
DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms(); "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; double pfpHeight = 128;
class RankView extends StatefulWidget { class RankView extends StatefulWidget {
@ -141,11 +172,6 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
body: TabBarView( body: TabBarView(
controller: _tabController, controller: _tabController,
children: [ children: [
Column(
mainAxisSize: MainAxisSize.min,
children: [
LayoutBuilder(builder: (context, constraints) {
return true ?
Column( Column(
children: [ children: [
Row( Row(
@ -158,10 +184,10 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: Text("X axis:", style: const TextStyle(fontSize: 22))), child: Text("X axis:", style: const TextStyle(fontSize: 22))),
DropdownButton( DropdownButton(
items: chartsData, items: chartsShortTitlesDropdowns,
value: chartsData[chartsIndex].value, value: chartsShortTitlesDropdowns[chartsIndexX].value,
onChanged: (value) { onChanged: (value) {
chartsIndex = chartsData.indexWhere((element) => element.value == value); chartsIndexX = chartsShortTitlesDropdowns.indexWhere((element) => element.value == value);
_justUpdate(); _justUpdate();
} }
), ),
@ -177,10 +203,10 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
child: Text("Y axis:", style: const TextStyle(fontSize: 22)), child: Text("Y axis:", style: const TextStyle(fontSize: 22)),
), ),
DropdownButton( DropdownButton(
items: chartsData, items: chartsShortTitlesDropdowns,
value: chartsData[chartsIndex].value, value: chartsShortTitlesDropdowns[chartsIndexY].value,
onChanged: (value) { onChanged: (value) {
chartsIndex = chartsData.indexWhere((element) => element.value == value); chartsIndexY = chartsShortTitlesDropdowns.indexWhere((element) => element.value == value);
_justUpdate(); _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(),) if(widget.rank[1]["entries"].length > 1) SizedBox(
else Center(child: Text(t.notEnoughData, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28))) 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( Column(
@ -235,7 +293,7 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
builder: (context) => MainView( builder: (context) => MainView(
player: widget player: widget
.rank[1]["entries"][index] .rank[1]["entries"][index]
.userId), .username),
maintainState: false, maintainState: false,
), ),
); );
@ -912,94 +970,69 @@ class _ListEntry extends StatelessWidget {
} }
} }
class _ChartThigy extends StatelessWidget { double takeStat(TetrioPlayerFromLeaderboard entry, String stat) {
final List<FlSpot> data; switch (stat) {
final String title; case "TR":
final String yAxisTitle; return entry.rating;
final bool bigScreen; case "Glicko":
final double leftSpace; return entry.glicko;
final NumberFormat yFormat; case "RD":
const _ChartThigy( return entry.rd;
{required this.data, case "GP":
required this.title, return entry.gamesPlayed.toDouble();
required this.yAxisTitle, case "GW":
required this.bigScreen, return entry.gamesWon.toDouble();
required this.leftSpace, case "WR%":
required this.yFormat}); 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});
@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())))
])
];
},
)))),
),
],
));
}
} }

View File

@ -93,10 +93,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: collection name: collection
sha256: "4a07be6cb69c84d677a6c3096fcf960cc3285a8330b4603e0d463d15d9bd934c" sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.17.1" version: "1.17.2"
convert: convert:
dependency: transitive dependency: transitive
description: description:
@ -361,10 +361,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: intl name: intl
sha256: a3715e3bc90294e971cb7dc063fbf3cd9ee0ebf8604ffeafabd9e6f16abbdbe6 sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.18.0" version: "0.18.1"
io: io:
dependency: transitive dependency: transitive
description: description:
@ -417,18 +417,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: matcher name: matcher
sha256: "6501fbd55da300384b768785b83e5ce66991266cec21af89ab9ae7f5ce1c4cbb" sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.15" version: "0.12.16"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
name: material_color_utilities name: material_color_utilities
sha256: d92141dc6fe1dad30722f9aa826c7fbc896d021d792f80678280601aff8cf724 sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.0" version: "0.5.0"
meta: meta:
dependency: transitive dependency: transitive
description: description:
@ -718,10 +718,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_span name: source_span
sha256: dd904f795d4b4f3b870833847c461801f6750a9fa8e61ea5ac53f9422b31f250 sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.10.0"
sqflite: sqflite:
dependency: "direct main" dependency: "direct main"
description: description:
@ -830,26 +830,26 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: test name: test
sha256: "3dac9aecf2c3991d09b9cdde4f98ded7b30804a88a0d7e4e7e1678e78d6b97f4" sha256: "13b41f318e2a5751c3169137103b60c584297353d4b1761b66029bae6411fe46"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.24.1" version: "1.24.3"
test_api: test_api:
dependency: transitive dependency: transitive
description: description:
name: test_api name: test_api
sha256: eb6ac1540b26de412b3403a163d919ba86f6a973fe6cc50ae3541b80092fdcfb sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.1" version: "0.6.0"
test_core: test_core:
dependency: transitive dependency: transitive
description: description:
name: test_core name: test_core
sha256: "5138dbffb77b2289ecb12b81c11ba46036590b72a64a7a90d6ffb880f1a29e93" sha256: "99806e9e6d95c7b059b7a0fc08f07fc53fabe54a829497f0d9676299f1e8637e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.1" version: "0.5.3"
typed_data: typed_data:
dependency: transitive dependency: transitive
description: description:
@ -946,6 +946,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.0" 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: web_socket_channel:
dependency: transitive dependency: transitive
description: description:
@ -995,5 +1003,5 @@ packages:
source: hosted source: hosted
version: "3.1.2" version: "3.1.2"
sdks: sdks:
dart: ">=3.0.0 <4.0.0" dart: ">=3.1.0-185.0.dev <4.0.0"
flutter: ">=3.10.0" flutter: ">=3.10.0"