All stats for TL and werid chart is done

This commit is contained in:
dan63047 2023-06-03 22:10:28 +03:00
parent 671142702f
commit 62e77cc6aa
4 changed files with 236 additions and 53 deletions

View File

@ -600,6 +600,7 @@ class TetraLeagueAlpha {
double? get vsapm => vs! / apm!;
double? get dss => (vs! / 100) - (apm! / 60);
double? get dsp => ((vs! / 100) - (apm! / 60)) / pps!;
double? get appdsp => app! + dsp!;
double? get cheese =>
(dsp! * 150) + (((vs! / apm!) - 2) * 50) + (0.6 - app!) * 125;
double? get gbe => ((app! * dss!) / pps!) * 2;
@ -631,6 +632,8 @@ class TetraLeagueAlpha {
return 25000 / temp3;
}
double? get esttracc => esttr! - rating;
Map<String, dynamic> toJson() {
final Map<String, dynamic> data = <String, dynamic>{};
data['gamesplayed'] = gamesPlayed;

View File

@ -1,10 +1,11 @@
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:path/path.dart';
import 'dart:convert';
import 'dart:math';
import 'package:tetra_stats/data_objects/tetrio.dart';
import 'package:tetra_stats/services/tetrio_crud.dart';
import 'package:tetra_stats/services/sqlite_db_controller.dart';
import 'package:fl_chart/fl_chart.dart';
extension StringExtension on String {
String capitalize() {
@ -32,13 +33,10 @@ class MainView extends StatefulWidget {
}
Future<TetrioPlayer> fetchTetrioPlayer(String user) async {
var url = Uri.https('ch.tetr.io', 'api/users/${user.toLowerCase()}');
var url = Uri.https('ch.tetr.io', 'api/users/${user.toLowerCase().trim()}');
final response = await http.get(url);
// final response = await http.get(Uri.parse('https://ch.tetr.io/'));
if (response.statusCode == 200) {
// If the server did return a 200 OK response,
// then parse the JSON.
return jsonDecode(response.body)['success']
? TetrioPlayer.fromJson(
jsonDecode(response.body)['data']['user'],
@ -47,8 +45,6 @@ Future<TetrioPlayer> fetchTetrioPlayer(String user) async {
isUtc: true))
: throw Exception("User doesn't exist");
} else {
// If the server did not return a 200 OK response,
// then throw an exception.
throw Exception('Failed to fetch player');
}
}
@ -57,10 +53,10 @@ class _MyHomePageState extends State<MainView>
with SingleTickerProviderStateMixin {
final bodyGlobalKey = GlobalKey();
final List<Widget> myTabs = [
Tab(text: "Tetra League"),
Tab(text: "40 Lines"),
Tab(text: "Blitz"),
Tab(text: "Other"),
const Tab(text: "Tetra League"),
const Tab(text: "40 Lines"),
const Tab(text: "Blitz"),
const Tab(text: "Other"),
];
bool _searchBoolean = false;
late TabController _tabController;
@ -69,6 +65,8 @@ class _MyHomePageState extends State<MainView>
Widget _searchTextField() {
return TextField(
maxLength: 25,
decoration: InputDecoration(counter: Offstage()),
style: const TextStyle(
shadows: <Shadow>[
Shadow(
@ -116,7 +114,7 @@ class _MyHomePageState extends State<MainView>
_smoothScrollToTop() {
_scrollController.animateTo(
0,
duration: Duration(microseconds: 300),
duration: const Duration(microseconds: 300),
curve: Curves.ease,
);
@ -125,16 +123,6 @@ class _MyHomePageState extends State<MainView>
});
}
_buildTabContext(int lineCount) => Container(
child: ListView.builder(
physics: const ClampingScrollPhysics(),
itemCount: lineCount,
itemBuilder: (BuildContext context, int index) {
return Text('some content');
},
),
);
@override
Widget build(BuildContext context) {
return Scaffold(
@ -239,18 +227,19 @@ class _MyHomePageState extends State<MainView>
fontSize: bigScreen ? 42 : 28)),
if (snapshot.data!.tlSeason1.gamesPlayed >=
10)
Center(
child: Wrap(
Wrap(
direction: Axis.horizontal,
alignment: WrapAlignment.center,
alignment: WrapAlignment.spaceAround,
crossAxisAlignment:
WrapCrossAlignment.center,
clipBehavior: Clip.hardEdge,
children: [
Image.asset(
"res/tetrio_tl_alpha_ranks/${snapshot.data!.tlSeason1.rank}.png",
height: bigScreen ? 256 : 128,
height: 128,
),
Column(
children: [
Text(
"${snapshot.data!.tlSeason1.rating.toStringAsFixed(2)} TR",
style: TextStyle(
@ -264,6 +253,7 @@ class _MyHomePageState extends State<MainView>
),
],
),
],
)
else
Row(
@ -409,6 +399,13 @@ class _MyHomePageState extends State<MainView>
fractionDigits: 3,
playerStatLabel:
"Downstack\nPer Piece"),
_StatCellNum(
playerStat: snapshot.data!
.tlSeason1.appdsp!,
isScreenBig: bigScreen,
fractionDigits: 3,
playerStatLabel:
"APP + DS/P"),
_StatCellNum(
playerStat: snapshot.data!
.tlSeason1.cheese!,
@ -439,6 +436,168 @@ class _MyHomePageState extends State<MainView>
]),
)
],
),
Padding(
padding:
const EdgeInsets.fromLTRB(0, 16, 0, 48),
child: SizedBox(
width: bigScreen
? MediaQuery.of(context).size.width *
0.4
: MediaQuery.of(context).size.width *
0.85,
child: Column(
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
const Text(
"Est. of TR:",
style: TextStyle(fontSize: 24),
),
Text(
snapshot.data!.tlSeason1.esttr!
.toStringAsFixed(2),
style: const TextStyle(
fontSize: 24),
),
],
),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
const Text(
"Accuracy of TR Est.:",
style: TextStyle(fontSize: 24),
),
Text(
(snapshot.data!.tlSeason1
.esttracc!)
.toStringAsFixed(2),
style: const TextStyle(
fontSize: 24),
),
],
),
],
),
),
),
Padding(
padding:
const EdgeInsets.fromLTRB(0, 0, 0, 48),
child: SizedBox(
height: 300,
child: RadarChart(
RadarChartData(
getTitle: (index, angle) {
bool relativeAngleMode = true;
double angleValue = 0;
final usedAngle = relativeAngleMode
? angle + angleValue
: angleValue;
switch (index) {
case 0:
return RadarChartTitle(
text: 'APM',
angle: usedAngle,
);
case 1:
return RadarChartTitle(
text: 'PPS',
angle: usedAngle,
);
case 2:
return RadarChartTitle(
text: 'VS',
angle: usedAngle);
case 3:
return RadarChartTitle(
text: 'APP',
angle: usedAngle);
case 4:
return RadarChartTitle(
text: 'DS/S',
angle: usedAngle);
case 5:
return RadarChartTitle(
text: 'DS/P',
angle: usedAngle);
case 6:
return RadarChartTitle(
text: 'APP+DS/P',
angle: usedAngle);
case 7:
return RadarChartTitle(
text: 'VS/APM',
angle: usedAngle);
case 8:
return RadarChartTitle(
text: 'Cheese',
angle: usedAngle);
case 9:
return RadarChartTitle(
text: 'Gb Eff.',
angle: usedAngle);
default:
return const RadarChartTitle(
text: '');
}
},
dataSets: [
RadarDataSet(
dataEntries: [
RadarEntry(
value: snapshot.data!
.tlSeason1.apm! *
1),
RadarEntry(
value: snapshot.data!
.tlSeason1.pps! *
45),
RadarEntry(
value: snapshot.data!
.tlSeason1.vs! *
0.444),
RadarEntry(
value: snapshot.data!
.tlSeason1.app! *
185),
RadarEntry(
value: snapshot.data!
.tlSeason1.dss! *
175),
RadarEntry(
value: snapshot.data!
.tlSeason1.dsp! *
450),
RadarEntry(
value: snapshot.data!
.tlSeason1.appdsp!),
RadarEntry(
value: snapshot.data!
.tlSeason1.vsapm!),
RadarEntry(
value: snapshot.data!
.tlSeason1.cheese!),
RadarEntry(
value: snapshot.data!
.tlSeason1.gbe! *
315),
],
)
],
),
swapAnimationDuration: const Duration(
milliseconds: 150), // Optional
swapAnimationCurve:
Curves.linear, // Optional
),
),
)
]
: [
@ -451,11 +610,15 @@ class _MyHomePageState extends State<MainView>
);
},
),
Container(
child: Text("40 Lines",
Column(
children: (snapshot.data!.sprint.isNotEmpty)
? []
: [
Text("That user never played 40 Lines",
style: TextStyle(
fontFamily: "Eurostile Round Extended",
fontSize: bigScreen ? 42 : 28)),
fontSize: bigScreen ? 42 : 28))
],
),
Container(
child: Text("Blitz",

View File

@ -49,6 +49,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "1.0.5"
equatable:
dependency: transitive
description:
name: equatable
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
url: "https://pub.dev"
source: hosted
version: "2.0.5"
fake_async:
dependency: transitive
description:
@ -73,6 +81,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "6.1.4"
fl_chart:
dependency: "direct main"
description:
name: fl_chart
sha256: "48a1b69be9544e2b03d9a8e843affd89e43f3194c9248776222efcb4206bb1ec"
url: "https://pub.dev"
source: hosted
version: "0.62.0"
flutter:
dependency: "direct main"
description: flutter

View File

@ -34,6 +34,7 @@ dependencies:
sqflite_common_ffi: any
path_provider: ^2.0.15
path: ^1.8.2
fl_chart: ^0.62.0
dev_dependencies:
flutter_test: