1.6.4, many fixes
This commit is contained in:
parent
2376c0eb58
commit
67da831cd2
|
@ -1,10 +1,12 @@
|
||||||
// p1nkl0bst3r data objects
|
// p1nkl0bst3r data objects
|
||||||
|
|
||||||
class Cutoffs{
|
class Cutoffs{
|
||||||
|
DateTime ts;
|
||||||
Map<String, double> tr;
|
Map<String, double> tr;
|
||||||
Map<String, double> glicko;
|
Map<String, double> glicko;
|
||||||
|
Map<String, double> gxe;
|
||||||
|
|
||||||
Cutoffs(this.tr, this.glicko);
|
Cutoffs(this.ts, this.tr, this.glicko, this.gxe);
|
||||||
}
|
}
|
||||||
|
|
||||||
class TopTr{
|
class TopTr{
|
||||||
|
|
|
@ -42,26 +42,26 @@ const Map<String, double> rankCutoffs = {
|
||||||
"z": -1,
|
"z": -1,
|
||||||
"": 0.5
|
"": 0.5
|
||||||
};
|
};
|
||||||
const Map<String, double> rankTargets = {
|
// const Map<String, double> rankTargets = {
|
||||||
"x": 24503.75, // where that comes from?
|
// "x": 24503.75, // where that comes from?
|
||||||
"u": 23038,
|
// "u": 23038,
|
||||||
"ss": 21583,
|
// "ss": 21583,
|
||||||
"s+": 20128,
|
// "s+": 20128,
|
||||||
"s": 18673,
|
// "s": 18673,
|
||||||
"s-": 16975,
|
// "s-": 16975,
|
||||||
"a+": 15035,
|
// "a+": 15035,
|
||||||
"a": 13095,
|
// "a": 13095,
|
||||||
"a-": 11155,
|
// "a-": 11155,
|
||||||
"b+": 9215,
|
// "b+": 9215,
|
||||||
"b": 7275,
|
// "b": 7275,
|
||||||
"b-": 5335,
|
// "b-": 5335,
|
||||||
"c+": 3880,
|
// "c+": 3880,
|
||||||
"c": 2425,
|
// "c": 2425,
|
||||||
"c-": 1213,
|
// "c-": 1213,
|
||||||
"d+": 606,
|
// "d+": 606,
|
||||||
"d": 0,
|
// "d": 0,
|
||||||
};
|
// };
|
||||||
DateTime seasonStart = DateTime.utc(2024, 08, 16, 18);
|
// DateTime seasonStart = DateTime.utc(2024, 08, 16, 18);
|
||||||
//DateTime seasonEnd = DateTime.utc(2024, 07, 26, 15);
|
//DateTime seasonEnd = DateTime.utc(2024, 07, 26, 15);
|
||||||
enum Stats {
|
enum Stats {
|
||||||
tr,
|
tr,
|
||||||
|
@ -123,7 +123,8 @@ const Map<Stats, String> chartsShortTitles = {
|
||||||
Stats.openerMinusInfDS: "Opener - Inf. DS"
|
Stats.openerMinusInfDS: "Opener - Inf. DS"
|
||||||
};
|
};
|
||||||
|
|
||||||
const Map<String, Color> rankColors = { // thanks osk for const rankColors at https://ch.tetr.io/res/js/base.js:418
|
const Map<String, Color> rankColors = { // thanks osk for const rankColors at https://ch.tetr.io/res/js/base.js:458
|
||||||
|
'x+': Color(0xFF643C8D),
|
||||||
'x': Color(0xFFFF45FF),
|
'x': Color(0xFFFF45FF),
|
||||||
'u': Color(0xFFFF3813),
|
'u': Color(0xFFFF3813),
|
||||||
'ss': Color(0xFFDB8B1F),
|
'ss': Color(0xFFDB8B1F),
|
||||||
|
@ -1422,10 +1423,10 @@ class TetraLeague {
|
||||||
timestamp = ts;
|
timestamp = ts;
|
||||||
gamesPlayed = json['gamesplayed'] ?? 0;
|
gamesPlayed = json['gamesplayed'] ?? 0;
|
||||||
gamesWon = json['gameswon'] ?? 0;
|
gamesWon = json['gameswon'] ?? 0;
|
||||||
tr = json['tr'] != null ? json['tr'].toDouble() : -1;
|
tr = json['tr'] != null ? json['tr'].toDouble() : json['rating'] != null ? json['rating'].toDouble() : -1;
|
||||||
glicko = json['glicko']?.toDouble();
|
glicko = json['glicko']?.toDouble();
|
||||||
rd = json['rd'] != null ? json['rd']!.toDouble() : noTrRd;
|
rd = json['rd'] != null ? json['rd']!.toDouble() : noTrRd;
|
||||||
gxe = json['gxe'].toDouble();
|
gxe = json['gxe'] != null ? json['gxe'].toDouble() : -1;
|
||||||
rank = json['rank'] != null ? json['rank']!.toString() : 'z';
|
rank = json['rank'] != null ? json['rank']!.toString() : 'z';
|
||||||
bestRank = json['bestrank'] != null ? json['bestrank']!.toString() : 'z';
|
bestRank = json['bestrank'] != null ? json['bestrank']!.toString() : 'z';
|
||||||
apm = json['apm']?.toDouble();
|
apm = json['apm']?.toDouble();
|
||||||
|
@ -1721,6 +1722,11 @@ class TetrioPlayersLeaderboard {
|
||||||
|
|
||||||
TetrioPlayersLeaderboard(this.type, this.leaderboard);
|
TetrioPlayersLeaderboard(this.type, this.leaderboard);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString(){
|
||||||
|
return "$type leaderboard: ${leaderboard.length} players";
|
||||||
|
}
|
||||||
|
|
||||||
List<TetrioPlayerFromLeaderboard> getStatRanking(List<TetrioPlayerFromLeaderboard> leaderboard, Stats stat, {bool reversed = false, String country = ""}){
|
List<TetrioPlayerFromLeaderboard> getStatRanking(List<TetrioPlayerFromLeaderboard> leaderboard, Stats stat, {bool reversed = false, String country = ""}){
|
||||||
List<TetrioPlayerFromLeaderboard> lb = List.from(leaderboard);
|
List<TetrioPlayerFromLeaderboard> lb = List.from(leaderboard);
|
||||||
if (country.isNotEmpty){
|
if (country.isNotEmpty){
|
||||||
|
@ -2425,6 +2431,10 @@ class TetrioPlayersLeaderboard {
|
||||||
leaderboard.add(TetrioPlayerFromLeaderboard.fromJson(entry, ts));
|
leaderboard.add(TetrioPlayerFromLeaderboard.fromJson(entry, ts));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
addPlayers(List<TetrioPlayerFromLeaderboard> list){
|
||||||
|
leaderboard.addAll(list);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class TetrioPlayerFromLeaderboard {
|
class TetrioPlayerFromLeaderboard {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'dart:math';
|
||||||
|
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
|
|
||||||
class UserAgentClient extends http.BaseClient {
|
class UserAgentClient extends http.BaseClient {
|
||||||
|
@ -9,6 +11,7 @@ class UserAgentClient extends http.BaseClient {
|
||||||
@override
|
@override
|
||||||
Future<http.StreamedResponse> send(http.BaseRequest request) {
|
Future<http.StreamedResponse> send(http.BaseRequest request) {
|
||||||
request.headers['user-agent'] = userAgent;
|
request.headers['user-agent'] = userAgent;
|
||||||
|
request.headers['X-Session-ID'] = "${Random().nextInt(1<<32)}";
|
||||||
return _inner.send(request);
|
return _inner.send(request);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -411,12 +411,7 @@ class TetrioService extends DB {
|
||||||
Cutoffs? cached = _cache.get("", Cutoffs);
|
Cutoffs? cached = _cache.get("", Cutoffs);
|
||||||
if (cached != null) return cached;
|
if (cached != null) return cached;
|
||||||
|
|
||||||
Uri url;
|
Uri url = Uri.https('ts.dan63.by', 'beanserver_blaster/cutoffs.json', {"users": null});
|
||||||
if (kIsWeb) {
|
|
||||||
url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "TLCutoffs"});
|
|
||||||
} else {
|
|
||||||
url = Uri.https('api.p1nkl0bst3r.xyz', 'rankcutoff', {"users": null});
|
|
||||||
}
|
|
||||||
|
|
||||||
try{
|
try{
|
||||||
final response = await client.get(url);
|
final response = await client.get(url);
|
||||||
|
@ -424,13 +419,14 @@ class TetrioService extends DB {
|
||||||
switch (response.statusCode) {
|
switch (response.statusCode) {
|
||||||
case 200:
|
case 200:
|
||||||
Map<String, dynamic> rawData = jsonDecode(response.body);
|
Map<String, dynamic> rawData = jsonDecode(response.body);
|
||||||
Map<String, dynamic> data = rawData["cutoffs"] as Map<String, dynamic>;
|
Map<String, dynamic> data = rawData["data"] as Map<String, dynamic>;
|
||||||
Cutoffs result = Cutoffs({}, {});
|
Cutoffs result = Cutoffs(DateTime.fromMillisecondsSinceEpoch(rawData["created"]), {}, {}, {});
|
||||||
for (String rank in data.keys){
|
for (String rank in data.keys){
|
||||||
result.tr[rank] = data[rank]["rating"];
|
result.tr[rank] = data[rank]["tr"];
|
||||||
result.glicko[rank] = data[rank]["glicko"];
|
result.glicko[rank] = data[rank]["glicko"];
|
||||||
|
result.gxe[rank] = data[rank]["gxe"];
|
||||||
}
|
}
|
||||||
_cache.store(result, rawData["ts"] + 300000);
|
_cache.store(result, rawData["cache_until"]);
|
||||||
return result;
|
return result;
|
||||||
case 404:
|
case 404:
|
||||||
developer.log("fetchCutoffs: Cutoffs are gone", name: "services/tetrio_crud", error: response.statusCode);
|
developer.log("fetchCutoffs: Cutoffs are gone", name: "services/tetrio_crud", error: response.statusCode);
|
||||||
|
@ -466,7 +462,7 @@ class TetrioService extends DB {
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "TLTopOne"});
|
url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "TLTopOne"});
|
||||||
} else {
|
} else {
|
||||||
url = Uri.https('ch.tetr.io', 'api/users/lists/league', {"after": "25000", "limit": "1"});
|
url = Uri.https('ch.tetr.io', 'api/users/by/league', {"after": "25000:0:0", "limit": "1"});
|
||||||
}
|
}
|
||||||
|
|
||||||
try{
|
try{
|
||||||
|
@ -475,7 +471,7 @@ class TetrioService extends DB {
|
||||||
switch (response.statusCode) {
|
switch (response.statusCode) {
|
||||||
case 200:
|
case 200:
|
||||||
var rawJson = jsonDecode(response.body);
|
var rawJson = jsonDecode(response.body);
|
||||||
TetrioPlayerFromLeaderboard result = TetrioPlayerFromLeaderboard.fromJson(rawJson["data"]["users"][0], DateTime.fromMillisecondsSinceEpoch(rawJson["cache"]["cached_at"]));
|
TetrioPlayerFromLeaderboard result = TetrioPlayerFromLeaderboard.fromJson(rawJson["data"]["entries"][0], DateTime.fromMillisecondsSinceEpoch(rawJson["cache"]["cached_at"]));
|
||||||
_cache.store(result, rawJson["cache"]["cached_until"]);
|
_cache.store(result, rawJson["cache"]["cached_until"]);
|
||||||
return result;
|
return result;
|
||||||
case 404:
|
case 404:
|
||||||
|
@ -640,15 +636,17 @@ 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() async {
|
Future<TetrioPlayersLeaderboard> fetchTLLeaderboard({double? after}) async {
|
||||||
TetrioPlayersLeaderboard? cached = _cache.get("league", TetrioPlayersLeaderboard);
|
TetrioPlayersLeaderboard? cached = _cache.get("league${after != null ? after.toString() : ""}", TetrioPlayersLeaderboard);
|
||||||
if (cached != null) return cached;
|
if (cached != null) return cached;
|
||||||
|
|
||||||
Uri url;
|
Uri url;
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "TLLeaderboard"});
|
url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "TLLeaderboard"});
|
||||||
} else {
|
} else {
|
||||||
url = Uri.https('ch.tetr.io', 'api/users/by/league');
|
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);
|
||||||
|
@ -688,6 +686,20 @@ class TetrioService extends DB {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stream<TetrioPlayersLeaderboard> fetchFullLeaderboard() async* {
|
||||||
|
late double after;
|
||||||
|
int lbLength = 100;
|
||||||
|
TetrioPlayersLeaderboard leaderboard = await fetchTLLeaderboard();
|
||||||
|
after = leaderboard.leaderboard.last.tr;
|
||||||
|
while (lbLength == 100){
|
||||||
|
TetrioPlayersLeaderboard pseudoLb = await fetchTLLeaderboard(after: after);
|
||||||
|
leaderboard.addPlayers(pseudoLb.leaderboard);
|
||||||
|
lbLength = pseudoLb.leaderboard.length;
|
||||||
|
after = pseudoLb.leaderboard.last.tr;
|
||||||
|
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 {
|
||||||
// TetrioPlayersLeaderboard? cached = _cache.get("league", TetrioPlayersLeaderboard);
|
// TetrioPlayersLeaderboard? cached = _cache.get("league", TetrioPlayersLeaderboard);
|
||||||
|
|
|
@ -11,6 +11,7 @@ import 'package:intl/intl.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_stats.dart';
|
||||||
import 'package:tetra_stats/data_objects/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/main.dart' show prefs, teto;
|
import 'package:tetra_stats/main.dart' show prefs, teto;
|
||||||
|
@ -156,8 +157,8 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS) await windowManager.setTitle(title);
|
if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS) await windowManager.setTitle(title);
|
||||||
|
|
||||||
// Requesting Tetra League (alpha), records, news and top TR of player
|
// Requesting Tetra League (alpha), records, news and top TR of player
|
||||||
late List<dynamic> requests;
|
List<dynamic> requests;
|
||||||
late Summaries summaries;
|
Summaries summaries = await teto.fetchSummaries(_searchFor);
|
||||||
late TetraLeagueBetaStream tlStream;
|
late TetraLeagueBetaStream tlStream;
|
||||||
late News news;
|
late News news;
|
||||||
// late SingleplayerStream recentSprint;
|
// late SingleplayerStream recentSprint;
|
||||||
|
@ -166,20 +167,20 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
// late SingleplayerStream blitz;
|
// late SingleplayerStream blitz;
|
||||||
late SingleplayerStream recentZenith;
|
late SingleplayerStream recentZenith;
|
||||||
late SingleplayerStream recentZenithEX;
|
late SingleplayerStream recentZenithEX;
|
||||||
// late TetrioPlayerFromLeaderboard? topOne;
|
late TetrioPlayerFromLeaderboard? topOne;
|
||||||
// late TopTr? topTR;
|
// late TopTr? topTR;
|
||||||
requests = await Future.wait([ // all at once (8 requests to oskware in total)
|
requests = await Future.wait([
|
||||||
teto.fetchSummaries(_searchFor),
|
teto.fetchSummaries(_searchFor),
|
||||||
teto.fetchTLStream(_searchFor),
|
teto.fetchTLStream(_searchFor),
|
||||||
teto.fetchNews(_searchFor),
|
teto.fetchNews(_searchFor),
|
||||||
teto.fetchStream(_searchFor, "zenith/recent"),
|
teto.fetchStream(_searchFor, "zenith/recent"),
|
||||||
teto.fetchStream(_searchFor, "zenithex/recent"),
|
teto.fetchStream(_searchFor, "zenithex/recent"),
|
||||||
//teto.fetchStream(_searchFor, "40l/top"),
|
teto.fetchCutoffs(),
|
||||||
//teto.fetchStream(_searchFor, "blitz/top"),
|
(summaries.league.rank != "z" ? summaries.league.rank == "x+" : summaries.league.percentileRank == "x+") ? teto.fetchTopOneFromTheLeaderboard() : Future.delayed(Duration.zero, ()=>null),
|
||||||
]);
|
]);
|
||||||
//prefs.getBool("showPositions") != true ? teto.fetchCutoffs() : Future.delayed(Duration.zero, ()=><Map<String, double>>[]),
|
//prefs.getBool("showPositions") != true ? teto.fetchCutoffs() : Future.delayed(Duration.zero, ()=><Map<String, double>>[]),
|
||||||
//(me.tlSeason1.rank != "z" ? me.tlSeason1.rank == "x" : me.tlSeason1.percentileRank == "x") ? teto.fetchTopOneFromTheLeaderboard() : Future.delayed(Duration.zero, ()=>null),
|
|
||||||
//(me.tlSeason1.gamesPlayed > 9) ? teto.fetchTopTR(_searchFor) : Future.delayed(Duration.zero, () => null) // can retrieve this only if player has TR
|
//(summaries.league.gamesPlayed > 9) ? teto.fetchTopTR(_searchFor) : Future.delayed(Duration.zero, () => null) // can retrieve this only if player has TR
|
||||||
summaries = requests[0] as Summaries;
|
summaries = requests[0] as Summaries;
|
||||||
tlStream = requests[1] as TetraLeagueBetaStream;
|
tlStream = requests[1] as TetraLeagueBetaStream;
|
||||||
// records = requests[1] as UserRecords;
|
// records = requests[1] as UserRecords;
|
||||||
|
@ -189,7 +190,7 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
// recent = requests[3] as SingleplayerStream;
|
// recent = requests[3] as SingleplayerStream;
|
||||||
// sprint = requests[4] as SingleplayerStream;
|
// sprint = requests[4] as SingleplayerStream;
|
||||||
// blitz = requests[5] as SingleplayerStream;
|
// blitz = requests[5] as SingleplayerStream;
|
||||||
// topOne = requests[7] as TetrioPlayerFromLeaderboard?;
|
topOne = requests[6] as TetrioPlayerFromLeaderboard?;
|
||||||
// topTR = requests[8] as TopTr?; // No TR - no Top TR
|
// topTR = requests[8] as TopTr?; // No TR - no Top TR
|
||||||
|
|
||||||
meAmongEveryone = teto.getCachedLeaderboardPositions(me.userId);
|
meAmongEveryone = teto.getCachedLeaderboardPositions(me.userId);
|
||||||
|
@ -202,17 +203,17 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
if (meAmongEveryone != null) teto.cacheLeaderboardPositions(me.userId, meAmongEveryone!);
|
if (meAmongEveryone != null) teto.cacheLeaderboardPositions(me.userId, meAmongEveryone!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Map<String, double>? cutoffs = prefs.getBool("showPositions") == true ? everyone!.cutoffs : (requests[6] as Cutoffs?)?.tr;
|
Map<String, double>? cutoffs = (requests[5] as Cutoffs?)?.tr;
|
||||||
//Map<String, double>? cutoffsGlicko = prefs.getBool("showPositions") == true ? everyone!.cutoffsGlicko : (requests[6] as Cutoffs?)?.glicko;
|
Map<String, double>? cutoffsGlicko = (requests[5] as Cutoffs?)?.glicko;
|
||||||
|
|
||||||
// if (me.tlSeason1.gamesPlayed > 9) {
|
if (summaries.league.gamesPlayed > 9) {
|
||||||
// thatRankCutoff = cutoffs?[me.tlSeason1.rank != "z" ? me.tlSeason1.rank : me.tlSeason1.percentileRank];
|
thatRankCutoff = cutoffs?[summaries.league.rank != "z" ? summaries.league.rank : summaries.league.percentileRank];
|
||||||
// thatRankGlickoCutoff = cutoffsGlicko?[me.tlSeason1.rank != "z" ? me.tlSeason1.rank : me.tlSeason1.percentileRank];
|
thatRankGlickoCutoff = cutoffsGlicko?[summaries.league.rank != "z" ? summaries.league.rank : summaries.league.percentileRank];
|
||||||
// nextRankCutoff = (me.tlSeason1.rank != "z" ? me.tlSeason1.rank == "x" : me.tlSeason1.percentileRank == "x") ? topOne?.tr??25000 : cutoffs?[ranks.elementAtOrNull(ranks.indexOf(me.tlSeason1.rank != "z" ? me.tlSeason1.rank : me.tlSeason1.percentileRank)+1)];
|
nextRankCutoff = (summaries.league.rank != "z" ? summaries.league.rank == "x+" : summaries.league.percentileRank == "x+") ? topOne?.tr??25000 : cutoffs?[ranks.elementAtOrNull(ranks.indexOf(summaries.league.rank != "z" ? summaries.league.rank : summaries.league.percentileRank)+1)];
|
||||||
// nextRankGlickoCutoff = (me.tlSeason1.rank != "z" ? me.tlSeason1.rank == "x" : me.tlSeason1.percentileRank == "x") ? topOne?.glicko??double.infinity : cutoffsGlicko?[ranks.elementAtOrNull(ranks.indexOf(me.tlSeason1.rank != "z" ? me.tlSeason1.rank : me.tlSeason1.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 && me.tlSeason1.gamesPlayed > 9) rankAverages = everyone?.averages[me.tlSeason1.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);
|
||||||
|
@ -270,7 +271,7 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//states.addAll(await teto.getPlayer(me.userId));
|
states.addAll(await teto.getPlayer(me.userId));
|
||||||
for (var element in states) { // For graphs I need only unique entries
|
for (var element in states) { // For graphs I need only unique entries
|
||||||
if (element.tlSeason1 != null && uniqueTL.isNotEmpty && uniqueTL.last != element.tlSeason1) uniqueTL.add(element.tlSeason1!);
|
if (element.tlSeason1 != null && uniqueTL.isNotEmpty && uniqueTL.last != element.tlSeason1) uniqueTL.add(element.tlSeason1!);
|
||||||
if (uniqueTL.isEmpty) uniqueTL.add(element.tlSeason1!);
|
if (uniqueTL.isEmpty) uniqueTL.add(element.tlSeason1!);
|
||||||
|
@ -475,12 +476,12 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
//lastMatchPlayed: snapshot.data![11],
|
//lastMatchPlayed: snapshot.data![11],
|
||||||
bot: snapshot.data![0].role == "bot",
|
bot: snapshot.data![0].role == "bot",
|
||||||
guest: snapshot.data![0].role == "anon",
|
guest: snapshot.data![0].role == "anon",
|
||||||
//thatRankCutoff: thatRankCutoff,
|
thatRankCutoff: thatRankCutoff,
|
||||||
//thatRankCutoffGlicko: thatRankGlickoCutoff,
|
thatRankCutoffGlicko: thatRankGlickoCutoff,
|
||||||
//thatRankTarget: snapshot.data![0].tlSeason1.rank != "z" ? rankTargets[snapshot.data![0].tlSeason1.rank] : null,
|
//thatRankTarget: snapshot.data![1].league.rank != "z" ? rankTargets[snapshot.data![1].league.rank] : null,
|
||||||
//nextRankCutoff: nextRankCutoff,
|
nextRankCutoff: nextRankCutoff,
|
||||||
//nextRankCutoffGlicko: nextRankGlickoCutoff,
|
nextRankCutoffGlicko: nextRankGlickoCutoff,
|
||||||
//nextRankTarget: (snapshot.data![0].tlSeason1.rank != "z" && snapshot.data![0].tlSeason1.rank != "x") ? rankTargets[ranks.elementAtOrNull(ranks.indexOf(snapshot.data![0].tlSeason1.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
|
||||||
),
|
),
|
||||||
|
@ -516,12 +517,12 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
//lastMatchPlayed: snapshot.data![11],
|
//lastMatchPlayed: snapshot.data![11],
|
||||||
bot: snapshot.data![0].role == "bot",
|
bot: snapshot.data![0].role == "bot",
|
||||||
guest: snapshot.data![0].role == "anon",
|
guest: snapshot.data![0].role == "anon",
|
||||||
//thatRankCutoff: thatRankCutoff,
|
thatRankCutoff: thatRankCutoff,
|
||||||
//thatRankCutoffGlicko: thatRankGlickoCutoff,
|
thatRankCutoffGlicko: thatRankGlickoCutoff,
|
||||||
//thatRankTarget: snapshot.data![0].tlSeason1.rank != "z" ? rankTargets[snapshot.data![0].tlSeason1.rank] : null,
|
//thatRankTarget: snapshot.data![1].league.rank != "z" ? rankTargets[snapshot.data![1].league.rank] : null,
|
||||||
//nextRankCutoff: nextRankCutoff,
|
nextRankCutoff: nextRankCutoff,
|
||||||
//nextRankCutoffGlicko: nextRankGlickoCutoff,
|
nextRankCutoffGlicko: nextRankGlickoCutoff,
|
||||||
//nextRankTarget: (snapshot.data![0].tlSeason1.rank != "z" && snapshot.data![0].tlSeason1.rank != "x") ? rankTargets[ranks.elementAtOrNull(ranks.indexOf(snapshot.data![0].tlSeason1.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
|
||||||
),
|
),
|
||||||
|
|
|
@ -170,7 +170,7 @@ class DestinationLeaderboards extends StatefulWidget{
|
||||||
|
|
||||||
class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
|
class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
|
||||||
Cards rightCard = Cards.tetraLeague;
|
Cards rightCard = Cards.tetraLeague;
|
||||||
Duration postSeasonLeft = seasonStart.difference(DateTime.now());
|
//Duration postSeasonLeft = seasonStart.difference(DateTime.now());
|
||||||
final List<String> leaderboards = ["Tetra League", "Quick Play", "Quick Play Expert"];
|
final List<String> leaderboards = ["Tetra League", "Quick Play", "Quick Play Expert"];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -245,7 +245,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
||||||
final List _historyShortTitles = ["TR", "Glicko", "RD", "APM", "PPS", "VS", "APP", "DS/S", "DS/P", "APP + DS/P", "VS/APM", "Cheese", "GbE", "wAPP", "Area", "eTR", "±eTR", "Opener", "Plonk", "Inf. DS", "Stride"];
|
final List _historyShortTitles = ["TR", "Glicko", "RD", "APM", "PPS", "VS", "APP", "DS/S", "DS/P", "APP + DS/P", "VS/APM", "Cheese", "GbE", "wAPP", "Area", "eTR", "±eTR", "Opener", "Plonk", "Inf. DS", "Stride"];
|
||||||
int _chartsIndex = 0;
|
int _chartsIndex = 0;
|
||||||
late List<DropdownMenuItem<List<_HistoryChartSpot>>> chartsData;
|
late List<DropdownMenuItem<List<_HistoryChartSpot>>> chartsData;
|
||||||
Duration postSeasonLeft = seasonStart.difference(DateTime.now());
|
//Duration postSeasonLeft = seasonStart.difference(DateTime.now());
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState(){
|
void initState(){
|
||||||
|
@ -611,7 +611,7 @@ class RecordSummary extends StatelessWidget{
|
||||||
class _DestinationHomeState extends State<DestinationHome> {
|
class _DestinationHomeState extends State<DestinationHome> {
|
||||||
Cards rightCard = Cards.overview;
|
Cards rightCard = Cards.overview;
|
||||||
CardMod cardMod = CardMod.info;
|
CardMod cardMod = CardMod.info;
|
||||||
Duration postSeasonLeft = seasonStart.difference(DateTime.now());
|
//Duration postSeasonLeft = seasonStart.difference(DateTime.now());
|
||||||
late Map<Cards, List<ButtonSegment<CardMod>>> modeButtons;
|
late Map<Cards, List<ButtonSegment<CardMod>>> modeButtons;
|
||||||
late MapEntry? closestAverageBlitz;
|
late MapEntry? closestAverageBlitz;
|
||||||
late bool blitzBetterThanClosestAverage;
|
late bool blitzBetterThanClosestAverage;
|
||||||
|
@ -849,7 +849,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(t.tetraLeague, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 42)),
|
Text(t.tetraLeague, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 42)),
|
||||||
Text("${t.seasonStarts} ${countdown(postSeasonLeft)}", textAlign: TextAlign.center)
|
//Text("${t.seasonStarts} ${countdown(postSeasonLeft)}", textAlign: TextAlign.center)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1021,7 +1021,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Text(t.quickPlay, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 42)),
|
Text(t.quickPlay, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 42)),
|
||||||
Text("Leaderboard reset in ${countdown(postSeasonLeft)}", textAlign: TextAlign.center),
|
//Text("Leaderboard reset in ${countdown(postSeasonLeft)}", textAlign: TextAlign.center),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetra_stats.dart';
|
||||||
|
import 'package:tetra_stats/data_objects/tetrio.dart';
|
||||||
import 'package:tetra_stats/gen/strings.g.dart';
|
import 'package:tetra_stats/gen/strings.g.dart';
|
||||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||||
|
import 'package:tetra_stats/utils/text_shadow.dart';
|
||||||
|
import 'package:tetra_stats/views/compare_view.dart';
|
||||||
import 'package:tetra_stats/views/rank_averages_view.dart';
|
import 'package:tetra_stats/views/rank_averages_view.dart';
|
||||||
|
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
||||||
import 'package:window_manager/window_manager.dart';
|
import 'package:window_manager/window_manager.dart';
|
||||||
import 'package:tetra_stats/main.dart' show teto;
|
import 'package:tetra_stats/main.dart' show teto;
|
||||||
|
|
||||||
|
@ -17,14 +22,9 @@ class RankAveragesView extends StatefulWidget {
|
||||||
late String oldWindowTitle;
|
late String oldWindowTitle;
|
||||||
|
|
||||||
class RanksAverages extends State<RankAveragesView> {
|
class RanksAverages extends State<RankAveragesView> {
|
||||||
Map<String, List<dynamic>> averages = {};
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
teto.fetchTLLeaderboard().then((value){
|
|
||||||
averages = value.averages;
|
|
||||||
setState(() {});
|
|
||||||
});
|
|
||||||
if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS){
|
if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS){
|
||||||
windowManager.getTitle().then((value) => oldWindowTitle = value);
|
windowManager.getTitle().then((value) => oldWindowTitle = value);
|
||||||
windowManager.setTitle("Tetra Stats: ${t.rankAveragesViewTitle}");
|
windowManager.setTitle("Tetra Stats: ${t.rankAveragesViewTitle}");
|
||||||
|
@ -40,35 +40,110 @@ class RanksAverages extends State<RankAveragesView> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
bool bigScreen = MediaQuery.of(context).size.width >= 700;
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(t.rankAveragesViewTitle),
|
title: Text(t.rankAveragesViewTitle),
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
body: SafeArea(
|
body: SafeArea(
|
||||||
child: averages.isEmpty ? const Center(child: Text('Fetching...')) : ListView.builder(
|
child: FutureBuilder<Cutoffs?>(future: teto.fetchCutoffs(), builder: (context, snapshot){
|
||||||
itemCount: averages.length,
|
switch (snapshot.connectionState) {
|
||||||
itemBuilder: (context, index){
|
case ConnectionState.none:
|
||||||
List<String> keys = averages.keys.toList();
|
case ConnectionState.waiting:
|
||||||
return ListTile(
|
case ConnectionState.active:
|
||||||
leading: Image.asset("res/tetrio_tl_alpha_ranks/${keys[index]}.png", height: 48),
|
return const Center(child: CircularProgressIndicator(color: Colors.white));
|
||||||
title: Text(t.players(n: averages[keys[index]]?[1]["players"]), style: const TextStyle(fontFamily: "Eurostile Round Extended")),
|
case ConnectionState.done:
|
||||||
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",
|
if (snapshot.hasData){
|
||||||
style: const TextStyle(fontFamily: "Eurostile Round Condensed", color: Colors.grey, fontSize: 13)),
|
return Container(
|
||||||
trailing: Text("${f2.format(averages[keys[index]]?[1]["toEnterTR"])} TR", style: const TextStyle(fontSize: 28, fontFamily: "Eurostile Round")),
|
alignment: Alignment.center,
|
||||||
onTap: (){
|
child: SingleChildScrollView(
|
||||||
if (averages[keys[index]]?[1]["players"] > 0) {
|
scrollDirection: Axis.horizontal,
|
||||||
Navigator.push(
|
child: Container(
|
||||||
context,
|
alignment: Alignment.center,
|
||||||
MaterialPageRoute(
|
width: MediaQuery.of(context).size.width,
|
||||||
builder: (context) => RankView(rank: averages[keys[index]]!),
|
constraints: const BoxConstraints(maxWidth: 900, minWidth: 610),
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Table(
|
||||||
|
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||||
|
border: TableBorder.all(color: Colors.grey.shade900),
|
||||||
|
columnWidths: const {0: FixedColumnWidth(48)},
|
||||||
|
children: [
|
||||||
|
TableRow(
|
||||||
|
children: [
|
||||||
|
Text(t.rank, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
|
child: Text("TR", textAlign: TextAlign.right, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round" : "Eurostile Round Condensed", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
|
child: Text("Glicko", textAlign: TextAlign.right, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round" : "Eurostile Round Condensed", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
|
child: Text("Glixare", textAlign: TextAlign.right, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round" : "Eurostile Round Condensed", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
|
child: Text("S1 TR", textAlign: TextAlign.right, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round" : "Eurostile Round Condensed", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
for (String rank in snapshot.data!.tr.keys) TableRow(
|
||||||
|
decoration: BoxDecoration(gradient: LinearGradient(colors: [rankColors[rank]!.withAlpha(100), rankColors[rank]!.withAlpha(200)])),
|
||||||
|
children: [
|
||||||
|
Container(decoration: BoxDecoration(boxShadow: [BoxShadow(color: Colors.black.withAlpha(132), blurRadius: 32.0, blurStyle: BlurStyle.inner)]), child: Image.asset("res/tetrio_tl_alpha_ranks/$rank.png", height: 48)),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
|
child: Text(f2.format(snapshot.data!.tr[rank]), textAlign: TextAlign.right, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round" : "Eurostile Round Condensed", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white, shadows: textShadow)),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
|
child: Text(f2.format(snapshot.data!.glicko[rank]), textAlign: TextAlign.right, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round" : "Eurostile Round Condensed", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white, shadows: textShadow)),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
|
child: Text(f2.format(snapshot.data!.gxe[rank]), textAlign: TextAlign.right, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round" : "Eurostile Round Condensed", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white, shadows: textShadow)),
|
||||||
|
),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 8.0),
|
||||||
|
child: Text(f2.format(snapshot.data!.gxe[rank]!*250), textAlign: TextAlign.right, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round" : "Eurostile Round Condensed", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white, shadows: textShadow)),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Text(t.sprintAndBlitsRelevance(date: timestamp(snapshot.data!.ts)))
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
),
|
||||||
}
|
),
|
||||||
},
|
),
|
||||||
);
|
);
|
||||||
})
|
}
|
||||||
),
|
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 const Text("end of FutureBuilder");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ class TLProgress extends StatelessWidget{
|
||||||
if (tlData.nextAt > 0 && nextRankTRcutoff != null) const TextSpan(text: "\n"),
|
if (tlData.nextAt > 0 && nextRankTRcutoff != null) const TextSpan(text: "\n"),
|
||||||
if (nextRankTRcutoff != null) TextSpan(text: "${f2.format(nextRankTRcutoff)} (${comparef2.format(nextRankTRcutoff!-tlData.tr)}) TR"),
|
if (nextRankTRcutoff != null) TextSpan(text: "${f2.format(nextRankTRcutoff)} (${comparef2.format(nextRankTRcutoff!-tlData.tr)}) TR"),
|
||||||
if ((tlData.nextAt > 0 || nextRankTRcutoff != null) && nextRankGlickoCutoff != null) const TextSpan(text: "\n"),
|
if ((tlData.nextAt > 0 || nextRankTRcutoff != null) && nextRankGlickoCutoff != null) const TextSpan(text: "\n"),
|
||||||
if (nextRankGlickoCutoff != null) TextSpan(text: (tlData.standing < tlData.nextAt || ((nextRankGlickoCutoff!-tlData.glicko!)/glickoForWin < 0.5 && ((tlData.rank != "x" && tlData.rank != "z") || tlData.percentileRank != "x"))) ? t.promotionOnNextWin : t.numOfVictories(wins: f2.format((nextRankGlickoCutoff!-tlData.glicko!)/glickoForWin)), style: TextStyle(color: (tlData.standing < tlData.nextAt || ((nextRankGlickoCutoff!-tlData.glicko!)/glickoForWin < 0.5 && tlData.percentileRank != "x")) ? Colors.greenAccent : null))
|
if (nextRankGlickoCutoff != null) TextSpan(text: (tlData.standing < tlData.nextAt || ((nextRankGlickoCutoff!-tlData.glicko!)/glickoForWin < 0.5 && ((tlData.rank != "x+" && tlData.rank != "z") || tlData.percentileRank != "x+"))) ? t.promotionOnNextWin : t.numOfVictories(wins: f2.format((nextRankGlickoCutoff!-tlData.glicko!)/glickoForWin)), style: TextStyle(color: (tlData.standing < tlData.nextAt || ((nextRankGlickoCutoff!-tlData.glicko!)/glickoForWin < 0.5 && tlData.percentileRank != "x+")) ? Colors.greenAccent : null))
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -148,7 +148,7 @@ class _ZenithThingyState extends State<ZenithThingy> {
|
||||||
const Positioned(left: 25, top: 20, child: Text("otal time", style: TextStyle(fontFamily: "Eurostile Round Extended"))),
|
const Positioned(left: 25, top: 20, child: Text("otal time", style: TextStyle(fontFamily: "Eurostile Round Extended"))),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(left: 10.0),
|
padding: const EdgeInsets.only(left: 10.0),
|
||||||
child: Text("${getMoreNormalTime(record!.stats.finalTime)}%", style: TextStyle(
|
child: Text("${getMoreNormalTime(record!.stats.finalTime)}", style: TextStyle(
|
||||||
shadows: textShadow,
|
shadows: textShadow,
|
||||||
fontFamily: "Eurostile Round Extended",
|
fontFamily: "Eurostile Round Extended",
|
||||||
fontSize: 36,
|
fontSize: 36,
|
||||||
|
@ -158,7 +158,6 @@ class _ZenithThingyState extends State<ZenithThingy> {
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Text("Total time: ${getMoreNormalTime(record!.stats.finalTime)}", style: const TextStyle(color: Colors.white, fontFamily: "Eurostile Round Extended"), textAlign: TextAlign.center),
|
|
||||||
Table(
|
Table(
|
||||||
columnWidths: const {
|
columnWidths: const {
|
||||||
0: FixedColumnWidth(36)
|
0: FixedColumnWidth(36)
|
||||||
|
|
|
@ -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.3+29
|
version: 1.6.4+30
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=3.0.0'
|
sdk: '>=3.0.0'
|
||||||
|
|
Loading…
Reference in New Issue