detailed stats for rank (not finished) + bug fix
This commit is contained in:
parent
f7784cb494
commit
518f2db7ea
|
@ -894,32 +894,214 @@ class TetrioPlayersLeaderboard {
|
||||||
TetrioPlayersLeaderboard(this.type, this.leaderboard);
|
TetrioPlayersLeaderboard(this.type, this.leaderboard);
|
||||||
|
|
||||||
List<dynamic> getAverageOfRank(String rank){
|
List<dynamic> getAverageOfRank(String rank){
|
||||||
|
if (rank.isNotEmpty && !rankCutoffs.keys.contains(rank)) throw Exception("Invalid rank");
|
||||||
List<TetrioPlayerFromLeaderboard> filtredLeaderboard = List.from(leaderboard);
|
List<TetrioPlayerFromLeaderboard> filtredLeaderboard = List.from(leaderboard);
|
||||||
filtredLeaderboard.removeWhere((element) => element.rank != rank);
|
if (rank.isNotEmpty) {
|
||||||
if (filtredLeaderboard.isEmpty) throw Exception("Invalid rank");
|
filtredLeaderboard.removeWhere((element) => element.rank != rank);
|
||||||
double avgAPM = 0, avgPPS = 0, avgVS = 0, avgTR = 0, avgGlicko = 0, avgRD = 0, lowestTR = 25000;
|
} else {
|
||||||
int avgGamesPlayed = 0, avgGamesWon = 0, totalGamesPlayed = 0, totalGamesWon = 0;
|
rank = "z";
|
||||||
for (var entry in filtredLeaderboard){
|
}
|
||||||
avgAPM += entry.apm;
|
if (filtredLeaderboard.isNotEmpty){
|
||||||
avgPPS += entry.pps;
|
double avgAPM = 0,
|
||||||
avgVS += entry.vs;
|
avgPPS = 0,
|
||||||
avgTR += entry.rating;
|
avgVS = 0,
|
||||||
avgGlicko += entry.glicko;
|
avgTR = 0,
|
||||||
avgRD += entry.rd;
|
avgGlicko = 0,
|
||||||
totalGamesPlayed += entry.gamesPlayed;
|
avgRD = 0,
|
||||||
totalGamesWon += entry.gamesWon;
|
lowestTR = 25000,
|
||||||
if (entry.rating < lowestTR) lowestTR = entry.rating;
|
lowestGlicko = double.infinity,
|
||||||
|
lowestWinrate = double.infinity,
|
||||||
|
lowestAPM = double.infinity,
|
||||||
|
lowestPPS = double.infinity,
|
||||||
|
lowestVS = double.infinity,
|
||||||
|
highestTR = 0,
|
||||||
|
highestGlicko = 0,
|
||||||
|
highestWinrate = 0,
|
||||||
|
highestAPM = 0,
|
||||||
|
highestPPS = 0,
|
||||||
|
highestVS = 0;
|
||||||
|
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 = "",
|
||||||
|
lowestGamesPlayedID = "", lowestGamesPlayedNick = "",
|
||||||
|
lowestGamesWonID = "", lowestGamesWonNick = "",
|
||||||
|
lowestWinrateID = "", lowestWinrateNick = "",
|
||||||
|
lowestAPMid = "", lowestAPMnick = "",
|
||||||
|
lowestPPSid = "", lowestPPSnick = "",
|
||||||
|
lowestVSid = "", lowestVSnick = "",
|
||||||
|
highestTRid = "", highestTRnick = "",
|
||||||
|
highestGlickoID = "", highestGlickoNick = "",
|
||||||
|
highestGamesPlayedID = "", highestGamesPlayedNick = "",
|
||||||
|
highestGamesWonID = "", highestGamesWonNick = "",
|
||||||
|
highestWinrateID = "", highestWinrateNick = "",
|
||||||
|
highestAPMid = "", highestAPMnick = "",
|
||||||
|
highestPPSid = "", highestPPSnick = "",
|
||||||
|
highestVSid = "", highestVSnick = "";
|
||||||
|
for (var entry in filtredLeaderboard){
|
||||||
|
avgAPM += entry.apm;
|
||||||
|
avgPPS += entry.pps;
|
||||||
|
avgVS += entry.vs;
|
||||||
|
avgTR += entry.rating;
|
||||||
|
avgGlicko += entry.glicko;
|
||||||
|
avgRD += entry.rd;
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
if (entry.gamesPlayed < lowestGamesPlayed){
|
||||||
|
lowestGamesPlayed = entry.gamesPlayed;
|
||||||
|
lowestGamesPlayedID = entry.userId;
|
||||||
|
lowestGamesPlayedNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.gamesWon < lowestGamesWon){
|
||||||
|
lowestGamesWon = entry.gamesWon;
|
||||||
|
lowestGamesWonID = entry.userId;
|
||||||
|
lowestGamesWonNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.winrate < lowestWinrate){
|
||||||
|
lowestWinrate = entry.winrate;
|
||||||
|
lowestWinrateID = entry.userId;
|
||||||
|
lowestWinrateNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.apm < lowestAPM){
|
||||||
|
lowestAPM = entry.apm;
|
||||||
|
lowestAPMid = entry.userId;
|
||||||
|
lowestAPMnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.pps < lowestPPS){
|
||||||
|
lowestPPS = entry.pps;
|
||||||
|
lowestPPSid = entry.userId;
|
||||||
|
lowestPPSnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.vs < lowestVS){
|
||||||
|
lowestVS = entry.vs;
|
||||||
|
lowestVSid = entry.userId;
|
||||||
|
lowestVSnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.rating > highestTR){
|
||||||
|
highestTR = entry.rating;
|
||||||
|
highestTRid = entry.userId;
|
||||||
|
highestTRnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.glicko > highestGlicko){
|
||||||
|
highestGlicko = entry.glicko;
|
||||||
|
highestGlickoID = entry.userId;
|
||||||
|
highestGlickoNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.gamesPlayed > highestGamesPlayed){
|
||||||
|
highestGamesPlayed = entry.gamesPlayed;
|
||||||
|
highestGamesPlayedID = entry.userId;
|
||||||
|
highestGamesPlayedNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.gamesWon > highestGamesWon){
|
||||||
|
highestGamesWon = entry.gamesWon;
|
||||||
|
highestGamesWonID = entry.userId;
|
||||||
|
highestGamesWonNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.winrate > highestWinrate){
|
||||||
|
highestWinrate = entry.winrate;
|
||||||
|
highestWinrateID = entry.userId;
|
||||||
|
highestWinrateNick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.apm > highestAPM){
|
||||||
|
highestAPM = entry.apm;
|
||||||
|
highestAPMid = entry.userId;
|
||||||
|
highestAPMnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.pps > highestPPS){
|
||||||
|
highestPPS = entry.pps;
|
||||||
|
highestPPSid = entry.userId;
|
||||||
|
highestPPSnick = entry.username;
|
||||||
|
}
|
||||||
|
if (entry.vs > highestVS){
|
||||||
|
highestVS = entry.vs;
|
||||||
|
highestVSid = entry.userId;
|
||||||
|
highestVSnick = entry.username;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avgAPM /= filtredLeaderboard.length;
|
||||||
|
avgPPS /= filtredLeaderboard.length;
|
||||||
|
avgVS /= filtredLeaderboard.length;
|
||||||
|
avgTR /= filtredLeaderboard.length;
|
||||||
|
avgGlicko /= filtredLeaderboard.length;
|
||||||
|
avgRD /= filtredLeaderboard.length;
|
||||||
|
avgGamesPlayed = (totalGamesPlayed / filtredLeaderboard.length).floor();
|
||||||
|
avgGamesWon = (totalGamesWon / filtredLeaderboard.length).floor();
|
||||||
|
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, percentileRank: rank, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1),
|
||||||
|
{
|
||||||
|
"totalGamesPlayed": totalGamesPlayed,
|
||||||
|
"totalGamesWon": totalGamesWon,
|
||||||
|
"players": filtredLeaderboard.length,
|
||||||
|
"lowestTR": lowestTR,
|
||||||
|
"lowestTRid": lowestTRid,
|
||||||
|
"lowestTRnick": lowestTRnick,
|
||||||
|
"lowestGlicko": lowestGlicko,
|
||||||
|
"lowestGlickoID": lowestGlickoID,
|
||||||
|
"lowestGlickoNick": lowestGlickoNick,
|
||||||
|
"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,
|
||||||
|
"highestTR": highestTR,
|
||||||
|
"highestTRid": highestTRid,
|
||||||
|
"highestTRnick": highestTRnick,
|
||||||
|
"highestGlicko": highestGlicko,
|
||||||
|
"highestGlickoID": highestGlickoID,
|
||||||
|
"highestGlickoNick": highestGlickoNick,
|
||||||
|
"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,
|
||||||
|
"toEnterTR": rank.toLowerCase() != "z" ? leaderboard[(leaderboard.length * rankCutoffs[rank]!).floor()-1].rating : lowestTR,
|
||||||
|
"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),
|
||||||
|
{"players": filtredLeaderboard.length, "lowestTR": 0, "toEnterTR": 0}];
|
||||||
}
|
}
|
||||||
avgAPM /= filtredLeaderboard.length;
|
|
||||||
avgPPS /= filtredLeaderboard.length;
|
|
||||||
avgVS /= filtredLeaderboard.length;
|
|
||||||
avgTR /= filtredLeaderboard.length;
|
|
||||||
avgGlicko /= filtredLeaderboard.length;
|
|
||||||
avgRD /= filtredLeaderboard.length;
|
|
||||||
avgGamesPlayed = (totalGamesPlayed / filtredLeaderboard.length).floor();
|
|
||||||
avgGamesWon = (totalGamesWon / filtredLeaderboard.length).floor();
|
|
||||||
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, percentileRank: rank, percentile: 0, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1),
|
|
||||||
{"totalGamesPlayed": totalGamesPlayed, "totalGamesWon": totalGamesWon, "players": filtredLeaderboard.length, "lowestTR": lowestTR, "toEnterTR": leaderboard[(leaderboard.length * rankCutoffs[rank]!).floor()-1].rating}];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, List<dynamic>> get averages => {
|
Map<String, List<dynamic>> get averages => {
|
||||||
|
@ -939,7 +1121,8 @@ class TetrioPlayersLeaderboard {
|
||||||
'c': getAverageOfRank("c"),
|
'c': getAverageOfRank("c"),
|
||||||
'c-': getAverageOfRank("c-"),
|
'c-': getAverageOfRank("c-"),
|
||||||
'd+': getAverageOfRank("d+"),
|
'd+': getAverageOfRank("d+"),
|
||||||
'd': getAverageOfRank("d")
|
'd': getAverageOfRank("d"),
|
||||||
|
'z': getAverageOfRank("z")
|
||||||
};
|
};
|
||||||
|
|
||||||
TetrioPlayersLeaderboard.fromJson(List<dynamic> json, String t, DateTime ts) {
|
TetrioPlayersLeaderboard.fromJson(List<dynamic> json, String t, DateTime ts) {
|
||||||
|
@ -994,6 +1177,7 @@ class TetrioPlayerFromLeaderboard {
|
||||||
this.vs,
|
this.vs,
|
||||||
this.decaying);
|
this.decaying);
|
||||||
|
|
||||||
|
double get winrate => gamesWon / gamesPlayed;
|
||||||
get app => apm / (pps * 60);
|
get app => apm / (pps * 60);
|
||||||
get vsapm => vs / apm;
|
get vsapm => vs / apm;
|
||||||
|
|
||||||
|
|
|
@ -135,7 +135,7 @@ class TetrioService extends DB {
|
||||||
);
|
);
|
||||||
history.add(state);
|
history.add(state);
|
||||||
}
|
}
|
||||||
ensureDbIsOpen();
|
await ensureDbIsOpen();
|
||||||
final db = getDatabaseOrThrow();
|
final db = getDatabaseOrThrow();
|
||||||
late List<TetrioPlayer> states;
|
late List<TetrioPlayer> states;
|
||||||
try{
|
try{
|
||||||
|
@ -237,7 +237,7 @@ class TetrioService extends DB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> saveTLMatchesFromStream(TetraLeagueAlphaStream stream) async {
|
Future<void> saveTLMatchesFromStream(TetraLeagueAlphaStream stream) async {
|
||||||
ensureDbIsOpen();
|
await ensureDbIsOpen();
|
||||||
final db = getDatabaseOrThrow();
|
final db = getDatabaseOrThrow();
|
||||||
for (TetraLeagueAlphaRecord match in stream.records) {
|
for (TetraLeagueAlphaRecord match in stream.records) {
|
||||||
final results = await db.query(tetraLeagueMatchesTable, where: '$idCol = ?', whereArgs: [match.ownId]);
|
final results = await db.query(tetraLeagueMatchesTable, where: '$idCol = ?', whereArgs: [match.ownId]);
|
||||||
|
@ -247,7 +247,7 @@ class TetrioService extends DB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<TetraLeagueAlphaRecord>> getTLMatchesbyPlayerID(String playerID) async {
|
Future<List<TetraLeagueAlphaRecord>> getTLMatchesbyPlayerID(String playerID) async {
|
||||||
ensureDbIsOpen();
|
await ensureDbIsOpen();
|
||||||
final db = getDatabaseOrThrow();
|
final db = getDatabaseOrThrow();
|
||||||
List<TetraLeagueAlphaRecord> matches = [];
|
List<TetraLeagueAlphaRecord> matches = [];
|
||||||
final results = await db.query(tetraLeagueMatchesTable, where: '($player1id = ?) OR ($player2id = ?)', whereArgs: [playerID, playerID]);
|
final results = await db.query(tetraLeagueMatchesTable, where: '($player1id = ?) OR ($player2id = ?)', whereArgs: [playerID, playerID]);
|
||||||
|
@ -304,7 +304,7 @@ class TetrioService extends DB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> createPlayer(TetrioPlayer tetrioPlayer) async {
|
Future<void> createPlayer(TetrioPlayer tetrioPlayer) async {
|
||||||
ensureDbIsOpen();
|
await ensureDbIsOpen();
|
||||||
final db = getDatabaseOrThrow();
|
final db = getDatabaseOrThrow();
|
||||||
final results = await db.query(tetrioUsersTable, limit: 1, where: '$idCol = ?', whereArgs: [tetrioPlayer.userId.toLowerCase()]);
|
final results = await db.query(tetrioUsersTable, limit: 1, where: '$idCol = ?', whereArgs: [tetrioPlayer.userId.toLowerCase()]);
|
||||||
if (results.isNotEmpty) {
|
if (results.isNotEmpty) {
|
||||||
|
@ -319,7 +319,7 @@ class TetrioService extends DB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> addPlayerToTrack(TetrioPlayer tetrioPlayer) async {
|
Future<void> addPlayerToTrack(TetrioPlayer tetrioPlayer) async {
|
||||||
ensureDbIsOpen();
|
await ensureDbIsOpen();
|
||||||
final db = getDatabaseOrThrow();
|
final db = getDatabaseOrThrow();
|
||||||
final results = await db.query(tetrioUsersToTrackTable, where: '$idCol = ?', whereArgs: [tetrioPlayer.userId.toLowerCase()]);
|
final results = await db.query(tetrioUsersToTrackTable, where: '$idCol = ?', whereArgs: [tetrioPlayer.userId.toLowerCase()]);
|
||||||
if (results.isNotEmpty) {
|
if (results.isNotEmpty) {
|
||||||
|
@ -329,7 +329,7 @@ class TetrioService extends DB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> isPlayerTracking(String id) async {
|
Future<bool> isPlayerTracking(String id) async {
|
||||||
ensureDbIsOpen();
|
await ensureDbIsOpen();
|
||||||
final db = getDatabaseOrThrow();
|
final db = getDatabaseOrThrow();
|
||||||
final results = await db.query(tetrioUsersToTrackTable, where: '$idCol = ?', whereArgs: [id.toLowerCase()]);
|
final results = await db.query(tetrioUsersToTrackTable, where: '$idCol = ?', whereArgs: [id.toLowerCase()]);
|
||||||
if (results.isEmpty) {
|
if (results.isEmpty) {
|
||||||
|
@ -360,12 +360,11 @@ class TetrioService extends DB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> storeState(TetrioPlayer tetrioPlayer) async {
|
Future<void> storeState(TetrioPlayer tetrioPlayer) async {
|
||||||
ensureDbIsOpen();
|
await ensureDbIsOpen();
|
||||||
final db = getDatabaseOrThrow();
|
final db = getDatabaseOrThrow();
|
||||||
late List<TetrioPlayer> states;
|
late List<TetrioPlayer> states;
|
||||||
try {
|
try {
|
||||||
states = _players[tetrioPlayer.userId]!;
|
states = _players[tetrioPlayer.userId]!;
|
||||||
//states = await getPlayer(tetrioPlayer.userId);
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
await createPlayer(tetrioPlayer);
|
await createPlayer(tetrioPlayer);
|
||||||
states = await getPlayer(tetrioPlayer.userId);
|
states = await getPlayer(tetrioPlayer.userId);
|
||||||
|
@ -383,7 +382,7 @@ class TetrioService extends DB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deleteState(TetrioPlayer tetrioPlayer) async {
|
Future<void> deleteState(TetrioPlayer tetrioPlayer) async {
|
||||||
ensureDbIsOpen();
|
await ensureDbIsOpen();
|
||||||
final db = getDatabaseOrThrow();
|
final db = getDatabaseOrThrow();
|
||||||
late List<TetrioPlayer> states;
|
late List<TetrioPlayer> states;
|
||||||
states = await getPlayer(tetrioPlayer.userId);
|
states = await getPlayer(tetrioPlayer.userId);
|
||||||
|
@ -400,7 +399,7 @@ class TetrioService extends DB {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<TetrioPlayer>> getPlayer(String id) async {
|
Future<List<TetrioPlayer>> getPlayer(String id) async {
|
||||||
ensureDbIsOpen();
|
await ensureDbIsOpen();
|
||||||
final db = getDatabaseOrThrow();
|
final db = getDatabaseOrThrow();
|
||||||
List<TetrioPlayer> states = [];
|
List<TetrioPlayer> states = [];
|
||||||
final results = await db.query(tetrioUsersTable, limit: 1, where: '$idCol = ?', whereArgs: [id.toLowerCase()]);
|
final results = await db.query(tetrioUsersTable, limit: 1, where: '$idCol = ?', whereArgs: [id.toLowerCase()]);
|
||||||
|
@ -417,7 +416,7 @@ class TetrioService extends DB {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<TetrioPlayer> fetchPlayer(String user) async {
|
Future<TetrioPlayer> fetchPlayer(String user, {bool isItDiscordID = false}) async {
|
||||||
try{
|
try{
|
||||||
var cached = _playersCache.entries.firstWhere((element) => element.value.userId == user || element.value.username == user);
|
var cached = _playersCache.entries.firstWhere((element) => element.value.userId == user || element.value.username == user);
|
||||||
if (DateTime.fromMillisecondsSinceEpoch(int.parse(cached.key.toString()), isUtc: true).isAfter(DateTime.now())){
|
if (DateTime.fromMillisecondsSinceEpoch(int.parse(cached.key.toString()), isUtc: true).isAfter(DateTime.now())){
|
||||||
|
@ -430,7 +429,29 @@ class TetrioService extends DB {
|
||||||
}catch(e){
|
}catch(e){
|
||||||
developer.log("fetchPlayer: Trying to retrieve $user", name: "services/tetrio_crud");
|
developer.log("fetchPlayer: Trying to retrieve $user", name: "services/tetrio_crud");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isItDiscordID){
|
||||||
|
Uri dUrl;
|
||||||
|
if (kIsWeb) {
|
||||||
|
dUrl = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "tetrioUserByDiscordID", "user": user.toLowerCase().trim()});
|
||||||
|
} else {
|
||||||
|
dUrl = Uri.https('ch.tetr.io', 'api/users/search/${user.toLowerCase().trim()}');
|
||||||
|
}
|
||||||
|
final response = await http.get(dUrl);
|
||||||
|
if (response.statusCode == 200) {
|
||||||
|
var json = jsonDecode(response.body);
|
||||||
|
if (json['success'] && json['data'] != null) {
|
||||||
|
user = json['data']['user']['_id'];
|
||||||
|
} else {
|
||||||
|
developer.log("fetchPlayer User dosen't exist", name: "services/tetrio_crud", error: response.body);
|
||||||
|
throw TetrioPlayerNotExist();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
developer.log("fetchPlayer Failed to fetch player", name: "services/tetrio_crud", error: response.statusCode);
|
||||||
|
throw ConnectionIssue(response.statusCode, response.reasonPhrase??"No reason");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Uri url;
|
Uri url;
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "tetrioUser", "user": user.toLowerCase().trim()});
|
url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "tetrioUser", "user": user.toLowerCase().trim()});
|
||||||
|
|
|
@ -116,7 +116,12 @@ class _MainState extends State<MainView> with SingleTickerProviderStateMixin {
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List> fetch(String nickOrID, {bool fetchHistory = false}) async {
|
Future<List> fetch(String nickOrID, {bool fetchHistory = false}) async {
|
||||||
TetrioPlayer me = await teto.fetchPlayer(nickOrID);
|
TetrioPlayer me;
|
||||||
|
if (nickOrID.startsWith("ds:")){
|
||||||
|
me = await teto.fetchPlayer(nickOrID.substring(3), isItDiscordID: true);
|
||||||
|
}else{
|
||||||
|
me = await teto.fetchPlayer(nickOrID);
|
||||||
|
}
|
||||||
_searchFor = me.userId;
|
_searchFor = me.userId;
|
||||||
setState((){_titleNickname = me.username;});
|
setState((){_titleNickname = me.username;});
|
||||||
var tlStream = await teto.getTLStream(me.userId);
|
var tlStream = await teto.getTLStream(me.userId);
|
||||||
|
|
|
@ -0,0 +1,397 @@
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
//import 'package:tetra_stats/data_objects/tetrio.dart';
|
||||||
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
|
import 'package:tetra_stats/views/main_view.dart';
|
||||||
|
import 'package:tetra_stats/widgets/stat_sell_num.dart';
|
||||||
|
//import 'package:tetra_stats/widgets/tl_thingy.dart';
|
||||||
|
|
||||||
|
final DateFormat dateFormat =
|
||||||
|
DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
|
||||||
|
double pfpHeight = 128;
|
||||||
|
|
||||||
|
class RankView extends StatefulWidget {
|
||||||
|
final List rank;
|
||||||
|
const RankView({Key? key, required this.rank}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<StatefulWidget> createState() => RankState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class RankState extends State<RankView> with SingleTickerProviderStateMixin {
|
||||||
|
late ScrollController _scrollController;
|
||||||
|
late TabController _tabController;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
_scrollController = ScrollController();
|
||||||
|
_tabController = TabController(length: 6, vsync: this);
|
||||||
|
super.initState();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_tabController.dispose();
|
||||||
|
_scrollController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _justUpdate() {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final t = Translations.of(context);
|
||||||
|
bool bigScreen = MediaQuery.of(context).size.width > 768;
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(widget.rank[0].rank.toUpperCase()),
|
||||||
|
),
|
||||||
|
backgroundColor: Colors.black,
|
||||||
|
body: SafeArea(
|
||||||
|
child: NestedScrollView(
|
||||||
|
controller: _scrollController,
|
||||||
|
headerSliverBuilder: (context, value) {
|
||||||
|
return [
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Flex(
|
||||||
|
direction: Axis.vertical,
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Stack(
|
||||||
|
alignment: Alignment.topCenter,
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
padding:
|
||||||
|
EdgeInsets.fromLTRB(0, pfpHeight, 0, 0),
|
||||||
|
child: Image.asset(
|
||||||
|
"res/tetrio_tl_alpha_ranks/${widget.rank[0].rank}.png",
|
||||||
|
fit: BoxFit.fitHeight,
|
||||||
|
height: 128),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"Values for ${widget.rank[0].rank.toUpperCase()} rank",
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: "Eurostile Round Extended",
|
||||||
|
fontSize: bigScreen ? 42 : 28)),
|
||||||
|
Text(
|
||||||
|
"${widget.rank[1]["entries"].length} players",
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: "Eurostile Round Extended",
|
||||||
|
fontSize: bigScreen ? 42 : 28)),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Wrap(
|
||||||
|
direction: Axis.horizontal,
|
||||||
|
alignment: WrapAlignment.center,
|
||||||
|
spacing: 25,
|
||||||
|
crossAxisAlignment: WrapCrossAlignment.start,
|
||||||
|
clipBehavior: Clip.hardEdge, // hard WHAT???
|
||||||
|
children: [
|
||||||
|
StatCellNum(
|
||||||
|
playerStat: widget.rank[1]["totalGamesPlayed"],
|
||||||
|
playerStatLabel: "Total games\nplayed",
|
||||||
|
isScreenBig: bigScreen,
|
||||||
|
higherIsBetter: true,
|
||||||
|
),
|
||||||
|
StatCellNum(
|
||||||
|
playerStat: widget.rank[1]["totalGamesWon"],
|
||||||
|
playerStatLabel: "Total games\nwon",
|
||||||
|
isScreenBig: bigScreen,
|
||||||
|
higherIsBetter: true,
|
||||||
|
),
|
||||||
|
StatCellNum(
|
||||||
|
playerStat: (widget.rank[1]["totalGamesWon"] /
|
||||||
|
widget.rank[1]["totalGamesPlayed"]) *
|
||||||
|
100,
|
||||||
|
playerStatLabel: t.statCellNum.winrate,
|
||||||
|
fractionDigits: 3,
|
||||||
|
isScreenBig: bigScreen,
|
||||||
|
higherIsBetter: true)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: TabBar(
|
||||||
|
controller: _tabController,
|
||||||
|
isScrollable: true,
|
||||||
|
tabs: const [
|
||||||
|
Tab(text: "Chart"),
|
||||||
|
Tab(text: "Entries"),
|
||||||
|
Tab(text: "Minimums"),
|
||||||
|
Tab(text: "Averages"),
|
||||||
|
Tab(text: "Maximums"),
|
||||||
|
Tab(text: "Other"),
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
body: TabBarView(
|
||||||
|
controller: _tabController,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Text("Chart",
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: "Eurostile Round Extended",
|
||||||
|
fontSize: bigScreen ? 42 : 28)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Text("Entries",
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: "Eurostile Round Extended",
|
||||||
|
fontSize: bigScreen ? 42 : 28)),
|
||||||
|
Expanded(
|
||||||
|
child: ListView.builder(
|
||||||
|
itemCount: widget.rank[1]["entries"]!.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
bool bigScreen =
|
||||||
|
MediaQuery.of(context).size.width > 768;
|
||||||
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
|
widget.rank[1]["entries"][index].username,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontFamily:
|
||||||
|
"Eurostile Round Extended")),
|
||||||
|
subtitle: Text(
|
||||||
|
"${f2.format(widget.rank[1]["entries"][index].apm)} APM, ${f2.format(widget.rank[1]["entries"][index].pps)} PPS, ${f2.format(widget.rank[1]["entries"][index].vs)} VS, ${f2.format(widget.rank[1]["entries"][index].app)} APP, ${f2.format(widget.rank[1]["entries"][index].vsapm)} VS/APM"),
|
||||||
|
trailing: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
"${f2.format(widget.rank[1]["entries"][index].rating)} TR",
|
||||||
|
style: bigScreen
|
||||||
|
? const TextStyle(fontSize: 28)
|
||||||
|
: null),
|
||||||
|
Image.asset(
|
||||||
|
"res/tetrio_tl_alpha_ranks/${widget.rank[1]["entries"][index].rank}.png",
|
||||||
|
height: bigScreen ? 48 : 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => MainView(
|
||||||
|
player: widget
|
||||||
|
.rank[1]["entries"][index]
|
||||||
|
.userId),
|
||||||
|
maintainState: false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Text("Lowest Values",
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: "Eurostile Round Extended",
|
||||||
|
fontSize: bigScreen ? 42 : 28)),
|
||||||
|
Expanded(
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
_ListEntry(
|
||||||
|
value: widget.rank[1]["lowestTR"],
|
||||||
|
label: "Tetra Rating",
|
||||||
|
id: widget.rank[1]["lowestTRid"],
|
||||||
|
username: widget.rank[1]["lowestTRnick"],
|
||||||
|
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]["lowestGamesPlayed"],
|
||||||
|
label: "Games Played",
|
||||||
|
id: widget.rank[1]["lowestGamesPlayedID"],
|
||||||
|
username: widget.rank[1]
|
||||||
|
["lowestGamesPlayedNick"],
|
||||||
|
approximate: false),
|
||||||
|
_ListEntry(
|
||||||
|
value: widget.rank[1]["lowestGamesWon"],
|
||||||
|
label: "Games Won",
|
||||||
|
id: widget.rank[1]["lowestGamesWonID"],
|
||||||
|
username: widget.rank[1]
|
||||||
|
["lowestGamesWonNick"],
|
||||||
|
approximate: false),
|
||||||
|
_ListEntry(
|
||||||
|
value: widget.rank[1]["lowestWinrate"] * 100,
|
||||||
|
label: "Winrate Percentage",
|
||||||
|
id: widget.rank[1]["lowestWinrateID"],
|
||||||
|
username: widget.rank[1]["lowestWinrateNick"],
|
||||||
|
approximate: false,
|
||||||
|
fractionDigits: 2),
|
||||||
|
_ListEntry(
|
||||||
|
value: widget.rank[1]["lowestAPM"],
|
||||||
|
label: "Attack Per Minute",
|
||||||
|
id: widget.rank[1]["lowestAPMid"],
|
||||||
|
username: widget.rank[1]["lowestAPMnick"],
|
||||||
|
approximate: false,
|
||||||
|
fractionDigits: 2),
|
||||||
|
_ListEntry(
|
||||||
|
value: widget.rank[1]["lowestPPS"],
|
||||||
|
label: "Pieces Per Second",
|
||||||
|
id: widget.rank[1]["lowestPPSid"],
|
||||||
|
username: widget.rank[1]["lowestPPSnick"],
|
||||||
|
approximate: false,
|
||||||
|
fractionDigits: 2),
|
||||||
|
_ListEntry(
|
||||||
|
value: widget.rank[1]["lowestVS"],
|
||||||
|
label: "Versus Score",
|
||||||
|
id: widget.rank[1]["lowestVSid"],
|
||||||
|
username: widget.rank[1]["lowestVSnick"],
|
||||||
|
approximate: false,
|
||||||
|
fractionDigits: 2)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Text("Highest Values",
|
||||||
|
style: TextStyle(
|
||||||
|
fontFamily: "Eurostile Round Extended",
|
||||||
|
fontSize: bigScreen ? 42 : 28)),
|
||||||
|
Expanded(
|
||||||
|
child: ListView(
|
||||||
|
children: [
|
||||||
|
_ListEntry(
|
||||||
|
value: widget.rank[1]["highestTR"],
|
||||||
|
label: "Tetra Rating",
|
||||||
|
id: widget.rank[1]["highestTRid"],
|
||||||
|
username: widget.rank[1]["highestTRnick"],
|
||||||
|
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]["highestGamesPlayed"],
|
||||||
|
label: "Games Played",
|
||||||
|
id: widget.rank[1]["highestGamesPlayedID"],
|
||||||
|
username: widget.rank[1]
|
||||||
|
["highestGamesPlayedNick"],
|
||||||
|
approximate: false),
|
||||||
|
_ListEntry(
|
||||||
|
value: widget.rank[1]["highestGamesWon"],
|
||||||
|
label: "Games Won",
|
||||||
|
id: widget.rank[1]["highestGamesWonID"],
|
||||||
|
username: widget.rank[1]
|
||||||
|
["highestGamesWonNick"],
|
||||||
|
approximate: false),
|
||||||
|
_ListEntry(
|
||||||
|
value: widget.rank[1]["highestWinrate"] * 100,
|
||||||
|
label: "Winrate Percentage",
|
||||||
|
id: widget.rank[1]["highestWinrateID"],
|
||||||
|
username: widget.rank[1]
|
||||||
|
["highestWinrateNick"],
|
||||||
|
approximate: false,
|
||||||
|
fractionDigits: 2),
|
||||||
|
_ListEntry(
|
||||||
|
value: widget.rank[1]["highestAPM"],
|
||||||
|
label: "Attack Per Minute",
|
||||||
|
id: widget.rank[1]["highestAPMid"],
|
||||||
|
username: widget.rank[1]["highestAPMnick"],
|
||||||
|
approximate: false,
|
||||||
|
fractionDigits: 2),
|
||||||
|
_ListEntry(
|
||||||
|
value: widget.rank[1]["highestPPS"],
|
||||||
|
label: "Pieces Per Second",
|
||||||
|
id: widget.rank[1]["highestPPSid"],
|
||||||
|
username: widget.rank[1]["highestPPSnick"],
|
||||||
|
approximate: false,
|
||||||
|
fractionDigits: 2),
|
||||||
|
_ListEntry(
|
||||||
|
value: widget.rank[1]["highestVS"],
|
||||||
|
label: "Versus Score",
|
||||||
|
id: widget.rank[1]["highestVSid"],
|
||||||
|
username: widget.rank[1]["highestVSnick"],
|
||||||
|
approximate: false,
|
||||||
|
fractionDigits: 2)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Column(
|
||||||
|
children: [],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ListEntry extends StatelessWidget {
|
||||||
|
final num value;
|
||||||
|
final String label;
|
||||||
|
final String id;
|
||||||
|
final String username;
|
||||||
|
final bool approximate;
|
||||||
|
final int? fractionDigits;
|
||||||
|
const _ListEntry(
|
||||||
|
{required this.value,
|
||||||
|
required this.label,
|
||||||
|
this.fractionDigits,
|
||||||
|
required this.id,
|
||||||
|
required this.username,
|
||||||
|
required this.approximate});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
NumberFormat f = NumberFormat.decimalPatternDigits(
|
||||||
|
locale: LocaleSettings.currentLocale.languageCode,
|
||||||
|
decimalDigits: fractionDigits ?? 0);
|
||||||
|
return ListTile(
|
||||||
|
title: Text(label),
|
||||||
|
trailing: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(f.format(value),
|
||||||
|
style: const TextStyle(fontSize: 22, height: 0.9)),
|
||||||
|
if (id.isNotEmpty) Text('for player $username')
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: id.isNotEmpty
|
||||||
|
? () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => MainView(player: id),
|
||||||
|
maintainState: false,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
|
import 'package:tetra_stats/views/rank_averages_view.dart';
|
||||||
import 'package:tetra_stats/views/tl_leaderboard_view.dart';
|
import 'package:tetra_stats/views/tl_leaderboard_view.dart';
|
||||||
|
|
||||||
class RankAveragesView extends StatefulWidget {
|
class RankAveragesView extends StatefulWidget {
|
||||||
|
@ -41,7 +42,16 @@ class RanksAverages extends State<RankAveragesView> {
|
||||||
leading: Image.asset("res/tetrio_tl_alpha_ranks/${keys[index]}.png", height: 48),
|
leading: Image.asset("res/tetrio_tl_alpha_ranks/${keys[index]}.png", height: 48),
|
||||||
title: Text("${averages[keys[index]]?[1]["players"]} players", style: const TextStyle(fontFamily: "Eurostile Round Extended")),
|
title: Text("${averages[keys[index]]?[1]["players"]} players", style: const TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||||
subtitle: Text("${f2.format(averages[keys[index]]?[0].apm)} APM, ${f2.format(averages[keys[index]]?[0].pps)} PPS, ${f2.format(averages[keys[index]]?[0].vs)} VS, ${f2.format(averages[keys[index]]?[0].nerdStats.app)} APP, ${f2.format(averages[keys[index]]?[0].nerdStats.vsapm)} VS/APM"),
|
subtitle: Text("${f2.format(averages[keys[index]]?[0].apm)} APM, ${f2.format(averages[keys[index]]?[0].pps)} PPS, ${f2.format(averages[keys[index]]?[0].vs)} VS, ${f2.format(averages[keys[index]]?[0].nerdStats.app)} APP, ${f2.format(averages[keys[index]]?[0].nerdStats.vsapm)} VS/APM"),
|
||||||
trailing: Text("${f2.format(averages[keys[index]]?[1]["toEnterTR"])} TR", style: bigScreen ? const TextStyle(fontSize: 28) : null));
|
trailing: Text("${f2.format(averages[keys[index]]?[1]["toEnterTR"])} TR", style: bigScreen ? const TextStyle(fontSize: 28) : null),
|
||||||
|
onTap: (){
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
builder: (context) => RankView(rank: averages[keys[index]]!),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
})
|
})
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -67,7 +67,7 @@ class TLThingy extends StatelessWidget {
|
||||||
minimum: tl.nextAt.toDouble(),
|
minimum: tl.nextAt.toDouble(),
|
||||||
maximum: tl.prevAt.toDouble(),
|
maximum: tl.prevAt.toDouble(),
|
||||||
interval: tl.prevAt.toDouble() - tl.nextAt.toDouble(),
|
interval: tl.prevAt.toDouble() - tl.nextAt.toDouble(),
|
||||||
ranges: [LinearGaugeRange(startValue: tl.standing.toDouble(), endValue: tl.prevAt.toDouble(), color: Colors.cyanAccent,)],
|
ranges: [LinearGaugeRange(startValue: tl.standing.toDouble() <= tl.prevAt.toDouble() ? tl.standing.toDouble() : tl.prevAt.toDouble(), endValue: tl.prevAt.toDouble(), color: Colors.cyanAccent,)],
|
||||||
//barPointers: [LinearBarPointer(value: 80)],
|
//barPointers: [LinearBarPointer(value: 80)],
|
||||||
isAxisInversed: true,
|
isAxisInversed: true,
|
||||||
isMirrored: true,
|
isMirrored: true,
|
||||||
|
|
Loading…
Reference in New Issue