This commit is contained in:
dan63047 2024-11-01 03:05:26 +03:00
parent 5b1a54c59e
commit 14494db134
8 changed files with 311 additions and 174 deletions

View File

@ -132,7 +132,7 @@ const Map<Stats, String> chartsShortTitles = {
Stats.area: "Area", Stats.area: "Area",
Stats.eTR: "eTR", Stats.eTR: "eTR",
Stats.acceTR: "±eTR", Stats.acceTR: "±eTR",
Stats.acceTRabs: "+eTR absolute", Stats.acceTRabs: "±eTR absolute",
Stats.opener: "Opener", Stats.opener: "Opener",
Stats.plonk: "Plonk", Stats.plonk: "Plonk",
Stats.infDS: "Inf. DS", Stats.infDS: "Inf. DS",

View File

@ -57,35 +57,14 @@ class TetrioPlayersLeaderboard {
return lb; return lb;
} }
List<dynamic> getAverageOfRank(String rank){ // i tried to refactor it and that's was terrible List<dynamic> getRankData(String rank){
if (rank.isNotEmpty && !rankCutoffs.keys.contains(rank)) throw Exception("Invalid rank"); if (rank.isNotEmpty && !rankCutoffs.keys.contains(rank)) throw Exception("Invalid rank");
List<TetrioPlayerFromLeaderboard> filtredLeaderboard = List.from(leaderboard); List<TetrioPlayerFromLeaderboard> filtredLeaderboard = List.from(leaderboard);
if (rank.isNotEmpty) { if (rank.isNotEmpty) {
filtredLeaderboard.removeWhere((element) => element.rank != rank); filtredLeaderboard.removeWhere((element) => element.rank != rank);
} }
if (filtredLeaderboard.isNotEmpty){ if (filtredLeaderboard.isNotEmpty){
double avgAPM = 0, double
avgPPS = 0,
avgVS = 0,
avgTR = 0,
avgGlixare = 0,
avgGlicko = 0,
avgRD = 0,
avgAPP = 0,
avgVSAPM = 0,
avgDSS = 0,
avgDSP = 0,
avgAPPDSP = 0,
avgCheese = 0,
avgGBE = 0,
avgNyaAPP = 0,
avgArea = 0,
avgEstTR = 0,
avgEstAcc = 0,
avgOpener = 0,
avgPlonk = 0,
avgStride = 0,
avgInfDS = 0,
lowestTR = 25000, lowestTR = 25000,
lowestGlixare = double.infinity, lowestGlixare = double.infinity,
lowestGlicko = double.infinity, lowestGlicko = double.infinity,
@ -131,7 +110,11 @@ class TetrioPlayersLeaderboard {
highestOpener = double.negativeInfinity, highestOpener = double.negativeInfinity,
highestPlonk = double.negativeInfinity, highestPlonk = double.negativeInfinity,
highestStride = double.negativeInfinity, highestStride = double.negativeInfinity,
highestInfDS = double.negativeInfinity; highestInfDS = double.negativeInfinity,
avgTR = 0,
avgGlixare = 0,
avgGlicko = 0,
avgRD = 0;
int avgGamesPlayed = 0, int avgGamesPlayed = 0,
avgGamesWon = 0, avgGamesWon = 0,
totalGamesPlayed = 0, totalGamesPlayed = 0,
@ -191,28 +174,10 @@ class TetrioPlayersLeaderboard {
highestStrideID = "", highestStrideNick = "", highestStrideID = "", highestStrideNick = "",
highestInfDSid = "", highestInfDSnick = ""; highestInfDSid = "", highestInfDSnick = "";
for (var entry in filtredLeaderboard){ for (var entry in filtredLeaderboard){
avgAPM += entry.apm;
avgPPS += entry.pps;
avgVS += entry.vs;
avgTR += entry.tr; avgTR += entry.tr;
avgGlixare += entry.gxe; 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;
avgVSAPM += entry.nerdStats.vsapm;
avgDSS += entry.nerdStats.dss;
avgDSP += entry.nerdStats.dsp;
avgAPPDSP += entry.nerdStats.appdsp;
avgCheese += entry.nerdStats.cheese;
avgGBE += entry.nerdStats.gbe;
avgNyaAPP += entry.nerdStats.nyaapp;
avgArea += entry.nerdStats.area;
avgEstTR += entry.estTr.esttr;
avgEstAcc += entry.esttracc;
avgOpener += entry.playstyle.opener;
avgPlonk += entry.playstyle.plonk;
avgStride += entry.playstyle.stride;
avgInfDS += entry.playstyle.infds;
totalGamesPlayed += entry.gamesPlayed; totalGamesPlayed += entry.gamesPlayed;
totalGamesWon += entry.gamesWon; totalGamesWon += entry.gamesWon;
if (entry.tr < lowestTR){ if (entry.tr < lowestTR){
@ -466,33 +431,14 @@ class TetrioPlayersLeaderboard {
highestInfDSnick = entry.username; highestInfDSnick = entry.username;
} }
} }
avgAPM /= filtredLeaderboard.length;
avgPPS /= filtredLeaderboard.length;
avgVS /= filtredLeaderboard.length;
avgTR /= filtredLeaderboard.length; avgTR /= filtredLeaderboard.length;
avgGlixare /= filtredLeaderboard.length; avgGlixare /= filtredLeaderboard.length;
avgGlicko /= filtredLeaderboard.length; avgGlicko /= filtredLeaderboard.length;
avgRD /= filtredLeaderboard.length; avgRD /= filtredLeaderboard.length;
avgAPP /= filtredLeaderboard.length;
avgVSAPM /= filtredLeaderboard.length;
avgDSS /= filtredLeaderboard.length;
avgDSP /= filtredLeaderboard.length;
avgAPPDSP /= leaderboard.length;
avgCheese /= filtredLeaderboard.length;
avgGBE /= filtredLeaderboard.length;
avgNyaAPP /= filtredLeaderboard.length;
avgArea /= filtredLeaderboard.length;
avgEstTR /= filtredLeaderboard.length;
avgEstAcc /= filtredLeaderboard.length;
avgOpener /= filtredLeaderboard.length;
avgPlonk /= filtredLeaderboard.length;
avgStride /= filtredLeaderboard.length;
avgInfDS /= filtredLeaderboard.length;
avgGamesPlayed = (totalGamesPlayed / filtredLeaderboard.length).floor(); avgGamesPlayed = (totalGamesPlayed / filtredLeaderboard.length).floor();
avgGamesWon = (totalGamesWon / filtredLeaderboard.length).floor(); avgGamesWon = (totalGamesWon / filtredLeaderboard.length).floor();
return [TetraLeague(id: "", timestamp: DateTime.now(), apm: avgAPM, pps: avgPPS, vs: avgVS, gxe: avgGlixare, glicko: avgGlicko, rd: avgRD, gamesPlayed: avgGamesPlayed, gamesWon: avgGamesWon, bestRank: rank, decaying: false, tr: avgTR, rank: rank == "" ? "z" : rank, percentileRank: rank, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1, season: currentSeason), return [TetraLeague(id: "", timestamp: DateTime.now(), apm: null, pps: null, vs: null, gxe: avgGlixare, glicko: avgGlicko, rd: avgRD, gamesPlayed: avgGamesPlayed, gamesWon: avgGamesWon, bestRank: rank, decaying: false, tr: avgTR, rank: rank == "" ? "z" : rank, percentileRank: rank, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1, season: currentSeason),
{ {
"everyone": rank == "",
"totalGamesPlayed": totalGamesPlayed, "totalGamesPlayed": totalGamesPlayed,
"totalGamesWon": totalGamesWon, "totalGamesWon": totalGamesWon,
"players": filtredLeaderboard.length, "players": filtredLeaderboard.length,
@ -652,24 +598,7 @@ class TetrioPlayersLeaderboard {
"highestInfDS": highestInfDS, "highestInfDS": highestInfDS,
"highestInfDSid": highestInfDSid, "highestInfDSid": highestInfDSid,
"highestInfDSnick": highestInfDSnick, "highestInfDSnick": highestInfDSnick,
"avgAPP": avgAPP,
"avgVSAPM": avgVSAPM,
"avgDSS": avgDSS,
"avgDSP": avgDSP,
"avgAPPDSP": avgAPPDSP,
"avgCheese": avgCheese,
"avgGBE": avgGBE,
"avgNyaAPP": avgNyaAPP,
"avgArea": avgArea,
"avgEstTR": avgEstTR,
"avgEstAcc": avgEstAcc,
"avgOpener": avgOpener,
"avgPlonk": avgPlonk,
"avgStride": avgStride,
"avgInfDS": avgInfDS,
"toEnterTR": rank.toLowerCase() != "z" ? leaderboard[(leaderboard.length * rankCutoffs[rank]!).floor()-1].tr : lowestTR,
"toEnterGlicko": rank.toLowerCase() != "z" ? leaderboard[(leaderboard.length * rankCutoffs[rank]!).floor()-1].glicko : 0, "toEnterGlicko": rank.toLowerCase() != "z" ? leaderboard[(leaderboard.length * rankCutoffs[rank]!).floor()-1].glicko : 0,
"entries": filtredLeaderboard
}]; }];
}else{ }else{
return [TetraLeague(id: "", timestamp: DateTime.now(), apm: 0, pps: 0, vs: 0, glicko: 0, rd: noTrRd, gamesPlayed: 0, gamesWon: 0, bestRank: rank, decaying: false, tr: 0, rank: rank, percentileRank: rank, gxe: -1, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1, season: currentSeason), return [TetraLeague(id: "", timestamp: DateTime.now(), apm: 0, pps: 0, vs: 0, glicko: 0, rd: noTrRd, gamesPlayed: 0, gamesWon: 0, bestRank: rank, decaying: false, tr: 0, rank: rank, percentileRank: rank, gxe: -1, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1, season: currentSeason),
@ -702,65 +631,45 @@ class TetrioPlayersLeaderboard {
} }
Map<String, List<dynamic>> get averages => { Map<String, List<dynamic>> get averages => {
'x+': getAverageOfRank("x+"), 'x+': getRankData("x+"),
'x': getAverageOfRank("x"), 'x': getRankData("x"),
'u': getAverageOfRank("u"), 'u': getRankData("u"),
'ss': getAverageOfRank("ss"), 'ss': getRankData("ss"),
's+': getAverageOfRank("s+"), 's+': getRankData("s+"),
's': getAverageOfRank("s"), 's': getRankData("s"),
's-': getAverageOfRank("s-"), 's-': getRankData("s-"),
'a+': getAverageOfRank("a+"), 'a+': getRankData("a+"),
'a': getAverageOfRank("a"), 'a': getRankData("a"),
'a-': getAverageOfRank("a-"), 'a-': getRankData("a-"),
'b+': getAverageOfRank("b+"), 'b+': getRankData("b+"),
'b': getAverageOfRank("b"), 'b': getRankData("b"),
'b-': getAverageOfRank("b-"), 'b-': getRankData("b-"),
'c+': getAverageOfRank("c+"), 'c+': getRankData("c+"),
'c': getAverageOfRank("c"), 'c': getRankData("c"),
'c-': getAverageOfRank("c-"), 'c-': getRankData("c-"),
'd+': getAverageOfRank("d+"), 'd+': getRankData("d+"),
'd': getAverageOfRank("d"), 'd': getRankData("d"),
'z': getAverageOfRank("z") 'z': getRankData("z")
};
Map<String, double> get cutoffs => {
'x': getAverageOfRank("x")[1]["toEnterTR"],
'u': getAverageOfRank("u")[1]["toEnterTR"],
'ss': getAverageOfRank("ss")[1]["toEnterTR"],
's+': getAverageOfRank("s+")[1]["toEnterTR"],
's': getAverageOfRank("s")[1]["toEnterTR"],
's-': getAverageOfRank("s-")[1]["toEnterTR"],
'a+': getAverageOfRank("a+")[1]["toEnterTR"],
'a': getAverageOfRank("a")[1]["toEnterTR"],
'a-': getAverageOfRank("a-")[1]["toEnterTR"],
'b+': getAverageOfRank("b+")[1]["toEnterTR"],
'b': getAverageOfRank("b")[1]["toEnterTR"],
'b-': getAverageOfRank("b-")[1]["toEnterTR"],
'c+': getAverageOfRank("c+")[1]["toEnterTR"],
'c': getAverageOfRank("c")[1]["toEnterTR"],
'c-': getAverageOfRank("c-")[1]["toEnterTR"],
'd+': getAverageOfRank("d+")[1]["toEnterTR"],
'd': getAverageOfRank("d")[1]["toEnterTR"]
}; };
Map<String, double> get cutoffsGlicko => { Map<String, double> get cutoffsGlicko => {
'x': getAverageOfRank("x")[1]["toEnterGlicko"], 'x': getRankData("x")[1]["toEnterGlicko"],
'u': getAverageOfRank("u")[1]["toEnterGlicko"], 'u': getRankData("u")[1]["toEnterGlicko"],
'ss': getAverageOfRank("ss")[1]["toEnterGlicko"], 'ss': getRankData("ss")[1]["toEnterGlicko"],
's+': getAverageOfRank("s+")[1]["toEnterGlicko"], 's+': getRankData("s+")[1]["toEnterGlicko"],
's': getAverageOfRank("s")[1]["toEnterGlicko"], 's': getRankData("s")[1]["toEnterGlicko"],
's-': getAverageOfRank("s-")[1]["toEnterGlicko"], 's-': getRankData("s-")[1]["toEnterGlicko"],
'a+': getAverageOfRank("a+")[1]["toEnterGlicko"], 'a+': getRankData("a+")[1]["toEnterGlicko"],
'a': getAverageOfRank("a")[1]["toEnterGlicko"], 'a': getRankData("a")[1]["toEnterGlicko"],
'a-': getAverageOfRank("a-")[1]["toEnterGlicko"], 'a-': getRankData("a-")[1]["toEnterGlicko"],
'b+': getAverageOfRank("b+")[1]["toEnterGlicko"], 'b+': getRankData("b+")[1]["toEnterGlicko"],
'b': getAverageOfRank("b")[1]["toEnterGlicko"], 'b': getRankData("b")[1]["toEnterGlicko"],
'b-': getAverageOfRank("b-")[1]["toEnterGlicko"], 'b-': getRankData("b-")[1]["toEnterGlicko"],
'c+': getAverageOfRank("c+")[1]["toEnterGlicko"], 'c+': getRankData("c+")[1]["toEnterGlicko"],
'c': getAverageOfRank("c")[1]["toEnterGlicko"], 'c': getRankData("c")[1]["toEnterGlicko"],
'c-': getAverageOfRank("c-")[1]["toEnterGlicko"], 'c-': getRankData("c-")[1]["toEnterGlicko"],
'd+': getAverageOfRank("d+")[1]["toEnterGlicko"], 'd+': getRankData("d+")[1]["toEnterGlicko"],
'd': getAverageOfRank("d")[1]["toEnterGlicko"] 'd': getRankData("d")[1]["toEnterGlicko"]
}; };
TetrioPlayersLeaderboard.fromJson(List<dynamic> json, String t, DateTime ts) { TetrioPlayersLeaderboard.fromJson(List<dynamic> json, String t, DateTime ts) {

View File

@ -68,10 +68,10 @@ class CompareState extends State<CompareView> {
try { try {
if (user.startsWith("\$avg")){ if (user.startsWith("\$avg")){
try{ try{
var average = (await teto.fetchTLLeaderboard()).getAverageOfRank(user.substring(4).toLowerCase())[0]; //var average = (await teto.fetchTLLeaderboard()).getAverageOfRank(user.substring(4).toLowerCase())[0];
Summaries summary = Summaries("avg${user.substring(4).toLowerCase()}", average, TetrioZen(level: 0, score: 0)); //Summaries summary = Summaries("avg${user.substring(4).toLowerCase()}", average, TetrioZen(level: 0, score: 0));
redSideMode = Mode.averages; redSideMode = Mode.averages;
theRedSide = [null, null, summary]; //theRedSide = [null, null, summary];
return setState(() {}); return setState(() {});
}on Exception { }on Exception {
if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.compareViewWrongValue(value: user)))); if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.compareViewWrongValue(value: user))));
@ -147,10 +147,10 @@ class CompareState extends State<CompareView> {
try { try {
if (user.startsWith("\$avg")){ if (user.startsWith("\$avg")){
try{ try{
var average = (await teto.fetchTLLeaderboard()).getAverageOfRank(user.substring(4).toLowerCase())[0]; //var average = (await teto.fetchTLLeaderboard()).getAverageOfRank(user.substring(4).toLowerCase())[0];
Summaries summary = Summaries("avg${user.substring(4).toLowerCase()}", average, TetrioZen(level: 0, score: 0)); //Summaries summary = Summaries("avg${user.substring(4).toLowerCase()}", average, TetrioZen(level: 0, score: 0));
greenSideMode = Mode.averages; greenSideMode = Mode.averages;
theGreenSide = [null, null, summary]; //theGreenSide = [null, null, summary];
return setState(() {}); return setState(() {});
}on Exception { }on Exception {
if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Falied to assign $user"))); if (context.mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("Falied to assign $user")));

View File

@ -211,7 +211,12 @@ class _DestinationCutoffsState extends State<DestinationCutoffs> {
), ),
Padding( Padding(
padding: const EdgeInsets.only(right: 8.0), padding: const EdgeInsets.only(right: 8.0),
child: Text("More info", textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)), child: TextButton(child: Text("More Info", textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)), onPressed: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => RankView(rank: "", nextRankTR: snapshot.data!.data["top1"]!.tr, nextRankPercentile: 0.00, nextRankTargetTR: 25000.00, totalPlayers: snapshot.data!.total, cutoffTetrio: CutoffTetrio(apm: 0, pps: 0, vs: 0, pos: 0, percentile: 0, count: snapshot.data!.total, countPercentile: 1, tr: 10000.00, targetTr: 10000.00)),
),
);
},),
), ),
] ]
), ),

View File

@ -166,6 +166,8 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
} }
fetchData = false; fetchData = false;
historyPlayerUsername.value = await teto.getNicknameByID(widget.searchFor);
return historyData; return historyData;
} }

View File

@ -1,11 +1,14 @@
import 'dart:async'; import 'dart:async';
import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tetra_stats/data_objects/tetrio_constants.dart'; import 'package:tetra_stats/data_objects/tetrio_constants.dart';
import 'package:tetra_stats/data_objects/tetrio_player_from_leaderboard.dart';
import 'package:tetra_stats/gen/strings.g.dart'; import 'package:tetra_stats/gen/strings.g.dart';
import 'package:tetra_stats/main.dart'; import 'package:tetra_stats/main.dart';
import 'package:tetra_stats/utils/numers_formats.dart'; import 'package:tetra_stats/utils/numers_formats.dart';
import 'package:tetra_stats/utils/relative_timestamps.dart'; import 'package:tetra_stats/utils/relative_timestamps.dart';
import 'package:tetra_stats/views/main_view_tiles.dart'; import 'package:tetra_stats/views/main_view_tiles.dart';
import 'package:tetra_stats/views/tl_leaderboard_view.dart';
import 'package:tetra_stats/views/user_view.dart'; import 'package:tetra_stats/views/user_view.dart';
class DestinationLeaderboards extends StatefulWidget{ class DestinationLeaderboards extends StatefulWidget{
@ -46,12 +49,20 @@ class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
Stream<List<dynamic>> get dataStream => _dataStreamController.stream; Stream<List<dynamic>> get dataStream => _dataStreamController.stream;
List<dynamic> list = []; List<dynamic> list = [];
bool _isFetchingData = false; bool _isFetchingData = false;
List<String> _excludeRanks = [];
bool _reverse = false;
String? prisecter; String? prisecter;
List<DropdownMenuEntry> _countries = [for (MapEntry e in t.countries.entries) DropdownMenuEntry(value: e.key, label: e.value)]; List<DropdownMenuEntry> _countries = [for (MapEntry e in t.countries.entries) DropdownMenuEntry(value: e.key, label: e.value)];
List<DropdownMenuEntry> _stats = [for (MapEntry e in chartsShortTitles.entries) DropdownMenuEntry(value: e.key, label: e.value)]; List<DropdownMenuEntry> _stats = [for (MapEntry e in chartsShortTitles.entries) DropdownMenuEntry(value: e.key, label: e.value)];
String? _country; String? _country;
Stats stat = Stats.tr; Stats stat = Stats.tr;
bool? getTotalFilterValue(){
if (_excludeRanks.isEmpty) return true;
if (_excludeRanks.length == ranks.length) return false;
return null;
}
Future<void> _fetchData() async { Future<void> _fetchData() async {
if (_isFetchingData) { if (_isFetchingData) {
// Avoid fetching new data while already fetching // Avoid fetching new data while already fetching
@ -72,7 +83,9 @@ class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
Leaderboards.zenithex => await teto.fetchTetrioRecordsLeaderboard(prisecter: prisecter, lb: "zenithex_global", country: _country), Leaderboards.zenithex => await teto.fetchTetrioRecordsLeaderboard(prisecter: prisecter, lb: "zenithex_global", country: _country),
}; };
list.addAll(items); if (_currentLb == Leaderboards.fullTL && _excludeRanks.isNotEmpty) items.removeWhere((e) => _excludeRanks.indexOf((e as TetrioPlayerFromLeaderboard).rank) != -1);
list.addAll((_reverse && _currentLb == Leaderboards.fullTL) ? items.reversed : items);
_dataStreamController.add(list); _dataStreamController.add(list);
prisecter = list.last.prisecter.toString(); prisecter = list.last.prisecter.toString();
@ -129,10 +142,10 @@ class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
itemCount: leaderboards.length, itemCount: leaderboards.length,
itemBuilder: (BuildContext context, int index) { itemBuilder: (BuildContext context, int index) {
return Card( return Card(
surfaceTintColor: index == 1 ? Colors.redAccent : theme.colorScheme.primary,
child: ListTile( child: ListTile(
title: Text(leaderboards.values.elementAt(index)), title: Text(leaderboards.values.elementAt(index)),
subtitle: index == 1 ? Text("Heavy, but allows you to sort players by their stats", style: TextStyle(color: Colors.grey, fontSize: 12)) : null, trailing: Icon(Icons.arrow_right, color: _currentLb.index == index ? Colors.white : Colors.grey),
subtitle: index == 1 ? Text("Heavy, but allows you to sort players by their stats and filter them by ranks", style: TextStyle(color: Colors.grey, fontSize: 12)) : null,
onTap: () { onTap: () {
_currentLb = leaderboards.keys.elementAt(index); _currentLb = leaderboards.keys.elementAt(index);
list.clear(); list.clear();
@ -198,6 +211,71 @@ class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
_isFetchingData = false; _isFetchingData = false;
setState((){_fetchData();}); setState((){_fetchData();});
}) })
),
if (_currentLb == Leaderboards.fullTL) IconButton(
color: _excludeRanks.isNotEmpty ? Theme.of(context).colorScheme.primary : null,
onPressed: (){
showDialog(context: context, builder: (BuildContext context) {
return StatefulBuilder(
builder: (context, StateSetter setAlertState) {
return AlertDialog(
title: Text("Filter", textAlign: TextAlign.center),
content: SingleChildScrollView(
child: Column(
children: [
CheckboxListTile(value: getTotalFilterValue(), tristate: true, title: Text("All", style: TextStyle(fontFamily: "Eurostile Round Extended")), onChanged: (value){
setAlertState(
(){
if (_excludeRanks.length*2 > ranks.length){
_excludeRanks.clear();
}else{
_excludeRanks = List.of(ranks);
}
}
);
}),
for(String rank in ranks.reversed) CheckboxListTile(value: _excludeRanks.indexOf(rank) == -1, onChanged: (value){
setAlertState(
(){
if (_excludeRanks.indexOf(rank) == -1){
_excludeRanks.add(rank);
}else{
_excludeRanks.remove(rank);
}
}
);
}, title: Text(rank.toUpperCase()),)
],
),
),
actions: <Widget>[
TextButton(
child: const Text("Apply"),
onPressed: () {Navigator.of(context).pop(); setState((){
_currentLb = Leaderboards.fullTL;
list.clear();
prisecter = null;
_fetchData();});
}
)
]
);
}
);
});
}, icon: Icon(Icons.filter_alt)),
if (_currentLb == Leaderboards.fullTL) IconButton(
color: _reverse ? Theme.of(context).colorScheme.primary : null,
icon: Container(transform: _reverse ? Matrix4.rotationX(pi) : null, child: Icon(Icons.filter_list)),
onPressed: (){
setState((){
_reverse = !_reverse;
_currentLb = Leaderboards.fullTL;
list.clear();
prisecter = null;
_fetchData();
});
},
) )
], ],
), ),

View File

@ -1,6 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:tetra_stats/data_objects/cutoff_tetrio.dart'; import 'package:tetra_stats/data_objects/cutoff_tetrio.dart';
import 'package:tetra_stats/main.dart';
import 'package:tetra_stats/utils/numers_formats.dart'; import 'package:tetra_stats/utils/numers_formats.dart';
import 'package:tetra_stats/views/main_view_tiles.dart';
class RankView extends StatefulWidget { class RankView extends StatefulWidget {
final String rank; final String rank;
@ -25,6 +27,11 @@ enum CardMod{
class _RankState extends State<RankView> { class _RankState extends State<RankView> {
CardMod cardMod = CardMod.graph; CardMod cardMod = CardMod.graph;
Future<List> getRanksAverages(String rank) async {
var lb = await teto.fetchTLLeaderboard();
return lb.getRankData(rank);
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double percentileGap = widget.cutoffTetrio.percentile - widget.nextRankPercentile; double percentileGap = widget.cutoffTetrio.percentile - widget.nextRankPercentile;
@ -228,36 +235,141 @@ class _RankState extends State<RankView> {
) )
], ],
), ),
), )
), ),
SizedBox( SizedBox(
width: constraints.maxWidth - 350, width: constraints.maxWidth - 350,
height: constraints.maxHeight, child: FutureBuilder<List<dynamic>>(
child: Row( future: getRanksAverages(widget.rank),
children: [ builder: (context, snapshot) {
SizedBox( switch (snapshot.connectionState){
width: 200.0, case ConnectionState.none:
child: Card( case ConnectionState.waiting:
child: Column( case ConnectionState.active:
children: [], return const Center(child: CircularProgressIndicator());
), case ConnectionState.done:
), if (snapshot.hasError){ return FutureError(snapshot); }
), if (snapshot.hasData){
Expanded( return SingleChildScrollView(
child: Card( child: Row(
child: Column( crossAxisAlignment: CrossAxisAlignment.start,
children: [], children: [
), SizedBox(
), width: 200.0,
), child: Card(
Expanded( child: Column(
child: Card( children: [
child: Column( Text("Cheese Index", style: TextStyle(fontSize: 28, color: Colors.transparent)),
children: [], Divider(),
), RankViewEntry("Tetra Rating", null, null),
), RankViewEntry("Glicko", null, null, differentBG: true),
) RankViewEntry("RD", null, null),
], RankViewEntry("Glixare", null, null, differentBG: true),
RankViewEntry("S1 TR", null, null),
RankViewEntry("Games Played", null, null, differentBG: true),
RankViewEntry("Games Won", null, null),
RankViewEntry("Winrate", null, null, differentBG: true),
RankViewEntry("Attack Per Minute", null, null),
RankViewEntry("Pieces Per Second", null, null, differentBG: true),
RankViewEntry("Versus Score", null, null),
RankViewEntry("Attack Per Piece", null, null, differentBG: true),
RankViewEntry("VS / APM", null, null),
RankViewEntry("Downstack Per Second", null, null, differentBG: true),
RankViewEntry("Downstack Per Piece", null, null),
RankViewEntry("APP + DS/P", null, null, differentBG: true),
RankViewEntry("Cheese Index", null, null),
RankViewEntry("Garbage Efficiency", null, null, differentBG: true),
RankViewEntry("Weighted APP", null, null),
RankViewEntry("Area", null, null, differentBG: true),
RankViewEntry("Estimated TR", null, null),
RankViewEntry("Est. TR Accuracy", null, null, differentBG: true),
RankViewEntry("Opener", null, null),
RankViewEntry("Plonk", null, null, differentBG: true),
RankViewEntry("Stride", null, null),
RankViewEntry("Infinite Downstack", null, null, differentBG: true),
],
),
),
),
Expanded(
child: Card(
child: Column(
children: [
Text("Minimums", style: TextStyle(fontSize: 28)),
Divider(),
RankViewEntry("${f4.format(snapshot.data![1]["lowestTR"])} TR", snapshot.data![1]["lowestTRnick"], snapshot.data![1]["lowestTRid"]),
RankViewEntry(f4.format(snapshot.data![1]["lowestGlicko"]), snapshot.data![1]["lowestGlickoNick"], snapshot.data![1]["lowestGlickoID"], differentBG: true),
RankViewEntry(f4.format(snapshot.data![1]["lowestRD"]), snapshot.data![1]["lowestRdNick"], snapshot.data![1]["lowestRdID"]),
RankViewEntry(f4.format(snapshot.data![1]["lowestGlixare"]), snapshot.data![1]["lowestGlixareNick"], snapshot.data![1]["lowestGlixareID"], differentBG: true),
RankViewEntry(f2.format(snapshot.data![1]["lowestS1tr"]), snapshot.data![1]["lowestS1trNick"], snapshot.data![1]["lowestS1trID"]),
RankViewEntry(intf.format(snapshot.data![1]["lowestGamesPlayed"]), snapshot.data![1]["lowestGamesPlayedNick"], snapshot.data![1]["lowestGamesPlayedID"], differentBG: true),
RankViewEntry(intf.format(snapshot.data![1]["lowestGamesWon"]), snapshot.data![1]["lowestGamesWonNick"], snapshot.data![1]["lowestGamesWonID"]),
RankViewEntry(percentage.format(snapshot.data![1]["lowestWinrate"]), snapshot.data![1]["lowestWinrateNick"], snapshot.data![1]["lowestWinrateID"], differentBG: true),
RankViewEntry("${f2.format(snapshot.data![1]["lowestAPM"])} APM", snapshot.data![1]["lowestAPMnick"], snapshot.data![1]["lowestAPMid"]),
RankViewEntry("${f2.format(snapshot.data![1]["lowestPPS"])} PPS", snapshot.data![1]["lowestPPSnick"], snapshot.data![1]["lowestPPSid"], differentBG: true),
RankViewEntry("${f2.format(snapshot.data![1]["lowestVS"])} VS", snapshot.data![1]["lowestVSnick"], snapshot.data![1]["lowestVSid"]),
RankViewEntry("${f4.format(snapshot.data![1]["lowestAPP"])} APP", snapshot.data![1]["lowestAPPnick"], snapshot.data![1]["lowestAPPid"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["lowestVSAPM"])} VS/APM", snapshot.data![1]["lowestVSAPMnick"], snapshot.data![1]["lowestVSAPMid"]),
RankViewEntry("${f4.format(snapshot.data![1]["lowestDSS"])} DS/S", snapshot.data![1]["lowestDSSnick"], snapshot.data![1]["lowestDSSid"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["lowestDSP"])} DS/P", snapshot.data![1]["lowestDSPnick"], snapshot.data![1]["lowestDSPid"]),
RankViewEntry("${f4.format(snapshot.data![1]["lowestAPPDSP"])} APP+DS/P", snapshot.data![1]["lowestAPPDSPnick"], snapshot.data![1]["lowestAPPDSPid"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["lowestCheese"])} Cheese", snapshot.data![1]["lowestCheeseNick"], snapshot.data![1]["lowestCheeseID"]),
RankViewEntry("${f4.format(snapshot.data![1]["lowestGBE"])} Gbe", snapshot.data![1]["lowestGBEnick"], snapshot.data![1]["lowestGBEid"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["lowestNyaAPP"])} wAPP", snapshot.data![1]["lowestNyaAPPnick"], snapshot.data![1]["lowestNyaAPPid"]),
RankViewEntry("${f4.format(snapshot.data![1]["lowestArea"])} Area", snapshot.data![1]["lowestAreaNick"], snapshot.data![1]["lowestAreaID"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["lowestEstTR"])} eTR", snapshot.data![1]["lowestEstTRnick"], snapshot.data![1]["lowestEstTRid"]),
RankViewEntry("${f4.format(snapshot.data![1]["lowestEstAcc"])} ±eTR", snapshot.data![1]["lowestEstAccNick"], snapshot.data![1]["lowestEstAccID"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["lowestOpener"])}", snapshot.data![1]["lowestOpenerNick"], snapshot.data![1]["lowestOpenerID"]),
RankViewEntry("${f4.format(snapshot.data![1]["lowestPlonk"])}", snapshot.data![1]["lowestPlonkNick"], snapshot.data![1]["lowestPlonkID"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["lowestStride"])}", snapshot.data![1]["lowestStrideNick"], snapshot.data![1]["lowestStrideID"]),
RankViewEntry("${f4.format(snapshot.data![1]["lowestInfDS"])}", snapshot.data![1]["lowestInfDSnick"], snapshot.data![1]["lowestInfDSid"], differentBG: true)
],
),
),
),
Expanded(
child: Card(
child: Column(
children: [
Text("Maximums", style: TextStyle(fontSize: 28)),
Divider(),
RankViewEntry("${f4.format(snapshot.data![1]["highestTR"])} TR", snapshot.data![1]["highestTRnick"], snapshot.data![1]["highestTRid"]),
RankViewEntry(f4.format(snapshot.data![1]["highestGlicko"]), snapshot.data![1]["highestGlickoNick"], snapshot.data![1]["highestGlickoID"], differentBG: true),
RankViewEntry(f4.format(snapshot.data![1]["highestRD"]), snapshot.data![1]["highestRdNick"], snapshot.data![1]["highestRdID"]),
RankViewEntry(f4.format(snapshot.data![1]["highestGlixare"]), snapshot.data![1]["highestGlixareNick"], snapshot.data![1]["highestGlixareID"], differentBG: true),
RankViewEntry(f2.format(snapshot.data![1]["highestS1tr"]), snapshot.data![1]["highestS1trNick"], snapshot.data![1]["highestS1trID"]),
RankViewEntry(intf.format(snapshot.data![1]["highestGamesPlayed"]), snapshot.data![1]["highestGamesPlayedNick"], snapshot.data![1]["highestGamesPlayedID"], differentBG: true),
RankViewEntry(intf.format(snapshot.data![1]["highestGamesWon"]), snapshot.data![1]["highestGamesWonNick"], snapshot.data![1]["highestGamesWonID"]),
RankViewEntry(percentage.format(snapshot.data![1]["highestWinrate"]), snapshot.data![1]["highestWinrateNick"], snapshot.data![1]["highestWinrateID"], differentBG: true),
RankViewEntry("${f2.format(snapshot.data![1]["highestAPM"])} APM", snapshot.data![1]["highestAPMnick"], snapshot.data![1]["highestAPMid"]),
RankViewEntry("${f2.format(snapshot.data![1]["highestPPS"])} PPS", snapshot.data![1]["highestPPSnick"], snapshot.data![1]["highestPPSid"], differentBG: true),
RankViewEntry("${f2.format(snapshot.data![1]["highestVS"])} VS", snapshot.data![1]["highestVSnick"], snapshot.data![1]["highestVSid"]),
RankViewEntry("${f4.format(snapshot.data![1]["highestAPP"])} APP", snapshot.data![1]["highestAPPnick"], snapshot.data![1]["highestAPPid"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["highestVSAPM"])} VS/APM", snapshot.data![1]["highestVSAPMnick"], snapshot.data![1]["highestVSAPMid"]),
RankViewEntry("${f4.format(snapshot.data![1]["highestDSS"])} DS/S", snapshot.data![1]["highestDSSnick"], snapshot.data![1]["highestDSSid"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["highestDSP"])} DS/P", snapshot.data![1]["highestDSPnick"], snapshot.data![1]["highestDSPid"]),
RankViewEntry("${f4.format(snapshot.data![1]["highestAPPDSP"])} APP+DS/P", snapshot.data![1]["highestAPPDSPnick"], snapshot.data![1]["highestAPPDSPid"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["highestCheese"])} Cheese", snapshot.data![1]["highestCheeseNick"], snapshot.data![1]["highestCheeseID"]),
RankViewEntry("${f4.format(snapshot.data![1]["highestGBE"])} Gbe", snapshot.data![1]["highestGBEnick"], snapshot.data![1]["highestGBEid"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["highestNyaAPP"])} wAPP", snapshot.data![1]["highestNyaAPPnick"], snapshot.data![1]["highestNyaAPPid"]),
RankViewEntry("${f4.format(snapshot.data![1]["highestArea"])} Area", snapshot.data![1]["highestAreaNick"], snapshot.data![1]["highestAreaID"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["highestEstTR"])} eTR", snapshot.data![1]["highestEstTRnick"], snapshot.data![1]["highestEstTRid"]),
RankViewEntry("${f4.format(snapshot.data![1]["highestEstAcc"])} ±eTR", snapshot.data![1]["highestEstAccNick"], snapshot.data![1]["highestEstAccID"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["highestOpener"])}", snapshot.data![1]["highestOpenerNick"], snapshot.data![1]["highestOpenerID"]),
RankViewEntry("${f4.format(snapshot.data![1]["highestPlonk"])}", snapshot.data![1]["highestPlonkNick"], snapshot.data![1]["highestPlonkID"], differentBG: true),
RankViewEntry("${f4.format(snapshot.data![1]["highestStride"])}", snapshot.data![1]["highestStrideNick"], snapshot.data![1]["highestStrideID"]),
RankViewEntry("${f4.format(snapshot.data![1]["highestInfDS"])}", snapshot.data![1]["highestInfDSnick"], snapshot.data![1]["highestInfDSid"], differentBG: true)
],
),
),
)
],
),
);
}
}
return const Text("End of FutureBuilder<List>");
}
), ),
) )
], ],
@ -267,3 +379,34 @@ class _RankState extends State<RankView> {
); );
} }
} }
class RankViewEntry extends StatelessWidget {
final String formattedValue;
final String? username;
final String? userId;
final bool differentBG;
const RankViewEntry(this.formattedValue, this.username, this.userId, {this.differentBG = false});
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(color: differentBG ? Colors.black26 : null),
child: Center(
child: Padding(
padding: username != null ? EdgeInsets.only(bottom: 4.0) : EdgeInsets.all(0),
child: RichText(
textAlign: TextAlign.center,
text: TextSpan(
text: formattedValue,
style: Theme.of(context).textTheme.displayLarge,
children: [
TextSpan(text: username != null ? "\n(${username!.toUpperCase()})" : "\n", style: Theme.of(context).textTheme.displayLarge!.copyWith(color: Colors.grey, fontSize: 14))
]
)),
),
),
);
}
}

View File

@ -95,7 +95,7 @@ class TLLeaderboardState extends State<TLLeaderboardView> {
Navigator.push( Navigator.push(
context, context,
MaterialPageRoute( MaterialPageRoute(
builder: (context) => RankView(rank: snapshot.data!.getAverageOfRank("")), builder: (context) => RankView(rank: snapshot.data!.getRankData("")),
), ),
); );
}, child: Text(t.everyoneAverages, }, child: Text(t.everyoneAverages,