Serialisation polished, time to think how to store

This commit is contained in:
dan63047 2023-05-13 21:22:57 +03:00
parent 5feadcfe09
commit cbea8dedaf
2 changed files with 173 additions and 166 deletions

View File

@ -2,75 +2,67 @@ import 'dart:math';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'dart:convert'; import 'dart:convert';
Future<TetrioPlayer> fetchTetrioRecords(String user) async {
var url = Uri.https('ch.tetr.io', 'api/users/$user/records');
final response = await http.get(url);
// final response = await http.get(Uri.parse('https://ch.tetr.io/'));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return TetrioPlayer.fromJson(jsonDecode(response.body));
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to fetch player');
}
}
Duration doubleSecondsToDuration(double value) { Duration doubleSecondsToDuration(double value) {
value = value * 1000000; value = value * 1000000;
return Duration(microseconds: value.floor()); return Duration(microseconds: value.floor());
} }
Duration doubleMillisecondsToDuration(double value) {
value = value * 1000;
return Duration(microseconds: value.floor());
}
class TetrioPlayer { class TetrioPlayer {
String? userId; late String userId;
String? username; late String username;
String? role; late String role;
int? avatarRevision; int? avatarRevision;
int? bannerRevision; int? bannerRevision;
DateTime? registrationTime; DateTime? registrationTime;
List<Badge>? badges; List<Badge> badges = [];
String? bio; String? bio;
String? country; String? country;
int? friendCount; late int friendCount;
int? gamesPlayed; late int gamesPlayed;
int? gamesWon; late int gamesWon;
Duration? gameTime; late Duration gameTime;
double? xp; late double xp;
int? supporterTier; late int supporterTier;
bool? verified; late bool verified;
Connections? connections; bool? badstanding;
TetraLeagueAlpha? tlSeason1; bool? bot;
List<RecordSingle>? sprint; late Connections connections;
List<RecordSingle>? blitz; late TetraLeagueAlpha tlSeason1;
List<RecordSingle?> sprint = [];
List<RecordSingle?> blitz = [];
TetrioZen? zen; TetrioZen? zen;
Distinguishment? distinguishment;
TetrioPlayer({ TetrioPlayer({
this.userId, required this.userId,
this.username, required this.username,
this.role, required this.role,
this.registrationTime, this.registrationTime,
this.badges, required this.badges,
this.bio, this.bio,
this.country, this.country,
this.friendCount, required this.friendCount,
this.gamesPlayed, required this.gamesPlayed,
this.gamesWon, required this.gamesWon,
this.gameTime, required this.gameTime,
this.xp, required this.xp,
this.supporterTier, required this.supporterTier,
this.verified, required this.verified,
this.connections, required this.connections,
this.tlSeason1, required this.tlSeason1,
this.sprint, required this.sprint,
this.blitz, required this.blitz,
this.zen, this.zen,
}); });
double getLevel() { double getLevel() {
return pow((xp! / 500), 0.6) + return pow((xp / 500), 0.6) +
(xp! / (5000 + (max(0, xp! - 4 * pow(10, 6)) / 5000))) + (xp / (5000 + (max(0, xp - 4 * pow(10, 6)) / 5000))) +
1; 1;
} }
@ -80,9 +72,8 @@ class TetrioPlayer {
role = json['role']; role = json['role'];
registrationTime = json['ts'] != null ? DateTime.parse(json['ts']) : null; registrationTime = json['ts'] != null ? DateTime.parse(json['ts']) : null;
if (json['badges'] != null) { if (json['badges'] != null) {
badges = <Badge>[];
json['badges'].forEach((v) { json['badges'].forEach((v) {
badges!.add(Badge.fromJson(v)); badges.add(Badge.fromJson(v));
}); });
} }
xp = json['xp'].toDouble(); xp = json['xp'].toDouble();
@ -92,33 +83,24 @@ class TetrioPlayer {
country = json['country']; country = json['country'];
supporterTier = json['supporter_tier']; supporterTier = json['supporter_tier'];
verified = json['verified']; verified = json['verified'];
tlSeason1 = json['league'] != null tlSeason1 = TetraLeagueAlpha.fromJson(json['league']);
? TetraLeagueAlpha.fromJson(json['league'])
: null;
avatarRevision = json['avatar_revision']; avatarRevision = json['avatar_revision'];
bannerRevision = json['banner_revision']; bannerRevision = json['banner_revision'];
bio = json['bio']; bio = json['bio'];
connections = json['connections'] != null connections = Connections.fromJson(json['connections']);
? Connections.fromJson(json['connections']) distinguishment = json['distinguishment'] != null
? Distinguishment.fromJson(json['distinguishment'])
: null; : null;
var url = Uri.https('ch.tetr.io', 'api/users/$userId/records'); var url = Uri.https('ch.tetr.io', 'api/users/$userId/records');
Future response = http.get(url); Future response = http.get(url);
response.then((value) { response.then((value) {
if (value.statusCode == 200) { if (value.statusCode == 200) {
sprint = jsonDecode(value.body)['data']['records']['40l']['record'] != if(jsonDecode(value.body)['data']['records']['40l']['record'] != null){
null sprint.add(RecordSingle.fromJson(jsonDecode(value.body)['data']['records']['40l']['record']));
? [ }
RecordSingle.fromJson( if(jsonDecode(value.body)['data']['records']['blitz']['record'] != null){
jsonDecode(value.body)['data']['records']['40l']['record']) blitz.add(RecordSingle.fromJson(jsonDecode(value.body)['data']['records']['blitz']['record']));
] }
: null;
blitz =
jsonDecode(value.body)['data']['records']['blitz']['record'] != null
? [
RecordSingle.fromJson(jsonDecode(value.body)['data']
['records']['blitz']['record'])
]
: null;
zen = TetrioZen.fromJson(jsonDecode(value.body)['data']['zen']); zen = TetrioZen.fromJson(jsonDecode(value.body)['data']['zen']);
} else { } else {
throw Exception('Failed to fetch player'); throw Exception('Failed to fetch player');
@ -133,9 +115,7 @@ class TetrioPlayer {
data['username'] = username; data['username'] = username;
data['role'] = role; data['role'] = role;
data['ts'] = registrationTime; data['ts'] = registrationTime;
if (badges != null) { data['badges'] = badges.map((v) => v.toJson()).toList();
data['badges'] = badges!.map((v) => v.toJson()).toList();
}
data['xp'] = xp; data['xp'] = xp;
data['gamesplayed'] = gamesPlayed; data['gamesplayed'] = gamesPlayed;
data['gameswon'] = gamesWon; data['gameswon'] = gamesWon;
@ -143,26 +123,22 @@ class TetrioPlayer {
data['country'] = country; data['country'] = country;
data['supporter_tier'] = supporterTier; data['supporter_tier'] = supporterTier;
data['verified'] = verified; data['verified'] = verified;
if (tlSeason1 != null) { data['league'] = tlSeason1.toJson();
data['league'] = tlSeason1!.toJson();
}
data['avatar_revision'] = avatarRevision; data['avatar_revision'] = avatarRevision;
data['banner_revision'] = bannerRevision; data['banner_revision'] = bannerRevision;
data['bio'] = bio; data['bio'] = bio;
if (connections != null) { data['connections'] = connections.toJson();
data['connections'] = connections!.toJson();
}
data['friend_count'] = friendCount; data['friend_count'] = friendCount;
return data; return data;
} }
} }
class Badge { class Badge {
String? badgeId; late String badgeId;
String? label; late String label;
DateTime? ts; DateTime? ts;
Badge({required this.badgeId, required this.label, required this.ts}); Badge({required this.badgeId, required this.label, this.ts});
Badge.fromJson(Map<String, dynamic> json) { Badge.fromJson(Map<String, dynamic> json) {
badgeId = json['id']; badgeId = json['id'];
@ -199,34 +175,34 @@ class Connections {
} }
class Clears { class Clears {
int? singles; late int singles;
int? doubles; late int doubles;
int? triples; late int triples;
int? quads; late int quads;
int? allClears; late int allClears;
int? tSpinZeros; late int tSpinZeros;
int? tSpinSingles; late int tSpinSingles;
int? tSpinDoubles; late int tSpinDoubles;
int? tSpinTriples; late int tSpinTriples;
int? tSpinQuads; late int tSpinQuads;
int? tSpinMiniZeros; late int tSpinMiniZeros;
int? tSpinMiniSingles; late int tSpinMiniSingles;
int? tSpinMiniDoubles; late int tSpinMiniDoubles;
Clears( Clears(
{this.singles, {required this.singles,
this.doubles, required this.doubles,
this.triples, required this.triples,
this.quads, required this.quads,
this.allClears, required this.allClears,
this.tSpinZeros, required this.tSpinZeros,
this.tSpinSingles, required this.tSpinSingles,
this.tSpinDoubles, required this.tSpinDoubles,
this.tSpinTriples, required this.tSpinTriples,
this.tSpinQuads, required this.tSpinQuads,
this.tSpinMiniZeros, required this.tSpinMiniZeros,
this.tSpinMiniSingles, required this.tSpinMiniSingles,
this.tSpinMiniDoubles}); required this.tSpinMiniDoubles});
Clears.fromJson(Map<String, dynamic> json) { Clears.fromJson(Map<String, dynamic> json) {
singles = json['singles']; singles = json['singles'];
@ -264,10 +240,10 @@ class Clears {
} }
class Discord { class Discord {
String? id; late String id;
String? username; late String username;
Discord({this.id, this.username}); Discord({required this.id, required this.username});
Discord.fromJson(Map<String, dynamic> json) { Discord.fromJson(Map<String, dynamic> json) {
id = json['id']; id = json['id'];
@ -283,11 +259,12 @@ class Discord {
} }
class Finesse { class Finesse {
int? combo; late int combo;
int? faults; late int faults;
int? perfectPieces; late int perfectPieces;
Finesse({this.combo, this.faults, this.perfectPieces}); Finesse(
{required this.combo, required this.faults, required this.perfectPieces});
Finesse.fromJson(Map<String, dynamic> json) { Finesse.fromJson(Map<String, dynamic> json) {
combo = json['combo']; combo = json['combo'];
@ -341,7 +318,7 @@ class EndContextSingle {
lines = json['lines']; lines = json['lines'];
inputs = json['inputs']; inputs = json['inputs'];
holds = json['holds']; holds = json['holds'];
finalTime = doubleSecondsToDuration(json['finalTime'].toDouble()); finalTime = doubleMillisecondsToDuration(json['finalTime'].toDouble());
score = json['score']; score = json['score'];
level = json['level']; level = json['level'];
topCombo = json['topcombo']; topCombo = json['topcombo'];
@ -379,15 +356,20 @@ class EndContextSingle {
} }
class Handling { class Handling {
double? arr; late double arr;
double? das; late double das;
int? sdf; late int sdf;
int? dcd; late int dcd;
bool? cancel; late bool cancel;
bool? safeLock; late bool safeLock;
Handling( Handling(
{this.arr, this.das, this.sdf, this.dcd, this.cancel, this.safeLock}); {required this.arr,
required this.das,
required this.sdf,
required this.dcd,
required this.cancel,
required this.safeLock});
Handling.fromJson(Map<String, dynamic> json) { Handling.fromJson(Map<String, dynamic> json) {
arr = json['arr']; arr = json['arr'];
@ -484,46 +466,44 @@ class EndContextMulti {
} }
class TetraLeagueAlpha { class TetraLeagueAlpha {
String? userId; late int gamesPlayed;
int? gamesPlayed; late int gamesWon;
int? gamesWon; late String bestRank;
String? bestRank; late bool decaying;
bool? decaying; late double rating;
double? rating; late String rank;
String? rank;
double? glicko; double? glicko;
double? rd; double? rd;
String? percentileRank; late String percentileRank;
double? percentile; late double percentile;
int? standing; late int standing;
int? standingLocal; late int standingLocal;
String? nextRank; String? nextRank;
int? nextAt; late int nextAt;
String? prevRank; String? prevRank;
int? prevAt; late int prevAt;
double? apm; double? apm;
double? pps; double? pps;
double? vs; double? vs;
List? records; List? records;
TetraLeagueAlpha( TetraLeagueAlpha(
{this.userId, {required this.gamesPlayed,
this.gamesPlayed, required this.gamesWon,
this.gamesWon, required this.bestRank,
this.bestRank, required this.decaying,
this.decaying, required this.rating,
this.rating, required this.rank,
this.rank,
this.glicko, this.glicko,
this.rd, this.rd,
this.percentileRank, required this.percentileRank,
this.percentile, required this.percentile,
this.standing, required this.standing,
this.standingLocal, required this.standingLocal,
this.nextRank, this.nextRank,
this.nextAt, required this.nextAt,
this.prevRank, this.prevRank,
this.prevAt, required this.prevAt,
this.apm, this.apm,
this.pps, this.pps,
this.vs, this.vs,
@ -577,17 +557,17 @@ class TetraLeagueAlpha {
} }
class RecordSingle { class RecordSingle {
String? userId; late String userId;
String? replayId; late String replayId;
String? ownId; late String ownId;
DateTime? timestamp; DateTime? timestamp;
EndContextSingle? endContext; EndContextSingle? endContext;
int? rank; int? rank;
RecordSingle( RecordSingle(
{this.userId, {required this.userId,
this.replayId, required this.replayId,
this.ownId, required this.ownId,
this.timestamp, this.timestamp,
this.endContext, this.endContext,
this.rank}); this.rank});
@ -617,11 +597,10 @@ class RecordSingle {
} }
class TetrioZen { class TetrioZen {
String? userId; late int level;
int? level; late int score;
int? score;
TetrioZen({this.userId, this.level, this.score}); TetrioZen({required this.level, required this.score});
TetrioZen.fromJson(Map<String, dynamic> json) { TetrioZen.fromJson(Map<String, dynamic> json) {
level = json['level']; level = json['level'];
@ -635,3 +614,28 @@ class TetrioZen {
return data; return data;
} }
} }
class Distinguishment {
late String type;
String? detail;
String? header;
String? footer;
Distinguishment({required this.type, this.detail, this.header, this.footer});
Distinguishment.fromJson(Map<String, dynamic> json) {
type = json['type'];
detail = json['detail'];
header = json['header'];
footer = json['footer'];
}
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['type'] = type;
data['detail'] = detail;
data['header'] = header;
data['footer'] = footer;
return data;
}
}

View File

@ -4,7 +4,7 @@ import 'dart:convert';
import 'package:tetra_stats/data_objects/tetrio.dart'; import 'package:tetra_stats/data_objects/tetrio.dart';
String _searchFor = ""; String _searchFor = "";
TetrioPlayer me = TetrioPlayer(); late TetrioPlayer me;
class MainView extends StatefulWidget { class MainView extends StatefulWidget {
const MainView({Key? key}) : super(key: key); const MainView({Key? key}) : super(key: key);
@ -51,6 +51,9 @@ class _MainViewState extends State<MainView> {
child: TextField( child: TextField(
onChanged: (String value) { onChanged: (String value) {
_searchFor = value; _searchFor = value;
setState(() {
});
}, },
onSubmitted: (String value) { onSubmitted: (String value) {
setState(() { setState(() {
@ -87,19 +90,19 @@ class _MainViewState extends State<MainView> {
Text("Supporter tier ${snapshot.data!.supporterTier}"), Text("Supporter tier ${snapshot.data!.supporterTier}"),
const Text("\nTetra League", softWrap: true), const Text("\nTetra League", softWrap: true),
Text( Text(
"${snapshot.data!.tlSeason1!.rating?.toStringAsFixed(2)} TR"), "${snapshot.data!.tlSeason1.rating.toStringAsFixed(2)} TR"),
Text( Text(
"${snapshot.data!.tlSeason1!.glicko?.toStringAsFixed(2)}±${snapshot.data!.tlSeason1!.rd?.toStringAsFixed(2)} GLICKO"), "${snapshot.data!.tlSeason1.glicko?.toStringAsFixed(2)}±${snapshot.data!.tlSeason1.rd?.toStringAsFixed(2)} GLICKO"),
Text( Text(
"Rank: ${snapshot.data!.tlSeason1!.rank?.toUpperCase()} (top ${(snapshot.data!.tlSeason1!.percentile! * 100).toStringAsFixed(2)}%)"), "Rank: ${snapshot.data!.tlSeason1.rank.toUpperCase()} (top ${(snapshot.data!.tlSeason1.percentile * 100).toStringAsFixed(2)}%)"),
Text( Text(
"Won/Games: ${snapshot.data!.tlSeason1!.gamesPlayed}/${snapshot.data!.tlSeason1!.gamesWon}"), "Won/Games: ${snapshot.data!.tlSeason1.gamesPlayed}/${snapshot.data!.tlSeason1.gamesWon}"),
Text( Text(
"${snapshot.data!.tlSeason1!.standing} (№${snapshot.data!.tlSeason1!.standingLocal} in country)"), "${snapshot.data!.tlSeason1.standing} (№${snapshot.data!.tlSeason1.standingLocal} in country)"),
Text( Text(
"${snapshot.data!.tlSeason1!.apm} APM, ${snapshot.data!.tlSeason1!.pps} PPS, ${snapshot.data!.tlSeason1!.vs} VS"), "${snapshot.data!.tlSeason1.apm} APM, ${snapshot.data!.tlSeason1.pps} PPS, ${snapshot.data!.tlSeason1.vs} VS"),
const Text("\n40 Lines", softWrap: true), const Text("\n40 Lines", softWrap: true),
Text(snapshot.data!.sprint.toString()), Text(snapshot.data!.sprint.isNotEmpty ? snapshot.data!.sprint[0].toString() : "No record"),
])); ]));
} else if (snapshot.hasError) { } else if (snapshot.hasError) {
return Text('${snapshot.error}'); return Text('${snapshot.error}');