Zenith added
I probably should push Nerd Stats into new widget, but i planning to redo UI a little bit, so idk
This commit is contained in:
parent
90ad788c6c
commit
c1561fba80
|
@ -457,8 +457,10 @@ class TetrioPlayer {
|
|||
|
||||
class Summaries{
|
||||
late String id;
|
||||
late RecordSingle sprint;
|
||||
late RecordSingle blitz;
|
||||
RecordSingle? sprint;
|
||||
RecordSingle? blitz;
|
||||
RecordSingle? zenith;
|
||||
RecordSingle? zenithEx;
|
||||
late TetraLeagueAlpha league;
|
||||
late TetrioZen zen;
|
||||
|
||||
|
@ -466,8 +468,10 @@ class Summaries{
|
|||
|
||||
Summaries.fromJson(Map<String, dynamic> json, String i){
|
||||
id = i;
|
||||
sprint = RecordSingle.fromJson(json['40l']['record'], json['40l']['rank']);
|
||||
blitz = RecordSingle.fromJson(json['blitz']['record'], json['blitz']['rank']);
|
||||
if (json['40l']['record'] != null) sprint = RecordSingle.fromJson(json['40l']['record'], json['40l']['rank'], json['40l']['rank_local']);
|
||||
if (json['blitz']['record'] != null) blitz = RecordSingle.fromJson(json['blitz']['record'], json['blitz']['rank'], json['40l']['rank_local']);
|
||||
if (json['zenith']['record'] != null) zenith = RecordSingle.fromJson(json['zenith']['record'], json['zenith']['rank'], json['zenith']['rank_local']);
|
||||
if (json['zenithex']['record'] != null) zenithEx = RecordSingle.fromJson(json['zenithex']['record'], json['zenithex']['rank'], json['zenithex']['rank_local']);
|
||||
league = TetraLeagueAlpha.fromJson(json['league'], DateTime.now());
|
||||
zen = TetrioZen.fromJson(json['zen']);
|
||||
}
|
||||
|
@ -676,11 +680,13 @@ class ResultsStats {
|
|||
late int piecesPlaced;
|
||||
late int lines;
|
||||
late int score;
|
||||
late int seed;
|
||||
int? seed;
|
||||
late Duration finalTime;
|
||||
late int tSpins;
|
||||
late Clears clears;
|
||||
late Finesse? finesse;
|
||||
late int kills;
|
||||
Finesse? finesse;
|
||||
ZenithResults? zenith;
|
||||
|
||||
double get pps => piecesPlaced / (finalTime.inMicroseconds / 1000000);
|
||||
double get kpp => inputs / piecesPlaced;
|
||||
|
@ -717,7 +723,9 @@ class ResultsStats {
|
|||
tSpins = json['tspins'];
|
||||
piecesPlaced = json['piecesplaced'];
|
||||
clears = Clears.fromJson(json['clears']);
|
||||
finesse = json.containsKey("finesse") ? Finesse.fromJson(json['finesse']) : null;
|
||||
kills = json['kills'];
|
||||
if (json.containsKey("finesse")) finesse = Finesse.fromJson(json['finesse']);
|
||||
if (json.containsKey("zenith")) zenith = ZenithResults.fromJson(json['zenith']);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
@ -739,6 +747,39 @@ class ResultsStats {
|
|||
}
|
||||
}
|
||||
|
||||
class ZenithResults{
|
||||
late double altitude;
|
||||
late double rank;
|
||||
late double peakrank;
|
||||
late double avgrankpts;
|
||||
late int floor;
|
||||
late double targetingfactor;
|
||||
late double targetinggrace;
|
||||
late double totalbonus;
|
||||
late int revives;
|
||||
late int revivesTotal;
|
||||
late bool speedrun;
|
||||
late bool speedrunSeen;
|
||||
late List<Duration> splits;
|
||||
|
||||
ZenithResults.fromJson(Map<String, dynamic> json){
|
||||
altitude = json['altitude'].toDouble();
|
||||
rank = json['rank'].toDouble();
|
||||
peakrank = json['peakrank'].toDouble();
|
||||
avgrankpts = json['avgrankpts'].toDouble();
|
||||
floor = json['floor'];
|
||||
targetingfactor = json['targetingfactor'].toDouble();
|
||||
targetinggrace = json['targetinggrace'].toDouble();
|
||||
totalbonus = json['totalbonus'].toDouble();
|
||||
revives = json['revives'];
|
||||
revivesTotal = json['revivesTotal'];
|
||||
speedrun = json['speedrun'];
|
||||
speedrunSeen = json['speedrun_seen'];
|
||||
splits = [];
|
||||
for (int ms in json['splits']) splits.add(Duration(milliseconds: ms));
|
||||
}
|
||||
}
|
||||
|
||||
class Handling {
|
||||
late num arr;
|
||||
late num das;
|
||||
|
@ -997,7 +1038,7 @@ class SingleplayerStream{
|
|||
userId = userID;
|
||||
type = tp;
|
||||
records = [];
|
||||
for (var value in json) {records.add(RecordSingle.fromJson(value, null));}
|
||||
for (var value in json) {records.add(RecordSingle.fromJson(value, -1, -1));}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1079,9 +1120,9 @@ class BetaLeagueStats{
|
|||
}
|
||||
|
||||
BetaLeagueStats.fromJson(Map<String, dynamic> json){
|
||||
apm = json['apm'].toDouble();
|
||||
pps = json['pps'].toDouble();
|
||||
vs = json['vsscore'].toDouble();
|
||||
apm = json['apm'] != null ? json['apm'].toDouble() : 0.00;
|
||||
pps = json['apm'] != null ? json['pps'].toDouble() : 0.00;
|
||||
vs = json['apm'] != null ? json['vsscore'].toDouble() : 0.00;
|
||||
garbageSent = json['garbagesent'];
|
||||
garbageReceived = json['garbagereceived'];
|
||||
kills = json['kills'];
|
||||
|
@ -1364,11 +1405,13 @@ class RecordSingle {
|
|||
late String gamemode;
|
||||
late DateTime timestamp;
|
||||
late ResultsStats stats;
|
||||
int? rank;
|
||||
late int rank;
|
||||
late int countryRank;
|
||||
late AggregateStats aggregateStats;
|
||||
|
||||
RecordSingle({required this.userId, required this.replayId, required this.ownId, required this.timestamp, required this.stats, this.rank});
|
||||
RecordSingle({required this.userId, required this.replayId, required this.ownId, required this.timestamp, required this.stats, required this.rank, required this.countryRank, required this.aggregateStats});
|
||||
|
||||
RecordSingle.fromJson(Map<String, dynamic> json, int? ran) {
|
||||
RecordSingle.fromJson(Map<String, dynamic> json, int ran, int cran) {
|
||||
//developer.log("RecordSingle.fromJson: $json", name: "data_objects/tetrio");
|
||||
ownId = json['_id'];
|
||||
gamemode = json['gamemode'];
|
||||
|
@ -1377,6 +1420,8 @@ class RecordSingle {
|
|||
timestamp = DateTime.parse(json['ts']);
|
||||
userId = json['user']['id'];
|
||||
rank = ran;
|
||||
countryRank = cran;
|
||||
aggregateStats = AggregateStats.fromJson(json['results']['aggregatestats']);
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
@ -1391,12 +1436,38 @@ class RecordSingle {
|
|||
}
|
||||
}
|
||||
|
||||
class AggregateStats{
|
||||
late double apm;
|
||||
late double pps;
|
||||
late double vs;
|
||||
late NerdStats nerdStats;
|
||||
late EstTr estTr;
|
||||
late Playstyle playstyle;
|
||||
|
||||
AggregateStats(this.apm, this.pps, this.vs){
|
||||
nerdStats = NerdStats(apm, pps, vs);
|
||||
estTr = EstTr(apm, pps, vs, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);
|
||||
playstyle = Playstyle(apm, pps, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank);
|
||||
}
|
||||
|
||||
AggregateStats.fromJson(Map<String, dynamic> json){
|
||||
apm = json['apm'] != null ? json['apm'].toDouble() : 0.00;
|
||||
pps = json['apm'] != null ? json['pps'].toDouble() : 0.00;
|
||||
vs = json['apm'] != null ? json['vsscore'].toDouble() : 0.00;
|
||||
nerdStats = NerdStats(apm, pps, vs);
|
||||
estTr = EstTr(apm, pps, vs, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);
|
||||
playstyle = Playstyle(apm, pps, nerdStats.app, nerdStats.vsapm, nerdStats.dsp, nerdStats.gbe, estTr.srarea, estTr.statrank);
|
||||
}
|
||||
}
|
||||
|
||||
class TetrioZen {
|
||||
late int level;
|
||||
late int score;
|
||||
|
||||
TetrioZen({required this.level, required this.score});
|
||||
|
||||
double get scoreRequirement => (10000 + 10000 * ((log(level + 1) / log(2)) - 1));
|
||||
|
||||
TetrioZen.fromJson(Map<String, dynamic> json) {
|
||||
level = json['level'];
|
||||
score = json['score'];
|
||||
|
|
|
@ -904,10 +904,10 @@ class TetrioService extends DB {
|
|||
if (jsonDecode(response.body)['success']) {
|
||||
Map jsonRecords = jsonDecode(response.body);
|
||||
var sprint = jsonRecords['data']['records']['40l']['record'] != null
|
||||
? RecordSingle.fromJson(jsonRecords['data']['records']['40l']['record'], jsonRecords['data']['records']['40l']['rank'])
|
||||
? RecordSingle.fromJson(jsonRecords['data']['records']['40l']['record'], jsonRecords['data']['records']['40l']['rank'], jsonRecords['data']['records']['40l']['rank_local'])
|
||||
: null;
|
||||
var blitz = jsonRecords['data']['records']['blitz']['record'] != null
|
||||
? RecordSingle.fromJson(jsonRecords['data']['records']['blitz']['record'], jsonRecords['data']['records']['blitz']['rank'])
|
||||
? RecordSingle.fromJson(jsonRecords['data']['records']['blitz']['record'], jsonRecords['data']['records']['blitz']['rank'], jsonRecords['data']['records']['blitz']['rank_local'])
|
||||
: null;
|
||||
var zen = TetrioZen.fromJson(jsonRecords['data']['zen']);
|
||||
UserRecords result = UserRecords(userID, sprint, blitz, zen);
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'package:tetra_stats/gen/strings.g.dart';
|
|||
import 'package:tetra_stats/utils/numers_formats.dart';
|
||||
|
||||
final NumberFormat secs = NumberFormat("00.###", LocaleSettings.currentLocale.languageCode);
|
||||
final NumberFormat fixedSecs = NumberFormat("00.000", LocaleSettings.currentLocale.languageCode);
|
||||
final NumberFormat nonsecs = NumberFormat("00", LocaleSettings.currentLocale.languageCode);
|
||||
final NumberFormat nonsecs3 = NumberFormat("000", LocaleSettings.currentLocale.languageCode);
|
||||
final NumberFormat _timeInSec = NumberFormat("#,###.###s.", LocaleSettings.currentLocale.languageCode);
|
||||
|
@ -70,6 +71,10 @@ String get40lTime(int microseconds){
|
|||
return microseconds > 60000000 ? "${(microseconds/1000000/60).floor()}:${(secs.format(microseconds /1000000 % 60))}" : _timeInSec.format(microseconds / 1000000);
|
||||
}
|
||||
|
||||
String getMoreNormalTime(Duration time){
|
||||
return "${nonsecs.format(time.inMinutes)}:${(fixedSecs.format(time.inMilliseconds/1000%60))}";
|
||||
}
|
||||
|
||||
/// Readable [a] - [b], without sign
|
||||
String readableTimeDifference(Duration a, Duration b){
|
||||
Duration result = a - b;
|
||||
|
|
|
@ -11,6 +11,7 @@ import 'package:intl/intl.dart';
|
|||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||
import 'package:syncfusion_flutter_gauges/gauges.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';
|
||||
|
@ -23,6 +24,8 @@ import 'package:tetra_stats/utils/text_shadow.dart';
|
|||
import 'package:tetra_stats/views/singleplayer_record_view.dart';
|
||||
import 'package:tetra_stats/views/tl_match_view.dart' show TlMatchResultView;
|
||||
import 'package:tetra_stats/widgets/finesse_thingy.dart';
|
||||
import 'package:tetra_stats/widgets/gauget_num.dart';
|
||||
import 'package:tetra_stats/widgets/graphs.dart';
|
||||
import 'package:tetra_stats/widgets/lineclears_thingy.dart';
|
||||
import 'package:tetra_stats/widgets/list_tile_trailing_stats.dart';
|
||||
import 'package:tetra_stats/widgets/recent_sp_games.dart';
|
||||
|
@ -430,12 +433,14 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
tabs: bigScreen ? [
|
||||
Tab(text: t.tetraLeague,),
|
||||
Tab(text: t.history),
|
||||
Tab(text: "Quick Play"),
|
||||
Tab(text: "${t.sprint} & ${t.blitz}"),
|
||||
Tab(text: t.other),
|
||||
] : [
|
||||
Tab(text: t.tetraLeague),
|
||||
Tab(text: t.tlRecords),
|
||||
Tab(text: t.history),
|
||||
Tab(text: "Quick Play"),
|
||||
Tab(text: t.sprint),
|
||||
Tab(text: t.blitz),
|
||||
Tab(text: t.recentRuns),
|
||||
|
@ -478,6 +483,7 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
),
|
||||
],),
|
||||
_History(chartsData: chartsData, changePlayer: changePlayer, userID: _searchFor, update: _justUpdate, wasActiveInTL: snapshot.data![1].league.gamesPlayed > 0),
|
||||
_ZenithThingy(record: snapshot.data![1].zenith, recordEX: snapshot.data![1].zenithEx),
|
||||
_TwoRecordsThingy(sprint: snapshot.data![1].sprint, blitz: snapshot.data![1].blitz, rank: snapshot.data![1].league.percentileRank, recent: SingleplayerStream(userId: "userId", records: [], type: "recent"), sprintStream: SingleplayerStream(userId: "userId", records: [], type: "40l"), blitzStream: SingleplayerStream(userId: "userId", records: [], type: "blitz")),
|
||||
_OtherThingy(zen: snapshot.data![1].zen, bio: snapshot.data![0].bio, distinguishment: snapshot.data![0].distinguishment, newsletter: snapshot.data![2])
|
||||
] : [
|
||||
|
@ -500,6 +506,7 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
),
|
||||
_TLRecords(userID: snapshot.data![0].userId, changePlayer: changePlayer, data: snapshot.data![3].records, wasActiveInTL: true, oldMathcesHere: _TLHistoryWasFetched, separateScrollController: true),
|
||||
_History(chartsData: chartsData, changePlayer: changePlayer, userID: _searchFor, update: _justUpdate, wasActiveInTL: snapshot.data![1].league.gamesPlayed > 0),
|
||||
_ZenithThingy(record: snapshot.data![1].zenith, recordEX: snapshot.data![1].zenithEx),
|
||||
SingleplayerRecord(record: snapshot.data![1].sprint, rank: snapshot.data![1].league.percentileRank, stream: SingleplayerStream(userId: "userId", records: [], type: "40l")),
|
||||
SingleplayerRecord(record: snapshot.data![1].blitz, rank: snapshot.data![1].league.percentileRank, stream: SingleplayerStream(userId: "userId", records: [], type: "Blitz")),
|
||||
_RecentSingleplayersThingy(SingleplayerStream(userId: "userId", records: [], type: "recent")),
|
||||
|
@ -1218,7 +1225,230 @@ class _RecentSingleplayersThingy extends StatelessWidget {
|
|||
child: RecentSingleplayerGames(recent: recent, hideTitle: true)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ZenithThingy extends StatefulWidget{
|
||||
final RecordSingle? record;
|
||||
final RecordSingle? recordEX;
|
||||
|
||||
_ZenithThingy({this.record, this.recordEX});
|
||||
|
||||
@override
|
||||
State<_ZenithThingy> createState() => _ZenithThingyState();
|
||||
}
|
||||
|
||||
class _ZenithThingyState extends State<_ZenithThingy> {
|
||||
late RecordSingle? record;
|
||||
bool ex = false;
|
||||
|
||||
@override
|
||||
void initState(){
|
||||
super.initState();
|
||||
record = ex ? widget.recordEX : widget.record;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(builder: (context, constraints){
|
||||
bool bigScreen = constraints.maxWidth > 768;
|
||||
if (record == null) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text("Quick Play${ex ? " Expert" : ""}", style: const TextStyle(height: 0.1, fontFamily: "Eurostile Round Extended", fontSize: 18)),
|
||||
RichText(text: TextSpan(
|
||||
text: "--- m",
|
||||
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 36 : 32, fontWeight: FontWeight.w500, color: Colors.grey),
|
||||
),
|
||||
),
|
||||
TextButton(onPressed: (){
|
||||
if (ex){
|
||||
ex = false;
|
||||
}else{
|
||||
ex = true;
|
||||
}
|
||||
setState(() {
|
||||
record = ex ? widget.recordEX : widget.record;
|
||||
});
|
||||
}, child: Text(ex ? "Switch to normal" : "Switch to Expert")),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return SingleChildScrollView(
|
||||
child: Padding(padding: const EdgeInsets.only(top: 8.0),
|
||||
child: Column(
|
||||
children: [
|
||||
Text("Quick Play${ex ? " Expert" : ""}", style: const TextStyle(height: 0.1, fontFamily: "Eurostile Round Extended", fontSize: 18)),
|
||||
RichText(text: TextSpan(
|
||||
text: "${f2.format(record!.stats.zenith!.altitude)} m",
|
||||
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 36 : 32, fontWeight: FontWeight.w500, color: Colors.white),
|
||||
),
|
||||
),
|
||||
RichText(
|
||||
text: TextSpan(
|
||||
text: "",
|
||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey),
|
||||
children: [
|
||||
if (record!.rank != -1) TextSpan(text: "№${record!.rank}"),
|
||||
if (record!.rank != -1) const TextSpan(text: " • "),
|
||||
if (record!.countryRank != -1) TextSpan(text: "№${record!.countryRank} local"),
|
||||
if (record!.countryRank != -1) const TextSpan(text: " • "),
|
||||
TextSpan(text: timestamp(widget.record!.timestamp)),
|
||||
]
|
||||
),
|
||||
),
|
||||
TextButton(onPressed: (){
|
||||
if (ex){
|
||||
ex = false;
|
||||
}else{
|
||||
ex = true;
|
||||
}
|
||||
setState(() {
|
||||
record = ex ? widget.recordEX : widget.record;
|
||||
});
|
||||
}, child: Text(ex ? "Switch to normal" : "Switch to Expert")),
|
||||
Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
crossAxisAlignment: WrapCrossAlignment.start,
|
||||
spacing: 20,
|
||||
children: [
|
||||
StatCellNum(playerStat: record!.aggregateStats.apm, playerStatLabel: t.statCellNum.apm, fractionDigits: 2, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: true),
|
||||
StatCellNum(playerStat: record!.aggregateStats.pps, playerStatLabel: t.statCellNum.pps, fractionDigits: 2, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: false),
|
||||
StatCellNum(playerStat: record!.aggregateStats.vs, playerStatLabel: t.statCellNum.vs, fractionDigits: 2, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: true),
|
||||
StatCellNum(playerStat: record!.stats.kills, playerStatLabel: "Kills", isScreenBig: bigScreen, higherIsBetter: true)
|
||||
],
|
||||
),
|
||||
FinesseThingy(record?.stats.finesse, record?.stats.finessePercentage),
|
||||
LineclearsThingy(record!.stats.clears, record!.stats.lines, record!.stats.holds, record!.stats.tSpins),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 8.0),
|
||||
child: SizedBox(
|
||||
width: 300,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text("Total time: ${getMoreNormalTime(record!.stats.finalTime)}", style: const TextStyle(color: Colors.white, fontFamily: "Eurostile Round Extended"), textAlign: TextAlign.center),
|
||||
Table(
|
||||
children: [
|
||||
TableRow(
|
||||
children: [
|
||||
Text("Floor"),
|
||||
Text("Split"),
|
||||
Text("Total"),
|
||||
]
|
||||
),
|
||||
for (int i = 0; i < record!.stats.zenith!.splits.length; i++) TableRow(
|
||||
children: [
|
||||
Text((i+1).toString()),
|
||||
Text(record!.stats.zenith!.splits[i] != Duration.zero ? getMoreNormalTime(record!.stats.zenith!.splits[i]-(i-1 != -1 ? record!.stats.zenith!.splits[i-1] : Duration.zero)) : "--:--.---"),
|
||||
Text(record!.stats.zenith!.splits[i] != Duration.zero ? getMoreNormalTime(record!.stats.zenith!.splits[i]) : "--:--.---"),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
Column(
|
||||
children: [
|
||||
Text(t.nerdStats, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||
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: [
|
||||
GaugetNum(playerStat: record!.aggregateStats.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}: ${record!.aggregateStats.nerdStats.app}")
|
||||
]),
|
||||
GaugetNum(playerStat: record!.aggregateStats.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}: ${record!.aggregateStats.nerdStats.vsapm}")
|
||||
])
|
||||
]),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
|
||||
child: Wrap(
|
||||
direction: Axis.horizontal,
|
||||
alignment: WrapAlignment.center,
|
||||
spacing: 25,
|
||||
crossAxisAlignment: WrapCrossAlignment.start,
|
||||
clipBehavior: Clip.hardEdge,
|
||||
children: [
|
||||
StatCellNum(playerStat: record!.aggregateStats.nerdStats.dss, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.dss,
|
||||
alertWidgets: [Text(t.statCellNum.dssDescription),
|
||||
Text("${t.formula}: (VS / 100) - (APM / 60)"),
|
||||
Text("${t.exactValue}: ${record!.aggregateStats.nerdStats.dss}"),],
|
||||
okText: t.popupActions.ok,
|
||||
higherIsBetter: true,),
|
||||
StatCellNum(playerStat: record!.aggregateStats.nerdStats.dsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.dsp,
|
||||
alertWidgets: [Text(t.statCellNum.dspDescription),
|
||||
Text("${t.formula}: DS/S / PPS"),
|
||||
Text("${t.exactValue}: ${record!.aggregateStats.nerdStats.dsp}"),],
|
||||
okText: t.popupActions.ok,
|
||||
higherIsBetter: true),
|
||||
StatCellNum(playerStat: record!.aggregateStats.nerdStats.appdsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.appdsp,
|
||||
alertWidgets: [Text(t.statCellNum.appdspDescription),
|
||||
Text("${t.formula}: APP + DS/P"),
|
||||
Text("${t.exactValue}: ${record!.aggregateStats.nerdStats.appdsp}"),],
|
||||
okText: t.popupActions.ok,
|
||||
higherIsBetter: true),
|
||||
StatCellNum(playerStat: record!.aggregateStats.nerdStats.cheese, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.cheese,
|
||||
alertWidgets: [Text(t.statCellNum.cheeseDescription),
|
||||
Text("${t.formula}: (DS/P * 150) + ((VS/APM - 2) * 50) + (0.6 - APP) * 125"),
|
||||
Text("${t.exactValue}: ${record!.aggregateStats.nerdStats.cheese}"),],
|
||||
okText: t.popupActions.ok,
|
||||
higherIsBetter: false),
|
||||
StatCellNum(playerStat: record!.aggregateStats.nerdStats.gbe, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.gbe,
|
||||
alertWidgets: [Text(t.statCellNum.gbeDescription),
|
||||
Text("${t.formula}: APP * DS/P * 2"),
|
||||
Text("${t.exactValue}: ${record!.aggregateStats.nerdStats.gbe}"),],
|
||||
okText: t.popupActions.ok,
|
||||
higherIsBetter: true),
|
||||
StatCellNum(playerStat: record!.aggregateStats.nerdStats.nyaapp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.nyaapp,
|
||||
alertWidgets: [Text(t.statCellNum.nyaappDescription),
|
||||
Text("${t.formula}: APP - 5 * tan(radians((Cheese Index / -30) + 1))"),
|
||||
Text("${t.exactValue}: ${record!.aggregateStats.nerdStats.nyaapp}")],
|
||||
okText: t.popupActions.ok,
|
||||
higherIsBetter: true),
|
||||
StatCellNum(playerStat: record!.aggregateStats.nerdStats.area, isScreenBig: bigScreen, fractionDigits: 1, playerStatLabel: t.statCellNum.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}: ${record!.aggregateStats.nerdStats.area}"),],
|
||||
okText: t.popupActions.ok,
|
||||
higherIsBetter: true)
|
||||
]),
|
||||
)
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 16.0),
|
||||
child: Graphs(record!.aggregateStats.apm, record!.aggregateStats.pps, record!.aggregateStats.vs, record!.aggregateStats.nerdStats, record!.aggregateStats.playstyle),
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
class _OtherThingy extends StatelessWidget {
|
||||
|
@ -1314,6 +1544,7 @@ class _OtherThingy extends StatelessWidget {
|
|||
"40l" => get40lTime((news.data["result"]*1000).floor()),
|
||||
"5mblast" => get40lTime((news.data["result"]*1000).floor()),
|
||||
"zenith" => "${f2.format(news.data["result"])} m.",
|
||||
"zenithex" => "${f2.format(news.data["result"])} m.",
|
||||
_ => "unknown"
|
||||
},
|
||||
style: const TextStyle(fontWeight: FontWeight.bold)
|
||||
|
@ -1463,6 +1694,14 @@ class _OtherThingy extends StatelessWidget {
|
|||
Text(t.zen, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||
Text("${t.statCellNum.level} ${NumberFormat.decimalPattern().format(zen!.level)}", style: const TextStyle(fontSize: 28, fontWeight: FontWeight.bold)),
|
||||
Text("${t.statCellNum.score} ${NumberFormat.decimalPattern().format(zen!.score)}", style: const TextStyle(fontSize: 18)),
|
||||
Container(
|
||||
constraints: BoxConstraints(maxWidth: 300.0),
|
||||
child: Row(children: [
|
||||
Text("Score requirement to level up:"),
|
||||
Spacer(),
|
||||
Text(intf.format(zen!.scoreRequirement))
|
||||
],),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -68,8 +68,21 @@ News testNews = News("6098518e3d5155e6ec429cdc", [
|
|||
NewsEntry(type: "personalbest", data: {"gametype": "blitz", "result": 23.232}, timestamp: DateTime(2002, 2, 25, 10, 30, 02)),
|
||||
NewsEntry(type: "personalbest", data: {"gametype": "5mblast", "result": 23.232}, timestamp: DateTime(2002, 2, 25, 10, 30, 03)),
|
||||
]);
|
||||
late ScrollController controller;
|
||||
|
||||
class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||
@override
|
||||
void initState() {
|
||||
controller = ScrollController();
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
controller.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(body: Row(
|
||||
|
@ -94,138 +107,185 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
],
|
||||
selectedIndex: 0
|
||||
),
|
||||
SizedBox(
|
||||
width: 450.0,
|
||||
child: Column(
|
||||
children: [
|
||||
NewUserThingy(player: testPlayer, showStateTimestamp: false, setState: setState),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(4.0, 0.0, 4.0, 0.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(child: ElevatedButton.icon(onPressed: (){print("ok, and?");}, icon: Icon(Icons.person_add), label: Text(t.track), style: ButtonStyle(shape: MaterialStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.horizontal(left: Radius.circular(12.0), right: Radius.zero)))))),
|
||||
Expanded(child: ElevatedButton.icon(onPressed: (){print("ok, and?");}, icon: Icon(Icons.balance), label: Text(t.compare), style: ButtonStyle(shape: MaterialStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.horizontal(left: Radius.zero, right: Radius.circular(12.0)))))))
|
||||
],
|
||||
),
|
||||
),
|
||||
Card(
|
||||
surfaceTintColor: theme.colorScheme.surface,
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 0.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Badges", style: TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||
Spacer(),
|
||||
Text(intf.format(testPlayer.badges.length))
|
||||
],
|
||||
),
|
||||
),
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: [
|
||||
for (var badge in testPlayer.badges)
|
||||
IconButton(
|
||||
onPressed: () => showDialog<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(badge.label, style: const TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: [
|
||||
Wrap(
|
||||
direction: Axis.horizontal,
|
||||
alignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
spacing: 25,
|
||||
children: [
|
||||
Image.asset("res/tetrio_badges/${badge.badgeId}.png"),
|
||||
Text(badge.ts != null
|
||||
? t.obtainDate(date: timestamp(badge.ts!))
|
||||
: t.assignedManualy),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(t.popupActions.ok),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
tooltip: badge.label,
|
||||
icon: Image.asset(
|
||||
"res/tetrio_badges/${badge.badgeId}.png",
|
||||
height: 32,
|
||||
width: 32,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Image.network(
|
||||
kIsWeb ? "https://ts.dan63.by/oskware_bridge.php?endpoint=TetrioBadge&badge=${badge.badgeId}" : "https://tetr.io/res/badges/${badge.badgeId}.png",
|
||||
height: 32,
|
||||
width: 32,
|
||||
errorBuilder:(context, error, stackTrace) {
|
||||
return Image.asset("res/icons/kagari.png", height: 32, width: 32);
|
||||
}
|
||||
);
|
||||
},
|
||||
)
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
if (testPlayer.distinguishment != null) DistinguishmentThingy(testPlayer.distinguishment!),
|
||||
if (testPlayer.bio != null) Card(
|
||||
surfaceTintColor: theme.colorScheme.surface,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
Expanded(
|
||||
child: Scrollbar(
|
||||
controller: controller,
|
||||
thumbVisibility: true,
|
||||
child: SingleChildScrollView(
|
||||
controller: controller,
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 450.0,
|
||||
child: Column(
|
||||
children: [
|
||||
Spacer(),
|
||||
Text(t.bio, style: TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||
Spacer()
|
||||
NewUserThingy(player: testPlayer, showStateTimestamp: false, setState: setState),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(4.0, 0.0, 4.0, 0.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(child: ElevatedButton.icon(onPressed: (){print("ok, and?");}, icon: Icon(Icons.person_add), label: Text(t.track), style: ButtonStyle(shape: MaterialStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.horizontal(left: Radius.circular(12.0), right: Radius.zero)))))),
|
||||
Expanded(child: ElevatedButton.icon(onPressed: (){print("ok, and?");}, icon: Icon(Icons.balance), label: Text(t.compare), style: ButtonStyle(shape: MaterialStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.horizontal(left: Radius.zero, right: Radius.circular(12.0)))))))
|
||||
],
|
||||
),
|
||||
),
|
||||
Card(
|
||||
surfaceTintColor: theme.colorScheme.surface,
|
||||
child: Column(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 0.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Badges", style: TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||
Spacer(),
|
||||
Text(intf.format(testPlayer.badges.length))
|
||||
],
|
||||
),
|
||||
),
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: [
|
||||
for (var badge in testPlayer.badges)
|
||||
IconButton(
|
||||
onPressed: () => showDialog<void>(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return AlertDialog(
|
||||
title: Text(badge.label, style: const TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||
content: SingleChildScrollView(
|
||||
child: ListBody(
|
||||
children: [
|
||||
Wrap(
|
||||
direction: Axis.horizontal,
|
||||
alignment: WrapAlignment.center,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
spacing: 25,
|
||||
children: [
|
||||
Image.asset("res/tetrio_badges/${badge.badgeId}.png"),
|
||||
Text(badge.ts != null
|
||||
? t.obtainDate(date: timestamp(badge.ts!))
|
||||
: t.assignedManualy),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: Text(t.popupActions.ok),
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop();
|
||||
},
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
tooltip: badge.label,
|
||||
icon: Image.asset(
|
||||
"res/tetrio_badges/${badge.badgeId}.png",
|
||||
height: 32,
|
||||
width: 32,
|
||||
errorBuilder: (context, error, stackTrace) {
|
||||
return Image.network(
|
||||
kIsWeb ? "https://ts.dan63.by/oskware_bridge.php?endpoint=TetrioBadge&badge=${badge.badgeId}" : "https://tetr.io/res/badges/${badge.badgeId}.png",
|
||||
height: 32,
|
||||
width: 32,
|
||||
errorBuilder:(context, error, stackTrace) {
|
||||
return Image.asset("res/icons/kagari.png", height: 32, width: 32);
|
||||
}
|
||||
);
|
||||
},
|
||||
)
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
if (testPlayer.distinguishment != null) DistinguishmentThingy(testPlayer.distinguishment!),
|
||||
if (testPlayer.bio != null) Card(
|
||||
surfaceTintColor: theme.colorScheme.surface,
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Spacer(),
|
||||
Text(t.bio, style: TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||
Spacer()
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: MarkdownBody(data: testPlayer.bio!, styleSheet: MarkdownStyleSheet(textAlign: WrapAlignment.center)),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
//if (testNews != null && testNews!.news.isNotEmpty)
|
||||
Expanded(child: NewsThingy(testNews))
|
||||
],
|
||||
)
|
||||
),
|
||||
SizedBox(
|
||||
width: 450.0,
|
||||
child: Column(
|
||||
children: [
|
||||
Card(
|
||||
child: Row(
|
||||
children: [
|
||||
Spacer(),
|
||||
Text("test card"),
|
||||
Spacer()
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: MarkdownBody(data: testPlayer.bio!, styleSheet: MarkdownStyleSheet(textAlign: WrapAlignment.center)),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 450.0,
|
||||
child: Column(
|
||||
children: [
|
||||
Card(
|
||||
child: Row(
|
||||
children: [
|
||||
Spacer(),
|
||||
Text("test card"),
|
||||
Spacer()
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 450.0,
|
||||
child: Column(
|
||||
children: [
|
||||
Card(
|
||||
child: Row(
|
||||
children: [
|
||||
Spacer(),
|
||||
Text("test card"),
|
||||
Spacer()
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
//if (testNews != null && testNews!.news.isNotEmpty)
|
||||
Expanded(child: NewsThingy(testNews))
|
||||
],
|
||||
)
|
||||
),
|
||||
SizedBox(
|
||||
width: 450.0,
|
||||
child: Column(
|
||||
children: [
|
||||
Card(
|
||||
child: Row(
|
||||
children: [
|
||||
Spacer(),
|
||||
Text("test card"),
|
||||
Spacer()
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
],
|
||||
));
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ class StatCellNum extends StatelessWidget {
|
|||
required this.playerStat,
|
||||
required this.playerStatLabel,
|
||||
required this.isScreenBig,
|
||||
this.smallDecimal = true,
|
||||
this.smallDecimal = false,
|
||||
this.alertWidgets,
|
||||
this.fractionDigits,
|
||||
this.oldPlayerStat,
|
||||
|
|
Loading…
Reference in New Issue