2023-08-21 15:39:04 +00:00
// ignore_for_file: hash_and_equals
2023-06-17 21:50:52 +00:00
import ' dart:math ' ;
import ' package:flutter/foundation.dart ' ;
2023-07-11 17:02:35 +00:00
import ' package:flutter/material.dart ' ;
2023-08-28 19:42:35 +00:00
import ' package:tetra_stats/gen/strings.g.dart ' ;
2023-06-17 21:50:52 +00:00
import ' package:vector_math/vector_math.dart ' ;
2023-06-21 19:17:39 +00:00
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 ;
2024-04-20 22:37:31 +00:00
const List < String > ranks = [
" d " , " d+ " , " c- " , " c " , " c+ " , " b- " , " b " , " b+ " , " a- " , " a " , " a+ " , " s- " , " s " , " s+ " , " ss " , " u " , " x "
] ;
2023-07-11 17:02:35 +00:00
const Map < String , double > rankCutoffs = {
2023-07-09 16:50:17 +00:00
" 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 ,
2023-07-18 17:53:43 +00:00
" d " : 1 ,
2023-08-20 21:57:01 +00:00
" z " : - 1 ,
" " : 0.5
2023-07-09 16:50:17 +00:00
} ;
2024-03-13 22:44:53 +00:00
const Map < String , double > rankTargets = {
2024-04-29 22:45:11 +00:00
" x " : 24503.75 , // where that comes from?
2024-03-13 22:44:53 +00:00
" u " : 23038 ,
" ss " : 21583 ,
" s+ " : 20128 ,
" s " : 18673 ,
" s- " : 16975 ,
" a+ " : 15035 ,
" a " : 13095 ,
" a- " : 11155 ,
" b+ " : 9215 ,
" b " : 7275 ,
" b- " : 5335 ,
" c+ " : 3880 ,
" c " : 2425 ,
" c- " : 1213 ,
" d+ " : 606 ,
" d " : 0 ,
} ;
2023-08-28 19:42:35 +00:00
enum Stats {
tr ,
glicko ,
rd ,
gp ,
gw ,
wr ,
apm ,
pps ,
vs ,
app ,
dss ,
dsp ,
appdsp ,
vsapm ,
cheese ,
gbe ,
nyaapp ,
area ,
eTR ,
acceTR ,
2024-03-14 22:53:19 +00:00
acceTRabs ,
2023-08-28 19:42:35 +00:00
opener ,
plonk ,
infDS ,
stride ,
stridemMinusPlonk ,
openerMinusInfDS
}
2023-09-02 22:48:50 +00:00
const Map < Stats , String > chartsShortTitles = {
Stats . tr: " 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 " ,
2024-03-14 22:53:19 +00:00
Stats . acceTRabs: " +eTR absolute " ,
2023-09-02 22:48:50 +00:00
Stats . opener: " Opener " ,
Stats . plonk: " Plonk " ,
Stats . infDS: " Inf. DS " ,
Stats . stride: " Stride " ,
Stats . stridemMinusPlonk: " Stride - Plonk " ,
Stats . openerMinusInfDS: " Opener - Inf. DS "
} ;
2023-07-11 17:02:35 +00:00
const Map < String , Color > rankColors = { // thanks osk for const rankColors at https://ch.tetr.io/res/js/base.js:418
' 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 )
} ;
2024-05-28 21:05:01 +00:00
// const Map<String, Duration> sprintAverages = { // old data, based on https://discord.com/channels/673303546107658242/917098364787650590/1214231970259673098
// 'x': Duration(seconds: 25, milliseconds: 413),
// 'u': Duration(seconds: 34, milliseconds: 549),
// 'ss': Duration(seconds: 43, milliseconds: 373),
// 's+': Duration(seconds: 54, milliseconds: 027),
// 's': Duration(seconds: 60, milliseconds: 412),
// 's-': Duration(seconds: 67, milliseconds: 381),
// 'a+': Duration(seconds: 73, milliseconds: 694),
// 'a': Duration(seconds: 81, milliseconds: 166),
// 'a-': Duration(seconds: 88, milliseconds: 334),
// 'b+': Duration(seconds: 93, milliseconds: 741),
// 'b': Duration(seconds: 98, milliseconds: 354),
// 'b-': Duration(seconds: 109, milliseconds: 610),
// 'c+': Duration(seconds: 124, milliseconds: 641),
// 'c': Duration(seconds: 126, milliseconds: 104),
// 'c-': Duration(seconds: 145, milliseconds: 865),
// 'd+': Duration(seconds: 154, milliseconds: 338),
// 'd': Duration(seconds: 162, milliseconds: 063),
// //'z': Duration(seconds: 66, milliseconds: 802)
// };
// const Map<String, int> blitzAverages = {
// 'x': 626494,
// 'u': 406059,
// 'ss': 243166,
// 's+': 168636,
// 's': 121594,
// 's-': 107845,
// 'a+': 87142,
// 'a': 73413,
// 'a-': 60799,
// 'b+': 55417,
// 'b': 47608,
// 'b-': 40534,
// 'c+': 34200,
// 'c': 32535,
// 'c-': 25808,
// 'd+': 23345,
// 'd': 23063,
// //'z': 72084
// };
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 ) ,
2024-03-04 22:05:59 +00:00
//'z': Duration(seconds: 66, milliseconds: 802)
} ;
const Map < String , int > blitzAverages = {
2024-05-28 21:05:01 +00:00
' 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 ,
2024-03-04 22:05:59 +00:00
//'z': 72084
} ;
2023-08-28 19:42:35 +00:00
String getStatNameByEnum ( Stats stat ) {
return t [ stat . name ] ;
}
2023-06-21 19:17:39 +00:00
2023-06-17 21:50:52 +00:00
Duration doubleSecondsToDuration ( double value ) {
value = value * 1000000 ;
return Duration ( microseconds: value . floor ( ) ) ;
}
Duration doubleMillisecondsToDuration ( double value ) {
value = value * 1000 ;
return Duration ( microseconds: value . floor ( ) ) ;
}
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 ;
2023-07-18 17:53:43 +00:00
Connections ? connections ;
2023-06-17 21:50:52 +00:00
late TetraLeagueAlpha tlSeason1 ;
List < RecordSingle ? > sprint = [ ] ;
List < RecordSingle ? > blitz = [ ] ;
TetrioZen ? zen ;
Distinguishment ? distinguishment ;
2024-06-03 23:42:44 +00:00
DateTime ? cachedUntil ;
2023-06-17 21:50:52 +00:00
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 ,
required this . tlSeason1 ,
required this . sprint ,
required this . blitz ,
this . zen ,
this . distinguishment ,
2024-06-03 23:42:44 +00:00
this . cachedUntil
2023-06-17 21:50:52 +00:00
} ) ;
double get level = > pow ( ( xp / 500 ) , 0.6 ) + ( xp / ( 5000 + ( max ( 0 , xp - 4 * pow ( 10 , 6 ) ) / 5000 ) ) ) + 1 ;
2024-06-03 23:42:44 +00:00
TetrioPlayer . fromJson ( Map < String , dynamic > json , DateTime stateTime , String id , String nick , [ DateTime ? cUntil ] ) {
2023-06-17 21:50:52 +00:00
//developer.log("TetrioPlayer.fromJson $stateTime: $json", name: "data_objects/tetrio");
2023-07-18 17:53:43 +00:00
userId = id ;
username = nick ;
2023-06-17 21:50:52 +00:00
state = stateTime ;
2023-07-18 17:53:43 +00:00
role = json [ ' role ' ] ;
2023-06-17 21:50:52 +00:00
registrationTime = json [ ' ts ' ] ! = null ? DateTime . parse ( json [ ' ts ' ] ) : null ;
if ( json [ ' badges ' ] ! = null ) {
json [ ' badges ' ] . forEach ( ( v ) {
badges . add ( Badge . fromJson ( v ) ) ;
} ) ;
}
2023-07-18 17:53:43 +00:00
xp = json [ ' xp ' ] ! = null ? json [ ' xp ' ] . toDouble ( ) : - 1 ;
gamesPlayed = json [ ' gamesplayed ' ] ? ? - 1 ;
gamesWon = json [ ' gameswon ' ] ? ? - 1 ;
gameTime = json [ ' gametime ' ] ! = null & & json [ ' gametime ' ] ! = - 1 ? doubleSecondsToDuration ( json [ ' gametime ' ] . toDouble ( ) ) : const Duration ( seconds: - 1 ) ;
2023-06-17 21:50:52 +00:00
country = json [ ' country ' ] ;
2023-07-18 17:53:43 +00:00
supporterTier = json [ ' supporter_tier ' ] ? ? 0 ;
verified = json [ ' verified ' ] ? ? false ;
2023-06-28 16:50:40 +00:00
tlSeason1 = TetraLeagueAlpha . fromJson ( json [ ' league ' ] , stateTime ) ;
2023-06-17 21:50:52 +00:00
avatarRevision = json [ ' avatar_revision ' ] ;
bannerRevision = json [ ' banner_revision ' ] ;
bio = json [ ' bio ' ] ;
2023-07-18 17:53:43 +00:00
if ( json [ ' connections ' ] ! = null & & json [ ' connections ' ] . isNotEmpty ) connections = Connections . fromJson ( json [ ' connections ' ] ) ;
2023-06-17 21:50:52 +00:00
distinguishment = json [ ' distinguishment ' ] ! = null ? Distinguishment . fromJson ( json [ ' distinguishment ' ] ) : null ;
friendCount = json [ ' friend_count ' ] ? ? 0 ;
badstanding = json [ ' badstanding ' ] ;
botmaster = json [ ' botmaster ' ] ;
2024-06-03 23:42:44 +00:00
cachedUntil = cUntil ;
2023-06-17 21:50:52 +00:00
}
Map < String , dynamic > toJson ( ) {
final Map < String , dynamic > data = < String , dynamic > { } ;
2023-07-18 17:53:43 +00:00
// data['_id'] = userId;
// data['username'] = username;
2023-06-17 21:50:52 +00:00
data [ ' role ' ] = role ;
if ( registrationTime ! = null ) data [ ' ts ' ] = registrationTime ? . toString ( ) ;
2023-07-18 17:53:43 +00:00
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 ;
2023-06-17 21:50:52 +00:00
if ( country ! = null ) data [ ' country ' ] = country ;
2023-07-18 17:53:43 +00:00
if ( supporterTier > 0 ) data [ ' supporter_tier ' ] = supporterTier ;
if ( verified ) data [ ' verified ' ] = verified ;
2023-06-17 21:50:52 +00:00
data [ ' league ' ] = tlSeason1 . toJson ( ) ;
if ( distinguishment ! = null ) data [ ' distinguishment ' ] = distinguishment ? . toJson ( ) ;
if ( avatarRevision ! = null ) data [ ' avatar_revision ' ] = avatarRevision ;
if ( bannerRevision ! = null ) data [ ' banner_revision ' ] = bannerRevision ;
2023-07-18 17:53:43 +00:00
if ( bio ! = null ) data [ ' bio ' ] = bio ;
if ( connections ! = null ) data [ ' connections ' ] = connections ! . toJson ( ) ;
if ( friendCount > 0 ) data [ ' friend_count ' ] = friendCount ;
2023-06-17 21:50:52 +00:00
if ( badstanding ! = null ) data [ ' badstanding ' ] = badstanding ;
if ( botmaster ! = null ) data [ ' botmaster ' ] = botmaster ;
//developer.log("TetrioPlayer.toJson: $data", name: "data_objects/tetrio");
return data ;
}
2023-07-17 17:57:24 +00:00
bool isSameState ( covariant TetrioPlayer other ) {
2023-06-17 21:50:52 +00:00
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 ( tlSeason1 ! = other . tlSeason1 ) return false ;
if ( distinguishment ! = other . distinguishment ) return false ;
return true ;
}
2023-07-17 17:57:24 +00:00
bool checkForRetrivedHistory ( covariant TetrioPlayer other ) {
return tlSeason1 . lessStrictCheck ( other . tlSeason1 ) ;
}
2024-03-07 23:06:35 +00:00
TetrioPlayerFromLeaderboard convertToPlayerFromLeaderboard ( ) = > TetrioPlayerFromLeaderboard (
userId , username , role , xp , country , supporterTier > 0 , verified , state , gamesPlayed , gamesWon ,
tlSeason1 . rating , tlSeason1 . glicko ? ? 0 , tlSeason1 . rd ? ? noTrRd , tlSeason1 . rank , tlSeason1 . bestRank , tlSeason1 . apm ? ? 0 , tlSeason1 . pps ? ? 0 , tlSeason1 . vs ? ? 0 , tlSeason1 . decaying ) ;
2023-06-17 21:50:52 +00:00
@ override
String toString ( ) {
return " $ username ( $ state ) " ;
}
2023-08-28 19:42:35 +00:00
num ? getStatByEnum ( Stats stat ) {
switch ( stat ) {
case Stats . tr:
return tlSeason1 . rating ;
case Stats . glicko:
return tlSeason1 . glicko ;
case Stats . rd:
return tlSeason1 . rd ;
case Stats . gp:
return tlSeason1 . gamesPlayed ;
case Stats . gw:
return tlSeason1 . gamesWon ;
case Stats . wr:
return tlSeason1 . winrate ;
case Stats . apm:
return tlSeason1 . apm ;
case Stats . pps:
return tlSeason1 . pps ;
case Stats . vs:
return tlSeason1 . vs ;
case Stats . app:
return tlSeason1 . nerdStats ? . app ;
case Stats . dss:
return tlSeason1 . nerdStats ? . dss ;
case Stats . dsp:
return tlSeason1 . nerdStats ? . dsp ;
case Stats . appdsp:
return tlSeason1 . nerdStats ? . appdsp ;
case Stats . vsapm:
return tlSeason1 . nerdStats ? . vsapm ;
case Stats . cheese:
return tlSeason1 . nerdStats ? . cheese ;
case Stats . gbe:
return tlSeason1 . nerdStats ? . gbe ;
case Stats . nyaapp:
return tlSeason1 . nerdStats ? . nyaapp ;
case Stats . area:
return tlSeason1 . nerdStats ? . area ;
case Stats . eTR:
return tlSeason1 . estTr ? . esttr ;
case Stats . acceTR:
return tlSeason1 . esttracc ;
2024-03-14 22:53:19 +00:00
case Stats . acceTRabs:
return tlSeason1 . esttracc ? . abs ( ) ;
2023-08-28 19:42:35 +00:00
case Stats . opener:
return tlSeason1 . playstyle ? . opener ;
case Stats . plonk:
return tlSeason1 . playstyle ? . plonk ;
case Stats . infDS:
return tlSeason1 . playstyle ? . infds ;
case Stats . stride:
return tlSeason1 . playstyle ? . stride ;
case Stats . stridemMinusPlonk:
return tlSeason1 . playstyle ! = null ? tlSeason1 . playstyle ! . stride - tlSeason1 . playstyle ! . plonk : null ;
case Stats . openerMinusInfDS:
return tlSeason1 . playstyle ! = null ? tlSeason1 . playstyle ! . opener - tlSeason1 . playstyle ! . infds : null ;
}
}
2023-06-17 21:50:52 +00:00
@ override
int get hashCode = > state . hashCode ;
@ override
2023-06-19 20:42:37 +00:00
bool operator = = ( covariant TetrioPlayer other ) = > isSameState ( other ) & & state . isAtSameMomentAs ( other . state ) ;
2023-06-17 21:50:52 +00:00
}
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 ;
}
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 Clears {
late int singles ;
late int doubles ;
late int triples ;
late int quads ;
2024-01-03 23:02:50 +00:00
late int pentas ;
2023-06-17 21:50:52 +00:00
late int allClears ;
late int tSpinZeros ;
late int tSpinSingles ;
late int tSpinDoubles ;
late int tSpinTriples ;
late int tSpinQuads ;
2024-01-03 23:02:50 +00:00
late int tSpinPentas ;
2023-06-17 21:50:52 +00:00
late int tSpinMiniZeros ;
late int tSpinMiniSingles ;
late int tSpinMiniDoubles ;
Clears (
{ required this . singles ,
required this . doubles ,
required this . triples ,
required this . quads ,
2024-01-03 23:02:50 +00:00
required this . pentas ,
2023-06-17 21:50:52 +00:00
required this . allClears ,
required this . tSpinZeros ,
required this . tSpinSingles ,
required this . tSpinDoubles ,
required this . tSpinTriples ,
2024-01-03 23:02:50 +00:00
required this . tSpinPentas ,
2023-06-17 21:50:52 +00:00
required this . tSpinQuads ,
required this . tSpinMiniZeros ,
required this . tSpinMiniSingles ,
required this . tSpinMiniDoubles } ) ;
Clears . fromJson ( Map < String , dynamic > json ) {
singles = json [ ' singles ' ] ;
doubles = json [ ' doubles ' ] ;
triples = json [ ' triples ' ] ;
quads = json [ ' quads ' ] ;
2024-01-03 23:02:50 +00:00
pentas = json [ ' pentas ' ] ? ? 0 ;
2023-06-17 21:50:52 +00:00
tSpinZeros = json [ ' realtspins ' ] ;
tSpinMiniZeros = json [ ' minitspins ' ] ;
tSpinMiniSingles = json [ ' minitspinsingles ' ] ;
tSpinSingles = json [ ' tspinsingles ' ] ;
tSpinMiniDoubles = json [ ' minitspindoubles ' ] ;
tSpinDoubles = json [ ' tspindoubles ' ] ;
tSpinTriples = json [ ' tspintriples ' ] ;
tSpinQuads = json [ ' tspinquads ' ] ;
2024-01-03 23:02:50 +00:00
tSpinPentas = json [ ' tspinpentas ' ] ? ? 0 ;
2023-06-17 21:50:52 +00:00
allClears = json [ ' allclear ' ] ;
}
2024-01-04 23:04:05 +00:00
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
) ;
}
2023-06-17 21:50:52 +00:00
Map < String , dynamic > toJson ( ) {
final Map < String , dynamic > data = < String , dynamic > { } ;
data [ ' singles ' ] = singles ;
data [ ' doubles ' ] = doubles ;
data [ ' triples ' ] = triples ;
data [ ' quads ' ] = quads ;
2024-01-03 23:02:50 +00:00
data [ ' pentas ' ] = pentas ;
2023-06-17 21:50:52 +00:00
data [ ' realtspins ' ] = tSpinZeros ;
data [ ' minitspins ' ] = tSpinMiniZeros ;
data [ ' minitspinsingles ' ] = tSpinMiniSingles ;
data [ ' tspinsingles ' ] = tSpinSingles ;
data [ ' minitspindoubles ' ] = tSpinMiniDoubles ;
data [ ' tspindoubles ' ] = tSpinDoubles ;
data [ ' tspintriples ' ] = tSpinTriples ;
data [ ' tspinquads ' ] = tSpinQuads ;
2024-01-03 23:02:50 +00:00
data [ ' tspinpentas ' ] = tSpinPentas ;
2023-06-17 21:50:52 +00:00
data [ ' allclear ' ] = allClears ;
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 ;
}
}
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 ' ] ;
}
2024-01-04 23:04:05 +00:00
Finesse operator + ( Finesse other ) {
return Finesse ( combo: max ( combo , other . combo ) , faults: faults + other . faults , perfectPieces: perfectPieces + other . perfectPieces ) ;
}
2023-06-17 21:50:52 +00:00
Map < String , dynamic > toJson ( ) {
final Map < String , dynamic > data = < String , dynamic > { } ;
data [ ' combo ' ] = combo ;
data [ ' faults ' ] = faults ;
data [ ' perfectpieces ' ] = perfectPieces ;
return data ;
}
}
class EndContextSingle {
late String gameType ;
late int topBtB ;
late int topCombo ;
late int holds ;
late int inputs ;
late int level ;
late int piecesPlaced ;
late int lines ;
late int score ;
2023-06-26 17:13:53 +00:00
late double seed ;
2023-06-17 21:50:52 +00:00
late Duration finalTime ;
late int tSpins ;
late Clears clears ;
2024-01-16 22:55:21 +00:00
late Finesse ? finesse ;
2023-06-17 21:50:52 +00:00
double get pps = > piecesPlaced / ( finalTime . inMicroseconds / 1000000 ) ;
double get kpp = > inputs / piecesPlaced ;
double get spp = > score / piecesPlaced ;
double get kps = > inputs / ( finalTime . inMicroseconds / 1000000 ) ;
2024-01-16 22:55:21 +00:00
double get finessePercentage = > finesse ! = null ? finesse ! . perfectPieces / piecesPlaced : 0 ;
2023-06-17 21:50:52 +00:00
EndContextSingle (
{ required this . gameType ,
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 } ) ;
EndContextSingle . fromJson ( Map < String , dynamic > json ) {
2023-06-26 17:13:53 +00:00
seed = json [ ' seed ' ] . toDouble ( ) ;
2023-06-17 21:50:52 +00:00
lines = json [ ' lines ' ] ;
inputs = json [ ' inputs ' ] ;
holds = json [ ' holds ' ] ? ? 0 ;
finalTime = doubleMillisecondsToDuration ( json [ ' finalTime ' ] . toDouble ( ) ) ;
score = json [ ' score ' ] ;
level = json [ ' level ' ] ;
topCombo = json [ ' topcombo ' ] ;
topBtB = json [ ' topbtb ' ] ;
tSpins = json [ ' tspins ' ] ;
piecesPlaced = json [ ' piecesplaced ' ] ;
clears = Clears . fromJson ( json [ ' clears ' ] ) ;
2024-01-16 22:55:21 +00:00
finesse = json . containsKey ( " finesse " ) ? Finesse . fromJson ( json [ ' finesse ' ] ) : null ;
2023-06-17 21:50:52 +00:00
gameType = json [ ' gametype ' ] ;
}
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 ( ) ;
2024-01-16 22:55:21 +00:00
if ( finesse ! = null ) data [ ' finesse ' ] = finesse ! . toJson ( ) ;
2023-06-17 21:50:52 +00:00
data [ ' finalTime ' ] = finalTime ;
data [ ' gametype ' ] = gameType ;
return data ;
}
}
class Handling {
2023-06-20 20:53:28 +00:00
late num arr ;
late num das ;
late num sdf ;
late num dcd ;
2023-06-17 21:50:52 +00:00
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 > { } ;
2023-06-23 18:38:15 +00:00
data [ ' arr ' ] = arr . toDouble ( ) ;
data [ ' das ' ] = das . toDouble ( ) ;
data [ ' dcd ' ] = dcd . toDouble ( ) ;
data [ ' sdf ' ] = sdf . toDouble ( ) ;
2023-06-17 21:50:52 +00:00
data [ ' safelock ' ] = safeLock ;
data [ ' cancel ' ] = cancel ;
return data ;
}
}
class NerdStats {
final double _apm ;
final double _pps ;
final double _vs ;
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 ( this . _apm , this . _pps , this . _vs ) {
app = _apm / ( _pps * 60 ) ;
vsapm = _vs / _apm ;
dss = ( _vs / 100 ) - ( _apm / 60 ) ;
dsp = ( ( _vs / 100 ) - ( _apm / 60 ) ) / _pps ;
appdsp = app + dsp ;
2023-06-27 20:55:59 +00:00
cheese = ( dsp * 150 ) + ( ( vsapm - 2 ) * 50 ) + ( 0.6 - app ) * 125 ;
2024-01-22 18:00:24 +00:00
gbe = app * dsp * 2 ;
2023-06-17 21:50:52 +00:00
nyaapp = app - 5 * tan ( radians ( ( cheese / - 30 ) + 1 ) ) ;
area = _apm * 1 + _pps * 45 + _vs * 0.444 + app * 185 + dss * 175 + dsp * 450 + gbe * 315 ;
}
}
class EstTr {
final double _apm ;
final double _pps ;
final double _vs ;
final double _app ;
final double _dss ;
final double _dsp ;
final double _gbe ;
late double esttr ;
late double srarea ;
late double statrank ;
2023-06-28 16:50:40 +00:00
late double estglicko ;
2023-06-17 21:50:52 +00:00
2023-10-08 17:20:42 +00:00
EstTr ( this . _apm , this . _pps , this . _vs , this . _app , this . _dss , this . _dsp , this . _gbe ) {
2023-06-17 21:50:52 +00:00
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 ;
2024-05-02 22:26:12 +00:00
//estglicko = (4.0867 * srarea + 186.68);
2023-08-19 23:20:06 +00:00
double ntemp = _pps * ( 150 + ( ( ( _vs / _apm ) - 1.66 ) * 35 ) ) + _app * 290 + _dsp * 700 ;
2024-05-02 22:26:12 +00:00
estglicko = 0.000013 * pow ( ntemp , 3 ) - 0.0196 * pow ( ntemp , 2 ) + ( 12.645 * ntemp ) - 1005.4 ;
2023-08-19 23:20:06 +00:00
esttr = 25000 /
(
1 + pow ( 10 , (
(
(
2024-05-02 22:26:12 +00:00
1500 - estglicko
2023-08-19 23:20:06 +00:00
) * pi
) / sqrt (
(
(
3 * pow ( ln10 , 2 )
) * pow ( 60 , 2 )
) + (
2500 * (
( 64 * pow ( pi , 2 ) ) + ( 147 * pow ( ln10 , 2 ) )
)
)
)
) )
) ;
2023-06-17 21:50:52 +00:00
}
}
class Playstyle {
final double _apm ;
final double _pps ;
//final double _vs;
final double _app ;
final double _vsapm ;
//final double _dss;
final double _dsp ;
final double _gbe ;
final double _srarea ;
final double _statrank ;
late double opener ;
late double plonk ;
late double stride ;
late double infds ;
Playstyle ( this . _apm , this . _pps , this . _app , this . _vsapm , this . _dsp , this . _gbe , this . _srarea , this . _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 ;
}
}
2023-06-20 20:53:28 +00:00
class TetraLeagueAlphaStream {
late String userId ;
2023-06-23 18:38:15 +00:00
late List < TetraLeagueAlphaRecord > records ;
2023-06-20 20:53:28 +00:00
2023-06-23 18:38:15 +00:00
TetraLeagueAlphaStream ( { required this . userId , required this . records } ) ;
2023-06-20 20:53:28 +00:00
TetraLeagueAlphaStream . fromJson ( List < dynamic > json , String userID ) {
userId = userID ;
records = [ ] ;
2023-06-23 18:38:15 +00:00
for ( var value in json ) { records . add ( TetraLeagueAlphaRecord . fromJson ( value ) ) ; }
2023-06-20 20:53:28 +00:00
}
}
2024-06-12 22:32:45 +00:00
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 , null ) ) ; }
}
}
2023-06-20 20:53:28 +00:00
class TetraLeagueAlphaRecord {
late String replayId ;
late String ownId ;
2023-06-23 18:38:15 +00:00
late DateTime timestamp ;
2023-10-18 21:50:41 +00:00
late bool replayAvalable ;
2023-06-20 20:53:28 +00:00
late List < EndContextMulti > endContext ;
2023-10-18 21:50:41 +00:00
TetraLeagueAlphaRecord ( { required this . replayId , required this . ownId , required this . timestamp , required this . endContext , required this . replayAvalable } ) ;
2023-06-20 20:53:28 +00:00
TetraLeagueAlphaRecord . fromJson ( Map < String , dynamic > json ) {
endContext = [ EndContextMulti . fromJson ( json [ ' endcontext ' ] [ 0 ] ) , EndContextMulti . fromJson ( json [ ' endcontext ' ] [ 1 ] ) ] ;
replayId = json [ ' replayid ' ] ;
2024-07-10 15:31:00 +00:00
ownId = json [ ' _id ' ] ? ? replayId ;
2023-06-20 20:53:28 +00:00
timestamp = DateTime . parse ( json [ ' ts ' ] ) ;
2024-07-10 16:21:03 +00:00
replayAvalable = ownId ! = replayId ;
2023-06-20 20:53:28 +00:00
}
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 ;
}
2023-06-23 18:38:15 +00:00
@ override
2023-10-13 22:53:33 +00:00
bool operator = = ( covariant TetraLeagueAlphaRecord other ) = > ( ownId = = other . ownId ) | | ( replayId = = other . replayId ) ;
2023-06-23 18:38:15 +00:00
2023-06-20 20:53:28 +00:00
@ override
String toString ( ) {
return " TetraLeagueAlphaRecord: ${ endContext . first . userId } vs ${ endContext . last . userId } " ;
}
}
2023-06-17 21:50:52 +00:00
class EndContextMulti {
2023-06-21 19:17:39 +00:00
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 ;
2023-06-23 18:38:15 +00:00
late List secondaryTracking ;
2023-06-21 19:17:39 +00:00
late double tertiary ;
2023-06-23 18:38:15 +00:00
late List tertiaryTracking ;
2023-06-21 19:17:39 +00:00
late double extra ;
2023-06-23 18:38:15 +00:00
late List extraTracking ;
2023-06-21 19:17:39 +00:00
late bool success ;
late NerdStats nerdStats ;
2023-09-05 20:32:34 +00:00
late List < NerdStats > nerdStatsTracking ;
2023-06-21 19:17:39 +00:00
late EstTr estTr ;
2023-09-05 20:32:34 +00:00
late List < EstTr > estTrTracking ;
2023-06-21 19:17:39 +00:00
late Playstyle playstyle ;
2023-09-05 20:32:34 +00:00
late List < Playstyle > playstyleTracking ;
2023-06-17 21:50:52 +00:00
EndContextMulti (
2023-06-21 19:17:39 +00:00
{ 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 ,
2024-02-03 13:02:58 +00:00
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 ) ] ;
}
2023-06-17 21:50:52 +00:00
EndContextMulti . fromJson ( Map < String , dynamic > json ) {
2023-11-08 22:17:44 +00:00
userId = json [ ' id ' ] ? ? json [ ' user ' ] [ ' _id ' ] ;
username = json [ ' username ' ] ? ? json [ ' user ' ] [ ' username ' ] ;
2024-07-10 15:31:00 +00:00
handling = json [ ' handling ' ] ! = null ? Handling . fromJson ( json [ ' handling ' ] ) : Handling ( arr: - 1 , das: - 1 , sdf: - 1 , dcd: 0 , cancel: true , safeLock: true ) ;
2023-06-17 21:50:52 +00:00
success = json [ ' success ' ] ;
2024-07-10 15:31:00 +00:00
inputs = json [ ' inputs ' ] ? ? - 1 ;
piecesPlaced = json [ ' piecesplaced ' ] ? ? - 1 ;
2023-06-17 21:50:52 +00:00
naturalOrder = json [ ' naturalorder ' ] ;
wins = json [ ' wins ' ] ;
points = json [ ' points ' ] [ ' primary ' ] ;
2023-06-22 19:02:49 +00:00
secondary = json [ ' points ' ] [ ' secondary ' ] . toDouble ( ) ;
tertiary = json [ ' points ' ] [ ' tertiary ' ] . toDouble ( ) ;
2024-07-10 15:31:00 +00:00
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 ( ) : [ ] ;
2023-06-22 19:02:49 +00:00
extra = json [ ' points ' ] [ ' extra ' ] [ ' vs ' ] . toDouble ( ) ;
2024-07-10 15:31:00 +00:00
extraTracking = json [ ' points ' ] [ ' extraAvgTracking ' ] ! = null ? json [ ' points ' ] [ ' extraAvgTracking ' ] [ ' aggregatestats___vsscore ' ] . map ( ( e ) = > e . toDouble ( ) ) . toList ( ) : [ ] ;
2023-06-21 19:17:39 +00:00
nerdStats = NerdStats ( secondary , tertiary , extra ) ;
2023-09-05 20:32:34 +00:00
nerdStatsTracking = [ for ( int i = 0 ; i < secondaryTracking . length ; i + + ) NerdStats ( secondaryTracking [ i ] , tertiaryTracking [ i ] , extraTracking [ i ] ) ] ;
2023-10-08 17:20:42 +00:00
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 ) ] ;
2023-06-21 19:17:39 +00:00
playstyle = Playstyle ( secondary , tertiary , nerdStats . app , nerdStats . vsapm , nerdStats . dsp , nerdStats . gbe , estTr . srarea , estTr . statrank ) ;
2023-09-05 20:32:34 +00:00
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 ) ] ;
2023-06-17 21:50:52 +00:00
}
2024-01-05 23:11:45 +00:00
@ override
bool operator = = ( covariant EndContextMulti other ) {
if ( userId ! = other . userId ) return false ;
return true ;
}
2023-06-17 21:50:52 +00:00
Map < String , dynamic > toJson ( ) {
final Map < String , dynamic > data = < String , dynamic > { } ;
2023-06-23 18:38:15 +00:00
data [ ' user ' ] = { ' _id ' : userId , ' username ' : username } ;
2023-06-21 19:17:39 +00:00
data [ ' handling ' ] = handling . toJson ( ) ;
2023-06-17 21:50:52 +00:00
data [ ' success ' ] = success ;
data [ ' inputs ' ] = inputs ;
data [ ' piecesplaced ' ] = piecesPlaced ;
data [ ' naturalorder ' ] = naturalOrder ;
data [ ' wins ' ] = wins ;
2023-06-23 18:38:15 +00:00
data [ ' points ' ] = { ' primary ' : points , ' secondary ' : secondary , ' tertiary ' : tertiary , ' extra ' : { ' vs ' : extra } , ' secondaryAvgTracking ' : secondaryTracking , ' tertiaryAvgTracking ' : tertiaryTracking , ' extraAvgTracking ' : { ' aggregatestats___vsscore ' : extraTracking } } ;
2023-06-17 21:50:52 +00:00
return data ;
}
}
class TetraLeagueAlpha {
2023-06-28 16:50:40 +00:00
late DateTime timestamp ;
2023-06-17 21:50:52 +00:00
late int gamesPlayed ;
late int gamesWon ;
late String bestRank ;
late bool decaying ;
late double rating ;
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 ;
List ? records ;
TetraLeagueAlpha (
2023-07-17 17:57:24 +00:00
{ required this . timestamp ,
required this . gamesPlayed ,
2023-06-17 21:50:52 +00:00
required this . gamesWon ,
required this . bestRank ,
required this . decaying ,
required this . rating ,
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 ,
2023-07-06 12:48:04 +00:00
this . records } ) {
2023-07-18 17:53:43 +00:00
nerdStats = ( apm ! = null & & pps ! = null & & vs ! = null ) ? NerdStats ( apm ! , pps ! , vs ! ) : null ;
2023-10-08 17:20:42 +00:00
estTr = ( nerdStats ! = null ) ? EstTr ( apm ! , pps ! , vs ! , nerdStats ! . app , nerdStats ! . dss , nerdStats ! . dsp , nerdStats ! . gbe ) : null ;
2023-07-06 12:48:04 +00:00
playstyle = ( nerdStats ! = null ) ? Playstyle ( apm ! , pps ! , nerdStats ! . app , nerdStats ! . vsapm , nerdStats ! . dsp , nerdStats ! . gbe , estTr ! . srarea , estTr ! . statrank ) : null ;
}
2023-06-17 21:50:52 +00:00
double get winrate = > gamesWon / gamesPlayed ;
2023-06-28 16:50:40 +00:00
TetraLeagueAlpha . fromJson ( Map < String , dynamic > json , ts ) {
timestamp = ts ;
2023-07-18 17:53:43 +00:00
gamesPlayed = json [ ' gamesplayed ' ] ? ? 0 ;
gamesWon = json [ ' gameswon ' ] ? ? 0 ;
rating = json [ ' rating ' ] ! = null ? json [ ' rating ' ] . toDouble ( ) : - 1 ;
2023-06-17 21:50:52 +00:00
glicko = json [ ' glicko ' ] ? . toDouble ( ) ;
2023-07-18 17:53:43 +00:00
rd = json [ ' rd ' ] ! = null ? json [ ' rd ' ] ! . toDouble ( ) : noTrRd ;
rank = json [ ' rank ' ] ! = null ? json [ ' rank ' ] ! . toString ( ) : ' z ' ;
bestRank = json [ ' bestrank ' ] ! = null ? json [ ' bestrank ' ] ! . toString ( ) : ' z ' ;
2024-01-13 18:49:36 +00:00
apm = json [ ' apm ' ] ? . toDouble ( ) ;
pps = json [ ' pps ' ] ? . toDouble ( ) ;
vs = json [ ' vs ' ] ? . toDouble ( ) ;
2023-07-18 17:53:43 +00:00
decaying = json [ ' decaying ' ] ? ? false ;
standing = json [ ' standing ' ] ? ? - 1 ;
percentile = json [ ' percentile ' ] ! = null ? json [ ' percentile ' ] . toDouble ( ) : rankCutoffs [ rank ] ;
standingLocal = json [ ' standing_local ' ] ? ? - 1 ;
2023-06-17 21:50:52 +00:00
prevRank = json [ ' prev_rank ' ] ;
2023-07-18 17:53:43 +00:00
prevAt = json [ ' prev_at ' ] ? ? - 1 ;
2023-06-17 21:50:52 +00:00
nextRank = json [ ' next_rank ' ] ;
2023-07-18 17:53:43 +00:00
nextAt = json [ ' next_at ' ] ? ? - 1 ;
percentileRank = json [ ' percentile_rank ' ] ? ? rank ;
2023-07-09 16:50:17 +00:00
nerdStats = ( apm ! = null & & pps ! = null & & vs ! = null ) ? NerdStats ( apm ! , pps ! , vs ! ) : null ;
2023-10-08 17:20:42 +00:00
estTr = ( nerdStats ! = null ) ? EstTr ( apm ! , pps ! , vs ! , nerdStats ! . app , nerdStats ! . dss , nerdStats ! . dsp , nerdStats ! . gbe ) : null ;
2023-07-18 17:53:43 +00:00
playstyle = ( nerdStats ! = null ) ? Playstyle ( apm ! , pps ! , nerdStats ! . app , nerdStats ! . vsapm , nerdStats ! . dsp , nerdStats ! . gbe , estTr ! . srarea , estTr ! . statrank ) : null ;
2023-06-17 21:50:52 +00:00
}
@ override
bool operator = = ( covariant TetraLeagueAlpha other ) = > gamesPlayed = = other . gamesPlayed & & rd = = other . rd ;
2023-07-17 17:57:24 +00:00
bool lessStrictCheck ( covariant TetraLeagueAlpha other ) = > gamesPlayed = = other . gamesPlayed & & glicko = = other . glicko ;
2023-06-17 21:50:52 +00:00
double ? get esttracc = > ( estTr ! = null ) ? estTr ! . esttr - rating : null ;
Map < String , dynamic > toJson ( ) {
final Map < String , dynamic > data = < String , dynamic > { } ;
2023-07-18 17:53:43 +00:00
if ( gamesPlayed > 0 ) data [ ' gamesplayed ' ] = gamesPlayed ;
if ( gamesWon > 0 ) data [ ' gameswon ' ] = gamesWon ;
if ( rating > = 0 ) data [ ' rating ' ] = rating ;
2023-06-17 21:50:52 +00:00
if ( glicko ! = null ) data [ ' glicko ' ] = glicko ;
2023-07-18 17:53:43 +00:00
if ( rd ! = null & & rd ! = noTrRd ) data [ ' rd ' ] = rd ;
if ( rank ! = ' z ' ) data [ ' rank ' ] = rank ;
if ( bestRank ! = ' z ' ) data [ ' bestrank ' ] = bestRank ;
2023-06-17 21:50:52 +00:00
if ( apm ! = null ) data [ ' apm ' ] = apm ;
if ( pps ! = null ) data [ ' pps ' ] = pps ;
if ( vs ! = null ) data [ ' vs ' ] = vs ;
2023-07-18 17:53:43 +00:00
if ( decaying ) data [ ' decaying ' ] = decaying ;
if ( standing > = 0 ) data [ ' standing ' ] = standing ;
if ( ! rankCutoffs . containsValue ( percentile ) ) data [ ' percentile ' ] = percentile ;
if ( standingLocal > = 0 ) data [ ' standing_local ' ] = standingLocal ;
2023-06-17 21:50:52 +00:00
if ( prevRank ! = null ) data [ ' prev_rank ' ] = prevRank ;
2023-07-18 17:53:43 +00:00
if ( prevAt > = 0 ) data [ ' prev_at ' ] = prevAt ;
2023-06-17 21:50:52 +00:00
if ( nextRank ! = null ) data [ ' next_rank ' ] = nextRank ;
2023-07-18 17:53:43 +00:00
if ( nextAt > = 0 ) data [ ' next_at ' ] = nextAt ;
if ( percentileRank ! = rank ) data [ ' percentile_rank ' ] = percentileRank ;
2023-06-17 21:50:52 +00:00
return data ;
}
}
class RecordSingle {
late String userId ;
late String replayId ;
late String ownId ;
2024-06-12 22:32:45 +00:00
late DateTime timestamp ;
late EndContextSingle endContext ;
2023-06-17 21:50:52 +00:00
int ? rank ;
2024-06-12 22:32:45 +00:00
RecordSingle ( { required this . userId , required this . replayId , required this . ownId , required this . timestamp , required this . endContext , this . rank } ) ;
2023-06-17 21:50:52 +00:00
RecordSingle . fromJson ( Map < String , dynamic > json , int ? ran ) {
//developer.log("RecordSingle.fromJson: $json", name: "data_objects/tetrio");
ownId = json [ ' _id ' ] ;
2024-06-12 22:32:45 +00:00
endContext = EndContextSingle . fromJson ( json [ ' endcontext ' ] ) ;
2023-06-17 21:50:52 +00:00
replayId = json [ ' replayid ' ] ;
timestamp = DateTime . parse ( json [ ' ts ' ] ) ;
userId = json [ ' user ' ] [ ' _id ' ] ;
rank = ran ;
}
Map < String , dynamic > toJson ( ) {
final Map < String , dynamic > data = < String , dynamic > { } ;
data [ ' _id ' ] = ownId ;
2024-06-12 22:32:45 +00:00
data [ ' endcontext ' ] = endContext . toJson ( ) ;
2023-06-17 21:50:52 +00:00
data [ ' ismulti ' ] = false ;
data [ ' replayid ' ] = replayId ;
data [ ' ts ' ] = timestamp ;
data [ ' user_id ' ] = userId ;
return data ;
}
}
class TetrioZen {
late int level ;
late int score ;
TetrioZen ( { required this . level , required this . score } ) ;
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 ;
}
}
2024-06-03 21:06:00 +00:00
class UserRecords {
String id ;
RecordSingle ? sprint ;
RecordSingle ? blitz ;
TetrioZen zen ;
UserRecords ( this . id , this . sprint , this . blitz , this . zen ) ;
}
2023-06-17 21:50:52 +00:00
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 ;
}
}
2024-06-03 21:06:00 +00:00
class News {
2023-10-07 16:44:54 +00:00
late String id ;
2024-06-03 21:06:00 +00:00
late List < NewsEntry > news ;
News ( this . id , this . news ) ;
News . fromJson ( Map < String , dynamic > json , String ? userID ) {
2024-06-16 21:04:07 +00:00
id = userID ! = null ? " user_ $ userID " : json [ ' news ' ] . first [ ' stream ' ] ;
2024-06-03 21:06:00 +00:00
news = [ for ( var entry in json [ ' news ' ] ) NewsEntry . fromJson ( entry ) ] ;
}
}
class NewsEntry {
//late String id; do i need it?
2023-10-07 16:44:54 +00:00
late String type ;
late Map < String , dynamic > data ;
late DateTime timestamp ;
2024-06-03 21:06:00 +00:00
NewsEntry ( { required this . type , required this . data , required this . timestamp } ) ;
2023-10-07 16:44:54 +00:00
2024-06-03 21:06:00 +00:00
NewsEntry . fromJson ( Map < String , dynamic > json ) {
//id = json["_id"];
2023-10-07 16:44:54 +00:00
type = json [ " type " ] ;
data = json [ " data " ] ;
timestamp = DateTime . parse ( json [ ' ts ' ] ) ;
}
}
2024-03-06 22:34:15 +00:00
class PlayerLeaderboardPosition {
2024-03-07 23:06:35 +00:00
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 ;
2024-03-06 22:34:15 +00:00
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
} ) ;
2024-03-07 23:06:35 +00:00
PlayerLeaderboardPosition . fromSearchResults ( List < LeaderboardPosition ? > results ) {
2024-03-06 22:34:15 +00:00
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 ] ;
}
}
class LeaderboardPosition {
int position ;
double percentage ;
LeaderboardPosition ( this . position , this . percentage ) ;
}
2023-06-17 21:50:52 +00:00
class TetrioPlayersLeaderboard {
late String type ;
2023-06-28 16:50:40 +00:00
late DateTime timestamp ;
2023-06-17 21:50:52 +00:00
late List < TetrioPlayerFromLeaderboard > leaderboard ;
TetrioPlayersLeaderboard ( this . type , this . leaderboard ) ;
2023-09-02 22:48:50 +00:00
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 ) {
2024-05-17 15:16:24 +00:00
if ( a . getStatByEnum ( stat ) . isNaN ) return 1 ;
if ( b . getStatByEnum ( stat ) . isNaN ) return - 1 ;
2023-09-02 22:48:50 +00:00
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 ;
2023-08-28 19:42:35 +00:00
}
List < dynamic > getAverageOfRank ( String rank ) { // i tried to refactor it and that's was terrible
2023-07-29 18:01:49 +00:00
if ( rank . isNotEmpty & & ! rankCutoffs . keys . contains ( rank ) ) throw Exception ( " Invalid rank " ) ;
2023-07-09 16:50:17 +00:00
List < TetrioPlayerFromLeaderboard > filtredLeaderboard = List . from ( leaderboard ) ;
2023-07-29 18:01:49 +00:00
if ( rank . isNotEmpty ) {
filtredLeaderboard . removeWhere ( ( element ) = > element . rank ! = rank ) ;
}
if ( filtredLeaderboard . isNotEmpty ) {
double avgAPM = 0 ,
avgPPS = 0 ,
avgVS = 0 ,
avgTR = 0 ,
avgGlicko = 0 ,
avgRD = 0 ,
2023-08-08 19:30:24 +00:00
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 ,
2023-07-29 18:01:49 +00:00
lowestTR = 25000 ,
lowestGlicko = double . infinity ,
2023-08-08 19:30:24 +00:00
lowestRD = double . infinity ,
2023-07-29 18:01:49 +00:00
lowestWinrate = double . infinity ,
lowestAPM = double . infinity ,
lowestPPS = double . infinity ,
lowestVS = double . infinity ,
2023-08-08 19:30:24 +00:00
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 ,
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 ;
2023-07-29 18:01:49 +00:00
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 = " " ,
lowestGlickoID = " " , lowestGlickoNick = " " ,
2023-08-08 19:30:24 +00:00
lowestRdID = " " , lowestRdNick = " " ,
2023-07-29 18:01:49 +00:00
lowestGamesPlayedID = " " , lowestGamesPlayedNick = " " ,
lowestGamesWonID = " " , lowestGamesWonNick = " " ,
lowestWinrateID = " " , lowestWinrateNick = " " ,
lowestAPMid = " " , lowestAPMnick = " " ,
lowestPPSid = " " , lowestPPSnick = " " ,
lowestVSid = " " , lowestVSnick = " " ,
2023-08-08 19:30:24 +00:00
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 = " " ,
2023-07-29 18:01:49 +00:00
highestTRid = " " , highestTRnick = " " ,
highestGlickoID = " " , highestGlickoNick = " " ,
2023-08-08 19:30:24 +00:00
highestRdID = " " , highestRdNick = " " ,
2023-07-29 18:01:49 +00:00
highestGamesPlayedID = " " , highestGamesPlayedNick = " " ,
highestGamesWonID = " " , highestGamesWonNick = " " ,
highestWinrateID = " " , highestWinrateNick = " " ,
highestAPMid = " " , highestAPMnick = " " ,
highestPPSid = " " , highestPPSnick = " " ,
2023-08-08 19:30:24 +00:00
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 = " " ;
2023-07-29 18:01:49 +00:00
for ( var entry in filtredLeaderboard ) {
avgAPM + = entry . apm ;
avgPPS + = entry . pps ;
avgVS + = entry . vs ;
avgTR + = entry . rating ;
avgGlicko + = entry . glicko ;
avgRD + = entry . rd ;
2023-08-08 19:30:24 +00:00
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 ;
2023-07-29 18:01:49 +00:00
totalGamesPlayed + = entry . gamesPlayed ;
totalGamesWon + = entry . gamesWon ;
if ( entry . rating < lowestTR ) {
lowestTR = entry . rating ;
lowestTRid = entry . userId ;
lowestTRnick = entry . username ;
}
if ( entry . glicko < lowestGlicko ) {
lowestGlicko = entry . glicko ;
lowestGlickoID = entry . userId ;
lowestGlickoNick = entry . username ;
}
2023-08-08 19:30:24 +00:00
if ( entry . rd < lowestRD ) {
lowestRD = entry . rd ;
lowestRdID = entry . userId ;
lowestRdNick = entry . username ;
}
2023-07-29 18:01:49 +00:00
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 ;
}
2023-08-08 19:30:24 +00:00
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 ;
}
2023-07-29 18:01:49 +00:00
if ( entry . rating > highestTR ) {
highestTR = entry . rating ;
highestTRid = entry . userId ;
highestTRnick = entry . username ;
}
if ( entry . glicko > highestGlicko ) {
highestGlicko = entry . glicko ;
highestGlickoID = entry . userId ;
highestGlickoNick = entry . username ;
}
2023-08-08 19:30:24 +00:00
if ( entry . rd > highestRD ) {
highestRD = entry . rd ;
highestRdID = entry . userId ;
highestRdNick = entry . username ;
}
2023-07-29 18:01:49 +00:00
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 ;
}
2023-08-08 19:30:24 +00:00
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 ;
}
2023-07-29 18:01:49 +00:00
}
avgAPM / = filtredLeaderboard . length ;
avgPPS / = filtredLeaderboard . length ;
avgVS / = filtredLeaderboard . length ;
avgTR / = filtredLeaderboard . length ;
avgGlicko / = filtredLeaderboard . length ;
avgRD / = filtredLeaderboard . length ;
2023-08-08 19:30:24 +00:00
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 ;
2023-07-29 18:01:49 +00:00
avgGamesPlayed = ( totalGamesPlayed / filtredLeaderboard . length ) . floor ( ) ;
avgGamesWon = ( totalGamesWon / filtredLeaderboard . length ) . floor ( ) ;
2023-08-20 21:57:01 +00:00
return [ TetraLeagueAlpha ( timestamp: DateTime . now ( ) , apm: avgAPM , pps: avgPPS , vs: avgVS , glicko: avgGlicko , rd: avgRD , gamesPlayed: avgGamesPlayed , gamesWon: avgGamesWon , bestRank: rank , decaying: false , rating: avgTR , rank: rank = = " " ? " z " : rank , percentileRank: rank , percentile: rankCutoffs [ rank ] ! , standing: - 1 , standingLocal: - 1 , nextAt: - 1 , prevAt: - 1 ) ,
2023-07-29 18:01:49 +00:00
{
2023-08-14 21:26:20 +00:00
" everyone " : rank = = " " ,
2023-07-29 18:01:49 +00:00
" totalGamesPlayed " : totalGamesPlayed ,
" totalGamesWon " : totalGamesWon ,
" players " : filtredLeaderboard . length ,
" lowestTR " : lowestTR ,
" lowestTRid " : lowestTRid ,
" lowestTRnick " : lowestTRnick ,
" lowestGlicko " : lowestGlicko ,
" lowestGlickoID " : lowestGlickoID ,
" lowestGlickoNick " : lowestGlickoNick ,
2023-08-08 19:30:24 +00:00
" lowestRD " : lowestRD ,
" lowestRdID " : lowestRdID ,
" lowestRdNick " : lowestRdNick ,
2023-07-29 18:01:49 +00:00
" 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 ,
2023-08-08 19:30:24 +00:00
" 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 ,
2023-07-29 18:01:49 +00:00
" highestTR " : highestTR ,
" highestTRid " : highestTRid ,
" highestTRnick " : highestTRnick ,
" highestGlicko " : highestGlicko ,
" highestGlickoID " : highestGlickoID ,
" highestGlickoNick " : highestGlickoNick ,
2023-08-08 19:30:24 +00:00
" highestRD " : highestRD ,
" highestRdID " : highestRdID ,
" highestRdNick " : highestRdNick ,
2023-07-29 18:01:49 +00:00
" 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 ,
2023-08-08 19:30:24 +00:00
" 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 ,
2023-07-29 18:01:49 +00:00
" toEnterTR " : rank . toLowerCase ( ) ! = " z " ? leaderboard [ ( leaderboard . length * rankCutoffs [ rank ] ! ) . floor ( ) - 1 ] . rating : lowestTR ,
2024-05-01 23:12:52 +00:00
" toEnterGlicko " : rank . toLowerCase ( ) ! = " z " ? leaderboard [ ( leaderboard . length * rankCutoffs [ rank ] ! ) . floor ( ) - 1 ] . glicko : 0 ,
2023-07-29 18:01:49 +00:00
" entries " : filtredLeaderboard
} ] ;
} else {
return [ TetraLeagueAlpha ( timestamp: DateTime . now ( ) , apm: 0 , pps: 0 , vs: 0 , glicko: 0 , rd: noTrRd , gamesPlayed: 0 , gamesWon: 0 , bestRank: rank , decaying: false , rating: 0 , rank: rank , percentileRank: rank , percentile: rankCutoffs [ rank ] ! , standing: - 1 , standingLocal: - 1 , nextAt: - 1 , prevAt: - 1 ) ,
2024-05-01 23:12:52 +00:00
{ " players " : filtredLeaderboard . length , " lowestTR " : 0 , " toEnterTR " : 0 , " toEnterGlicko " : 0 } ] ;
2023-07-09 16:50:17 +00:00
}
}
2024-03-07 23:06:35 +00:00
PlayerLeaderboardPosition ? getLeaderboardPosition ( TetrioPlayer user ) {
if ( user . tlSeason1 . gamesPlayed = = 0 ) return null ;
bool fakePositions = false ;
late List < TetrioPlayerFromLeaderboard > copyOfLeaderboard ;
if ( leaderboard . indexWhere ( ( element ) = > element . userId = = user . userId ) = = - 1 ) {
fakePositions = true ;
copyOfLeaderboard = List . of ( leaderboard ) ;
copyOfLeaderboard . add ( user . convertToPlayerFromLeaderboard ( ) ) ;
}
2024-03-06 22:34:15 +00:00
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 ] ;
2024-03-07 23:06:35 +00:00
List < LeaderboardPosition ? > results = [ ] ;
2024-03-06 22:34:15 +00:00
for ( Stats stat in stats ) {
2024-03-10 22:34:30 +00:00
List < TetrioPlayerFromLeaderboard > sortedLeaderboard = getStatRanking ( fakePositions ? copyOfLeaderboard : leaderboard , stat , reversed: stat = = Stats . cheese ? true : false ) ;
2024-03-07 23:06:35 +00:00
int position = sortedLeaderboard . indexWhere ( ( element ) = > element . userId = = user . userId ) + 1 ;
if ( position = = 0 ) {
results . add ( null ) ;
} else {
results . add ( LeaderboardPosition ( fakePositions ? 1001 : position , position / sortedLeaderboard . length ) ) ;
}
2024-03-06 22:34:15 +00:00
}
return PlayerLeaderboardPosition . fromSearchResults ( results ) ;
}
2023-07-09 16:50:17 +00:00
Map < String , List < dynamic > > get averages = > {
' 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+ " ) ,
2023-07-29 18:01:49 +00:00
' d ' : getAverageOfRank ( " d " ) ,
' z ' : getAverageOfRank ( " z " )
2023-07-09 16:50:17 +00:00
} ;
2024-03-13 22:44:53 +00:00
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 " ]
} ;
2024-05-01 23:12:52 +00:00
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 " ]
} ;
2023-07-07 20:32:57 +00:00
TetrioPlayersLeaderboard . fromJson ( List < dynamic > json , String t , DateTime ts ) {
type = t ;
2023-06-28 16:50:40 +00:00
timestamp = ts ;
2023-07-07 20:32:57 +00:00
leaderboard = [ ] ;
for ( Map < String , dynamic > entry in json ) {
2023-06-28 16:50:40 +00:00
leaderboard . add ( TetrioPlayerFromLeaderboard . fromJson ( entry , ts ) ) ;
2023-06-17 21:50:52 +00:00
}
}
}
class TetrioPlayerFromLeaderboard {
late String userId ;
late String username ;
late String role ;
late double xp ;
String ? country ;
late bool supporter ;
late bool verified ;
2023-07-07 20:32:57 +00:00
late DateTime timestamp ;
late int gamesPlayed ;
late int gamesWon ;
late double rating ;
late double glicko ;
late double rd ;
late String rank ;
late String bestRank ;
late double apm ;
late double pps ;
late double vs ;
late bool decaying ;
2023-08-08 19:30:24 +00:00
late NerdStats nerdStats ;
late EstTr estTr ;
late Playstyle playstyle ;
2023-06-17 21:50:52 +00:00
2023-07-07 20:32:57 +00:00
TetrioPlayerFromLeaderboard (
this . userId ,
this . username ,
this . role ,
this . xp ,
this . country ,
this . supporter ,
this . verified ,
this . timestamp ,
this . gamesPlayed ,
this . gamesWon ,
this . rating ,
this . glicko ,
this . rd ,
this . rank ,
this . bestRank ,
this . apm ,
this . pps ,
this . vs ,
2024-03-07 23:06:35 +00:00
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 ) ;
}
2023-07-07 20:32:57 +00:00
2023-07-29 18:01:49 +00:00
double get winrate = > gamesWon / gamesPlayed ;
2023-08-08 19:30:24 +00:00
double get esttracc = > estTr . esttr - rating ;
2023-06-17 21:50:52 +00:00
2023-06-28 16:50:40 +00:00
TetrioPlayerFromLeaderboard . fromJson ( Map < String , dynamic > json , DateTime ts ) {
2023-06-17 21:50:52 +00:00
userId = json [ ' _id ' ] ;
username = json [ ' username ' ] ;
role = json [ ' role ' ] ;
xp = json [ ' xp ' ] . toDouble ( ) ;
2023-09-02 22:48:50 +00:00
country = json [ ' country ' ] ;
2023-06-17 21:50:52 +00:00
supporter = json [ ' supporter ' ] ;
verified = json [ ' verified ' ] ;
2023-07-07 20:32:57 +00:00
timestamp = ts ;
gamesPlayed = json [ ' league ' ] [ ' gamesplayed ' ] ;
gamesWon = json [ ' league ' ] [ ' gameswon ' ] ;
rating = json [ ' league ' ] [ ' rating ' ] . toDouble ( ) ;
glicko = json [ ' league ' ] [ ' glicko ' ] . toDouble ( ) ;
rd = json [ ' league ' ] [ ' rd ' ] . toDouble ( ) ;
rank = json [ ' league ' ] [ ' rank ' ] ;
bestRank = json [ ' league ' ] [ ' bestrank ' ] ;
2023-11-13 21:19:34 +00:00
apm = json [ ' league ' ] [ ' apm ' ] ! = null ? json [ ' league ' ] [ ' apm ' ] . toDouble ( ) : 0.00 ;
2023-11-13 21:27:18 +00:00
pps = json [ ' league ' ] [ ' pps ' ] ! = null ? json [ ' league ' ] [ ' pps ' ] . toDouble ( ) : 0.00 ;
vs = json [ ' league ' ] [ ' vs ' ] ! = null ? json [ ' league ' ] [ ' vs ' ] . toDouble ( ) : 0.00 ;
2023-07-07 20:32:57 +00:00
decaying = json [ ' league ' ] [ ' decaying ' ] ;
2023-08-08 19:30:24 +00:00
nerdStats = NerdStats ( apm , pps , vs ) ;
2023-10-08 17:20:42 +00:00
estTr = EstTr ( apm , pps , vs , nerdStats . app , nerdStats . dss , nerdStats . dsp , nerdStats . gbe ) ;
2023-08-08 19:30:24 +00:00
playstyle = Playstyle ( apm , pps , nerdStats . app , nerdStats . vsapm , nerdStats . dsp , nerdStats . gbe , estTr . srarea , estTr . statrank ) ;
2023-06-17 21:50:52 +00:00
}
2023-08-28 19:42:35 +00:00
num getStatByEnum ( Stats stat ) {
switch ( stat ) {
case Stats . tr:
return rating ;
case Stats . glicko:
return glicko ;
case Stats . rd:
return rd ;
case Stats . gp:
return gamesPlayed ;
case Stats . gw:
return gamesWon ;
case Stats . wr:
2023-09-02 22:48:50 +00:00
return winrate * 100 ;
2023-08-28 19:42:35 +00:00
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 ;
2024-03-14 22:53:19 +00:00
case Stats . acceTRabs:
return esttracc . abs ( ) ;
2023-08-28 19:42:35 +00:00
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 ;
}
}
2023-06-17 21:50:52 +00:00
}