Compare view improvements, win chance implemented
Also now you can delete states and players from db Numbers formatting Ready for v0.1.0
This commit is contained in:
parent
b72d47e202
commit
daefbb9504
|
@ -148,6 +148,23 @@ class TetrioService extends DB {
|
||||||
_tetrioStreamController.add(_players);
|
_tetrioStreamController.add(_players);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> deleteState(TetrioPlayer tetrioPlayer) async {
|
||||||
|
ensureDbIsOpen();
|
||||||
|
final db = getDatabaseOrThrow();
|
||||||
|
late List<TetrioPlayer> states;
|
||||||
|
states = await getPlayer(tetrioPlayer.userId);
|
||||||
|
_players[tetrioPlayer.userId]!.removeWhere((element) => element.state == tetrioPlayer.state);
|
||||||
|
states = _players[tetrioPlayer.userId]!;
|
||||||
|
final Map<String, dynamic> statesJson = {};
|
||||||
|
for (var e in states) {
|
||||||
|
statesJson.addEntries({e.state.millisecondsSinceEpoch.toString(): e.toJson()}.entries);
|
||||||
|
}
|
||||||
|
db.update(tetrioUsersTable, {idCol: tetrioPlayer.userId, nickCol: tetrioPlayer.username, statesCol: jsonEncode(statesJson)},
|
||||||
|
where: '$idCol = ?', whereArgs: [tetrioPlayer.userId]);
|
||||||
|
_players[tetrioPlayer.userId]!.add(tetrioPlayer);
|
||||||
|
_tetrioStreamController.add(_players);
|
||||||
|
}
|
||||||
|
|
||||||
Future<List<TetrioPlayer>> getPlayer(String id) async {
|
Future<List<TetrioPlayer>> getPlayer(String id) async {
|
||||||
ensureDbIsOpen();
|
ensureDbIsOpen();
|
||||||
final db = getDatabaseOrThrow();
|
final db = getDatabaseOrThrow();
|
||||||
|
|
|
@ -15,7 +15,7 @@ class CalcState extends State<CalcView> {
|
||||||
title: const Text("Stats Calculator"),
|
title: const Text("Stats Calculator"),
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.black,
|
backgroundColor: Colors.black,
|
||||||
body: const SafeArea(child: Text("Maybe next commit idk... or shoud i think about CRUD??? idk idk")),
|
body: const SafeArea(child: Text("Next build")),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
import 'dart:math';
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:intl/intl.dart';
|
import 'package:intl/intl.dart';
|
||||||
|
@ -8,6 +9,9 @@ TetrioPlayer? theGreenSide;
|
||||||
TetrioPlayer? theRedSide;
|
TetrioPlayer? theRedSide;
|
||||||
final TetrioService teto = TetrioService();
|
final TetrioService teto = TetrioService();
|
||||||
|
|
||||||
|
FocusNode greenFocusNode = FocusNode();
|
||||||
|
FocusNode redFocusNode = FocusNode();
|
||||||
|
|
||||||
class CompareView extends StatefulWidget {
|
class CompareView extends StatefulWidget {
|
||||||
final TetrioPlayer greenSide;
|
final TetrioPlayer greenSide;
|
||||||
final TetrioPlayer? redSide;
|
final TetrioPlayer? redSide;
|
||||||
|
@ -46,6 +50,16 @@ class CompareState extends State<CompareView> {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
double getWinrateByTR(double yourGlicko, double yourRD, double notyourGlicko, double notyourRD) {
|
||||||
|
double q = 400 * sqrt(1 + 3 * pow(log(10) / (400 * pi), 2));
|
||||||
|
double k = (notyourGlicko - yourGlicko) / (q * sqrt(pow(yourRD, 2) + pow(notyourRD, 2)));
|
||||||
|
//return 1 / (1 + pow(10, (notyourGlicko - yourGlicko)) / (400 * sqrt(1 + (3 * pow(0.00575646273, 2) * (pow(yourRD, 2) + pow(notyourRD, 2))) / pow(pi, 2))));
|
||||||
|
return ((1 /
|
||||||
|
(1 + pow(10, (notyourGlicko - yourGlicko) / (400 * sqrt(1 + (3 * pow(0.0057564273, 2) * (pow(yourRD, 2) + pow(notyourRD, 2)) / pow(pi, 2))))))));
|
||||||
|
//return 1 / (1 + pow(10, k));
|
||||||
|
}
|
||||||
|
|
||||||
|
// 1/(1+10^(rating[1]-rating[0])/(400*sqrt(1+(3*Q^2*(RD[0]^2+RD[1]^2))/PI^2)))) wtf where is
|
||||||
void _justUpdate() {
|
void _justUpdate() {
|
||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
@ -72,9 +86,22 @@ class CompareState extends State<CompareView> {
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [Colors.green, Colors.transparent],
|
||||||
|
begin: Alignment.bottomCenter,
|
||||||
|
end: Alignment.topCenter,
|
||||||
|
stops: [0.0, 0.4],
|
||||||
|
)),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
|
||||||
child: PlayerSelector(player: theGreenSide, change: fetchGreenSide, updateState: _justUpdate),
|
child: PlayerSelector(
|
||||||
|
player: theGreenSide,
|
||||||
|
change: fetchGreenSide,
|
||||||
|
updateState: _justUpdate,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Padding(
|
const Padding(
|
||||||
|
@ -82,9 +109,22 @@ class CompareState extends State<CompareView> {
|
||||||
child: Text("VS"),
|
child: Text("VS"),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [Colors.red, Colors.transparent],
|
||||||
|
begin: Alignment.bottomCenter,
|
||||||
|
end: Alignment.topCenter,
|
||||||
|
stops: [0.0, 0.4],
|
||||||
|
)),
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
|
padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
|
||||||
child: PlayerSelector(player: theRedSide, change: fetchRedSide, updateState: _justUpdate),
|
child: PlayerSelector(
|
||||||
|
player: theRedSide,
|
||||||
|
change: fetchRedSide,
|
||||||
|
updateState: _justUpdate,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -99,6 +139,10 @@ class CompareState extends State<CompareView> {
|
||||||
body: theGreenSide != null && theRedSide != null
|
body: theGreenSide != null && theRedSide != null
|
||||||
? ListView(
|
? ListView(
|
||||||
children: [
|
children: [
|
||||||
|
if (theGreenSide!.role != "banned" && theRedSide!.role != "banned")
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
CompareRegTimeThingy(greenSide: theGreenSide!.registrationTime, redSide: theRedSide!.registrationTime, label: "Registred"),
|
||||||
CompareThingy(
|
CompareThingy(
|
||||||
label: "Level",
|
label: "Level",
|
||||||
greenSide: theGreenSide!.level,
|
greenSide: theGreenSide!.level,
|
||||||
|
@ -106,6 +150,14 @@ class CompareState extends State<CompareView> {
|
||||||
higherIsBetter: true,
|
higherIsBetter: true,
|
||||||
fractionDigits: 2,
|
fractionDigits: 2,
|
||||||
),
|
),
|
||||||
|
if (!theGreenSide!.gameTime.isNegative && !theRedSide!.gameTime.isNegative)
|
||||||
|
CompareThingy(
|
||||||
|
greenSide: theGreenSide!.gameTime.inMicroseconds / 1000000 / 60 / 60,
|
||||||
|
redSide: theRedSide!.gameTime.inMicroseconds / 1000000 / 60 / 60,
|
||||||
|
label: "Hours Played",
|
||||||
|
higherIsBetter: true,
|
||||||
|
fractionDigits: 2,
|
||||||
|
),
|
||||||
if (theGreenSide!.gamesPlayed >= 0 && theRedSide!.gamesPlayed >= 0)
|
if (theGreenSide!.gamesPlayed >= 0 && theRedSide!.gamesPlayed >= 0)
|
||||||
CompareThingy(
|
CompareThingy(
|
||||||
label: "Online Games",
|
label: "Online Games",
|
||||||
|
@ -126,6 +178,10 @@ class CompareState extends State<CompareView> {
|
||||||
redSide: theRedSide!.friendCount,
|
redSide: theRedSide!.friendCount,
|
||||||
higherIsBetter: true,
|
higherIsBetter: true,
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
else
|
||||||
|
CompareBoolThingy(greenSide: theGreenSide!.role == "banned", redSide: theRedSide!.role == "banned", label: "Banned", trueIsBetter: false),
|
||||||
const Divider(),
|
const Divider(),
|
||||||
theGreenSide!.tlSeason1.gamesPlayed > 0 && theRedSide!.tlSeason1.gamesPlayed > 0
|
theGreenSide!.tlSeason1.gamesPlayed > 0 && theRedSide!.tlSeason1.gamesPlayed > 0
|
||||||
? Column(
|
? Column(
|
||||||
|
@ -217,37 +273,11 @@ class CompareState extends State<CompareView> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
: Padding(
|
: CompareBoolThingy(
|
||||||
padding: const EdgeInsets.fromLTRB(16, 2, 16, 2),
|
greenSide: theGreenSide!.tlSeason1.gamesPlayed > 0,
|
||||||
child: Row(children: [
|
redSide: theRedSide!.tlSeason1.gamesPlayed > 0,
|
||||||
Expanded(
|
label: "Played Tetra League",
|
||||||
child: Text(
|
trueIsBetter: false),
|
||||||
theGreenSide!.tlSeason1.gamesPlayed > 0 ? "Yes" : "No",
|
|
||||||
style: const TextStyle(fontSize: 22),
|
|
||||||
textAlign: TextAlign.start,
|
|
||||||
)),
|
|
||||||
Column(
|
|
||||||
children: const [
|
|
||||||
Text(
|
|
||||||
"Played Tetra League",
|
|
||||||
style: TextStyle(fontSize: 22),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
"---",
|
|
||||||
style: TextStyle(fontSize: 16),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
)
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
theRedSide!.tlSeason1.gamesPlayed > 0 ? "Yes" : "No",
|
|
||||||
style: const TextStyle(fontSize: 22),
|
|
||||||
textAlign: TextAlign.end,
|
|
||||||
)),
|
|
||||||
]),
|
|
||||||
),
|
|
||||||
const Divider(),
|
const Divider(),
|
||||||
if (theGreenSide!.tlSeason1.apm != null &&
|
if (theGreenSide!.tlSeason1.apm != null &&
|
||||||
theRedSide!.tlSeason1.apm != null &&
|
theRedSide!.tlSeason1.apm != null &&
|
||||||
|
@ -393,8 +423,8 @@ class CompareState extends State<CompareView> {
|
||||||
},
|
},
|
||||||
dataSets: [
|
dataSets: [
|
||||||
RadarDataSet(
|
RadarDataSet(
|
||||||
fillColor: const Color.fromARGB(117, 105, 240, 175),
|
fillColor: const Color.fromARGB(115, 76, 175, 79),
|
||||||
borderColor: Colors.greenAccent,
|
borderColor: Colors.green,
|
||||||
dataEntries: [
|
dataEntries: [
|
||||||
RadarEntry(value: theGreenSide!.tlSeason1.apm! * 1),
|
RadarEntry(value: theGreenSide!.tlSeason1.apm! * 1),
|
||||||
RadarEntry(value: theGreenSide!.tlSeason1.pps! * 45),
|
RadarEntry(value: theGreenSide!.tlSeason1.pps! * 45),
|
||||||
|
@ -409,8 +439,8 @@ class CompareState extends State<CompareView> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
RadarDataSet(
|
RadarDataSet(
|
||||||
fillColor: const Color.fromARGB(117, 255, 82, 82),
|
fillColor: const Color.fromARGB(115, 244, 67, 54),
|
||||||
borderColor: Colors.redAccent,
|
borderColor: Colors.red,
|
||||||
dataEntries: [
|
dataEntries: [
|
||||||
RadarEntry(value: theRedSide!.tlSeason1.apm! * 1),
|
RadarEntry(value: theRedSide!.tlSeason1.apm! * 1),
|
||||||
RadarEntry(value: theRedSide!.tlSeason1.pps! * 45),
|
RadarEntry(value: theRedSide!.tlSeason1.pps! * 45),
|
||||||
|
@ -482,8 +512,8 @@ class CompareState extends State<CompareView> {
|
||||||
},
|
},
|
||||||
dataSets: [
|
dataSets: [
|
||||||
RadarDataSet(
|
RadarDataSet(
|
||||||
fillColor: const Color.fromARGB(117, 105, 240, 175),
|
fillColor: Color.fromARGB(115, 76, 175, 79),
|
||||||
borderColor: Colors.greenAccent,
|
borderColor: Colors.green,
|
||||||
dataEntries: [
|
dataEntries: [
|
||||||
RadarEntry(value: theGreenSide!.tlSeason1.playstyle!.opener),
|
RadarEntry(value: theGreenSide!.tlSeason1.playstyle!.opener),
|
||||||
RadarEntry(value: theGreenSide!.tlSeason1.playstyle!.stride),
|
RadarEntry(value: theGreenSide!.tlSeason1.playstyle!.stride),
|
||||||
|
@ -492,8 +522,8 @@ class CompareState extends State<CompareView> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
RadarDataSet(
|
RadarDataSet(
|
||||||
fillColor: const Color.fromARGB(117, 255, 82, 82),
|
fillColor: Color.fromARGB(115, 244, 67, 54),
|
||||||
borderColor: Colors.redAccent,
|
borderColor: Colors.red,
|
||||||
dataEntries: [
|
dataEntries: [
|
||||||
RadarEntry(value: theRedSide!.tlSeason1.playstyle!.opener),
|
RadarEntry(value: theRedSide!.tlSeason1.playstyle!.opener),
|
||||||
RadarEntry(value: theRedSide!.tlSeason1.playstyle!.stride),
|
RadarEntry(value: theRedSide!.tlSeason1.playstyle!.stride),
|
||||||
|
@ -533,6 +563,17 @@ class CompareState extends State<CompareView> {
|
||||||
padding: const EdgeInsets.only(bottom: 16),
|
padding: const EdgeInsets.only(bottom: 16),
|
||||||
child: Text("Win Chance", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
child: Text("Win Chance", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||||
),
|
),
|
||||||
|
CompareThingy(
|
||||||
|
label: "By Glicko",
|
||||||
|
greenSide: getWinrateByTR(theGreenSide!.tlSeason1.glicko!, theGreenSide!.tlSeason1.rd!, theRedSide!.tlSeason1.glicko!,
|
||||||
|
theRedSide!.tlSeason1.rd!) *
|
||||||
|
100,
|
||||||
|
redSide: getWinrateByTR(theRedSide!.tlSeason1.glicko!, theRedSide!.tlSeason1.rd!, theGreenSide!.tlSeason1.glicko!,
|
||||||
|
theGreenSide!.tlSeason1.rd!) *
|
||||||
|
100,
|
||||||
|
fractionDigits: 2,
|
||||||
|
higherIsBetter: true,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
@ -566,9 +607,25 @@ class PlayerSelector extends StatelessWidget {
|
||||||
decoration: const InputDecoration(counter: Offstage()),
|
decoration: const InputDecoration(counter: Offstage()),
|
||||||
onSubmitted: (String value) {
|
onSubmitted: (String value) {
|
||||||
change(value);
|
change(value);
|
||||||
},
|
}),
|
||||||
|
if (player != null)
|
||||||
|
Text(
|
||||||
|
player!.toString(),
|
||||||
|
style: TextStyle(
|
||||||
|
shadows: <Shadow>[
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 3.0,
|
||||||
|
color: Colors.black,
|
||||||
),
|
),
|
||||||
if (player != null) Text(player!.toString())
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 8.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -598,12 +655,43 @@ class CompareThingy extends StatelessWidget {
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [Colors.green, Colors.transparent],
|
||||||
|
begin: Alignment.centerLeft,
|
||||||
|
end: Alignment.centerRight,
|
||||||
|
stops: [
|
||||||
|
0.0,
|
||||||
|
higherIsBetter
|
||||||
|
? greenSide > redSide
|
||||||
|
? 0.6
|
||||||
|
: 0
|
||||||
|
: greenSide < redSide
|
||||||
|
? 0.6
|
||||||
|
: 0
|
||||||
|
],
|
||||||
|
)),
|
||||||
child: Text(
|
child: Text(
|
||||||
f.format(greenSide),
|
f.format(greenSide),
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: 22,
|
fontSize: 22,
|
||||||
|
shadows: <Shadow>[
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 3.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 8.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
textAlign: TextAlign.start,
|
textAlign: TextAlign.start,
|
||||||
|
),
|
||||||
)),
|
)),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
|
@ -620,8 +708,216 @@ class CompareThingy extends StatelessWidget {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [Colors.red, Colors.transparent],
|
||||||
|
begin: Alignment.centerRight,
|
||||||
|
end: Alignment.centerLeft,
|
||||||
|
stops: [
|
||||||
|
0.0,
|
||||||
|
higherIsBetter
|
||||||
|
? redSide > greenSide
|
||||||
|
? 0.6
|
||||||
|
: 0
|
||||||
|
: redSide < greenSide
|
||||||
|
? 0.6
|
||||||
|
: 0
|
||||||
|
],
|
||||||
|
)),
|
||||||
child: Text(
|
child: Text(
|
||||||
f.format(redSide),
|
f.format(redSide),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
shadows: <Shadow>[
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 3.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 8.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CompareBoolThingy extends StatelessWidget {
|
||||||
|
final bool greenSide;
|
||||||
|
final bool redSide;
|
||||||
|
final String label;
|
||||||
|
final bool trueIsBetter;
|
||||||
|
const CompareBoolThingy({super.key, required this.greenSide, required this.redSide, required this.label, required this.trueIsBetter});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 2, 16, 2),
|
||||||
|
child: Row(children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [Colors.green, Colors.transparent],
|
||||||
|
begin: Alignment.centerLeft,
|
||||||
|
end: Alignment.centerRight,
|
||||||
|
stops: [
|
||||||
|
0.0,
|
||||||
|
trueIsBetter
|
||||||
|
? greenSide
|
||||||
|
? 0.6
|
||||||
|
: 0
|
||||||
|
: !greenSide
|
||||||
|
? 0.6
|
||||||
|
: 0
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
child: Text(
|
||||||
|
greenSide ? "Yes" : "No",
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
shadows: <Shadow>[
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 3.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 8.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
label,
|
||||||
|
style: const TextStyle(fontSize: 22),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const Text(
|
||||||
|
"---",
|
||||||
|
style: TextStyle(fontSize: 16),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [Colors.red, Colors.transparent],
|
||||||
|
begin: Alignment.centerRight,
|
||||||
|
end: Alignment.centerLeft,
|
||||||
|
stops: [
|
||||||
|
0.0,
|
||||||
|
trueIsBetter
|
||||||
|
? redSide
|
||||||
|
? 0.6
|
||||||
|
: 0
|
||||||
|
: !redSide
|
||||||
|
? 0.6
|
||||||
|
: 0
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
child: Text(
|
||||||
|
redSide ? "Yes" : "No",
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
shadows: <Shadow>[
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 3.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 8.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CompareDurationThingy extends StatelessWidget {
|
||||||
|
final Duration greenSide;
|
||||||
|
final Duration redSide;
|
||||||
|
final String label;
|
||||||
|
final bool higherIsBetter;
|
||||||
|
const CompareDurationThingy({super.key, required this.greenSide, required this.redSide, required this.label, required this.higherIsBetter});
|
||||||
|
|
||||||
|
Duration verdict(Duration greenSide, Duration redSide) {
|
||||||
|
return greenSide - redSide;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 2, 16, 2),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
greenSide.toString(),
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
)),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
label,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
shadows: <Shadow>[
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 3.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 8.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
verdict(greenSide, redSide).toString(),
|
||||||
|
style: const TextStyle(fontSize: 16),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
redSide.toString(),
|
||||||
style: const TextStyle(fontSize: 22),
|
style: const TextStyle(fontSize: 22),
|
||||||
textAlign: TextAlign.end,
|
textAlign: TextAlign.end,
|
||||||
)),
|
)),
|
||||||
|
@ -630,3 +926,119 @@ class CompareThingy extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CompareRegTimeThingy extends StatelessWidget {
|
||||||
|
final DateTime? greenSide;
|
||||||
|
final DateTime? redSide;
|
||||||
|
final String label;
|
||||||
|
final int? fractionDigits;
|
||||||
|
const CompareRegTimeThingy({super.key, required this.greenSide, required this.redSide, required this.label, this.fractionDigits});
|
||||||
|
|
||||||
|
String verdict(DateTime? greenSide, DateTime? redSide) {
|
||||||
|
var f = NumberFormat("#,### days later;#,### days before");
|
||||||
|
String result = "---";
|
||||||
|
if (greenSide != null && redSide != null) result = f.format(greenSide.difference(redSide).inDays);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
DateFormat f = DateFormat.yMMMd();
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.fromLTRB(16, 2, 16, 2),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [Colors.green, Colors.transparent],
|
||||||
|
begin: Alignment.centerLeft,
|
||||||
|
end: Alignment.centerRight,
|
||||||
|
stops: [
|
||||||
|
0.0,
|
||||||
|
greenSide == null
|
||||||
|
? 0.6
|
||||||
|
: redSide != null && greenSide!.isBefore(redSide!)
|
||||||
|
? 0.6
|
||||||
|
: 0
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
child: Text(
|
||||||
|
greenSide != null ? f.format(greenSide!) : "From beginning",
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
shadows: <Shadow>[
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 3.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 8.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.start,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
label,
|
||||||
|
style: const TextStyle(fontSize: 22),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
verdict(greenSide, redSide),
|
||||||
|
style: const TextStyle(fontSize: 16),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Container(
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
gradient: LinearGradient(
|
||||||
|
colors: [Colors.red, Colors.transparent],
|
||||||
|
begin: Alignment.centerRight,
|
||||||
|
end: Alignment.centerLeft,
|
||||||
|
stops: [
|
||||||
|
0.0,
|
||||||
|
redSide == null
|
||||||
|
? 0.6
|
||||||
|
: greenSide != null && redSide!.isBefore(greenSide!)
|
||||||
|
? 0.6
|
||||||
|
: 0
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
child: Text(
|
||||||
|
redSide != null ? f.format(redSide!) : "From beginning",
|
||||||
|
style: const TextStyle(
|
||||||
|
fontSize: 22,
|
||||||
|
shadows: <Shadow>[
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 3.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
Shadow(
|
||||||
|
offset: Offset(0.0, 0.0),
|
||||||
|
blurRadius: 8.0,
|
||||||
|
color: Colors.black,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.end,
|
||||||
|
),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'dart:developer' as developer;
|
import 'dart:developer' as developer;
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
@ -16,6 +17,8 @@ late SharedPreferences prefs;
|
||||||
const allowedHeightForPlayerIdInPixels = 40.0;
|
const allowedHeightForPlayerIdInPixels = 40.0;
|
||||||
const allowedHeightForPlayerBioInPixels = 30.0;
|
const allowedHeightForPlayerBioInPixels = 30.0;
|
||||||
const givenTextHeightByScreenPercentage = 0.3;
|
const givenTextHeightByScreenPercentage = 0.3;
|
||||||
|
final NumberFormat timeInSec = NumberFormat("#,###.###s.");
|
||||||
|
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);
|
||||||
|
@ -364,10 +367,18 @@ class _RecordThingy extends StatelessWidget {
|
||||||
else if (record!.stream.contains("blitz"))
|
else if (record!.stream.contains("blitz"))
|
||||||
Text("Blitz", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
Text("Blitz", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||||
if (record!.stream.contains("40l"))
|
if (record!.stream.contains("40l"))
|
||||||
Text(record!.endContext!.finalTime.toString(), style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28))
|
Text(timeInSec.format(record!.endContext!.finalTime.inMicroseconds / 1000000),
|
||||||
|
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28))
|
||||||
else if (record!.stream.contains("blitz"))
|
else if (record!.stream.contains("blitz"))
|
||||||
Text(record!.endContext!.score.toString(), style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
Text(NumberFormat.decimalPattern().format(record!.endContext!.score),
|
||||||
|
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||||
if (record!.rank != null) StatCellNum(playerStat: record!.rank!, playerStatLabel: "Leaderboard Placement", isScreenBig: bigScreen),
|
if (record!.rank != null) StatCellNum(playerStat: record!.rank!, playerStatLabel: "Leaderboard Placement", isScreenBig: bigScreen),
|
||||||
|
Text("Obtained ${dateFormat.format(record!.timestamp!)}",
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(
|
||||||
|
fontFamily: "Eurostile Round",
|
||||||
|
fontSize: 16,
|
||||||
|
)),
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.fromLTRB(0, 48, 0, 48),
|
padding: const EdgeInsets.fromLTRB(0, 48, 0, 48),
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
|
@ -586,11 +597,9 @@ class _OtherThingy extends StatelessWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
Text("Zen", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
Text("Zen", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||||
Text("Level ${zen!.level}", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
Text("Level ${NumberFormat.decimalPattern().format(zen!.level)}",
|
||||||
Text(
|
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||||
"Score ${zen!.score}",
|
Text("Score ${NumberFormat.decimalPattern().format(zen!.score)}", style: const TextStyle(fontSize: 18)),
|
||||||
style: const TextStyle(fontSize: 18),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
|
@ -108,7 +108,12 @@ class SettingsState extends State<SettingsView> {
|
||||||
const Divider(),
|
const Divider(),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text("About app"),
|
title: const Text("About app"),
|
||||||
subtitle: Text("${_packageInfo.appName} (${_packageInfo.packageName}) Version ${_packageInfo.version} Build ${_packageInfo.buildNumber}"),
|
subtitle: Text("""
|
||||||
|
${_packageInfo.appName} (${_packageInfo.packageName}) Version ${_packageInfo.version} Build ${_packageInfo.buildNumber}
|
||||||
|
|
||||||
|
Developed by dan63047
|
||||||
|
Formulas provided by kerrmunism
|
||||||
|
"""),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/tetrio.dart';
|
||||||
|
import 'package:tetra_stats/views/compare_view.dart';
|
||||||
import 'package:tetra_stats/views/state_view.dart';
|
import 'package:tetra_stats/views/state_view.dart';
|
||||||
|
|
||||||
class StatesView extends StatefulWidget {
|
class StatesView extends StatefulWidget {
|
||||||
|
@ -10,6 +12,8 @@ class StatesView extends StatefulWidget {
|
||||||
State<StatefulWidget> createState() => StatesState();
|
State<StatefulWidget> createState() => StatesState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final DateFormat dateFormat = DateFormat.yMMMd().add_Hms();
|
||||||
|
|
||||||
class StatesState extends State<StatesView> {
|
class StatesState extends State<StatesView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -23,11 +27,16 @@ class StatesState extends State<StatesView> {
|
||||||
itemCount: widget.states.length,
|
itemCount: widget.states.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text("On ${widget.states[index].state}"),
|
title: Text("On ${dateFormat.format(widget.states[index].state)}"),
|
||||||
subtitle: Text("Level ${widget.states[index].level.toStringAsFixed(2)} level, ${widget.states[index].gameTime} of gametime"),
|
subtitle: Text("Level ${widget.states[index].level.toStringAsFixed(2)} level, ${widget.states[index].gameTime} of gametime"),
|
||||||
trailing: IconButton(
|
trailing: IconButton(
|
||||||
icon: const Icon(Icons.delete_forever),
|
icon: const Icon(Icons.delete_forever),
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
DateTime nn = widget.states[index].state;
|
||||||
|
teto.deleteState(widget.states[index]).then((value) => setState(() {
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("${dateFormat.format(nn)} state was removed from database!")));
|
||||||
|
}));
|
||||||
|
},
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/tetrio.dart';
|
||||||
import 'package:tetra_stats/services/tetrio_crud.dart';
|
import 'package:tetra_stats/services/tetrio_crud.dart';
|
||||||
import 'package:tetra_stats/views/states_view.dart';
|
import 'package:tetra_stats/views/states_view.dart';
|
||||||
|
@ -12,6 +13,8 @@ class TrackedPlayersView extends StatefulWidget {
|
||||||
State<StatefulWidget> createState() => TrackedPlayersState();
|
State<StatefulWidget> createState() => TrackedPlayersState();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final DateFormat dateFormat = DateFormat.yMMMd().add_Hms();
|
||||||
|
|
||||||
class TrackedPlayersState extends State<TrackedPlayersView> {
|
class TrackedPlayersState extends State<TrackedPlayersView> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -33,12 +36,22 @@ class TrackedPlayersState extends State<TrackedPlayersView> {
|
||||||
List<String> keys = allPlayers.keys.toList();
|
List<String> keys = allPlayers.keys.toList();
|
||||||
return NestedScrollView(
|
return NestedScrollView(
|
||||||
headerSliverBuilder: (context, value) {
|
headerSliverBuilder: (context, value) {
|
||||||
|
String howManyPlayers(int numberOfPlayers) => Intl.plural(
|
||||||
|
numberOfPlayers,
|
||||||
|
zero: 'Empty list. Press "Track" button in previous view to add current player here',
|
||||||
|
one: 'There is only one player',
|
||||||
|
other: 'There are $numberOfPlayers players',
|
||||||
|
name: 'howManyPeople',
|
||||||
|
args: [numberOfPlayers],
|
||||||
|
desc: 'Description of how many people are seen in a place.',
|
||||||
|
examples: const {'numberOfPeople': 3},
|
||||||
|
);
|
||||||
return [
|
return [
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.only(left: 16),
|
padding: const EdgeInsets.only(left: 16),
|
||||||
child: Text(
|
child: Text(
|
||||||
'There are ${allPlayers.length} players',
|
howManyPlayers(allPlayers.length),
|
||||||
style: const TextStyle(color: Colors.white, fontSize: 25),
|
style: const TextStyle(color: Colors.white, fontSize: 25),
|
||||||
),
|
),
|
||||||
)),
|
)),
|
||||||
|
@ -50,10 +63,15 @@ class TrackedPlayersState extends State<TrackedPlayersView> {
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return ListTile(
|
return ListTile(
|
||||||
title: Text("${allPlayers[keys[index]]?.last.username}: ${allPlayers[keys[index]]?.length} states"),
|
title: Text("${allPlayers[keys[index]]?.last.username}: ${allPlayers[keys[index]]?.length} states"),
|
||||||
subtitle: Text("From ${allPlayers[keys[index]]?.first.state} until ${allPlayers[keys[index]]?.last.state}"),
|
subtitle: Text(
|
||||||
|
"From ${dateFormat.format(allPlayers[keys[index]]!.first.state)} until ${dateFormat.format(allPlayers[keys[index]]!.last.state)}"),
|
||||||
trailing: IconButton(
|
trailing: IconButton(
|
||||||
icon: const Icon(Icons.delete_forever),
|
icon: const Icon(Icons.delete_forever),
|
||||||
onPressed: () {},
|
onPressed: () {
|
||||||
|
String nn = allPlayers[keys[index]]!.last.username;
|
||||||
|
teto.deletePlayer(keys[index]);
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("$nn states was removed from database!")));
|
||||||
|
},
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.push(
|
Navigator.push(
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
|
||||||
class StatCellNum extends StatelessWidget {
|
class StatCellNum extends StatelessWidget {
|
||||||
const StatCellNum({super.key, required this.playerStat, required this.playerStatLabel, required this.isScreenBig, this.snackBar, this.fractionDigits});
|
const StatCellNum({super.key, required this.playerStat, required this.playerStatLabel, required this.isScreenBig, this.snackBar, this.fractionDigits});
|
||||||
|
@ -11,10 +12,11 @@ class StatCellNum extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
NumberFormat f = NumberFormat.decimalPatternDigits(decimalDigits: fractionDigits ?? 0);
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
fractionDigits != null ? playerStat.toStringAsFixed(fractionDigits!) : playerStat.floor().toString(),
|
f.format(playerStat),
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: "Eurostile Round Extended",
|
fontFamily: "Eurostile Round Extended",
|
||||||
fontSize: isScreenBig ? 32 : 24,
|
fontSize: isScreenBig ? 32 : 24,
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
import 'package:tetra_stats/data_objects/tetrio.dart';
|
import 'package:tetra_stats/data_objects/tetrio.dart';
|
||||||
import 'package:fl_chart/fl_chart.dart';
|
import 'package:fl_chart/fl_chart.dart';
|
||||||
import 'package:tetra_stats/widgets/stat_sell_num.dart';
|
import 'package:tetra_stats/widgets/stat_sell_num.dart';
|
||||||
|
|
||||||
|
var fDiff = NumberFormat("+#,###.###;-#,###.###");
|
||||||
|
final NumberFormat f2 = NumberFormat.decimalPatternDigits(decimalDigits: 2);
|
||||||
|
|
||||||
class TLThingy extends StatelessWidget {
|
class TLThingy extends StatelessWidget {
|
||||||
final TetraLeagueAlpha tl;
|
final TetraLeagueAlpha tl;
|
||||||
final String userID;
|
final String userID;
|
||||||
|
@ -32,10 +36,9 @@ class TLThingy extends StatelessWidget {
|
||||||
: Image.asset("res/tetrio_tl_alpha_ranks/${tl.rank}.png", height: 128),
|
: Image.asset("res/tetrio_tl_alpha_ranks/${tl.rank}.png", height: 128),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
Text("${tl.rating.toStringAsFixed(2)} TR",
|
Text("${f2.format(tl.rating)} TR", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
||||||
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
|
|
||||||
Text(
|
Text(
|
||||||
"Top ${(tl.percentile * 100).toStringAsFixed(2)}% (${tl.percentileRank.toUpperCase()}) • Top Rank: ${tl.bestRank.toUpperCase()} • Glicko: ${tl.glicko?.toStringAsFixed(2)}±${tl.rd?.toStringAsFixed(2)}${tl.decaying ? ' • Decaying' : ''}",
|
"Top ${f2.format(tl.percentile * 100)}% (${tl.percentileRank.toUpperCase()}) • Top Rank: ${tl.bestRank.toUpperCase()} • Glicko: ${f2.format(tl.glicko!)}±${f2.format(tl.rd!)}${tl.decaying ? ' • Decaying' : ''}",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -45,6 +48,7 @@ class TLThingy extends StatelessWidget {
|
||||||
else
|
else
|
||||||
Text("${10 - tl.gamesPlayed} games until being ranked",
|
Text("${10 - tl.gamesPlayed} games until being ranked",
|
||||||
softWrap: true,
|
softWrap: true,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: "Eurostile Round Extended",
|
fontFamily: "Eurostile Round Extended",
|
||||||
fontSize: bigScreen ? 42 : 28,
|
fontSize: bigScreen ? 42 : 28,
|
||||||
|
@ -116,7 +120,7 @@ class TLThingy extends StatelessWidget {
|
||||||
style: TextStyle(fontSize: 24),
|
style: TextStyle(fontSize: 24),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
tl.estTr!.esttr.toStringAsFixed(2),
|
f2.format(tl.estTr!.esttr),
|
||||||
style: const TextStyle(fontSize: 24),
|
style: const TextStyle(fontSize: 24),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -130,7 +134,7 @@ class TLThingy extends StatelessWidget {
|
||||||
style: TextStyle(fontSize: 24),
|
style: TextStyle(fontSize: 24),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
tl.esttracc!.toStringAsFixed(2),
|
fDiff.format(tl.esttracc!),
|
||||||
style: const TextStyle(fontSize: 24),
|
style: const TextStyle(fontSize: 24),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.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';
|
||||||
import 'package:tetra_stats/views/compare_view.dart';
|
import 'package:tetra_stats/views/compare_view.dart';
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
import 'dart:developer' as developer;
|
import 'dart:developer' as developer;
|
||||||
import 'package:tetra_stats/widgets/stat_sell_num.dart';
|
import 'package:tetra_stats/widgets/stat_sell_num.dart';
|
||||||
|
|
||||||
|
@ -15,6 +16,8 @@ Future<void> copyToClipboard(String text) async {
|
||||||
await Clipboard.setData(ClipboardData(text: text));
|
await Clipboard.setData(ClipboardData(text: text));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final DateFormat dateFormat = DateFormat.yMMMd().add_Hms();
|
||||||
|
|
||||||
class UserThingy extends StatelessWidget {
|
class UserThingy extends StatelessWidget {
|
||||||
final TetrioPlayer player;
|
final TetrioPlayer player;
|
||||||
final bool showStateTimestamp;
|
final bool showStateTimestamp;
|
||||||
|
@ -102,7 +105,7 @@ class UserThingy extends StatelessWidget {
|
||||||
],
|
],
|
||||||
)),
|
)),
|
||||||
showStateTimestamp
|
showStateTimestamp
|
||||||
? Text("Fetched ${player.state}")
|
? Text("Fetched ${dateFormat.format(player.state)}")
|
||||||
: Wrap(direction: Axis.horizontal, alignment: WrapAlignment.center, spacing: 25, crossAxisAlignment: WrapCrossAlignment.start, children: [
|
: Wrap(direction: Axis.horizontal, alignment: WrapAlignment.center, spacing: 25, crossAxisAlignment: WrapCrossAlignment.start, children: [
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: teto.isPlayerTracking(player.userId),
|
future: teto.isPlayerTracking(player.userId),
|
||||||
|
@ -209,7 +212,7 @@ class UserThingy extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
"${player.country != null ? "${player.country?.toUpperCase()} • " : ""}${player.role.capitalize()} account ${player.registrationTime == null ? "that was from very beginning" : 'created ${player.registrationTime}'}${player.botmaster != null ? " by ${player.botmaster}" : ""} • ${player.supporterTier == 0 ? "Not a supporter" : "Supporter tier ${player.supporterTier}"}",
|
"${player.country != null ? "${player.country?.toUpperCase()} • " : ""}${player.role.capitalize()} account ${player.registrationTime == null ? "that was from very beginning" : 'created ${dateFormat.format(player.registrationTime!)}'}${player.botmaster != null ? " by ${player.botmaster}" : ""} • ${player.supporterTier == 0 ? "Not a supporter" : "Supporter tier ${player.supporterTier}"}",
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontFamily: "Eurostile Round",
|
fontFamily: "Eurostile Round",
|
||||||
|
@ -245,7 +248,9 @@ class UserThingy extends StatelessWidget {
|
||||||
spacing: 25,
|
spacing: 25,
|
||||||
children: [
|
children: [
|
||||||
Image.asset("res/tetrio_badges/${badge.badgeId}.png"),
|
Image.asset("res/tetrio_badges/${badge.badgeId}.png"),
|
||||||
Text(badge.ts != null ? "Obtained ${badge.ts}" : "That badge was assigned manualy by TETR.IO admins"),
|
Text(badge.ts != null
|
||||||
|
? "Obtained ${dateFormat.format(badge.ts!)}"
|
||||||
|
: "That badge was assigned manualy by TETR.IO admins"),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
|
|
|
@ -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.0.2+2
|
version: 0.1.0+3
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: '>=2.19.6 <3.0.0'
|
sdk: '>=2.19.6 <3.0.0'
|
||||||
|
|
Loading…
Reference in New Issue