Experimental new feature
This commit is contained in:
parent
0648ca9a5d
commit
f95ffb59aa
|
@ -1139,6 +1139,73 @@ class News {
|
|||
}
|
||||
}
|
||||
|
||||
class PlayerLeaderboardPosition{
|
||||
late LeaderboardPosition apm;
|
||||
late LeaderboardPosition pps;
|
||||
late LeaderboardPosition vs;
|
||||
late LeaderboardPosition gamesPlayed;
|
||||
late LeaderboardPosition gamesWon;
|
||||
late LeaderboardPosition winrate;
|
||||
late LeaderboardPosition app;
|
||||
late LeaderboardPosition vsapm;
|
||||
late LeaderboardPosition dss;
|
||||
late LeaderboardPosition dsp;
|
||||
late LeaderboardPosition appdsp;
|
||||
late LeaderboardPosition cheese;
|
||||
late LeaderboardPosition gbe;
|
||||
late LeaderboardPosition nyaapp;
|
||||
late LeaderboardPosition area;
|
||||
late LeaderboardPosition estTr;
|
||||
late LeaderboardPosition accOfEst;
|
||||
|
||||
PlayerLeaderboardPosition({
|
||||
required this.apm,
|
||||
required this.pps,
|
||||
required this.vs,
|
||||
required this.gamesPlayed,
|
||||
required this.gamesWon,
|
||||
required this.winrate,
|
||||
required this.app,
|
||||
required this.vsapm,
|
||||
required this.dss,
|
||||
required this.dsp,
|
||||
required this.appdsp,
|
||||
required this.cheese,
|
||||
required this.gbe,
|
||||
required this.nyaapp,
|
||||
required this.area,
|
||||
required this.estTr,
|
||||
required this.accOfEst
|
||||
});
|
||||
|
||||
PlayerLeaderboardPosition.fromSearchResults(List<LeaderboardPosition> results){
|
||||
apm = results[0];
|
||||
pps = results[1];
|
||||
vs = results[2];
|
||||
gamesPlayed = results[3];
|
||||
gamesWon = results[4];
|
||||
winrate = results[5];
|
||||
app = results[6];
|
||||
vsapm = results[7];
|
||||
dss = results[8];
|
||||
dsp = results[9];
|
||||
appdsp = results[10];
|
||||
cheese = results[11];
|
||||
gbe = results[12];
|
||||
nyaapp = results[13];
|
||||
area = results[14];
|
||||
estTr = results[15];
|
||||
accOfEst = results[16];
|
||||
}
|
||||
}
|
||||
|
||||
class LeaderboardPosition{
|
||||
int position;
|
||||
double percentage;
|
||||
|
||||
LeaderboardPosition(this.position, this.percentage);
|
||||
}
|
||||
|
||||
class TetrioPlayersLeaderboard {
|
||||
late String type;
|
||||
late DateTime timestamp;
|
||||
|
@ -1163,6 +1230,20 @@ class TetrioPlayersLeaderboard {
|
|||
return lb;
|
||||
}
|
||||
|
||||
List<TetrioPlayerFromLeaderboard> getStatRankingSequel(Stats stat){
|
||||
List<TetrioPlayerFromLeaderboard> lb = List.from(leaderboard);
|
||||
lb.sort(((a, b) {
|
||||
if (a.getStatByEnum(stat) > b.getStatByEnum(stat)){
|
||||
return -1;
|
||||
}else if (a.getStatByEnum(stat) == b.getStatByEnum(stat)){
|
||||
return 0;
|
||||
}else{
|
||||
return 1;
|
||||
}
|
||||
}));
|
||||
return lb;
|
||||
}
|
||||
|
||||
List<dynamic> getAverageOfRank(String rank){ // i tried to refactor it and that's was terrible
|
||||
if (rank.isNotEmpty && !rankCutoffs.keys.contains(rank)) throw Exception("Invalid rank");
|
||||
List<TetrioPlayerFromLeaderboard> filtredLeaderboard = List.from(leaderboard);
|
||||
|
@ -1753,6 +1834,19 @@ class TetrioPlayersLeaderboard {
|
|||
}
|
||||
}
|
||||
|
||||
PlayerLeaderboardPosition? getLeaderboardPosition(String userID) {
|
||||
if (leaderboard.indexWhere((element) => element.userId == userID) == -1) return null;
|
||||
List<Stats> stats = [Stats.apm, Stats.pps, Stats.vs, Stats.gp, Stats.gw, Stats.wr,
|
||||
Stats.app, Stats.vsapm, Stats.dss, Stats.dsp, Stats.appdsp, Stats.cheese, Stats.gbe, Stats.nyaapp, Stats.area, Stats.eTR, Stats.acceTR];
|
||||
List<LeaderboardPosition> results = [];
|
||||
for (Stats stat in stats) {
|
||||
List<TetrioPlayerFromLeaderboard> sortedLeaderboard = getStatRanking(leaderboard, stat, reversed: false);
|
||||
int position = sortedLeaderboard.indexWhere((element) => element.userId == userID) + 1;
|
||||
results.add(LeaderboardPosition(position, position / sortedLeaderboard.length));
|
||||
}
|
||||
return PlayerLeaderboardPosition.fromSearchResults(results);
|
||||
}
|
||||
|
||||
Map<String, List<dynamic>> get averages => {
|
||||
'x': getAverageOfRank("x"),
|
||||
'u': getAverageOfRank("u"),
|
||||
|
|
|
@ -74,6 +74,7 @@ class TetrioService extends DB {
|
|||
final Map<String, Map<String, dynamic>> _recordsCache = {};
|
||||
final Map<String, dynamic> _replaysCache = {}; // the only one is different: {"replayID": [replayString, replayBytes]}
|
||||
final Map<String, TetrioPlayersLeaderboard> _leaderboardsCache = {};
|
||||
final Map<String, PlayerLeaderboardPosition> _lbPositions = {};
|
||||
final Map<String, List<News>> _newsCache = {};
|
||||
final Map<String, Map<String, double?>> _topTRcache = {};
|
||||
final Map<String, TetraLeagueAlphaStream> _tlStreamsCache = {};
|
||||
|
@ -142,6 +143,14 @@ class TetrioService extends DB {
|
|||
db.insert(tetrioTLReplayStatsTable, {idCol: replay.id, "data": jsonEncode(replay.toJson())});
|
||||
}
|
||||
|
||||
void cacheLeaderboardPositions(String userID, PlayerLeaderboardPosition positions){
|
||||
_lbPositions[userID] = positions;
|
||||
}
|
||||
|
||||
PlayerLeaderboardPosition? getCachedLeaderboardPositions(String userID){
|
||||
return _lbPositions[userID];
|
||||
}
|
||||
|
||||
/// Downloads replay from inoue (szy API). Requiers [replayID]. If request have
|
||||
/// different from 200 statusCode, it will throw an excepction. Returns list, that contains same replay
|
||||
/// as string and as binary.
|
||||
|
@ -504,6 +513,7 @@ class TetrioService extends DB {
|
|||
|
||||
switch (response.statusCode) {
|
||||
case 200:
|
||||
_lbPositions.clear();
|
||||
var rawJson = jsonDecode(response.body);
|
||||
if (rawJson['success']) { // if api confirmed that everything ok
|
||||
TetrioPlayersLeaderboard leaderboard = TetrioPlayersLeaderboard.fromJson(rawJson['data']['users'], "league", DateTime.fromMillisecondsSinceEpoch(rawJson['cache']['cached_at']));
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
import 'package:intl/intl.dart';
|
||||
import 'package:tetra_stats/gen/strings.g.dart';
|
||||
|
||||
final NumberFormat comparef = NumberFormat("+#,###.###;-#,###.###")..maximumFractionDigits = 3;
|
||||
final NumberFormat intf = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 0);
|
||||
final NumberFormat f3 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 3);
|
||||
final NumberFormat f2 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 2);
|
|
@ -13,7 +13,6 @@ double? vs;
|
|||
NerdStats? nerdStats;
|
||||
EstTr? estTr;
|
||||
Playstyle? playstyle;
|
||||
final NumberFormat f2 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 2);
|
||||
late String oldWindowTitle;
|
||||
|
||||
class CalcView extends StatefulWidget {
|
||||
|
|
|
@ -31,6 +31,7 @@ import 'package:go_router/go_router.dart';
|
|||
|
||||
Future<List> me = Future.delayed(const Duration(seconds: 60), () => [null, null, null, null, null, null]); // I love lists shut up
|
||||
TetrioPlayersLeaderboard? everyone;
|
||||
PlayerLeaderboardPosition? meAmongEveryone;
|
||||
String _searchFor = "6098518e3d5155e6ec429cdc"; // who we looking for
|
||||
String _titleNickname = "dan63047";
|
||||
final TetrioService teto = TetrioService(); // thing, that manadge our local DB
|
||||
|
@ -168,8 +169,14 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
news = requests[2] as List<News>;
|
||||
topTR = requests.elementAtOrNull(3) as double?; // No TR - no Top TR
|
||||
|
||||
// Get tetra League leaderboard if needed
|
||||
// if(prefs.getBool("loadLeaderboard") == true) everyone = await teto.fetchTLLeaderboard();
|
||||
meAmongEveryone = teto.getCachedLeaderboardPositions(me.userId);
|
||||
if (meAmongEveryone == null && prefs.getBool("showPositions") == true){
|
||||
// Get tetra League leaderboard
|
||||
everyone = teto.getCachedLeaderboard();
|
||||
everyone ??= await teto.fetchTLLeaderboard();
|
||||
meAmongEveryone = await compute(everyone!.getLeaderboardPosition, me.userId);
|
||||
if (meAmongEveryone != null) teto.cacheLeaderboardPositions(me.userId, meAmongEveryone!);
|
||||
}
|
||||
|
||||
// Making list of Tetra League matches
|
||||
List<TetraLeagueAlphaRecord> tlMatches = [];
|
||||
|
@ -394,7 +401,15 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
body: TabBarView(
|
||||
controller: _tabController,
|
||||
children: [
|
||||
TLThingy(tl: snapshot.data![0].tlSeason1, userID: snapshot.data![0].userId, states: snapshot.data![2], topTR: snapshot.data![7], bot: snapshot.data![0].role == "bot", guest: snapshot.data![0].role == "anon"),
|
||||
TLThingy(
|
||||
tl: snapshot.data![0].tlSeason1,
|
||||
userID: snapshot.data![0].userId,
|
||||
states: snapshot.data![2],
|
||||
topTR: snapshot.data![7],
|
||||
bot: snapshot.data![0].role == "bot",
|
||||
guest: snapshot.data![0].role == "anon",
|
||||
lbPositions: meAmongEveryone
|
||||
),
|
||||
_TLRecords(userID: snapshot.data![0].userId, data: snapshot.data![3]),
|
||||
_History(states: snapshot.data![2], update: _justUpdate),
|
||||
_RecordThingy(record: snapshot.data![1]['sprint'], rank: snapshot.data![0].tlSeason1.percentileRank),
|
||||
|
@ -958,71 +973,58 @@ class _RecordThingy extends StatelessWidget {
|
|||
else if (record!.stream.contains("blitz")) Text(t.blitz, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||
|
||||
// show main metric
|
||||
Wrap(
|
||||
direction: Axis.horizontal,
|
||||
alignment: WrapAlignment.spaceAround,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
children: [
|
||||
// Show grade based on closest rank average
|
||||
if (record!.stream.contains("40l")) Image.asset("res/tetrio_tl_alpha_ranks/${closestAverageSprint.key}.png", height: 96)
|
||||
else if (record!.stream.contains("blitz")) Image.asset("res/tetrio_tl_alpha_ranks/${closestAverageBlitz.key}.png", height: 96),
|
||||
if (record!.stream.contains("40l")) Image.asset("res/tetrio_tl_alpha_ranks/${closestAverageSprint.key}.png", height: 48)
|
||||
else if (record!.stream.contains("blitz")) Image.asset("res/tetrio_tl_alpha_ranks/${closestAverageBlitz.key}.png", height: 48),
|
||||
|
||||
// TODO: I'm not sure abour that element. Maybe, it could be done differenly
|
||||
Column(
|
||||
children: [
|
||||
// Show result
|
||||
if (record!.stream.contains("40l")) Text(get40lTime(record!.endContext!.finalTime.inMicroseconds), style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28))
|
||||
else if (record!.stream.contains("blitz")) Text(NumberFormat.decimalPattern().format(record!.endContext!.score), style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||
|
||||
// Show difference between rank average
|
||||
if (record!.stream.contains("40l") && (rank != null && rank != "z")) Text(
|
||||
"${readableTimeDifference(record!.endContext!.finalTime, sprintAverages[rank]!)} ${sprintBetterThanRankAverage??false ? "better" : "worse"} than ${rank!.toUpperCase()} rank average",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: sprintBetterThanRankAverage??false ?
|
||||
Colors.greenAccent :
|
||||
Colors.redAccent
|
||||
)
|
||||
)
|
||||
else if (record!.stream.contains("40l") && (rank == null || rank == "z")) Text(
|
||||
"${readableTimeDifference(record!.endContext!.finalTime, closestAverageSprint.value)} ${sprintBetterThanClosestAverage ? "better" : "worse"} than ${closestAverageSprint.key!.toUpperCase()} rank average",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: sprintBetterThanClosestAverage ?
|
||||
Colors.greenAccent :
|
||||
Colors.redAccent
|
||||
)
|
||||
)
|
||||
else if (record!.stream.contains("blitz") && (rank != null && rank != "z")) Text(
|
||||
"${readableIntDifference(record!.endContext!.score, blitzAverages[rank]!)} ${blitzBetterThanRankAverage??false ? "better" : "worse"} than ${rank!.toUpperCase()} rank average",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: blitzBetterThanRankAverage??false ?
|
||||
Colors.greenAccent :
|
||||
Colors.redAccent
|
||||
)
|
||||
)
|
||||
else if (record!.stream.contains("blitz") && (rank == null || rank == "z")) Text(
|
||||
"${readableIntDifference(record!.endContext!.score, closestAverageBlitz.value)} ${blitzBetterThanClosestAverage ? "better" : "worse"} than ${closestAverageBlitz.key!.toUpperCase()} rank average",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: blitzBetterThanClosestAverage ?
|
||||
Colors.greenAccent :
|
||||
Colors.redAccent
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
// Show result
|
||||
if (record!.stream.contains("40l")) Text(get40lTime(record!.endContext!.finalTime.inMicroseconds), style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28))
|
||||
else if (record!.stream.contains("blitz")) Text(NumberFormat.decimalPattern().format(record!.endContext!.score), style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||
],
|
||||
),
|
||||
// if (record!.stream.contains("40l")) Text(get40lTime(record!.endContext!.finalTime.inMicroseconds), style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28))
|
||||
// else if (record!.stream.contains("blitz")) Text(NumberFormat.decimalPattern().format(record!.endContext!.score), style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||
|
||||
// // Compare with averages
|
||||
// if (record!.stream.contains("40l") && rank != null) RichText(text: TextSpan(text: "${readableTimeDifference(record!.endContext!.finalTime, sprintAverages[rank]!)} ${sprintBetterThanRankAverage??false ? "better" : "worse"} than ${rank!.toUpperCase()} rank average", style: TextStyle(fontFamily: "Eurostile Round", color: sprintBetterThanRankAverage??false ? Colors.green : Colors.red)))
|
||||
// //Text("${record!.endContext!.finalTime - sprintAverages[rank]!}; ${sprintAverages[rank]}; ${get40lTime((record!.endContext!.finalTime - sprintAverages[rank]!).inMicroseconds)}")
|
||||
// else if (record!.stream.contains("blitz")) Text("${closestAverageBlitz}; ${blitzAverages[rank]}"),
|
||||
// Show difference between rank average
|
||||
if (record!.stream.contains("40l") && (rank != null && rank != "z")) Text(
|
||||
"${readableTimeDifference(record!.endContext!.finalTime, sprintAverages[rank]!)} ${sprintBetterThanRankAverage??false ? "better" : "worse"} than ${rank!.toUpperCase()} rank average",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: sprintBetterThanRankAverage??false ?
|
||||
Colors.greenAccent :
|
||||
Colors.redAccent
|
||||
)
|
||||
)
|
||||
else if (record!.stream.contains("40l") && (rank == null || rank == "z")) Text(
|
||||
"${readableTimeDifference(record!.endContext!.finalTime, closestAverageSprint.value)} ${sprintBetterThanClosestAverage ? "better" : "worse"} than ${closestAverageSprint.key!.toUpperCase()} rank average",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: sprintBetterThanClosestAverage ?
|
||||
Colors.greenAccent :
|
||||
Colors.redAccent
|
||||
)
|
||||
)
|
||||
else if (record!.stream.contains("blitz") && (rank != null && rank != "z")) Text(
|
||||
"${readableIntDifference(record!.endContext!.score, blitzAverages[rank]!)} ${blitzBetterThanRankAverage??false ? "better" : "worse"} than ${rank!.toUpperCase()} rank average",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: blitzBetterThanRankAverage??false ?
|
||||
Colors.greenAccent :
|
||||
Colors.redAccent
|
||||
)
|
||||
)
|
||||
else if (record!.stream.contains("blitz") && (rank == null || rank == "z")) Text(
|
||||
"${readableIntDifference(record!.endContext!.score, closestAverageBlitz.value)} ${blitzBetterThanClosestAverage ? "better" : "worse"} than ${closestAverageBlitz.key!.toUpperCase()} rank average",
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: blitzBetterThanClosestAverage ?
|
||||
Colors.greenAccent :
|
||||
Colors.redAccent
|
||||
)
|
||||
),
|
||||
|
||||
// Show rank if presented
|
||||
if (record!.rank != null) StatCellNum(playerStat: record!.rank!, playerStatLabel: "Leaderboard Placement", isScreenBig: bigScreen, higherIsBetter: false),
|
||||
|
@ -1054,7 +1056,8 @@ class _RecordThingy extends StatelessWidget {
|
|||
|
||||
// List of actions
|
||||
Padding(padding: const EdgeInsets.fromLTRB(0, 16, 0, 48),
|
||||
child: SizedBox(width: bigScreen ? MediaQuery.of(context).size.width * 0.4 : MediaQuery.of(context).size.width * 0.85,
|
||||
child: Container(width: bigScreen ? MediaQuery.of(context).size.width * 0.4 : MediaQuery.of(context).size.width * 0.85,
|
||||
constraints: BoxConstraints(maxWidth: 452),
|
||||
child: Column(crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Row(
|
||||
|
|
|
@ -8,7 +8,6 @@ import 'package:tetra_stats/views/tl_match_view.dart';
|
|||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
final TetrioService teto = TetrioService();
|
||||
final NumberFormat f2 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 2);
|
||||
late String oldWindowTitle;
|
||||
|
||||
class MatchesView extends StatefulWidget {
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import 'dart:io';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:tetra_stats/gen/strings.g.dart';
|
||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||
import 'package:tetra_stats/views/rank_averages_view.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
import 'main_view.dart'; // lol
|
||||
|
@ -40,7 +40,6 @@ class RanksAverages extends State<RankAveragesView> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final NumberFormat f2 = NumberFormat.decimalPattern(LocaleSettings.currentLocale.languageCode)..maximumFractionDigits = 2;
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(t.rankAveragesViewTitle),
|
||||
|
|
|
@ -26,7 +26,7 @@ class SettingsState extends State<SettingsView> {
|
|||
late SharedPreferences prefs;
|
||||
final TetrioService teto = TetrioService();
|
||||
String defaultNickname = "Checking...";
|
||||
late bool loadLeaderboard;
|
||||
late bool showPositions;
|
||||
final TextEditingController _playertext = TextEditingController();
|
||||
|
||||
@override
|
||||
|
@ -47,10 +47,10 @@ class SettingsState extends State<SettingsView> {
|
|||
|
||||
Future<void> _getPreferences() async {
|
||||
prefs = await SharedPreferences.getInstance();
|
||||
if (prefs.getBool("loadLeaderboard") != null) {
|
||||
loadLeaderboard = prefs.getBool("loadLeaderboard")!;
|
||||
if (prefs.getBool("showPositions") != null) {
|
||||
showPositions = prefs.getBool("showPositions")!;
|
||||
} else {
|
||||
loadLeaderboard = false;
|
||||
showPositions = false;
|
||||
}
|
||||
_setDefaultNickname(prefs.getString("player"));
|
||||
}
|
||||
|
@ -266,12 +266,12 @@ class SettingsState extends State<SettingsView> {
|
|||
onTap: () {
|
||||
Navigator.pushNamed(context, "/customization");
|
||||
},),
|
||||
ListTile(title: Text("Load leaderboard on startup"),
|
||||
subtitle: Text("That will allow app to show additional stats, like..."),
|
||||
trailing: Switch(value: loadLeaderboard, onChanged: (bool value){
|
||||
prefs.setBool("loadLeaderboard", value);
|
||||
ListTile(title: Text("Show LB position for each stat"),
|
||||
subtitle: Text("That will impact on app performance..."),
|
||||
trailing: Switch(value: showPositions, onChanged: (bool value){
|
||||
prefs.setBool("showPositions", value);
|
||||
setState(() {
|
||||
loadLeaderboard = value;
|
||||
showPositions = value;
|
||||
});
|
||||
}),),
|
||||
const Divider(),
|
||||
|
|
|
@ -71,7 +71,7 @@ class TLLeaderboardState extends State<TLLeaderboardView> {
|
|||
case ConnectionState.none:
|
||||
case ConnectionState.waiting:
|
||||
case ConnectionState.active:
|
||||
return const Center(child: Text('Fetching...'));
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
case ConnectionState.done:
|
||||
final allPlayers = snapshot.data?.getStatRanking(snapshot.data!.leaderboard, _sortBy, reversed: reversed, country: _country);
|
||||
if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS) windowManager.setTitle("Tetra Stats: ${t.tlLeaderboard} - ${t.players(n: allPlayers!.length)}");
|
||||
|
|
|
@ -0,0 +1,98 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
||||
import 'package:tetra_stats/gen/strings.g.dart';
|
||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||
import 'package:tetra_stats/widgets/tl_thingy.dart';
|
||||
|
||||
class GaugetNum extends StatelessWidget {
|
||||
final num playerStat;
|
||||
final num? oldPlayerStat;
|
||||
final bool higherIsBetter;
|
||||
final List<GaugeRange> ranges;
|
||||
final double minimum;
|
||||
final double maximum;
|
||||
final String playerStatLabel;
|
||||
final String? okText;
|
||||
final String? alertTitle;
|
||||
final List<Widget>? alertWidgets;
|
||||
final LeaderboardPosition? pos;
|
||||
|
||||
const GaugetNum(
|
||||
{super.key,
|
||||
required this.playerStat,
|
||||
required this.playerStatLabel,
|
||||
this.alertWidgets,
|
||||
this.oldPlayerStat,
|
||||
required this.higherIsBetter,
|
||||
required this.minimum,
|
||||
required this.maximum,
|
||||
required this.ranges,
|
||||
this.okText, this.alertTitle, this.pos});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SizedBox(
|
||||
width: 200,
|
||||
height: 120,
|
||||
child: SfRadialGauge(
|
||||
title: GaugeTitle(text: playerStatLabel),
|
||||
axes: [RadialAxis(
|
||||
startAngle: 180,
|
||||
endAngle: 360,
|
||||
showLabels: false,
|
||||
showTicks: false,
|
||||
radiusFactor: 2.1,
|
||||
centerY: 0.5,
|
||||
minimum: minimum,
|
||||
maximum: maximum,
|
||||
ranges: ranges,
|
||||
pointers: [
|
||||
NeedlePointer(
|
||||
value: playerStat as double,
|
||||
enableAnimation: true,
|
||||
needleLength: 0.9,
|
||||
needleStartWidth: 2,
|
||||
needleEndWidth: 15,
|
||||
knobStyle: const KnobStyle(color: Colors.transparent),
|
||||
gradient: const LinearGradient(colors: [Colors.transparent, Colors.white], begin: Alignment.bottomCenter, end: Alignment.topCenter, stops: [0.5, 1]),)
|
||||
],
|
||||
annotations: [GaugeAnnotation(
|
||||
widget: TextButton(child: Text(f3.format(playerStat),
|
||||
style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, color: Colors.white)),
|
||||
onPressed: (){
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) => AlertDialog(
|
||||
title: Text(alertTitle??playerStatLabel, style: const TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||
content: SingleChildScrollView(child: ListBody(children: alertWidgets!)),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(okText??t.popupActions.ok),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
)
|
||||
],
|
||||
));
|
||||
},), verticalAlignment: GaugeAlignment.far, positionFactor: 0.05),
|
||||
if (oldPlayerStat != null || pos != null) GaugeAnnotation(
|
||||
widget: RichText(text: TextSpan(
|
||||
text: "",
|
||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey),
|
||||
children: [
|
||||
if (oldPlayerStat != null) TextSpan(text: comparef.format(playerStat - oldPlayerStat!), style: TextStyle(
|
||||
color: higherIsBetter ?
|
||||
oldPlayerStat! > playerStat ? Colors.redAccent : Colors.greenAccent :
|
||||
oldPlayerStat! < playerStat ? Colors.redAccent : Colors.greenAccent
|
||||
),),
|
||||
if ((oldTl != null && oldTl!.gamesPlayed > 0) && pos != null) const TextSpan(text: " • "),
|
||||
if (pos != null) TextSpan(text: pos!.position >= 1000 ? "Top ${f2.format(pos!.percentage*100)}%" : "№${pos!.position}")
|
||||
]
|
||||
),
|
||||
),
|
||||
positionFactor: 0.05)],
|
||||
)],),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:tetra_stats/gen/strings.g.dart';
|
||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||
|
||||
class TrailingStats extends StatelessWidget{
|
||||
final double yourAPM;
|
||||
|
@ -14,7 +13,6 @@ class TrailingStats extends StatelessWidget{
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final NumberFormat f2 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 2);
|
||||
const TextStyle style = TextStyle(height: 1.1, fontWeight: FontWeight.w100);
|
||||
return Table(
|
||||
defaultColumnWidth: const IntrinsicColumnWidth(),
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
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/utils/numers_formats.dart';
|
||||
|
||||
class StatCellNum extends StatelessWidget {
|
||||
const StatCellNum(
|
||||
|
@ -12,7 +14,7 @@ class StatCellNum extends StatelessWidget {
|
|||
this.fractionDigits,
|
||||
this.oldPlayerStat,
|
||||
required this.higherIsBetter,
|
||||
this.okText, this.alertTitle});
|
||||
this.okText, this.alertTitle, this.pos});
|
||||
|
||||
final num playerStat;
|
||||
final num? oldPlayerStat;
|
||||
|
@ -23,11 +25,11 @@ class StatCellNum extends StatelessWidget {
|
|||
final String? alertTitle;
|
||||
final List<Widget>? alertWidgets;
|
||||
final int? fractionDigits;
|
||||
final LeaderboardPosition? pos;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
NumberFormat comparef = NumberFormat("+#,###.###;-#,###.###")..maximumFractionDigits = fractionDigits ?? 0;
|
||||
NumberFormat intf = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 0);
|
||||
NumberFormat fractionf = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: fractionDigits ?? 0)..maximumIntegerDigits = 0;
|
||||
num fraction = playerStat.isNegative ? 1 - (playerStat - playerStat.floor()) : playerStat - playerStat.floor();
|
||||
int integer = playerStat.isNegative ? (playerStat + fraction).toInt() : (playerStat - fraction).toInt();
|
||||
|
@ -48,11 +50,20 @@ class StatCellNum extends StatelessWidget {
|
|||
)
|
||||
)
|
||||
),
|
||||
if (oldPlayerStat != null) Text(comparef.format(playerStat - oldPlayerStat!), style: TextStyle(
|
||||
color: higherIsBetter ?
|
||||
oldPlayerStat! > playerStat ? Colors.redAccent : Colors.greenAccent :
|
||||
oldPlayerStat! < playerStat ? Colors.redAccent : Colors.greenAccent
|
||||
),),
|
||||
if (oldPlayerStat != null || pos != null) RichText(text: TextSpan(
|
||||
text: "",
|
||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey),
|
||||
children: [
|
||||
if (oldPlayerStat != null) TextSpan(text: comparef.format(playerStat - oldPlayerStat!), style: TextStyle(
|
||||
color: higherIsBetter ?
|
||||
oldPlayerStat! > playerStat ? Colors.redAccent : Colors.greenAccent :
|
||||
oldPlayerStat! < playerStat ? Colors.redAccent : Colors.greenAccent
|
||||
),),
|
||||
if (oldPlayerStat != null && pos != null) const TextSpan(text: " • "),
|
||||
if (pos != null) TextSpan(text: pos!.position >= 1000 ? "Top ${f2.format(pos!.percentage*100)}%" : "№${pos!.position}")
|
||||
]
|
||||
),
|
||||
),
|
||||
alertWidgets == null
|
||||
? Text(
|
||||
playerStatLabel,
|
||||
|
|
|
@ -3,13 +3,14 @@ import 'package:intl/intl.dart';
|
|||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
||||
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
||||
import 'package:tetra_stats/gen/strings.g.dart';
|
||||
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||
import 'package:tetra_stats/widgets/gauget_num.dart';
|
||||
import 'package:tetra_stats/widgets/graphs.dart';
|
||||
import 'package:tetra_stats/widgets/stat_sell_num.dart';
|
||||
|
||||
var fDiff = NumberFormat("+#,###.###;-#,###.###");
|
||||
var intFDiff = NumberFormat("+#,###;-#,###");
|
||||
final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
|
||||
final NumberFormat f2 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 2);
|
||||
final NumberFormat f3 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 3);
|
||||
late RangeValues _currentRangeValues;
|
||||
TetraLeagueAlpha? oldTl;
|
||||
late TetraLeagueAlpha currentTl;
|
||||
|
@ -23,7 +24,8 @@ class TLThingy extends StatefulWidget {
|
|||
final bool bot;
|
||||
final bool guest;
|
||||
final double? topTR;
|
||||
const TLThingy({super.key, required this.tl, required this.userID, required this.states, this.showTitle = true, this.bot=false, this.guest=false, this.topTR});
|
||||
final PlayerLeaderboardPosition? lbPositions;
|
||||
const TLThingy({super.key, required this.tl, required this.userID, required this.states, this.showTitle = true, this.bot=false, this.guest=false, this.topTR, this.lbPositions});
|
||||
|
||||
@override
|
||||
State<TLThingy> createState() => _TLThingyState();
|
||||
|
@ -47,6 +49,8 @@ class _TLThingyState extends State<TLThingy> {
|
|||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Translations.of(context);
|
||||
NumberFormat fractionfEstTR = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 2)..maximumIntegerDigits = 0;
|
||||
NumberFormat fractionfEstTRAcc = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 3)..maximumIntegerDigits = 0;
|
||||
if (currentTl.gamesPlayed == 0) return Center(child: Text(widget.guest ? t.anonTL : widget.bot ? t.botTL : t.neverPlayedTL, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28), textAlign: TextAlign.center,));
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
bool bigScreen = constraints.maxWidth > 768;
|
||||
|
@ -159,13 +163,13 @@ class _TLThingyState extends State<TLThingy> {
|
|||
crossAxisAlignment: WrapCrossAlignment.start,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
children: [
|
||||
if (currentTl.apm != null) StatCellNum(playerStat: currentTl.apm!, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.apm, higherIsBetter: true, oldPlayerStat: oldTl?.apm),
|
||||
if (currentTl.pps != null) StatCellNum(playerStat: currentTl.pps!, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.pps, higherIsBetter: true, oldPlayerStat: oldTl?.pps),
|
||||
if (currentTl.vs != null) StatCellNum(playerStat: currentTl.vs!, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.vs, higherIsBetter: true, oldPlayerStat: oldTl?.vs),
|
||||
if (currentTl.apm != null) StatCellNum(playerStat: currentTl.apm!, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.apm, higherIsBetter: true, oldPlayerStat: oldTl?.apm, pos: widget.lbPositions?.apm),
|
||||
if (currentTl.pps != null) StatCellNum(playerStat: currentTl.pps!, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.pps, higherIsBetter: true, oldPlayerStat: oldTl?.pps, pos: widget.lbPositions?.pps),
|
||||
if (currentTl.vs != null) StatCellNum(playerStat: currentTl.vs!, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.vs, higherIsBetter: true, oldPlayerStat: oldTl?.vs, pos: widget.lbPositions?.vs),
|
||||
if (currentTl.standingLocal > 0) StatCellNum(playerStat: currentTl.standingLocal, isScreenBig: bigScreen, playerStatLabel: t.statCellNum.lbpc, higherIsBetter: false, oldPlayerStat: oldTl?.standingLocal),
|
||||
StatCellNum(playerStat: currentTl.gamesPlayed, isScreenBig: bigScreen, playerStatLabel: t.statCellNum.gamesPlayed, higherIsBetter: true, oldPlayerStat: oldTl?.gamesPlayed),
|
||||
StatCellNum(playerStat: currentTl.gamesWon, isScreenBig: bigScreen, playerStatLabel: t.statCellNum.gamesWonTL, higherIsBetter: true, oldPlayerStat: oldTl?.gamesWon),
|
||||
StatCellNum(playerStat: currentTl.winrate * 100, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.winrate, higherIsBetter: true, oldPlayerStat: oldTl != null ? oldTl!.winrate*100 : null),
|
||||
StatCellNum(playerStat: currentTl.gamesPlayed, isScreenBig: bigScreen, playerStatLabel: t.statCellNum.gamesPlayed, higherIsBetter: true, oldPlayerStat: oldTl?.gamesPlayed, pos: widget.lbPositions?.gamesPlayed),
|
||||
StatCellNum(playerStat: currentTl.gamesWon, isScreenBig: bigScreen, playerStatLabel: t.statCellNum.gamesWonTL, higherIsBetter: true, oldPlayerStat: oldTl?.gamesWon, pos: widget.lbPositions?.gamesWon),
|
||||
StatCellNum(playerStat: currentTl.winrate * 100, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.winrate, higherIsBetter: true, oldPlayerStat: oldTl != null ? oldTl!.winrate*100 : null, pos: widget.lbPositions?.winrate),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -176,138 +180,31 @@ class _TLThingyState extends State<TLThingy> {
|
|||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 40, 0, 0),
|
||||
child: Wrap(
|
||||
direction: Axis.horizontal,
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 35,
|
||||
crossAxisAlignment: WrapCrossAlignment.start,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 200,
|
||||
height: 120,
|
||||
child: SfRadialGauge(
|
||||
title: GaugeTitle(text: t.statCellNum.app),
|
||||
axes: [RadialAxis(
|
||||
startAngle: 180,
|
||||
endAngle: 360,
|
||||
showLabels: false,
|
||||
showTicks: false,
|
||||
radiusFactor: 2.1,
|
||||
centerY: 0.5,
|
||||
minimum: 0,
|
||||
maximum: 1,
|
||||
ranges: [
|
||||
GaugeRange(startValue: 0, endValue: 0.2, color: Colors.red),
|
||||
GaugeRange(startValue: 0.2, endValue: 0.4, color: Colors.yellow),
|
||||
GaugeRange(startValue: 0.4, endValue: 0.6, color: Colors.green),
|
||||
GaugeRange(startValue: 0.6, endValue: 0.8, color: Colors.blue),
|
||||
GaugeRange(startValue: 0.8, endValue: 1, color: Colors.purple),
|
||||
],
|
||||
pointers: [
|
||||
NeedlePointer(
|
||||
value: currentTl.nerdStats!.app,
|
||||
enableAnimation: true,
|
||||
needleLength: 0.9,
|
||||
needleStartWidth: 2,
|
||||
needleEndWidth: 15,
|
||||
knobStyle: const KnobStyle(color: Colors.transparent),
|
||||
gradient: const LinearGradient(colors: [Colors.transparent, Colors.white], begin: Alignment.bottomCenter, end: Alignment.topCenter, stops: [0.5, 1]),)
|
||||
],
|
||||
annotations: [GaugeAnnotation(
|
||||
widget: TextButton(child: Text(f3.format(currentTl.nerdStats!.app),
|
||||
style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, color: Colors.white)),
|
||||
onPressed: (){
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) => AlertDialog(
|
||||
title: Text(t.statCellNum.app,
|
||||
style: const TextStyle(
|
||||
fontFamily: "Eurostile Round Extended")),
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(children: [
|
||||
Text(t.statCellNum.appDescription),
|
||||
Text("${t.exactValue}: ${currentTl.nerdStats!.app}")
|
||||
]),
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(t.popupActions.ok),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
)
|
||||
],
|
||||
));
|
||||
},), verticalAlignment: GaugeAlignment.far, positionFactor: 0.05,),
|
||||
if (oldTl != null && oldTl!.gamesPlayed > 0) GaugeAnnotation(widget: Text(fDiff.format(currentTl.nerdStats!.app - oldTl!.nerdStats!.app), style: TextStyle(
|
||||
color: currentTl.nerdStats!.app - oldTl!.nerdStats!.app < 0 ?
|
||||
Colors.redAccent :
|
||||
Colors.greenAccent
|
||||
),), positionFactor: 0.05,)],
|
||||
)],),
|
||||
),
|
||||
SizedBox(
|
||||
width: 200,
|
||||
height: 120,
|
||||
child: SfRadialGauge(
|
||||
title: const GaugeTitle(text: "VS / APM"),
|
||||
axes: [RadialAxis(
|
||||
startAngle: 180,
|
||||
endAngle: 360,
|
||||
showTicks: false,
|
||||
showLabels: false,
|
||||
radiusFactor: 2.1,
|
||||
centerY: 0.5,
|
||||
minimum: 1.8,
|
||||
maximum: 2.4,
|
||||
ranges: [
|
||||
GaugeRange(startValue: 1.8, endValue: 2.0, color: Colors.green),
|
||||
GaugeRange(startValue: 2.0, endValue: 2.2, color: Colors.blue),
|
||||
GaugeRange(startValue: 2.2, endValue: 2.4, color: Colors.purple),
|
||||
],
|
||||
pointers: [
|
||||
NeedlePointer(
|
||||
value: currentTl.nerdStats!.vsapm,
|
||||
enableAnimation: true,
|
||||
needleLength: 0.9,
|
||||
needleStartWidth: 2,
|
||||
needleEndWidth: 15,
|
||||
knobStyle: const KnobStyle(color: Colors.transparent),
|
||||
gradient: const LinearGradient(colors: [Colors.transparent, Colors.white], begin: Alignment.bottomCenter, end: Alignment.topCenter, stops: [0.5, 1]),)
|
||||
],
|
||||
annotations: [GaugeAnnotation(
|
||||
widget: TextButton(child: Text(f3.format(currentTl.nerdStats!.vsapm),
|
||||
style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, color: Colors.white)),
|
||||
onPressed: (){
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) => AlertDialog(
|
||||
title: const Text("VS / APM",
|
||||
style: TextStyle(
|
||||
fontFamily: "Eurostile Round Extended")),
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(children: [
|
||||
Text(t.statCellNum.vsapmDescription),
|
||||
Text("${t.exactValue}: ${currentTl.nerdStats!.vsapm}")
|
||||
]),
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(t.popupActions.ok),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
)
|
||||
],
|
||||
));
|
||||
},), verticalAlignment: GaugeAlignment.far, positionFactor: 0.05),
|
||||
if (oldTl != null && oldTl!.gamesPlayed > 0) GaugeAnnotation(widget: Text(fDiff.format(currentTl.nerdStats!.vsapm - oldTl!.nerdStats!.vsapm), style: TextStyle(
|
||||
color: currentTl.nerdStats!.vsapm - oldTl!.nerdStats!.vsapm < 0 ?
|
||||
Colors.redAccent :
|
||||
Colors.greenAccent
|
||||
),), positionFactor: 0.05,)],
|
||||
)],),
|
||||
),]),
|
||||
direction: Axis.horizontal,
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 35,
|
||||
crossAxisAlignment: WrapCrossAlignment.start,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
children: [
|
||||
GaugetNum(playerStat: currentTl.nerdStats!.app, playerStatLabel: t.statCellNum.app, higherIsBetter: true, minimum: 0, maximum: 1, ranges: [
|
||||
GaugeRange(startValue: 0, endValue: 0.2, color: Colors.red),
|
||||
GaugeRange(startValue: 0.2, endValue: 0.4, color: Colors.yellow),
|
||||
GaugeRange(startValue: 0.4, endValue: 0.6, color: Colors.green),
|
||||
GaugeRange(startValue: 0.6, endValue: 0.8, color: Colors.blue),
|
||||
GaugeRange(startValue: 0.8, endValue: 1, color: Colors.purple),
|
||||
], alertWidgets: [
|
||||
Text(t.statCellNum.appDescription),
|
||||
Text("${t.exactValue}: ${currentTl.nerdStats!.app}")
|
||||
], oldPlayerStat: oldTl?.nerdStats?.app, pos: widget.lbPositions?.app),
|
||||
GaugetNum(playerStat: currentTl.nerdStats!.vsapm, playerStatLabel: "VS / APM", higherIsBetter: true, minimum: 1.8, maximum: 2.4, ranges: [
|
||||
GaugeRange(startValue: 1.8, endValue: 2.0, color: Colors.green),
|
||||
GaugeRange(startValue: 2.0, endValue: 2.2, color: Colors.blue),
|
||||
GaugeRange(startValue: 2.2, endValue: 2.4, color: Colors.purple),
|
||||
], alertWidgets: [
|
||||
Text(t.statCellNum.vsapmDescription),
|
||||
Text("${t.exactValue}: ${currentTl.nerdStats!.vsapm}")
|
||||
], oldPlayerStat: oldTl?.nerdStats?.vsapm, pos: widget.lbPositions?.vsapm)
|
||||
]),
|
||||
),
|
||||
Wrap(
|
||||
direction: Axis.horizontal,
|
||||
|
@ -317,6 +214,7 @@ class _TLThingyState extends State<TLThingy> {
|
|||
clipBehavior: Clip.hardEdge,
|
||||
children: [
|
||||
StatCellNum(playerStat: currentTl.nerdStats!.dss, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.dss,
|
||||
pos: widget.lbPositions?.dss,
|
||||
alertWidgets: [Text(t.statCellNum.dssDescription),
|
||||
Text("${t.formula}: (VS / 100) - (APM / 60)"),
|
||||
Text("${t.exactValue}: ${currentTl.nerdStats!.dss}"),],
|
||||
|
@ -324,6 +222,7 @@ class _TLThingyState extends State<TLThingy> {
|
|||
higherIsBetter: true,
|
||||
oldPlayerStat: oldTl?.nerdStats?.dss,),
|
||||
StatCellNum(playerStat: currentTl.nerdStats!.dsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.dsp,
|
||||
pos: widget.lbPositions?.dsp,
|
||||
alertWidgets: [Text(t.statCellNum.dspDescription),
|
||||
Text("${t.formula}: DS/S / PPS"),
|
||||
Text("${t.exactValue}: ${currentTl.nerdStats!.dsp}"),],
|
||||
|
@ -331,6 +230,7 @@ class _TLThingyState extends State<TLThingy> {
|
|||
higherIsBetter: true,
|
||||
oldPlayerStat: oldTl?.nerdStats?.dsp,),
|
||||
StatCellNum(playerStat: currentTl.nerdStats!.appdsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.appdsp,
|
||||
pos: widget.lbPositions?.appdsp,
|
||||
alertWidgets: [Text(t.statCellNum.appdspDescription),
|
||||
Text("${t.formula}: APP + DS/P"),
|
||||
Text("${t.exactValue}: ${currentTl.nerdStats!.appdsp}"),],
|
||||
|
@ -338,6 +238,7 @@ class _TLThingyState extends State<TLThingy> {
|
|||
higherIsBetter: true,
|
||||
oldPlayerStat: oldTl?.nerdStats?.appdsp,),
|
||||
StatCellNum(playerStat: currentTl.nerdStats!.cheese, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.cheese,
|
||||
pos: widget.lbPositions?.cheese,
|
||||
alertWidgets: [Text(t.statCellNum.cheeseDescription),
|
||||
Text("${t.formula}: (DS/P * 150) + ((VS/APM - 2) * 50) + (0.6 - APP) * 125"),
|
||||
Text("${t.exactValue}: ${currentTl.nerdStats!.cheese}"),],
|
||||
|
@ -345,6 +246,7 @@ class _TLThingyState extends State<TLThingy> {
|
|||
higherIsBetter: true,
|
||||
oldPlayerStat: oldTl?.nerdStats?.cheese,),
|
||||
StatCellNum(playerStat: currentTl.nerdStats!.gbe, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.gbe,
|
||||
pos: widget.lbPositions?.gbe,
|
||||
alertWidgets: [Text(t.statCellNum.gbeDescription),
|
||||
Text("${t.formula}: APP * DS/P * 2"),
|
||||
Text("${t.exactValue}: ${currentTl.nerdStats!.gbe}"),],
|
||||
|
@ -352,6 +254,7 @@ class _TLThingyState extends State<TLThingy> {
|
|||
higherIsBetter: true,
|
||||
oldPlayerStat: oldTl?.nerdStats?.gbe,),
|
||||
StatCellNum(playerStat: currentTl.nerdStats!.nyaapp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.nyaapp,
|
||||
pos: widget.lbPositions?.nyaapp,
|
||||
alertWidgets: [Text(t.statCellNum.nyaappDescription),
|
||||
Text("${t.formula}: APP - 5 * tan(radians((Cheese Index / -30) + 1))"),
|
||||
Text("${t.exactValue}: ${currentTl.nerdStats!.nyaapp}"),],
|
||||
|
@ -359,6 +262,7 @@ class _TLThingyState extends State<TLThingy> {
|
|||
higherIsBetter: true,
|
||||
oldPlayerStat: oldTl?.nerdStats?.nyaapp,),
|
||||
StatCellNum(playerStat: currentTl.nerdStats!.area, isScreenBig: bigScreen, fractionDigits: 1, playerStatLabel: t.statCellNum.area,
|
||||
pos: widget.lbPositions?.area,
|
||||
alertWidgets: [Text(t.statCellNum.areaDescription),
|
||||
Text("${t.formula}: APM * 1 + PPS * 45 + VS * 0.444 + APP * 185 + DS/S * 175 + DS/P * 450 + Garbage Effi * 315"),
|
||||
Text("${t.exactValue}: ${currentTl.nerdStats!.area}"),],
|
||||
|
@ -370,42 +274,104 @@ class _TLThingyState extends State<TLThingy> {
|
|||
),
|
||||
if (currentTl.estTr != null)
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 16, 0, 48),
|
||||
child: SizedBox(
|
||||
padding: const EdgeInsets.fromLTRB(0, 48, 0, 48),
|
||||
child: Container(
|
||||
//alignment: Alignment.center,
|
||||
width: bigScreen ? MediaQuery.of(context).size.width * 0.4 : MediaQuery.of(context).size.width * 0.85,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
constraints: BoxConstraints(maxWidth: 768),
|
||||
child: Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
spacing: 20,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
"${bigScreen ? t.statCellNum.estOfTR : t.statCellNum.estOfTRShort}:",
|
||||
style: const TextStyle(fontSize: 24),
|
||||
Text(t.statCellNum.estOfTR, style: TextStyle(height: 0.1),),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
text: intf.format(currentTl.estTr!.esttr.truncate()),
|
||||
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, fontWeight: FontWeight.w500),
|
||||
children: [TextSpan(text: fractionfEstTR.format(currentTl.estTr!.esttr - currentTl.estTr!.esttr.truncate()).substring(1), style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))]
|
||||
),
|
||||
),
|
||||
Text(
|
||||
f2.format(currentTl.estTr!.esttr),
|
||||
style: const TextStyle(fontSize: 24),
|
||||
if (oldTl?.estTr?.esttr != null || widget.lbPositions != null) RichText(text: TextSpan(
|
||||
text: "",
|
||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey, height: 0.5),
|
||||
children: [
|
||||
if (oldTl?.estTr?.esttr != null) TextSpan(text: comparef.format(currentTl.estTr!.esttr - oldTl!.estTr!.esttr), style: TextStyle(
|
||||
color: oldTl!.estTr!.esttr > currentTl.estTr!.esttr ? Colors.redAccent : Colors.greenAccent
|
||||
),),
|
||||
if (oldTl?.estTr?.esttr != null && widget.lbPositions?.estTr != null) const TextSpan(text: " • "),
|
||||
if (widget.lbPositions?.estTr != null) TextSpan(text: widget.lbPositions!.estTr.position >= 1000 ? "Top ${f2.format(widget.lbPositions!.estTr.percentage*100)}%" : "№${widget.lbPositions!.estTr.position}")
|
||||
]
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
if (currentTl.rating >= 0)
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
],),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Text(t.statCellNum.accOfEst, style: const TextStyle(height: 0.1),),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
text: (currentTl.esttracc != null) ? intFDiff.format(currentTl.esttracc!.truncate()) : "-",
|
||||
style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, fontWeight: FontWeight.w500),
|
||||
children: [
|
||||
TextSpan(text: (currentTl.esttracc != null) ? fractionfEstTRAcc.format(currentTl.esttracc!.isNegative ? 1 - (currentTl.esttracc! - currentTl.esttracc!.truncate()) : (currentTl.esttracc! - currentTl.esttracc!.truncate())).substring(1) : ".---", style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))
|
||||
]
|
||||
),
|
||||
),
|
||||
if (oldTl?.esttracc != null || widget.lbPositions != null) RichText(text: TextSpan(
|
||||
text: "",
|
||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey, height: 0.5),
|
||||
children: [
|
||||
Text(
|
||||
"${bigScreen ? t.statCellNum.accOfEst : t.statCellNum.accOfEstShort}:",
|
||||
style: const TextStyle(fontSize: 24),
|
||||
),
|
||||
Text(
|
||||
fDiff.format(currentTl.esttracc!),
|
||||
style: const TextStyle(fontSize: 24),
|
||||
),
|
||||
],
|
||||
if (oldTl?.esttracc != null) TextSpan(text: comparef.format(currentTl.esttracc! - oldTl!.esttracc!), style: TextStyle(
|
||||
color: oldTl!.esttracc! > currentTl.esttracc! ? Colors.redAccent : Colors.greenAccent
|
||||
),),
|
||||
if (oldTl?.esttracc != null && widget.lbPositions?.accOfEst != null) const TextSpan(text: " • "),
|
||||
if (widget.lbPositions?.accOfEst != null) TextSpan(text: widget.lbPositions!.accOfEst.position >= 1000 ? "Top ${f2.format(widget.lbPositions!.accOfEst.percentage*100)}%" : "№${widget.lbPositions!.accOfEst.position}")
|
||||
]
|
||||
),
|
||||
),
|
||||
],)
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
// child: Container(
|
||||
// width: bigScreen ? MediaQuery.of(context).size.width * 0.4 : MediaQuery.of(context).size.width * 0.85,
|
||||
// constraints: BoxConstraints(maxWidth: 452),
|
||||
// child: Column(
|
||||
// crossAxisAlignment: CrossAxisAlignment.start,
|
||||
// children: [
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// Text(
|
||||
// "${bigScreen ? t.statCellNum.estOfTR : t.statCellNum.estOfTRShort}:",
|
||||
// style: const TextStyle(fontSize: 24),
|
||||
// ),
|
||||
// Text(
|
||||
// f2.format(currentTl.estTr!.esttr),
|
||||
// style: const TextStyle(fontSize: 24),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// if (currentTl.rating >= 0)
|
||||
// Row(
|
||||
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
// children: [
|
||||
// Text(
|
||||
// "${bigScreen ? t.statCellNum.accOfEst : t.statCellNum.accOfEstShort}:",
|
||||
// style: const TextStyle(fontSize: 24),
|
||||
// ),
|
||||
// Text(
|
||||
// fDiff.format(currentTl.esttracc!),
|
||||
// style: const TextStyle(fontSize: 24),
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ],
|
||||
// ),
|
||||
// ),
|
||||
),
|
||||
if (currentTl.nerdStats != null) Graphs(currentTl.apm!, currentTl.pps!, currentTl.vs!, currentTl.nerdStats!, currentTl.playstyle!)
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue