Optimized data storing and history saving
This commit is contained in:
parent
501832c9aa
commit
248b708276
|
@ -31,7 +31,8 @@ const Map<String, double> rankCutoffs = {
|
|||
"c": 0.9,
|
||||
"c-": 0.95,
|
||||
"d+": 0.975,
|
||||
"d": 1
|
||||
"d": 1,
|
||||
"z": -1
|
||||
};
|
||||
const Map<String, Color> rankColors = { // thanks osk for const rankColors at https://ch.tetr.io/res/js/base.js:418
|
||||
'x': Color(0xFFFF45FF),
|
||||
|
@ -85,7 +86,7 @@ class TetrioPlayer {
|
|||
late bool verified;
|
||||
bool? badstanding;
|
||||
String? botmaster;
|
||||
late Connections connections;
|
||||
Connections? connections;
|
||||
late TetraLeagueAlpha tlSeason1;
|
||||
List<RecordSingle?> sprint = [];
|
||||
List<RecordSingle?> blitz = [];
|
||||
|
@ -122,34 +123,30 @@ class TetrioPlayer {
|
|||
|
||||
double get level => pow((xp / 500), 0.6) + (xp / (5000 + (max(0, xp - 4 * pow(10, 6)) / 5000))) + 1;
|
||||
|
||||
TetrioPlayer.fromJson(Map<String, dynamic> json, DateTime stateTime) {
|
||||
TetrioPlayer.fromJson(Map<String, dynamic> json, DateTime stateTime, String id, String nick) {
|
||||
//developer.log("TetrioPlayer.fromJson $stateTime: $json", name: "data_objects/tetrio");
|
||||
userId = json['_id'];
|
||||
username = json['username'];
|
||||
userId = id;
|
||||
username = nick;
|
||||
state = stateTime;
|
||||
if (json['role'] == "retrived from p1nkl0bst3r api"){ //i fucked my own db lol i remove it later
|
||||
role = "p1nkl0bst3r";
|
||||
}else{
|
||||
role = json['role'];
|
||||
}
|
||||
role = json['role'];
|
||||
registrationTime = json['ts'] != null ? DateTime.parse(json['ts']) : null;
|
||||
if (json['badges'] != null) {
|
||||
json['badges'].forEach((v) {
|
||||
badges.add(Badge.fromJson(v));
|
||||
});
|
||||
}
|
||||
xp = json['xp'].toDouble();
|
||||
gamesPlayed = json['gamesplayed'];
|
||||
gamesWon = json['gameswon'];
|
||||
gameTime = doubleSecondsToDuration(json['gametime'].toDouble());
|
||||
xp = json['xp'] != null ? json['xp'].toDouble() : -1;
|
||||
gamesPlayed = json['gamesplayed'] ?? -1;
|
||||
gamesWon = json['gameswon'] ?? -1;
|
||||
gameTime = json['gametime'] != null && json['gametime'] != -1 ? doubleSecondsToDuration(json['gametime'].toDouble()) : const Duration(seconds: -1);
|
||||
country = json['country'];
|
||||
supporterTier = json['supporter_tier'];
|
||||
verified = json['verified'];
|
||||
supporterTier = json['supporter_tier'] ?? 0;
|
||||
verified = json['verified'] ?? false;
|
||||
tlSeason1 = TetraLeagueAlpha.fromJson(json['league'], stateTime);
|
||||
avatarRevision = json['avatar_revision'];
|
||||
bannerRevision = json['banner_revision'];
|
||||
bio = json['bio'];
|
||||
connections = Connections.fromJson(json['connections']);
|
||||
if (json['connections'] != null && json['connections'].isNotEmpty) connections = Connections.fromJson(json['connections']);
|
||||
distinguishment = json['distinguishment'] != null ? Distinguishment.fromJson(json['distinguishment']) : null;
|
||||
friendCount = json['friend_count'] ?? 0;
|
||||
badstanding = json['badstanding'];
|
||||
|
@ -158,25 +155,25 @@ class TetrioPlayer {
|
|||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['_id'] = userId;
|
||||
data['username'] = username;
|
||||
// data['_id'] = userId;
|
||||
// data['username'] = username;
|
||||
data['role'] = role;
|
||||
if (registrationTime != null) data['ts'] = registrationTime?.toString();
|
||||
data['badges'] = badges.map((v) => v.toJson()).toList();
|
||||
data['xp'] = xp;
|
||||
data['gamesplayed'] = gamesPlayed;
|
||||
data['gameswon'] = gamesWon;
|
||||
data['gametime'] = gameTime.inMicroseconds / 1000000;
|
||||
if (badges.isNotEmpty) data['badges'] = badges.map((v) => v.toJson()).toList();
|
||||
if (xp >= 0) data['xp'] = xp;
|
||||
if (gamesPlayed >= 0) data['gamesplayed'] = gamesPlayed;
|
||||
if (gamesWon >= 0) data['gameswon'] = gamesWon;
|
||||
if (!gameTime.isNegative) data['gametime'] = gameTime.inMicroseconds / 1000000;
|
||||
if (country != null) data['country'] = country;
|
||||
data['supporter_tier'] = supporterTier;
|
||||
data['verified'] = verified;
|
||||
if (supporterTier > 0) data['supporter_tier'] = supporterTier;
|
||||
if (verified) data['verified'] = verified;
|
||||
data['league'] = tlSeason1.toJson();
|
||||
if (distinguishment != null) data['distinguishment'] = distinguishment?.toJson();
|
||||
if (avatarRevision != null) data['avatar_revision'] = avatarRevision;
|
||||
if (bannerRevision != null) data['banner_revision'] = bannerRevision;
|
||||
if (data['bio'] != null) data['bio'] = bio;
|
||||
data['connections'] = connections.toJson();
|
||||
data['friend_count'] = friendCount;
|
||||
if (bio != null) data['bio'] = bio;
|
||||
if (connections != null) data['connections'] = connections!.toJson();
|
||||
if (friendCount > 0) data['friend_count'] = friendCount;
|
||||
if (badstanding != null) data['badstanding'] = badstanding;
|
||||
if (botmaster != null) data['botmaster'] = botmaster;
|
||||
//developer.log("TetrioPlayer.toJson: $data", name: "data_objects/tetrio");
|
||||
|
@ -741,7 +738,7 @@ class TetraLeagueAlpha {
|
|||
this.pps,
|
||||
this.vs,
|
||||
this.records}){
|
||||
nerdStats = (apm != null && pps != null && apm != null) ? NerdStats(apm!, pps!, vs!) : null;
|
||||
nerdStats = (apm != null && pps != null && vs != null) ? NerdStats(apm!, pps!, vs!) : null;
|
||||
estTr = (nerdStats != null) ? EstTr(apm!, pps!, vs!, (rd != null) ? rd! : 69, nerdStats!.app, nerdStats!.dss, nerdStats!.dsp, nerdStats!.gbe) : null;
|
||||
playstyle =(nerdStats != null) ? Playstyle(apm!, pps!, nerdStats!.app, nerdStats!.vsapm, nerdStats!.dsp, nerdStats!.gbe, estTr!.srarea, estTr!.statrank) : null;
|
||||
}
|
||||
|
@ -750,29 +747,28 @@ class TetraLeagueAlpha {
|
|||
|
||||
TetraLeagueAlpha.fromJson(Map<String, dynamic> json, ts) {
|
||||
timestamp = ts;
|
||||
gamesPlayed = json['gamesplayed'];
|
||||
gamesWon = json['gameswon'];
|
||||
rating = json['rating'].toDouble();
|
||||
gamesPlayed = json['gamesplayed'] ?? 0;
|
||||
gamesWon = json['gameswon'] ?? 0;
|
||||
rating = json['rating'] != null ? json['rating'].toDouble() : -1;
|
||||
glicko = json['glicko']?.toDouble();
|
||||
rd = json['rd']?.toDouble();
|
||||
rank = json['rank'];
|
||||
bestRank = json['bestrank'].toString();
|
||||
apm = json['apm']?.toDouble();
|
||||
pps = json['pps']?.toDouble();
|
||||
vs = json['vs']?.toDouble();
|
||||
decaying = json['decaying'];
|
||||
standing = json['standing'];
|
||||
percentile = json['percentile'].toDouble();
|
||||
standingLocal = json['standing_local'];
|
||||
rd = json['rd'] != null ? json['rd']!.toDouble() : noTrRd;
|
||||
rank = json['rank'] != null ? json['rank']!.toString() : 'z';
|
||||
bestRank = json['bestrank'] != null ? json['bestrank']!.toString() : 'z';
|
||||
apm = json['apm'] != null ? json['apm']!.toDouble() : null;
|
||||
pps = json['pps'] != null ? json['pps']!.toDouble() : null;
|
||||
vs = json['vs'] != null ? json['vs']!.toDouble() : null;
|
||||
decaying = json['decaying'] ?? false;
|
||||
standing = json['standing'] ?? -1;
|
||||
percentile = json['percentile'] != null ? json['percentile'].toDouble() : rankCutoffs[rank];
|
||||
standingLocal = json['standing_local'] ?? -1;
|
||||
prevRank = json['prev_rank'];
|
||||
prevAt = json['prev_at'];
|
||||
prevAt = json['prev_at'] ?? -1;
|
||||
nextRank = json['next_rank'];
|
||||
nextAt = json['next_at'];
|
||||
percentileRank = json['percentile_rank'];
|
||||
nextAt = json['next_at'] ?? -1;
|
||||
percentileRank = json['percentile_rank'] ?? rank;
|
||||
nerdStats = (apm != null && pps != null && vs != null) ? NerdStats(apm!, pps!, vs!) : null;
|
||||
estTr = (nerdStats != null) ? EstTr(apm!, pps!, vs!, (rd != null) ? rd! : 69, nerdStats!.app, nerdStats!.dss, nerdStats!.dsp, nerdStats!.gbe) : null;
|
||||
playstyle =
|
||||
(nerdStats != null) ? Playstyle(apm!, pps!, nerdStats!.app, nerdStats!.vsapm, nerdStats!.dsp, nerdStats!.gbe, estTr!.srarea, estTr!.statrank) : null;
|
||||
playstyle = (nerdStats != null) ? Playstyle(apm!, pps!, nerdStats!.app, nerdStats!.vsapm, nerdStats!.dsp, nerdStats!.gbe, estTr!.srarea, estTr!.statrank) : null;
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -784,25 +780,25 @@ class TetraLeagueAlpha {
|
|||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['gamesplayed'] = gamesPlayed;
|
||||
data['gameswon'] = gamesWon;
|
||||
data['rating'] = rating;
|
||||
if (gamesPlayed > 0) data['gamesplayed'] = gamesPlayed;
|
||||
if (gamesWon > 0) data['gameswon'] = gamesWon;
|
||||
if (rating >= 0) data['rating'] = rating;
|
||||
if (glicko != null) data['glicko'] = glicko;
|
||||
if (rd != null) data['rd'] = rd;
|
||||
data['rank'] = rank;
|
||||
data['bestrank'] = bestRank;
|
||||
if (rd != null && rd != noTrRd) data['rd'] = rd;
|
||||
if (rank != 'z') data['rank'] = rank;
|
||||
if (bestRank != 'z') data['bestrank'] = bestRank;
|
||||
if (apm != null) data['apm'] = apm;
|
||||
if (pps != null) data['pps'] = pps;
|
||||
if (vs != null) data['vs'] = vs;
|
||||
data['decaying'] = decaying;
|
||||
data['standing'] = standing;
|
||||
data['percentile'] = percentile;
|
||||
data['standing_local'] = standingLocal;
|
||||
if (decaying) data['decaying'] = decaying;
|
||||
if (standing >= 0) data['standing'] = standing;
|
||||
if (!rankCutoffs.containsValue(percentile)) data['percentile'] = percentile;
|
||||
if (standingLocal >= 0) data['standing_local'] = standingLocal;
|
||||
if (prevRank != null) data['prev_rank'] = prevRank;
|
||||
data['prev_at'] = prevAt;
|
||||
if (prevAt >= 0) data['prev_at'] = prevAt;
|
||||
if (nextRank != null) data['next_rank'] = nextRank;
|
||||
data['next_at'] = nextAt;
|
||||
data['percentile_rank'] = percentileRank;
|
||||
if (nextAt >= 0) data['next_at'] = nextAt;
|
||||
if (percentileRank != rank) data['percentile_rank'] = percentileRank;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -117,15 +117,30 @@ class TetrioService extends DB {
|
|||
xp: -1,
|
||||
supporterTier: 0,
|
||||
verified: false,
|
||||
connections: Connections(),
|
||||
tlSeason1: TetraLeagueAlpha(timestamp: DateTime.parse(entry[9]), apm: entry[6], pps: entry[7], vs: entry[8], glicko: entry[4], rd: noTrRd, gamesPlayed: entry[1], gamesWon: entry[2], bestRank: "z", decaying: false, rating: entry[3], rank: entry[5], percentileRank: entry[5], percentile: rankCutoffs[entry[5]]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1),
|
||||
connections: null,
|
||||
tlSeason1: TetraLeagueAlpha(timestamp: DateTime.parse(entry[9]), apm: entry[6] != '' ? entry[6] : null, pps: entry[7] != '' ? entry[7] : null, vs: entry[8] != '' ? entry[8] : null, glicko: entry[4], rd: noTrRd, gamesPlayed: entry[1], gamesWon: entry[2], bestRank: "z", decaying: false, rating: entry[3], rank: entry[5], percentileRank: entry[5], percentile: rankCutoffs[entry[5]]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1),
|
||||
sprint: [],
|
||||
blitz: []
|
||||
);
|
||||
history.add(state);
|
||||
// _players.addEntries({state.userId: [state]}.entries);
|
||||
await storeState(state, isFromHistory: true);
|
||||
history.add(state);
|
||||
}
|
||||
ensureDbIsOpen();
|
||||
final db = getDatabaseOrThrow();
|
||||
late List<TetrioPlayer> states;
|
||||
try{
|
||||
states = _players[id]!;
|
||||
}catch(e){
|
||||
var player = await fetchPlayer(id);
|
||||
await createPlayer(player);
|
||||
states = _players[id]!;
|
||||
}
|
||||
states.insertAll(0, history.reversed);
|
||||
final Map<String, dynamic> statesJson = {};
|
||||
for (var e in states) {
|
||||
statesJson.addEntries({(e.state.millisecondsSinceEpoch ~/ 1000).toString(): e.toJson()}.entries);
|
||||
}
|
||||
await db.update(tetrioUsersTable, {idCol: id, nickCol: nick, statesCol: jsonEncode(statesJson)}, where: '$idCol = ?', whereArgs: [id]);
|
||||
_tetrioStreamController.add(_players);
|
||||
return history;
|
||||
}
|
||||
else {
|
||||
|
@ -270,7 +285,7 @@ class TetrioService extends DB {
|
|||
if (results.isNotEmpty) {
|
||||
throw TetrioPlayerAlreadyExist();
|
||||
}
|
||||
final Map<String, dynamic> statesJson = {tetrioPlayer.state.millisecondsSinceEpoch.toString(): tetrioPlayer.toJson()};
|
||||
final Map<String, dynamic> statesJson = {(tetrioPlayer.state.millisecondsSinceEpoch ~/ 1000).toString(): tetrioPlayer.toJson()};
|
||||
db.insert(tetrioUsersTable, {idCol: tetrioPlayer.userId, nickCol: tetrioPlayer.username, statesCol: jsonEncode(statesJson)});
|
||||
_players.addEntries({
|
||||
tetrioPlayer.userId: [tetrioPlayer]
|
||||
|
@ -319,7 +334,7 @@ class TetrioService extends DB {
|
|||
}
|
||||
}
|
||||
|
||||
Future<void> storeState(TetrioPlayer tetrioPlayer, {bool isFromHistory = false}) async {
|
||||
Future<void> storeState(TetrioPlayer tetrioPlayer) async {
|
||||
ensureDbIsOpen();
|
||||
final db = getDatabaseOrThrow();
|
||||
late List<TetrioPlayer> states;
|
||||
|
@ -330,15 +345,15 @@ class TetrioService extends DB {
|
|||
await createPlayer(tetrioPlayer);
|
||||
states = await getPlayer(tetrioPlayer.userId);
|
||||
}
|
||||
bool test = isFromHistory ? _players[tetrioPlayer.userId]!.last.checkForRetrivedHistory(tetrioPlayer) : _players[tetrioPlayer.userId]!.last.isSameState(tetrioPlayer);
|
||||
if (test == false) isFromHistory ? states.insert(0, tetrioPlayer) : states.add(tetrioPlayer);
|
||||
bool test = _players[tetrioPlayer.userId]!.last.isSameState(tetrioPlayer);
|
||||
if (test == false) states.add(tetrioPlayer);
|
||||
final Map<String, dynamic> statesJson = {};
|
||||
for (var e in states) {
|
||||
statesJson.addEntries({e.state.millisecondsSinceEpoch.toString(): e.toJson()}.entries);
|
||||
statesJson.addEntries({(e.state.millisecondsSinceEpoch ~/ 1000).toString(): e.toJson()}.entries);
|
||||
}
|
||||
await db.update(tetrioUsersTable, {idCol: tetrioPlayer.userId, nickCol: tetrioPlayer.username, statesCol: jsonEncode(statesJson)},
|
||||
where: '$idCol = ?', whereArgs: [tetrioPlayer.userId]);
|
||||
isFromHistory ? _players[tetrioPlayer.userId]!.insert(0, tetrioPlayer) : _players[tetrioPlayer.userId]!.add(tetrioPlayer);
|
||||
_players[tetrioPlayer.userId]!.add(tetrioPlayer);
|
||||
_tetrioStreamController.add(_players);
|
||||
}
|
||||
|
||||
|
@ -369,7 +384,7 @@ class TetrioService extends DB {
|
|||
} else {
|
||||
dynamic rawStates = results.first['jsonStates'] as String;
|
||||
rawStates = json.decode(rawStates);
|
||||
rawStates.forEach((k, v) => states.add(TetrioPlayer.fromJson(v, DateTime.fromMillisecondsSinceEpoch(int.parse(k)))));
|
||||
rawStates.forEach((k, v) => states.add(TetrioPlayer.fromJson(v, DateTime.fromMillisecondsSinceEpoch(int.parse(k) * 1000), id, results.first[nickCol] as String)));
|
||||
_players.removeWhere((key, value) => key == id);
|
||||
_players.addEntries({states.last.userId: states}.entries);
|
||||
_tetrioStreamController.add(_players);
|
||||
|
@ -395,9 +410,9 @@ class TetrioService extends DB {
|
|||
final response = await http.get(url);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
if (jsonDecode(response.body)['success']) {
|
||||
TetrioPlayer player = TetrioPlayer.fromJson(
|
||||
jsonDecode(response.body)['data']['user'], DateTime.fromMillisecondsSinceEpoch(jsonDecode(response.body)['cache']['cached_at'], isUtc: true));
|
||||
var json = jsonDecode(response.body);
|
||||
if (json['success']) {
|
||||
TetrioPlayer player = TetrioPlayer.fromJson(json['data']['user'], DateTime.fromMillisecondsSinceEpoch(json['cache']['cached_at'], isUtc: true), json['data']['user']['_id'], json['data']['user']['username']);
|
||||
developer.log("fetchPlayer: $user retrieved and cached", name: "services/tetrio_crud");
|
||||
_playersCache[jsonDecode(response.body)['cache']['cached_until'].toString()] = player;
|
||||
return player;
|
||||
|
@ -421,7 +436,7 @@ class TetrioService extends DB {
|
|||
// what the fuck am i doing here?
|
||||
var test = json.decode(row['jsonStates'] as String);
|
||||
List<TetrioPlayer> states = [];
|
||||
test.forEach((k, v) => states.add(TetrioPlayer.fromJson(v, DateTime.fromMillisecondsSinceEpoch(int.parse(k)))));
|
||||
test.forEach((k, v) => states.add(TetrioPlayer.fromJson(v, DateTime.fromMillisecondsSinceEpoch(int.parse(k) * 1000), row[idCol] as String, row[nickCol] as String)));
|
||||
data.addEntries({states.last.userId: states}.entries);
|
||||
return data;
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue