Pull to refresh + now we have only one chart
But it's possible to change sets of data for chart Also changed fetch function in main view
This commit is contained in:
parent
8770d5dca8
commit
041b70a86c
|
@ -344,7 +344,7 @@ class EndContextSingle {
|
||||||
late int piecesPlaced;
|
late int piecesPlaced;
|
||||||
late int lines;
|
late int lines;
|
||||||
late int score;
|
late int score;
|
||||||
late int seed;
|
late double seed;
|
||||||
late Duration finalTime;
|
late Duration finalTime;
|
||||||
late int tSpins;
|
late int tSpins;
|
||||||
late Clears clears;
|
late Clears clears;
|
||||||
|
@ -373,7 +373,7 @@ class EndContextSingle {
|
||||||
required this.finesse});
|
required this.finesse});
|
||||||
|
|
||||||
EndContextSingle.fromJson(Map<String, dynamic> json) {
|
EndContextSingle.fromJson(Map<String, dynamic> json) {
|
||||||
seed = json['seed'];
|
seed = json['seed'].toDouble();
|
||||||
lines = json['lines'];
|
lines = json['lines'];
|
||||||
inputs = json['inputs'];
|
inputs = json['inputs'];
|
||||||
holds = json['holds'] ?? 0;
|
holds = json['holds'] ?? 0;
|
||||||
|
|
|
@ -34,13 +34,14 @@ const String createTetrioUsersToTrack = '''
|
||||||
''';
|
''';
|
||||||
const String createTetrioTLRecordsTable = '''
|
const String createTetrioTLRecordsTable = '''
|
||||||
CREATE TABLE IF NOT EXISTS "tetrioAlphaLeagueMathces" (
|
CREATE TABLE IF NOT EXISTS "tetrioAlphaLeagueMathces" (
|
||||||
"id" TEXT,
|
"id" TEXT NOT NULL UNIQUE,
|
||||||
"replayId" TEXT,
|
"replayId" TEXT,
|
||||||
"player1id" TEXT,
|
"player1id" TEXT,
|
||||||
"player2id" TEXT,
|
"player2id" TEXT,
|
||||||
"timestamp" TEXT,
|
"timestamp" TEXT,
|
||||||
"endContext1" TEXT,
|
"endContext1" TEXT,
|
||||||
"endContext2" TEXT
|
"endContext2" TEXT,
|
||||||
|
PRIMARY KEY("id")
|
||||||
)
|
)
|
||||||
''';
|
''';
|
||||||
|
|
||||||
|
@ -70,7 +71,6 @@ class TetrioService extends DB {
|
||||||
final allPlayers = await getAllPlayers();
|
final allPlayers = await getAllPlayers();
|
||||||
_players = allPlayers.toList().first; // ???
|
_players = allPlayers.toList().first; // ???
|
||||||
_tetrioStreamController.add(_players);
|
_tetrioStreamController.add(_players);
|
||||||
developer.log("_loadPlayers: $_players", name: "services/tetrio_crud");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> deletePlayer(String id) async {
|
Future<void> deletePlayer(String id) async {
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
import 'dart:math';
|
import 'dart:math';
|
||||||
|
@ -17,6 +19,9 @@ String _searchFor = "dan63047";
|
||||||
String _titleNickname = "dan63047";
|
String _titleNickname = "dan63047";
|
||||||
final TetrioService teto = TetrioService();
|
final TetrioService teto = TetrioService();
|
||||||
late SharedPreferences prefs;
|
late SharedPreferences prefs;
|
||||||
|
var chartsData = <DropdownMenuItem<List<FlSpot>>>[];
|
||||||
|
List chartsShortTitles = ["TR", "Glicko", "RD", "APM", "PPS", "VS", "APP", "DS/S", "DS/P", "APP + DS/P", "VS/APM", "Cheese", "GbE", "wAPP", "Area", "eTR", "±eTR"];
|
||||||
|
int chartsIndex = 0;
|
||||||
const allowedHeightForPlayerIdInPixels = 40.0;
|
const allowedHeightForPlayerIdInPixels = 40.0;
|
||||||
const allowedHeightForPlayerBioInPixels = 30.0;
|
const allowedHeightForPlayerBioInPixels = 30.0;
|
||||||
const givenTextHeightByScreenPercentage = 0.3;
|
const givenTextHeightByScreenPercentage = 0.3;
|
||||||
|
@ -43,7 +48,7 @@ class _MainState extends State<MainView> with SingleTickerProviderStateMixin {
|
||||||
final List<Widget> myTabs = [
|
final List<Widget> myTabs = [
|
||||||
const Tab(text: "Tetra League"),
|
const Tab(text: "Tetra League"),
|
||||||
const Tab(text: "TL Records"),
|
const Tab(text: "TL Records"),
|
||||||
const Tab(text: "TL History"),
|
const Tab(text: "History"),
|
||||||
const Tab(text: "40 Lines"),
|
const Tab(text: "40 Lines"),
|
||||||
const Tab(text: "Blitz"),
|
const Tab(text: "Blitz"),
|
||||||
const Tab(text: "Other"),
|
const Tab(text: "Other"),
|
||||||
|
@ -110,33 +115,48 @@ class _MainState extends State<MainView> with SingleTickerProviderStateMixin {
|
||||||
Future<List> fetch(String nickOrID) async {
|
Future<List> fetch(String nickOrID) async {
|
||||||
TetrioPlayer me = await teto.fetchPlayer(nickOrID);
|
TetrioPlayer me = await teto.fetchPlayer(nickOrID);
|
||||||
setState((){_titleNickname = me.username;});
|
setState((){_titleNickname = me.username;});
|
||||||
|
var tlStream = await teto.getTLStream(me.userId);
|
||||||
|
List<TetraLeagueAlphaRecord> tlMatches = [];
|
||||||
bool isTracking = await teto.isPlayerTracking(me.userId);
|
bool isTracking = await teto.isPlayerTracking(me.userId);
|
||||||
List<TetrioPlayer> states = [];
|
List<TetrioPlayer> states = [];
|
||||||
if (isTracking){
|
if (isTracking){
|
||||||
teto.storeState(me);
|
teto.storeState(me);
|
||||||
teto.saveTLMatchesFromStream(await teto.getTLStream(me.userId));
|
teto.saveTLMatchesFromStream(await teto.getTLStream(me.userId));
|
||||||
states.addAll(await teto.getPlayer(me.userId));
|
states.addAll(await teto.getPlayer(me.userId));
|
||||||
}
|
chartsData = <DropdownMenuItem<List<FlSpot>>>[
|
||||||
Map<String, dynamic> records = await teto.fetchRecords(me.userId);
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.gamesPlayed > 9) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.rating)], child: const Text("Tetra Rating")),
|
||||||
return [me, records, states, isTracking];
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.gamesPlayed > 9) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.glicko!)], child: const Text("Glicko")),
|
||||||
}
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.gamesPlayed > 9) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.rd!)], child: const Text("Rating Deviation")),
|
||||||
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.apm != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.apm!)], child: const Text("Attack Per Minute")),
|
||||||
Future<List<TetraLeagueAlphaRecord>> getTLMatches(String userID) async {
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.pps != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.pps!)], child: const Text("Pieces Per Second")),
|
||||||
var fetched = await teto.getTLStream(userID);
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.vs != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.vs!)], child: const Text("Versus Score")),
|
||||||
bool isTracked = await teto.isPlayerTracking(userID);
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.app)], child: const Text("Attack Per Piece")),
|
||||||
if (!isTracked) return fetched.records;
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.dss)], child: const Text("Downstack Per Second")),
|
||||||
teto.saveTLMatchesFromStream(fetched);
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.dsp)], child: const Text("Downstack Per Piece")),
|
||||||
var fromdb = await teto.getTLMatchesbyPlayerID(userID);
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.appdsp)], child: const Text("APP + DS/P")),
|
||||||
for (var match in fetched.records) {
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.vsapm)], child: const Text("VS/APM")),
|
||||||
if (!fromdb.contains(match)) fromdb.add(match);
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.cheese)], child: const Text("Cheese Index")),
|
||||||
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.gbe)], child: const Text("Garbage Efficiency")),
|
||||||
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.nyaapp)], child: const Text("Weighted APP")),
|
||||||
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.area)], child: const Text("Area")),
|
||||||
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.estTr != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.estTr!.esttr)], child: const Text("Est. of TR")),
|
||||||
|
DropdownMenuItem(value: [for (var state in states) if (state.tlSeason1.esttracc != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.esttracc!)], child: const Text("Accuracy of Est.")),
|
||||||
|
];
|
||||||
|
tlMatches.addAll(await teto.getTLMatchesbyPlayerID(me.userId));
|
||||||
|
for (var match in tlStream.records) {
|
||||||
|
if (!tlMatches.contains(match)) tlMatches.add(match);
|
||||||
}
|
}
|
||||||
fromdb.sort((a, b) {
|
tlMatches.sort((a, b) {
|
||||||
if(a.timestamp.isBefore(b.timestamp)) return 1;
|
if(a.timestamp.isBefore(b.timestamp)) return 1;
|
||||||
if(a.timestamp.isAtSameMomentAs(b.timestamp)) return 0;
|
if(a.timestamp.isAtSameMomentAs(b.timestamp)) return 0;
|
||||||
if(a.timestamp.isAfter(b.timestamp)) return -1;
|
if(a.timestamp.isAfter(b.timestamp)) return -1;
|
||||||
return 0;
|
return 0;
|
||||||
});
|
});
|
||||||
return fromdb;
|
} else{
|
||||||
|
tlMatches = tlStream.records;
|
||||||
|
}
|
||||||
|
Map<String, dynamic> records = await teto.fetchRecords(me.userId);
|
||||||
|
return [me, records, states, tlMatches, isTracking];
|
||||||
}
|
}
|
||||||
|
|
||||||
void _justUpdate() {
|
void _justUpdate() {
|
||||||
|
@ -234,44 +254,57 @@ class _MainState extends State<MainView> with SingleTickerProviderStateMixin {
|
||||||
case ConnectionState.done:
|
case ConnectionState.done:
|
||||||
//bool bigScreen = MediaQuery.of(context).size.width > 1024;
|
//bool bigScreen = MediaQuery.of(context).size.width > 1024;
|
||||||
if (snapshot.hasData) {
|
if (snapshot.hasData) {
|
||||||
return NestedScrollView(
|
return RefreshIndicator(
|
||||||
controller: _scrollController,
|
onRefresh: () {
|
||||||
headerSliverBuilder: (context, value) {
|
return Future(() => changePlayer(snapshot.data![0].userId));
|
||||||
return [
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: UserThingy(
|
|
||||||
player: snapshot.data![0],
|
|
||||||
showStateTimestamp: false,
|
|
||||||
setState: _justUpdate,
|
|
||||||
)),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: TabBar(
|
|
||||||
controller: _tabController,
|
|
||||||
isScrollable: true,
|
|
||||||
tabs: myTabs,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
},
|
},
|
||||||
body: TabBarView(
|
notificationPredicate: (notification) {
|
||||||
controller: _tabController,
|
// with NestedScrollView local(depth == 2) OverscrollNotification are not sent
|
||||||
children: [
|
if (notification is OverscrollNotification || Platform.isIOS) {
|
||||||
TLThingy(
|
return notification.depth == 2;
|
||||||
tl: snapshot.data![0].tlSeason1,
|
}
|
||||||
userID: snapshot.data![0].userId),
|
return notification.depth == 0;
|
||||||
_TLRecords(userID: snapshot.data![0].userId, get: getTLMatches,),
|
},
|
||||||
_TLHistory(states: snapshot.data![2]),
|
child: NestedScrollView(
|
||||||
_RecordThingy(
|
controller: _scrollController,
|
||||||
record: (snapshot.data![1]['sprint'].isNotEmpty)
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
? snapshot.data![1]['sprint'][0]
|
headerSliverBuilder: (context, value) {
|
||||||
: null),
|
return [
|
||||||
_RecordThingy(
|
SliverToBoxAdapter(
|
||||||
record: (snapshot.data![1]['blitz'].isNotEmpty)
|
child: UserThingy(
|
||||||
? snapshot.data![1]['blitz'][0]
|
player: snapshot.data![0],
|
||||||
: null),
|
showStateTimestamp: false,
|
||||||
_OtherThingy(
|
setState: _justUpdate,
|
||||||
zen: snapshot.data![1]['zen'], bio: snapshot.data![0].bio)
|
)),
|
||||||
],
|
SliverToBoxAdapter(
|
||||||
|
child: TabBar(
|
||||||
|
controller: _tabController,
|
||||||
|
isScrollable: true,
|
||||||
|
tabs: myTabs,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
];
|
||||||
|
},
|
||||||
|
body: TabBarView(
|
||||||
|
controller: _tabController,
|
||||||
|
children: [
|
||||||
|
TLThingy(
|
||||||
|
tl: snapshot.data![0].tlSeason1,
|
||||||
|
userID: snapshot.data![0].userId),
|
||||||
|
_TLRecords(userID: snapshot.data![0].userId, data: snapshot.data![3]),
|
||||||
|
_History(states: snapshot.data![2], update: _justUpdate),
|
||||||
|
_RecordThingy(
|
||||||
|
record: (snapshot.data![1]['sprint'].isNotEmpty)
|
||||||
|
? snapshot.data![1]['sprint'][0]
|
||||||
|
: null),
|
||||||
|
_RecordThingy(
|
||||||
|
record: (snapshot.data![1]['blitz'].isNotEmpty)
|
||||||
|
? snapshot.data![1]['blitz'][0]
|
||||||
|
: null),
|
||||||
|
_OtherThingy(
|
||||||
|
zen: snapshot.data![1]['zen'], bio: snapshot.data![0].bio)
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
} else if (snapshot.hasError) {
|
} else if (snapshot.hasError) {
|
||||||
|
@ -401,99 +434,62 @@ class _NavDrawerState extends State<NavDrawer> {
|
||||||
|
|
||||||
class _TLRecords extends StatelessWidget {
|
class _TLRecords extends StatelessWidget {
|
||||||
final String userID;
|
final String userID;
|
||||||
final Future<List<TetraLeagueAlphaRecord>> Function(String user) get;
|
final List<TetraLeagueAlphaRecord> data;
|
||||||
|
|
||||||
const _TLRecords({required this.userID, required this.get});
|
const _TLRecords({required this.userID, required this.data});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FutureBuilder(
|
return ListView( // TODO: Redo using ListView.builder()
|
||||||
future: get(userID),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
builder: (context, snapshot) {
|
children: (data.isNotEmpty)
|
||||||
switch (snapshot.connectionState) {
|
? [for (var value in data) ListTile(
|
||||||
case ConnectionState.none:
|
leading: Text("${value.endContext.firstWhere((element) => element.userId == userID).points} : ${value.endContext.firstWhere((element) => element.userId != userID).points}",
|
||||||
case ConnectionState.waiting:
|
style: const TextStyle(
|
||||||
case ConnectionState.active:
|
fontFamily: "Eurostile Round Extended",
|
||||||
return const Center(
|
fontSize: 28,)),
|
||||||
child: CircularProgressIndicator(color: Colors.white));
|
title: Text("vs. ${value.endContext.firstWhere((element) => element.userId != userID).username}"),
|
||||||
case ConnectionState.done:
|
subtitle: Text(dateFormat.format(value.timestamp)),
|
||||||
if (snapshot.hasError) {
|
trailing: Column(mainAxisAlignment: MainAxisAlignment.center,
|
||||||
return Text(snapshot.error.toString(), style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28));
|
children: [
|
||||||
} else {
|
Text("${f2.format(value.endContext.firstWhere((element) => element.userId == userID).secondary)} : ${f2.format(value.endContext.firstWhere((element) => element.userId != userID).secondary)} APM", style: const TextStyle(height: 1.1)),
|
||||||
return ListView(
|
Text("${f2.format(value.endContext.firstWhere((element) => element.userId == userID).tertiary)} : ${f2.format(value.endContext.firstWhere((element) => element.userId != userID).tertiary)} PPS", style: const TextStyle(height: 1.1)),
|
||||||
physics: const ClampingScrollPhysics(),
|
Text("${f2.format(value.endContext.firstWhere((element) => element.userId == userID).extra)} : ${f2.format(value.endContext.firstWhere((element) => element.userId != userID).extra)} VS", style: const TextStyle(height: 1.1)),
|
||||||
children: (snapshot.data!.isNotEmpty)
|
]),
|
||||||
? [for (var value in snapshot.data!) ListTile(
|
onTap: (){Navigator.push(
|
||||||
leading: Text("${value.endContext.firstWhere((element) => element.userId == userID).points} : ${value.endContext.firstWhere((element) => element.userId != userID).points}",
|
context,
|
||||||
style: const TextStyle(
|
MaterialPageRoute(
|
||||||
fontFamily: "Eurostile Round Extended",
|
builder: (context) => TlMatchResultView(record: value, initPlayerId: userID),
|
||||||
fontSize: 28,)),
|
),
|
||||||
title: Text("vs. ${value.endContext.firstWhere((element) => element.userId != userID).username}"),
|
);},
|
||||||
subtitle: Text(dateFormat.format(value.timestamp)),
|
)]
|
||||||
trailing: Column(mainAxisAlignment: MainAxisAlignment.center,
|
: [const Center(child: Text("No records", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))],
|
||||||
children: [
|
);
|
||||||
Text("${f2.format(value.endContext.firstWhere((element) => element.userId == userID).secondary)} : ${f2.format(value.endContext.firstWhere((element) => element.userId != userID).secondary)} APM", style: const TextStyle(height: 1.1)),
|
|
||||||
Text("${f2.format(value.endContext.firstWhere((element) => element.userId == userID).tertiary)} : ${f2.format(value.endContext.firstWhere((element) => element.userId != userID).tertiary)} PPS", style: const TextStyle(height: 1.1)),
|
|
||||||
Text("${f2.format(value.endContext.firstWhere((element) => element.userId == userID).extra)} : ${f2.format(value.endContext.firstWhere((element) => element.userId != userID).extra)} VS", style: const TextStyle(height: 1.1)),
|
|
||||||
]),
|
|
||||||
onTap: (){Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => TlMatchResultView(record: value, initPlayerId: userID),
|
|
||||||
),
|
|
||||||
);},
|
|
||||||
)]
|
|
||||||
: [const Center(child: Text("No records", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TLHistory extends StatelessWidget{
|
class _History extends StatelessWidget{
|
||||||
final List<TetrioPlayer> states;
|
final List<TetrioPlayer> states;
|
||||||
const _TLHistory({required this.states});
|
final Function update;
|
||||||
|
const _History({required this.states, required this.update});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
bool bigScreen = MediaQuery.of(context).size.width > 768;
|
bool bigScreen = MediaQuery.of(context).size.width > 768;
|
||||||
List<FlSpot> trData = [for (var state in states) if (state.tlSeason1.gamesPlayed > 9) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.rating)];
|
|
||||||
List<FlSpot> apmData = [for (var state in states) if (state.tlSeason1.apm != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.apm!)];
|
|
||||||
List<FlSpot> ppsData = [for (var state in states) if (state.tlSeason1.pps != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.pps!)];
|
|
||||||
List<FlSpot> vsData = [for (var state in states) if (state.tlSeason1.vs != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.vs!)];
|
|
||||||
List<FlSpot> appData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.app)];
|
|
||||||
List<FlSpot> dssData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.dss)];
|
|
||||||
List<FlSpot> dspData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.dsp)];
|
|
||||||
List<FlSpot> appdspData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.appdsp)];
|
|
||||||
List<FlSpot> vsapmData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.vsapm)];
|
|
||||||
List<FlSpot> cheeseData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.cheese)];
|
|
||||||
List<FlSpot> gbeData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.gbe)];
|
|
||||||
List<FlSpot> nyaappData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.nyaapp)];
|
|
||||||
List<FlSpot> areaData = [for (var state in states) if (state.tlSeason1.nerdStats != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.nerdStats!.area)];
|
|
||||||
List<FlSpot> estTrData = [for (var state in states) if (state.tlSeason1.estTr != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.estTr!.esttr)];
|
|
||||||
List<FlSpot> estaccData = [for (var state in states) if (state.tlSeason1.esttracc != null) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.esttracc!)];
|
|
||||||
return ListView(physics: const ClampingScrollPhysics(),
|
return ListView(physics: const ClampingScrollPhysics(),
|
||||||
children: states.isNotEmpty ? [
|
children: states.isNotEmpty ? [
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
if(trData.length > 1) _HistoryChartThigy(data: trData, title: "Tetra Rating", yAxisTitle: "TR", bigScreen: bigScreen, leftSpace: bigScreen? 80 : 45, yFormat: bigScreen? f2 : NumberFormat.compact(),),
|
DropdownButton(
|
||||||
if(apmData.length > 1) _HistoryChartThigy(data: apmData, title: "Attack Per Minute", yAxisTitle: "APM", bigScreen: bigScreen, leftSpace: 40, yFormat: NumberFormat.compact(),),
|
items: chartsData,
|
||||||
if(ppsData.length > 1) _HistoryChartThigy(data: ppsData, title: "Pieces Per Second", yAxisTitle: "PPS", bigScreen: bigScreen, leftSpace: 40, yFormat: NumberFormat.compact(),),
|
value: chartsData[chartsIndex].value,
|
||||||
if(vsData.length > 1) _HistoryChartThigy(data: vsData, title: "Versus Score", yAxisTitle: "VS", bigScreen: bigScreen, leftSpace: 40, yFormat: NumberFormat.compact(),),
|
onChanged: (value) {
|
||||||
if(appData.length > 1) _HistoryChartThigy(data: appData, title: "Attack Per Piece", yAxisTitle: "APP", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),),
|
chartsIndex = chartsData.indexWhere((element) => element.value == value);
|
||||||
if(dssData.length > 1) _HistoryChartThigy(data: dssData, title: bigScreen ? "Downstack Per Second" : "Downstack\nPer Second", yAxisTitle: "DS/S", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),),
|
update();
|
||||||
if(dspData.length > 1) _HistoryChartThigy(data: dspData, title: bigScreen ? "Downstack Per Piece" : "Downstack\nPer Piece", yAxisTitle: "DS/P", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),),
|
}
|
||||||
if(appdspData.length > 1) _HistoryChartThigy(data: appdspData, title: "APP + DS/P", yAxisTitle: "APP + DS/P", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),),
|
),
|
||||||
if(vsapmData.length > 1) _HistoryChartThigy(data: vsapmData, title: "VS/APM", yAxisTitle: "VS/APM", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),),
|
if(chartsData[chartsIndex].value!.length > 1) _HistoryChartThigy(data: chartsData[chartsIndex].value!, title: "ss", yAxisTitle: chartsShortTitles[chartsIndex], bigScreen: bigScreen, leftSpace: bigScreen? 80 : 45, yFormat: bigScreen? f2 : NumberFormat.compact(),)
|
||||||
if(cheeseData.length > 1) _HistoryChartThigy(data: cheeseData, title: "Cheese Index", yAxisTitle: "Cheese", bigScreen: bigScreen, leftSpace: 40, yFormat: NumberFormat.compact(),),
|
else const Center(child: Text("Not enough data", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))
|
||||||
if(gbeData.length > 1) _HistoryChartThigy(data: gbeData, title: "Garbage Efficiency", yAxisTitle: "GbE", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),),
|
|
||||||
if(nyaappData.length > 1) _HistoryChartThigy(data: nyaappData, title: "Weighted APP", yAxisTitle: "wAPP", bigScreen: bigScreen, leftSpace: 48, yFormat: NumberFormat.compact(),),
|
|
||||||
if(areaData.length > 1) _HistoryChartThigy(data: areaData, title: "Area", yAxisTitle: "Area", bigScreen: bigScreen, leftSpace: 40, yFormat: NumberFormat.compact(),),
|
|
||||||
if(estTrData.length > 1) _HistoryChartThigy(data: estTrData, title: "Est. of TR", yAxisTitle: "eTR", bigScreen: bigScreen, leftSpace: bigScreen? 80 : 45, yFormat: bigScreen? f2 : NumberFormat.compact(),),
|
|
||||||
if(estaccData.length > 1) _HistoryChartThigy(data: estaccData, title: "Accuracy of Est.", yAxisTitle: "±eTR", bigScreen: bigScreen, leftSpace: 60, yFormat: NumberFormat.compact(explicitSign: true),),
|
|
||||||
if(trData.length <= 1 || apmData.length <= 1 || ppsData.length <= 1 || vsData.length <= 1 || appData.length <= 1 || dssData.length <= 1 || dspData.length <= 1 || appdspData.length <= 1 || vsapmData.length <= 1 || cheeseData.length <= 1 || gbeData.length <= 1 || nyaappData.length <= 1 || areaData.length <= 1 || estTrData.length <= 1 || estaccData.length <= 1) const Center(child: Text("Some charts aren't shown due to lack of data...", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))
|
|
||||||
// Why it's look like a garbage solution???
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
] : [const Center(child: Text("No history saved", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))]);
|
] : [const Center(child: Text("No history saved", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))]);
|
||||||
|
@ -512,12 +508,12 @@ class _HistoryChartThigy extends StatelessWidget{
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
double xInterval = bigScreen ? max(1, (data.last.x - data.first.x) / 6) : max(1, (data.last.x - data.first.x) / 3);
|
double xInterval = bigScreen ? max(1, (data.last.x - data.first.x) / 6) : max(1, (data.last.x - data.first.x) / 3);
|
||||||
return AspectRatio(
|
return SizedBox(
|
||||||
aspectRatio: bigScreen ? 1.9 : 1.1,
|
width: MediaQuery.of(context).size.width,
|
||||||
|
height: MediaQuery.of(context).size.height - 100,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
children: [
|
children: [
|
||||||
Row(mainAxisAlignment: MainAxisAlignment.center, children: [Text(title, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28))]),
|
Padding( padding: bigScreen ? const EdgeInsets.fromLTRB(40, 40, 40, 48) : const EdgeInsets.fromLTRB(0, 40, 0, 48) ,
|
||||||
Padding( padding: bigScreen ? const EdgeInsets.fromLTRB(40, 75, 40, 48) : const EdgeInsets.fromLTRB(0, 80, 0, 48) ,
|
|
||||||
child: LineChart(
|
child: LineChart(
|
||||||
LineChartData(
|
LineChartData(
|
||||||
lineBarsData: [LineChartBarData(spots: data)],
|
lineBarsData: [LineChartBarData(spots: data)],
|
||||||
|
@ -558,7 +554,7 @@ class _RecordThingy extends StatelessWidget {
|
||||||
return LayoutBuilder(builder: (context, constraints) {
|
return LayoutBuilder(builder: (context, constraints) {
|
||||||
bool bigScreen = constraints.maxWidth > 768;
|
bool bigScreen = constraints.maxWidth > 768;
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
physics: const ClampingScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
itemCount: 1,
|
itemCount: 1,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
return Column(
|
return Column(
|
||||||
|
@ -881,7 +877,7 @@ class _OtherThingy extends StatelessWidget {
|
||||||
return LayoutBuilder(builder: (context, constraints) {
|
return LayoutBuilder(builder: (context, constraints) {
|
||||||
bool bigScreen = constraints.maxWidth > 768;
|
bool bigScreen = constraints.maxWidth > 768;
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
physics: const ClampingScrollPhysics(),
|
physics: const AlwaysScrollableScrollPhysics(),
|
||||||
itemCount: 1,
|
itemCount: 1,
|
||||||
itemBuilder: (BuildContext context, int index) {
|
itemBuilder: (BuildContext context, int index) {
|
||||||
return Column(
|
return Column(
|
||||||
|
|
|
@ -85,6 +85,8 @@ flutter:
|
||||||
- res/tetrio_badges/early-supporter.png
|
- res/tetrio_badges/early-supporter.png
|
||||||
- res/tetrio_badges/founder.png
|
- res/tetrio_badges/founder.png
|
||||||
- res/tetrio_badges/galactic2x2_1.png
|
- res/tetrio_badges/galactic2x2_1.png
|
||||||
|
- res/tetrio_badges/galactic2x2_2.png
|
||||||
|
- res/tetrio_badges/galactic2x2_3.png
|
||||||
- res/tetrio_badges/ggc_1.png
|
- res/tetrio_badges/ggc_1.png
|
||||||
- res/tetrio_badges/ggc_2.png
|
- res/tetrio_badges/ggc_2.png
|
||||||
- res/tetrio_badges/ggc_3.png
|
- res/tetrio_badges/ggc_3.png
|
||||||
|
|
Binary file not shown.
After Width: | Height: | Size: 7.6 KiB |
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Loading…
Reference in New Issue