big and scary refactoring
This commit is contained in:
parent
c03ea44782
commit
e403b0cbee
|
@ -7,7 +7,10 @@
|
||||||
|
|
||||||
# The following line activates a set of recommended lints for Flutter apps,
|
# The following line activates a set of recommended lints for Flutter apps,
|
||||||
# packages, and plugins designed to encourage good coding practices.
|
# packages, and plugins designed to encourage good coding practices.
|
||||||
include: package:flutter_lints/flutter.yaml
|
analyzer:
|
||||||
|
errors:
|
||||||
|
use_build_context_synchronously: ignore
|
||||||
|
in ignoreclude: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
linter:
|
linter:
|
||||||
# The lint rules applied to this project can be customized in the
|
# The lint rules applied to this project can be customized in the
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
class Achievement {
|
||||||
|
late int k;
|
||||||
|
int? o;
|
||||||
|
late int rt;
|
||||||
|
late int vt;
|
||||||
|
late int min;
|
||||||
|
late int deci;
|
||||||
|
late String name;
|
||||||
|
late String object;
|
||||||
|
late String category;
|
||||||
|
late bool hidden;
|
||||||
|
late int art;
|
||||||
|
late bool nolb;
|
||||||
|
late String desc;
|
||||||
|
late String n;
|
||||||
|
String? sId;
|
||||||
|
double? v;
|
||||||
|
late int? a;
|
||||||
|
DateTime? t;
|
||||||
|
int? pos;
|
||||||
|
int? total;
|
||||||
|
int? rank;
|
||||||
|
|
||||||
|
Achievement(
|
||||||
|
{required this.k,
|
||||||
|
this.o,
|
||||||
|
required this.rt,
|
||||||
|
required this.vt,
|
||||||
|
required this.min,
|
||||||
|
required this.deci,
|
||||||
|
required this.name,
|
||||||
|
required this.object,
|
||||||
|
required this.category,
|
||||||
|
required this.hidden,
|
||||||
|
required this.art,
|
||||||
|
required this.nolb,
|
||||||
|
required this.desc,
|
||||||
|
required this.n,
|
||||||
|
this.sId,
|
||||||
|
this.v,
|
||||||
|
required this.a,
|
||||||
|
this.t,
|
||||||
|
this.pos,
|
||||||
|
this.total,
|
||||||
|
this.rank});
|
||||||
|
|
||||||
|
Achievement.fromJson(Map<String, dynamic> json) {
|
||||||
|
k = json['k'];
|
||||||
|
o = json['o'];
|
||||||
|
rt = json['rt'];
|
||||||
|
vt = json['vt'];
|
||||||
|
min = json['min'];
|
||||||
|
deci = json['deci'];
|
||||||
|
name = json['name'];
|
||||||
|
object = json['object'];
|
||||||
|
category = json['category'];
|
||||||
|
hidden = json['hidden'];
|
||||||
|
art = json['art'];
|
||||||
|
nolb = json['nolb'];
|
||||||
|
desc = json['desc'];
|
||||||
|
n = json['n'];
|
||||||
|
sId = json['_id'];
|
||||||
|
v = json['v']?.toDouble();
|
||||||
|
a = json['a'];
|
||||||
|
t = json['t'] != null ? DateTime.parse(json['t']) : null;
|
||||||
|
pos = json['pos'];
|
||||||
|
total = json['total'];
|
||||||
|
rank = json['rank'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['k'] = k;
|
||||||
|
data['o'] = o;
|
||||||
|
data['rt'] = rt;
|
||||||
|
data['vt'] = vt;
|
||||||
|
data['min'] = min;
|
||||||
|
data['deci'] = deci;
|
||||||
|
data['name'] = name;
|
||||||
|
data['object'] = object;
|
||||||
|
data['category'] = category;
|
||||||
|
data['hidden'] = hidden;
|
||||||
|
data['art'] = art;
|
||||||
|
data['nolb'] = nolb;
|
||||||
|
data['desc'] = desc;
|
||||||
|
data['n'] = n;
|
||||||
|
data['_id'] = sId;
|
||||||
|
data['v'] = v;
|
||||||
|
data['a'] = a;
|
||||||
|
data['t'] = t.toString();
|
||||||
|
data['pos'] = pos;
|
||||||
|
data['total'] = total;
|
||||||
|
data['rank'] = rank;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/est_tr.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/nerd_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/playstyle.dart';
|
||||||
|
|
||||||
|
class AggregateStats{
|
||||||
|
late double apm;
|
||||||
|
late double pps;
|
||||||
|
late double vs;
|
||||||
|
late NerdStats nerdStats;
|
||||||
|
late EstTr estTr;
|
||||||
|
late Playstyle playstyle;
|
||||||
|
|
||||||
|
AggregateStats(this.apm, this.pps, this.vs){
|
||||||
|
nerdStats = NerdStats(apm, pps, vs);
|
||||||
|
estTr = EstTr(apm, pps, vs, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);
|
||||||
|
playstyle = Playstyle(apm, pps, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank);
|
||||||
|
}
|
||||||
|
|
||||||
|
AggregateStats.fromJson(Map<String, dynamic> json){
|
||||||
|
apm = json['apm'] != null ? json['apm'].toDouble() : 0.00;
|
||||||
|
pps = json['apm'] != null ? json['pps'].toDouble() : 0.00;
|
||||||
|
vs = json['apm'] != null ? json['vsscore'].toDouble() : 0.00;
|
||||||
|
nerdStats = NerdStats(apm, pps, vs);
|
||||||
|
estTr = EstTr(apm, pps, vs, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);
|
||||||
|
playstyle = Playstyle(apm, pps, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
class Badge {
|
||||||
|
late String badgeId;
|
||||||
|
late String label;
|
||||||
|
DateTime? ts;
|
||||||
|
|
||||||
|
Badge({required this.badgeId, required this.label, this.ts});
|
||||||
|
|
||||||
|
Badge.fromJson(Map<String, dynamic> json) {
|
||||||
|
badgeId = json['id'];
|
||||||
|
label = json['label'];
|
||||||
|
ts = (json['ts'] != null && json['ts'] is String) ? DateTime.parse(json['ts']) : null; // man i love osk
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['id'] = badgeId;
|
||||||
|
data['label'] = label;
|
||||||
|
data['ts'] = ts?.toString();
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return "Badge $label ($badgeId)";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => badgeId.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(covariant Badge other) => badgeId == other.badgeId;
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/beta_league_stats.dart';
|
||||||
|
|
||||||
|
class BetaLeagueLeaderboardEntry{
|
||||||
|
late String id;
|
||||||
|
late String username;
|
||||||
|
late int naturalorder;
|
||||||
|
late int wins;
|
||||||
|
late BetaLeagueStats stats;
|
||||||
|
|
||||||
|
BetaLeagueLeaderboardEntry({required this.id, required this.username, required this.naturalorder, required this.wins, required this.stats});
|
||||||
|
|
||||||
|
BetaLeagueLeaderboardEntry.fromJson(Map<String, dynamic> json){
|
||||||
|
id = json['id'];
|
||||||
|
username = json['username'];
|
||||||
|
naturalorder = json['naturalorder'];
|
||||||
|
wins = json['wins'];
|
||||||
|
stats = BetaLeagueStats.fromJson(json['stats']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/beta_league_leaderboard_entry.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/beta_league_round.dart';
|
||||||
|
|
||||||
|
class BetaLeagueResults{
|
||||||
|
List<BetaLeagueLeaderboardEntry> leaderboard = [];
|
||||||
|
List<List<BetaLeagueRound>> rounds = [];
|
||||||
|
|
||||||
|
BetaLeagueResults({required this.leaderboard, required this.rounds});
|
||||||
|
|
||||||
|
BetaLeagueResults.fromJson(Map<String, dynamic> json){
|
||||||
|
for (var lbEntry in json['leaderboard']) {
|
||||||
|
leaderboard.add(BetaLeagueLeaderboardEntry.fromJson(lbEntry));
|
||||||
|
}
|
||||||
|
for (var roundEntry in json['rounds']){
|
||||||
|
List<BetaLeagueRound> round = [];
|
||||||
|
for (var r in roundEntry) {
|
||||||
|
round.add(BetaLeagueRound.fromJson(r));
|
||||||
|
}
|
||||||
|
rounds.add(round);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/beta_league_stats.dart';
|
||||||
|
|
||||||
|
class BetaLeagueRound{
|
||||||
|
late String id;
|
||||||
|
late String username;
|
||||||
|
late bool active;
|
||||||
|
late int naturalorder;
|
||||||
|
late bool alive;
|
||||||
|
late Duration lifetime;
|
||||||
|
late BetaLeagueStats stats;
|
||||||
|
|
||||||
|
BetaLeagueRound({required this.id, required this.username, required this.active, required this.naturalorder, required this.alive, required this.lifetime, required this.stats});
|
||||||
|
|
||||||
|
BetaLeagueRound.fromJson(Map<String, dynamic> json){
|
||||||
|
id = json['id'];
|
||||||
|
username = json['username'];
|
||||||
|
active = json['active'];
|
||||||
|
naturalorder = json['naturalorder'];
|
||||||
|
alive = json['alive'];
|
||||||
|
lifetime = Duration(milliseconds: json['lifetime']);
|
||||||
|
stats = BetaLeagueStats.fromJson(json['stats']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/est_tr.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/nerd_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/playstyle.dart';
|
||||||
|
|
||||||
|
class BetaLeagueStats{
|
||||||
|
late double apm;
|
||||||
|
late double pps;
|
||||||
|
late double vs;
|
||||||
|
late int garbageSent;
|
||||||
|
late int garbageReceived;
|
||||||
|
late int kills;
|
||||||
|
late double altitude;
|
||||||
|
late int rank;
|
||||||
|
int? targetingFactor;
|
||||||
|
int? targetingRace;
|
||||||
|
late NerdStats nerdStats;
|
||||||
|
late EstTr estTr;
|
||||||
|
late Playstyle playstyle;
|
||||||
|
|
||||||
|
BetaLeagueStats({required this.apm, required this.pps, required this.vs, required this.garbageSent, required this.garbageReceived, required this.kills, required this.altitude, required this.rank}){
|
||||||
|
nerdStats = NerdStats(apm, pps, vs);
|
||||||
|
estTr = EstTr(apm, pps, vs, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);
|
||||||
|
playstyle = Playstyle(apm, pps, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank);
|
||||||
|
}
|
||||||
|
|
||||||
|
BetaLeagueStats.fromJson(Map<String, dynamic> json){
|
||||||
|
apm = json['apm'] != null ? json['apm'].toDouble() : 0.00;
|
||||||
|
pps = json['apm'] != null ? json['pps'].toDouble() : 0.00;
|
||||||
|
vs = json['apm'] != null ? json['vsscore'].toDouble() : 0.00;
|
||||||
|
garbageSent = json['garbagesent'];
|
||||||
|
garbageReceived = json['garbagereceived'];
|
||||||
|
kills = json['kills'];
|
||||||
|
altitude = json['altitude'].toDouble();
|
||||||
|
rank = json['rank'];
|
||||||
|
targetingFactor = json['targetingfactor'];
|
||||||
|
targetingRace = json['targetinggrace'];
|
||||||
|
nerdStats = NerdStats(apm, pps, vs);
|
||||||
|
estTr = EstTr(apm, pps, vs, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);
|
||||||
|
playstyle = Playstyle(apm, pps, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/beta_league_results.dart';
|
||||||
|
|
||||||
|
class BetaRecord{
|
||||||
|
late String id;
|
||||||
|
late String replayID;
|
||||||
|
late String gamemode;
|
||||||
|
late DateTime ts;
|
||||||
|
late String enemyUsername;
|
||||||
|
late String enemyID;
|
||||||
|
late BetaLeagueResults results;
|
||||||
|
|
||||||
|
BetaRecord({required this.id, required this.replayID, required this.gamemode, required this.ts, required this.enemyUsername, required this.enemyID, required this.results});
|
||||||
|
|
||||||
|
BetaRecord.fromJson(Map<String, dynamic> json){
|
||||||
|
id = json['_id'];
|
||||||
|
replayID = json['replayid'];
|
||||||
|
gamemode = json['gamemode'];
|
||||||
|
ts = DateTime.parse(json['ts']);
|
||||||
|
enemyUsername = json['otherusers'][0]['username'];
|
||||||
|
enemyID = json['otherusers'][0]['id'];
|
||||||
|
results = BetaLeagueResults.fromJson(json['results']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
class Clears {
|
||||||
|
late int singles;
|
||||||
|
late int doubles;
|
||||||
|
late int triples;
|
||||||
|
late int quads;
|
||||||
|
late int pentas;
|
||||||
|
late int allClears;
|
||||||
|
late int tSpinZeros;
|
||||||
|
late int tSpinSingles;
|
||||||
|
late int tSpinDoubles;
|
||||||
|
late int tSpinTriples;
|
||||||
|
late int tSpinQuads;
|
||||||
|
late int tSpinPentas;
|
||||||
|
late int tSpinMiniZeros;
|
||||||
|
late int tSpinMiniSingles;
|
||||||
|
late int tSpinMiniDoubles;
|
||||||
|
late int tSpinMiniTriples;
|
||||||
|
late int tSpinMiniQuads;
|
||||||
|
|
||||||
|
Clears(
|
||||||
|
{required this.singles,
|
||||||
|
required this.doubles,
|
||||||
|
required this.triples,
|
||||||
|
required this.quads,
|
||||||
|
required this.pentas,
|
||||||
|
required this.allClears,
|
||||||
|
required this.tSpinZeros,
|
||||||
|
required this.tSpinSingles,
|
||||||
|
required this.tSpinDoubles,
|
||||||
|
required this.tSpinTriples,
|
||||||
|
required this.tSpinPentas,
|
||||||
|
required this.tSpinQuads,
|
||||||
|
required this.tSpinMiniZeros,
|
||||||
|
required this.tSpinMiniSingles,
|
||||||
|
required this.tSpinMiniDoubles,
|
||||||
|
required this.tSpinMiniTriples,
|
||||||
|
required this.tSpinMiniQuads});
|
||||||
|
|
||||||
|
Clears.fromJson(Map<String, dynamic> json) {
|
||||||
|
singles = json['singles'];
|
||||||
|
doubles = json['doubles'];
|
||||||
|
triples = json['triples'];
|
||||||
|
quads = json['quads'];
|
||||||
|
pentas = json['pentas']??0;
|
||||||
|
tSpinZeros = json['realtspins'];
|
||||||
|
tSpinMiniZeros = json['minitspins'];
|
||||||
|
tSpinMiniSingles = json['minitspinsingles'];
|
||||||
|
tSpinSingles = json['tspinsingles'];
|
||||||
|
tSpinMiniDoubles = json['minitspindoubles'];
|
||||||
|
tSpinDoubles = json['tspindoubles'];
|
||||||
|
tSpinMiniTriples = json['minitspintriples']??0;
|
||||||
|
tSpinTriples = json['tspintriples'];
|
||||||
|
tSpinMiniQuads = json['minitspinquads']??0;
|
||||||
|
tSpinQuads = json['tspinquads'];
|
||||||
|
tSpinPentas = json['tspinpentas']??0;
|
||||||
|
allClears = json['allclear'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Clears operator + (Clears other){
|
||||||
|
return Clears(
|
||||||
|
singles: singles + other.singles,
|
||||||
|
doubles: doubles + other.doubles,
|
||||||
|
triples: triples + other.triples,
|
||||||
|
quads: quads + other.quads,
|
||||||
|
pentas: pentas + other.pentas,
|
||||||
|
allClears: allClears + other.allClears,
|
||||||
|
tSpinZeros: tSpinZeros + other.tSpinZeros,
|
||||||
|
tSpinSingles: tSpinSingles + other.tSpinSingles,
|
||||||
|
tSpinDoubles: tSpinDoubles + other.tSpinDoubles,
|
||||||
|
tSpinTriples: tSpinTriples + other.tSpinTriples,
|
||||||
|
tSpinPentas: tSpinPentas + other.tSpinPentas,
|
||||||
|
tSpinQuads: tSpinQuads + other.tSpinQuads,
|
||||||
|
tSpinMiniZeros: tSpinMiniZeros + other.tSpinMiniZeros,
|
||||||
|
tSpinMiniSingles: tSpinMiniSingles + other.tSpinMiniSingles,
|
||||||
|
tSpinMiniDoubles: tSpinMiniDoubles + other.tSpinMiniDoubles,
|
||||||
|
tSpinMiniTriples: tSpinMiniTriples + other.tSpinMiniTriples,
|
||||||
|
tSpinMiniQuads: tSpinMiniQuads + other.tSpinMiniQuads
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['singles'] = singles;
|
||||||
|
data['doubles'] = doubles;
|
||||||
|
data['triples'] = triples;
|
||||||
|
data['quads'] = quads;
|
||||||
|
data['pentas'] = pentas;
|
||||||
|
data['realtspins'] = tSpinZeros;
|
||||||
|
data['minitspins'] = tSpinMiniZeros;
|
||||||
|
data['minitspinsingles'] = tSpinMiniSingles;
|
||||||
|
data['tspinsingles'] = tSpinSingles;
|
||||||
|
data['minitspindoubles'] = tSpinMiniDoubles;
|
||||||
|
data['tspindoubles'] = tSpinDoubles;
|
||||||
|
data['tspintriples'] = tSpinTriples;
|
||||||
|
data['tspinquads'] = tSpinQuads;
|
||||||
|
data['tspinpentas'] = tSpinPentas;
|
||||||
|
data['allclear'] = allClears;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
class Connections {
|
||||||
|
Discord? discord;
|
||||||
|
|
||||||
|
Connections({this.discord});
|
||||||
|
|
||||||
|
Connections.fromJson(Map<String, dynamic> json) {
|
||||||
|
discord = json['discord'] != null ? Discord.fromJson(json['discord']) : null;
|
||||||
|
}
|
||||||
|
@override
|
||||||
|
bool operator ==(covariant Connections other) => discord == other.discord;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
if (discord != null) {
|
||||||
|
data['discord'] = discord!.toJson();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class Discord {
|
||||||
|
late String id;
|
||||||
|
late String username;
|
||||||
|
|
||||||
|
Discord({required this.id, required this.username});
|
||||||
|
|
||||||
|
Discord.fromJson(Map<String, dynamic> json) {
|
||||||
|
id = json['id'];
|
||||||
|
username = json['username'];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(covariant Discord other) => id == other.id;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['id'] = id;
|
||||||
|
data['username'] = username;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
class CutoffTetrio {
|
||||||
|
late int pos;
|
||||||
|
late double percentile;
|
||||||
|
late double tr;
|
||||||
|
late double targetTr;
|
||||||
|
late double apm;
|
||||||
|
late double pps;
|
||||||
|
late double vs;
|
||||||
|
late int count;
|
||||||
|
late double countPercentile;
|
||||||
|
|
||||||
|
CutoffTetrio.fromJson(Map<String, dynamic> json, int total){
|
||||||
|
pos = json['pos'];
|
||||||
|
percentile = json['percentile'].toDouble();
|
||||||
|
tr = json['tr'].toDouble();
|
||||||
|
targetTr = json['targettr'].toDouble();
|
||||||
|
apm = json['apm'].toDouble();
|
||||||
|
pps = json['pps'].toDouble();
|
||||||
|
vs = json['vs'].toDouble();
|
||||||
|
count = json['count'];
|
||||||
|
countPercentile = count / total;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CutoffsTetrio {
|
||||||
|
late String id;
|
||||||
|
late DateTime timestamp;
|
||||||
|
late int total;
|
||||||
|
Map<String, CutoffTetrio> data = {};
|
||||||
|
|
||||||
|
CutoffsTetrio.fromJson(Map<String, dynamic> json){
|
||||||
|
id = json['s'];
|
||||||
|
timestamp = DateTime.parse(json['t']);
|
||||||
|
total = json['data']['total'];
|
||||||
|
json['data'].remove("total");
|
||||||
|
for (String rank in json['data'].keys){
|
||||||
|
data[rank] = CutoffTetrio.fromJson(json['data'][rank], total);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
class Distinguishment {
|
||||||
|
late String type;
|
||||||
|
String? detail;
|
||||||
|
String? header;
|
||||||
|
String? footer;
|
||||||
|
|
||||||
|
Distinguishment({required this.type, this.detail, this.header, this.footer});
|
||||||
|
|
||||||
|
Distinguishment.fromJson(Map<String, dynamic> json) {
|
||||||
|
type = json['type'];
|
||||||
|
detail = json['detail'];
|
||||||
|
header = json['header'];
|
||||||
|
footer = json['footer'];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(covariant Distinguishment other) => type == other.type && detail == other.detail && header == other.header && footer == other.footer;
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['type'] = type;
|
||||||
|
data['detail'] = detail;
|
||||||
|
data['header'] = header;
|
||||||
|
data['footer'] = footer;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,97 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/est_tr.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/handling.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/nerd_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/playstyle.dart';
|
||||||
|
|
||||||
|
class EndContextMulti {
|
||||||
|
late String userId;
|
||||||
|
late String username;
|
||||||
|
late int naturalOrder;
|
||||||
|
late int inputs;
|
||||||
|
late int piecesPlaced;
|
||||||
|
late Handling handling;
|
||||||
|
late int points;
|
||||||
|
late int wins;
|
||||||
|
late double secondary;
|
||||||
|
late List secondaryTracking;
|
||||||
|
late double tertiary;
|
||||||
|
late List tertiaryTracking;
|
||||||
|
late double extra;
|
||||||
|
late List extraTracking;
|
||||||
|
late bool success;
|
||||||
|
late NerdStats nerdStats;
|
||||||
|
late List<NerdStats> nerdStatsTracking;
|
||||||
|
late EstTr estTr;
|
||||||
|
late List<EstTr> estTrTracking;
|
||||||
|
late Playstyle playstyle;
|
||||||
|
late List<Playstyle> playstyleTracking;
|
||||||
|
|
||||||
|
EndContextMulti(
|
||||||
|
{required this.userId,
|
||||||
|
required this.username,
|
||||||
|
required this.naturalOrder,
|
||||||
|
required this.inputs,
|
||||||
|
required this.piecesPlaced,
|
||||||
|
required this.handling,
|
||||||
|
required this.points,
|
||||||
|
required this.wins,
|
||||||
|
required this.secondary,
|
||||||
|
required this.secondaryTracking,
|
||||||
|
required this.tertiary,
|
||||||
|
required this.tertiaryTracking,
|
||||||
|
required this.extra,
|
||||||
|
required this.extraTracking,
|
||||||
|
required this.success}){
|
||||||
|
nerdStats = NerdStats(secondary, tertiary, extra);
|
||||||
|
nerdStatsTracking = [for (int i = 0; i < secondaryTracking.length; i++) NerdStats(secondaryTracking[i], tertiaryTracking[i], extraTracking[i])];
|
||||||
|
estTr = EstTr(secondary, tertiary, extra, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);
|
||||||
|
estTrTracking = [for (int i = 0; i < secondaryTracking.length; i++) EstTr(secondaryTracking[i], tertiaryTracking[i], extraTracking[i], nerdStatsTracking[i].app, nerdStatsTracking[i].dss, nerdStatsTracking[i].dsp, nerdStatsTracking[i].gbe)];
|
||||||
|
playstyle = Playstyle(secondary, tertiary, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank);
|
||||||
|
playstyleTracking = [for (int i = 0; i < secondaryTracking.length; i++) Playstyle(secondaryTracking[i], tertiaryTracking[i], nerdStatsTracking[i].app, nerdStatsTracking[i].vsapm, nerdStatsTracking[i].dsp, nerdStatsTracking[i].gbe, estTrTracking[i].srarea, estTrTracking[i].statrank)];
|
||||||
|
}
|
||||||
|
|
||||||
|
EndContextMulti.fromJson(Map<String, dynamic> json) {
|
||||||
|
userId = json['id'] ?? json['user']['_id'];
|
||||||
|
username = json['username'] ?? json['user']['username'];
|
||||||
|
handling = json['handling'] != null ? Handling.fromJson(json['handling']) : Handling(arr: -1, das: -1, sdf: -1, dcd: 0, cancel: true, safeLock: true);
|
||||||
|
success = json['success'];
|
||||||
|
inputs = json['inputs'] ?? -1;
|
||||||
|
piecesPlaced = json['piecesplaced'] ?? -1;
|
||||||
|
naturalOrder = json['naturalorder'];
|
||||||
|
wins = json['wins'];
|
||||||
|
points = json['points']['primary'];
|
||||||
|
secondary = json['points']['secondary'].toDouble();
|
||||||
|
tertiary = json['points']['tertiary'].toDouble();
|
||||||
|
secondaryTracking = json['points']['secondaryAvgTracking'] != null ? json['points']['secondaryAvgTracking'].map((e) => e.toDouble()).toList() : [];
|
||||||
|
tertiaryTracking = json['points']['tertiaryAvgTracking'] != null ? json['points']['tertiaryAvgTracking'].map((e) => e.toDouble()).toList() : [];
|
||||||
|
extra = json['points']['extra']['vs'].toDouble();
|
||||||
|
extraTracking = json['points']['extraAvgTracking'] != null ? json['points']['extraAvgTracking']['aggregatestats___vsscore'].map((e) => e.toDouble()).toList() : [];
|
||||||
|
nerdStats = NerdStats(secondary, tertiary, extra);
|
||||||
|
nerdStatsTracking = [for (int i = 0; i < secondaryTracking.length; i++) NerdStats(secondaryTracking[i], tertiaryTracking[i], extraTracking[i])];
|
||||||
|
estTr = EstTr(secondary, tertiary, extra, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);
|
||||||
|
estTrTracking = [for (int i = 0; i < secondaryTracking.length; i++) EstTr(secondaryTracking[i], tertiaryTracking[i], extraTracking[i], nerdStatsTracking[i].app, nerdStatsTracking[i].dss, nerdStatsTracking[i].dsp, nerdStatsTracking[i].gbe)];
|
||||||
|
playstyle = Playstyle(secondary, tertiary, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank);
|
||||||
|
playstyleTracking = [for (int i = 0; i < secondaryTracking.length; i++) Playstyle(secondaryTracking[i], tertiaryTracking[i], nerdStatsTracking[i].app, nerdStatsTracking[i].vsapm, nerdStatsTracking[i].dsp, nerdStatsTracking[i].gbe, estTrTracking[i].srarea, estTrTracking[i].statrank)];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator == (covariant EndContextMulti other){
|
||||||
|
if (userId != other.userId) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['user'] = {'_id': userId, 'username': username};
|
||||||
|
data['handling'] = handling.toJson();
|
||||||
|
data['success'] = success;
|
||||||
|
data['inputs'] = inputs;
|
||||||
|
data['piecesplaced'] = piecesPlaced;
|
||||||
|
data['naturalorder'] = naturalOrder;
|
||||||
|
data['wins'] = wins;
|
||||||
|
data['points'] = {'primary': points, 'secondary': secondary, 'tertiary':tertiary, 'extra': {'vs': extra}, 'secondaryAvgTracking': secondaryTracking, 'tertiaryAvgTracking': tertiaryTracking, 'extraAvgTracking': {'aggregatestats___vsscore': extraTracking}};
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
class EstTr {
|
||||||
|
late double esttr;
|
||||||
|
late double srarea;
|
||||||
|
late double statrank;
|
||||||
|
late double estglicko;
|
||||||
|
|
||||||
|
EstTr(double apm, double pps, double vs, double app, double dss, double dsp, double gbe) {
|
||||||
|
srarea = (apm * 0) + (pps * 135) + (vs * 0) + (app * 290) + (dss * 0) + (dsp * 700) + (gbe * 0);
|
||||||
|
statrank = 11.2 * atan((srarea - 93) / 130) + 1;
|
||||||
|
if (statrank <= 0) statrank = 0.001;
|
||||||
|
//estglicko = (4.0867 * srarea + 186.68);
|
||||||
|
double ntemp = pps*(150+(((vs/apm) - 1.66)*35))+app*290+dsp*700;
|
||||||
|
estglicko = 0.000013*pow(ntemp, 3) - 0.0196 *pow(ntemp, 2) + (12.645*ntemp)-1005.4;
|
||||||
|
esttr = 25000 /
|
||||||
|
(
|
||||||
|
1 + pow(10, (
|
||||||
|
(
|
||||||
|
(
|
||||||
|
1500-estglicko
|
||||||
|
)*pi
|
||||||
|
)/sqrt(
|
||||||
|
(
|
||||||
|
(
|
||||||
|
3*pow(ln10, 2)
|
||||||
|
)*pow(60, 2)
|
||||||
|
)+(
|
||||||
|
2500*(
|
||||||
|
(64*pow(pi,2))+(147*pow(ln10, 2))
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
class Finesse {
|
||||||
|
late int combo;
|
||||||
|
late int faults;
|
||||||
|
late int perfectPieces;
|
||||||
|
|
||||||
|
Finesse({required this.combo, required this.faults, required this.perfectPieces});
|
||||||
|
|
||||||
|
Finesse.fromJson(Map<String, dynamic> json) {
|
||||||
|
combo = json['combo'];
|
||||||
|
faults = json['faults'];
|
||||||
|
perfectPieces = json['perfectpieces'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Finesse operator + (Finesse other){
|
||||||
|
return Finesse(combo: max(combo, other.combo), faults: faults + other.faults, perfectPieces: perfectPieces + other.perfectPieces);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['combo'] = combo;
|
||||||
|
data['faults'] = faults;
|
||||||
|
data['perfectpieces'] = perfectPieces;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
class Handling {
|
||||||
|
late num arr;
|
||||||
|
late num das;
|
||||||
|
late num sdf;
|
||||||
|
late num dcd;
|
||||||
|
late bool cancel;
|
||||||
|
late bool safeLock;
|
||||||
|
|
||||||
|
Handling({required this.arr, required this.das, required this.sdf, required this.dcd, required this.cancel, required this.safeLock});
|
||||||
|
|
||||||
|
Handling.fromJson(Map<String, dynamic> json) {
|
||||||
|
arr = json['arr'];
|
||||||
|
das = json['das'];
|
||||||
|
dcd = json['dcd'];
|
||||||
|
sdf = json['sdf'];
|
||||||
|
safeLock = json['safelock'];
|
||||||
|
cancel = json['cancel'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['arr'] = arr.toDouble();
|
||||||
|
data['das'] = das.toDouble();
|
||||||
|
data['dcd'] = dcd.toDouble();
|
||||||
|
data['sdf'] = sdf.toDouble();
|
||||||
|
data['safelock'] = safeLock;
|
||||||
|
data['cancel'] = cancel;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
class LeaderboardPosition{
|
||||||
|
int position;
|
||||||
|
double percentage;
|
||||||
|
|
||||||
|
LeaderboardPosition(this.position, this.percentage);
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'dart:math';
|
||||||
|
import 'package:vector_math/vector_math.dart';
|
||||||
|
|
||||||
|
class NerdStats {
|
||||||
|
late double app;
|
||||||
|
late double vsapm;
|
||||||
|
late double dss;
|
||||||
|
late double dsp;
|
||||||
|
late double appdsp;
|
||||||
|
late double cheese;
|
||||||
|
late double gbe;
|
||||||
|
late double nyaapp;
|
||||||
|
late double area;
|
||||||
|
|
||||||
|
NerdStats(double apm, double pps, double vs) {
|
||||||
|
app = apm / (pps * 60);
|
||||||
|
vsapm = vs / apm;
|
||||||
|
dss = (vs / 100) - (apm / 60);
|
||||||
|
dsp = ((vs / 100) - (apm / 60)) / pps;
|
||||||
|
appdsp = app + dsp;
|
||||||
|
cheese = (dsp * 150) + ((vsapm - 2) * 50) + (0.6 - app) * 125;
|
||||||
|
gbe = app * dsp * 2;
|
||||||
|
nyaapp = app - 5 * tan(radians((cheese / -30) + 1));
|
||||||
|
area = apm * 1 + pps * 45 + vs * 0.444 + app * 185 + dss * 175 + dsp * 450 + gbe * 315;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/news_entry.dart';
|
||||||
|
|
||||||
|
class News{
|
||||||
|
late String id;
|
||||||
|
late List<NewsEntry> news;
|
||||||
|
|
||||||
|
News(this.id, this.news);
|
||||||
|
|
||||||
|
News.fromJson(Map<String, dynamic> json, String? userID){
|
||||||
|
id = userID != null ? "user_$userID" : json['news'].first['stream'];
|
||||||
|
news = [for (var entry in json['news']) NewsEntry.fromJson(entry)];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
class NewsEntry {
|
||||||
|
late String type;
|
||||||
|
late Map<String, dynamic> data;
|
||||||
|
late DateTime timestamp;
|
||||||
|
|
||||||
|
NewsEntry({required this.type, required this.data, required this.timestamp});
|
||||||
|
|
||||||
|
NewsEntry.fromJson(Map<String, dynamic> json){
|
||||||
|
type = json["type"];
|
||||||
|
data = json["data"];
|
||||||
|
timestamp = DateTime.parse(json['ts']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/leaderboard_position.dart';
|
||||||
|
|
||||||
|
class PlayerLeaderboardPosition{
|
||||||
|
late LeaderboardPosition? apm;
|
||||||
|
late LeaderboardPosition? pps;
|
||||||
|
late LeaderboardPosition? vs;
|
||||||
|
late LeaderboardPosition? gamesPlayed;
|
||||||
|
late LeaderboardPosition? gamesWon;
|
||||||
|
late LeaderboardPosition? winrate;
|
||||||
|
late LeaderboardPosition? app;
|
||||||
|
late LeaderboardPosition? vsapm;
|
||||||
|
late LeaderboardPosition? dss;
|
||||||
|
late LeaderboardPosition? dsp;
|
||||||
|
late LeaderboardPosition? appdsp;
|
||||||
|
late LeaderboardPosition? cheese;
|
||||||
|
late LeaderboardPosition? gbe;
|
||||||
|
late LeaderboardPosition? nyaapp;
|
||||||
|
late LeaderboardPosition? area;
|
||||||
|
late LeaderboardPosition? estTr;
|
||||||
|
late LeaderboardPosition? accOfEst;
|
||||||
|
|
||||||
|
PlayerLeaderboardPosition({
|
||||||
|
required this.apm,
|
||||||
|
required this.pps,
|
||||||
|
required this.vs,
|
||||||
|
required this.gamesPlayed,
|
||||||
|
required this.gamesWon,
|
||||||
|
required this.winrate,
|
||||||
|
required this.app,
|
||||||
|
required this.vsapm,
|
||||||
|
required this.dss,
|
||||||
|
required this.dsp,
|
||||||
|
required this.appdsp,
|
||||||
|
required this.cheese,
|
||||||
|
required this.gbe,
|
||||||
|
required this.nyaapp,
|
||||||
|
required this.area,
|
||||||
|
required this.estTr,
|
||||||
|
required this.accOfEst
|
||||||
|
});
|
||||||
|
|
||||||
|
PlayerLeaderboardPosition.fromSearchResults(List<LeaderboardPosition?> results){
|
||||||
|
apm = results[0];
|
||||||
|
pps = results[1];
|
||||||
|
vs = results[2];
|
||||||
|
gamesPlayed = results[3];
|
||||||
|
gamesWon = results[4];
|
||||||
|
winrate = results[5];
|
||||||
|
app = results[6];
|
||||||
|
vsapm = results[7];
|
||||||
|
dss = results[8];
|
||||||
|
dsp = results[9];
|
||||||
|
appdsp = results[10];
|
||||||
|
cheese = results[11];
|
||||||
|
gbe = results[12];
|
||||||
|
nyaapp = results[13];
|
||||||
|
area = results[14];
|
||||||
|
estTr = results[15];
|
||||||
|
accOfEst = results[16];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
class Playstyle {
|
||||||
|
late double opener;
|
||||||
|
late double plonk;
|
||||||
|
late double stride;
|
||||||
|
late double infds;
|
||||||
|
|
||||||
|
Playstyle(double apm, double pps, double app, double vsapm, double dsp, double gbe, double srarea, double statrank) {
|
||||||
|
double nmapm = ((apm / srarea) / ((0.069 * pow(1.0017, (pow(statrank, 5) / 4700))) + statrank / 360)) - 1;
|
||||||
|
double nmpps = ((pps / srarea) / (0.0084264 * pow(2.14, (-2 * (statrank / 2.7 + 1.03))) - statrank / 5750 + 0.0067)) - 1;
|
||||||
|
//double nmvs = ((vs / srarea) / (0.1333 * pow(1.0021, ((pow(statrank, 7) * (statrank / 16.5)) / 1400000)) + statrank / 133)) - 1;
|
||||||
|
double nmapp = (app / (0.1368803292 * pow(1.0024, (pow(statrank, 5) / 2800)) + statrank / 54)) - 1;
|
||||||
|
//double nmdss = (dss / (0.01436466667 * pow(4.1, ((statrank - 9.6) / 2.9)) + statrank / 140 + 0.01)) - 1;
|
||||||
|
double nmdsp = (dsp / (0.02136327583 * pow(14, ((statrank - 14.75) / 3.9)) + statrank / 152 + 0.022)) - 1;
|
||||||
|
double nmgbe = (gbe / (statrank / 350 + 0.005948424455 * pow(3.8, ((statrank - 6.1) / 4)) + 0.006)) - 1;
|
||||||
|
double nmvsapm = (vsapm / (-pow(((statrank - 16) / 36), 2) + 2.133)) - 1;
|
||||||
|
opener = ((nmapm + nmpps * 0.75 + nmvsapm * -10 + nmapp * 0.75 + nmdsp * -0.25) / 3.5) + 0.5;
|
||||||
|
plonk = ((nmgbe + nmapp + nmdsp * 0.75 + nmpps * -1) / 2.73) + 0.5;
|
||||||
|
stride = ((nmapm * -0.25 + nmpps + nmapp * -2 + nmdsp * -0.5) * 0.79) + 0.5;
|
||||||
|
infds = ((nmdsp + nmapp * -0.75 + nmapm * 0.5 + nmvsapm * 1.5 + nmpps * 0.5) * 0.9) + 0.5;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
class RecordExtras{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
class ZenithExtras extends RecordExtras{
|
||||||
|
List<String> mods = [];
|
||||||
|
|
||||||
|
ZenithExtras.fromJson(Map<String, dynamic> json){
|
||||||
|
for (var mod in json["mods"]) {
|
||||||
|
mods.add(mod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/aggregate_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/record_extras.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/results_stats.dart';
|
||||||
|
|
||||||
|
class RecordSingle {
|
||||||
|
late String? userId;
|
||||||
|
late String replayId;
|
||||||
|
late String ownId;
|
||||||
|
late String gamemode;
|
||||||
|
late DateTime timestamp;
|
||||||
|
late ResultsStats stats;
|
||||||
|
late int rank;
|
||||||
|
late int countryRank;
|
||||||
|
late AggregateStats aggregateStats;
|
||||||
|
late RecordExtras extras;
|
||||||
|
|
||||||
|
RecordSingle({required this.userId, required this.replayId, required this.ownId, required this.timestamp, required this.stats, required this.rank, required this.countryRank, required this.aggregateStats});
|
||||||
|
|
||||||
|
RecordSingle.fromJson(Map<String, dynamic> json, int ran, int cran) {
|
||||||
|
ownId = json['_id'];
|
||||||
|
gamemode = json['gamemode'];
|
||||||
|
stats = ResultsStats.fromJson(json['results']['stats']);
|
||||||
|
replayId = json['replayid'];
|
||||||
|
timestamp = DateTime.parse(json['ts']);
|
||||||
|
if (json['user'] != null) userId = json['user']['id'];
|
||||||
|
rank = ran;
|
||||||
|
countryRank = cran;
|
||||||
|
aggregateStats = AggregateStats.fromJson(json['results']['aggregatestats']);
|
||||||
|
var ex = json['extras'] as Map<String, dynamic>;
|
||||||
|
switch (ex.keys.firstOrNull){
|
||||||
|
case "zenith":
|
||||||
|
extras = ZenithExtras.fromJson(json['extras']['zenith']);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['_id'] = ownId;
|
||||||
|
data['results']['stats'] = stats.toJson();
|
||||||
|
data['ismulti'] = false;
|
||||||
|
data['replayid'] = replayId;
|
||||||
|
data['ts'] = timestamp;
|
||||||
|
data['user_id'] = userId;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,82 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/clears.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/finesse.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/zenith_results.dart';
|
||||||
|
|
||||||
|
class ResultsStats {
|
||||||
|
late int topBtB;
|
||||||
|
late int topCombo;
|
||||||
|
late int holds;
|
||||||
|
late int inputs;
|
||||||
|
late int level;
|
||||||
|
late int piecesPlaced;
|
||||||
|
late int lines;
|
||||||
|
late int score;
|
||||||
|
double? seed;
|
||||||
|
late Duration finalTime;
|
||||||
|
late int tSpins;
|
||||||
|
late Clears clears;
|
||||||
|
late int kills;
|
||||||
|
Finesse? finesse;
|
||||||
|
ZenithResults? zenith;
|
||||||
|
|
||||||
|
double get pps => piecesPlaced / (finalTime.inMicroseconds / 1000000);
|
||||||
|
double get kpp => inputs / piecesPlaced;
|
||||||
|
double get spp => score / piecesPlaced;
|
||||||
|
double get kps => inputs / (finalTime.inMicroseconds / 1000000);
|
||||||
|
double get finessePercentage => finesse != null ? finesse!.perfectPieces / piecesPlaced : 0;
|
||||||
|
double get cps => zenith != null ? zenith!.avgrankpts / (finalTime.inMilliseconds / 1000 * 60) : 0;
|
||||||
|
|
||||||
|
ResultsStats(
|
||||||
|
{
|
||||||
|
required this.topBtB,
|
||||||
|
required this.topCombo,
|
||||||
|
required this.holds,
|
||||||
|
required this.inputs,
|
||||||
|
required this.level,
|
||||||
|
required this.piecesPlaced,
|
||||||
|
required this.lines,
|
||||||
|
required this.score,
|
||||||
|
required this.seed,
|
||||||
|
required this.finalTime,
|
||||||
|
required this.tSpins,
|
||||||
|
required this.clears,
|
||||||
|
required this.finesse});
|
||||||
|
|
||||||
|
ResultsStats.fromJson(Map<String, dynamic> json) {
|
||||||
|
seed = json['seed']?.toDouble();
|
||||||
|
lines = json['lines'];
|
||||||
|
inputs = json['inputs'];
|
||||||
|
holds = json['holds'] ?? 0;
|
||||||
|
finalTime = Duration(microseconds: (json['finaltime'].toDouble() * 1000).floor());
|
||||||
|
score = json['score'];
|
||||||
|
level = json['level'];
|
||||||
|
topCombo = json['topcombo'];
|
||||||
|
topBtB = json['topbtb'];
|
||||||
|
tSpins = json['tspins'];
|
||||||
|
piecesPlaced = json['piecesplaced'];
|
||||||
|
clears = Clears.fromJson(json['clears']);
|
||||||
|
kills = json['kills'];
|
||||||
|
if (json.containsKey("finesse")) finesse = Finesse.fromJson(json['finesse']);
|
||||||
|
if (json.containsKey("zenith")) zenith = ZenithResults.fromJson(json['zenith']);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['seed'] = seed;
|
||||||
|
data['lines'] = lines;
|
||||||
|
data['inputs'] = inputs;
|
||||||
|
data['holds'] = holds;
|
||||||
|
data['score'] = score;
|
||||||
|
data['level'] = level;
|
||||||
|
data['topcombo'] = topCombo;
|
||||||
|
data['topbtb'] = topBtB;
|
||||||
|
data['tspins'] = tSpins;
|
||||||
|
data['piecesplaced'] = piecesPlaced;
|
||||||
|
data['clears'] = clears.toJson();
|
||||||
|
if (finesse != null) data['finesse'] = finesse!.toJson();
|
||||||
|
data['finalTime'] = finalTime;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/record_single.dart';
|
||||||
|
|
||||||
|
class SingleplayerStream{
|
||||||
|
late String userId;
|
||||||
|
late String type;
|
||||||
|
late List<RecordSingle> records;
|
||||||
|
|
||||||
|
SingleplayerStream({required this.userId, required this.records, required this.type});
|
||||||
|
|
||||||
|
SingleplayerStream.fromJson(List<dynamic> json, String userID, String tp) {
|
||||||
|
userId = userID;
|
||||||
|
type = tp;
|
||||||
|
records = [];
|
||||||
|
for (var value in json) {records.add(RecordSingle.fromJson(value, -1, -1));}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/achievement.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/record_single.dart';
|
||||||
|
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{
|
||||||
|
late String id;
|
||||||
|
RecordSingle? sprint;
|
||||||
|
RecordSingle? blitz;
|
||||||
|
RecordSingle? zenith;
|
||||||
|
RecordSingle? zenithCareerBest; // leaderboard best, not overall
|
||||||
|
RecordSingle? zenithEx;
|
||||||
|
RecordSingle? zenithExCareerBest; // leaderboard best, not overall
|
||||||
|
late List<Achievement> achievements;
|
||||||
|
late TetraLeague league;
|
||||||
|
Map<int, TetraLeague> pastLeague = {};
|
||||||
|
late TetrioZen zen;
|
||||||
|
|
||||||
|
Summaries(this.id, this.league, this.zen);
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
zen = TetrioZen.fromJson(json['zen']);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,139 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/est_tr.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/nerd_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/playstyle.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_player_from_leaderboard.dart';
|
||||||
|
|
||||||
|
class TetraLeague {
|
||||||
|
late String id;
|
||||||
|
late DateTime timestamp;
|
||||||
|
late int gamesPlayed;
|
||||||
|
late int gamesWon;
|
||||||
|
late String bestRank;
|
||||||
|
late bool decaying;
|
||||||
|
late double tr;
|
||||||
|
late double gxe;
|
||||||
|
late String rank;
|
||||||
|
double? glicko;
|
||||||
|
double? rd;
|
||||||
|
late String percentileRank;
|
||||||
|
late double percentile;
|
||||||
|
late int standing;
|
||||||
|
late int standingLocal;
|
||||||
|
String? nextRank;
|
||||||
|
late int nextAt;
|
||||||
|
String? prevRank;
|
||||||
|
late int prevAt;
|
||||||
|
double? apm;
|
||||||
|
double? pps;
|
||||||
|
double? vs;
|
||||||
|
NerdStats? nerdStats;
|
||||||
|
EstTr? estTr;
|
||||||
|
Playstyle? playstyle;
|
||||||
|
late int season;
|
||||||
|
|
||||||
|
TetraLeague(
|
||||||
|
{required this.id,
|
||||||
|
required this.timestamp,
|
||||||
|
required this.gamesPlayed,
|
||||||
|
required this.gamesWon,
|
||||||
|
required this.bestRank,
|
||||||
|
required this.decaying,
|
||||||
|
required this.tr,
|
||||||
|
required this.gxe,
|
||||||
|
required this.rank,
|
||||||
|
this.glicko,
|
||||||
|
this.rd,
|
||||||
|
required this.percentileRank,
|
||||||
|
required this.percentile,
|
||||||
|
required this.standing,
|
||||||
|
required this.standingLocal,
|
||||||
|
this.nextRank,
|
||||||
|
required this.nextAt,
|
||||||
|
this.prevRank,
|
||||||
|
required this.prevAt,
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
double get winrate => gamesWon / gamesPlayed;
|
||||||
|
double get s1tr => gxe * 250;
|
||||||
|
|
||||||
|
TetraLeague.fromJson(Map<String, dynamic> json, ts, int s, String i) {
|
||||||
|
timestamp = ts;
|
||||||
|
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;
|
||||||
|
glicko = json['glicko']?.toDouble();
|
||||||
|
rd = json['rd'] != null ? json['rd']!.toDouble() : noTrRd;
|
||||||
|
gxe = json['gxe'] != null ? json['gxe'].toDouble() : -1;
|
||||||
|
rank = json['rank'] != null ? json['rank']!.toString() : 'z';
|
||||||
|
bestRank = json['bestrank'] != null ? json['bestrank']!.toString() : 'z';
|
||||||
|
apm = json['apm']?.toDouble();
|
||||||
|
pps = json['pps']?.toDouble();
|
||||||
|
vs = json['vs']?.toDouble();
|
||||||
|
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];
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(covariant TetraLeague other) => gamesPlayed == other.gamesPlayed && rd == other.rd;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
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;
|
||||||
|
if (glicko != null) data['glicko'] = glicko;
|
||||||
|
if (gxe != -1) data['gxe'] = gxe;
|
||||||
|
if (rd != null && rd != noTrRd) data['rd'] = rd;
|
||||||
|
if (rank != 'z') data['rank'] = rank;
|
||||||
|
if (bestRank != 'z') data['bestrank'] = bestRank;
|
||||||
|
if (apm != null) data['apm'] = apm;
|
||||||
|
if (pps != null) data['pps'] = pps;
|
||||||
|
if (vs != null) data['vs'] = vs;
|
||||||
|
if (decaying) data['decaying'] = decaying ? 1 : 0;
|
||||||
|
if (standing >= 0) data['standing'] = standing;
|
||||||
|
data['percentile'] = percentile;
|
||||||
|
if (standingLocal >= 0) data['standing_local'] = standingLocal;
|
||||||
|
if (prevRank != null) data['prev_rank'] = prevRank;
|
||||||
|
if (prevAt >= 0) data['prev_at'] = prevAt;
|
||||||
|
if (nextRank != null) data['next_rank'] = nextRank;
|
||||||
|
if (nextAt >= 0) data['next_at'] = nextAt;
|
||||||
|
data['percentile_rank'] = percentileRank;
|
||||||
|
data['season'] = season;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/end_context_multi.dart';
|
||||||
|
|
||||||
|
class TetraLeagueAlphaRecord{
|
||||||
|
late String replayId;
|
||||||
|
late String ownId;
|
||||||
|
late DateTime timestamp;
|
||||||
|
late bool replayAvalable;
|
||||||
|
late List<EndContextMulti> endContext;
|
||||||
|
|
||||||
|
TetraLeagueAlphaRecord({required this.replayId, required this.ownId, required this.timestamp, required this.endContext, required this.replayAvalable});
|
||||||
|
|
||||||
|
TetraLeagueAlphaRecord.fromJson(Map<String, dynamic> json) {
|
||||||
|
endContext = [EndContextMulti.fromJson(json['endcontext'][0]), EndContextMulti.fromJson(json['endcontext'][1])];
|
||||||
|
replayId = json['replayid'];
|
||||||
|
ownId = json['_id']??replayId;
|
||||||
|
timestamp = DateTime.parse(json['ts']);
|
||||||
|
replayAvalable = ownId != replayId;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['_id'] = ownId;
|
||||||
|
data['endcontext'][0] = endContext[0].toJson();
|
||||||
|
data['endcontext'][1] = endContext[1].toJson();
|
||||||
|
data['replayid'] = replayId;
|
||||||
|
data['ts'] = timestamp;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(covariant TetraLeagueAlphaRecord other) => (ownId == other.ownId) || (replayId == other.replayId);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return "TetraLeagueAlphaRecord: ${endContext.first.userId} vs ${endContext.last.userId}";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league_alpha_record.dart';
|
||||||
|
|
||||||
|
class TetraLeagueAlphaStream{
|
||||||
|
late String userId;
|
||||||
|
late List<TetraLeagueAlphaRecord> records;
|
||||||
|
|
||||||
|
TetraLeagueAlphaStream({required this.userId, required this.records});
|
||||||
|
|
||||||
|
TetraLeagueAlphaStream.fromJson(List<dynamic> json, String userID) {
|
||||||
|
userId = userID;
|
||||||
|
records = [];
|
||||||
|
for (var value in json) {records.add(TetraLeagueAlphaRecord.fromJson(value));}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,111 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/beta_league_leaderboard_entry.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/beta_league_results.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/beta_league_round.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/beta_league_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/beta_record.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league_alpha_record.dart';
|
||||||
|
|
||||||
|
class TetraLeagueBetaStream{
|
||||||
|
late String id;
|
||||||
|
List<BetaRecord> records = [];
|
||||||
|
|
||||||
|
TetraLeagueBetaStream({required this.id, required this.records});
|
||||||
|
|
||||||
|
TetraLeagueBetaStream.fromJson(List<dynamic> json, String userID) {
|
||||||
|
id = userID;
|
||||||
|
for (var entry in json) {
|
||||||
|
records.add(BetaRecord.fromJson(entry));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addFromAlphaStream(List<TetraLeagueAlphaRecord> r){
|
||||||
|
for (var entry in r) {
|
||||||
|
records.add(
|
||||||
|
BetaRecord(
|
||||||
|
id: entry.ownId,
|
||||||
|
replayID: entry.replayId,
|
||||||
|
ts: entry.timestamp,
|
||||||
|
enemyID: entry.endContext[1].userId,
|
||||||
|
enemyUsername: entry.endContext[1].username,
|
||||||
|
gamemode: "oldleague",
|
||||||
|
results: BetaLeagueResults(
|
||||||
|
leaderboard: [
|
||||||
|
BetaLeagueLeaderboardEntry(
|
||||||
|
id: entry.endContext[0].userId,
|
||||||
|
username: entry.endContext[0].username,
|
||||||
|
naturalorder: entry.endContext[0].naturalOrder,
|
||||||
|
wins: entry.endContext[0].points,
|
||||||
|
stats: BetaLeagueStats(
|
||||||
|
apm: entry.endContext[0].secondary,
|
||||||
|
pps: entry.endContext[0].tertiary,
|
||||||
|
vs: entry.endContext[0].extra,
|
||||||
|
garbageSent: -1,
|
||||||
|
garbageReceived: -1,
|
||||||
|
kills: entry.endContext[0].points,
|
||||||
|
altitude: 0.0,
|
||||||
|
rank: -1
|
||||||
|
)
|
||||||
|
),
|
||||||
|
BetaLeagueLeaderboardEntry(
|
||||||
|
id: entry.endContext[1].userId,
|
||||||
|
username: entry.endContext[1].username,
|
||||||
|
naturalorder: entry.endContext[1].naturalOrder,
|
||||||
|
wins: entry.endContext[1].points,
|
||||||
|
stats: BetaLeagueStats(
|
||||||
|
apm: entry.endContext[1].secondary,
|
||||||
|
pps: entry.endContext[1].tertiary,
|
||||||
|
vs: entry.endContext[1].extra,
|
||||||
|
garbageSent: -1,
|
||||||
|
garbageReceived: -1,
|
||||||
|
kills: entry.endContext[1].points,
|
||||||
|
altitude: 0.0,
|
||||||
|
rank: -1
|
||||||
|
)
|
||||||
|
)
|
||||||
|
],
|
||||||
|
rounds: [
|
||||||
|
for (int i=0; i<entry.endContext[0].secondaryTracking.length; i++)
|
||||||
|
[BetaLeagueRound(
|
||||||
|
id: entry.endContext[0].userId,
|
||||||
|
username: entry.endContext[0].username,
|
||||||
|
naturalorder: entry.endContext[0].naturalOrder,
|
||||||
|
active: false,
|
||||||
|
alive: false,
|
||||||
|
lifetime: const Duration(milliseconds: -1),
|
||||||
|
stats: BetaLeagueStats(
|
||||||
|
apm: entry.endContext[0].secondaryTracking[i],
|
||||||
|
pps: entry.endContext[0].tertiaryTracking[i],
|
||||||
|
vs: entry.endContext[0].extraTracking[i],
|
||||||
|
garbageSent: -1,
|
||||||
|
garbageReceived: -1,
|
||||||
|
kills: 0,
|
||||||
|
altitude: 0.0,
|
||||||
|
rank: -1
|
||||||
|
)
|
||||||
|
),BetaLeagueRound(
|
||||||
|
id: entry.endContext[1].userId,
|
||||||
|
username: entry.endContext[1].username,
|
||||||
|
naturalorder: entry.endContext[1].naturalOrder,
|
||||||
|
active: false,
|
||||||
|
alive: false,
|
||||||
|
lifetime: const Duration(milliseconds: -1),
|
||||||
|
stats: BetaLeagueStats(
|
||||||
|
apm: entry.endContext[1].secondaryTracking[i],
|
||||||
|
pps: entry.endContext[1].tertiaryTracking[i],
|
||||||
|
vs: entry.endContext[1].extraTracking[i],
|
||||||
|
garbageSent: -1,
|
||||||
|
garbageReceived: -1,
|
||||||
|
kills: 0,
|
||||||
|
altitude: 0.0,
|
||||||
|
rank: -1
|
||||||
|
)
|
||||||
|
)]
|
||||||
|
]
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,188 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
const int currentSeason = 2;
|
||||||
|
const double noTrRd = 60.9;
|
||||||
|
const double apmWeight = 1;
|
||||||
|
const double ppsWeight = 45;
|
||||||
|
const double vsWeight = 0.444;
|
||||||
|
const double appWeight = 185;
|
||||||
|
const double dssWeight = 175;
|
||||||
|
const double dspWeight = 450;
|
||||||
|
const double appdspWeight = 140;
|
||||||
|
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+"
|
||||||
|
];
|
||||||
|
const Map<String, double> rankCutoffs = {
|
||||||
|
"x+": 0.002,
|
||||||
|
"x": 0.01,
|
||||||
|
"u": 0.05,
|
||||||
|
"ss": 0.11,
|
||||||
|
"s+": 0.17,
|
||||||
|
"s": 0.23,
|
||||||
|
"s-": 0.3,
|
||||||
|
"a+": 0.38,
|
||||||
|
"a": 0.46,
|
||||||
|
"a-": 0.54,
|
||||||
|
"b+": 0.62,
|
||||||
|
"b": 0.7,
|
||||||
|
"b-": 0.78,
|
||||||
|
"c+": 0.84,
|
||||||
|
"c": 0.9,
|
||||||
|
"c-": 0.95,
|
||||||
|
"d+": 0.975,
|
||||||
|
"d": 1,
|
||||||
|
"z": -1,
|
||||||
|
"": 0.5
|
||||||
|
};
|
||||||
|
const Map<String, double> rankTargets = {
|
||||||
|
"x+": 24000.00,
|
||||||
|
"x": 22500.00,
|
||||||
|
"u": 20000.00,
|
||||||
|
"ss": 18000.00,
|
||||||
|
"s+": 16500.00,
|
||||||
|
"s": 15200.00,
|
||||||
|
"s-": 13800.00,
|
||||||
|
"a+": 12000.00,
|
||||||
|
"a": 10500.00,
|
||||||
|
"a-": 9000.00,
|
||||||
|
"b+": 7400.00,
|
||||||
|
"b": 5700.00,
|
||||||
|
"b-": 4200.00,
|
||||||
|
"c+": 3000.00,
|
||||||
|
"c": 2000.00,
|
||||||
|
"c-": 1300.00,
|
||||||
|
"d+": 800.00,
|
||||||
|
"d": 0.00,
|
||||||
|
};
|
||||||
|
// DateTime seasonStart = DateTime.utc(2024, 08, 16, 18);
|
||||||
|
//DateTime seasonEnd = DateTime.utc(2024, 07, 26, 15);
|
||||||
|
enum Stats {
|
||||||
|
tr,
|
||||||
|
glicko,
|
||||||
|
gxe,
|
||||||
|
s1tr,
|
||||||
|
rd,
|
||||||
|
gp,
|
||||||
|
gw,
|
||||||
|
wr,
|
||||||
|
apm,
|
||||||
|
pps,
|
||||||
|
vs,
|
||||||
|
app,
|
||||||
|
dss,
|
||||||
|
dsp,
|
||||||
|
appdsp,
|
||||||
|
vsapm,
|
||||||
|
cheese,
|
||||||
|
gbe,
|
||||||
|
nyaapp,
|
||||||
|
area,
|
||||||
|
eTR,
|
||||||
|
acceTR,
|
||||||
|
acceTRabs,
|
||||||
|
opener,
|
||||||
|
plonk,
|
||||||
|
infDS,
|
||||||
|
stride,
|
||||||
|
stridemMinusPlonk,
|
||||||
|
openerMinusInfDS
|
||||||
|
}
|
||||||
|
|
||||||
|
const Map<Stats, String> chartsShortTitles = {
|
||||||
|
Stats.tr: "TR",
|
||||||
|
Stats.gxe: "Glixare",
|
||||||
|
Stats.s1tr: "S1 TR",
|
||||||
|
Stats.glicko: "Glicko",
|
||||||
|
Stats.rd: "RD",
|
||||||
|
Stats.gp: "GP",
|
||||||
|
Stats.gw: "GW",
|
||||||
|
Stats.wr: "WR%",
|
||||||
|
Stats.apm: "APM",
|
||||||
|
Stats.pps: "PPS",
|
||||||
|
Stats.vs: "VS",
|
||||||
|
Stats.app: "APP",
|
||||||
|
Stats.dss: "DS/S",
|
||||||
|
Stats.dsp: "DS/P",
|
||||||
|
Stats.appdsp: "APP + DS/P",
|
||||||
|
Stats.vsapm: "VS/APM",
|
||||||
|
Stats.cheese: "Cheese",
|
||||||
|
Stats.gbe: "GbE",
|
||||||
|
Stats.nyaapp: "wAPP",
|
||||||
|
Stats.area: "Area",
|
||||||
|
Stats.eTR: "eTR",
|
||||||
|
Stats.acceTR: "±eTR",
|
||||||
|
Stats.acceTRabs: "+eTR absolute",
|
||||||
|
Stats.opener: "Opener",
|
||||||
|
Stats.plonk: "Plonk",
|
||||||
|
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)
|
||||||
|
};
|
||||||
|
|
||||||
|
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
|
||||||
|
};
|
|
@ -1,7 +1,12 @@
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'tetrio.dart';
|
import 'package:tetra_stats/data_objects/clears.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/end_context_multi.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/est_tr.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/finesse.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/nerd_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/playstyle.dart';
|
||||||
|
|
||||||
// I want to implement those fancy TWC stats
|
// I want to implement those fancy TWC stats
|
||||||
// So, i'm going to read replay for things
|
// So, i'm going to read replay for things
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'dart:math';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/badge.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/connections.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/distinguishment.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_zen.dart';
|
||||||
|
|
||||||
|
class TetrioPlayer {
|
||||||
|
late String userId;
|
||||||
|
late String username;
|
||||||
|
late DateTime state;
|
||||||
|
late String role;
|
||||||
|
int? avatarRevision;
|
||||||
|
int? bannerRevision;
|
||||||
|
DateTime? registrationTime;
|
||||||
|
List<Badge> badges = [];
|
||||||
|
String? bio;
|
||||||
|
String? country;
|
||||||
|
late int friendCount;
|
||||||
|
late int gamesPlayed;
|
||||||
|
late int gamesWon;
|
||||||
|
late Duration gameTime;
|
||||||
|
late double xp;
|
||||||
|
late int supporterTier;
|
||||||
|
late bool verified;
|
||||||
|
bool? badstanding;
|
||||||
|
String? botmaster;
|
||||||
|
Connections? connections;
|
||||||
|
TetrioZen? zen;
|
||||||
|
Distinguishment? distinguishment;
|
||||||
|
DateTime? cachedUntil;
|
||||||
|
|
||||||
|
TetrioPlayer({
|
||||||
|
required this.userId,
|
||||||
|
required this.username,
|
||||||
|
required this.role,
|
||||||
|
required this.state,
|
||||||
|
this.avatarRevision,
|
||||||
|
this.bannerRevision,
|
||||||
|
this.registrationTime,
|
||||||
|
required this.badges,
|
||||||
|
this.bio,
|
||||||
|
this.country,
|
||||||
|
required this.friendCount,
|
||||||
|
required this.gamesPlayed,
|
||||||
|
required this.gamesWon,
|
||||||
|
required this.gameTime,
|
||||||
|
required this.xp,
|
||||||
|
required this.supporterTier,
|
||||||
|
required this.verified,
|
||||||
|
this.badstanding,
|
||||||
|
this.botmaster,
|
||||||
|
required this.connections,
|
||||||
|
this.zen,
|
||||||
|
this.distinguishment,
|
||||||
|
this.cachedUntil
|
||||||
|
});
|
||||||
|
|
||||||
|
double get level => pow((xp / 500), 0.6) + (xp / (5000 + (max(0, xp - 4 * pow(10, 6)) / 5000))) + 1;
|
||||||
|
|
||||||
|
TetrioPlayer.fromJson(Map<String, dynamic> json, DateTime stateTime, String id, String nick, [DateTime? cUntil]) {
|
||||||
|
//developer.log("TetrioPlayer.fromJson $stateTime: $json", name: "data_objects/tetrio");
|
||||||
|
userId = id;
|
||||||
|
username = nick;
|
||||||
|
state = stateTime;
|
||||||
|
role = json['role'];
|
||||||
|
registrationTime = json['ts'] != null ? DateTime.parse(json['ts']) : DateTime.fromMillisecondsSinceEpoch(int.parse(id.substring(0, 8), radix: 16) * 1000);
|
||||||
|
if (json['badges'] != null) {
|
||||||
|
json['badges'].forEach((v) {
|
||||||
|
badges.add(Badge.fromJson(v));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
xp = json['xp'] != null ? json['xp'].toDouble() : -1;
|
||||||
|
gamesPlayed = json['gamesplayed'] ?? -1;
|
||||||
|
gamesWon = json['gameswon'] ?? -1;
|
||||||
|
gameTime = json['gametime'] != null && json['gametime'] != -1 ? Duration(microseconds: (json['gametime'].toDouble() * 1000000).floor()) : const Duration(seconds: -1);
|
||||||
|
country = json['country'];
|
||||||
|
supporterTier = json['supporter_tier'] ?? 0;
|
||||||
|
verified = json['verified'] ?? false;
|
||||||
|
avatarRevision = json['avatar_revision'];
|
||||||
|
bannerRevision = json['banner_revision'];
|
||||||
|
bio = json['bio'];
|
||||||
|
if (json['connections'] != null && json['connections'].isNotEmpty) connections = Connections.fromJson(json['connections']);
|
||||||
|
distinguishment = json['distinguishment'] != null ? Distinguishment.fromJson(json['distinguishment']) : null;
|
||||||
|
friendCount = json['friend_count'] ?? 0;
|
||||||
|
badstanding = json['badstanding'];
|
||||||
|
botmaster = json['botmaster'];
|
||||||
|
cachedUntil = cUntil;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
// data['_id'] = userId;
|
||||||
|
// data['username'] = username;
|
||||||
|
data['role'] = role;
|
||||||
|
if (registrationTime != null) data['ts'] = registrationTime?.toString();
|
||||||
|
if (badges.isNotEmpty) data['badges'] = badges.map((v) => v.toJson()).toList();
|
||||||
|
if (xp >= 0) data['xp'] = xp;
|
||||||
|
if (gamesPlayed >= 0) data['gamesplayed'] = gamesPlayed;
|
||||||
|
if (gamesWon >= 0) data['gameswon'] = gamesWon;
|
||||||
|
if (!gameTime.isNegative) data['gametime'] = gameTime.inMicroseconds / 1000000;
|
||||||
|
if (country != null) data['country'] = country;
|
||||||
|
if (supporterTier > 0) data['supporter_tier'] = supporterTier;
|
||||||
|
if (verified) data['verified'] = verified;
|
||||||
|
if (distinguishment != null) data['distinguishment'] = distinguishment?.toJson();
|
||||||
|
if (avatarRevision != null) data['avatar_revision'] = avatarRevision;
|
||||||
|
if (bannerRevision != null) data['banner_revision'] = bannerRevision;
|
||||||
|
if (bio != null) data['bio'] = bio;
|
||||||
|
if (connections != null) data['connections'] = connections!.toJson();
|
||||||
|
if (friendCount > 0) data['friend_count'] = friendCount;
|
||||||
|
if (badstanding != null) data['badstanding'] = badstanding;
|
||||||
|
if (botmaster != null) data['botmaster'] = botmaster;
|
||||||
|
//developer.log("TetrioPlayer.toJson: $data", name: "data_objects/tetrio");
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSameState(covariant TetrioPlayer other) {
|
||||||
|
if (userId != other.userId) return false;
|
||||||
|
if (username != other.username) return false;
|
||||||
|
if (role != other.role) return false;
|
||||||
|
if (listEquals(badges, other.badges) == false) return false;
|
||||||
|
//if (bio != other.bio) return false;
|
||||||
|
if (country != other.country) return false;
|
||||||
|
if (friendCount != other.friendCount) return false;
|
||||||
|
if (gamesPlayed != other.gamesPlayed) return false;
|
||||||
|
if (gamesWon != other.gamesWon) return false;
|
||||||
|
if (gameTime != other.gameTime) return false;
|
||||||
|
if (xp != other.xp) return false;
|
||||||
|
if (supporterTier != other.supporterTier) return false;
|
||||||
|
if (verified != other.verified) return false;
|
||||||
|
if (badstanding != other.badstanding) return false;
|
||||||
|
if (botmaster != other.botmaster) return false;
|
||||||
|
if (connections != other.connections) return false;
|
||||||
|
if (distinguishment != other.distinguishment) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return "$username ($state)";
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => state.hashCode;
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(covariant TetrioPlayer other) => isSameState(other) && state.isAtSameMomentAs(other.state);
|
||||||
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/est_tr.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/nerd_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/playstyle.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||||
|
|
||||||
|
class TetrioPlayerFromLeaderboard {
|
||||||
|
late String userId;
|
||||||
|
late String username;
|
||||||
|
late String role;
|
||||||
|
late double xp;
|
||||||
|
String? country;
|
||||||
|
late DateTime timestamp;
|
||||||
|
late int gamesPlayed;
|
||||||
|
late int gamesWon;
|
||||||
|
late double tr;
|
||||||
|
late double gxe;
|
||||||
|
late double? glicko;
|
||||||
|
late double? rd;
|
||||||
|
late String rank;
|
||||||
|
late String? bestRank;
|
||||||
|
late double apm;
|
||||||
|
late double pps;
|
||||||
|
late double vs;
|
||||||
|
late bool decaying;
|
||||||
|
late NerdStats nerdStats;
|
||||||
|
late EstTr estTr;
|
||||||
|
late Playstyle playstyle;
|
||||||
|
|
||||||
|
TetrioPlayerFromLeaderboard(
|
||||||
|
this.userId,
|
||||||
|
this.username,
|
||||||
|
this.role,
|
||||||
|
this.xp,
|
||||||
|
this.country,
|
||||||
|
this.timestamp,
|
||||||
|
this.gamesPlayed,
|
||||||
|
this.gamesWon,
|
||||||
|
this.tr,
|
||||||
|
this.gxe,
|
||||||
|
this.glicko,
|
||||||
|
this.rd,
|
||||||
|
this.rank,
|
||||||
|
this.bestRank,
|
||||||
|
this.apm,
|
||||||
|
this.pps,
|
||||||
|
this.vs,
|
||||||
|
this.decaying){
|
||||||
|
nerdStats = NerdStats(apm, pps, vs);
|
||||||
|
estTr = EstTr(apm, pps, vs, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);
|
||||||
|
playstyle = Playstyle(apm, pps, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank);
|
||||||
|
}
|
||||||
|
|
||||||
|
double get winrate => gamesWon / gamesPlayed;
|
||||||
|
double get esttracc => estTr.esttr - tr;
|
||||||
|
double get s1tr => gxe * 250;
|
||||||
|
|
||||||
|
TetrioPlayerFromLeaderboard.fromJson(Map<String, dynamic> json, DateTime ts) {
|
||||||
|
userId = json['_id'];
|
||||||
|
username = json['username'];
|
||||||
|
role = json['role'];
|
||||||
|
xp = json['xp'].toDouble();
|
||||||
|
country = json['country'];
|
||||||
|
timestamp = ts;
|
||||||
|
gamesPlayed = json['league']['gamesplayed'] as int;
|
||||||
|
gamesWon = json['league']['gameswon'] as int;
|
||||||
|
tr = json['league']['tr'] != null ? json['league']['tr'].toDouble() : 0;
|
||||||
|
gxe = json['league']['gxe']??-1;
|
||||||
|
glicko = json['league']['glicko']?.toDouble();
|
||||||
|
rd = json['league']['rd']?.toDouble();
|
||||||
|
rank = json['league']['rank'];
|
||||||
|
bestRank = json['league']['bestrank'];
|
||||||
|
apm = json['league']['apm'] != null ? json['league']['apm'].toDouble() : 0.00;
|
||||||
|
pps = json['league']['pps'] != null ? json['league']['pps'].toDouble() : 0.00;
|
||||||
|
vs = json['league']['vs'] != null ? json['league']['vs'].toDouble(): 0.00;
|
||||||
|
decaying = json['league']['decaying'];
|
||||||
|
nerdStats = NerdStats(apm, pps, vs);
|
||||||
|
estTr = EstTr(apm, pps, vs, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);
|
||||||
|
playstyle = Playstyle(apm, pps, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank);
|
||||||
|
}
|
||||||
|
|
||||||
|
num getStatByEnum(Stats stat){
|
||||||
|
switch (stat) {
|
||||||
|
case Stats.tr:
|
||||||
|
return tr;
|
||||||
|
case Stats.glicko:
|
||||||
|
return glicko??-1;
|
||||||
|
case Stats.gxe:
|
||||||
|
return gxe;
|
||||||
|
case Stats.s1tr:
|
||||||
|
return s1tr;
|
||||||
|
case Stats.rd:
|
||||||
|
return rd??-1;
|
||||||
|
case Stats.gp:
|
||||||
|
return gamesPlayed;
|
||||||
|
case Stats.gw:
|
||||||
|
return gamesWon;
|
||||||
|
case Stats.wr:
|
||||||
|
return winrate*100;
|
||||||
|
case Stats.apm:
|
||||||
|
return apm;
|
||||||
|
case Stats.pps:
|
||||||
|
return pps;
|
||||||
|
case Stats.vs:
|
||||||
|
return vs;
|
||||||
|
case Stats.app:
|
||||||
|
return nerdStats.app;
|
||||||
|
case Stats.dss:
|
||||||
|
return nerdStats.dss;
|
||||||
|
case Stats.dsp:
|
||||||
|
return nerdStats.dsp;
|
||||||
|
case Stats.appdsp:
|
||||||
|
return nerdStats.appdsp;
|
||||||
|
case Stats.vsapm:
|
||||||
|
return nerdStats.vsapm;
|
||||||
|
case Stats.cheese:
|
||||||
|
return nerdStats.cheese;
|
||||||
|
case Stats.gbe:
|
||||||
|
return nerdStats.gbe;
|
||||||
|
case Stats.nyaapp:
|
||||||
|
return nerdStats.nyaapp;
|
||||||
|
case Stats.area:
|
||||||
|
return nerdStats.area;
|
||||||
|
case Stats.eTR:
|
||||||
|
return estTr.esttr;
|
||||||
|
case Stats.acceTR:
|
||||||
|
return esttracc;
|
||||||
|
case Stats.acceTRabs:
|
||||||
|
return esttracc.abs();
|
||||||
|
case Stats.opener:
|
||||||
|
return playstyle.opener;
|
||||||
|
case Stats.plonk:
|
||||||
|
return playstyle.plonk;
|
||||||
|
case Stats.infDS:
|
||||||
|
return playstyle.infds;
|
||||||
|
case Stats.stride:
|
||||||
|
return playstyle.stride;
|
||||||
|
case Stats.stridemMinusPlonk:
|
||||||
|
return playstyle.stride - playstyle.plonk;
|
||||||
|
case Stats.openerMinusInfDS:
|
||||||
|
return playstyle.opener - playstyle.infds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,759 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'dart:math';
|
||||||
|
import 'package:tetra_stats/data_objects/leaderboard_position.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/player_leaderboard_position.dart';
|
||||||
|
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_player_from_leaderboard.dart';
|
||||||
|
|
||||||
|
class TetrioPlayersLeaderboard {
|
||||||
|
late String type;
|
||||||
|
late DateTime timestamp;
|
||||||
|
late List<TetrioPlayerFromLeaderboard> leaderboard;
|
||||||
|
|
||||||
|
TetrioPlayersLeaderboard(this.type, this.leaderboard);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString(){
|
||||||
|
return "$type leaderboard: ${leaderboard.length} players";
|
||||||
|
}
|
||||||
|
|
||||||
|
List<TetrioPlayerFromLeaderboard> getStatRanking(List<TetrioPlayerFromLeaderboard> leaderboard, Stats stat, {bool reversed = false, String country = ""}){
|
||||||
|
List<TetrioPlayerFromLeaderboard> lb = List.from(leaderboard);
|
||||||
|
if (country.isNotEmpty){
|
||||||
|
lb.removeWhere((element) => element.country != country);
|
||||||
|
}
|
||||||
|
lb.sort(((a, b) {
|
||||||
|
if (a.getStatByEnum(stat).isNaN) return 1;
|
||||||
|
if (b.getStatByEnum(stat).isNaN) return -1;
|
||||||
|
if (a.getStatByEnum(stat) > b.getStatByEnum(stat)){
|
||||||
|
return reversed ? 1 : -1;
|
||||||
|
}else if (a.getStatByEnum(stat) == b.getStatByEnum(stat)){
|
||||||
|
return 0;
|
||||||
|
}else{
|
||||||
|
return reversed ? -1 : 1;
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
return lb;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<dynamic> getAverageOfRank(String rank){ // i tried to refactor it and that's was terrible
|
||||||
|
if (rank.isNotEmpty && !rankCutoffs.keys.contains(rank)) throw Exception("Invalid rank");
|
||||||
|
List<TetrioPlayerFromLeaderboard> filtredLeaderboard = List.from(leaderboard);
|
||||||
|
if (rank.isNotEmpty) {
|
||||||
|
filtredLeaderboard.removeWhere((element) => element.rank != rank);
|
||||||
|
}
|
||||||
|
if (filtredLeaderboard.isNotEmpty){
|
||||||
|
double avgAPM = 0,
|
||||||
|
avgPPS = 0,
|
||||||
|
avgVS = 0,
|
||||||
|
avgTR = 0,
|
||||||
|
avgGlixare = 0,
|
||||||
|
avgGlicko = 0,
|
||||||
|
avgRD = 0,
|
||||||
|
avgAPP = 0,
|
||||||
|
avgVSAPM = 0,
|
||||||
|
avgDSS = 0,
|
||||||
|
avgDSP = 0,
|
||||||
|
avgAPPDSP = 0,
|
||||||
|
avgCheese = 0,
|
||||||
|
avgGBE = 0,
|
||||||
|
avgNyaAPP = 0,
|
||||||
|
avgArea = 0,
|
||||||
|
avgEstTR = 0,
|
||||||
|
avgEstAcc = 0,
|
||||||
|
avgOpener = 0,
|
||||||
|
avgPlonk = 0,
|
||||||
|
avgStride = 0,
|
||||||
|
avgInfDS = 0,
|
||||||
|
lowestTR = 25000,
|
||||||
|
lowestGlixare = double.infinity,
|
||||||
|
lowestGlicko = double.infinity,
|
||||||
|
lowestRD = double.infinity,
|
||||||
|
lowestWinrate = double.infinity,
|
||||||
|
lowestAPM = double.infinity,
|
||||||
|
lowestPPS = double.infinity,
|
||||||
|
lowestVS = double.infinity,
|
||||||
|
lowestAPP = double.infinity,
|
||||||
|
lowestVSAPM = double.infinity,
|
||||||
|
lowestDSS = double.infinity,
|
||||||
|
lowestDSP = double.infinity,
|
||||||
|
lowestAPPDSP = double.infinity,
|
||||||
|
lowestCheese = double.infinity,
|
||||||
|
lowestGBE = double.infinity,
|
||||||
|
lowestNyaAPP = double.infinity,
|
||||||
|
lowestArea = double.infinity,
|
||||||
|
lowestEstTR = double.infinity,
|
||||||
|
lowestEstAcc = double.infinity,
|
||||||
|
lowestOpener = double.infinity,
|
||||||
|
lowestPlonk = double.infinity,
|
||||||
|
lowestStride = double.infinity,
|
||||||
|
lowestInfDS = double.infinity,
|
||||||
|
highestTR = double.negativeInfinity,
|
||||||
|
highestGlixare = double.negativeInfinity,
|
||||||
|
highestGlicko = double.negativeInfinity,
|
||||||
|
highestRD = double.negativeInfinity,
|
||||||
|
highestWinrate = double.negativeInfinity,
|
||||||
|
highestAPM = double.negativeInfinity,
|
||||||
|
highestPPS = double.negativeInfinity,
|
||||||
|
highestVS = double.negativeInfinity,
|
||||||
|
highestAPP = double.negativeInfinity,
|
||||||
|
highestVSAPM = double.negativeInfinity,
|
||||||
|
highestDSS = double.negativeInfinity,
|
||||||
|
highestDSP = double.negativeInfinity,
|
||||||
|
highestAPPDSP = double.negativeInfinity,
|
||||||
|
highestCheese = double.negativeInfinity,
|
||||||
|
highestGBE = double.negativeInfinity,
|
||||||
|
highestNyaAPP = double.negativeInfinity,
|
||||||
|
highestArea = double.negativeInfinity,
|
||||||
|
highestEstTR = double.negativeInfinity,
|
||||||
|
highestEstAcc = double.negativeInfinity,
|
||||||
|
highestOpener = double.negativeInfinity,
|
||||||
|
highestPlonk = double.negativeInfinity,
|
||||||
|
highestStride = double.negativeInfinity,
|
||||||
|
highestInfDS = double.negativeInfinity;
|
||||||
|
int avgGamesPlayed = 0,
|
||||||
|
avgGamesWon = 0,
|
||||||
|
totalGamesPlayed = 0,
|
||||||
|
totalGamesWon = 0,
|
||||||
|
lowestGamesPlayed = pow(2, 53) as int,
|
||||||
|
lowestGamesWon = pow(2, 53) as int,
|
||||||
|
highestGamesPlayed = 0,
|
||||||
|
highestGamesWon = 0;
|
||||||
|
String lowestTRid = "", lowestTRnick = "",
|
||||||
|
lowestGlixareID = "", lowestGlixareNick = "",
|
||||||
|
lowestGlickoID = "", lowestGlickoNick = "",
|
||||||
|
lowestRdID = "", lowestRdNick = "",
|
||||||
|
lowestGamesPlayedID = "", lowestGamesPlayedNick = "",
|
||||||
|
lowestGamesWonID = "", lowestGamesWonNick = "",
|
||||||
|
lowestWinrateID = "", lowestWinrateNick = "",
|
||||||
|
lowestAPMid = "", lowestAPMnick = "",
|
||||||
|
lowestPPSid = "", lowestPPSnick = "",
|
||||||
|
lowestVSid = "", lowestVSnick = "",
|
||||||
|
lowestAPPid = "", lowestAPPnick = "",
|
||||||
|
lowestVSAPMid = "", lowestVSAPMnick = "",
|
||||||
|
lowestDSSid = "", lowestDSSnick = "",
|
||||||
|
lowestDSPid = "", lowestDSPnick = "",
|
||||||
|
lowestAPPDSPid = "", lowestAPPDSPnick = "",
|
||||||
|
lowestCheeseID = "", lowestCheeseNick = "",
|
||||||
|
lowestGBEid = "", lowestGBEnick = "",
|
||||||
|
lowestNyaAPPid = "", lowestNyaAPPnick = "",
|
||||||
|
lowestAreaID = "", lowestAreaNick = "",
|
||||||
|
lowestEstTRid = "", lowestEstTRnick = "",
|
||||||
|
lowestEstAccID = "", lowestEstAccNick = "",
|
||||||
|
lowestOpenerID = "", lowestOpenerNick = "",
|
||||||
|
lowestPlonkID = "", lowestPlonkNick = "",
|
||||||
|
lowestStrideID = "", lowestStrideNick = "",
|
||||||
|
lowestInfDSid = "", lowestInfDSnick = "",
|
||||||
|
highestTRid = "", highestTRnick = "",
|
||||||
|
highestGlixareID = "", highestGlixareNick = "",
|
||||||
|
highestGlickoID = "", highestGlickoNick = "",
|
||||||
|
highestRdID = "", highestRdNick = "",
|
||||||
|
highestGamesPlayedID = "", highestGamesPlayedNick = "",
|
||||||
|
highestGamesWonID = "", highestGamesWonNick = "",
|
||||||
|
highestWinrateID = "", highestWinrateNick = "",
|
||||||
|
highestAPMid = "", highestAPMnick = "",
|
||||||
|
highestPPSid = "", highestPPSnick = "",
|
||||||
|
highestVSid = "", highestVSnick = "",
|
||||||
|
highestAPPid = "", highestAPPnick = "",
|
||||||
|
highestVSAPMid = "", highestVSAPMnick = "",
|
||||||
|
highestDSSid = "", highestDSSnick = "",
|
||||||
|
highestDSPid = "", highestDSPnick = "",
|
||||||
|
highestAPPDSPid = "", highestAPPDSPnick = "",
|
||||||
|
highestCheeseID = "", highestCheeseNick = "",
|
||||||
|
highestGBEid = "", highestGBEnick = "",
|
||||||
|
highestNyaAPPid = "", highestNyaAPPnick = "",
|
||||||
|
highestAreaID = "", highestAreaNick = "",
|
||||||
|
highestEstTRid = "", highestEstTRnick = "",
|
||||||
|
highestEstAccID = "", highestEstAccNick = "",
|
||||||
|
highestOpenerID = "", highestOpenerNick = "",
|
||||||
|
highestPlonkID = "", highestPlonkNick = "",
|
||||||
|
highestStrideID = "", highestStrideNick = "",
|
||||||
|
highestInfDSid = "", highestInfDSnick = "";
|
||||||
|
for (var entry in filtredLeaderboard){
|
||||||
|
avgAPM += entry.apm;
|
||||||
|
avgPPS += entry.pps;
|
||||||
|
avgVS += entry.vs;
|
||||||
|
avgTR += entry.tr;
|
||||||
|
avgGlixare += entry.gxe;
|
||||||
|
if (entry.glicko != null) avgGlicko += entry.glicko!;
|
||||||
|
if (entry.rd != null) avgRD += entry.rd!;
|
||||||
|
avgAPP += entry.nerdStats.app;
|
||||||
|
avgVSAPM += entry.nerdStats.vsapm;
|
||||||
|
avgDSS += entry.nerdStats.dss;
|
||||||
|
avgDSP += entry.nerdStats.dsp;
|
||||||
|
avgAPPDSP += entry.nerdStats.appdsp;
|
||||||
|
avgCheese += entry.nerdStats.cheese;
|
||||||
|
avgGBE += entry.nerdStats.gbe;
|
||||||
|
avgNyaAPP += entry.nerdStats.nyaapp;
|
||||||
|
avgArea += entry.nerdStats.area;
|
||||||
|
avgEstTR += entry.estTr.esttr;
|
||||||
|
avgEstAcc += entry.esttracc;
|
||||||
|
avgOpener += entry.playstyle.opener;
|
||||||
|
avgPlonk += entry.playstyle.plonk;
|
||||||
|
avgStride += entry.playstyle.stride;
|
||||||
|
avgInfDS += entry.playstyle.infds;
|
||||||
|
totalGamesPlayed += entry.gamesPlayed;
|
||||||
|
totalGamesWon += entry.gamesWon;
|
||||||
|
if (entry.tr < lowestTR){
|
||||||
|
lowestTR = entry.tr;
|
||||||
|
lowestTRid = entry.userId;
|
||||||
|
lowestTRnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.gxe < lowestGlixare){
|
||||||
|
lowestGlixare = entry.gxe;
|
||||||
|
lowestGlixareID = entry.userId;
|
||||||
|
lowestGlixareNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.glicko != null && entry.glicko! < lowestGlicko){
|
||||||
|
lowestGlicko = entry.glicko!;
|
||||||
|
lowestGlickoID = entry.userId;
|
||||||
|
lowestGlickoNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.rd != null && entry.rd! < lowestRD){
|
||||||
|
lowestRD = entry.rd!;
|
||||||
|
lowestRdID = entry.userId;
|
||||||
|
lowestRdNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.gamesPlayed < lowestGamesPlayed){
|
||||||
|
lowestGamesPlayed = entry.gamesPlayed;
|
||||||
|
lowestGamesPlayedID = entry.userId;
|
||||||
|
lowestGamesPlayedNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.gamesWon < lowestGamesWon){
|
||||||
|
lowestGamesWon = entry.gamesWon;
|
||||||
|
lowestGamesWonID = entry.userId;
|
||||||
|
lowestGamesWonNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.winrate < lowestWinrate){
|
||||||
|
lowestWinrate = entry.winrate;
|
||||||
|
lowestWinrateID = entry.userId;
|
||||||
|
lowestWinrateNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.apm < lowestAPM){
|
||||||
|
lowestAPM = entry.apm;
|
||||||
|
lowestAPMid = entry.userId;
|
||||||
|
lowestAPMnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.pps < lowestPPS){
|
||||||
|
lowestPPS = entry.pps;
|
||||||
|
lowestPPSid = entry.userId;
|
||||||
|
lowestPPSnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.vs < lowestVS){
|
||||||
|
lowestVS = entry.vs;
|
||||||
|
lowestVSid = entry.userId;
|
||||||
|
lowestVSnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.app < lowestAPP){
|
||||||
|
lowestAPP = entry.nerdStats.app;
|
||||||
|
lowestAPPid = entry.userId;
|
||||||
|
lowestAPPnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.vsapm < lowestVSAPM){
|
||||||
|
lowestVSAPM = entry.nerdStats.vsapm;
|
||||||
|
lowestVSAPMid = entry.userId;
|
||||||
|
lowestVSAPMnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.dss < lowestDSS){
|
||||||
|
lowestDSS = entry.nerdStats.dss;
|
||||||
|
lowestDSSid = entry.userId;
|
||||||
|
lowestDSSnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.dsp < lowestDSP){
|
||||||
|
lowestDSP = entry.nerdStats.dsp;
|
||||||
|
lowestDSPid = entry.userId;
|
||||||
|
lowestDSPnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.appdsp < lowestAPPDSP){
|
||||||
|
lowestAPPDSP = entry.nerdStats.appdsp;
|
||||||
|
lowestAPPDSPid = entry.userId;
|
||||||
|
lowestAPPDSPnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.cheese < lowestCheese){
|
||||||
|
lowestCheese = entry.nerdStats.cheese;
|
||||||
|
lowestCheeseID = entry.userId;
|
||||||
|
lowestCheeseNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.gbe < lowestGBE){
|
||||||
|
lowestGBE = entry.nerdStats.gbe;
|
||||||
|
lowestGBEid = entry.userId;
|
||||||
|
lowestGBEnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.nyaapp < lowestNyaAPP){
|
||||||
|
lowestNyaAPP = entry.nerdStats.nyaapp;
|
||||||
|
lowestNyaAPPid = entry.userId;
|
||||||
|
lowestNyaAPPnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.area < lowestArea){
|
||||||
|
lowestArea = entry.nerdStats.area;
|
||||||
|
lowestAreaID = entry.userId;
|
||||||
|
lowestAreaNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.estTr.esttr < lowestEstTR){
|
||||||
|
lowestEstTR = entry.estTr.esttr;
|
||||||
|
lowestEstTRid = entry.userId;
|
||||||
|
lowestEstTRnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.esttracc < lowestEstAcc){
|
||||||
|
lowestEstAcc = entry.esttracc;
|
||||||
|
lowestEstAccID = entry.userId;
|
||||||
|
lowestEstAccNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.playstyle.opener < lowestOpener){
|
||||||
|
lowestOpener = entry.playstyle.opener;
|
||||||
|
lowestOpenerID = entry.userId;
|
||||||
|
lowestOpenerNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.playstyle.plonk < lowestPlonk){
|
||||||
|
lowestPlonk = entry.playstyle.plonk;
|
||||||
|
lowestPlonkID = entry.userId;
|
||||||
|
lowestPlonkNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.playstyle.stride < lowestStride){
|
||||||
|
lowestStride = entry.playstyle.stride;
|
||||||
|
lowestStrideID = entry.userId;
|
||||||
|
lowestStrideNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.playstyle.infds < lowestInfDS){
|
||||||
|
lowestInfDS = entry.playstyle.infds;
|
||||||
|
lowestInfDSid = entry.userId;
|
||||||
|
lowestInfDSnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.tr > highestTR){
|
||||||
|
highestTR = entry.tr;
|
||||||
|
highestTRid = entry.userId;
|
||||||
|
highestTRnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.gxe > highestGlixare){
|
||||||
|
highestGlixare = entry.gxe;
|
||||||
|
highestGlixareID = entry.userId;
|
||||||
|
highestGlixareNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.glicko != null && entry.glicko! > highestGlicko){
|
||||||
|
highestGlicko = entry.glicko!;
|
||||||
|
highestGlickoID = entry.userId;
|
||||||
|
highestGlickoNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.rd != null && entry.rd! > highestRD){
|
||||||
|
highestRD = entry.rd!;
|
||||||
|
highestRdID = entry.userId;
|
||||||
|
highestRdNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.gamesPlayed > highestGamesPlayed){
|
||||||
|
highestGamesPlayed = entry.gamesPlayed;
|
||||||
|
highestGamesPlayedID = entry.userId;
|
||||||
|
highestGamesPlayedNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.gamesWon > highestGamesWon){
|
||||||
|
highestGamesWon = entry.gamesWon;
|
||||||
|
highestGamesWonID = entry.userId;
|
||||||
|
highestGamesWonNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.winrate > highestWinrate){
|
||||||
|
highestWinrate = entry.winrate;
|
||||||
|
highestWinrateID = entry.userId;
|
||||||
|
highestWinrateNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.apm > highestAPM){
|
||||||
|
highestAPM = entry.apm;
|
||||||
|
highestAPMid = entry.userId;
|
||||||
|
highestAPMnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.pps > highestPPS){
|
||||||
|
highestPPS = entry.pps;
|
||||||
|
highestPPSid = entry.userId;
|
||||||
|
highestPPSnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.vs > highestVS){
|
||||||
|
highestVS = entry.vs;
|
||||||
|
highestVSid = entry.userId;
|
||||||
|
highestVSnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.app > highestAPP){
|
||||||
|
highestAPP = entry.nerdStats.app;
|
||||||
|
highestAPPid = entry.userId;
|
||||||
|
highestAPPnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.vsapm > highestVSAPM){
|
||||||
|
highestVSAPM = entry.nerdStats.vsapm;
|
||||||
|
highestVSAPMid = entry.userId;
|
||||||
|
highestVSAPMnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.dss > highestDSS){
|
||||||
|
highestDSS = entry.nerdStats.dss;
|
||||||
|
highestDSSid = entry.userId;
|
||||||
|
highestDSSnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.dsp > highestDSP){
|
||||||
|
highestDSP = entry.nerdStats.dsp;
|
||||||
|
highestDSPid = entry.userId;
|
||||||
|
highestDSPnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.appdsp > highestAPPDSP){
|
||||||
|
highestAPPDSP = entry.nerdStats.appdsp;
|
||||||
|
highestAPPDSPid = entry.userId;
|
||||||
|
highestAPPDSPnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.cheese > highestCheese){
|
||||||
|
highestCheese = entry.nerdStats.cheese;
|
||||||
|
highestCheeseID = entry.userId;
|
||||||
|
highestCheeseNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.gbe > highestGBE){
|
||||||
|
highestGBE = entry.nerdStats.gbe;
|
||||||
|
highestGBEid = entry.userId;
|
||||||
|
highestGBEnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.nyaapp > highestNyaAPP){
|
||||||
|
highestNyaAPP = entry.nerdStats.nyaapp;
|
||||||
|
highestNyaAPPid = entry.userId;
|
||||||
|
highestNyaAPPnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.nerdStats.area > highestArea){
|
||||||
|
highestArea = entry.nerdStats.area;
|
||||||
|
highestAreaID = entry.userId;
|
||||||
|
highestAreaNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.estTr.esttr > highestEstTR){
|
||||||
|
highestEstTR = entry.estTr.esttr;
|
||||||
|
highestEstTRid = entry.userId;
|
||||||
|
highestEstTRnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.esttracc > highestEstAcc){
|
||||||
|
highestEstAcc = entry.esttracc;
|
||||||
|
highestEstAccID = entry.userId;
|
||||||
|
highestEstAccNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.playstyle.opener > highestOpener){
|
||||||
|
highestOpener = entry.playstyle.opener;
|
||||||
|
highestOpenerID = entry.userId;
|
||||||
|
highestOpenerNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.playstyle.plonk > highestPlonk){
|
||||||
|
highestPlonk = entry.playstyle.plonk;
|
||||||
|
highestPlonkID = entry.userId;
|
||||||
|
highestPlonkNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.playstyle.stride > highestStride){
|
||||||
|
highestStride = entry.playstyle.stride;
|
||||||
|
highestStrideID = entry.userId;
|
||||||
|
highestStrideNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.playstyle.infds > highestInfDS){
|
||||||
|
highestInfDS = entry.playstyle.infds;
|
||||||
|
highestInfDSid = entry.userId;
|
||||||
|
highestInfDSnick = entry.username;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avgAPM /= filtredLeaderboard.length;
|
||||||
|
avgPPS /= filtredLeaderboard.length;
|
||||||
|
avgVS /= filtredLeaderboard.length;
|
||||||
|
avgTR /= filtredLeaderboard.length;
|
||||||
|
avgGlixare /= filtredLeaderboard.length;
|
||||||
|
avgGlicko /= filtredLeaderboard.length;
|
||||||
|
avgRD /= filtredLeaderboard.length;
|
||||||
|
avgAPP /= filtredLeaderboard.length;
|
||||||
|
avgVSAPM /= filtredLeaderboard.length;
|
||||||
|
avgDSS /= filtredLeaderboard.length;
|
||||||
|
avgDSP /= filtredLeaderboard.length;
|
||||||
|
avgAPPDSP /= leaderboard.length;
|
||||||
|
avgCheese /= filtredLeaderboard.length;
|
||||||
|
avgGBE /= filtredLeaderboard.length;
|
||||||
|
avgNyaAPP /= filtredLeaderboard.length;
|
||||||
|
avgArea /= filtredLeaderboard.length;
|
||||||
|
avgEstTR /= filtredLeaderboard.length;
|
||||||
|
avgEstAcc /= filtredLeaderboard.length;
|
||||||
|
avgOpener /= filtredLeaderboard.length;
|
||||||
|
avgPlonk /= filtredLeaderboard.length;
|
||||||
|
avgStride /= filtredLeaderboard.length;
|
||||||
|
avgInfDS /= filtredLeaderboard.length;
|
||||||
|
avgGamesPlayed = (totalGamesPlayed / filtredLeaderboard.length).floor();
|
||||||
|
avgGamesWon = (totalGamesWon / filtredLeaderboard.length).floor();
|
||||||
|
return [TetraLeague(id: "", timestamp: DateTime.now(), apm: avgAPM, pps: avgPPS, vs: avgVS, gxe: avgGlixare, glicko: avgGlicko, rd: avgRD, gamesPlayed: avgGamesPlayed, gamesWon: avgGamesWon, bestRank: rank, decaying: false, tr: avgTR, rank: rank == "" ? "z" : rank, percentileRank: rank, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1, season: currentSeason),
|
||||||
|
{
|
||||||
|
"everyone": rank == "",
|
||||||
|
"totalGamesPlayed": totalGamesPlayed,
|
||||||
|
"totalGamesWon": totalGamesWon,
|
||||||
|
"players": filtredLeaderboard.length,
|
||||||
|
"lowestTR": lowestTR,
|
||||||
|
"lowestTRid": lowestTRid,
|
||||||
|
"lowestTRnick": lowestTRnick,
|
||||||
|
"lowestGlixare": lowestGlixare,
|
||||||
|
"lowestGlixareID": lowestGlixareID,
|
||||||
|
"lowestGlixareNick": lowestGlixareNick,
|
||||||
|
"lowestS1tr": lowestGlixare * 250,
|
||||||
|
"lowestS1trID": lowestGlixareID,
|
||||||
|
"lowestS1trNick": lowestGlixareNick,
|
||||||
|
"lowestGlicko": lowestGlicko,
|
||||||
|
"lowestGlickoID": lowestGlickoID,
|
||||||
|
"lowestGlickoNick": lowestGlickoNick,
|
||||||
|
"lowestRD": lowestRD,
|
||||||
|
"lowestRdID": lowestRdID,
|
||||||
|
"lowestRdNick": lowestRdNick,
|
||||||
|
"lowestGamesPlayed": lowestGamesPlayed,
|
||||||
|
"lowestGamesPlayedID": lowestGamesPlayedID,
|
||||||
|
"lowestGamesPlayedNick": lowestGamesPlayedNick,
|
||||||
|
"lowestGamesWon": lowestGamesWon,
|
||||||
|
"lowestGamesWonID": lowestGamesWonID,
|
||||||
|
"lowestGamesWonNick": lowestGamesWonNick,
|
||||||
|
"lowestWinrate": lowestWinrate,
|
||||||
|
"lowestWinrateID": lowestWinrateID,
|
||||||
|
"lowestWinrateNick": lowestWinrateNick,
|
||||||
|
"lowestAPM": lowestAPM,
|
||||||
|
"lowestAPMid": lowestAPMid,
|
||||||
|
"lowestAPMnick": lowestAPMnick,
|
||||||
|
"lowestPPS": lowestPPS,
|
||||||
|
"lowestPPSid": lowestPPSid,
|
||||||
|
"lowestPPSnick": lowestPPSnick,
|
||||||
|
"lowestVS": lowestVS,
|
||||||
|
"lowestVSid": lowestVSid,
|
||||||
|
"lowestVSnick": lowestVSnick,
|
||||||
|
"lowestAPP": lowestAPP,
|
||||||
|
"lowestAPPid": lowestAPPid,
|
||||||
|
"lowestAPPnick": lowestAPPnick,
|
||||||
|
"lowestVSAPM": lowestVSAPM,
|
||||||
|
"lowestVSAPMid": lowestVSAPMid,
|
||||||
|
"lowestVSAPMnick": lowestVSAPMnick,
|
||||||
|
"lowestDSS": lowestDSS,
|
||||||
|
"lowestDSSid": lowestDSSid,
|
||||||
|
"lowestDSSnick": lowestDSSnick,
|
||||||
|
"lowestDSP": lowestDSP,
|
||||||
|
"lowestDSPid": lowestDSPid,
|
||||||
|
"lowestDSPnick": lowestDSPnick,
|
||||||
|
"lowestAPPDSP": lowestAPPDSP,
|
||||||
|
"lowestAPPDSPid": lowestAPPDSPid,
|
||||||
|
"lowestAPPDSPnick": lowestAPPDSPnick,
|
||||||
|
"lowestCheese": lowestCheese,
|
||||||
|
"lowestCheeseID": lowestCheeseID,
|
||||||
|
"lowestCheeseNick": lowestCheeseNick,
|
||||||
|
"lowestGBE": lowestGBE,
|
||||||
|
"lowestGBEid": lowestGBEid,
|
||||||
|
"lowestGBEnick": lowestGBEnick,
|
||||||
|
"lowestNyaAPP": lowestNyaAPP,
|
||||||
|
"lowestNyaAPPid": lowestNyaAPPid,
|
||||||
|
"lowestNyaAPPnick": lowestNyaAPPnick,
|
||||||
|
"lowestArea": lowestArea,
|
||||||
|
"lowestAreaID": lowestAreaID,
|
||||||
|
"lowestAreaNick": lowestAreaNick,
|
||||||
|
"lowestEstTR": lowestEstTR,
|
||||||
|
"lowestEstTRid": lowestEstTRid,
|
||||||
|
"lowestEstTRnick": lowestEstTRnick,
|
||||||
|
"lowestEstAcc": lowestEstAcc,
|
||||||
|
"lowestEstAccID": lowestEstAccID,
|
||||||
|
"lowestEstAccNick": lowestEstAccNick,
|
||||||
|
"lowestOpener": lowestOpener,
|
||||||
|
"lowestOpenerID": lowestOpenerID,
|
||||||
|
"lowestOpenerNick": lowestOpenerNick,
|
||||||
|
"lowestPlonk": lowestPlonk,
|
||||||
|
"lowestPlonkID": lowestPlonkID,
|
||||||
|
"lowestPlonkNick": lowestPlonkNick,
|
||||||
|
"lowestStride": lowestStride,
|
||||||
|
"lowestStrideID": lowestStrideID,
|
||||||
|
"lowestStrideNick": lowestStrideNick,
|
||||||
|
"lowestInfDS": lowestInfDS,
|
||||||
|
"lowestInfDSid": lowestInfDSid,
|
||||||
|
"lowestInfDSnick": lowestInfDSnick,
|
||||||
|
"highestTR": highestTR,
|
||||||
|
"highestTRid": highestTRid,
|
||||||
|
"highestTRnick": highestTRnick,
|
||||||
|
"highestGlixare": highestGlixare,
|
||||||
|
"highestGlixareID": highestGlixareID,
|
||||||
|
"highestGlixareNick": highestGlixareNick,
|
||||||
|
"highestS1tr": highestGlixare * 250,
|
||||||
|
"highestS1trID": highestGlixareID,
|
||||||
|
"highestS1trNick": highestGlixareNick,
|
||||||
|
"highestGlicko": highestGlicko,
|
||||||
|
"highestGlickoID": highestGlickoID,
|
||||||
|
"highestGlickoNick": highestGlickoNick,
|
||||||
|
"highestRD": highestRD,
|
||||||
|
"highestRdID": highestRdID,
|
||||||
|
"highestRdNick": highestRdNick,
|
||||||
|
"highestGamesPlayed": highestGamesPlayed,
|
||||||
|
"highestGamesPlayedID": highestGamesPlayedID,
|
||||||
|
"highestGamesPlayedNick": highestGamesPlayedNick,
|
||||||
|
"highestGamesWon": highestGamesWon,
|
||||||
|
"highestGamesWonID": highestGamesWonID,
|
||||||
|
"highestGamesWonNick": highestGamesWonNick,
|
||||||
|
"highestWinrate": highestWinrate,
|
||||||
|
"highestWinrateID": highestWinrateID,
|
||||||
|
"highestWinrateNick": highestWinrateNick,
|
||||||
|
"highestAPM": highestAPM,
|
||||||
|
"highestAPMid": highestAPMid,
|
||||||
|
"highestAPMnick": highestAPMnick,
|
||||||
|
"highestPPS": highestPPS,
|
||||||
|
"highestPPSid": highestPPSid,
|
||||||
|
"highestPPSnick": highestPPSnick,
|
||||||
|
"highestVS": highestVS,
|
||||||
|
"highestVSid": highestVSid,
|
||||||
|
"highestVSnick": highestVSnick,
|
||||||
|
"highestAPP": highestAPP,
|
||||||
|
"highestAPPid": highestAPPid,
|
||||||
|
"highestAPPnick": highestAPPnick,
|
||||||
|
"highestVSAPM": highestVSAPM,
|
||||||
|
"highestVSAPMid": highestVSAPMid,
|
||||||
|
"highestVSAPMnick": highestVSAPMnick,
|
||||||
|
"highestDSS": highestDSS,
|
||||||
|
"highestDSSid": highestDSSid,
|
||||||
|
"highestDSSnick": highestDSSnick,
|
||||||
|
"highestDSP": highestDSP,
|
||||||
|
"highestDSPid": highestDSPid,
|
||||||
|
"highestDSPnick": highestDSPnick,
|
||||||
|
"highestAPPDSP": highestAPPDSP,
|
||||||
|
"highestAPPDSPid": highestAPPDSPid,
|
||||||
|
"highestAPPDSPnick": highestAPPDSPnick,
|
||||||
|
"highestCheese": highestCheese,
|
||||||
|
"highestCheeseID": highestCheeseID,
|
||||||
|
"highestCheeseNick": highestCheeseNick,
|
||||||
|
"highestGBE": highestGBE,
|
||||||
|
"highestGBEid": highestGBEid,
|
||||||
|
"highestGBEnick": highestGBEnick,
|
||||||
|
"highestNyaAPP": highestNyaAPP,
|
||||||
|
"highestNyaAPPid": highestNyaAPPid,
|
||||||
|
"highestNyaAPPnick": highestNyaAPPnick,
|
||||||
|
"highestArea": highestArea,
|
||||||
|
"highestAreaID": highestAreaID,
|
||||||
|
"highestAreaNick": highestAreaNick,
|
||||||
|
"highestEstTR": highestEstTR,
|
||||||
|
"highestEstTRid": highestEstTRid,
|
||||||
|
"highestEstTRnick": highestEstTRnick,
|
||||||
|
"highestEstAcc": highestEstAcc,
|
||||||
|
"highestEstAccID": highestEstAccID,
|
||||||
|
"highestEstAccNick": highestEstAccNick,
|
||||||
|
"highestOpener": highestOpener,
|
||||||
|
"highestOpenerID": highestOpenerID,
|
||||||
|
"highestOpenerNick": highestOpenerNick,
|
||||||
|
"highestPlonk": highestPlonk,
|
||||||
|
"highestPlonkID": highestPlonkID,
|
||||||
|
"highestPlonkNick": highestPlonkNick,
|
||||||
|
"highestStride": highestStride,
|
||||||
|
"highestStrideID": highestStrideID,
|
||||||
|
"highestStrideNick": highestStrideNick,
|
||||||
|
"highestInfDS": highestInfDS,
|
||||||
|
"highestInfDSid": highestInfDSid,
|
||||||
|
"highestInfDSnick": highestInfDSnick,
|
||||||
|
"avgAPP": avgAPP,
|
||||||
|
"avgVSAPM": avgVSAPM,
|
||||||
|
"avgDSS": avgDSS,
|
||||||
|
"avgDSP": avgDSP,
|
||||||
|
"avgAPPDSP": avgAPPDSP,
|
||||||
|
"avgCheese": avgCheese,
|
||||||
|
"avgGBE": avgGBE,
|
||||||
|
"avgNyaAPP": avgNyaAPP,
|
||||||
|
"avgArea": avgArea,
|
||||||
|
"avgEstTR": avgEstTR,
|
||||||
|
"avgEstAcc": avgEstAcc,
|
||||||
|
"avgOpener": avgOpener,
|
||||||
|
"avgPlonk": avgPlonk,
|
||||||
|
"avgStride": avgStride,
|
||||||
|
"avgInfDS": avgInfDS,
|
||||||
|
"toEnterTR": rank.toLowerCase() != "z" ? leaderboard[(leaderboard.length * rankCutoffs[rank]!).floor()-1].tr : lowestTR,
|
||||||
|
"toEnterGlicko": rank.toLowerCase() != "z" ? leaderboard[(leaderboard.length * rankCutoffs[rank]!).floor()-1].glicko : 0,
|
||||||
|
"entries": filtredLeaderboard
|
||||||
|
}];
|
||||||
|
}else{
|
||||||
|
return [TetraLeague(id: "", timestamp: DateTime.now(), apm: 0, pps: 0, vs: 0, glicko: 0, rd: noTrRd, gamesPlayed: 0, gamesWon: 0, bestRank: rank, decaying: false, tr: 0, rank: rank, percentileRank: rank, gxe: -1, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1, season: currentSeason),
|
||||||
|
{"players": filtredLeaderboard.length, "lowestTR": 0, "toEnterTR": 0, "toEnterGlicko": 0}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PlayerLeaderboardPosition? getLeaderboardPosition(Map<String, TetraLeague>league) {
|
||||||
|
if (league.values.first.gamesPlayed == 0) return null;
|
||||||
|
bool fakePositions = false;
|
||||||
|
late List<TetrioPlayerFromLeaderboard> copyOfLeaderboard;
|
||||||
|
if (leaderboard.indexWhere((element) => element.userId == league.keys.first) == -1){
|
||||||
|
fakePositions =true;
|
||||||
|
copyOfLeaderboard = List.of(leaderboard);
|
||||||
|
copyOfLeaderboard.add(league.values.first.convertToPlayerFromLeaderboard(league.keys.first));
|
||||||
|
}
|
||||||
|
List<Stats> stats = [Stats.apm, Stats.pps, Stats.vs, Stats.gp, Stats.gw, Stats.wr,
|
||||||
|
Stats.app, Stats.vsapm, Stats.dss, Stats.dsp, Stats.appdsp, Stats.cheese, Stats.gbe, Stats.nyaapp, Stats.area, Stats.eTR, Stats.acceTR];
|
||||||
|
List<LeaderboardPosition?> results = [];
|
||||||
|
for (Stats stat in stats) {
|
||||||
|
List<TetrioPlayerFromLeaderboard> sortedLeaderboard = getStatRanking(fakePositions ? copyOfLeaderboard : leaderboard, stat, reversed: stat == Stats.cheese ? true : false);
|
||||||
|
int position = sortedLeaderboard.indexWhere((element) => element.userId == league.keys.first) + 1;
|
||||||
|
if (position == 0) {
|
||||||
|
results.add(null);
|
||||||
|
} else {
|
||||||
|
results.add(LeaderboardPosition(fakePositions ? 1001 : position, position / sortedLeaderboard.length));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return PlayerLeaderboardPosition.fromSearchResults(results);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, List<dynamic>> get averages => {
|
||||||
|
'x+': getAverageOfRank("x+"),
|
||||||
|
'x': getAverageOfRank("x"),
|
||||||
|
'u': getAverageOfRank("u"),
|
||||||
|
'ss': getAverageOfRank("ss"),
|
||||||
|
's+': getAverageOfRank("s+"),
|
||||||
|
's': getAverageOfRank("s"),
|
||||||
|
's-': getAverageOfRank("s-"),
|
||||||
|
'a+': getAverageOfRank("a+"),
|
||||||
|
'a': getAverageOfRank("a"),
|
||||||
|
'a-': getAverageOfRank("a-"),
|
||||||
|
'b+': getAverageOfRank("b+"),
|
||||||
|
'b': getAverageOfRank("b"),
|
||||||
|
'b-': getAverageOfRank("b-"),
|
||||||
|
'c+': getAverageOfRank("c+"),
|
||||||
|
'c': getAverageOfRank("c"),
|
||||||
|
'c-': getAverageOfRank("c-"),
|
||||||
|
'd+': getAverageOfRank("d+"),
|
||||||
|
'd': getAverageOfRank("d"),
|
||||||
|
'z': getAverageOfRank("z")
|
||||||
|
};
|
||||||
|
|
||||||
|
Map<String, double> get cutoffs => {
|
||||||
|
'x': getAverageOfRank("x")[1]["toEnterTR"],
|
||||||
|
'u': getAverageOfRank("u")[1]["toEnterTR"],
|
||||||
|
'ss': getAverageOfRank("ss")[1]["toEnterTR"],
|
||||||
|
's+': getAverageOfRank("s+")[1]["toEnterTR"],
|
||||||
|
's': getAverageOfRank("s")[1]["toEnterTR"],
|
||||||
|
's-': getAverageOfRank("s-")[1]["toEnterTR"],
|
||||||
|
'a+': getAverageOfRank("a+")[1]["toEnterTR"],
|
||||||
|
'a': getAverageOfRank("a")[1]["toEnterTR"],
|
||||||
|
'a-': getAverageOfRank("a-")[1]["toEnterTR"],
|
||||||
|
'b+': getAverageOfRank("b+")[1]["toEnterTR"],
|
||||||
|
'b': getAverageOfRank("b")[1]["toEnterTR"],
|
||||||
|
'b-': getAverageOfRank("b-")[1]["toEnterTR"],
|
||||||
|
'c+': getAverageOfRank("c+")[1]["toEnterTR"],
|
||||||
|
'c': getAverageOfRank("c")[1]["toEnterTR"],
|
||||||
|
'c-': getAverageOfRank("c-")[1]["toEnterTR"],
|
||||||
|
'd+': getAverageOfRank("d+")[1]["toEnterTR"],
|
||||||
|
'd': getAverageOfRank("d")[1]["toEnterTR"]
|
||||||
|
};
|
||||||
|
|
||||||
|
Map<String, double> get cutoffsGlicko => {
|
||||||
|
'x': getAverageOfRank("x")[1]["toEnterGlicko"],
|
||||||
|
'u': getAverageOfRank("u")[1]["toEnterGlicko"],
|
||||||
|
'ss': getAverageOfRank("ss")[1]["toEnterGlicko"],
|
||||||
|
's+': getAverageOfRank("s+")[1]["toEnterGlicko"],
|
||||||
|
's': getAverageOfRank("s")[1]["toEnterGlicko"],
|
||||||
|
's-': getAverageOfRank("s-")[1]["toEnterGlicko"],
|
||||||
|
'a+': getAverageOfRank("a+")[1]["toEnterGlicko"],
|
||||||
|
'a': getAverageOfRank("a")[1]["toEnterGlicko"],
|
||||||
|
'a-': getAverageOfRank("a-")[1]["toEnterGlicko"],
|
||||||
|
'b+': getAverageOfRank("b+")[1]["toEnterGlicko"],
|
||||||
|
'b': getAverageOfRank("b")[1]["toEnterGlicko"],
|
||||||
|
'b-': getAverageOfRank("b-")[1]["toEnterGlicko"],
|
||||||
|
'c+': getAverageOfRank("c+")[1]["toEnterGlicko"],
|
||||||
|
'c': getAverageOfRank("c")[1]["toEnterGlicko"],
|
||||||
|
'c-': getAverageOfRank("c-")[1]["toEnterGlicko"],
|
||||||
|
'd+': getAverageOfRank("d+")[1]["toEnterGlicko"],
|
||||||
|
'd': getAverageOfRank("d")[1]["toEnterGlicko"]
|
||||||
|
};
|
||||||
|
|
||||||
|
TetrioPlayersLeaderboard.fromJson(List<dynamic> json, String t, DateTime ts) {
|
||||||
|
type = t;
|
||||||
|
timestamp = ts;
|
||||||
|
leaderboard = [];
|
||||||
|
for (Map<String, dynamic> entry in json) {
|
||||||
|
leaderboard.add(TetrioPlayerFromLeaderboard.fromJson(entry, ts));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addPlayers(List<TetrioPlayerFromLeaderboard> list){
|
||||||
|
leaderboard.addAll(list);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
|
class TetrioZen {
|
||||||
|
late int level;
|
||||||
|
late int score;
|
||||||
|
|
||||||
|
TetrioZen({required this.level, required this.score});
|
||||||
|
|
||||||
|
double get scoreRequirement => (10000 + 10000 * ((log(level + 1) / log(2)) - 1));
|
||||||
|
|
||||||
|
TetrioZen.fromJson(Map<String, dynamic> json) {
|
||||||
|
level = json['level'];
|
||||||
|
score = json['score'];
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
|
data['level'] = level;
|
||||||
|
data['score'] = score;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
import 'package:tetra_stats/data_objects/record_single.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_zen.dart';
|
||||||
|
|
||||||
|
class UserRecords{
|
||||||
|
String id;
|
||||||
|
RecordSingle? sprint;
|
||||||
|
RecordSingle? blitz;
|
||||||
|
TetrioZen zen;
|
||||||
|
|
||||||
|
UserRecords(this.id, this.sprint, this.blitz, this.zen);
|
||||||
|
}
|
|
@ -0,0 +1,36 @@
|
||||||
|
// ignore_for_file: hash_and_equals
|
||||||
|
|
||||||
|
class ZenithResults{
|
||||||
|
late double altitude;
|
||||||
|
late double rank;
|
||||||
|
late double peakrank;
|
||||||
|
late double avgrankpts;
|
||||||
|
late int floor;
|
||||||
|
late double targetingfactor;
|
||||||
|
late double targetinggrace;
|
||||||
|
late double totalbonus;
|
||||||
|
late int revives;
|
||||||
|
late int revivesTotal;
|
||||||
|
late bool speedrun;
|
||||||
|
late bool speedrunSeen;
|
||||||
|
late List<Duration> splits;
|
||||||
|
|
||||||
|
ZenithResults.fromJson(Map<String, dynamic> json){
|
||||||
|
altitude = json['altitude'].toDouble();
|
||||||
|
rank = json['rank'].toDouble();
|
||||||
|
peakrank = json['peakrank'].toDouble();
|
||||||
|
avgrankpts = json['avgrankpts'].toDouble();
|
||||||
|
floor = json['floor'];
|
||||||
|
targetingfactor = json['targetingfactor'].toDouble();
|
||||||
|
targetinggrace = json['targetinggrace'].toDouble();
|
||||||
|
totalbonus = json['totalbonus'].toDouble();
|
||||||
|
revives = json['revives'];
|
||||||
|
revivesTotal = json['revivesTotal'];
|
||||||
|
speedrun = json['speedrun'];
|
||||||
|
speedrunSeen = json['speedrun_seen'];
|
||||||
|
splits = [];
|
||||||
|
for (int ms in json['splits']) {
|
||||||
|
splits.add(Duration(milliseconds: ms));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -16,7 +16,7 @@ import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||||
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
|
import 'package:sqflite_common_ffi_web/sqflite_ffi_web.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||||
import 'package:tetra_stats/views/main_view.dart';
|
import 'package:tetra_stats/views/main_view_tiles.dart';
|
||||||
import 'package:tetra_stats/views/settings_view.dart';
|
import 'package:tetra_stats/views/settings_view.dart';
|
||||||
import 'package:tetra_stats/views/tracked_players_view.dart';
|
import 'package:tetra_stats/views/tracked_players_view.dart';
|
||||||
import 'package:tetra_stats/views/calc_view.dart';
|
import 'package:tetra_stats/views/calc_view.dart';
|
||||||
|
|
|
@ -5,17 +5,32 @@ import 'dart:convert';
|
||||||
import 'dart:developer' as developer;
|
import 'dart:developer' as developer;
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:sqflite/sql.dart';
|
|
||||||
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
import 'package:sqflite_common_ffi/sqflite_ffi.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetra_stats.dart';
|
import 'package:tetra_stats/data_objects/cutoff_tetrio.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/end_context_multi.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/news.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/p1nkl0bst3r.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/player_leaderboard_position.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/record_single.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/singleplayer_stream.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/summaries.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league_alpha_record.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league_alpha_stream.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league_beta_stream.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio_multiplayer_replay.dart';
|
import 'package:tetra_stats/data_objects/tetrio_multiplayer_replay.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_player.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_player_from_leaderboard.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_players_leaderboard.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_zen.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/user_records.dart';
|
||||||
import 'package:tetra_stats/main.dart' show packageInfo;
|
import 'package:tetra_stats/main.dart' show packageInfo;
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:tetra_stats/services/custom_http_client.dart';
|
import 'package:tetra_stats/services/custom_http_client.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:tetra_stats/services/crud_exceptions.dart';
|
import 'package:tetra_stats/services/crud_exceptions.dart';
|
||||||
import 'package:tetra_stats/services/sqlite_db_controller.dart';
|
import 'package:tetra_stats/services/sqlite_db_controller.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
|
||||||
import 'package:csv/csv.dart';
|
import 'package:csv/csv.dart';
|
||||||
|
|
||||||
const String dbName = "TetraStats.db";
|
const String dbName = "TetraStats.db";
|
||||||
|
|
|
@ -2,7 +2,9 @@ import 'dart:io';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.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/est_tr.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/nerd_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/playstyle.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/widgets/graphs.dart';
|
import 'package:tetra_stats/widgets/graphs.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
|
@ -5,7 +5,10 @@ import 'dart:math';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.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/summaries.dart';
|
||||||
|
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';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/main.dart' show teto;
|
import 'package:tetra_stats/main.dart' show teto;
|
||||||
import 'package:tetra_stats/utils/relative_timestamps.dart';
|
import 'package:tetra_stats/utils/relative_timestamps.dart';
|
||||||
|
|
|
@ -11,8 +11,25 @@ import 'package:intl/intl.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetra_stats.dart';
|
import 'package:tetra_stats/data_objects/beta_record.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/distinguishment.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/news.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/news_entry.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/player_leaderboard_position.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/record_extras.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/record_single.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/singleplayer_stream.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/summaries.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league_alpha_record.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league_alpha_stream.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league_beta_stream.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/p1nkl0bst3r.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_player.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_player_from_leaderboard.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_players_leaderboard.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_zen.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/main.dart' show prefs, teto;
|
import 'package:tetra_stats/main.dart' show prefs, teto;
|
||||||
import 'package:tetra_stats/services/crud_exceptions.dart';
|
import 'package:tetra_stats/services/crud_exceptions.dart';
|
||||||
|
@ -338,7 +355,7 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: _showSearchBar ? SearchBox(onSubmit: changePlayer, bigScreen: MediaQuery.of(context).size.width > 768) : Text(title, style: const TextStyle(shadows: textShadow)),
|
title: _showSearchBar ? SearchBox(onSubmit: changePlayer, bigScreen: MediaQuery.of(context).size.width > 768) : Text(title, style: const TextStyle(shadows: textShadow)),
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
actions: widget.player == null ? [ // search bar and PopupMenuButton hidden if player provided TODO: Subject to change
|
actions: widget.player == null ? [ // search bar and PopupMenuButton hidden if player provided
|
||||||
_showSearchBar
|
_showSearchBar
|
||||||
? IconButton(
|
? IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
@ -1555,7 +1572,7 @@ class _OtherThingy extends StatelessWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text(t.bio, style: TextStyle(fontFamily: "Eurostile Round Extended",fontSize: bigScreen ? 42 : 28)),
|
Text(t.bio, style: TextStyle(fontFamily: "Eurostile Round Extended",fontSize: bigScreen ? 42 : 28)),
|
||||||
MarkdownBody(data: bio!, styleSheet: MarkdownStyleSheet(textScaleFactor: 1.5, textAlign: WrapAlignment.center)) // Text(bio!, style: const TextStyle(fontSize: 18)),
|
MarkdownBody(data: bio!, styleSheet: MarkdownStyleSheet(textScaler: TextScaler.linear(1.5), textAlign: WrapAlignment.center)) // Text(bio!, style: const TextStyle(fontSize: 18)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -6,7 +6,23 @@ import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||||
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetra_stats.dart';
|
import 'package:tetra_stats/data_objects/badge.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/beta_record.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/distinguishment.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/est_tr.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/nerd_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/news.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/news_entry.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/p1nkl0bst3r.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/playstyle.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/record_extras.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/record_single.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/singleplayer_stream.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/summaries.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league_beta_stream.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_player.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/services/crud_exceptions.dart';
|
import 'package:tetra_stats/services/crud_exceptions.dart';
|
||||||
import 'package:tetra_stats/utils/colors_functions.dart';
|
import 'package:tetra_stats/utils/colors_functions.dart';
|
||||||
|
@ -20,9 +36,7 @@ import 'package:tetra_stats/widgets/graphs.dart';
|
||||||
import 'package:tetra_stats/widgets/lineclears_thingy.dart';
|
import 'package:tetra_stats/widgets/lineclears_thingy.dart';
|
||||||
import 'package:tetra_stats/widgets/list_tile_trailing_stats.dart';
|
import 'package:tetra_stats/widgets/list_tile_trailing_stats.dart';
|
||||||
import 'package:tetra_stats/widgets/sp_trailing_stats.dart';
|
import 'package:tetra_stats/widgets/sp_trailing_stats.dart';
|
||||||
import 'package:tetra_stats/widgets/stat_sell_num.dart';
|
|
||||||
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
|
||||||
import 'package:tetra_stats/main.dart';
|
import 'package:tetra_stats/main.dart';
|
||||||
import 'package:tetra_stats/widgets/tl_progress_bar.dart';
|
import 'package:tetra_stats/widgets/tl_progress_bar.dart';
|
||||||
import 'package:tetra_stats/widgets/user_thingy.dart';
|
import 'package:tetra_stats/widgets/user_thingy.dart';
|
||||||
|
@ -594,6 +608,35 @@ class RecordSummary extends StatelessWidget{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class LeagueCard extends StatelessWidget{
|
||||||
|
final TetraLeague league;
|
||||||
|
final bool showSeasonNumber;
|
||||||
|
|
||||||
|
const LeagueCard({super.key, required this.league, this.showSeasonNumber = false});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Card(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(20.0, 8.0, 20.0, 12.0),
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(showSeasonNumber ? "Season ${league.season}" : "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)),
|
||||||
|
Text("${league.apm != null ? f2.format(league.apm) : "-.--"} APM • ${league.pps != null ? f2.format(league.pps) : "-.--"} PPS • ${league.vs != null ? f2.format(league.vs) : "-.--"} VS • ${league.nerdStats != null ? f2.format(league.nerdStats!.app) : "-.--"} APP • ${league.nerdStats != null ? f2.format(league.nerdStats!.vsapm) : "-.--"} VS/APM", style: const TextStyle(color: Colors.grey))
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
class _DestinationHomeState extends State<DestinationHome> {
|
class _DestinationHomeState extends State<DestinationHome> {
|
||||||
Cards rightCard = Cards.overview;
|
Cards rightCard = Cards.overview;
|
||||||
CardMod cardMod = CardMod.info;
|
CardMod cardMod = CardMod.info;
|
||||||
|
@ -645,23 +688,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Card(
|
LeagueCard(league: summaries.league),
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(20.0, 8.0, 20.0, 12.0),
|
|
||||||
child: Center(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const 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: summaries.league, showPositions: true),
|
|
||||||
const Divider(color: Color.fromARGB(50, 158, 158, 158)),
|
|
||||||
Text("${summaries.league.apm != null ? f2.format(summaries.league.apm) : "-.--"} APM • ${summaries.league.pps != null ? f2.format(summaries.league.pps) : "-.--"} PPS • ${summaries.league.vs != null ? f2.format(summaries.league.vs) : "-.--"} VS • ${summaries.league.nerdStats != null ? f2.format(summaries.league.nerdStats!.app) : "-.--"} APP • ${summaries.league.nerdStats != null ? f2.format(summaries.league.nerdStats!.vsapm) : "-.--"} VS/APM", style: const TextStyle(color: Colors.grey))
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Row(
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
@ -840,6 +867,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Card(
|
Card(
|
||||||
|
//surfaceTintColor: rankColors[data.rank],
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(bottom: 4.0),
|
padding: const EdgeInsets.only(bottom: 4.0),
|
||||||
child: Center(
|
child: Center(
|
||||||
|
@ -856,6 +884,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
||||||
),
|
),
|
||||||
TetraLeagueThingy(league: data, cutoffs: cutoffs),
|
TetraLeagueThingy(league: data, cutoffs: cutoffs),
|
||||||
if (data.nerdStats != null) Card(
|
if (data.nerdStats != null) Card(
|
||||||
|
//surfaceTintColor: rankColors[data.rank],
|
||||||
child: Row(
|
child: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
|
@ -871,6 +900,31 @@ class _DestinationHomeState extends State<DestinationHome> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget getPreviousSeasonsList(Map<int, TetraLeague> pastLeague){
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Card(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 4.0),
|
||||||
|
child: Center(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text("Previous Seasons", style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 42)),
|
||||||
|
//Text("${t.seasonStarts} ${countdown(postSeasonLeft)}", textAlign: TextAlign.center)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
for (var key in pastLeague.keys) Card(
|
||||||
|
child: LeagueCard(league: pastLeague[key]!, showSeasonNumber: true),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
Widget getListOfRecords(String recentStream, String topStream, BoxConstraints constraints){
|
Widget getListOfRecords(String recentStream, String topStream, BoxConstraints constraints){
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
|
@ -1373,6 +1427,10 @@ class _DestinationHomeState extends State<DestinationHome> {
|
||||||
value: CardMod.info,
|
value: CardMod.info,
|
||||||
label: Text('Standing'),
|
label: Text('Standing'),
|
||||||
),
|
),
|
||||||
|
const ButtonSegment<CardMod>(
|
||||||
|
value: CardMod.ex, // yeah i misusing my own Enum shut the fuck up
|
||||||
|
label: Text('Previous Seasons'),
|
||||||
|
),
|
||||||
const ButtonSegment<CardMod>(
|
const ButtonSegment<CardMod>(
|
||||||
value: CardMod.records,
|
value: CardMod.records,
|
||||||
label: Text('Recent Matches'),
|
label: Text('Recent Matches'),
|
||||||
|
@ -1436,10 +1494,10 @@ class _DestinationHomeState extends State<DestinationHome> {
|
||||||
Column(
|
Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Text(t.errors.noSuchUser, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 42, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
Text(snapshot.error.toString(), style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 42, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(top: 8.0),
|
padding: const EdgeInsets.only(top: 8.0),
|
||||||
child: Text(t.errors.noSuchUserSub, textAlign: TextAlign.center),
|
child: Text(snapshot.stackTrace.toString(), textAlign: TextAlign.center),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -1524,6 +1582,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
||||||
Cards.overview => getOverviewCard(snapshot.data!.summaries!),
|
Cards.overview => getOverviewCard(snapshot.data!.summaries!),
|
||||||
Cards.tetraLeague => switch (cardMod){
|
Cards.tetraLeague => switch (cardMod){
|
||||||
CardMod.info => getTetraLeagueCard(snapshot.data!.summaries!.league, snapshot.data!.cutoffs),
|
CardMod.info => getTetraLeagueCard(snapshot.data!.summaries!.league, snapshot.data!.cutoffs),
|
||||||
|
CardMod.ex => getPreviousSeasonsList(snapshot.data!.summaries!.pastLeague),
|
||||||
CardMod.records => getRecentTLrecords(widget.constraints),
|
CardMod.records => getRecentTLrecords(widget.constraints),
|
||||||
_ => const Center(child: Text("huh?"))
|
_ => const Center(child: Text("huh?"))
|
||||||
},
|
},
|
||||||
|
@ -1532,7 +1591,6 @@ class _DestinationHomeState extends State<DestinationHome> {
|
||||||
CardMod.records => getListOfRecords("zenith/recent", "zenith/top", widget.constraints),
|
CardMod.records => getListOfRecords("zenith/recent", "zenith/top", widget.constraints),
|
||||||
CardMod.ex => getZenithCard(snapshot.data?.summaries!.zenithEx),
|
CardMod.ex => getZenithCard(snapshot.data?.summaries!.zenithEx),
|
||||||
CardMod.exRecords => getListOfRecords("zenithex/recent", "zenithex/top", widget.constraints),
|
CardMod.exRecords => getListOfRecords("zenithex/recent", "zenithex/top", widget.constraints),
|
||||||
_ => const Center(child: Text("huh?"))
|
|
||||||
},
|
},
|
||||||
Cards.sprint => switch (cardMod){
|
Cards.sprint => switch (cardMod){
|
||||||
CardMod.info => getRecordCard(snapshot.data?.summaries!.sprint, sprintBetterThanRankAverage, closestAverageSprint, sprintBetterThanClosestAverage, snapshot.data!.summaries!.league.rank),
|
CardMod.info => getRecordCard(snapshot.data?.summaries!.sprint, sprintBetterThanRankAverage, closestAverageSprint, sprintBetterThanClosestAverage, snapshot.data!.summaries!.league.rank),
|
||||||
|
@ -2356,6 +2414,7 @@ class TetraLeagueThingy extends StatelessWidget{
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Card(
|
return Card(
|
||||||
|
//surfaceTintColor: rankColors[league.rank],
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
TLRatingThingy(userID: "w", tlData: league),
|
TLRatingThingy(userID: "w", tlData: league),
|
||||||
|
|
|
@ -3,7 +3,9 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/gestures.dart';
|
import 'package:flutter/gestures.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_constants.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_player_from_leaderboard.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_players_leaderboard.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' show MainView;
|
import 'package:tetra_stats/views/main_view.dart' show MainView;
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/cutoff_tetrio.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
import 'package:tetra_stats/utils/text_shadow.dart';
|
import 'package:tetra_stats/utils/text_shadow.dart';
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/tetrio_player.dart';
|
||||||
import 'package:tetra_stats/main.dart' show packageInfo, teto, prefs;
|
import 'package:tetra_stats/main.dart' show packageInfo, teto, prefs;
|
||||||
import 'package:file_selector/file_selector.dart';
|
import 'package:file_selector/file_selector.dart';
|
||||||
import 'package:file_picker/file_picker.dart';
|
import 'package:file_picker/file_picker.dart';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/record_single.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/widgets/singleplayer_record.dart';
|
import 'package:tetra_stats/widgets/singleplayer_record.dart';
|
||||||
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:io';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.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_constants.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/utils/relative_timestamps.dart';
|
import 'package:tetra_stats/utils/relative_timestamps.dart';
|
||||||
import 'package:tetra_stats/utils/text_shadow.dart';
|
import 'package:tetra_stats/utils/text_shadow.dart';
|
||||||
|
|
|
@ -2,11 +2,10 @@ import 'dart:io';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.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/tetra_league.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
||||||
import 'package:tetra_stats/widgets/tl_thingy.dart';
|
import 'package:tetra_stats/widgets/tl_thingy.dart';
|
||||||
import 'package:tetra_stats/widgets/user_thingy.dart';
|
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
|
final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
|
||||||
|
@ -41,13 +40,9 @@ class StateState extends State<StateView> {
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
void _justUpdate() {
|
|
||||||
setState(() {});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final t = Translations.of(context);
|
//final t = Translations.of(context);
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text("State from ${timestamp(widget.state.timestamp)}"),
|
title: Text("State from ${timestamp(widget.state.timestamp)}"),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/tetra_league.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/main.dart' show teto;
|
import 'package:tetra_stats/main.dart' show teto;
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'dart:io';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.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_constants.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/main.dart';
|
import 'package:tetra_stats/main.dart';
|
||||||
import 'package:tetra_stats/views/main_view.dart';
|
import 'package:tetra_stats/views/main_view.dart';
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
// ignore_for_file: use_build_context_synchronously, type_literal_in_constant_pattern
|
// ignore_for_file: use_build_context_synchronously, type_literal_in_constant_pattern
|
||||||
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'package:tetra_stats/data_objects/beta_league_round.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/beta_league_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/beta_record.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio_multiplayer_replay.dart';
|
import 'package:tetra_stats/data_objects/tetrio_multiplayer_replay.dart';
|
||||||
import 'package:tetra_stats/utils/relative_timestamps.dart';
|
import 'package:tetra_stats/utils/relative_timestamps.dart';
|
||||||
import 'package:tetra_stats/views/compare_view.dart' show CompareThingy;
|
import 'package:tetra_stats/views/compare_view.dart' show CompareThingy;
|
||||||
|
@ -10,7 +13,6 @@ import 'package:tetra_stats/widgets/vs_graphs.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.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/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/utils/open_in_browser.dart';
|
import 'package:tetra_stats/utils/open_in_browser.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
|
@ -2,12 +2,10 @@ import 'dart:io';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.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/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/main.dart' show teto;
|
import 'package:tetra_stats/main.dart' show teto;
|
||||||
import 'package:tetra_stats/utils/filesizes_converter.dart';
|
import 'package:tetra_stats/utils/filesizes_converter.dart';
|
||||||
import 'package:tetra_stats/views/states_view.dart';
|
import 'package:tetra_stats/views/states_view.dart';
|
||||||
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
late String oldWindowTitle;
|
late String oldWindowTitle;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/record_single.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
||||||
import 'package:tetra_stats/widgets/zenith_thingy.dart';
|
import 'package:tetra_stats/widgets/zenith_thingy.dart';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
// ignore_for_file: curly_braces_in_flow_control_structures
|
// ignore_for_file: curly_braces_in_flow_control_structures
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/finesse.dart';
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
import 'package:tetra_stats/utils/text_shadow.dart';
|
import 'package:tetra_stats/utils/text_shadow.dart';
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/leaderboard_position.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/utils/colors_functions.dart';
|
import 'package:tetra_stats/utils/colors_functions.dart';
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
|
|
|
@ -8,9 +8,11 @@ import 'package:fl_chart/src/chart/radar_chart/radar_chart_renderer.dart';
|
||||||
import 'package:fl_chart/src/chart/base/base_chart/base_chart_painter.dart';
|
import 'package:fl_chart/src/chart/base/base_chart/base_chart_painter.dart';
|
||||||
import 'package:fl_chart/src/utils/canvas_wrapper.dart';
|
import 'package:fl_chart/src/utils/canvas_wrapper.dart';
|
||||||
import 'package:fl_chart/src/utils/utils.dart';
|
import 'package:fl_chart/src/utils/utils.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/nerd_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/playstyle.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||||
import 'package:tetra_stats/main.dart' show prefs;
|
import 'package:tetra_stats/main.dart' show prefs;
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.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/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/clears.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
|
|
||||||
class LineclearsThingy extends StatelessWidget{
|
class LineclearsThingy extends StatelessWidget{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
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/record_single.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/singleplayer_stream.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/utils/relative_timestamps.dart';
|
import 'package:tetra_stats/utils/relative_timestamps.dart';
|
||||||
import 'package:tetra_stats/utils/text_shadow.dart';
|
import 'package:tetra_stats/utils/text_shadow.dart';
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
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/record_single.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/singleplayer_stream.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/utils/colors_functions.dart';
|
import 'package:tetra_stats/utils/colors_functions.dart';
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/record_single.dart';
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
import 'package:tetra_stats/utils/relative_timestamps.dart';
|
import 'package:tetra_stats/utils/relative_timestamps.dart';
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
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/leaderboard_position.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/utils/colors_functions.dart';
|
import 'package:tetra_stats/utils/colors_functions.dart';
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
|
|
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
||||||
import 'package:tetra_stats/data_objects/glicko.dart';
|
import 'package:tetra_stats/data_objects/glicko.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/tetra_league.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
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/tetra_league.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/main.dart' show prefs;
|
import 'package:tetra_stats/main.dart' show prefs;
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
import 'dart:async';
|
|
||||||
|
|
||||||
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/player_leaderboard_position.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_league.dart';
|
||||||
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/main.dart';
|
|
||||||
import 'package:tetra_stats/utils/colors_functions.dart';
|
import 'package:tetra_stats/utils/colors_functions.dart';
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
import 'package:tetra_stats/utils/relative_timestamps.dart';
|
|
||||||
import 'package:tetra_stats/widgets/gauget_num.dart';
|
import 'package:tetra_stats/widgets/gauget_num.dart';
|
||||||
import 'package:tetra_stats/widgets/graphs.dart';
|
import 'package:tetra_stats/widgets/graphs.dart';
|
||||||
import 'package:tetra_stats/widgets/stat_sell_num.dart';
|
import 'package:tetra_stats/widgets/stat_sell_num.dart';
|
||||||
|
@ -80,8 +77,6 @@ class _TLThingyState extends State<TLThingy> with TickerProviderStateMixin {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
if (widget.showTitle) Text(t.tetraLeague, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
if (widget.showTitle) Text(t.tetraLeague, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||||
//if (DateTime.now().isBefore(seasonEnd)) Text(t.seasonEnds(countdown: countdown(seasonLeft)))
|
|
||||||
//else Text(t.seasonEnded),
|
|
||||||
if (oldTl != null) Text(t.comparingWith(newDate: timestamp(currentTl.timestamp), oldDate: timestamp(oldTl!.timestamp)),
|
if (oldTl != null) Text(t.comparingWith(newDate: timestamp(currentTl.timestamp), oldDate: timestamp(oldTl!.timestamp)),
|
||||||
textAlign: TextAlign.center,),
|
textAlign: TextAlign.center,),
|
||||||
if (oldTl != null) RangeSlider(values: _currentRangeValues, max: widget.states.length.toDouble(),
|
if (oldTl != null) RangeSlider(values: _currentRangeValues, max: widget.states.length.toDouble(),
|
||||||
|
@ -95,7 +90,7 @@ class _TLThingyState extends State<TLThingy> with TickerProviderStateMixin {
|
||||||
if (values.start.round() == 0){
|
if (values.start.round() == 0){
|
||||||
currentTl = widget.tl;
|
currentTl = widget.tl;
|
||||||
}else{
|
}else{
|
||||||
currentTl = sortedStates[values.start.round()-1]!;
|
currentTl = sortedStates[values.start.round()-1];
|
||||||
}
|
}
|
||||||
if (values.end.round() == 0){
|
if (values.end.round() == 0){
|
||||||
oldTl = widget.tl;
|
oldTl = widget.tl;
|
||||||
|
@ -207,7 +202,6 @@ class _TLThingyState extends State<TLThingy> with TickerProviderStateMixin {
|
||||||
oldPlayerStat: oldTl?.nerdStats?.appdsp,),
|
oldPlayerStat: oldTl?.nerdStats?.appdsp,),
|
||||||
StatCellNum(playerStat: currentTl.nerdStats!.cheese, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.cheese,
|
StatCellNum(playerStat: currentTl.nerdStats!.cheese, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.cheese,
|
||||||
pos: widget.lbPositions?.cheese,
|
pos: widget.lbPositions?.cheese,
|
||||||
//averageStat: rankAverages?.nerdStats?.cheese, TODO: questonable
|
|
||||||
alertWidgets: [Text(t.statCellNum.cheeseDescription),
|
alertWidgets: [Text(t.statCellNum.cheeseDescription),
|
||||||
Text("${t.formula}: (DS/P * 150) + ((VS/APM - 2) * 50) + (0.6 - APP) * 125"),
|
Text("${t.formula}: (DS/P * 150) + ((VS/APM - 2) * 50) + (0.6 - APP) * 125"),
|
||||||
Text("${t.exactValue}: ${currentTl.nerdStats!.cheese}"),],
|
Text("${t.exactValue}: ${currentTl.nerdStats!.cheese}"),],
|
||||||
|
|
|
@ -2,7 +2,7 @@ import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/tetrio_player.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/main.dart' show teto;
|
import 'package:tetra_stats/main.dart' show teto;
|
||||||
import 'package:tetra_stats/views/compare_view.dart';
|
import 'package:tetra_stats/views/compare_view.dart';
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
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:tetra_stats/data_objects/nerd_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/playstyle.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||||
import 'package:tetra_stats/widgets/graphs.dart' show MyRadarChart;
|
import 'package:tetra_stats/widgets/graphs.dart' show MyRadarChart;
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
|
|
||||||
class VsGraphs extends StatelessWidget{
|
class VsGraphs extends StatelessWidget{
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/record_extras.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/record_single.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/utils/colors_functions.dart';
|
import 'package:tetra_stats/utils/colors_functions.dart';
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
|
|
Loading…
Reference in New Issue