Recent singleplayer games (wide viewports for now)
This commit is contained in:
parent
9394b818cc
commit
02f0cf660f
|
@ -872,6 +872,21 @@ class TetraLeagueAlphaStream{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SingleplayerStream{
|
||||||
|
late String userId;
|
||||||
|
late String type;
|
||||||
|
late List<RecordSingle> records;
|
||||||
|
|
||||||
|
SingleplayerStream({required this.userId, required this.records, required this.type});
|
||||||
|
|
||||||
|
SingleplayerStream.fromJson(List<dynamic> json, String userID, String tp) {
|
||||||
|
userId = userID;
|
||||||
|
type = tp;
|
||||||
|
records = [];
|
||||||
|
for (var value in json) {records.add(RecordSingle.fromJson(value, null));}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class TetraLeagueAlphaRecord{
|
class TetraLeagueAlphaRecord{
|
||||||
late String replayId;
|
late String replayId;
|
||||||
late String ownId;
|
late String ownId;
|
||||||
|
@ -1116,19 +1131,17 @@ class RecordSingle {
|
||||||
late String userId;
|
late String userId;
|
||||||
late String replayId;
|
late String replayId;
|
||||||
late String ownId;
|
late String ownId;
|
||||||
late String stream;
|
late DateTime timestamp;
|
||||||
DateTime? timestamp;
|
late EndContextSingle endContext;
|
||||||
EndContextSingle? endContext;
|
|
||||||
int? rank;
|
int? rank;
|
||||||
|
|
||||||
RecordSingle({required this.userId, required this.replayId, required this.ownId, this.timestamp, this.endContext, this.rank});
|
RecordSingle({required this.userId, required this.replayId, required this.ownId, required this.timestamp, required this.endContext, this.rank});
|
||||||
|
|
||||||
RecordSingle.fromJson(Map<String, dynamic> json, int? ran) {
|
RecordSingle.fromJson(Map<String, dynamic> json, int? ran) {
|
||||||
//developer.log("RecordSingle.fromJson: $json", name: "data_objects/tetrio");
|
//developer.log("RecordSingle.fromJson: $json", name: "data_objects/tetrio");
|
||||||
ownId = json['_id'];
|
ownId = json['_id'];
|
||||||
endContext = json['endcontext'] != null ? EndContextSingle.fromJson(json['endcontext']) : null;
|
endContext = EndContextSingle.fromJson(json['endcontext']);
|
||||||
replayId = json['replayid'];
|
replayId = json['replayid'];
|
||||||
stream = json['stream'];
|
|
||||||
timestamp = DateTime.parse(json['ts']);
|
timestamp = DateTime.parse(json['ts']);
|
||||||
userId = json['user']['_id'];
|
userId = json['user']['_id'];
|
||||||
rank = ran;
|
rank = ran;
|
||||||
|
@ -1137,9 +1150,7 @@ class RecordSingle {
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final Map<String, dynamic> data = <String, dynamic>{};
|
final Map<String, dynamic> data = <String, dynamic>{};
|
||||||
data['_id'] = ownId;
|
data['_id'] = ownId;
|
||||||
if (endContext != null) {
|
data['endcontext'] = endContext.toJson();
|
||||||
data['endcontext'] = endContext!.toJson();
|
|
||||||
}
|
|
||||||
data['ismulti'] = false;
|
data['ismulti'] = false;
|
||||||
data['replayid'] = replayId;
|
data['replayid'] = replayId;
|
||||||
data['ts'] = timestamp;
|
data['ts'] = timestamp;
|
||||||
|
|
|
@ -90,6 +90,8 @@ class CacheController {
|
||||||
return object.runtimeType.toString()+"topone";
|
return object.runtimeType.toString()+"topone";
|
||||||
case TetraLeagueAlphaStream:
|
case TetraLeagueAlphaStream:
|
||||||
return object.runtimeType.toString()+object.userId;
|
return object.runtimeType.toString()+object.userId;
|
||||||
|
case SingleplayerStream:
|
||||||
|
return object.type+object.userId;
|
||||||
default:
|
default:
|
||||||
return object.runtimeType.toString()+object.id;
|
return object.runtimeType.toString()+object.id;
|
||||||
}
|
}
|
||||||
|
@ -303,6 +305,53 @@ class TetrioService extends DB {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves avaliable Tetra League matches from Tetra Channel api. Returns stream object (fake stream).
|
||||||
|
/// Throws an exception if fails to retrieve.
|
||||||
|
Future<SingleplayerStream> fetchSingleplayerStream(String userID, String stream) async {
|
||||||
|
SingleplayerStream? cached = _cache.get(userID, SingleplayerStream);
|
||||||
|
if (cached != null) return cached;
|
||||||
|
|
||||||
|
Uri url;
|
||||||
|
if (kIsWeb) {
|
||||||
|
url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "singleplayerStream", "user": userID.toLowerCase().trim(), "stream": stream});
|
||||||
|
} else {
|
||||||
|
url = Uri.https('ch.tetr.io', 'api/streams/${stream}_${userID.toLowerCase().trim()}');
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final response = await client.get(url);
|
||||||
|
|
||||||
|
switch (response.statusCode) {
|
||||||
|
case 200:
|
||||||
|
if (jsonDecode(response.body)['success']) {
|
||||||
|
SingleplayerStream records = SingleplayerStream.fromJson(jsonDecode(response.body)['data']['records'], userID, stream);
|
||||||
|
_cache.store(records, jsonDecode(response.body)['cache']['cached_until']);
|
||||||
|
developer.log("fetchSingleplayerStream: $stream $userID stream retrieved and cached", name: "services/tetrio_crud");
|
||||||
|
return records;
|
||||||
|
} else {
|
||||||
|
developer.log("fetchSingleplayerStream: User dosen't exist", name: "services/tetrio_crud", error: response.body);
|
||||||
|
throw TetrioPlayerNotExist();
|
||||||
|
}
|
||||||
|
case 403:
|
||||||
|
throw TetrioForbidden();
|
||||||
|
case 429:
|
||||||
|
throw TetrioTooManyRequests();
|
||||||
|
case 418:
|
||||||
|
throw TetrioOskwareBridgeProblem();
|
||||||
|
case 500:
|
||||||
|
case 502:
|
||||||
|
case 503:
|
||||||
|
case 504:
|
||||||
|
throw TetrioInternalProblem();
|
||||||
|
default:
|
||||||
|
developer.log("fetchSingleplayerStream: Failed to fetch stream $stream $userID", name: "services/tetrio_crud", error: response.statusCode);
|
||||||
|
throw ConnectionIssue(response.statusCode, response.reasonPhrase??"No reason");
|
||||||
|
}
|
||||||
|
} on http.ClientException catch (e, s) {
|
||||||
|
developer.log("$e, $s");
|
||||||
|
throw http.ClientException(e.message, e.uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Gets and returns Top TR for a player with given [id]. May return null if player top tr is unknown
|
/// Gets and returns Top TR for a player with given [id]. May return null if player top tr is unknown
|
||||||
/// or api is unavaliable (404). May throw an exception, if something else happens.
|
/// or api is unavaliable (404). May throw an exception, if something else happens.
|
||||||
Future<TopTr?> fetchTopTR(String id) async {
|
Future<TopTr?> fetchTopTR(String id) async {
|
||||||
|
|
|
@ -174,12 +174,14 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
late TetraLeagueAlphaStream tlStream;
|
late TetraLeagueAlphaStream tlStream;
|
||||||
late UserRecords records;
|
late UserRecords records;
|
||||||
late News news;
|
late News news;
|
||||||
|
late SingleplayerStream recent;
|
||||||
late TetrioPlayerFromLeaderboard? topOne;
|
late TetrioPlayerFromLeaderboard? topOne;
|
||||||
late TopTr? topTR;
|
late TopTr? topTR;
|
||||||
requests = await Future.wait([ // all at once
|
requests = await Future.wait([ // all at once
|
||||||
teto.fetchTLStream(_searchFor),
|
teto.fetchTLStream(_searchFor),
|
||||||
teto.fetchRecords(_searchFor),
|
teto.fetchRecords(_searchFor),
|
||||||
teto.fetchNews(_searchFor),
|
teto.fetchNews(_searchFor),
|
||||||
|
teto.fetchSingleplayerStream(_searchFor, "any_userrecent"),
|
||||||
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.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
|
(me.tlSeason1.gamesPlayed > 9) ? teto.fetchTopTR(_searchFor) : Future.delayed(Duration.zero, () => null) // can retrieve this only if player has TR
|
||||||
|
@ -187,8 +189,9 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
tlStream = requests[0] as TetraLeagueAlphaStream;
|
tlStream = requests[0] as TetraLeagueAlphaStream;
|
||||||
records = requests[1] as UserRecords;
|
records = requests[1] as UserRecords;
|
||||||
news = requests[2] as News;
|
news = requests[2] as News;
|
||||||
topOne = requests[4] as TetrioPlayerFromLeaderboard?;
|
recent = requests[3] as SingleplayerStream;
|
||||||
topTR = requests[5] as TopTr?; // No TR - no Top TR
|
topOne = requests[5] as TetrioPlayerFromLeaderboard?;
|
||||||
|
topTR = requests[6] as TopTr?; // No TR - no Top TR
|
||||||
|
|
||||||
meAmongEveryone = teto.getCachedLeaderboardPositions(me.userId);
|
meAmongEveryone = teto.getCachedLeaderboardPositions(me.userId);
|
||||||
if (prefs.getBool("showPositions") == true){
|
if (prefs.getBool("showPositions") == true){
|
||||||
|
@ -200,8 +203,8 @@ 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[3] as Cutoffs?)?.tr;
|
Map<String, double>? cutoffs = prefs.getBool("showPositions") == true ? everyone!.cutoffs : (requests[4] as Cutoffs?)?.tr;
|
||||||
Map<String, double>? cutoffsGlicko = prefs.getBool("showPositions") == true ? everyone!.cutoffsGlicko : (requests[3] as Cutoffs?)?.glicko;
|
Map<String, double>? cutoffsGlicko = prefs.getBool("showPositions") == true ? everyone!.cutoffsGlicko : (requests[4] as Cutoffs?)?.glicko;
|
||||||
|
|
||||||
if (me.tlSeason1.gamesPlayed > 9) {
|
if (me.tlSeason1.gamesPlayed > 9) {
|
||||||
thatRankCutoff = cutoffs?[me.tlSeason1.rank != "z" ? me.tlSeason1.rank : me.tlSeason1.percentileRank];
|
thatRankCutoff = cutoffs?[me.tlSeason1.rank != "z" ? me.tlSeason1.rank : me.tlSeason1.percentileRank];
|
||||||
|
@ -313,7 +316,7 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return [me, records, states, tlMatches, compareWith, isTracking, news, topTR];
|
return [me, records, states, tlMatches, compareWith, isTracking, news, topTR, recent];
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Triggers widgets rebuild
|
/// Triggers widgets rebuild
|
||||||
|
@ -483,7 +486,7 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
||||||
),
|
),
|
||||||
],),
|
],),
|
||||||
_History(chartsData: chartsData, changePlayer: changePlayer, userID: _searchFor, update: _justUpdate, wasActiveInTL: snapshot.data![0].tlSeason1.gamesPlayed > 0),
|
_History(chartsData: chartsData, changePlayer: changePlayer, userID: _searchFor, update: _justUpdate, wasActiveInTL: snapshot.data![0].tlSeason1.gamesPlayed > 0),
|
||||||
_TwoRecordsThingy(sprint: snapshot.data![1].sprint, blitz: snapshot.data![1].blitz, rank: snapshot.data![0].tlSeason1.percentileRank,),
|
_TwoRecordsThingy(sprint: snapshot.data![1].sprint, blitz: snapshot.data![1].blitz, rank: snapshot.data![0].tlSeason1.percentileRank, recent: snapshot.data![8]),
|
||||||
_OtherThingy(zen: snapshot.data![1].zen, bio: snapshot.data![0].bio, distinguishment: snapshot.data![0].distinguishment, newsletter: snapshot.data![6],)
|
_OtherThingy(zen: snapshot.data![1].zen, bio: snapshot.data![0].bio, distinguishment: snapshot.data![0].distinguishment, newsletter: snapshot.data![6],)
|
||||||
] : [
|
] : [
|
||||||
TLThingy(
|
TLThingy(
|
||||||
|
@ -1000,9 +1003,10 @@ class _HistoryChartThigyState extends State<_HistoryChartThigy> {
|
||||||
class _TwoRecordsThingy extends StatelessWidget {
|
class _TwoRecordsThingy extends StatelessWidget {
|
||||||
final RecordSingle? sprint;
|
final RecordSingle? sprint;
|
||||||
final RecordSingle? blitz;
|
final RecordSingle? blitz;
|
||||||
|
final SingleplayerStream recent;
|
||||||
final String? rank;
|
final String? rank;
|
||||||
|
|
||||||
const _TwoRecordsThingy({required this.sprint, required this.blitz, this.rank});
|
const _TwoRecordsThingy({required this.sprint, required this.blitz, this.rank, required this.recent});
|
||||||
|
|
||||||
Color getColorOfRank(int rank){
|
Color getColorOfRank(int rank){
|
||||||
if (rank == 1) return Colors.yellowAccent;
|
if (rank == 1) return Colors.yellowAccent;
|
||||||
|
@ -1018,17 +1022,17 @@ class _TwoRecordsThingy extends StatelessWidget {
|
||||||
//if (record == null) return Center(child: Text(t.noRecord, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28)));
|
//if (record == null) return Center(child: Text(t.noRecord, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28)));
|
||||||
late MapEntry closestAverageBlitz;
|
late MapEntry closestAverageBlitz;
|
||||||
late bool blitzBetterThanClosestAverage;
|
late bool blitzBetterThanClosestAverage;
|
||||||
bool? blitzBetterThanRankAverage = (rank != null && rank != "z" && blitz != null) ? blitz!.endContext!.score > blitzAverages[rank]! : null;
|
bool? blitzBetterThanRankAverage = (rank != null && rank != "z" && blitz != null) ? blitz!.endContext.score > blitzAverages[rank]! : null;
|
||||||
late MapEntry closestAverageSprint;
|
late MapEntry closestAverageSprint;
|
||||||
late bool sprintBetterThanClosestAverage;
|
late bool sprintBetterThanClosestAverage;
|
||||||
bool? sprintBetterThanRankAverage = (rank != null && rank != "z" && sprint != null) ? sprint!.endContext!.finalTime < sprintAverages[rank]! : null;
|
bool? sprintBetterThanRankAverage = (rank != null && rank != "z" && sprint != null) ? sprint!.endContext.finalTime < sprintAverages[rank]! : null;
|
||||||
if (sprint != null) {
|
if (sprint != null) {
|
||||||
closestAverageSprint = sprintAverages.entries.singleWhere((element) => element.value == sprintAverages.values.reduce((a, b) => (a-sprint!.endContext!.finalTime).abs() < (b -sprint!.endContext!.finalTime).abs() ? a : b));
|
closestAverageSprint = sprintAverages.entries.singleWhere((element) => element.value == sprintAverages.values.reduce((a, b) => (a-sprint!.endContext.finalTime).abs() < (b -sprint!.endContext.finalTime).abs() ? a : b));
|
||||||
sprintBetterThanClosestAverage = sprint!.endContext!.finalTime < closestAverageSprint.value;
|
sprintBetterThanClosestAverage = sprint!.endContext.finalTime < closestAverageSprint.value;
|
||||||
}
|
}
|
||||||
if (blitz != null){
|
if (blitz != null){
|
||||||
closestAverageBlitz = blitzAverages.entries.singleWhere((element) => element.value == blitzAverages.values.reduce((a, b) => (a-blitz!.endContext!.score).abs() < (b -blitz!.endContext!.score).abs() ? a : b));
|
closestAverageBlitz = blitzAverages.entries.singleWhere((element) => element.value == blitzAverages.values.reduce((a, b) => (a-blitz!.endContext.score).abs() < (b -blitz!.endContext.score).abs() ? a : b));
|
||||||
blitzBetterThanClosestAverage = blitz!.endContext!.score > closestAverageBlitz.value;
|
blitzBetterThanClosestAverage = blitz!.endContext.score > closestAverageBlitz.value;
|
||||||
}
|
}
|
||||||
return SingleChildScrollView(child: Padding(
|
return SingleChildScrollView(child: Padding(
|
||||||
padding: const EdgeInsets.only(top: 20.0),
|
padding: const EdgeInsets.only(top: 20.0),
|
||||||
|
@ -1050,24 +1054,24 @@ class _TwoRecordsThingy extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
Text(t.sprint, style: const TextStyle(height: 0.1, fontFamily: "Eurostile Round Extended", fontSize: 18)),
|
Text(t.sprint, style: const TextStyle(height: 0.1, fontFamily: "Eurostile Round Extended", fontSize: 18)),
|
||||||
RichText(text: TextSpan(
|
RichText(text: TextSpan(
|
||||||
text: sprint != null ? get40lTime(sprint!.endContext!.finalTime.inMicroseconds) : "---",
|
text: sprint != null ? get40lTime(sprint!.endContext.finalTime.inMicroseconds) : "---",
|
||||||
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, fontWeight: FontWeight.w500, color: sprint != null ? Colors.white : Colors.grey),
|
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, fontWeight: FontWeight.w500, color: sprint != null ? Colors.white : Colors.grey),
|
||||||
//children: [TextSpan(text: get40lTime(record!.endContext!.finalTime.inMicroseconds), style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))]
|
//children: [TextSpan(text: get40lTime(record!.endContext.finalTime.inMicroseconds), style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100))]
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (sprint != null) RichText(text: TextSpan(
|
if (sprint != null) RichText(text: TextSpan(
|
||||||
text: "",
|
text: "",
|
||||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey),
|
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey),
|
||||||
children: [
|
children: [
|
||||||
if (rank != null && rank != "z") TextSpan(text: "${t.verdictGeneral(n: readableTimeDifference(sprint!.endContext!.finalTime, sprintAverages[rank]!), verdict: sprintBetterThanRankAverage??false ? t.verdictBetter : t.verdictWorse, rank: rank!.toUpperCase())}\n", style: TextStyle(
|
if (rank != null && rank != "z") TextSpan(text: "${t.verdictGeneral(n: readableTimeDifference(sprint!.endContext.finalTime, sprintAverages[rank]!), verdict: sprintBetterThanRankAverage??false ? t.verdictBetter : t.verdictWorse, rank: rank!.toUpperCase())}\n", style: TextStyle(
|
||||||
color: sprintBetterThanRankAverage??false ? Colors.greenAccent : Colors.redAccent
|
color: sprintBetterThanRankAverage??false ? Colors.greenAccent : Colors.redAccent
|
||||||
))
|
))
|
||||||
else TextSpan(text: "${t.verdictGeneral(n: readableTimeDifference(sprint!.endContext!.finalTime, closestAverageSprint.value), verdict: sprintBetterThanClosestAverage ? t.verdictBetter : t.verdictWorse, rank: closestAverageSprint.key.toUpperCase())}\n", style: TextStyle(
|
else TextSpan(text: "${t.verdictGeneral(n: readableTimeDifference(sprint!.endContext.finalTime, closestAverageSprint.value), verdict: sprintBetterThanClosestAverage ? t.verdictBetter : t.verdictWorse, rank: closestAverageSprint.key.toUpperCase())}\n", style: TextStyle(
|
||||||
color: sprintBetterThanClosestAverage ? Colors.greenAccent : Colors.redAccent
|
color: sprintBetterThanClosestAverage ? Colors.greenAccent : Colors.redAccent
|
||||||
)),
|
)),
|
||||||
if (sprint!.rank != null) TextSpan(text: "№${sprint!.rank}", style: TextStyle(color: getColorOfRank(sprint!.rank!))),
|
if (sprint!.rank != null) TextSpan(text: "№${sprint!.rank}", style: TextStyle(color: getColorOfRank(sprint!.rank!))),
|
||||||
if (sprint!.rank != null) const TextSpan(text: " • "),
|
if (sprint!.rank != null) const TextSpan(text: " • "),
|
||||||
TextSpan(text: timestamp(sprint!.timestamp!)),
|
TextSpan(text: timestamp(sprint!.timestamp)),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1079,14 +1083,14 @@ class _TwoRecordsThingy extends StatelessWidget {
|
||||||
alignment: WrapAlignment.spaceBetween,
|
alignment: WrapAlignment.spaceBetween,
|
||||||
spacing: 20,
|
spacing: 20,
|
||||||
children: [
|
children: [
|
||||||
StatCellNum(playerStat: sprint!.endContext!.piecesPlaced, playerStatLabel: t.statCellNum.pieces, isScreenBig: true, higherIsBetter: true, smallDecimal: false),
|
StatCellNum(playerStat: sprint!.endContext.piecesPlaced, playerStatLabel: t.statCellNum.pieces, isScreenBig: true, higherIsBetter: true, smallDecimal: false),
|
||||||
StatCellNum(playerStat: sprint!.endContext!.pps, playerStatLabel: t.statCellNum.pps, fractionDigits: 2, isScreenBig: true, higherIsBetter: true, smallDecimal: false),
|
StatCellNum(playerStat: sprint!.endContext.pps, playerStatLabel: t.statCellNum.pps, fractionDigits: 2, isScreenBig: true, higherIsBetter: true, smallDecimal: false),
|
||||||
StatCellNum(playerStat: sprint!.endContext!.kpp, playerStatLabel: t.statCellNum.kpp, fractionDigits: 2, isScreenBig: true, higherIsBetter: true, smallDecimal: false),
|
StatCellNum(playerStat: sprint!.endContext.kpp, playerStatLabel: t.statCellNum.kpp, fractionDigits: 2, isScreenBig: true, higherIsBetter: true, smallDecimal: false),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (sprint != null) FinesseThingy(sprint?.endContext?.finesse, sprint?.endContext?.finessePercentage),
|
if (sprint != null) FinesseThingy(sprint?.endContext.finesse, sprint?.endContext.finessePercentage),
|
||||||
if (sprint != null) LineclearsThingy(sprint!.endContext!.clears, sprint!.endContext!.lines, sprint!.endContext!.holds, sprint!.endContext!.tSpins),
|
if (sprint != null) LineclearsThingy(sprint!.endContext.clears, sprint!.endContext.lines, sprint!.endContext.holds, sprint!.endContext.tSpins),
|
||||||
if (sprint != null) Text("${sprint!.endContext!.inputs} KP • ${f2.format(sprint!.endContext!.kps)} KPS")
|
if (sprint != null) Text("${sprint!.endContext.inputs} KP • ${f2.format(sprint!.endContext.kps)} KPS")
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
|
@ -1106,7 +1110,7 @@ class _TwoRecordsThingy extends StatelessWidget {
|
||||||
text: "",
|
text: "",
|
||||||
style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, fontWeight: FontWeight.w500, color: Colors.white),
|
style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, fontWeight: FontWeight.w500, color: Colors.white),
|
||||||
children: [
|
children: [
|
||||||
TextSpan(text: blitz != null ? NumberFormat.decimalPattern().format(blitz!.endContext!.score) : "---"),
|
TextSpan(text: blitz != null ? NumberFormat.decimalPattern().format(blitz!.endContext.score) : "---"),
|
||||||
//WidgetSpan(child: Image.asset("res/icons/kagari.png", height: 48))
|
//WidgetSpan(child: Image.asset("res/icons/kagari.png", height: 48))
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
|
@ -1117,13 +1121,13 @@ class _TwoRecordsThingy extends StatelessWidget {
|
||||||
text: "",
|
text: "",
|
||||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey),
|
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey),
|
||||||
children: [
|
children: [
|
||||||
if (rank != null && rank != "z") TextSpan(text: "${t.verdictGeneral(n: readableIntDifference(blitz!.endContext!.score, blitzAverages[rank]!), verdict: blitzBetterThanRankAverage??false ? t.verdictBetter : t.verdictWorse, rank: rank!.toUpperCase())}\n", style: TextStyle(
|
if (rank != null && rank != "z") TextSpan(text: "${t.verdictGeneral(n: readableIntDifference(blitz!.endContext.score, blitzAverages[rank]!), verdict: blitzBetterThanRankAverage??false ? t.verdictBetter : t.verdictWorse, rank: rank!.toUpperCase())}\n", style: TextStyle(
|
||||||
color: blitzBetterThanRankAverage??false ? Colors.greenAccent : Colors.redAccent
|
color: blitzBetterThanRankAverage??false ? Colors.greenAccent : Colors.redAccent
|
||||||
))
|
))
|
||||||
else TextSpan(text: "${t.verdictGeneral(n: readableIntDifference(blitz!.endContext!.score, closestAverageBlitz.value), verdict: blitzBetterThanClosestAverage ? t.verdictBetter : t.verdictWorse, rank: closestAverageBlitz.key.toUpperCase())}\n", style: TextStyle(
|
else TextSpan(text: "${t.verdictGeneral(n: readableIntDifference(blitz!.endContext.score, closestAverageBlitz.value), verdict: blitzBetterThanClosestAverage ? t.verdictBetter : t.verdictWorse, rank: closestAverageBlitz.key.toUpperCase())}\n", style: TextStyle(
|
||||||
color: blitzBetterThanClosestAverage ? Colors.greenAccent : Colors.redAccent
|
color: blitzBetterThanClosestAverage ? Colors.greenAccent : Colors.redAccent
|
||||||
)),
|
)),
|
||||||
TextSpan(text: timestamp(blitz!.timestamp!)),
|
TextSpan(text: timestamp(blitz!.timestamp)),
|
||||||
if (blitz!.rank != null) const TextSpan(text: " • "),
|
if (blitz!.rank != null) const TextSpan(text: " • "),
|
||||||
if (blitz!.rank != null) TextSpan(text: "№${blitz!.rank}", style: TextStyle(color: getColorOfRank(blitz!.rank!))),
|
if (blitz!.rank != null) TextSpan(text: "№${blitz!.rank}", style: TextStyle(color: getColorOfRank(blitz!.rank!))),
|
||||||
]
|
]
|
||||||
|
@ -1140,16 +1144,50 @@ class _TwoRecordsThingy extends StatelessWidget {
|
||||||
crossAxisAlignment: WrapCrossAlignment.start,
|
crossAxisAlignment: WrapCrossAlignment.start,
|
||||||
spacing: 20,
|
spacing: 20,
|
||||||
children: [
|
children: [
|
||||||
StatCellNum(playerStat: blitz!.endContext!.level, playerStatLabel: t.statCellNum.level, isScreenBig: true, higherIsBetter: true, smallDecimal: false),
|
StatCellNum(playerStat: blitz!.endContext.level, playerStatLabel: t.statCellNum.level, isScreenBig: true, higherIsBetter: true, smallDecimal: false),
|
||||||
StatCellNum(playerStat: blitz!.endContext!.pps, playerStatLabel: t.statCellNum.pps, fractionDigits: 2, isScreenBig: true, higherIsBetter: true, smallDecimal: false),
|
StatCellNum(playerStat: blitz!.endContext.pps, playerStatLabel: t.statCellNum.pps, fractionDigits: 2, isScreenBig: true, higherIsBetter: true, smallDecimal: false),
|
||||||
StatCellNum(playerStat: blitz!.endContext!.spp, playerStatLabel: t.statCellNum.spp, fractionDigits: 2, isScreenBig: true, higherIsBetter: true)
|
StatCellNum(playerStat: blitz!.endContext.spp, playerStatLabel: t.statCellNum.spp, fractionDigits: 2, isScreenBig: true, higherIsBetter: true)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (blitz != null) FinesseThingy(blitz?.endContext?.finesse, blitz?.endContext?.finessePercentage),
|
if (blitz != null) FinesseThingy(blitz?.endContext.finesse, blitz?.endContext.finessePercentage),
|
||||||
if (blitz != null) LineclearsThingy(blitz!.endContext!.clears, blitz!.endContext!.lines, blitz!.endContext!.holds, blitz!.endContext!.tSpins),
|
if (blitz != null) LineclearsThingy(blitz!.endContext.clears, blitz!.endContext.lines, blitz!.endContext.holds, blitz!.endContext.tSpins),
|
||||||
if (blitz != null) Text("${blitz!.endContext!.piecesPlaced} P • ${blitz!.endContext!.inputs} KP • ${f2.format(blitz!.endContext!.kpp)} KPP • ${f2.format(blitz!.endContext!.kps)} KPS")
|
if (blitz != null) Text("${blitz!.endContext.piecesPlaced} P • ${blitz!.endContext.inputs} KP • ${f2.format(blitz!.endContext.kpp)} KPP • ${f2.format(blitz!.endContext.kps)} KPS")
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 350,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text("Recent", style: const TextStyle(height: 0.1, fontFamily: "Eurostile Round Extended", fontSize: 18)),
|
||||||
|
for(RecordSingle record in recent.records) ListTile(
|
||||||
|
leading: Text(
|
||||||
|
switch (record.endContext.gameType){
|
||||||
|
"40l" => "40L",
|
||||||
|
"blitz" => "BLZ",
|
||||||
|
"5mblast" => "5MB",
|
||||||
|
String() => "huh",
|
||||||
|
},
|
||||||
|
style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28, shadows: textShadow)
|
||||||
|
),
|
||||||
|
title: Text(
|
||||||
|
switch (record.endContext.gameType){
|
||||||
|
"40l" => get40lTime(record.endContext.finalTime.inMicroseconds),
|
||||||
|
"blitz" => "${NumberFormat.decimalPattern().format(record.endContext.score)} points",
|
||||||
|
"5mblast" => get40lTime(record.endContext.finalTime.inMicroseconds),
|
||||||
|
String() => "huh",
|
||||||
|
},
|
||||||
|
),
|
||||||
|
subtitle: Text(timestamp(record.timestamp)),
|
||||||
|
// trailing: switch (record.endContext.gameType){
|
||||||
|
// "40l" => get40lTime(record.endContext.finalTime.inMicroseconds),
|
||||||
|
// "blitz" => "${NumberFormat.decimalPattern().format(record.endContext.score)} points",
|
||||||
|
// "5mblast" => get40lTime(record.endContext.finalTime.inMicroseconds),
|
||||||
|
// String() => "huh",
|
||||||
|
// },
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
]),
|
]),
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
@ -1176,16 +1214,16 @@ class _RecordThingy extends StatelessWidget {
|
||||||
if (record == null) return Center(child: Text(t.noRecord, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28)));
|
if (record == null) return Center(child: Text(t.noRecord, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28)));
|
||||||
late MapEntry closestAverageBlitz;
|
late MapEntry closestAverageBlitz;
|
||||||
late bool blitzBetterThanClosestAverage;
|
late bool blitzBetterThanClosestAverage;
|
||||||
bool? blitzBetterThanRankAverage = (rank != null && rank != "z") ? record!.endContext!.score > blitzAverages[rank]! : null;
|
bool? blitzBetterThanRankAverage = (rank != null && rank != "z") ? record!.endContext.score > blitzAverages[rank]! : null;
|
||||||
late MapEntry closestAverageSprint;
|
late MapEntry closestAverageSprint;
|
||||||
late bool sprintBetterThanClosestAverage;
|
late bool sprintBetterThanClosestAverage;
|
||||||
bool? sprintBetterThanRankAverage = (rank != null && rank != "z") ? record!.endContext!.finalTime < sprintAverages[rank]! : null;
|
bool? sprintBetterThanRankAverage = (rank != null && rank != "z") ? record!.endContext.finalTime < sprintAverages[rank]! : null;
|
||||||
if (record!.stream.contains("40l")) {
|
if (record!.endContext.gameType == "40l") {
|
||||||
closestAverageSprint = sprintAverages.entries.singleWhere((element) => element.value == sprintAverages.values.reduce((a, b) => (a-record!.endContext!.finalTime).abs() < (b -record!.endContext!.finalTime).abs() ? a : b));
|
closestAverageSprint = sprintAverages.entries.singleWhere((element) => element.value == sprintAverages.values.reduce((a, b) => (a-record!.endContext.finalTime).abs() < (b -record!.endContext.finalTime).abs() ? a : b));
|
||||||
sprintBetterThanClosestAverage = record!.endContext!.finalTime < closestAverageSprint.value;
|
sprintBetterThanClosestAverage = record!.endContext.finalTime < closestAverageSprint.value;
|
||||||
}else if (record!.stream.contains("blitz")){
|
}else if (record!.endContext.gameType == "blitz"){
|
||||||
closestAverageBlitz = blitzAverages.entries.singleWhere((element) => element.value == blitzAverages.values.reduce((a, b) => (a-record!.endContext!.score).abs() < (b -record!.endContext!.score).abs() ? a : b));
|
closestAverageBlitz = blitzAverages.entries.singleWhere((element) => element.value == blitzAverages.values.reduce((a, b) => (a-record!.endContext.score).abs() < (b -record!.endContext.score).abs() ? a : b));
|
||||||
blitzBetterThanClosestAverage = record!.endContext!.score > closestAverageBlitz.value;
|
blitzBetterThanClosestAverage = record!.endContext.score > closestAverageBlitz.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
return LayoutBuilder(
|
return LayoutBuilder(
|
||||||
|
@ -1201,19 +1239,19 @@ class _RecordThingy extends StatelessWidget {
|
||||||
Row(
|
Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
if (record!.stream.contains("40l")) Padding(padding: const EdgeInsets.only(right: 8.0),
|
if (record!.endContext.gameType == "40l") Padding(padding: const EdgeInsets.only(right: 8.0),
|
||||||
child: Image.asset("res/tetrio_tl_alpha_ranks/${closestAverageSprint.key}.png", height: 96)
|
child: Image.asset("res/tetrio_tl_alpha_ranks/${closestAverageSprint.key}.png", height: 96)
|
||||||
),
|
),
|
||||||
if (record!.stream.contains("blitz")) Padding(padding: const EdgeInsets.only(right: 8.0),
|
if (record!.endContext.gameType == "blitz") Padding(padding: const EdgeInsets.only(right: 8.0),
|
||||||
child: Image.asset("res/tetrio_tl_alpha_ranks/${closestAverageBlitz.key}.png", height: 96)
|
child: Image.asset("res/tetrio_tl_alpha_ranks/${closestAverageBlitz.key}.png", height: 96)
|
||||||
),
|
),
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (record!.stream.contains("40l")) Text(t.sprint, style: const TextStyle(height: 0.1, fontFamily: "Eurostile Round Extended", fontSize: 18)),
|
if (record!.endContext.gameType == "40l") Text(t.sprint, style: const TextStyle(height: 0.1, fontFamily: "Eurostile Round Extended", fontSize: 18)),
|
||||||
if (record!.stream.contains("blitz")) Text(t.blitz, style: const TextStyle(height: 0.1, fontFamily: "Eurostile Round Extended", fontSize: 18)),
|
if (record!.endContext.gameType == "blitz") Text(t.blitz, style: const TextStyle(height: 0.1, fontFamily: "Eurostile Round Extended", fontSize: 18)),
|
||||||
RichText(text: TextSpan(
|
RichText(text: TextSpan(
|
||||||
text: record!.stream.contains("40l") ? get40lTime(record!.endContext!.finalTime.inMicroseconds) : NumberFormat.decimalPattern().format(record!.endContext!.score),
|
text: record!.endContext.gameType == "40l" ? get40lTime(record!.endContext.finalTime.inMicroseconds) : NumberFormat.decimalPattern().format(record!.endContext.score),
|
||||||
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 36 : 32, fontWeight: FontWeight.w500, color: Colors.white),
|
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 36 : 32, fontWeight: FontWeight.w500, color: Colors.white),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -1221,50 +1259,50 @@ class _RecordThingy extends StatelessWidget {
|
||||||
text: "",
|
text: "",
|
||||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey),
|
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey),
|
||||||
children: [
|
children: [
|
||||||
if (record!.stream.contains("40l") && (rank != null && rank != "z")) TextSpan(text: "${t.verdictGeneral(n: readableTimeDifference(record!.endContext!.finalTime, sprintAverages[rank]!), verdict: sprintBetterThanRankAverage??false ? t.verdictBetter : t.verdictWorse, rank: rank!.toUpperCase())}\n", style: TextStyle(
|
if (record!.endContext.gameType == "40l" && (rank != null && rank != "z")) TextSpan(text: "${t.verdictGeneral(n: readableTimeDifference(record!.endContext.finalTime, sprintAverages[rank]!), verdict: sprintBetterThanRankAverage??false ? t.verdictBetter : t.verdictWorse, rank: rank!.toUpperCase())}\n", style: TextStyle(
|
||||||
color: sprintBetterThanRankAverage??false ? Colors.greenAccent : Colors.redAccent
|
color: sprintBetterThanRankAverage??false ? Colors.greenAccent : Colors.redAccent
|
||||||
))
|
))
|
||||||
else if (record!.stream.contains("40l") && (rank == null || rank == "z")) TextSpan(text: "${t.verdictGeneral(n: readableTimeDifference(record!.endContext!.finalTime, closestAverageSprint.value), verdict: sprintBetterThanClosestAverage ? t.verdictBetter : t.verdictWorse, rank: closestAverageSprint.key.toUpperCase())}\n", style: TextStyle(
|
else if (record!.endContext.gameType == "40l" && (rank == null || rank == "z")) TextSpan(text: "${t.verdictGeneral(n: readableTimeDifference(record!.endContext.finalTime, closestAverageSprint.value), verdict: sprintBetterThanClosestAverage ? t.verdictBetter : t.verdictWorse, rank: closestAverageSprint.key.toUpperCase())}\n", style: TextStyle(
|
||||||
color: sprintBetterThanClosestAverage ? Colors.greenAccent : Colors.redAccent
|
color: sprintBetterThanClosestAverage ? Colors.greenAccent : Colors.redAccent
|
||||||
))
|
))
|
||||||
else if (record!.stream.contains("blitz") && (rank != null && rank != "z")) TextSpan(text: "${t.verdictGeneral(n: readableIntDifference(record!.endContext!.score, blitzAverages[rank]!), verdict: blitzBetterThanRankAverage??false ? t.verdictBetter : t.verdictWorse, rank: rank!.toUpperCase())}\n", style: TextStyle(
|
else if (record!.endContext.gameType == "blitz" && (rank != null && rank != "z")) TextSpan(text: "${t.verdictGeneral(n: readableIntDifference(record!.endContext.score, blitzAverages[rank]!), verdict: blitzBetterThanRankAverage??false ? t.verdictBetter : t.verdictWorse, rank: rank!.toUpperCase())}\n", style: TextStyle(
|
||||||
color: blitzBetterThanRankAverage??false ? Colors.greenAccent : Colors.redAccent
|
color: blitzBetterThanRankAverage??false ? Colors.greenAccent : Colors.redAccent
|
||||||
))
|
))
|
||||||
else if (record!.stream.contains("blitz") && (rank == null || rank == "z")) TextSpan(text: "${t.verdictGeneral(n: readableIntDifference(record!.endContext!.score, closestAverageBlitz.value), verdict: blitzBetterThanClosestAverage ? t.verdictBetter : t.verdictWorse, rank: closestAverageBlitz.key.toUpperCase())}\n", style: TextStyle(
|
else if (record!.endContext.gameType == "blitz" && (rank == null || rank == "z")) TextSpan(text: "${t.verdictGeneral(n: readableIntDifference(record!.endContext.score, closestAverageBlitz.value), verdict: blitzBetterThanClosestAverage ? t.verdictBetter : t.verdictWorse, rank: closestAverageBlitz.key.toUpperCase())}\n", style: TextStyle(
|
||||||
color: blitzBetterThanClosestAverage ? Colors.greenAccent : Colors.redAccent
|
color: blitzBetterThanClosestAverage ? Colors.greenAccent : Colors.redAccent
|
||||||
)),
|
)),
|
||||||
if (record!.rank != null) TextSpan(text: "№${record!.rank}", style: TextStyle(color: getColorOfRank(record!.rank!))),
|
if (record!.rank != null) TextSpan(text: "№${record!.rank}", style: TextStyle(color: getColorOfRank(record!.rank!))),
|
||||||
if (record!.rank != null) const TextSpan(text: " • "),
|
if (record!.rank != null) const TextSpan(text: " • "),
|
||||||
TextSpan(text: timestamp(record!.timestamp!)),
|
TextSpan(text: timestamp(record!.timestamp)),
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
],),
|
],),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (record!.stream.contains("40l")) Wrap(
|
if (record!.endContext.gameType == "40l") Wrap(
|
||||||
alignment: WrapAlignment.spaceBetween,
|
alignment: WrapAlignment.spaceBetween,
|
||||||
spacing: 20,
|
spacing: 20,
|
||||||
children: [
|
children: [
|
||||||
StatCellNum(playerStat: record!.endContext!.piecesPlaced, playerStatLabel: t.statCellNum.pieces, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: false),
|
StatCellNum(playerStat: record!.endContext.piecesPlaced, playerStatLabel: t.statCellNum.pieces, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: false),
|
||||||
StatCellNum(playerStat: record!.endContext!.pps, playerStatLabel: t.statCellNum.pps, fractionDigits: 2, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: false),
|
StatCellNum(playerStat: record!.endContext.pps, playerStatLabel: t.statCellNum.pps, fractionDigits: 2, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: false),
|
||||||
StatCellNum(playerStat: record!.endContext!.kpp, playerStatLabel: t.statCellNum.kpp, fractionDigits: 2, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: false),
|
StatCellNum(playerStat: record!.endContext.kpp, playerStatLabel: t.statCellNum.kpp, fractionDigits: 2, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: false),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (record!.stream.contains("blitz")) Wrap(
|
if (record!.endContext.gameType == "blitz") Wrap(
|
||||||
alignment: WrapAlignment.spaceBetween,
|
alignment: WrapAlignment.spaceBetween,
|
||||||
crossAxisAlignment: WrapCrossAlignment.start,
|
crossAxisAlignment: WrapCrossAlignment.start,
|
||||||
spacing: 20,
|
spacing: 20,
|
||||||
children: [
|
children: [
|
||||||
StatCellNum(playerStat: record!.endContext!.level, playerStatLabel: t.statCellNum.level, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: false),
|
StatCellNum(playerStat: record!.endContext.level, playerStatLabel: t.statCellNum.level, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: false),
|
||||||
StatCellNum(playerStat: record!.endContext!.pps, playerStatLabel: t.statCellNum.pps, fractionDigits: 2, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: false),
|
StatCellNum(playerStat: record!.endContext.pps, playerStatLabel: t.statCellNum.pps, fractionDigits: 2, isScreenBig: bigScreen, higherIsBetter: true, smallDecimal: false),
|
||||||
StatCellNum(playerStat: record!.endContext!.spp, playerStatLabel: t.statCellNum.spp, fractionDigits: 2, isScreenBig: bigScreen, higherIsBetter: true)
|
StatCellNum(playerStat: record!.endContext.spp, playerStatLabel: t.statCellNum.spp, fractionDigits: 2, isScreenBig: bigScreen, higherIsBetter: true)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
FinesseThingy(record?.endContext?.finesse, record?.endContext?.finessePercentage),
|
FinesseThingy(record?.endContext.finesse, record?.endContext.finessePercentage),
|
||||||
LineclearsThingy(record!.endContext!.clears, record!.endContext!.lines, record!.endContext!.holds, record!.endContext!.tSpins),
|
LineclearsThingy(record!.endContext.clears, record!.endContext.lines, record!.endContext.holds, record!.endContext.tSpins),
|
||||||
if (record!.stream.contains("40l")) Text("${record!.endContext!.inputs} KP • ${f2.format(record!.endContext!.kps)} KPS"),
|
if (record!.endContext.gameType == "40l") Text("${record!.endContext.inputs} KP • ${f2.format(record!.endContext.kps)} KPS"),
|
||||||
if (record!.stream.contains("blitz")) Text("${record!.endContext!.piecesPlaced} P • ${record!.endContext!.inputs} KP • ${f2.format(record!.endContext!.kpp)} KPP • ${f2.format(record!.endContext!.kps)} KPS")
|
if (record!.endContext.gameType == "blitz") Text("${record!.endContext.piecesPlaced} P • ${record!.endContext.inputs} KP • ${f2.format(record!.endContext.kpp)} KPP • ${f2.format(record!.endContext.kps)} KPS")
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
Loading…
Reference in New Issue