history is fixed, but maaan...

This commit is contained in:
dan63047 2024-09-04 00:07:27 +03:00
parent 9ed6ddb33d
commit 3d28e5a214
4 changed files with 79 additions and 74 deletions

View File

@ -576,7 +576,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<TetraLeague>> 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});
@ -1100,15 +1100,11 @@ class TetrioService extends DB {
}
}
Future<List<TetraLeague>> getStates(String userID, int season) async {
Future<List<TetraLeague>> getStates(String userID, {int? season}) async {
await ensureDbIsOpen();
final db = getDatabaseOrThrow();
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;
List<Map> query = await db.query(tetrioLeagueTable, where: season != null ? '"id" LIKE ? AND "season" = ?' : '"id" LIKE ?', whereArgs: season != null ? ["${userID}%", season] : ["${userID}%"], orderBy: '"id" ASC');
return [for (var entry in query) TetraLeague.fromJson(entry as Map<String, dynamic>, DateTime.fromMillisecondsSinceEpoch(int.parse(entry["id"].substring(24), radix: 16)), entry["season"], entry["id"].substring(0, 24))];
}
/// Saves state (which is [TetraLeague]) to the local database.
@ -1121,14 +1117,6 @@ class TetrioService extends DB {
}
}
Future<List<TetraLeague>> getHistory(String id, {int season = currentSeason}) async {
await ensureDbIsOpen();
final db = getDatabaseOrThrow();
List<Map> raw = await db.query(tetrioLeagueTable, where: '"id" = ? AND "season" = ?', whereArgs: [id, season]);
List<TetraLeague> result = [for (var entry in raw) TetraLeague.fromJson(entry as Map<String, dynamic>, DateTime.fromMillisecondsSinceEpoch(int.parse(entry["id"].substring(24), radix: 16)), entry["season"], entry["id"].substring(0, 24))];
return result;
}
/// Remove state (which is [tetrioPlayer]) from the local database
// Future<void> deleteState(TetrioPlayer tetrioPlayer) async {
// await ensureDbIsOpen();

View File

