Redoing local DB
- Retrieving history is slow rn because i save one entry at the time - No check if entry is already here - S1 history is not avaliable for now - Maybe i should store it like i did that during S1 but idk
This commit is contained in:
parent
d710674973
commit
38ec643a01
|
@ -3,10 +3,10 @@
|
|||
import 'dart:math';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tetra_stats/data_objects/tetra_stats.dart';
|
||||
import 'package:tetra_stats/gen/strings.g.dart';
|
||||
import 'package:vector_math/vector_math.dart';
|
||||
|
||||
const int currentSeason = 2;
|
||||
const double noTrRd = 60.9;
|
||||
const double apmWeight = 1;
|
||||
const double ppsWeight = 45;
|
||||
|
@ -228,7 +228,6 @@ class TetrioPlayer {
|
|||
bool? badstanding;
|
||||
String? botmaster;
|
||||
Connections? connections;
|
||||
TetraLeague? tlSeason1;
|
||||
TetrioZen? zen;
|
||||
Distinguishment? distinguishment;
|
||||
DateTime? cachedUntil;
|
||||
|
@ -254,7 +253,6 @@ class TetrioPlayer {
|
|||
this.badstanding,
|
||||
this.botmaster,
|
||||
required this.connections,
|
||||
required this.tlSeason1,
|
||||
this.zen,
|
||||
this.distinguishment,
|
||||
this.cachedUntil
|
||||
|
@ -281,7 +279,6 @@ class TetrioPlayer {
|
|||
country = json['country'];
|
||||
supporterTier = json['supporter_tier'] ?? 0;
|
||||
verified = json['verified'] ?? false;
|
||||
tlSeason1 = json['league'] != null ? TetraLeague.fromJson(json['league'], stateTime) : null;
|
||||
avatarRevision = json['avatar_revision'];
|
||||
bannerRevision = json['banner_revision'];
|
||||
bio = json['bio'];
|
||||
|
@ -307,7 +304,6 @@ class TetrioPlayer {
|
|||
if (country != null) data['country'] = country;
|
||||
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;
|
||||
|
@ -337,83 +333,15 @@ class TetrioPlayer {
|
|||
if (badstanding != other.badstanding) return false;
|
||||
if (botmaster != other.botmaster) return false;
|
||||
if (connections != other.connections) return false;
|
||||
if (tlSeason1 != other.tlSeason1) return false;
|
||||
if (distinguishment != other.distinguishment) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool checkForRetrivedHistory(covariant TetrioPlayer other) {
|
||||
return tlSeason1!.lessStrictCheck(other.tlSeason1!);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return "$username ($state)";
|
||||
}
|
||||
|
||||
num? getStatByEnum(Stats stat){
|
||||
switch (stat) {
|
||||
case Stats.tr:
|
||||
return tlSeason1?.tr;
|
||||
case Stats.glicko:
|
||||
return tlSeason1?.glicko;
|
||||
case Stats.gxe:
|
||||
return tlSeason1?.gxe;
|
||||
case Stats.s1tr:
|
||||
return tlSeason1?.s1tr;
|
||||
case Stats.rd:
|
||||
return tlSeason1?.rd;
|
||||
case Stats.gp:
|
||||
return tlSeason1?.gamesPlayed;
|
||||
case Stats.gw:
|
||||
return tlSeason1?.gamesWon;
|
||||
case Stats.wr:
|
||||
return tlSeason1?.winrate;
|
||||
case Stats.apm:
|
||||
return tlSeason1?.apm;
|
||||
case Stats.pps:
|
||||
return tlSeason1?.pps;
|
||||
case Stats.vs:
|
||||
return tlSeason1?.vs;
|
||||
case Stats.app:
|
||||
return tlSeason1?.nerdStats?.app;
|
||||
case Stats.dss:
|
||||
return tlSeason1?.nerdStats?.dss;
|
||||
case Stats.dsp:
|
||||
return tlSeason1?.nerdStats?.dsp;
|
||||
case Stats.appdsp:
|
||||
return tlSeason1?.nerdStats?.appdsp;
|
||||
case Stats.vsapm:
|
||||
return tlSeason1?.nerdStats?.vsapm;
|
||||
case Stats.cheese:
|
||||
return tlSeason1?.nerdStats?.cheese;
|
||||
case Stats.gbe:
|
||||
return tlSeason1?.nerdStats?.gbe;
|
||||
case Stats.nyaapp:
|
||||
return tlSeason1?.nerdStats?.nyaapp;
|
||||
case Stats.area:
|
||||
return tlSeason1?.nerdStats?.area;
|
||||
case Stats.eTR:
|
||||
return tlSeason1?.estTr?.esttr;
|
||||
case Stats.acceTR:
|
||||
return tlSeason1?.esttracc;
|
||||
case Stats.acceTRabs:
|
||||
return tlSeason1?.esttracc?.abs();
|
||||
case Stats.opener:
|
||||
return tlSeason1?.playstyle?.opener;
|
||||
case Stats.plonk:
|
||||
return tlSeason1?.playstyle?.plonk;
|
||||
case Stats.infDS:
|
||||
return tlSeason1?.playstyle?.infds;
|
||||
case Stats.stride:
|
||||
return tlSeason1?.playstyle?.stride;
|
||||
case Stats.stridemMinusPlonk:
|
||||
return tlSeason1?.playstyle != null ? tlSeason1!.playstyle!.stride - tlSeason1!.playstyle!.plonk : null;
|
||||
case Stats.openerMinusInfDS:
|
||||
return tlSeason1?.playstyle != null ? tlSeason1!.playstyle!.opener - tlSeason1!.playstyle!.infds : null;
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => state.hashCode;
|
||||
|
||||
|
@ -444,7 +372,7 @@ class Summaries{
|
|||
if (json['zenithex']['record'] != null) zenithEx = RecordSingle.fromJson(json['zenithex']['record'], json['zenithex']['rank'], json['zenithex']['rank_local']);
|
||||
if (json['zenithex']['best']['record'] != null) zenithCareerBest = RecordSingle.fromJson(json['zenithex']['best']['record'], json['zenith']['best']['rank'], -1);
|
||||
achievements = [for (var achievement in json['achievements']) Achievement.fromJson(achievement)];
|
||||
league = TetraLeague.fromJson(json['league'], DateTime.now());
|
||||
league = TetraLeague.fromJson(json['league'], DateTime.now(), currentSeason, i);
|
||||
zen = TetrioZen.fromJson(json['zen']);
|
||||
}
|
||||
}
|
||||
|
@ -1373,6 +1301,7 @@ class EndContextMulti {
|
|||
}
|
||||
|
||||
class TetraLeague {
|
||||
late String id;
|
||||
late DateTime timestamp;
|
||||
late int gamesPlayed;
|
||||
late int gamesWon;
|
||||
|
@ -1397,10 +1326,11 @@ class TetraLeague {
|
|||
NerdStats? nerdStats;
|
||||
EstTr? estTr;
|
||||
Playstyle? playstyle;
|
||||
List? records;
|
||||
late int season;
|
||||
|
||||
TetraLeague(
|
||||
{required this.timestamp,
|
||||
{required this.id,
|
||||
required this.timestamp,
|
||||
required this.gamesPlayed,
|
||||
required this.gamesWon,
|
||||
required this.bestRank,
|
||||
|
@ -1421,7 +1351,7 @@ class TetraLeague {
|
|||
this.apm,
|
||||
this.pps,
|
||||
this.vs,
|
||||
this.records}){
|
||||
required this.season}){
|
||||
nerdStats = (apm != null && pps != null && vs != null) ? NerdStats(apm!, pps!, vs!) : null;
|
||||
estTr = (nerdStats != null) ? EstTr(apm!, pps!, vs!, 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;
|
||||
|
@ -1430,8 +1360,10 @@ class TetraLeague {
|
|||
double get winrate => gamesWon / gamesPlayed;
|
||||
double get s1tr => gxe * 250;
|
||||
|
||||
TetraLeague.fromJson(Map<String, dynamic> json, ts) {
|
||||
TetraLeague.fromJson(Map<String, dynamic> json, ts, int s, String i) {
|
||||
timestamp = ts;
|
||||
season = s;
|
||||
id = i;
|
||||
gamesPlayed = json['gamesplayed'] ?? 0;
|
||||
gamesWon = json['gameswon'] ?? 0;
|
||||
tr = json['tr'] != null ? json['tr'].toDouble() : json['rating'] != null ? json['rating'].toDouble() : -1;
|
||||
|
@ -1470,25 +1402,29 @@ class TetraLeague {
|
|||
|
||||
Map<String, dynamic> toJson() {
|
||||
final Map<String, dynamic> data = <String, dynamic>{};
|
||||
data['id'] = id;
|
||||
data['timestamp'] = timestamp.millisecondsSinceEpoch;
|
||||
if (gamesPlayed > 0) data['gamesplayed'] = gamesPlayed;
|
||||
if (gamesWon > 0) data['gameswon'] = gamesWon;
|
||||
if (tr >= 0) data['tr'] = tr;
|
||||
if (glicko != null) data['glicko'] = glicko;
|
||||
if (gxe != -1) data['gxe'] = gxe;
|
||||
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;
|
||||
if (decaying) data['decaying'] = decaying;
|
||||
if (decaying) data['decaying'] = decaying ? 1 : 0;
|
||||
if (standing >= 0) data['standing'] = standing;
|
||||
if (!rankCutoffs.containsValue(percentile)) data['percentile'] = percentile;
|
||||
data['percentile'] = percentile;
|
||||
if (standingLocal >= 0) data['standing_local'] = standingLocal;
|
||||
if (prevRank != null) data['prev_rank'] = prevRank;
|
||||
if (prevAt >= 0) data['prev_at'] = prevAt;
|
||||
if (nextRank != null) data['next_rank'] = nextRank;
|
||||
if (nextAt >= 0) data['next_at'] = nextAt;
|
||||
if (percentileRank != rank) data['percentile_rank'] = percentileRank;
|
||||
data['percentile_rank'] = percentileRank;
|
||||
data['season'] = season;
|
||||
return data;
|
||||
}
|
||||
}
|
||||
|
@ -2193,7 +2129,7 @@ class TetrioPlayersLeaderboard {
|
|||
avgInfDS /= filtredLeaderboard.length;
|
||||
avgGamesPlayed = (totalGamesPlayed / filtredLeaderboard.length).floor();
|
||||
avgGamesWon = (totalGamesWon / filtredLeaderboard.length).floor();
|
||||
return [TetraLeague(timestamp: DateTime.now(), apm: avgAPM, pps: avgPPS, vs: avgVS, gxe: avgGlixare, glicko: avgGlicko, rd: avgRD, gamesPlayed: avgGamesPlayed, gamesWon: avgGamesWon, bestRank: rank, decaying: false, tr: avgTR, rank: rank == "" ? "z" : rank, percentileRank: rank, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1),
|
||||
return [TetraLeague(id: "", timestamp: DateTime.now(), apm: avgAPM, pps: avgPPS, vs: avgVS, gxe: avgGlixare, glicko: avgGlicko, rd: avgRD, gamesPlayed: avgGamesPlayed, gamesWon: avgGamesWon, bestRank: rank, decaying: false, tr: avgTR, rank: rank == "" ? "z" : rank, percentileRank: rank, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1, season: currentSeason),
|
||||
{
|
||||
"everyone": rank == "",
|
||||
"totalGamesPlayed": totalGamesPlayed,
|
||||
|
@ -2375,7 +2311,7 @@ class TetrioPlayersLeaderboard {
|
|||
"entries": filtredLeaderboard
|
||||
}];
|
||||
}else{
|
||||
return [TetraLeague(timestamp: DateTime.now(), apm: 0, pps: 0, vs: 0, glicko: 0, rd: noTrRd, gamesPlayed: 0, gamesWon: 0, bestRank: rank, decaying: false, tr: 0, rank: rank, percentileRank: rank, gxe: -1, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1),
|
||||
return [TetraLeague(id: "", timestamp: DateTime.now(), apm: 0, pps: 0, vs: 0, glicko: 0, rd: noTrRd, gamesPlayed: 0, gamesWon: 0, bestRank: rank, decaying: false, tr: 0, rank: rank, percentileRank: rank, gxe: -1, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1, season: currentSeason),
|
||||
{"players": filtredLeaderboard.length, "lowestTR": 0, "toEnterTR": 0, "toEnterGlicko": 0}];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,14 +39,14 @@ ThemeData theme = ThemeData(
|
|||
shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.horizontal(left: Radius.circular(12.0), right: Radius.circular(12.0)))),
|
||||
elevation: WidgetStatePropertyAll(8.0)
|
||||
),
|
||||
chipTheme: ChipThemeData(
|
||||
chipTheme: const ChipThemeData(
|
||||
side: BorderSide(color: Colors.transparent),
|
||||
),
|
||||
segmentedButtonTheme: SegmentedButtonThemeData(
|
||||
style: ButtonStyle(
|
||||
side: WidgetStatePropertyAll(BorderSide(color: Colors.transparent)),
|
||||
surfaceTintColor: WidgetStatePropertyAll(Colors.cyanAccent),
|
||||
iconColor: WidgetStatePropertyAll(Colors.cyanAccent),
|
||||
side: const WidgetStatePropertyAll(BorderSide(color: Colors.transparent)),
|
||||
surfaceTintColor: const WidgetStatePropertyAll(Colors.cyanAccent),
|
||||
iconColor: const WidgetStatePropertyAll(Colors.cyanAccent),
|
||||
shadowColor: WidgetStatePropertyAll(Colors.cyanAccent.shade200),
|
||||
)
|
||||
),
|
||||
|
|
|
@ -33,6 +33,7 @@ class DB {
|
|||
await db.execute(createTetrioUsersToTrack);
|
||||
await db.execute(createTetrioTLRecordsTable);
|
||||
await db.execute(createTetrioTLReplayStats);
|
||||
await db.execute(createTetrioLeagueTable);
|
||||
} on MissingPlatformDirectoryException {
|
||||
throw UnableToGetDocuments();
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import 'dart:convert';
|
|||
import 'dart:developer' as developer;
|
||||
import 'dart:io';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:sqflite/sql.dart';
|
||||
import 'package:tetra_stats/data_objects/tetra_stats.dart';
|
||||
import 'package:tetra_stats/data_objects/tetrio_multiplayer_replay.dart';
|
||||
import 'package:tetra_stats/main.dart' show packageInfo;
|
||||
|
@ -21,6 +22,7 @@ const String tetrioUsersTable = "tetrioUsers";
|
|||
const String tetrioUsersToTrackTable = "tetrioUsersToTrack";
|
||||
const String tetraLeagueMatchesTable = "tetrioAlphaLeagueMathces";
|
||||
const String tetrioTLReplayStatsTable = "tetrioTLReplayStats";
|
||||
const String tetrioLeagueTable = "tetrioLeague";
|
||||
const String idCol = "id";
|
||||
const String replayID = "replayId";
|
||||
const String nickCol = "nickname";
|
||||
|
@ -67,6 +69,33 @@ const String createTetrioTLReplayStats = '''
|
|||
PRIMARY KEY("id")
|
||||
)
|
||||
''';
|
||||
const String createTetrioLeagueTable = '''
|
||||
CREATE TABLE IF NOT EXISTS "tetrioLeague" (
|
||||
"id" TEXT NOT NULL,
|
||||
"timestamp" INTEGER NOT NULL,
|
||||
"gamesplayed" INTEGER NOT NULL DEFAULT 0,
|
||||
"gameswon" INTEGER NOT NULL DEFAULT 0,
|
||||
"tr" REAL,
|
||||
"glicko" REAL,
|
||||
"rd" REAL,
|
||||
"gxe" REAL,
|
||||
"rank" TEXT NOT NULL DEFAULT 'z',
|
||||
"bestrank" TEXT NOT NULL DEFAULT 'z',
|
||||
"apm" REAL,
|
||||
"pps" REAL,
|
||||
"vs" REAL,
|
||||
"decaying" INTEGER NOT NULL DEFAULT 0,
|
||||
"standing" INTEGER NOT NULL DEFAULT -1,
|
||||
"standing_local" INTEGER NOT NULL DEFAULT -1,
|
||||
"percentile" REAL NOT NULL,
|
||||
"prev_rank" TEXT,
|
||||
"prev_at" INTEGER NOT NULL DEFAULT -1,
|
||||
"next_rank" TEXT,
|
||||
"next_at" INTEGER NOT NULL DEFAULT -1,
|
||||
"percentile_rank" TEXT NOT NULL DEFAULT 'z',
|
||||
"season" INTEGER NOT NULL DEFAULT 1
|
||||
)
|
||||
''';
|
||||
|
||||
class CacheController {
|
||||
late Map<String, dynamic> _cache;
|
||||
|
@ -546,7 +575,7 @@ class TetrioService extends DB {
|
|||
|
||||
/// Retrieves Tetra League history from p1nkl0bst3r api for a player with given [id]. Returns a list of states
|
||||
/// (state = instance of [TetrioPlayer] at some point of time). Can throw an exception if fails to retrieve data.
|
||||
Future<List<TetrioPlayer>> fetchAndsaveTLHistory(String id) async {
|
||||
Future<List<TetraLeague>> fetchAndsaveTLHistory(String id) async {
|
||||
Uri url;
|
||||
if (kIsWeb) {
|
||||
url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "TLHistory", "user": id});
|
||||
|
@ -558,27 +587,14 @@ class TetrioService extends DB {
|
|||
|
||||
switch (response.statusCode) {
|
||||
case 200:
|
||||
await ensureDbIsOpen();
|
||||
final db = getDatabaseOrThrow();
|
||||
// that one api returns csv instead of json
|
||||
List<List<dynamic>> csv = const CsvToListConverter().convert(response.body)..removeAt(0);
|
||||
List<TetrioPlayer> history = [];
|
||||
// doesn't return nickname, need to retrieve it separately
|
||||
String nick = await getNicknameByID(id);
|
||||
List<TetraLeague> history = [];
|
||||
for (List<dynamic> entry in csv){ // each entry is one state
|
||||
TetrioPlayer state = TetrioPlayer(
|
||||
userId: id,
|
||||
username: nick,
|
||||
role: "p1nkl0bst3r",
|
||||
state: DateTime.parse(entry[9]),
|
||||
badges: [],
|
||||
friendCount: -1,
|
||||
gamesPlayed: -1,
|
||||
gamesWon: -1,
|
||||
gameTime: const Duration(seconds: -1),
|
||||
xp: -1,
|
||||
supporterTier: 0,
|
||||
verified: false,
|
||||
connections: null,
|
||||
tlSeason1: TetraLeague(
|
||||
TetraLeague state = TetraLeague(
|
||||
id: id,
|
||||
timestamp: DateTime.parse(entry[9]),
|
||||
apm: entry[6] != '' ? entry[6] : null,
|
||||
pps: entry[7] != '' ? entry[7] : null,
|
||||
|
@ -597,24 +613,12 @@ class TetrioService extends DB {
|
|||
standing: -1,
|
||||
standingLocal: -1,
|
||||
nextAt: -1,
|
||||
prevAt: -1
|
||||
),
|
||||
prevAt: -1,
|
||||
season: 1
|
||||
);
|
||||
history.add(state);
|
||||
await db.insert(tetrioLeagueTable, state.toJson(), conflictAlgorithm: ConflictAlgorithm.replace);
|
||||
}
|
||||
|
||||
// trying to dump it to local DB
|
||||
await ensureDbIsOpen();
|
||||
final db = getDatabaseOrThrow();
|
||||
List<TetrioPlayer> states = await getPlayer(id);
|
||||
if (states.isEmpty) await createPlayer(history.first);
|
||||
states.insertAll(0, history.reversed);
|
||||
final Map<String, dynamic> statesJson = {};
|
||||
for (var e in states) { // making one big json out of this list
|
||||
statesJson.addEntries({(e.state.millisecondsSinceEpoch ~/ 1000).toString(): e.toJson()}.entries);
|
||||
}
|
||||
// and putting it to local DB
|
||||
await db.update(tetrioUsersTable, {idCol: id, nickCol: nick, statesCol: jsonEncode(statesJson)}, where: '$idCol = ?', whereArgs: [id]);
|
||||
return history;
|
||||
case 404:
|
||||
developer.log("fetchTLHistory: Probably, history doesn't exist", name: "services/tetrio_crud", error: response.statusCode);
|
||||
|
@ -1057,7 +1061,10 @@ class TetrioService extends DB {
|
|||
if (results.isNotEmpty) {
|
||||
throw TetrioPlayerAlreadyExist();
|
||||
}
|
||||
await db.insert(tetrioUsersTable, {idCol: tetrioPlayer.userId, nickCol: tetrioPlayer.username}, conflictAlgorithm: ConflictAlgorithm.replace);
|
||||
db.insert(tetrioUsersToTrackTable, {idCol: tetrioPlayer.userId});
|
||||
_players[tetrioPlayer.userId] = tetrioPlayer.username;
|
||||
_tetrioStreamController.add(_players);
|
||||
}
|
||||
|
||||
/// Returns bool, which tells whether is given [id] is in [tetrioUsersToTrackTable].
|
||||
|
@ -1081,6 +1088,7 @@ class TetrioService extends DB {
|
|||
await ensureDbIsOpen();
|
||||
final db = getDatabaseOrThrow();
|
||||
final deletedPlayer = await db.delete(tetrioUsersToTrackTable, where: '$idCol = ?', whereArgs: [id.toLowerCase()]);
|
||||
await db.delete(tetrioUsersTable, where: '$idCol = ?', whereArgs: [id.toLowerCase()]);
|
||||
if (deletedPlayer != 1) {
|
||||
throw CouldNotDeletePlayer();
|
||||
} else {
|
||||
|
@ -1089,72 +1097,67 @@ class TetrioService extends DB {
|
|||
}
|
||||
}
|
||||
|
||||
/// Saves state (which is [tetrioPlayer]) to the local database.
|
||||
Future<void> storeState(TetrioPlayer tetrioPlayer) async {
|
||||
// if tetrio player doesn't have entry in database - just calling different function
|
||||
List<TetrioPlayer> states = await getPlayer(tetrioPlayer.userId);
|
||||
if (states.isEmpty) {
|
||||
await createPlayer(tetrioPlayer);
|
||||
return;
|
||||
}
|
||||
|
||||
// we not going to add state, that is same, as the previous
|
||||
if (!states.last.isSameState(tetrioPlayer)) states.add(tetrioPlayer);
|
||||
|
||||
// Making map of the states
|
||||
final Map<String, dynamic> statesJson = {};
|
||||
for (var e in states) {
|
||||
// Saving in format: {"unix_seconds": json_of_state}
|
||||
statesJson.addEntries({(e.state.millisecondsSinceEpoch ~/ 1000).toString(): e.toJson()}.entries);
|
||||
}
|
||||
|
||||
// Rewrite our database
|
||||
Future<List<TetraLeague>> getStates(String userID, int season) async {
|
||||
await ensureDbIsOpen();
|
||||
final db = getDatabaseOrThrow();
|
||||
await db.update(tetrioUsersTable, {idCol: tetrioPlayer.userId, nickCol: tetrioPlayer.username, statesCol: jsonEncode(statesJson)},
|
||||
where: '$idCol = ?', whereArgs: [tetrioPlayer.userId]);
|
||||
List<Map> query = await db.query(tetrioLeagueTable, where: '"id" = ? AND "season" = ?', whereArgs: [userID, season]);
|
||||
List<TetraLeague> result = [];
|
||||
for (var entry in query){
|
||||
result.add(TetraLeague.fromJson(entry as Map<String, dynamic>, entry["timestamp"], entry["season"], entry["id"]));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/// Saves state (which is [TetraLeague]) to the local database.
|
||||
Future<void> storeState(TetraLeague league) async {
|
||||
await ensureDbIsOpen();
|
||||
final db = getDatabaseOrThrow();
|
||||
List<Map> test = await db.query(tetrioLeagueTable, where: '"id" = ? AND "gamesplayed" = ? AND "rd" = ?', whereArgs: [league.id, league.gamesPlayed, league.rd]);
|
||||
if (test.isEmpty) {
|
||||
await db.insert(tetrioLeagueTable, league.toJson());
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove state (which is [tetrioPlayer]) from the local database
|
||||
Future<void> deleteState(TetrioPlayer tetrioPlayer) async {
|
||||
await ensureDbIsOpen();
|
||||
final db = getDatabaseOrThrow();
|
||||
List<TetrioPlayer> states = await getPlayer(tetrioPlayer.userId);
|
||||
// removing state from map that contain every state of each user
|
||||
states.removeWhere((element) => element.state == tetrioPlayer.state);
|
||||
// Future<void> deleteState(TetrioPlayer tetrioPlayer) async {
|
||||
// await ensureDbIsOpen();
|
||||
// final db = getDatabaseOrThrow();
|
||||
// //List<TetrioPlayer> states = await getPlayer(tetrioPlayer.userId);
|
||||
// // removing state from map that contain every state of each user
|
||||
// states.removeWhere((element) => element.state == tetrioPlayer.state);
|
||||
|
||||
// Making map of the states (without deleted one)
|
||||
final Map<String, dynamic> statesJson = {};
|
||||
for (var e in states) {
|
||||
statesJson.addEntries({(e.state.millisecondsSinceEpoch ~/ 1000).toString(): e.toJson()}.entries);
|
||||
}
|
||||
// Rewriting database entry with new json
|
||||
await db.update(tetrioUsersTable, {idCol: tetrioPlayer.userId, nickCol: tetrioPlayer.username, statesCol: jsonEncode(statesJson)},
|
||||
where: '$idCol = ?', whereArgs: [tetrioPlayer.userId]);
|
||||
_tetrioStreamController.add(_players);
|
||||
}
|
||||
// // Making map of the states (without deleted one)
|
||||
// final Map<String, dynamic> statesJson = {};
|
||||
// // for (var e in states) {
|
||||
// // statesJson.addEntries({(e.state.millisecondsSinceEpoch ~/ 1000).toString(): e.toJson()}.entries);
|
||||
// // }
|
||||
// // Rewriting database entry with new json
|
||||
// await db.update(tetrioUsersTable, {idCol: tetrioPlayer.userId, nickCol: tetrioPlayer.username, statesCol: jsonEncode(statesJson)},
|
||||
// where: '$idCol = ?', whereArgs: [tetrioPlayer.userId]);
|
||||
// _tetrioStreamController.add(_players);
|
||||
// }
|
||||
|
||||
/// Returns list of all states of player with given [id] from database. Can return empty list if player
|
||||
/// was not found.
|
||||
Future<List<TetrioPlayer>> getPlayer(String id) async {
|
||||
await ensureDbIsOpen();
|
||||
final db = getDatabaseOrThrow();
|
||||
List<TetrioPlayer> states = [];
|
||||
final results = await db.query(tetrioUsersTable, limit: 1, where: '$idCol = ?', whereArgs: [id.toLowerCase()]);
|
||||
if (results.isEmpty) {
|
||||
return states; // it empty
|
||||
} else {
|
||||
dynamic rawStates = results.first['jsonStates'] as String;
|
||||
rawStates = json.decode(rawStates);
|
||||
// recreating objects of states
|
||||
rawStates.forEach((k, v) => states.add(TetrioPlayer.fromJson(v, DateTime.fromMillisecondsSinceEpoch(int.parse(k) * 1000), id, results.first[nickCol] as String)));
|
||||
// updating the stream
|
||||
_players.removeWhere((key, value) => key == id);
|
||||
_players.addEntries({states.last.userId: states.last.username}.entries);
|
||||
_tetrioStreamController.add(_players);
|
||||
return states;
|
||||
}
|
||||
}
|
||||
// Future<List<TetrioPlayer>> getPlayer(String id) async {
|
||||
// await ensureDbIsOpen();
|
||||
// final db = getDatabaseOrThrow();
|
||||
// List<TetrioPlayer> states = [];
|
||||
// final results = await db.query(tetrioUsersTable, limit: 1, where: '$idCol = ?', whereArgs: [id.toLowerCase()]);
|
||||
// if (results.isEmpty) {
|
||||
// return states; // it empty
|
||||
// } else {
|
||||
// dynamic rawStates = results.first['jsonStates'] as String;
|
||||
// rawStates = json.decode(rawStates);
|
||||
// // recreating objects of states
|
||||
// rawStates.forEach((k, v) => states.add(TetrioPlayer.fromJson(v, DateTime.fromMillisecondsSinceEpoch(int.parse(k) * 1000), id, results.first[nickCol] as String)));
|
||||
// // updating the stream
|
||||
// _players.removeWhere((key, value) => key == id);
|
||||
// _players.addEntries({states.last.userId: states.last.username}.entries);
|
||||
// _tetrioStreamController.add(_players);
|
||||
// return states;
|
||||
// }
|
||||
// }
|
||||
|
||||
/// Retrieves general stats of [user] (nickname or id) from Tetra Channel api. Returns [TetrioPlayer] object of this user.
|
||||
/// If [isItDiscordID] is true, function expects [user] to be a discord user id. Throws an exception if fails to retrieve.
|
||||
|
|
|
@ -85,6 +85,7 @@ class CompareState extends State<CompareView> {
|
|||
theRedSide = [null,
|
||||
null,
|
||||
Summaries(user, TetraLeague(
|
||||
id: "",
|
||||
timestamp: DateTime.now(),
|
||||
apm: apm,
|
||||
pps: pps,
|
||||
|
@ -102,7 +103,7 @@ class CompareState extends State<CompareView> {
|
|||
standing: -1,
|
||||
standingLocal: -1,
|
||||
nextAt: -1,
|
||||
prevAt: -1), TetrioZen(level: 0, score: 0))];
|
||||
prevAt: -1, season: currentSeason), TetrioZen(level: 0, score: 0))];
|
||||
return setState(() {});
|
||||
}
|
||||
var player = await teto.fetchPlayer(user);
|
||||
|
@ -132,9 +133,11 @@ class CompareState extends State<CompareView> {
|
|||
_justUpdate();
|
||||
}
|
||||
|
||||
void changeRedSide(TetrioPlayer user) {
|
||||
setState(() {theRedSide[0] = user;
|
||||
theRedSide[2].league = user.tlSeason1;});
|
||||
void changeRedSide(TetraLeague user) {
|
||||
setState(() {
|
||||
//theRedSide[0] = user;
|
||||
theRedSide[2].league = user;
|
||||
});
|
||||
}
|
||||
|
||||
void fetchGreenSide(String user) async {
|
||||
|
@ -161,6 +164,7 @@ class CompareState extends State<CompareView> {
|
|||
theGreenSide = [null,
|
||||
null,
|
||||
Summaries(user, TetraLeague(
|
||||
id: "",
|
||||
timestamp: DateTime.now(),
|
||||
apm: apm,
|
||||
pps: pps,
|
||||
|
@ -178,7 +182,7 @@ class CompareState extends State<CompareView> {
|
|||
standing: -1,
|
||||
standingLocal: -1,
|
||||
nextAt: -1,
|
||||
prevAt: -1), TetrioZen(level: 0, score: 0))];
|
||||
prevAt: -1, season: currentSeason), TetrioZen(level: 0, score: 0))];
|
||||
return setState(() {});
|
||||
}
|
||||
var player = await teto.fetchPlayer(user);
|
||||
|
@ -208,9 +212,11 @@ class CompareState extends State<CompareView> {
|
|||
_justUpdate();
|
||||
}
|
||||
|
||||
void changeGreenSide(TetrioPlayer user) {
|
||||
setState(() {theGreenSide[0] = user;
|
||||
theGreenSide[2].league = user.tlSeason1;});
|
||||
void changeGreenSide(TetraLeague user) {
|
||||
setState(() {
|
||||
//theGreenSide[0] = user;
|
||||
theGreenSide[2].league = user;
|
||||
});
|
||||
}
|
||||
|
||||
double getWinrateByTR(double yourGlicko, double yourRD, double notyourGlicko,double notyourRD) {
|
||||
|
@ -955,7 +961,7 @@ class CompareState extends State<CompareView> {
|
|||
const Divider(),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 16),
|
||||
child: Text("${t.quickPlay} ${t.expert} ${t.nerdStats}", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)),
|
||||
child: Text("${t.quickPlay} ${t.expert} ${t.nerdStats}", style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)),
|
||||
),
|
||||
CompareThingy(
|
||||
label: "APP",
|
||||
|
|
|
@ -216,15 +216,15 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
if (everyone != null && summaries.league.gamesPlayed > 9) rankAverages = everyone?.averages[summaries.league.percentileRank]?[0];
|
||||
|
||||
// Making list of Tetra League matches
|
||||
//bool isTracking = await teto.isPlayerTracking(me.userId);
|
||||
bool isTracking = await teto.isPlayerTracking(me.userId);
|
||||
List<TetrioPlayer> states = [];
|
||||
TetraLeague? compareWith;
|
||||
Set<TetraLeague> uniqueTL = {};
|
||||
List<TetraLeagueAlphaRecord> storedRecords = await teto.getTLMatchesbyPlayerID(me.userId); // get old matches
|
||||
// if (isTracking){ // if tracked - save data to local DB
|
||||
// await teto.storeState(me);
|
||||
// //await teto.saveTLMatchesFromStream(tlStream);
|
||||
// }
|
||||
if (isTracking){ // if tracked - save data to local DB
|
||||
await teto.storeState(summaries.league);
|
||||
//await teto.saveTLMatchesFromStream(tlStream);
|
||||
}
|
||||
TetraLeagueAlphaStream? oldMatches;
|
||||
// building list of TL matches
|
||||
if(fetchTLmatches) {
|
||||
|
@ -271,11 +271,11 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
}
|
||||
}
|
||||
|
||||
states.addAll(await teto.getPlayer(me.userId));
|
||||
for (var element in states) { // For graphs I need only unique entries
|
||||
if (element.tlSeason1 != null && uniqueTL.isNotEmpty && uniqueTL.last != element.tlSeason1) uniqueTL.add(element.tlSeason1!);
|
||||
if (uniqueTL.isEmpty) uniqueTL.add(summaries.league);
|
||||
}
|
||||
//states.addAll(await teto.getPlayer(me.userId));
|
||||
// for (var element in states) { // For graphs I need only unique entries
|
||||
// if (element.tlSeason1 != null && uniqueTL.isNotEmpty && uniqueTL.last != element.tlSeason1) uniqueTL.add(element.tlSeason1!);
|
||||
// if (uniqueTL.isEmpty) uniqueTL.add(summaries.league);
|
||||
// }
|
||||
// Also i need previous Tetra League State for comparison if avaliable
|
||||
if (uniqueTL.length >= 2){
|
||||
compareWith = uniqueTL.toList().elementAtOrNull(uniqueTL.length - 2);
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:flutter_svg/flutter_svg.dart';
|
|||
import 'package:intl/intl.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/gen/strings.g.dart';
|
||||
import 'package:tetra_stats/services/crud_exceptions.dart';
|
||||
import 'package:tetra_stats/utils/colors_functions.dart';
|
||||
|
@ -286,11 +287,11 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
}
|
||||
}
|
||||
|
||||
states.addAll(await teto.getPlayer(widget.searchFor));
|
||||
for (var element in states) {
|
||||
if (element.tlSeason1 != null && uniqueTL.isNotEmpty && uniqueTL.last != element.tlSeason1) uniqueTL.add(element.tlSeason1!);
|
||||
if (uniqueTL.isEmpty) uniqueTL.add(element.tlSeason1!);
|
||||
}
|
||||
//states.addAll(await teto.getPlayer(widget.searchFor));
|
||||
// for (var element in states) {
|
||||
// if (element.tlSeason1 != null && uniqueTL.isNotEmpty && uniqueTL.last != element.tlSeason1) uniqueTL.add(element.tlSeason1!);
|
||||
// if (uniqueTL.isEmpty) uniqueTL.add(element.tlSeason1!);
|
||||
// }
|
||||
|
||||
if (uniqueTL.length >= 2){
|
||||
chartsData = <DropdownMenuItem<List<_HistoryChartSpot>>>[ // Dumping charts data into dropdown menu items, while cheking if every entry is valid
|
||||
|
@ -511,9 +512,10 @@ class FetchResults{
|
|||
bool success;
|
||||
TetrioPlayer? player;
|
||||
Summaries? summaries;
|
||||
Cutoffs? cutoffs;
|
||||
Exception? exception;
|
||||
|
||||
FetchResults(this.success, this.player, this.summaries, this.exception);
|
||||
FetchResults(this.success, this.player, this.summaries, this.cutoffs, this.exception);
|
||||
}
|
||||
|
||||
class RecordSummary extends StatelessWidget{
|
||||
|
@ -613,10 +615,17 @@ class _DestinationHomeState extends State<DestinationHome> {
|
|||
player = await teto.fetchPlayer(widget.searchFor); // Otherwise it's probably a user id or username
|
||||
}
|
||||
}on TetrioPlayerNotExist{
|
||||
return FetchResults(false, null, null, TetrioPlayerNotExist());
|
||||
return FetchResults(false, null, null, null, TetrioPlayerNotExist());
|
||||
}
|
||||
Summaries summaries = await teto.fetchSummaries(player.userId);
|
||||
return FetchResults(true, player, summaries, null);
|
||||
late Summaries summaries;
|
||||
late Cutoffs cutoffs;
|
||||
List<dynamic> requests = await Future.wait([
|
||||
teto.fetchSummaries(player.userId),
|
||||
teto.fetchCutoffsBeanserver(),
|
||||
]);
|
||||
summaries = requests[0];
|
||||
cutoffs = requests[1];
|
||||
return FetchResults(true, player, summaries, cutoffs, null);
|
||||
}
|
||||
|
||||
Widget getOverviewCard(Summaries summaries){
|
||||
|
@ -645,7 +654,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
|||
children: [
|
||||
const Text("Tetra League", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28, height: 0.9)),
|
||||
const Divider(color: Color.fromARGB(50, 158, 158, 158)),
|
||||
TLRatingThingy(userID: "", tlData: summaries.league),
|
||||
TLRatingThingy(userID: "", tlData: summaries.league, showPositions: true),
|
||||
const Divider(color: Color.fromARGB(50, 158, 158, 158)),
|
||||
Text("${summaries.league.apm != null ? f2.format(summaries.league.apm) : "-.--"} APM • ${summaries.league.pps != null ? f2.format(summaries.league.pps) : "-.--"} PPS • ${summaries.league.vs != null ? f2.format(summaries.league.vs) : "-.--"} VS • ${summaries.league.nerdStats != null ? f2.format(summaries.league.nerdStats!.app) : "-.--"} APP • ${summaries.league.nerdStats != null ? f2.format(summaries.league.nerdStats!.vsapm) : "-.--"} VS/APM", style: const TextStyle(color: Colors.grey))
|
||||
],
|
||||
|
@ -827,7 +836,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget getTetraLeagueCard(TetraLeague data){
|
||||
Widget getTetraLeagueCard(TetraLeague data, Cutoffs? cutoffs){
|
||||
return Column(
|
||||
children: [
|
||||
Card(
|
||||
|
@ -845,7 +854,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
|||
),
|
||||
),
|
||||
),
|
||||
TetraLeagueThingy(league: data),
|
||||
TetraLeagueThingy(league: data, cutoffs: cutoffs),
|
||||
if (data.nerdStats != null) Card(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
|
@ -1514,7 +1523,7 @@ class _DestinationHomeState extends State<DestinationHome> {
|
|||
child: switch (rightCard){
|
||||
Cards.overview => getOverviewCard(snapshot.data!.summaries!),
|
||||
Cards.tetraLeague => switch (cardMod){
|
||||
CardMod.info => getTetraLeagueCard(snapshot.data!.summaries!.league),
|
||||
CardMod.info => getTetraLeagueCard(snapshot.data!.summaries!.league, snapshot.data!.cutoffs),
|
||||
CardMod.records => getRecentTLrecords(widget.constraints),
|
||||
_ => const Center(child: Text("huh?"))
|
||||
},
|
||||
|
@ -2340,8 +2349,9 @@ class _SearchDrawerState extends State<SearchDrawer> {
|
|||
|
||||
class TetraLeagueThingy extends StatelessWidget{
|
||||
final TetraLeague league;
|
||||
final Cutoffs? cutoffs;
|
||||
|
||||
const TetraLeagueThingy({super.key, required this.league});
|
||||
const TetraLeagueThingy({super.key, required this.league, this.cutoffs});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -2349,7 +2359,15 @@ class TetraLeagueThingy extends StatelessWidget{
|
|||
child: Column(
|
||||
children: [
|
||||
TLRatingThingy(userID: "w", tlData: league),
|
||||
TLProgress(tlData: league,),
|
||||
TLProgress(
|
||||
tlData: league,
|
||||
previousRankTRcutoff: cutoffs != null ? cutoffs!.tr[league.rank != "z" ? league.rank : league.percentileRank] : null,
|
||||
nextRankTRcutoff: cutoffs != null ? (league.rank != "z" ? league.rank == "x+" : league.percentileRank == "x+") ? 25000 : cutoffs!.tr[ranks.elementAtOrNull(ranks.indexOf(league.rank != "z" ? league.rank : league.percentileRank)+1)] : null,
|
||||
nextRankTRcutoffTarget: league.rank != "z" ? rankTargets[league.rank] : null,
|
||||
previousRankTRcutoffTarget: (league.rank != "z" && league.rank != "x+") ? rankTargets[ranks.elementAtOrNull(ranks.indexOf(league.rank)+1)] : null,
|
||||
previousGlickoCutoff: cutoffs != null ? cutoffs!.glicko[league.rank != "z" ? league.rank : league.percentileRank] : null,
|
||||
nextRankGlickoCutoff: cutoffs != null ? (league.rank != "z" ? league.rank == "x+" : league.percentileRank == "x+") ? 25000 : cutoffs!.glicko[ranks.elementAtOrNull(ranks.indexOf(league.rank != "z" ? league.rank : league.percentileRank)+1)] : null,
|
||||
),
|
||||
Row(
|
||||
// spacing: 25.0,
|
||||
// alignment: WrapAlignment.spaceAround,
|
||||
|
@ -2809,9 +2827,10 @@ class TLRatingThingy extends StatelessWidget{
|
|||
final TetraLeague tlData;
|
||||
final TetraLeague? oldTl;
|
||||
final double? topTR;
|
||||
final bool? showPositions;
|
||||
final DateTime? lastMatchPlayed;
|
||||
|
||||
const TLRatingThingy({super.key, required this.userID, required this.tlData, this.oldTl, this.topTR, this.lastMatchPlayed});
|
||||
const TLRatingThingy({super.key, required this.userID, required this.tlData, this.oldTl, this.topTR, this.lastMatchPlayed, this.showPositions});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -2893,7 +2912,7 @@ class TLRatingThingy extends StatelessWidget{
|
|||
),
|
||||
],
|
||||
),
|
||||
RichText(
|
||||
if (showPositions == true) RichText(
|
||||
textAlign: TextAlign.start,
|
||||
text: TextSpan(
|
||||
text: "",
|
||||
|
|
|
@ -523,7 +523,7 @@ class _ListEntry extends StatelessWidget {
|
|||
children: [
|
||||
Text(f.format(value),
|
||||
style: const TextStyle(fontSize: 22, height: 0.9)),
|
||||
if (id.isNotEmpty) Text(t.forPlayer(username: username), style: TextStyle(color: Colors.grey, fontWeight: FontWeight.w100),)
|
||||
if (id.isNotEmpty) Text(t.forPlayer(username: username), style: const TextStyle(color: Colors.grey, fontWeight: FontWeight.w100),)
|
||||
],
|
||||
),
|
||||
onTap: id.isNotEmpty
|
||||
|
|
|
@ -4,7 +4,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:intl/intl.dart';
|
||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
||||
import 'package:tetra_stats/gen/strings.g.dart';
|
||||
import 'package:tetra_stats/widgets/tl_thingy.dart';
|
||||
//import 'package:tetra_stats/widgets/tl_thingy.dart';
|
||||
import 'package:tetra_stats/widgets/user_thingy.dart';
|
||||
import 'package:window_manager/window_manager.dart';
|
||||
|
||||
|
@ -58,6 +58,6 @@ class StateState extends State<StateView> {
|
|||
headerSliverBuilder: (context, value) {
|
||||
return [SliverToBoxAdapter(child: UserThingy(player: widget.state, showStateTimestamp: true, setState: _justUpdate))];
|
||||
},
|
||||
body: TLThingy(tl: widget.state.tlSeason1!, userID: widget.state.userId, states: const []))));
|
||||
body: Container())));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -61,14 +61,14 @@ class StatesState extends State<StatesView> {
|
|||
itemBuilder: (context, index) {
|
||||
return ListTile(
|
||||
title: Text(timestamp(widget.states[index].state)),
|
||||
subtitle: Text(t.statesViewEntry(level: widget.states[index].level.toStringAsFixed(2), gameTime: widget.states[index].gameTime, friends: widget.states[index].friendCount, rd: NumberFormat.compact().format(widget.states[index].tlSeason1?.rd??0))),
|
||||
subtitle: Text(t.statesViewEntry(level: widget.states[index].level.toStringAsFixed(2), gameTime: widget.states[index].gameTime, friends: widget.states[index].friendCount, rd: 0)),
|
||||
trailing: IconButton(
|
||||
icon: const Icon(Icons.delete_forever),
|
||||
onPressed: () {
|
||||
DateTime nn = widget.states[index].state;
|
||||
teto.deleteState(widget.states[index]).then((value) => setState(() {
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.stateRemoved(date: timestamp(nn)))));
|
||||
}));
|
||||
// teto.deleteState(widget.states[index]).then((value) => setState(() {
|
||||
// ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.stateRemoved(date: timestamp(nn)))));
|
||||
// }));
|
||||
},
|
||||
),
|
||||
onTap: () {
|
||||
|
|
|
@ -210,7 +210,7 @@ class TLLeaderboardState extends State<TLLeaderboardView> {
|
|||
)
|
||||
);
|
||||
}
|
||||
return Text("end of FutureBuilder");
|
||||
return const Text("end of FutureBuilder");
|
||||
}
|
||||
})),
|
||||
);
|
||||
|
|
|
@ -51,7 +51,7 @@ class TLProgress extends StatelessWidget{
|
|||
]
|
||||
)
|
||||
),
|
||||
Spacer(),
|
||||
const Spacer(),
|
||||
RichText(
|
||||
textAlign: TextAlign.right,
|
||||
text: TextSpan(
|
||||
|
|
|
@ -59,7 +59,7 @@ class TLRatingThingy extends StatelessWidget{
|
|||
if (formatedTR.elementAtOrNull(1) != null) TextSpan(text: decimalSeparator + formatedTR[1]),
|
||||
TextSpan(text: " TR", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28))
|
||||
],
|
||||
} : [TextSpan(text: "---\n", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28, color: Colors.grey)), TextSpan(text: t.gamesUntilRanked(left: 10-tlData.gamesPlayed), style: TextStyle(color: Colors.grey, fontSize: 14)),]
|
||||
} : [TextSpan(text: "---\n", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28, color: Colors.grey)), TextSpan(text: t.gamesUntilRanked(left: 10-tlData.gamesPlayed), style: const TextStyle(color: Colors.grey, fontSize: 14)),]
|
||||
)
|
||||
),
|
||||
if (oldTl != null) Text(
|
||||
|
|
|
@ -22,7 +22,7 @@ var intFDiff = NumberFormat("+#,###.000;-#,###.000");
|
|||
class TLThingy extends StatefulWidget {
|
||||
final TetraLeague tl;
|
||||
final String userID;
|
||||
final List<TetrioPlayer> states;
|
||||
final List<TetraLeague> states;
|
||||
final bool showTitle;
|
||||
final bool bot;
|
||||
final bool guest;
|
||||
|
@ -47,13 +47,13 @@ class _TLThingyState extends State<TLThingy> with TickerProviderStateMixin {
|
|||
late TetraLeague? oldTl;
|
||||
late TetraLeague currentTl;
|
||||
late RangeValues _currentRangeValues;
|
||||
late List<TetrioPlayer> sortedStates;
|
||||
late List<TetraLeague> sortedStates;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_currentRangeValues = const RangeValues(0, 1);
|
||||
sortedStates = widget.states.reversed.toList();
|
||||
oldTl = sortedStates.elementAtOrNull(1)?.tlSeason1;
|
||||
oldTl = sortedStates.elementAtOrNull(1);
|
||||
currentTl = widget.tl;
|
||||
super.initState();
|
||||
}
|
||||
|
@ -95,12 +95,12 @@ class _TLThingyState extends State<TLThingy> with TickerProviderStateMixin {
|
|||
if (values.start.round() == 0){
|
||||
currentTl = widget.tl;
|
||||
}else{
|
||||
currentTl = sortedStates[values.start.round()-1].tlSeason1!;
|
||||
currentTl = sortedStates[values.start.round()-1]!;
|
||||
}
|
||||
if (values.end.round() == 0){
|
||||
oldTl = widget.tl;
|
||||
}else{
|
||||
oldTl = sortedStates[values.end.round()-1].tlSeason1;
|
||||
oldTl = sortedStates[values.end.round()-1];
|
||||
}
|
||||
});
|
||||
},
|
||||
|
|
|
@ -182,7 +182,6 @@ class UserThingy extends StatelessWidget {
|
|||
],),
|
||||
onPressed: () {
|
||||
teto.addPlayerToTrack(player).then((value) => setState());
|
||||
teto.storeState(player);
|
||||
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.becameTracked)));
|
||||
},
|
||||
),
|
||||
|
@ -213,7 +212,7 @@ class UserThingy extends StatelessWidget {
|
|||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => CompareView(greenSide: [player, null, player.tlSeason1], redSide: const [null, null, null], greenMode: Mode.player, redMode: Mode.player),
|
||||
builder: (context) => CompareView(greenSide: [player, null, null], redSide: const [null, null, null], greenMode: Mode.player, redMode: Mode.player),
|
||||
),
|
||||
);
|
||||
},
|
||||
|
|
|
@ -148,7 +148,7 @@ class _ZenithThingyState extends State<ZenithThingy> {
|
|||
const Positioned(left: 25, top: 20, child: Text("otal time", style: TextStyle(fontFamily: "Eurostile Round Extended"))),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 10.0),
|
||||
child: Text("${getMoreNormalTime(record!.stats.finalTime)}", style: TextStyle(
|
||||
child: Text(getMoreNormalTime(record!.stats.finalTime), style: const TextStyle(
|
||||
shadows: textShadow,
|
||||
fontFamily: "Eurostile Round Extended",
|
||||
fontSize: 36,
|
||||
|
|
Loading…
Reference in New Issue