Full leaderboard - full capabilities

This commit is contained in:
dan63047 2024-08-19 20:59:25 +03:00
parent e21ec84fc1
commit c0d395235b
6 changed files with 234 additions and 187 deletions

View File

@ -66,6 +66,8 @@ const Map<String, double> rankCutoffs = {
enum Stats { enum Stats {
tr, tr,
glicko, glicko,
gxe,
s1tr,
rd, rd,
gp, gp,
gw, gw,
@ -95,6 +97,8 @@ enum Stats {
const Map<Stats, String> chartsShortTitles = { const Map<Stats, String> chartsShortTitles = {
Stats.tr: "TR", Stats.tr: "TR",
Stats.gxe: "Glixare",
Stats.s1tr: "S1 TR",
Stats.glicko: "Glicko", Stats.glicko: "Glicko",
Stats.rd: "RD", Stats.rd: "RD",
Stats.gp: "GP", Stats.gp: "GP",
@ -351,6 +355,10 @@ class TetrioPlayer {
return tlSeason1?.tr; return tlSeason1?.tr;
case Stats.glicko: case Stats.glicko:
return tlSeason1?.glicko; return tlSeason1?.glicko;
case Stats.gxe:
return tlSeason1?.gxe;
case Stats.s1tr:
return tlSeason1?.s1tr;
case Stats.rd: case Stats.rd:
return tlSeason1?.rd; return tlSeason1?.rd;
case Stats.gp: case Stats.gp:
@ -1414,6 +1422,7 @@ class TetraLeague {
} }
double get winrate => gamesWon / gamesPlayed; double get winrate => gamesWon / gamesPlayed;
double get s1tr => gxe * 250;
TetraLeague.fromJson(Map<String, dynamic> json, ts) { TetraLeague.fromJson(Map<String, dynamic> json, ts) {
timestamp = ts; timestamp = ts;
@ -1451,7 +1460,7 @@ class TetraLeague {
TetrioPlayerFromLeaderboard convertToPlayerFromLeaderboard(String id) => TetrioPlayerFromLeaderboard( TetrioPlayerFromLeaderboard convertToPlayerFromLeaderboard(String id) => TetrioPlayerFromLeaderboard(
id, "", "user", -1, null, timestamp, gamesPlayed, gamesWon, id, "", "user", -1, null, timestamp, gamesPlayed, gamesWon,
tr, glicko??0, rd??noTrRd, rank, bestRank, apm??0, pps??0, vs??0, decaying); tr, gxe, glicko??0, rd??noTrRd, rank, bestRank, apm??0, pps??0, vs??0, decaying);
Map<String, dynamic> toJson() { Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{}; final Map<String, dynamic> data = <String, dynamic>{};
@ -1757,6 +1766,7 @@ class TetrioPlayersLeaderboard {
avgPPS = 0, avgPPS = 0,
avgVS = 0, avgVS = 0,
avgTR = 0, avgTR = 0,
avgGlixare = 0,
avgGlicko = 0, avgGlicko = 0,
avgRD = 0, avgRD = 0,
avgAPP = 0, avgAPP = 0,
@ -1775,6 +1785,7 @@ class TetrioPlayersLeaderboard {
avgStride = 0, avgStride = 0,
avgInfDS = 0, avgInfDS = 0,
lowestTR = 25000, lowestTR = 25000,
lowestGlixare = double.infinity,
lowestGlicko = double.infinity, lowestGlicko = double.infinity,
lowestRD = double.infinity, lowestRD = double.infinity,
lowestWinrate = double.infinity, lowestWinrate = double.infinity,
@ -1797,6 +1808,7 @@ class TetrioPlayersLeaderboard {
lowestStride = double.infinity, lowestStride = double.infinity,
lowestInfDS = double.infinity, lowestInfDS = double.infinity,
highestTR = double.negativeInfinity, highestTR = double.negativeInfinity,
highestGlixare = double.negativeInfinity,
highestGlicko = double.negativeInfinity, highestGlicko = double.negativeInfinity,
highestRD = double.negativeInfinity, highestRD = double.negativeInfinity,
highestWinrate = double.negativeInfinity, highestWinrate = double.negativeInfinity,
@ -1827,6 +1839,7 @@ class TetrioPlayersLeaderboard {
highestGamesPlayed = 0, highestGamesPlayed = 0,
highestGamesWon = 0; highestGamesWon = 0;
String lowestTRid = "", lowestTRnick = "", String lowestTRid = "", lowestTRnick = "",
lowestGlixareID = "", lowestGlixareNick = "",
lowestGlickoID = "", lowestGlickoNick = "", lowestGlickoID = "", lowestGlickoNick = "",
lowestRdID = "", lowestRdNick = "", lowestRdID = "", lowestRdNick = "",
lowestGamesPlayedID = "", lowestGamesPlayedNick = "", lowestGamesPlayedID = "", lowestGamesPlayedNick = "",
@ -1851,6 +1864,7 @@ class TetrioPlayersLeaderboard {
lowestStrideID = "", lowestStrideNick = "", lowestStrideID = "", lowestStrideNick = "",
lowestInfDSid = "", lowestInfDSnick = "", lowestInfDSid = "", lowestInfDSnick = "",
highestTRid = "", highestTRnick = "", highestTRid = "", highestTRnick = "",
highestGlixareID = "", highestGlixareNick = "",
highestGlickoID = "", highestGlickoNick = "", highestGlickoID = "", highestGlickoNick = "",
highestRdID = "", highestRdNick = "", highestRdID = "", highestRdNick = "",
highestGamesPlayedID = "", highestGamesPlayedNick = "", highestGamesPlayedID = "", highestGamesPlayedNick = "",
@ -1879,6 +1893,7 @@ class TetrioPlayersLeaderboard {
avgPPS += entry.pps; avgPPS += entry.pps;
avgVS += entry.vs; avgVS += entry.vs;
avgTR += entry.tr; avgTR += entry.tr;
avgGlixare += entry.gxe;
if (entry.glicko != null) avgGlicko += entry.glicko!; if (entry.glicko != null) avgGlicko += entry.glicko!;
if (entry.rd != null) avgRD += entry.rd!; if (entry.rd != null) avgRD += entry.rd!;
avgAPP += entry.nerdStats.app; avgAPP += entry.nerdStats.app;
@ -1903,6 +1918,11 @@ class TetrioPlayersLeaderboard {
lowestTRid = entry.userId; lowestTRid = entry.userId;
lowestTRnick = entry.username; lowestTRnick = entry.username;
} }
if (entry.gxe < lowestGlixare){
lowestGlixare = entry.gxe;
lowestGlixareID = entry.userId;
lowestGlixareNick = entry.username;
}
if (entry.glicko != null && entry.glicko! < lowestGlicko){ if (entry.glicko != null && entry.glicko! < lowestGlicko){
lowestGlicko = entry.glicko!; lowestGlicko = entry.glicko!;
lowestGlickoID = entry.userId; lowestGlickoID = entry.userId;
@ -2023,6 +2043,11 @@ class TetrioPlayersLeaderboard {
highestTRid = entry.userId; highestTRid = entry.userId;
highestTRnick = entry.username; highestTRnick = entry.username;
} }
if (entry.gxe > highestGlixare){
highestGlixare = entry.gxe;
highestGlixareID = entry.userId;
highestGlixareNick = entry.username;
}
if (entry.glicko != null && entry.glicko! > highestGlicko){ if (entry.glicko != null && entry.glicko! > highestGlicko){
highestGlicko = entry.glicko!; highestGlicko = entry.glicko!;
highestGlickoID = entry.userId; highestGlickoID = entry.userId;
@ -2143,6 +2168,7 @@ class TetrioPlayersLeaderboard {
avgPPS /= filtredLeaderboard.length; avgPPS /= filtredLeaderboard.length;
avgVS /= filtredLeaderboard.length; avgVS /= filtredLeaderboard.length;
avgTR /= filtredLeaderboard.length; avgTR /= filtredLeaderboard.length;
avgGlixare /= filtredLeaderboard.length;
avgGlicko /= filtredLeaderboard.length; avgGlicko /= filtredLeaderboard.length;
avgRD /= filtredLeaderboard.length; avgRD /= filtredLeaderboard.length;
avgAPP /= filtredLeaderboard.length; avgAPP /= filtredLeaderboard.length;
@ -2162,7 +2188,7 @@ class TetrioPlayersLeaderboard {
avgInfDS /= filtredLeaderboard.length; avgInfDS /= filtredLeaderboard.length;
avgGamesPlayed = (totalGamesPlayed / filtredLeaderboard.length).floor(); avgGamesPlayed = (totalGamesPlayed / filtredLeaderboard.length).floor();
avgGamesWon = (totalGamesWon / filtredLeaderboard.length).floor(); avgGamesWon = (totalGamesWon / filtredLeaderboard.length).floor();
return [TetraLeague(timestamp: DateTime.now(), apm: avgAPM, pps: avgPPS, vs: avgVS, glicko: avgGlicko, rd: avgRD, gamesPlayed: avgGamesPlayed, gamesWon: avgGamesWon, bestRank: rank, gxe: -1, decaying: false, tr: avgTR, rank: rank == "" ? "z" : rank, percentileRank: rank, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1), return [TetraLeague(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),
{ {
"everyone": rank == "", "everyone": rank == "",
"totalGamesPlayed": totalGamesPlayed, "totalGamesPlayed": totalGamesPlayed,
@ -2171,6 +2197,12 @@ class TetrioPlayersLeaderboard {
"lowestTR": lowestTR, "lowestTR": lowestTR,
"lowestTRid": lowestTRid, "lowestTRid": lowestTRid,
"lowestTRnick": lowestTRnick, "lowestTRnick": lowestTRnick,
"lowestGlixare": lowestGlixare,
"lowestGlixareID": lowestGlixareID,
"lowestGlixareNick": lowestGlixareNick,
"lowestS1tr": lowestGlixare * 250,
"lowestS1trID": lowestGlixareID,
"lowestS1trNick": lowestGlixareNick,
"lowestGlicko": lowestGlicko, "lowestGlicko": lowestGlicko,
"lowestGlickoID": lowestGlickoID, "lowestGlickoID": lowestGlickoID,
"lowestGlickoNick": lowestGlickoNick, "lowestGlickoNick": lowestGlickoNick,
@ -2243,6 +2275,12 @@ class TetrioPlayersLeaderboard {
"highestTR": highestTR, "highestTR": highestTR,
"highestTRid": highestTRid, "highestTRid": highestTRid,
"highestTRnick": highestTRnick, "highestTRnick": highestTRnick,
"highestGlixare": highestGlixare,
"highestGlixareID": highestGlixareID,
"highestGlixareNick": highestGlixareNick,
"highestS1tr": highestGlixare * 250,
"highestS1trID": highestGlixareID,
"highestS1trNick": highestGlixareNick,
"highestGlicko": highestGlicko, "highestGlicko": highestGlicko,
"highestGlickoID": highestGlickoID, "highestGlickoID": highestGlickoID,
"highestGlickoNick": highestGlickoNick, "highestGlickoNick": highestGlickoNick,
@ -2327,8 +2365,8 @@ class TetrioPlayersLeaderboard {
"avgPlonk": avgPlonk, "avgPlonk": avgPlonk,
"avgStride": avgStride, "avgStride": avgStride,
"avgInfDS": avgInfDS, "avgInfDS": avgInfDS,
"toEnterTR": rank.toLowerCase() != "z" ? leaderboard[(leaderboard.length * rankCutoffs[rank]!).floor()].tr : lowestTR, "toEnterTR": rank.toLowerCase() != "z" ? leaderboard[(leaderboard.length * rankCutoffs[rank]!).floor()-1].tr : lowestTR,
"toEnterGlicko": rank.toLowerCase() != "z" ? leaderboard[(leaderboard.length * rankCutoffs[rank]!).floor()].glicko : 0, "toEnterGlicko": rank.toLowerCase() != "z" ? leaderboard[(leaderboard.length * rankCutoffs[rank]!).floor()-1].glicko : 0,
"entries": filtredLeaderboard "entries": filtredLeaderboard
}]; }];
}else{ }else{
@ -2447,6 +2485,7 @@ class TetrioPlayerFromLeaderboard {
late int gamesPlayed; late int gamesPlayed;
late int gamesWon; late int gamesWon;
late double tr; late double tr;
late double gxe;
late double? glicko; late double? glicko;
late double? rd; late double? rd;
late String rank; late String rank;
@ -2469,6 +2508,7 @@ class TetrioPlayerFromLeaderboard {
this.gamesPlayed, this.gamesPlayed,
this.gamesWon, this.gamesWon,
this.tr, this.tr,
this.gxe,
this.glicko, this.glicko,
this.rd, this.rd,
this.rank, this.rank,
@ -2484,6 +2524,7 @@ class TetrioPlayerFromLeaderboard {
double get winrate => gamesWon / gamesPlayed; double get winrate => gamesWon / gamesPlayed;
double get esttracc => estTr.esttr - tr; double get esttracc => estTr.esttr - tr;
double get s1tr => gxe * 250;
TetrioPlayerFromLeaderboard.fromJson(Map<String, dynamic> json, DateTime ts) { TetrioPlayerFromLeaderboard.fromJson(Map<String, dynamic> json, DateTime ts) {
userId = json['_id']; userId = json['_id'];
@ -2495,6 +2536,7 @@ class TetrioPlayerFromLeaderboard {
gamesPlayed = json['league']['gamesplayed'] as int; gamesPlayed = json['league']['gamesplayed'] as int;
gamesWon = json['league']['gameswon'] as int; gamesWon = json['league']['gameswon'] as int;
tr = json['league']['tr'] != null ? json['league']['tr'].toDouble() : 0; tr = json['league']['tr'] != null ? json['league']['tr'].toDouble() : 0;
gxe = json['league']['gxe']??-1;
glicko = json['league']['glicko']?.toDouble(); glicko = json['league']['glicko']?.toDouble();
rd = json['league']['rd']?.toDouble(); rd = json['league']['rd']?.toDouble();
rank = json['league']['rank']; rank = json['league']['rank'];
@ -2514,6 +2556,10 @@ class TetrioPlayerFromLeaderboard {
return tr; return tr;
case Stats.glicko: case Stats.glicko:
return glicko??-1; return glicko??-1;
case Stats.gxe:
return gxe;
case Stats.s1tr:
return s1tr;
case Stats.rd: case Stats.rd:
return rd??-1; return rd??-1;
case Stats.gp: case Stats.gp:

View File

@ -636,18 +636,12 @@ class TetrioService extends DB {
} }
/// Retrieves full Tetra League leaderboard from Tetra Channel api. Returns a leaderboard object. Throws an exception if fails to retrieve. /// Retrieves full Tetra League leaderboard from Tetra Channel api. Returns a leaderboard object. Throws an exception if fails to retrieve.
Future<TetrioPlayersLeaderboard> fetchTLLeaderboard({double? after}) async { Future<TetrioPlayersLeaderboard> fetchTLLeaderboard() async {
TetrioPlayersLeaderboard? cached = _cache.get("league${after != null ? after.toString() : ""}", TetrioPlayersLeaderboard); TetrioPlayersLeaderboard? cached = _cache.get("league", TetrioPlayersLeaderboard);
if (cached != null) return cached; if (cached != null) return cached;
Uri url;
if (kIsWeb) { Uri url = Uri.https('ts.dan63.by', 'beanserver_blaster/leaderboard.json');
url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "TLLeaderboard"});
} else {
url = Uri.https('ch.tetr.io', 'api/users/by/league', {
"limit": "100",
if (after != null) "after": "$after:0:0"
});
}
try{ try{
final response = await client.get(url); final response = await client.get(url);
@ -655,16 +649,10 @@ class TetrioService extends DB {
case 200: case 200:
_lbPositions.clear(); _lbPositions.clear();
var rawJson = jsonDecode(response.body); var rawJson = jsonDecode(response.body);
if (rawJson['success']) { // if api confirmed that everything ok TetrioPlayersLeaderboard leaderboard = TetrioPlayersLeaderboard.fromJson(rawJson['data'], "league", DateTime.fromMillisecondsSinceEpoch(rawJson['created']));
TetrioPlayersLeaderboard leaderboard = TetrioPlayersLeaderboard.fromJson(rawJson['data']['entries'], "league", DateTime.fromMillisecondsSinceEpoch(rawJson['cache']['cached_at']));
developer.log("fetchTLLeaderboard: Leaderboard retrieved and cached", name: "services/tetrio_crud"); developer.log("fetchTLLeaderboard: Leaderboard retrieved and cached", name: "services/tetrio_crud");
//_leaderboardsCache[rawJson['cache']['cached_until'].toString()] = leaderboard; _cache.store(leaderboard, rawJson['cache_until']);
_cache.store(leaderboard, rawJson['cache']['cached_until']);
return leaderboard; return leaderboard;
} else { // idk how to hit that one
developer.log("fetchTLLeaderboard: Bruh", name: "services/tetrio_crud", error: rawJson);
throw Exception("Failed to get leaderboard (problems on the tetr.io side)"); // will it be on tetr.io side?
}
case 403: case 403:
throw TetrioForbidden(); throw TetrioForbidden();
case 429: case 429:
@ -686,19 +674,19 @@ class TetrioService extends DB {
} }
} }
Stream<TetrioPlayersLeaderboard> fetchFullLeaderboard() async* { // Stream<TetrioPlayersLeaderboard> fetchFullLeaderboard() async* {
late double after; // late double after;
int lbLength = 100; // int lbLength = 100;
TetrioPlayersLeaderboard leaderboard = await fetchTLLeaderboard(); // TetrioPlayersLeaderboard leaderboard = await fetchTLLeaderboard();
after = leaderboard.leaderboard.last.tr; // after = leaderboard.leaderboard.last.tr;
while (lbLength == 100){ // while (lbLength == 100){
TetrioPlayersLeaderboard pseudoLb = await fetchTLLeaderboard(after: after); // TetrioPlayersLeaderboard pseudoLb = await fetchTLLeaderboard(after: after);
leaderboard.addPlayers(pseudoLb.leaderboard); // leaderboard.addPlayers(pseudoLb.leaderboard);
lbLength = pseudoLb.leaderboard.length; // lbLength = pseudoLb.leaderboard.length;
after = pseudoLb.leaderboard.last.tr; // after = pseudoLb.leaderboard.last.tr;
yield leaderboard; // yield leaderboard;
} // }
} // }
// i want to know progress, so i trying to figure out this thing: // i want to know progress, so i trying to figure out this thing:
// Stream<TetrioPlayersLeaderboard> fetchTLLeaderboardAsStream() async { // Stream<TetrioPlayersLeaderboard> fetchTLLeaderboardAsStream() async {

View File

@ -213,7 +213,7 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
nextRankGlickoCutoff = (summaries.league.rank != "z" ? summaries.league.rank == "x+" : summaries.league.percentileRank == "x+") ? topOne?.glicko??double.infinity : cutoffsGlicko?[ranks.elementAtOrNull(ranks.indexOf(summaries.league.rank != "z" ? summaries.league.rank : summaries.league.percentileRank)+1)]; nextRankGlickoCutoff = (summaries.league.rank != "z" ? summaries.league.rank == "x+" : summaries.league.percentileRank == "x+") ? topOne?.glicko??double.infinity : cutoffsGlicko?[ranks.elementAtOrNull(ranks.indexOf(summaries.league.rank != "z" ? summaries.league.rank : summaries.league.percentileRank)+1)];
} }
// if (everyone != null && summaries.league.gamesPlayed > 9) rankAverages = everyone?.averages[summaries.league.percentileRank]?[0]; if (everyone != null && summaries.league.gamesPlayed > 9) rankAverages = everyone?.averages[summaries.league.percentileRank]?[0];
// Making list of Tetra League matches // Making list of Tetra League matches
//bool isTracking = await teto.isPlayerTracking(me.userId); //bool isTracking = await teto.isPlayerTracking(me.userId);
@ -482,8 +482,8 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
nextRankCutoff: nextRankCutoff, nextRankCutoff: nextRankCutoff,
nextRankCutoffGlicko: nextRankGlickoCutoff, nextRankCutoffGlicko: nextRankGlickoCutoff,
//nextRankTarget: (snapshot.data![1].league.rank != "z" && snapshot.data![1].league.rank != "x") ? rankTargets[ranks.elementAtOrNull(ranks.indexOf(snapshot.data![1].league.rank)+1)] : null, //nextRankTarget: (snapshot.data![1].league.rank != "z" && snapshot.data![1].league.rank != "x") ? rankTargets[ranks.elementAtOrNull(ranks.indexOf(snapshot.data![1].league.rank)+1)] : null,
//averages: rankAverages, averages: rankAverages,
//lbPositions: meAmongEveryone lbPositions: meAmongEveryone
), ),
), ),
SizedBox( SizedBox(
@ -523,8 +523,8 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
nextRankCutoff: nextRankCutoff, nextRankCutoff: nextRankCutoff,
nextRankCutoffGlicko: nextRankGlickoCutoff, nextRankCutoffGlicko: nextRankGlickoCutoff,
//nextRankTarget: (snapshot.data![1].league.rank != "z" && snapshot.data![1].league.rank != "x") ? rankTargets[ranks.elementAtOrNull(ranks.indexOf(snapshot.data![1].league.rank)+1)] : null, //nextRankTarget: (snapshot.data![1].league.rank != "z" && snapshot.data![1].league.rank != "x") ? rankTargets[ranks.elementAtOrNull(ranks.indexOf(snapshot.data![1].league.rank)+1)] : null,
//averages: rankAverages, averages: rankAverages,
//lbPositions: meAmongEveryone lbPositions: meAmongEveryone
), ),
_TLRecords(userID: snapshot.data![0].userId, changePlayer: changePlayer, data: snapshot.data![3].records, wasActiveInTL: true, oldMathcesHere: _TLHistoryWasFetched, separateScrollController: true), _TLRecords(userID: snapshot.data![0].userId, changePlayer: changePlayer, data: snapshot.data![3].records, wasActiveInTL: true, oldMathcesHere: _TLHistoryWasFetched, separateScrollController: true),
_History(chartsData: chartsData, changePlayer: changePlayer, userID: _searchFor, update: _justUpdate, wasActiveInTL: snapshot.data![1].league.gamesPlayed > 0), _History(chartsData: chartsData, changePlayer: changePlayer, userID: _searchFor, update: _justUpdate, wasActiveInTL: snapshot.data![1].league.gamesPlayed > 0),

View File

@ -379,6 +379,8 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
child: ListView( child: ListView(
children: [ children: [
_ListEntry(value: widget.rank[1]["lowestTR"], label: t.statCellNum.tr.replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestTRid"], username: widget.rank[1]["lowestTRnick"], approximate: false, fractionDigits: 2), _ListEntry(value: widget.rank[1]["lowestTR"], label: t.statCellNum.tr.replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestTRid"], username: widget.rank[1]["lowestTRnick"], approximate: false, fractionDigits: 2),
_ListEntry(value: widget.rank[1]["lowestGlixare"], label: "Glixare", id: widget.rank[1]["lowestGlixareID"], username: widget.rank[1]["lowestGlixareNick"], approximate: false, fractionDigits: 3),
_ListEntry(value: widget.rank[1]["lowestS1tr"], label: "S1 ${t.statCellNum.tr.replaceAll(RegExp(r'\n'), " ")}", id: widget.rank[1]["lowestS1trID"], username: widget.rank[1]["lowestS1trNick"], approximate: false, fractionDigits: 2),
_ListEntry(value: widget.rank[1]["lowestGlicko"], label: "Glicko", id: widget.rank[1]["lowestGlickoID"], username: widget.rank[1]["lowestGlickoNick"], approximate: false, fractionDigits: 2), _ListEntry(value: widget.rank[1]["lowestGlicko"], label: "Glicko", id: widget.rank[1]["lowestGlickoID"], username: widget.rank[1]["lowestGlickoNick"], approximate: false, fractionDigits: 2),
_ListEntry(value: widget.rank[1]["lowestRD"], label: t.statCellNum.rd.replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestRdID"], username: widget.rank[1]["lowestRdNick"], approximate: false, fractionDigits: 3), _ListEntry(value: widget.rank[1]["lowestRD"], label: t.statCellNum.rd.replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestRdID"], username: widget.rank[1]["lowestRdNick"], approximate: false, fractionDigits: 3),
_ListEntry(value: widget.rank[1]["lowestGamesPlayed"], label: t.statCellNum.gamesPlayed.replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestGamesPlayedID"], username: widget.rank[1]["lowestGamesPlayedNick"], approximate: false), _ListEntry(value: widget.rank[1]["lowestGamesPlayed"], label: t.statCellNum.gamesPlayed.replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestGamesPlayedID"], username: widget.rank[1]["lowestGamesPlayedNick"], approximate: false),
@ -413,6 +415,8 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
Expanded( Expanded(
child: ListView(children: [ child: ListView(children: [
_ListEntry(value: widget.rank[0].tr, label: t.statCellNum.tr.replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 2), _ListEntry(value: widget.rank[0].tr, label: t.statCellNum.tr.replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 2),
_ListEntry(value: widget.rank[0].gxe, label: "Glixare", id: "", username: "", approximate: false, fractionDigits: 3),
_ListEntry(value: widget.rank[0].s1tr, label: "S1 ${t.statCellNum.tr.replaceAll(RegExp(r'\n'), " ")}", id: "", username: "", approximate: false, fractionDigits: 2),
_ListEntry(value: widget.rank[0].glicko, label: "Glicko", id: "", username: "", approximate: true, fractionDigits: 2), _ListEntry(value: widget.rank[0].glicko, label: "Glicko", id: "", username: "", approximate: true, fractionDigits: 2),
_ListEntry(value: widget.rank[0].rd, label: t.statCellNum.rd.replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 3), _ListEntry(value: widget.rank[0].rd, label: t.statCellNum.rd.replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 3),
_ListEntry(value: widget.rank[0].gamesPlayed, label: t.statCellNum.gamesPlayed.replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 0), _ListEntry(value: widget.rank[0].gamesPlayed, label: t.statCellNum.gamesPlayed.replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 0),
@ -446,6 +450,8 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
child: ListView( child: ListView(
children: [ children: [
_ListEntry(value: widget.rank[1]["highestTR"], label: t.statCellNum.tr.replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestTRid"], username: widget.rank[1]["highestTRnick"], approximate: false, fractionDigits: 2), _ListEntry(value: widget.rank[1]["highestTR"], label: t.statCellNum.tr.replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestTRid"], username: widget.rank[1]["highestTRnick"], approximate: false, fractionDigits: 2),
_ListEntry(value: widget.rank[1]["highestGlixare"], label: "Glixare", id: widget.rank[1]["highestGlixareID"], username: widget.rank[1]["highestGlixareNick"], approximate: false, fractionDigits: 3),
_ListEntry(value: widget.rank[1]["highestS1tr"], label: "S1 ${t.statCellNum.tr.replaceAll(RegExp(r'\n'), " ")}", id: widget.rank[1]["highestS1trID"], username: widget.rank[1]["highestS1trNick"], approximate: false, fractionDigits: 2),
_ListEntry(value: widget.rank[1]["highestGlicko"], label: "Glicko", id: widget.rank[1]["highestGlickoID"], username: widget.rank[1]["highestGlickoNick"], approximate: false, fractionDigits: 2), _ListEntry(value: widget.rank[1]["highestGlicko"], label: "Glicko", id: widget.rank[1]["highestGlickoID"], username: widget.rank[1]["highestGlickoNick"], approximate: false, fractionDigits: 2),
_ListEntry(value: widget.rank[1]["highestRD"], label: t.statCellNum.rd.replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestRdID"], username: widget.rank[1]["highestRdNick"], approximate: false, fractionDigits: 3), _ListEntry(value: widget.rank[1]["highestRD"], label: t.statCellNum.rd.replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestRdID"], username: widget.rank[1]["highestRdNick"], approximate: false, fractionDigits: 3),
_ListEntry(value: widget.rank[1]["highestGamesPlayed"], label: t.statCellNum.gamesPlayed.replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestGamesPlayedID"], username: widget.rank[1]["highestGamesPlayedNick"], approximate: false), _ListEntry(value: widget.rank[1]["highestGamesPlayed"], label: t.statCellNum.gamesPlayed.replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestGamesPlayedID"], username: widget.rank[1]["highestGamesPlayedNick"], approximate: false),
@ -517,7 +523,7 @@ class _ListEntry extends StatelessWidget {
children: [ children: [
Text(f.format(value), Text(f.format(value),
style: const TextStyle(fontSize: 22, height: 0.9)), style: const TextStyle(fontSize: 22, height: 0.9)),
if (id.isNotEmpty) Text(t.forPlayer(username: username)) if (id.isNotEmpty) Text(t.forPlayer(username: username), style: TextStyle(color: Colors.grey, fontWeight: FontWeight.w100),)
], ],
), ),
onTap: id.isNotEmpty onTap: id.isNotEmpty

View File

@ -4,13 +4,13 @@ import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:tetra_stats/data_objects/tetrio.dart'; import 'package:tetra_stats/data_objects/tetrio.dart';
import 'package:tetra_stats/gen/strings.g.dart'; import 'package:tetra_stats/gen/strings.g.dart';
import 'package:tetra_stats/services/tetrio_crud.dart'; import 'package:tetra_stats/main.dart';
import 'package:tetra_stats/views/main_view.dart'; import 'package:tetra_stats/views/main_view.dart';
import 'package:tetra_stats/views/rank_averages_view.dart'; import 'package:tetra_stats/views/rank_averages_view.dart';
import 'package:tetra_stats/views/ranks_averages_view.dart'; import 'package:tetra_stats/views/ranks_averages_view.dart';
import 'package:window_manager/window_manager.dart'; import 'package:window_manager/window_manager.dart';
import 'package:tetra_stats/widgets/text_timestamp.dart';
final TetrioService _teto = TetrioService();
List<DropdownMenuItem> _itemStats = [for (MapEntry e in chartsShortTitles.entries) DropdownMenuItem(value: e.key, child: Text(e.value))]; List<DropdownMenuItem> _itemStats = [for (MapEntry e in chartsShortTitles.entries) DropdownMenuItem(value: e.key, child: Text(e.value))];
Stats _sortBy = Stats.tr; Stats _sortBy = Stats.tr;
bool reversed = false; bool reversed = false;
@ -65,7 +65,7 @@ class TLLeaderboardState extends State<TLLeaderboardView> {
backgroundColor: Colors.black, backgroundColor: Colors.black,
body: SafeArea( body: SafeArea(
child: FutureBuilder( child: FutureBuilder(
future: _teto.fetchTLLeaderboard(), future: teto.fetchTLLeaderboard(),
builder: (context, snapshot) { builder: (context, snapshot) {
switch (snapshot.connectionState) { switch (snapshot.connectionState) {
case ConnectionState.none: case ConnectionState.none:
@ -73,21 +73,12 @@ class TLLeaderboardState extends State<TLLeaderboardView> {
case ConnectionState.active: case ConnectionState.active:
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
case ConnectionState.done: case ConnectionState.done:
if (snapshot.hasData){
final allPlayers = snapshot.data?.getStatRanking(snapshot.data!.leaderboard, _sortBy, reversed: reversed, country: _country); final allPlayers = snapshot.data?.getStatRanking(snapshot.data!.leaderboard, _sortBy, reversed: reversed, country: _country);
if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS) windowManager.setTitle("Tetra Stats: ${t.tlLeaderboard} - ${t.players(n: allPlayers != null ? allPlayers.length : 0)}"); if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS) windowManager.setTitle("Tetra Stats: ${t.tlLeaderboard} - ${t.players(n: allPlayers != null ? allPlayers.length : 0)}");
bool bigScreen = MediaQuery.of(context).size.width > 768; bool bigScreen = MediaQuery.of(context).size.width > 768;
return NestedScrollView( return NestedScrollView(
headerSliverBuilder: (context, value) { headerSliverBuilder: (context, value) {
String howManyPlayers(int numberOfPlayers) => Intl.plural(
numberOfPlayers,
zero: t.lbViewZeroEntrys,
one: t.lbViewOneEntry,
other: t.lbViewManyEntrys(numberOfPlayers: t.players(n: numberOfPlayers)),
name: 'howManyPeople',
args: [numberOfPlayers],
desc: 'Description of how many people are seen in a place.',
examples: const {'numberOfPeople': 3},
);
return [ return [
SliverToBoxAdapter( SliverToBoxAdapter(
child: Padding( child: Padding(
@ -97,7 +88,7 @@ class TLLeaderboardState extends State<TLLeaderboardView> {
alignment: WrapAlignment.spaceBetween, alignment: WrapAlignment.spaceBetween,
children: [ children: [
Text( Text(
howManyPlayers(allPlayers.length), "${t.players(n: allPlayers.length)}${t.sprintAndBlitsRelevance(date: timestamp(snapshot.data!.timestamp))}",
style: const TextStyle(color: Colors.white, fontSize: 25), style: const TextStyle(color: Colors.white, fontSize: 25),
), ),
TextButton(onPressed: (){ TextButton(onPressed: (){
@ -205,6 +196,22 @@ class TLLeaderboardState extends State<TLLeaderboardView> {
); );
})); }));
} }
if (snapshot.hasError){
return Center(child:
Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(snapshot.error.toString(), style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 42, fontWeight: FontWeight.bold), textAlign: TextAlign.center),
if (snapshot.stackTrace != null) Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(snapshot.stackTrace.toString(), style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 18), textAlign: TextAlign.center),
),
],
)
);
}
return Text("end of FutureBuilder");
}
})), })),
); );
} }

View File

@ -2,7 +2,7 @@ name: tetra_stats
description: Track your and other player stats in TETR.IO description: Track your and other player stats in TETR.IO
publish_to: 'none' publish_to: 'none'
version: 1.6.5+31 version: 1.6.6+32
environment: environment:
sdk: '>=3.0.0' sdk: '>=3.0.0'