@ -40,6 +40,7 @@ import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:go_router/go_router.dart';
int _chartsIndex = 0;
int _season = currentSeason-1;
bool _gamesPlayedInsteadOfDateAndTime = false;
late ZoomPanBehavior _zoomPanBehavior;
bool _smooth = false;
@ -73,7 +74,8 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
String _searchFor = "6098518e3d5155e6ec429cdc"; // who we looking for
String _titleNickname = "";
/// Each dropdown menu item contains list of dots for the graph
List<DropdownMenuItem<List<_HistoryChartSpot>>> chartsData = [];
/// chartsData[season-1][chart]
List<List<DropdownMenuItem<List<_HistoryChartSpot>>>> chartsData = [];
//var tableData = <TableRow>[];
final bodyGlobalKey = GlobalKey();
bool _showSearchBar = false;
@ -217,9 +219,9 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
// Making list of Tetra League matches
bool isTracking = await teto.isPlayerTracking(me.userId);
List<TetraLeague> states = await teto.getHistory(me.userId);
TetraLeague? compareWith;
Set<TetraLeague> uniqueTL = {};
List<List<TetraLeague>> states = await Future.wait<List<TetraLeague>>([
teto.getStates(me.userId, season: 1), teto.getStates(me.userId, season: 2),
]);
List<TetraLeagueAlphaRecord> storedRecords = await teto.getTLMatchesbyPlayerID(me.userId); // get old matches
if (isTracking){ // if tracked - save data to local DB
await teto.storeState(summaries.league);
@ -277,31 +279,32 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
// if (uniqueTL.isEmpty) uniqueTL.add(summaries.league);
// }
// Also i need previous Tetra League State for comparison if avaliable
if (states.length >= 2){
compareWith = states.elementAtOrNull(states.length - 2);
chartsData = <DropdownMenuItem<List<_HistoryChartSpot>>>[ // Dumping charts data into dropdown menu items, while cheking if every entry is valid
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.gamesPlayed > 9) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.tr)], child: Text(t.statCellNum.tr)),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.gamesPlayed > 9) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.glicko!)], child: const Text("Glicko")),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.gamesPlayed > 9) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.rd!)], child: const Text("Rating Deviation")),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.apm != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.apm!)], child: Text(t.statCellNum.apm.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.pps != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.pps!)], child: Text(t.statCellNum.pps.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.vs != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.vs!)], child: Text(t.statCellNum.vs.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.app)], child: Text(t.statCellNum.app.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.dss)], child: Text(t.statCellNum.dss.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.dsp)], child: Text(t.statCellNum.dsp.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.appdsp)], child: const Text("APP + DS/P")),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.vsapm)], child: const Text("VS/APM")),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.cheese)], child: Text(t.statCellNum.cheese.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.gbe)], child: Text(t.statCellNum.gbe.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.nyaapp)], child: Text(t.statCellNum.nyaapp.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.area)], child: Text(t.statCellNum.area.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.estTr != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.estTr!.esttr)], child: Text(t.statCellNum.estOfTR.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.esttracc != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.esttracc!)], child: Text(t.statCellNum.accOfEst.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.opener)], child: const Text("Opener")),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.plonk)], child: const Text("Plonk")),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.infds)], child: const Text("Inf. DS")),
DropdownMenuItem(value: [for (var tl in uniqueTL) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.stride)], child: const Text("Stride")),
];
TetraLeague? compareWith;
if (states[1].length >= 2 || states[0].length >= 2){
compareWith = states[1].length >= 2 ? states[1].elementAtOrNull(states.length - 2) : null;
chartsData = [for (List<TetraLeague> s in states) <DropdownMenuItem<List<_HistoryChartSpot>>>[ // Dumping charts data into dropdown menu items, while cheking if every entry is valid
DropdownMenuItem(value: [for (var tl in s) if (tl.gamesPlayed > 9) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.tr)], child: Text(t.statCellNum.tr)),
DropdownMenuItem(value: [for (var tl in s) if (tl.gamesPlayed > 9) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.glicko!)], child: const Text("Glicko")),
DropdownMenuItem(value: [for (var tl in s) if (tl.gamesPlayed > 9) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.rd!)], child: const Text("Rating Deviation")),
DropdownMenuItem(value: [for (var tl in s) if (tl.apm != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.apm!)], child: Text(t.statCellNum.apm.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in s) if (tl.pps != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.pps!)], child: Text(t.statCellNum.pps.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in s) if (tl.vs != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.vs!)], child: Text(t.statCellNum.vs.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.app)], child: Text(t.statCellNum.app.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.dss)], child: Text(t.statCellNum.dss.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.dsp)], child: Text(t.statCellNum.dsp.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.appdsp)], child: const Text("APP + DS/P")),
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.vsapm)], child: const Text("VS/APM")),
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.cheese)], child: Text(t.statCellNum.cheese.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.gbe)], child: Text(t.statCellNum.gbe.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.nyaapp)], child: Text(t.statCellNum.nyaapp.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in s) if (tl.nerdStats != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.nerdStats!.area)], child: Text(t.statCellNum.area.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in s) if (tl.estTr != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.estTr!.esttr)], child: Text(t.statCellNum.estOfTR.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in s) if (tl.esttracc != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.esttracc!)], child: Text(t.statCellNum.accOfEst.replaceAll(RegExp(r'\n'), " "))),
DropdownMenuItem(value: [for (var tl in s) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.opener)], child: const Text("Opener")),
DropdownMenuItem(value: [for (var tl in s) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.plonk)], child: const Text("Plonk")),
DropdownMenuItem(value: [for (var tl in s) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.infds)], child: const Text("Inf. DS")),
DropdownMenuItem(value: [for (var tl in s) if (tl.playstyle != null) _HistoryChartSpot(tl.timestamp, tl.gamesPlayed, tl.rank, tl.playstyle!.stride)], child: const Text("Stride")),
]];
}else{
compareWith = null;
chartsData = [];
@ -312,7 +315,7 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
changePlayer(me.userId);
});
}
return [me, summaries, news, tlStream, recentZenith, recentZenithEX, states];
return [me, summaries, news, tlStream, recentZenith, recentZenithEX, states[currentSeason-1]];
//return [me, records, states, tlMatches, compareWith, isTracking, news, topTR, recent, sprint, blitz, tlMatches.elementAtOrNull(0)?.timestamp];
}
@ -850,7 +853,7 @@ class _ZenithRecords extends StatelessWidget {
}
class _History extends StatelessWidget{
final List<DropdownMenuItem<List<_HistoryChartSpot>>> chartsData;
final List<List<DropdownMenuItem<List<_HistoryChartSpot>>>> chartsData;
final String userID;
final Function update;
final Function changePlayer;
@ -873,7 +876,7 @@ class _History extends StatelessWidget{
));
}
bool bigScreen = MediaQuery.of(context).size.width > 768;
List<_HistoryChartSpot> selectedGraph = chartsData[_chartsIndex].value!;
List<_HistoryChartSpot> selectedGraph = chartsData[_season][_chartsIndex].value!;
return SingleChildScrollView(
scrollDirection: Axis.vertical,
child: Column(
@ -883,6 +886,20 @@ class _History extends StatelessWidget{
spacing: 20,
crossAxisAlignment: WrapCrossAlignment.center,
children: [
Row(
mainAxisSize: MainAxisSize.min,
children: [
const Padding(padding: EdgeInsets.all(8.0), child: Text("Season:", style: TextStyle(fontSize: 22))),
DropdownButton(
items: [for (int i = 1; i <= currentSeason; i++) DropdownMenuItem(value: i-1, child: Text("$i"))],
value: _season,
onChanged: (value) {
_season = value!;
update();
}
),
],
),
Row(
mainAxisSize: MainAxisSize.min,
children: [
@ -902,10 +919,10 @@ class _History extends StatelessWidget{
children: [
const Padding(padding: EdgeInsets.all(8.0), child: Text("Y:", style: TextStyle(fontSize: 22))),
DropdownButton(
items: chartsData,
value: chartsData[_chartsIndex].value,
items: chartsData[_season],
value: chartsData[_season][_chartsIndex].value,
onChanged: (value) {
_chartsIndex = chartsData.indexWhere((element) => element.value == value);
_chartsIndex = chartsData[_season].indexWhere((element) => element.value == value);
update();
}
),
@ -926,13 +943,13 @@ class _History extends StatelessWidget{
IconButton(onPressed: () => _zoomPanBehavior.reset(), icon: const Icon(Icons.refresh), alignment: Alignment.center,)
],
),
if(chartsData[_chartsIndex].value!.length > 1) _HistoryChartThigy(data: selectedGraph, smooth: _smooth, yAxisTitle: _historyShortTitles[_chartsIndex], bigScreen: bigScreen, leftSpace: bigScreen? 80 : 45, yFormat: bigScreen? f2 : NumberFormat.compact(), xFormat: NumberFormat.compact())
else if (chartsData[_chartsIndex].value!.length <= 1) Center(child: Column(
if(chartsData[_season][_chartsIndex].value!.length > 1) _HistoryChartThigy(data: selectedGraph, smooth: _smooth, yAxisTitle: _historyShortTitles[_chartsIndex], bigScreen: bigScreen, leftSpace: bigScreen? 80 : 45, yFormat: bigScreen? f2 : NumberFormat.compact(), xFormat: NumberFormat.compact())
else if (chartsData[_season][_chartsIndex].value!.length <= 1) Center(child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(t.notEnoughData, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28)),
if (wasActiveInTL) Text(t.errors.actionSuggestion),
if (wasActiveInTL) TextButton(onPressed: (){changePlayer(userID, fetchHistory: true);}, child: Text(t.fetchAndsaveTLHistory))
if (wasActiveInTL && _season == 0) Text(t.errors.actionSuggestion),
if (wasActiveInTL && _season == 0) TextButton(onPressed: (){changePlayer(userID, fetchHistory: true);}, child: Text(t.fetchAndsaveTLHistory))
],
))
],

View File

@ -11,7 +11,7 @@ import 'package:tetra_stats/widgets/text_timestamp.dart';
import 'package:window_manager/window_manager.dart';
class StatesView extends StatefulWidget {
final List<TetrioPlayer> states;
final List<TetraLeague> states;
const StatesView({super.key, required this.states});
@override
@ -25,7 +25,7 @@ class StatesState extends State<StatesView> {
void initState() {
if (!kIsWeb && !Platform.isAndroid && !Platform.isIOS){
windowManager.getTitle().then((value) => oldWindowTitle = value);
windowManager.setTitle("Tetra Stats: ${t.statesViewTitle(number: widget.states.length, nickname: widget.states.last.username.toUpperCase())}");
windowManager.setTitle("Tetra Stats: ${t.statesViewTitle(number: widget.states.length, nickname: widget.states.last.id.toUpperCase())}");
}
super.initState();
}
@ -41,14 +41,14 @@ class StatesState extends State<StatesView> {
final t = Translations.of(context);
return Scaffold(
appBar: AppBar(
title: Text(t.statesViewTitle(number: widget.states.length, nickname: widget.states.last.username.toUpperCase())),
title: Text(t.statesViewTitle(number: widget.states.length, nickname: widget.states.first.id)),
actions: [
IconButton(
onPressed: (){
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => MatchesView(userID: widget.states.first.userId, username: widget.states.first.username),
builder: (context) => MatchesView(userID: widget.states.first.id, username: widget.states.first.id),
),
);
}, icon: const Icon(Icons.list), tooltip: t.viewAllMatches)
@ -60,24 +60,24 @@ class StatesState extends State<StatesView> {
itemCount: widget.states.length,
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: 0)),
title: Text(timestamp(widget.states[index].timestamp)),
//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;
//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)))));
// }));
},
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StateView(state: widget.states[index]),
),
);
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => StateView(state: widget.states[index]),
// ),
// );
},
);
})));

View File

@ -119,12 +119,12 @@ class TrackedPlayersState extends State<TrackedPlayersView> {
},
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => StatesView(states: allPlayers[keys[index]]!),
),
);
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => StatesView(states: allPlayers[keys[index]]!),
// ),
// );
},
);
}));