Compare commits
4 Commits
e403b0cbee
...
5f404d3508
Author | SHA1 | Date |
---|---|---|
dan63047 | 5f404d3508 | |
dan63047 | 9d183f7cd3 | |
dan63047 | 2f9cf0ee20 | |
Takathedinosaur | 858bb67801 |
|
@ -6,7 +6,7 @@ import 'package:tetra_stats/data_objects/tetra_league.dart';
|
|||
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||
import 'package:tetra_stats/data_objects/tetrio_zen.dart';
|
||||
|
||||
class Summaries{
|
||||
class Summaries {
|
||||
late String id;
|
||||
RecordSingle? sprint;
|
||||
RecordSingle? blitz;
|
||||
|
@ -21,19 +21,42 @@ class Summaries{
|
|||
|
||||
Summaries(this.id, this.league, this.zen);
|
||||
|
||||
Summaries.fromJson(Map<String, dynamic> json, String i){
|
||||
Summaries.fromJson(Map<String, dynamic> json, String i) {
|
||||
id = i;
|
||||
if (json['40l']['record'] != null) sprint = RecordSingle.fromJson(json['40l']['record'], json['40l']['rank'], json['40l']['rank_local']);
|
||||
if (json['blitz']['record'] != null) blitz = RecordSingle.fromJson(json['blitz']['record'], json['blitz']['rank'], json['40l']['rank_local']);
|
||||
if (json['zenith']['record'] != null) zenith = RecordSingle.fromJson(json['zenith']['record'], json['zenith']['rank'], json['zenith']['rank_local']);
|
||||
if (json['zenith']['best']['record'] != null) zenithCareerBest = RecordSingle.fromJson(json['zenith']['best']['record'], json['zenith']['best']['rank'], -1);
|
||||
if (json['zenithex']['record'] != null) zenithEx = RecordSingle.fromJson(json['zenithex']['record'], json['zenithex']['rank'], json['zenithex']['rank_local']);
|
||||
if (json['zenithex']['best']['record'] != null) zenithCareerBest = RecordSingle.fromJson(json['zenithex']['best']['record'], json['zenith']['best']['rank'], -1);
|
||||
achievements = [for (var achievement in json['achievements']) Achievement.fromJson(achievement)];
|
||||
league = TetraLeague.fromJson(json['league'], DateTime.now(), currentSeason, i);
|
||||
if (json['league']['past'].isNotEmpty) for (var key in json['league']['past'].keys){
|
||||
pastLeague[int.parse(key)] = TetraLeague.fromJson(json['league']['past'][key], DateTime(1970), int.parse(json['league']['past'][key]['season']), i);
|
||||
}
|
||||
if (json['40l']['record'] != null)
|
||||
sprint = RecordSingle.fromJson(json['40l']['record'], json['40l']['rank'],
|
||||
json['40l']['rank_local']);
|
||||
if (json['blitz']['record'] != null)
|
||||
blitz = RecordSingle.fromJson(json['blitz']['record'],
|
||||
json['blitz']['rank'], json['40l']['rank_local']);
|
||||
if (json['zenith']['record'] != null)
|
||||
zenith = RecordSingle.fromJson(json['zenith']['record'],
|
||||
json['zenith']['rank'], json['zenith']['rank_local']);
|
||||
if (json['zenith']['best']['record'] != null)
|
||||
zenithCareerBest = RecordSingle.fromJson(
|
||||
json['zenith']['best']['record'], json['zenith']['best']['rank'], -1);
|
||||
if (json['zenithex']['record'] != null)
|
||||
zenithEx = RecordSingle.fromJson(json['zenithex']['record'],
|
||||
json['zenithex']['rank'], json['zenithex']['rank_local']);
|
||||
if (json['zenithex']['best']['record'] != null)
|
||||
zenithCareerBest = RecordSingle.fromJson(
|
||||
json['zenithex']['best']['record'],
|
||||
json['zenith']['best']['rank'],
|
||||
-1);
|
||||
achievements = [
|
||||
for (var achievement in json['achievements'])
|
||||
Achievement.fromJson(achievement)
|
||||
];
|
||||
league =
|
||||
TetraLeague.fromJson(json['league'], DateTime.now(), currentSeason, i);
|
||||
if (json['league']['past'].isNotEmpty)
|
||||
for (var key in json['league']['past'].keys) {
|
||||
pastLeague[int.parse(key)] = TetraLeague.fromJson(
|
||||
json['league']['past'][key],
|
||||
null,
|
||||
int.parse(json['league']['past'][key]['season']),
|
||||
i);
|
||||
}
|
||||
zen = TetrioZen.fromJson(json['zen']);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -57,22 +57,35 @@ class TetraLeague {
|
|||
this.apm,
|
||||
this.pps,
|
||||
this.vs,
|
||||
required this.season}){
|
||||
nerdStats = (apm != null && pps != null && vs != null) ? NerdStats(apm!, pps!, vs!) : null;
|
||||
estTr = (nerdStats != null) ? EstTr(apm!, pps!, vs!, nerdStats!.app, nerdStats!.dss, nerdStats!.dsp, nerdStats!.gbe) : null;
|
||||
playstyle =(nerdStats != null) ? Playstyle(apm!, pps!, nerdStats!.app, nerdStats!.vsapm, nerdStats!.dsp, nerdStats!.gbe, estTr!.srarea, estTr!.statrank) : null;
|
||||
}
|
||||
required this.season}) {
|
||||
nerdStats = (apm != null && pps != null && vs != null)
|
||||
? NerdStats(apm!, pps!, vs!)
|
||||
: null;
|
||||
estTr = (nerdStats != null)
|
||||
? EstTr(apm!, pps!, vs!, nerdStats!.app, nerdStats!.dss, nerdStats!.dsp,
|
||||
nerdStats!.gbe)
|
||||
: null;
|
||||
playstyle = (nerdStats != null)
|
||||
? Playstyle(apm!, pps!, nerdStats!.app, nerdStats!.vsapm,
|
||||
nerdStats!.dsp, nerdStats!.gbe, estTr!.srarea, estTr!.statrank)
|
||||
: null;
|
||||
}
|
||||
|
||||
double get winrate => gamesWon / gamesPlayed;
|
||||
double get s1tr => gxe * 250;
|
||||
|
||||
TetraLeague.fromJson(Map<String, dynamic> json, ts, int s, String i) {
|
||||
timestamp = ts;
|
||||
TetraLeague.fromJson(
|
||||
Map<String, dynamic> json, DateTime? ts, int s, String i) {
|
||||
timestamp = ts != null ? ts : seasonEnds[s - 1];
|
||||
season = s;
|
||||
id = i;
|
||||
gamesPlayed = json['gamesplayed'] ?? 0;
|
||||
gamesWon = json['gameswon'] ?? 0;
|
||||
tr = json['tr'] != null ? json['tr'].toDouble() : json['rating'] != null ? json['rating'].toDouble() : -1;
|
||||
tr = json['tr'] != null
|
||||
? json['tr'].toDouble()
|
||||
: json['rating'] != null
|
||||
? json['rating'].toDouble()
|
||||
: -1;
|
||||
glicko = json['glicko']?.toDouble();
|
||||
rd = json['rd'] != null ? json['rd']!.toDouble() : noTrRd;
|
||||
gxe = json['gxe'] != null ? json['gxe'].toDouble() : -1;
|
||||
|
@ -81,38 +94,67 @@ class TetraLeague {
|
|||
apm = json['apm']?.toDouble();
|
||||
pps = json['pps']?.toDouble();
|
||||
vs = json['vs']?.toDouble();
|
||||
decaying = switch(json['decaying'].runtimeType){
|
||||
decaying = switch (json['decaying'].runtimeType) {
|
||||
int => json['decaying'] == 1,
|
||||
bool => json['decaying'],
|
||||
_ => false
|
||||
};
|
||||
standing = json['standing'] ?? json['placement'] ?? -1;
|
||||
percentile = json['percentile'] != null ? json['percentile'].toDouble() : rankCutoffs[rank];
|
||||
percentile = json['percentile'] != null
|
||||
? json['percentile'].toDouble()
|
||||
: rankCutoffs[rank];
|
||||
standingLocal = json['standing_local'] ?? -1;
|
||||
prevRank = json['prev_rank'];
|
||||
prevAt = json['prev_at'] ?? -1;
|
||||
nextRank = json['next_rank'];
|
||||
nextAt = json['next_at'] ?? -1;
|
||||
percentileRank = json['percentile_rank'] ?? rank;
|
||||
nerdStats = (apm != null && pps != null && vs != null) ? NerdStats(apm!, pps!, vs!) : null;
|
||||
estTr = (nerdStats != null) ? EstTr(apm!, pps!, vs!, nerdStats!.app, nerdStats!.dss, nerdStats!.dsp, nerdStats!.gbe) : null;
|
||||
playstyle = (nerdStats != null) ? Playstyle(apm!, pps!, nerdStats!.app, nerdStats!.vsapm, nerdStats!.dsp, nerdStats!.gbe, estTr!.srarea, estTr!.statrank) : null;
|
||||
nerdStats = (apm != null && pps != null && vs != null)
|
||||
? NerdStats(apm!, pps!, vs!)
|
||||
: null;
|
||||
estTr = (nerdStats != null)
|
||||
? EstTr(apm!, pps!, vs!, nerdStats!.app, nerdStats!.dss, nerdStats!.dsp,
|
||||
nerdStats!.gbe)
|
||||
: null;
|
||||
playstyle = (nerdStats != null)
|
||||
? Playstyle(apm!, pps!, nerdStats!.app, nerdStats!.vsapm,
|
||||
nerdStats!.dsp, nerdStats!.gbe, estTr!.srarea, estTr!.statrank)
|
||||
: null;
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(covariant TetraLeague other) => gamesPlayed == other.gamesPlayed && rd == other.rd;
|
||||
bool operator ==(covariant TetraLeague other) =>
|
||||
gamesPlayed == other.gamesPlayed && rd == other.rd;
|
||||
|
||||
bool lessStrictCheck (covariant TetraLeague other) => gamesPlayed == other.gamesPlayed && glicko == other.glicko;
|
||||
bool lessStrictCheck(covariant TetraLeague other) =>
|
||||
gamesPlayed == other.gamesPlayed && glicko == other.glicko;
|
||||
|
||||
double? get esttracc => (estTr != null) ? estTr!.esttr - tr : null;
|
||||
|
||||
TetrioPlayerFromLeaderboard convertToPlayerFromLeaderboard(String id) => TetrioPlayerFromLeaderboard(
|
||||
id, "", "user", -1, null, timestamp, gamesPlayed, gamesWon,
|
||||
tr, gxe, glicko??0, rd??noTrRd, rank, bestRank, apm??0, pps??0, vs??0, decaying);
|
||||
TetrioPlayerFromLeaderboard convertToPlayerFromLeaderboard(String id) =>
|
||||
TetrioPlayerFromLeaderboard(
|
||||
id,
|
||||
"",
|
||||
"user",
|
||||
-1,
|
||||
null,
|
||||
timestamp,
|
||||
gamesPlayed,
|
||||
gamesWon,
|
||||
tr,
|
||||
gxe,
|
||||
glicko ?? 0,
|
||||
rd ?? noTrRd,
|
||||
rank,
|
||||
bestRank,
|
||||
apm ?? 0,
|
||||
pps ?? 0,
|
||||
vs ?? 0,
|
||||
decaying);
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id+timestamp.millisecondsSinceEpoch.toRadixString(16);
|
||||
data['id'] = id + timestamp.millisecondsSinceEpoch.toRadixString(16);
|
||||
if (gamesPlayed > 0) data['gamesplayed'] = gamesPlayed;
|
||||
if (gamesWon > 0) data['gameswon'] = gamesWon;
|
||||
if (tr >= 0) data['tr'] = tr;
|
||||
|
|
|
@ -13,7 +13,24 @@ const double vsapmWeight = 60;
|
|||
const double cheeseWeight = 1.25;
|
||||
const double gbeWeight = 315;
|
||||
const List<String> ranks = [
|
||||
"d", "d+", "c-", "c", "c+", "b-", "b", "b+", "a-", "a", "a+", "s-", "s", "s+", "ss", "u", "x", "x+"
|
||||
"d",
|
||||
"d+",
|
||||
"c-",
|
||||
"c",
|
||||
"c+",
|
||||
"b-",
|
||||
"b",
|
||||
"b+",
|
||||
"a-",
|
||||
"a",
|
||||
"a+",
|
||||
"s-",
|
||||
"s",
|
||||
"s+",
|
||||
"ss",
|
||||
"u",
|
||||
"x",
|
||||
"x+"
|
||||
];
|
||||
const Map<String, double> rankCutoffs = {
|
||||
"x+": 0.002,
|
||||
|
@ -57,6 +74,7 @@ const Map<String, double> rankTargets = {
|
|||
"d+": 800.00,
|
||||
"d": 0.00,
|
||||
};
|
||||
|
||||
// DateTime seasonStart = DateTime.utc(2024, 08, 16, 18);
|
||||
//DateTime seasonEnd = DateTime.utc(2024, 07, 26, 15);
|
||||
enum Stats {
|
||||
|
@ -89,7 +107,7 @@ enum Stats {
|
|||
stride,
|
||||
stridemMinusPlonk,
|
||||
openerMinusInfDS
|
||||
}
|
||||
}
|
||||
|
||||
const Map<Stats, String> chartsShortTitles = {
|
||||
Stats.tr: "TR",
|
||||
|
@ -120,69 +138,81 @@ const Map<Stats, String> chartsShortTitles = {
|
|||
Stats.infDS: "Inf. DS",
|
||||
Stats.stride: "Stride",
|
||||
Stats.stridemMinusPlonk: "Stride - Plonk",
|
||||
Stats.openerMinusInfDS: "Opener - Inf. DS"
|
||||
};
|
||||
|
||||
const Map<String, Color> rankColors = { // thanks osk for const rankColors at https://ch.tetr.io/res/js/base.js:458
|
||||
'x+': Color(0xFF643C8D),
|
||||
'x': Color(0xFFFF45FF),
|
||||
'u': Color(0xFFFF3813),
|
||||
'ss': Color(0xFFDB8B1F),
|
||||
's+': Color(0xFFD8AF0E),
|
||||
's': Color(0xFFE0A71B),
|
||||
's-': Color(0xFFB2972B),
|
||||
'a+': Color(0xFF1FA834),
|
||||
'a': Color(0xFF46AD51),
|
||||
'a-': Color(0xFF3BB687),
|
||||
'b+': Color(0xFF4F99C0),
|
||||
'b': Color(0xFF4F64C9),
|
||||
'b-': Color(0xFF5650C7),
|
||||
'c+': Color(0xFF552883),
|
||||
'c': Color(0xFF733E8F),
|
||||
'c-': Color(0xFF79558C),
|
||||
'd+': Color(0xFF8E6091),
|
||||
'd': Color(0xFF907591),
|
||||
'z': Color(0xFF375433)
|
||||
Stats.openerMinusInfDS: "Opener - Inf. DS"
|
||||
};
|
||||
|
||||
const Map<String, Duration> sprintAverages = { // based on https://discord.com/channels/673303546107658242/674421736162197515/1244287342965952562
|
||||
'x': Duration(seconds: 25, milliseconds: 144),
|
||||
'u': Duration(seconds: 36, milliseconds: 115),
|
||||
'ss': Duration(seconds: 46, milliseconds: 396),
|
||||
's+': Duration(seconds: 55, milliseconds: 056),
|
||||
's': Duration(seconds: 61, milliseconds: 892),
|
||||
's-': Duration(seconds: 68, milliseconds: 918),
|
||||
'a+': Duration(seconds: 76, milliseconds: 187),
|
||||
'a': Duration(seconds: 83, milliseconds: 529),
|
||||
'a-': Duration(seconds: 88, milliseconds: 608),
|
||||
'b+': Duration(seconds: 97, milliseconds: 626),
|
||||
'b': Duration(seconds: 104, milliseconds: 687),
|
||||
'b-': Duration(seconds: 113, milliseconds: 372),
|
||||
'c+': Duration(seconds: 123, milliseconds: 461),
|
||||
'c': Duration(seconds: 135, milliseconds: 326),
|
||||
'c-': Duration(seconds: 147, milliseconds: 056),
|
||||
'd+': Duration(seconds: 156, milliseconds: 757),
|
||||
'd': Duration(seconds: 167, milliseconds: 393),
|
||||
//'z': Duration(seconds: 66, milliseconds: 802)
|
||||
const Map<String, Color> rankColors = {
|
||||
// thanks osk for const rankColors at https://ch.tetr.io/res/js/base.js:458
|
||||
'x+': Color(0xFF643C8D),
|
||||
'x': Color(0xFFFF45FF),
|
||||
'u': Color(0xFFFF3813),
|
||||
'ss': Color(0xFFDB8B1F),
|
||||
's+': Color(0xFFD8AF0E),
|
||||
's': Color(0xFFE0A71B),
|
||||
's-': Color(0xFFB2972B),
|
||||
'a+': Color(0xFF1FA834),
|
||||
'a': Color(0xFF46AD51),
|
||||
'a-': Color(0xFF3BB687),
|
||||
'b+': Color(0xFF4F99C0),
|
||||
'b': Color(0xFF4F64C9),
|
||||
'b-': Color(0xFF5650C7),
|
||||
'c+': Color(0xFF552883),
|
||||
'c': Color(0xFF733E8F),
|
||||
'c-': Color(0xFF79558C),
|
||||
'd+': Color(0xFF8E6091),
|
||||
'd': Color(0xFF907591),
|
||||
'z': Color(0xFF375433)
|
||||
};
|
||||
|
||||
const Map<String, Duration> sprintAverages = {
|
||||
// based on https://discord.com/channels/673303546107658242/674421736162197515/1244287342965952562
|
||||
'x': Duration(seconds: 25, milliseconds: 144),
|
||||
'u': Duration(seconds: 36, milliseconds: 115),
|
||||
'ss': Duration(seconds: 46, milliseconds: 396),
|
||||
's+': Duration(seconds: 55, milliseconds: 056),
|
||||
's': Duration(seconds: 61, milliseconds: 892),
|
||||
's-': Duration(seconds: 68, milliseconds: 918),
|
||||
'a+': Duration(seconds: 76, milliseconds: 187),
|
||||
'a': Duration(seconds: 83, milliseconds: 529),
|
||||
'a-': Duration(seconds: 88, milliseconds: 608),
|
||||
'b+': Duration(seconds: 97, milliseconds: 626),
|
||||
'b': Duration(seconds: 104, milliseconds: 687),
|
||||
'b-': Duration(seconds: 113, milliseconds: 372),
|
||||
'c+': Duration(seconds: 123, milliseconds: 461),
|
||||
'c': Duration(seconds: 135, milliseconds: 326),
|
||||
'c-': Duration(seconds: 147, milliseconds: 056),
|
||||
'd+': Duration(seconds: 156, milliseconds: 757),
|
||||
'd': Duration(seconds: 167, milliseconds: 393),
|
||||
//'z': Duration(seconds: 66, milliseconds: 802)
|
||||
};
|
||||
|
||||
const Map<String, int> blitzAverages = {
|
||||
'x': 600715,
|
||||
'u': 379418,
|
||||
'ss': 233740,
|
||||
's+': 158295,
|
||||
's': 125164,
|
||||
's-': 100933,
|
||||
'a+': 83593,
|
||||
'a': 68613,
|
||||
'a-': 60219,
|
||||
'b+': 51197,
|
||||
'b': 44171,
|
||||
'b-': 39045,
|
||||
'c+': 34130,
|
||||
'c': 28931,
|
||||
'c-': 25095,
|
||||
'd+': 22944,
|
||||
'd': 20728,
|
||||
//'z': 72084
|
||||
};
|
||||
'u': 379418,
|
||||
'ss': 233740,
|
||||
's+': 158295,
|
||||
's': 125164,
|
||||
's-': 100933,
|
||||
'a+': 83593,
|
||||
'a': 68613,
|
||||
'a-': 60219,
|
||||
'b+': 51197,
|
||||
'b': 44171,
|
||||
'b-': 39045,
|
||||
'c+': 34130,
|
||||
'c': 28931,
|
||||
'c-': 25095,
|
||||
'd+': 22944,
|
||||
'd': 20728,
|
||||
//'z': 72084
|
||||
};
|
||||
|
||||
List<DateTime> seasonStarts = [
|
||||
DateTime.utc(2020, DateTime.april, 18, 4), // Source = twitter or something
|
||||
DateTime.utc(
|
||||
2024, DateTime.august, 16, 18, 41, 10) // Source = osk status page
|
||||
];
|
||||
|
||||
List<DateTime> seasonEnds = [
|
||||
DateTime.utc(2024, DateTime.july, 26, 15) // Source - TETR.IO discord guild
|
||||
];
|
||||
|
|
|
@ -16,7 +16,7 @@ import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
|||
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
|
||||
import 'package:tetra_stats/gen/strings.g.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:tetra_stats/views/main_view_tiles.dart';
|
||||
import 'package:tetra_stats/views/main_view.dart';
|
||||
import 'package:tetra_stats/views/settings_view.dart';
|
||||
import 'package:tetra_stats/views/tracked_players_view.dart';
|
||||
import 'package:tetra_stats/views/calc_view.dart';
|
||||
|
|
|
@ -1154,7 +1154,7 @@ class TetrioService extends DB {
|
|||
if (kIsWeb) {
|
||||
dUrl = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "tetrioUserByDiscordID", "user": user.toLowerCase().trim()});
|
||||
} else {
|
||||
dUrl = Uri.https('ch.tetr.io', 'api/users/search/${user.toLowerCase().trim()}');
|
||||
dUrl = Uri.https('ch.tetr.io', 'api/users/search/discord:${user.toLowerCase().trim()}');
|
||||
}
|
||||
try{
|
||||
final response = await client.get(dUrl);
|
||||
|
|
|
@ -7,4 +7,8 @@ Color getColorOfRank(int rank){
|
|||
if (rank <= 9) return Colors.blueAccent;
|
||||
if (rank <= 99) return Colors.greenAccent;
|
||||
return Colors.grey;
|
||||
}
|
||||
|
||||
Color getDifferenceColor(num diff){
|
||||
return diff.isNegative ? Colors.redAccent : Colors.greenAccent;
|
||||
}
|
|
@ -1,6 +1,7 @@
|
|||
import 'package:intl/intl.dart';
|
||||
import 'package:tetra_stats/gen/strings.g.dart';
|
||||
|
||||
final NumberFormat compareIntf = NumberFormat("+#,###;-#,###")..maximumFractionDigits = 0;
|
||||
final NumberFormat comparef = NumberFormat("+#,###.###;-#,###.###")..maximumFractionDigits = 3;
|
||||
final NumberFormat comparef2 = NumberFormat("+#,###.##;-#,###.##")..maximumFractionDigits = 2;
|
||||
final NumberFormat intf = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 0);
|
||||
|
|
|
@ -243,7 +243,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
bool _smooth = false;
|
||||
final List _historyShortTitles = ["TR", "Glicko", "RD", "APM", "PPS", "VS", "APP", "DS/S", "DS/P", "APP + DS/P", "VS/APM", "Cheese", "GbE", "wAPP", "Area", "eTR", "±eTR", "Opener", "Plonk", "Inf. DS", "Stride"];
|
||||
int _chartsIndex = 0;
|
||||
late List<DropdownMenuItem<List<_HistoryChartSpot>>> chartsData;
|
||||
late List<List<DropdownMenuItem<List<_HistoryChartSpot>>>> historyData;
|
||||
//Duration postSeasonLeft = seasonStart.difference(DateTime.now());
|
||||
|
||||
@override
|
||||
|
@ -282,10 +282,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
super.initState();
|
||||
}
|
||||
|
||||
Future<List<DropdownMenuItem<List<_HistoryChartSpot>>>> getChartsData(bool fetchHistory) async {
|
||||
List<TetrioPlayer> states = [];
|
||||
Set<TetraLeague> uniqueTL = {};
|
||||
|
||||
Future<List<List<DropdownMenuItem<List<_HistoryChartSpot>>>>> getHistoryData(bool fetchHistory) async {
|
||||
if(fetchHistory){
|
||||
try{
|
||||
var history = await teto.fetchAndsaveTLHistory(widget.searchFor);
|
||||
|
@ -301,49 +298,47 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
}
|
||||
}
|
||||
|
||||
//states.addAll(await teto.getPlayer(widget.searchFor));
|
||||
// for (var element in states) {
|
||||
// if (element.tlSeason1 != null && uniqueTL.isNotEmpty && uniqueTL.last != element.tlSeason1) uniqueTL.add(element.tlSeason1!);
|
||||
// if (uniqueTL.isEmpty) uniqueTL.add(element.tlSeason1!);
|
||||
// }
|
||||
List<List<TetraLeague>> states = await Future.wait<List<TetraLeague>>([
|
||||
teto.getStates(widget.searchFor, season: 1), teto.getStates(widget.searchFor, season: 2),
|
||||
]);
|
||||
|
||||
if (uniqueTL.length >= 2){
|
||||
chartsData = <DropdownMenuItem<List<_HistoryChartSpot>>>[ // Dumping charts data into dropdown menu items, while cheking if every entry is valid
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.gamesPlayed > 9) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.tr)], child: Text(t.statCellNum.tr)),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.gamesPlayed > 9) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.glicko!)], child: const Text("Glicko")),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.gamesPlayed > 9) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.rd!)], child: const Text("Rating Deviation")),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.apm != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.apm!)], child: Text(t.statCellNum.apm.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.pps != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.pps!)], child: Text(t.statCellNum.pps.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.vs != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.vs!)], child: Text(t.statCellNum.vs.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.app)], child: Text(t.statCellNum.app.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.dss)], child: Text(t.statCellNum.dss.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.dsp)], child: Text(t.statCellNum.dsp.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.appdsp)], child: const Text("APP + DS/P")),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.vsapm)], child: const Text("VS/APM")),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.cheese)], child: Text(t.statCellNum.cheese.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.gbe)], child: Text(t.statCellNum.gbe.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.nyaapp)], child: Text(t.statCellNum.nyaapp.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.area)], child: Text(t.statCellNum.area.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.estTr != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.estTr!.esttr)], child: Text(t.statCellNum.estOfTR.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.esttracc != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.esttracc!)], child: Text(t.statCellNum.accOfEst.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.opener)], child: const Text("Opener")),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.plonk)], child: const Text("Plonk")),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.infds)], child: const Text("Inf. DS")),
|
||||
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.stride)], child: const Text("Stride")),
|
||||
];
|
||||
if (states.length >= 2){
|
||||
historyData = [for (List<TetraLeague> s in states) <DropdownMenuItem<List<_HistoryChartSpot>>>[ // Dumping charts data into dropdown menu items, while cheking if every entry is valid
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.gamesPlayed > 9) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.tr)], child: Text(t.statCellNum.tr)),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.gamesPlayed > 9) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.glicko!)], child: const Text("Glicko")),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.gamesPlayed > 9) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.rd!)], child: const Text("Rating Deviation")),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.apm != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.apm!)], child: Text(t.statCellNum.apm.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.pps != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.pps!)], child: Text(t.statCellNum.pps.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.vs != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.vs!)], child: Text(t.statCellNum.vs.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.app)], child: Text(t.statCellNum.app.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.dss)], child: Text(t.statCellNum.dss.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.dsp)], child: Text(t.statCellNum.dsp.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.appdsp)], child: const Text("APP + DS/P")),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.vsapm)], child: const Text("VS/APM")),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.cheese)], child: Text(t.statCellNum.cheese.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.gbe)], child: Text(t.statCellNum.gbe.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.nyaapp)], child: Text(t.statCellNum.nyaapp.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.area)], child: Text(t.statCellNum.area.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.estTr != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.estTr!.esttr)], child: Text(t.statCellNum.estOfTR.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.esttracc != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.esttracc!)], child: Text(t.statCellNum.accOfEst.replaceAll(RegExp(r'\n'), " "))),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.opener)], child: const Text("Opener")),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.plonk)], child: const Text("Plonk")),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.infds)], child: const Text("Inf. DS")),
|
||||
DropdownMenuItem(value: [for (var tl in s) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.stride)], child: const Text("Stride")),
|
||||
]];
|
||||
}else{
|
||||
chartsData = [];
|
||||
historyData = [];
|
||||
}
|
||||
|
||||
fetchData = false;
|
||||
|
||||
return chartsData;
|
||||
return historyData;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<List<DropdownMenuItem<List<_HistoryChartSpot>>>>(
|
||||
future: getChartsData(fetchData),
|
||||
return FutureBuilder<List<List<DropdownMenuItem<List<_HistoryChartSpot>>>>>(
|
||||
future: getHistoryData(fetchData),
|
||||
builder: (context, snapshot) {
|
||||
switch (snapshot.connectionState){
|
||||
case ConnectionState.none:
|
||||
|
@ -352,7 +347,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
return const Center(child: CircularProgressIndicator());
|
||||
case ConnectionState.done:
|
||||
if (snapshot.hasData && snapshot.data!.isNotEmpty){
|
||||
List<_HistoryChartSpot> selectedGraph = snapshot.data![_chartsIndex].value!;
|
||||
List<_HistoryChartSpot> selectedGraph = snapshot.data![currentSeason-1][_chartsIndex].value!;
|
||||
yAxisTitle = _historyShortTitles[_chartsIndex];
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
|
@ -384,11 +379,11 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
children: [
|
||||
const Padding(padding: EdgeInsets.all(8.0), child: Text("Y:", style: TextStyle(fontSize: 22))),
|
||||
DropdownButton(
|
||||
items: chartsData,
|
||||
value: chartsData[_chartsIndex].value,
|
||||
items: historyData[currentSeason-1],
|
||||
value: historyData[currentSeason-1][_chartsIndex].value,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_chartsIndex = chartsData.indexWhere((element) => element.value == value);
|
||||
_chartsIndex = historyData[currentSeason-1].indexWhere((element) => element.value == value);
|
||||
});
|
||||
}
|
||||
),
|
||||
|
@ -411,7 +406,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
],
|
||||
),
|
||||
),
|
||||
if(chartsData[_chartsIndex].value!.length > 1) Card(
|
||||
if(historyData[currentSeason-1][_chartsIndex].value!.length > 1) Card(
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width - 88,
|
||||
height: MediaQuery.of(context).size.height - 60,
|
||||
|
@ -427,7 +422,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
series: <CartesianSeries>[
|
||||
if (_gamesPlayedInsteadOfDateAndTime) StepLineSeries<_HistoryChartSpot, int>(
|
||||
enableTooltip: true,
|
||||
dataSource: chartsData[_chartsIndex].value!,
|
||||
dataSource: historyData[currentSeason-1][_chartsIndex].value!,
|
||||
animationDuration: 0,
|
||||
opacity: _smooth ? 0 : 1,
|
||||
xValueMapper: (_HistoryChartSpot data, _) => data.gamesPlayed,
|
||||
|
@ -436,14 +431,14 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
trendlines:<Trendline>[
|
||||
Trendline(
|
||||
isVisible: _smooth,
|
||||
period: (chartsData[_chartsIndex].value!.length/175).floor(),
|
||||
period: (historyData[currentSeason-1][_chartsIndex].value!.length/175).floor(),
|
||||
type: TrendlineType.movingAverage,
|
||||
color: Theme.of(context).colorScheme.primary)
|
||||
],
|
||||
)
|
||||
else StepLineSeries<_HistoryChartSpot, DateTime>(
|
||||
enableTooltip: true,
|
||||
dataSource: chartsData[_chartsIndex].value!,
|
||||
dataSource: historyData[currentSeason-1][_chartsIndex].value!,
|
||||
animationDuration: 0,
|
||||
opacity: _smooth ? 0 : 1,
|
||||
xValueMapper: (_HistoryChartSpot data, _) => data.timestamp,
|
||||
|
@ -452,7 +447,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
trendlines:<Trendline>[
|
||||
Trendline(
|
||||
isVisible: _smooth,
|
||||
period: (chartsData[_chartsIndex].value!.length/175).floor(),
|
||||
period: (historyData[currentSeason-1][_chartsIndex].value!.length/175).floor(),
|
||||
type: TrendlineType.movingAverage,
|
||||
color: Theme.of(context).colorScheme.primary)
|
||||
],
|
||||
|
@ -462,7 +457,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
)
|
||||
),
|
||||
)
|
||||
else if (chartsData[_chartsIndex].value!.length <= 1) Center(child: Column(
|
||||
else if (historyData[currentSeason-1][_chartsIndex].value!.length <= 1) Center(child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(t.notEnoughData, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28)),
|
||||
|
@ -525,11 +520,12 @@ class DestinationHome extends StatefulWidget{
|
|||
class FetchResults{
|
||||
bool success;
|
||||
TetrioPlayer? player;
|
||||
List<TetraLeague> states;
|
||||
Summaries? summaries;
|
||||
Cutoffs? cutoffs;
|
||||
Exception? exception;
|
||||
|
||||
FetchResults(this.success, this.player, this.summaries, this.cutoffs, this.exception);
|
||||
FetchResults(this.success, this.player, this.states, this.summaries, this.cutoffs, this.exception);
|
||||
}
|
||||
|
||||
class RecordSummary extends StatelessWidget{
|
||||
|
@ -623,7 +619,19 @@ class LeagueCard extends StatelessWidget{
|
|||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(showSeasonNumber ? "Season ${league.season}" : "Tetra League", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28, height: 0.9)),
|
||||
if (showSeasonNumber) Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
children: [
|
||||
Text("Season ${league.season}", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28, height: 0.9)),
|
||||
Spacer(),
|
||||
Text(
|
||||
"${seasonStarts.elementAtOrNull(league.season - 1) != null ? timestamp(seasonStarts[league.season - 1]) : "---"} — ${seasonEnds.elementAtOrNull(league.season - 1) != null ? timestamp(seasonEnds[league.season - 1]) : "---"}",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(color: Colors.grey)),
|
||||
],
|
||||
)
|
||||
else Text("Tetra League", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28, height: 0.9)),
|
||||
const Divider(color: Color.fromARGB(50, 158, 158, 158)),
|
||||
TLRatingThingy(userID: "", tlData: league, showPositions: true),
|
||||
const Divider(color: Color.fromARGB(50, 158, 158, 158)),
|
||||
|
@ -658,7 +666,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
|||
player = await teto.fetchPlayer(widget.searchFor); // Otherwise it's probably a user id or username
|
||||
}
|
||||
}on TetrioPlayerNotExist{
|
||||
return FetchResults(false, null, null, null, TetrioPlayerNotExist());
|
||||
return FetchResults(false, null, [], null, null, TetrioPlayerNotExist());
|
||||
}
|
||||
late Summaries summaries;
|
||||
late Cutoffs cutoffs;
|
||||
|
@ -666,9 +674,16 @@ class _DestinationHomeState extends State<DestinationHome> {
|
|||
teto.fetchSummaries(player.userId),
|
||||
teto.fetchCutoffsBeanserver(),
|
||||
]);
|
||||
List<TetraLeague> states = await teto.getStates(player.userId, season: currentSeason);
|
||||
summaries = requests[0];
|
||||
cutoffs = requests[1];
|
||||
return FetchResults(true, player, summaries, cutoffs, null);
|
||||
|
||||
bool isTracking = await teto.isPlayerTracking(player.userId);
|
||||
if (isTracking){ // if tracked - save data to local DB
|
||||
await teto.storeState(summaries.league);
|
||||
}
|
||||
|
||||
return FetchResults(true, player, states, summaries, cutoffs, null);
|
||||
}
|
||||
|
||||
Widget getOverviewCard(Summaries summaries){
|
||||
|
@ -863,7 +878,8 @@ class _DestinationHomeState extends State<DestinationHome> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget getTetraLeagueCard(TetraLeague data, Cutoffs? cutoffs){
|
||||
Widget getTetraLeagueCard(TetraLeague data, Cutoffs? cutoffs, List<TetraLeague> states){
|
||||
TetraLeague? toCompare = states.length >= 2 ? states.elementAtOrNull(states.length-2) : null;
|
||||
return Column(
|
||||
children: [
|
||||
Card(
|
||||
|
@ -876,13 +892,13 @@ class _DestinationHomeState extends State<DestinationHome> {
|
|||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text(t.tetraLeague, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 42)),
|
||||
//Text("${t.seasonStarts} ${countdown(postSeasonLeft)}", textAlign: TextAlign.center)
|
||||
//Text("${states.last.timestamp} ${states.last.tr}", textAlign: TextAlign.center)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
TetraLeagueThingy(league: data, cutoffs: cutoffs),
|
||||
TetraLeagueThingy(league: data, toCompare: toCompare, cutoffs: cutoffs),
|
||||
if (data.nerdStats != null) Card(
|
||||
//surfaceTintColor: rankColors[data.rank],
|
||||
child: Row(
|
||||
|
@ -894,7 +910,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
|||
],
|
||||
),
|
||||
),
|
||||
if (data.nerdStats != null) NerdStatsThingy(nerdStats: data.nerdStats!),
|
||||
if (data.nerdStats != null) NerdStatsThingy(nerdStats: data.nerdStats!, oldNerdStats: toCompare?.nerdStats),
|
||||
if (data.nerdStats != null) GraphsThingy(nerdStats: data.nerdStats!, playstyle: data.playstyle!, apm: data.apm!, pps: data.pps!, vs: data.vs!)
|
||||
],
|
||||
);
|
||||
|
@ -1581,7 +1597,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
|||
child: switch (rightCard){
|
||||
Cards.overview => getOverviewCard(snapshot.data!.summaries!),
|
||||
Cards.tetraLeague => switch (cardMod){
|
||||
CardMod.info => getTetraLeagueCard(snapshot.data!.summaries!.league, snapshot.data!.cutoffs),
|
||||
CardMod.info => getTetraLeagueCard(snapshot.data!.summaries!.league, snapshot.data!.cutoffs, snapshot.data!.states),
|
||||
CardMod.ex => getPreviousSeasonsList(snapshot.data!.summaries!.pastLeague),
|
||||
CardMod.records => getRecentTLrecords(widget.constraints),
|
||||
_ => const Center(child: Text("huh?"))
|
||||
|
@ -2065,12 +2081,10 @@ class BadgesThingy extends StatelessWidget{
|
|||
icon: Image.asset(
|
||||
"res/tetrio_badges/${badge.badgeId}.png",
|
||||
height: 32,
|
||||
width: 32,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Image.network(
|
||||
kIsWeb ? "https://ts.dan63.by/oskware_bridge.php?endpoint=TetrioBadge&badge=${badge.badgeId}" : "https://tetr.io/res/badges/${badge.badgeId}.png",
|
||||
height: 32,
|
||||
width: 32,
|
||||
errorBuilder:(context, error, stackTrace) {
|
||||
return Image.asset("res/icons/kagari.png", height: 32, width: 32);
|
||||
}
|
||||
|
@ -2407,9 +2421,10 @@ class _SearchDrawerState extends State<SearchDrawer> {
|
|||
|
||||
class TetraLeagueThingy extends StatelessWidget{
|
||||
final TetraLeague league;
|
||||
final TetraLeague? toCompare;
|
||||
final Cutoffs? cutoffs;
|
||||
|
||||
const TetraLeagueThingy({super.key, required this.league, this.cutoffs});
|
||||
const TetraLeagueThingy({super.key, required this.league, this.toCompare, this.cutoffs});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -2422,8 +2437,8 @@ class TetraLeagueThingy extends StatelessWidget{
|
|||
tlData: league,
|
||||
previousRankTRcutoff: cutoffs != null ? cutoffs!.tr[league.rank != "z" ? league.rank : league.percentileRank] : null,
|
||||
nextRankTRcutoff: cutoffs != null ? (league.rank != "z" ? league.rank == "x+" : league.percentileRank == "x+") ? 25000 : cutoffs!.tr[ranks.elementAtOrNull(ranks.indexOf(league.rank != "z" ? league.rank : league.percentileRank)+1)] : null,
|
||||
nextRankTRcutoffTarget: league.rank != "z" ? rankTargets[league.rank] : null,
|
||||
previousRankTRcutoffTarget: (league.rank != "z" && league.rank != "x+") ? rankTargets[ranks.elementAtOrNull(ranks.indexOf(league.rank)+1)] : null,
|
||||
previousRankTRcutoffTarget: league.rank != "z" ? rankTargets[league.rank] : null,
|
||||
nextRankTRcutoffTarget: (league.rank != "z" && league.rank != "x+") ? rankTargets[ranks.elementAtOrNull(ranks.indexOf(league.rank)+1)] : null,
|
||||
previousGlickoCutoff: cutoffs != null ? cutoffs!.glicko[league.rank != "z" ? league.rank : league.percentileRank] : null,
|
||||
nextRankGlickoCutoff: cutoffs != null ? (league.rank != "z" ? league.rank == "x+" : league.percentileRank == "x+") ? 25000 : cutoffs!.glicko[ranks.elementAtOrNull(ranks.indexOf(league.rank != "z" ? league.rank : league.percentileRank)+1)] : null,
|
||||
),
|
||||
|
@ -2438,16 +2453,19 @@ class TetraLeagueThingy extends StatelessWidget{
|
|||
defaultColumnWidth:const IntrinsicColumnWidth(),
|
||||
children: [
|
||||
TableRow(children: [
|
||||
const Text("APM: ", style: TextStyle(fontSize: 21)),
|
||||
Text(f2.format(league.apm??0.00), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
const Text(" APM", style: TextStyle(fontSize: 21)),
|
||||
if (toCompare != null) Text(" (${comparef2.format(league.apm!-toCompare!.apm!)})", textAlign: TextAlign.right, style: TextStyle(fontSize: 21, color: getDifferenceColor(league.apm!-toCompare!.apm!)))
|
||||
]),
|
||||
TableRow(children: [
|
||||
const Text("PPS: ", style: TextStyle(fontSize: 21)),
|
||||
Text(f2.format(league.pps??0.00), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
const Text(" PPS", style: TextStyle(fontSize: 21)),
|
||||
if (toCompare != null) Text(" (${comparef2.format(league.pps!-toCompare!.pps!)})", textAlign: TextAlign.right, style: TextStyle(fontSize: 21, color: getDifferenceColor(league.pps!-toCompare!.pps!)))
|
||||
]),
|
||||
TableRow(children: [
|
||||
const Text("VS: ", style: TextStyle(fontSize: 21)),
|
||||
Text(f2.format(league.vs??0.00), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
const Text(" VS", style: TextStyle(fontSize: 21)),
|
||||
if (toCompare != null) Text(" (${comparef2.format(league.vs!-toCompare!.vs!)})", textAlign: TextAlign.right, style: TextStyle(fontSize: 21, color: getDifferenceColor(league.vs!-toCompare!.vs!)))
|
||||
])
|
||||
],
|
||||
),
|
||||
|
@ -2480,6 +2498,10 @@ class TetraLeagueThingy extends StatelessWidget{
|
|||
GaugeAnnotation(widget: Container(child:
|
||||
Text(t.statCellNum.winrate, textAlign: TextAlign.center)),
|
||||
angle: 270,positionFactor: 0.4
|
||||
),
|
||||
if (toCompare != null) GaugeAnnotation(widget: Container(child:
|
||||
Text(comparef2.format((league.winrate-toCompare!.winrate)*100), textAlign: TextAlign.center, style: TextStyle(color: getDifferenceColor(league.winrate-toCompare!.winrate)))),
|
||||
angle: 90,positionFactor: 0.45
|
||||
)
|
||||
],
|
||||
)
|
||||
|
@ -2495,17 +2517,20 @@ class TetraLeagueThingy extends StatelessWidget{
|
|||
TableRow(children: [
|
||||
//Text("VS: ", style: TextStyle(fontSize: 21)),
|
||||
Text("№ ${league.standingLocal.isNegative ? "---" : intf.format(league.standingLocal)}", textAlign: TextAlign.right, style: TextStyle(fontSize: 21, color: league.standingLocal.isNegative ? Colors.grey : Colors.white)),
|
||||
Text(" local", style: TextStyle(fontSize: 21, color: league.standingLocal.isNegative ? Colors.grey : Colors.white))
|
||||
Text(" local", style: TextStyle(fontSize: 21, color: league.standingLocal.isNegative ? Colors.grey : Colors.white)),
|
||||
if (toCompare != null) Text(" (${compareIntf.format(league.standingLocal-toCompare!.standingLocal)})", textAlign: TextAlign.right, style: TextStyle(fontSize: 21, color: getDifferenceColor(league.standingLocal-toCompare!.standingLocal)))
|
||||
]),
|
||||
TableRow(children: [
|
||||
//Text("APM: ", style: TextStyle(fontSize: 21)),
|
||||
Text(intf.format(league.gamesPlayed), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
const Text(" Games", style: TextStyle(fontSize: 21))
|
||||
const Text(" Games", style: TextStyle(fontSize: 21)),
|
||||
if (toCompare != null) Text(" (${comparef2.format(league.gamesPlayed-toCompare!.gamesPlayed)})", textAlign: TextAlign.right, style: TextStyle(fontSize: 21, color: Colors.grey))
|
||||
]),
|
||||
TableRow(children: [
|
||||
//Text("PPS: ", style: TextStyle(fontSize: 21)),
|
||||
Text(intf.format(league.gamesWon), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
const Text(" Won", style: TextStyle(fontSize: 21))
|
||||
const Text(" Won", style: TextStyle(fontSize: 21)),
|
||||
if (toCompare != null) Text(" (${comparef2.format(league.gamesWon-toCompare!.gamesWon)})", textAlign: TextAlign.right, style: TextStyle(fontSize: 21, color: Colors.grey))
|
||||
])
|
||||
],
|
||||
),
|
||||
|
@ -2521,8 +2546,9 @@ class TetraLeagueThingy extends StatelessWidget{
|
|||
|
||||
class NerdStatsThingy extends StatelessWidget{
|
||||
final NerdStats nerdStats;
|
||||
final NerdStats? oldNerdStats;
|
||||
|
||||
const NerdStatsThingy({super.key, required this.nerdStats});
|
||||
const NerdStatsThingy({super.key, required this.nerdStats, this.oldNerdStats});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -2530,7 +2556,7 @@ class NerdStatsThingy extends StatelessWidget{
|
|||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(12.0, 0.0, 12.0, 0.0),
|
||||
padding: const EdgeInsets.fromLTRB(12.0, 8.0, 12.0, 8.0),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
|
@ -2565,7 +2591,7 @@ class NerdStatsThingy extends StatelessWidget{
|
|||
children: [
|
||||
const TextSpan(text: "APP\n"),
|
||||
TextSpan(text: f3.format(nerdStats.app), style: const TextStyle(fontSize: 25, fontFamily: "Eurostile Round Extended", fontWeight: FontWeight.w100)),
|
||||
//TextSpan(text: "\nAPP"),
|
||||
if (oldNerdStats != null) TextSpan(text: "\n${comparef.format(nerdStats.app - oldNerdStats!.app)}", style: TextStyle(color: getDifferenceColor(nerdStats.app - oldNerdStats!.app))),
|
||||
]
|
||||
))),
|
||||
angle: 270,positionFactor: 0.5
|
||||
|
@ -2595,6 +2621,7 @@ class NerdStatsThingy extends StatelessWidget{
|
|||
children: [
|
||||
const TextSpan(text: "VS/APM\n"),
|
||||
TextSpan(text: f3.format(nerdStats.vsapm), style: const TextStyle(fontSize: 25, fontFamily: "Eurostile Round Extended", fontWeight: FontWeight.w100)),
|
||||
if (oldNerdStats != null) TextSpan(text: "\n${comparef.format(nerdStats.vsapm - oldNerdStats!.vsapm)}", style: TextStyle(color: getDifferenceColor(nerdStats.vsapm - oldNerdStats!.vsapm))),
|
||||
]
|
||||
))),
|
||||
angle: 90,positionFactor: 0.5
|
||||
|
@ -2608,15 +2635,17 @@ class NerdStatsThingy extends StatelessWidget{
|
|||
Expanded(
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 10,
|
||||
spacing: 10.0,
|
||||
runSpacing: 10.0,
|
||||
runAlignment: WrapAlignment.start,
|
||||
children: [
|
||||
GaugetThingy(value: nerdStats.dss, min: 0, max: 1.0, tickInterval: .2, label: "DS/S", sideSize: 128.0, fractionDigits: 3),
|
||||
GaugetThingy(value: nerdStats.dsp, min: 0, max: 1.0, tickInterval: .2, label: "DS/P", sideSize: 128.0, fractionDigits: 3),
|
||||
GaugetThingy(value: nerdStats.appdsp, min: 0, max: 1.2, tickInterval: .2, label: "APP+DS/P", sideSize: 128.0, fractionDigits: 3),
|
||||
GaugetThingy(value: nerdStats.cheese, min: -80, max: 80, tickInterval: 40, label: "Cheese", sideSize: 128.0, fractionDigits: 2),
|
||||
GaugetThingy(value: nerdStats.gbe, min: 0, max: 1.0, tickInterval: .2, label: "GbE", sideSize: 128.0, fractionDigits: 3),
|
||||
GaugetThingy(value: nerdStats.nyaapp, min: 0, max: 1.2, tickInterval: .2, label: "wAPP", sideSize: 128.0, fractionDigits: 3),
|
||||
GaugetThingy(value: nerdStats.area, min: 0, max: 1000, tickInterval: 100, label: "Area", sideSize: 128.0, fractionDigits: 1),
|
||||
GaugetThingy(value: nerdStats.dss, oldValue: oldNerdStats?.dss, min: 0, max: 1.0, tickInterval: .2, label: "DS/S", sideSize: 128.0, fractionDigits: 3, moreIsBetter: true),
|
||||
GaugetThingy(value: nerdStats.dsp, oldValue: oldNerdStats?.dsp, min: 0, max: 1.0, tickInterval: .2, label: "DS/P", sideSize: 128.0, fractionDigits: 3, moreIsBetter: true),
|
||||
GaugetThingy(value: nerdStats.appdsp, oldValue: oldNerdStats?.appdsp, min: 0, max: 1.2, tickInterval: .2, label: "APP+DS/P", sideSize: 128.0, fractionDigits: 3, moreIsBetter: true),
|
||||
GaugetThingy(value: nerdStats.cheese, oldValue: oldNerdStats?.cheese, min: -80, max: 80, tickInterval: 40, label: "Cheese", sideSize: 128.0, fractionDigits: 2, moreIsBetter: false),
|
||||
GaugetThingy(value: nerdStats.gbe, oldValue: oldNerdStats?.gbe, min: 0, max: 1.0, tickInterval: .2, label: "GbE", sideSize: 128.0, fractionDigits: 3, moreIsBetter: true),
|
||||
GaugetThingy(value: nerdStats.nyaapp, oldValue: oldNerdStats?.nyaapp, min: 0, max: 1.2, tickInterval: .2, label: "wAPP", sideSize: 128.0, fractionDigits: 3, moreIsBetter: true),
|
||||
GaugetThingy(value: nerdStats.area, oldValue: oldNerdStats?.area, min: 0, max: 1000, tickInterval: 100, label: "Area", sideSize: 128.0, fractionDigits: 1, moreIsBetter: true),
|
||||
],
|
||||
),
|
||||
)
|
||||
|
@ -2667,12 +2696,14 @@ class GaugetThingy extends StatelessWidget{
|
|||
final double value;
|
||||
final double min;
|
||||
final double max;
|
||||
final double? oldValue;
|
||||
final bool moreIsBetter;
|
||||
final double tickInterval;
|
||||
final String label;
|
||||
final double sideSize;
|
||||
final int fractionDigits;
|
||||
|
||||
GaugetThingy({super.key, required this.value, required this.min, required this.max, required this.tickInterval, required this.label, required this.sideSize, required this.fractionDigits});
|
||||
GaugetThingy({super.key, required this.value, required this.min, required this.max, this.oldValue, required this.tickInterval, required this.label, required this.sideSize, required this.fractionDigits, required this.moreIsBetter});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -2704,6 +2735,10 @@ class GaugetThingy extends StatelessWidget{
|
|||
GaugeAnnotation(widget: Container(child:
|
||||
Text(label, textAlign: TextAlign.center, style: const TextStyle(height: .9))),
|
||||
angle: 270,positionFactor: 0.4
|
||||
),
|
||||
if (oldValue != null) GaugeAnnotation(widget: Container(child:
|
||||
Text(comparef2.format(value-oldValue!), textAlign: TextAlign.center, style: TextStyle(color: getDifferenceColor(moreIsBetter ? value-oldValue! : oldValue!-value)))),
|
||||
angle: 90,positionFactor: 0.45
|
||||
)
|
||||
],
|
||||
)
|
||||
|
|
|
@ -166,17 +166,17 @@ class MyRadarChartPainter extends RadarChartPainter{
|
|||
);
|
||||
}
|
||||
|
||||
_ticksTextPaint
|
||||
..text = TextSpan(
|
||||
text: percentage.format(tick),
|
||||
style: Utils().getThemeAwareTextStyle(context, data.ticksTextStyle),
|
||||
)
|
||||
..textDirection = TextDirection.ltr
|
||||
..layout(maxWidth: size.width);
|
||||
canvasWrapper.drawText(
|
||||
_ticksTextPaint,
|
||||
Offset(centerX + 5, centerY - tickRadius - _ticksTextPaint.height/2),
|
||||
);
|
||||
// _ticksTextPaint
|
||||
// ..text = TextSpan(
|
||||
// text: percentage.format(tick),
|
||||
// style: Utils().getThemeAwareTextStyle(context, data.ticksTextStyle),
|
||||
// )
|
||||
// ..textDirection = TextDirection.ltr
|
||||
// ..layout(maxWidth: size.width);
|
||||
// canvasWrapper.drawText(
|
||||
// _ticksTextPaint,
|
||||
// Offset(centerX + 5, centerY - tickRadius - _ticksTextPaint.height/2),
|
||||
// );
|
||||
},
|
||||
);
|
||||
}
|
||||
|
@ -302,12 +302,12 @@ class Graphs extends StatelessWidget{
|
|||
width: 310,
|
||||
child: MyRadarChart(
|
||||
RadarChartData(
|
||||
radarShape: RadarShape.polygon,
|
||||
radarShape: RadarShape.circle,
|
||||
tickCount: 4,
|
||||
ticksTextStyle: const TextStyle(color: Colors.transparent, fontSize: 10),
|
||||
radarBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
radarBackgroundColor: Colors.black.withAlpha(170),
|
||||
radarBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
gridBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
tickBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
tickBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
getTitle: (index, angle) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
|
@ -336,7 +336,7 @@ class Graphs extends StatelessWidget{
|
|||
},
|
||||
dataSets: [
|
||||
RadarDataSet(
|
||||
fillColor: Theme.of(context).colorScheme.primary.withAlpha(100),
|
||||
fillColor: Theme.of(context).colorScheme.primary.withAlpha(170),
|
||||
borderColor: Theme.of(context).colorScheme.primary,
|
||||
dataEntries: [
|
||||
RadarEntry(value: apm * apmWeight),
|
||||
|
@ -381,12 +381,12 @@ class Graphs extends StatelessWidget{
|
|||
width: 310,
|
||||
child: MyRadarChart(
|
||||
RadarChartData(
|
||||
radarShape: RadarShape.polygon,
|
||||
radarShape: RadarShape.circle,
|
||||
tickCount: 4,
|
||||
ticksTextStyle: const TextStyle(color: Colors.white24, fontSize: 10),
|
||||
radarBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
radarBackgroundColor: Colors.black.withAlpha(170),
|
||||
radarBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
gridBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
tickBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
tickBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
titleTextStyle: const TextStyle(height: 1.1),
|
||||
radarTouchData: RadarTouchData(),
|
||||
getTitle: (index, angle) {
|
||||
|
@ -405,7 +405,7 @@ class Graphs extends StatelessWidget{
|
|||
},
|
||||
dataSets: [
|
||||
RadarDataSet(
|
||||
fillColor: Theme.of(context).colorScheme.primary.withAlpha(100),
|
||||
fillColor: Theme.of(context).colorScheme.primary.withAlpha(170),
|
||||
borderColor: Theme.of(context).colorScheme.primary,
|
||||
dataEntries: [
|
||||
RadarEntry(value: playstyle.opener),
|
||||
|
@ -438,12 +438,12 @@ class Graphs extends StatelessWidget{
|
|||
width: 310,
|
||||
child: MyRadarChart(
|
||||
RadarChartData(
|
||||
radarShape: RadarShape.polygon,
|
||||
radarShape: RadarShape.circle,
|
||||
tickCount: 4,
|
||||
ticksTextStyle: const TextStyle(color: Colors.white24, fontSize: 10),
|
||||
radarBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
radarBackgroundColor: Colors.black.withAlpha(170),
|
||||
radarBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
gridBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
tickBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
tickBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
titleTextStyle: const TextStyle(height: 1.1),
|
||||
radarTouchData: RadarTouchData(),
|
||||
getTitle: (index, angle) {
|
||||
|
@ -462,7 +462,7 @@ class Graphs extends StatelessWidget{
|
|||
},
|
||||
dataSets: [
|
||||
RadarDataSet(
|
||||
fillColor: Theme.of(context).colorScheme.primary.withAlpha(100),
|
||||
fillColor: Theme.of(context).colorScheme.primary.withAlpha(170),
|
||||
borderColor: Theme.of(context).colorScheme.primary,
|
||||
dataEntries: [
|
||||
RadarEntry(value: attack),
|
||||
|
|
|
@ -2,7 +2,7 @@ name: tetra_stats
|
|||
description: Track your and other player stats in TETR.IO
|
||||
publish_to: 'none'
|
||||
|
||||
version: 1.6.9+35
|
||||
version: 1.6.10+36
|
||||
|
||||
environment:
|
||||
sdk: '>=3.0.0'
|
||||
|
|
Loading…
Reference in New Issue