Those graphs are mess but well see

This commit is contained in:
dan63047 2023-06-22 22:02:49 +03:00
parent 974294f167
commit 5d5ac32a8b
6 changed files with 90 additions and 16 deletions

View File

@ -13,7 +13,7 @@
- ~~Stats Calculator~~ - ~~Stats Calculator~~
- ~~Ability to compare player with himself in past~~ - ~~Ability to compare player with himself in past~~
- ~~Tetra League matches history~~ *dev build are here* - ~~Tetra League matches history~~ *dev build are here*
- Tetra League historic charts for tracked players (maybe even same sh*t for 40l and blitz well see) - ~~Tetra League historic charts for tracked players~~ (bit mess idk)
- Better UI with delta and hints for stats *that will be v0.2.0* - Better UI with delta and hints for stats *that will be v0.2.0*
- Ability to compare player with APM-PPS-VS stats - Ability to compare player with APM-PPS-VS stats
- Ability to fetch Tetra League leaderboard - Ability to fetch Tetra League leaderboard

View File

@ -614,11 +614,11 @@ class EndContextMulti {
naturalOrder = json['naturalorder']; naturalOrder = json['naturalorder'];
wins = json['wins']; wins = json['wins'];
points = json['points']['primary']; points = json['points']['primary'];
secondary = json['points']['secondary']; secondary = json['points']['secondary'].toDouble();
tertiary = json['points']['tertiary']; tertiary = json['points']['tertiary'].toDouble();
secondaryTracking = json['points']['secondaryAvgTracking'].cast<double>(); secondaryTracking = json['points']['secondaryAvgTracking'].cast<double>();
tertiaryTracking = json['points']['tertiaryAvgTracking'].cast<double>(); tertiaryTracking = json['points']['tertiaryAvgTracking'].cast<double>();
extra = json['points']['extra']['vs']; extra = json['points']['extra']['vs'].toDouble();
extraTracking = json['points']['extraAvgTracking']['aggregatestats___vsscore'].cast<double>(); extraTracking = json['points']['extraAvgTracking']['aggregatestats___vsscore'].cast<double>();
nerdStats = NerdStats(secondary, tertiary, extra); nerdStats = NerdStats(secondary, tertiary, extra);
estTr = EstTr(secondary, tertiary, extra, noTrRd, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe); estTr = EstTr(secondary, tertiary, extra, noTrRd, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe);

View File

@ -136,7 +136,7 @@ class TetrioService extends DB {
: []; : [];
var zen = TetrioZen.fromJson(jsonRecords['data']['zen']); var zen = TetrioZen.fromJson(jsonRecords['data']['zen']);
Map<String, dynamic> map = {"user": userID.toLowerCase().trim(), "sprint": sprint, "blitz": blitz, "zen": zen}; Map<String, dynamic> map = {"user": userID.toLowerCase().trim(), "sprint": sprint, "blitz": blitz, "zen": zen};
developer.log("fetchRecords: $userID stream retrieved and cached", name: "services/tetrio_crud"); developer.log("fetchRecords: $userID records retrieved and cached", name: "services/tetrio_crud");
_recordsCache[jsonDecode(response.body)['cache']['cached_until'].toString()] = map; _recordsCache[jsonDecode(response.body)['cache']['cached_until'].toString()] = map;
return map; return map;
} else { } else {

View File

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:fl_chart/fl_chart.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:tetra_stats/data_objects/tetrio.dart'; import 'package:tetra_stats/data_objects/tetrio.dart';
@ -20,6 +21,7 @@ const allowedHeightForPlayerBioInPixels = 30.0;
const givenTextHeightByScreenPercentage = 0.3; const givenTextHeightByScreenPercentage = 0.3;
final NumberFormat timeInSec = NumberFormat("#,###.###s."); final NumberFormat timeInSec = NumberFormat("#,###.###s.");
final NumberFormat f2 = NumberFormat.decimalPatternDigits(decimalDigits: 2); final NumberFormat f2 = NumberFormat.decimalPatternDigits(decimalDigits: 2);
final DateFormat dateFormat = DateFormat.yMMMd().add_Hms();
class MainView extends StatefulWidget { class MainView extends StatefulWidget {
const MainView({Key? key}) : super(key: key); const MainView({Key? key}) : super(key: key);
@ -106,10 +108,14 @@ 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;});
bool isTracking = await teto.isPlayerTracking(nickOrID); bool isTracking = await teto.isPlayerTracking(me.userId);
if (isTracking) teto.storeState(me); List<TetrioPlayer> states = [];
if (isTracking){
teto.storeState(me);
states.addAll(await teto.getPlayer(me.userId));
}
Map<String, dynamic> records = await teto.fetchRecords(me.userId); Map<String, dynamic> records = await teto.fetchRecords(me.userId);
return [me, records, isTracking]; return [me, records, states, isTracking];
} }
void _justUpdate() { void _justUpdate() {
@ -233,7 +239,7 @@ class _MainState extends State<MainView> with SingleTickerProviderStateMixin {
tl: snapshot.data![0].tlSeason1, tl: snapshot.data![0].tlSeason1,
userID: snapshot.data![0].userId), userID: snapshot.data![0].userId),
_TLRecords(userID: snapshot.data![0].userId), _TLRecords(userID: snapshot.data![0].userId),
Text("kekwa"), _TLHistory(states: snapshot.data![2]),
_RecordThingy( _RecordThingy(
record: (snapshot.data![1]['sprint'].isNotEmpty) record: (snapshot.data![1]['sprint'].isNotEmpty)
? snapshot.data![1]['sprint'][0] ? snapshot.data![1]['sprint'][0]
@ -415,7 +421,7 @@ class _TLRecords extends StatelessWidget {
), ),
);}, );},
)] )]
: [const Text("No records",style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28))], : [const Center(child: Text("No records", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))],
); );
} }
} }
@ -423,6 +429,77 @@ class _TLRecords extends StatelessWidget {
} }
} }
class _TLHistory extends StatelessWidget{
final List<TetrioPlayer> states;
const _TLHistory({super.key, required this.states});
@override
Widget build(BuildContext context) {
bool bigScreen = MediaQuery.of(context).size.width > 768;
List<FlSpot> trData = [for (var state in states) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.rating)];
List<FlSpot> apmData = [for (var state in states) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.apm!)];
List<FlSpot> ppsData = [for (var state in states) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.pps!)];
List<FlSpot> vsData = [for (var state in states) FlSpot(state.state.millisecondsSinceEpoch.toDouble(), state.tlSeason1.vs!)];
return ListView(physics: const ClampingScrollPhysics(),
children: states.isNotEmpty ? [
Column(
children: [
_HistoryChartThigy(data: trData, title: "Tetra Rating", yAxisTitle: "TR", bigScreen: bigScreen),
_HistoryChartThigy(data: apmData, title: "Attack Per Minute", yAxisTitle: "APM", bigScreen: bigScreen),
_HistoryChartThigy(data: ppsData, title: "Pieces Per Second", yAxisTitle: "PPS", bigScreen: bigScreen),
_HistoryChartThigy(data: vsData, title: "Versus Score", yAxisTitle: "VS", bigScreen: bigScreen),
],
),
] : [const Center(child: Text("No history saved", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))]);
}
}
class _HistoryChartThigy extends StatelessWidget{
final List<FlSpot> data;
final String title;
final String yAxisTitle;
final bool bigScreen;
const _HistoryChartThigy({super.key, required this.data, required this.title, required this.yAxisTitle, required this.bigScreen});
@override
Widget build(BuildContext context) {
return AspectRatio(
aspectRatio: bigScreen ? 1.9 : 1.1,
child: Stack(
children: [
Row(mainAxisAlignment: MainAxisAlignment.center, children: [Text(title, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28))]),
Padding( padding: bigScreen ? const EdgeInsets.fromLTRB(40, 80, 40, 48) : const EdgeInsets.fromLTRB(0, 80, 0, 48) ,
child: LineChart(
LineChartData(
lineBarsData: [LineChartBarData(spots: data)],
borderData: FlBorderData(show: false),
titlesData: FlTitlesData(topTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
rightTitles: AxisTitles(sideTitles: SideTitles(showTitles: false)),
bottomTitles: AxisTitles(sideTitles: SideTitles(showTitles: true, reservedSize: 30, getTitlesWidget: (double value, TitleMeta meta){
return SideTitleWidget(
axisSide: meta.axisSide,
angle: 0.3,
child: Text(DateFormat(DateFormat.YEAR_ABBR_MONTH_DAY).format(DateTime.fromMillisecondsSinceEpoch(value.floor()))),
);
})),
leftTitles: AxisTitles(sideTitles: SideTitles(showTitles: true, reservedSize: 80, getTitlesWidget: (double value, TitleMeta meta){
return SideTitleWidget(
axisSide: meta.axisSide,
child: Text(f2.format(value)),
);
}))),
lineTouchData: LineTouchData(touchTooltipData: LineTouchTooltipData(getTooltipItems: (touchedSpots) {
return [for (var v in touchedSpots) LineTooltipItem("${f2.format(v.y)} $yAxisTitle \n", TextStyle(), children: [TextSpan(text: "${dateFormat.format(DateTime.fromMillisecondsSinceEpoch(v.x.floor()))}")])];
},))
)
),
),
],
)
);
}
}
class _RecordThingy extends StatelessWidget { class _RecordThingy extends StatelessWidget {
final RecordSingle? record; final RecordSingle? record;
const _RecordThingy({Key? key, required this.record}) : super(key: key); const _RecordThingy({Key? key, required this.record}) : super(key: key);
@ -736,10 +813,7 @@ class _RecordThingy extends StatelessWidget {
), ),
] ]
: [ : [
Text("No record", const Text("No record", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28))
style: TextStyle(
fontFamily: "Eurostile Round Extended",
fontSize: bigScreen ? 42 : 28))
], ],
); );
}); });

View File

@ -307,7 +307,7 @@ class TLThingy extends StatelessWidget {
) )
] ]
: [ : [
Text("That user never played Tetra League", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), const Text("That user never played Tetra League", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)),
], ],
); );
}, },

View File

@ -14,7 +14,7 @@ publish_to: 'none'
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html # https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts # In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix. # of the product and file versions while build-number is used as the build suffix.
version: 0.1.0+3 version: 0.2.0+4
environment: environment:
sdk: '>=2.19.6 <3.0.0' sdk: '>=2.19.6 <3.0.0'