fix #81 , colors for achievements, achievements for tl and qp and erm...
This commit is contained in:
parent
c1b9db3b15
commit
16abd4c15c
|
@ -45,6 +45,27 @@ const List<String> ranks = [
|
|||
"x",
|
||||
"x+"
|
||||
];
|
||||
const List<String> ranks2 = [
|
||||
"top1",
|
||||
"x+",
|
||||
"x",
|
||||
"u",
|
||||
"ss",
|
||||
"s+",
|
||||
"s",
|
||||
"s-",
|
||||
"a+",
|
||||
"a",
|
||||
"a-",
|
||||
"b+",
|
||||
"b",
|
||||
"b-",
|
||||
"c+",
|
||||
"c",
|
||||
"c-",
|
||||
"d+",
|
||||
"d"
|
||||
];
|
||||
const Map<String, double> rankCutoffs = {
|
||||
"x+": 0.002,
|
||||
"x": 0.01,
|
||||
|
@ -178,6 +199,16 @@ const Map<String, Color> rankColors = {
|
|||
'top1': Colors.yellowAccent
|
||||
};
|
||||
|
||||
const List<Color> achievementColors = [
|
||||
Colors.grey,
|
||||
Color(0xFFB38070), // bronze
|
||||
Color(0xFF7E9EA7), // silver
|
||||
Color(0xFFE2A042), // gold
|
||||
Color(0xFF70D0A3), // platinum
|
||||
Color(0xFFD590FF), // diamond
|
||||
Colors.white,
|
||||
];
|
||||
|
||||
const Map<String, Duration> sprintAverages = {
|
||||
// based on https://discord.com/channels/673303546107658242/674421736162197515/1277367281264889908
|
||||
'x+': Duration(seconds: 18, milliseconds: 867),
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
/// To regenerate, run: `dart run slang`
|
||||
///
|
||||
/// Locales: 2
|
||||
/// Strings: 1528 (764 per locale)
|
||||
/// Strings: 1530 (765 per locale)
|
||||
///
|
||||
/// Built on 2024-12-12 at 21:30 UTC
|
||||
/// Built on 2024-12-21 at 17:08 UTC
|
||||
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
|
@ -187,6 +187,7 @@ class Translations implements BaseTranslations<AppLocale, Translations> {
|
|||
String get nerdStats => 'Nerd Stats';
|
||||
String get playstyles => 'Playstyles';
|
||||
String get horoscopes => 'Horoscopes';
|
||||
String get relatedAchievements => 'Related Achievements';
|
||||
String get season => 'Season';
|
||||
String get smooth => 'Smooth';
|
||||
String get dateAndTime => 'Date & Time';
|
||||
|
@ -890,7 +891,7 @@ class _StringsSettingsDestinationEn {
|
|||
// Translations
|
||||
String get title => 'Settings';
|
||||
String get general => 'General';
|
||||
String get customization => 'Custonization';
|
||||
String get customization => 'Customization';
|
||||
String get database => 'Local database';
|
||||
String get checking => 'Checking...';
|
||||
String get enterToSubmit => 'Press Enter to submit';
|
||||
|
@ -1726,6 +1727,7 @@ class _StringsRuRu implements Translations {
|
|||
@override String get nerdStats => 'Для Задротов';
|
||||
@override String get playstyles => 'Стили игры';
|
||||
@override String get horoscopes => 'Гороскопы';
|
||||
@override String get relatedAchievements => 'Достижения режима';
|
||||
@override String get season => 'Сезон';
|
||||
@override String get smooth => 'Сглаживание';
|
||||
@override String get dateAndTime => 'Дата и время';
|
||||
|
@ -3248,6 +3250,7 @@ extension on Translations {
|
|||
case 'nerdStats': return 'Nerd Stats';
|
||||
case 'playstyles': return 'Playstyles';
|
||||
case 'horoscopes': return 'Horoscopes';
|
||||
case 'relatedAchievements': return 'Related Achievements';
|
||||
case 'season': return 'Season';
|
||||
case 'smooth': return 'Smooth';
|
||||
case 'dateAndTime': return 'Date & Time';
|
||||
|
@ -3477,7 +3480,7 @@ extension on Translations {
|
|||
case 'savedDataDestination.TLrecords': return 'TL Records';
|
||||
case 'settingsDestination.title': return 'Settings';
|
||||
case 'settingsDestination.general': return 'General';
|
||||
case 'settingsDestination.customization': return 'Custonization';
|
||||
case 'settingsDestination.customization': return 'Customization';
|
||||
case 'settingsDestination.database': return 'Local database';
|
||||
case 'settingsDestination.checking': return 'Checking...';
|
||||
case 'settingsDestination.enterToSubmit': return 'Press Enter to submit';
|
||||
|
@ -4061,6 +4064,7 @@ extension on _StringsRuRu {
|
|||
case 'nerdStats': return 'Для Задротов';
|
||||
case 'playstyles': return 'Стили игры';
|
||||
case 'horoscopes': return 'Гороскопы';
|
||||
case 'relatedAchievements': return 'Достижения режима';
|
||||
case 'season': return 'Сезон';
|
||||
case 'smooth': return 'Сглаживание';
|
||||
case 'dateAndTime': return 'Дата и время';
|
||||
|
|
|
@ -35,7 +35,7 @@ import 'package:tetra_stats/services/sqlite_db_controller.dart';
|
|||
import 'package:csv/csv.dart';
|
||||
|
||||
const String dbName = "TetraStats.db";
|
||||
const String webVersionDomain = "tsbeta.dan63.by";
|
||||
const String webVersionDomain = "ts.dan63.by";
|
||||
const String tetrioUsersTable = "tetrioUsers";
|
||||
const String tetrioUsersToTrackTable = "tetrioUsersToTrack";
|
||||
const String tetraLeagueMatchesTable = "tetrioAlphaLeagueMathces";
|
||||
|
@ -831,7 +831,12 @@ class TetrioService extends DB {
|
|||
|
||||
Uri url;
|
||||
if (kIsWeb) {
|
||||
url = Uri.https(webVersionDomain, 'oskware_bridge.php', {"endpoint": "TLLeaderboard"});
|
||||
url = Uri.https(webVersionDomain, 'oskware_bridge.php', {
|
||||
"endpoint": "leaderboard",
|
||||
"lb": lb??"league",
|
||||
if (prisecter != null) "after": prisecter,
|
||||
if (country != null) "country": country
|
||||
});
|
||||
} else {
|
||||
url = Uri.https('ch.tetr.io', 'api/users/by/${lb??"league"}', {
|
||||
"limit": "100",
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
import 'dart:math';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_layout_grid/flutter_layout_grid.dart';
|
||||
import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
|
@ -15,6 +17,7 @@ import 'package:tetra_stats/data_objects/summaries.dart';
|
|||
import 'package:tetra_stats/data_objects/tetra_league.dart';
|
||||
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||
import 'package:tetra_stats/data_objects/tetrio_player.dart';
|
||||
import 'package:tetra_stats/data_objects/tetrio_player_from_leaderboard.dart';
|
||||
import 'package:tetra_stats/gen/strings.g.dart';
|
||||
import 'package:tetra_stats/main.dart';
|
||||
import 'package:tetra_stats/utils/colors_functions.dart';
|
||||
|
@ -120,8 +123,9 @@ class ZenithCard extends StatelessWidget {
|
|||
final RecordSingle? record;
|
||||
final bool old;
|
||||
final double width;
|
||||
final List<Achievement> achievements;
|
||||
|
||||
const ZenithCard(this.record, this.old, {this.width = double.infinity});
|
||||
const ZenithCard(this.record, this.old, this.achievements, {this.width = double.infinity});
|
||||
|
||||
Widget splitsCard(){
|
||||
return Card(
|
||||
|
@ -246,7 +250,23 @@ class ZenithCard extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
if (record != null) NerdStatsThingy(nerdStats: record!.aggregateStats.nerdStats, width: width),
|
||||
if (record != null) Graphs(record!.aggregateStats.apm, record!.aggregateStats.pps, record!.aggregateStats.vs, record!.aggregateStats.nerdStats, record!.aggregateStats.playstyle)
|
||||
if (record != null) Graphs(record!.aggregateStats.apm, record!.aggregateStats.pps, record!.aggregateStats.vs, record!.aggregateStats.nerdStats, record!.aggregateStats.playstyle),
|
||||
if (achievements.isNotEmpty) Card(
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Spacer(),
|
||||
Text(t.relatedAchievements, style: Theme.of(context).textTheme.titleLarge),
|
||||
const Spacer()
|
||||
],
|
||||
),
|
||||
),
|
||||
if (achievements.isNotEmpty) Wrap(
|
||||
direction: Axis.horizontal,
|
||||
children: [
|
||||
for (Achievement achievement in achievements) FractionallySizedBox(widthFactor: 1/((width/600).ceil()), child: AchievementSummary(achievement: achievement)),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -573,11 +593,10 @@ class AchievementSummary extends StatelessWidget{
|
|||
),
|
||||
child: ClipRect(
|
||||
child: Align(
|
||||
alignment: Alignment.topLeft.add(Alignment(0.285 * (((achievement?.k??1) - 1) % 8), 0.285 * (((achievement?.k??0) - 1) / 8).floor())),
|
||||
//alignment: Alignment.topLeft.add(Alignment(0.285 * 1, 0)),
|
||||
alignment: Alignment.topLeft.add(Alignment(0.286 * (((achievement?.k??1) - 1) % 8), 0.286 * (((achievement?.k??0) - 1) / 8).floor())),
|
||||
heightFactor: 0.125,
|
||||
widthFactor: 0.125,
|
||||
child: Image.asset("res/icons/achievements.png", width: 2048, height: 2048, scale: 1, color: achievement?.v == null ? Colors.grey : Colors.white),
|
||||
child: Image.asset("res/icons/achievements.png", width: 2048, height: 2048, scale: 1, color: achievement?.v == null ? Colors.grey : achievementColors[min(achievement!.rank!, 6)]),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -718,7 +737,6 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
1 2
|
||||
3 4
|
||||
5 6
|
||||
7 7
|
||||
''' : '''
|
||||
t
|
||||
1
|
||||
|
@ -727,10 +745,9 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
4
|
||||
5
|
||||
6
|
||||
7
|
||||
''',
|
||||
columnSizes: width > 600 ? [auto, auto] : [auto],
|
||||
rowSizes: width > 600 ? [auto, auto, auto, auto, auto, auto] : [auto, auto, auto, auto, auto, auto, auto, auto],
|
||||
rowSizes: width > 600 ? [auto, auto, auto, auto, auto] : [auto, auto, auto, auto, auto, auto, auto],
|
||||
columnGap: 0,
|
||||
rowGap: 0,
|
||||
children: [
|
||||
|
@ -869,34 +886,11 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
),
|
||||
),
|
||||
).inGridArea('6'),
|
||||
if (summaries.achievements.isNotEmpty) Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20.0, 0.0, 20.0, 0.0),
|
||||
child: Column(
|
||||
children: [
|
||||
if (summaries.achievements.firstWhere((e) => e.k == 16).v != null) Row(
|
||||
children: [
|
||||
const Text("Total height climbed in QP"),
|
||||
const Spacer(),
|
||||
Text("${f2.format(summaries.achievements.firstWhere((e) => e.k == 16).v!)} m"),
|
||||
],
|
||||
),
|
||||
if (summaries.achievements.firstWhere((e) => e.k == 17).v != null) Row(
|
||||
children: [
|
||||
const Text("KO's in QP"),
|
||||
const Spacer(),
|
||||
Text(intf.format(summaries.achievements.firstWhere((e) => e.k == 17).v!)),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
).inGridArea('7')
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
Widget getTetraLeagueCard(TetraLeague data, Cutoffs? cutoffs, CutoffTetrio? averages, List<TetraLeague> states, PlayerLeaderboardPosition? lbPos, double width){
|
||||
Widget getTetraLeagueCard(TetraLeague data, Cutoffs? cutoffs, CutoffTetrio? averages, List<TetraLeague> states, PlayerLeaderboardPosition? lbPos, double width, List<Achievement> achievements){
|
||||
TetraLeague toSee;
|
||||
TetraLeague? toCompare;
|
||||
if (currentRangeValues.start.round() == 0){
|
||||
|
@ -963,7 +957,24 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
),
|
||||
),
|
||||
if (data.nerdStats != null) NerdStatsThingy(nerdStats: toSee.nerdStats!, oldNerdStats: toCompare?.nerdStats, averages: averages, lbPos: lbPos, width: width),
|
||||
if (data.nerdStats != null) Graphs(toSee.apm!, toSee.pps!, toSee.vs!, toSee.nerdStats!, toSee.playstyle!)
|
||||
if (data.nerdStats != null) Graphs(toSee.apm!, toSee.pps!, toSee.vs!, toSee.nerdStats!, toSee.playstyle!),
|
||||
Card(
|
||||
//surfaceTintColor: rankColors[data.rank],
|
||||
child: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Spacer(),
|
||||
Text(t.relatedAchievements, style: Theme.of(context).textTheme.titleLarge),
|
||||
const Spacer()
|
||||
],
|
||||
),
|
||||
),
|
||||
Wrap(
|
||||
direction: Axis.horizontal,
|
||||
children: [
|
||||
for (Achievement achievement in achievements) FractionallySizedBox(widthFactor: 1/((width/600).ceil()), child: AchievementSummary(achievement: achievement)),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -1164,19 +1175,19 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
super.initState();
|
||||
}
|
||||
|
||||
Widget rigthCard(AsyncSnapshot<FetchResults> snapshot, List<Achievement> sprintAchievements, List<Achievement> blitzAchievements, double width){
|
||||
Widget rigthCard(AsyncSnapshot<FetchResults> snapshot, List<Achievement> sprintAchievements, List<Achievement> blitzAchievements, List<Achievement> tlAchievements, List<Achievement> qpAchievements, List<Achievement> qpExAchievements, double width){
|
||||
return switch (rightCard){
|
||||
Cards.overview => getOverviewCard(snapshot.data!.summaries!, (snapshot.data!.averages != null && snapshot.data!.summaries!.league.rank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.rank] : (snapshot.data!.averages != null && snapshot.data!.summaries!.league.percentileRank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.percentileRank] : null, width),
|
||||
Cards.tetraLeague => switch (cardMod){
|
||||
CardMod.info => getTetraLeagueCard(snapshot.data!.summaries!.league, snapshot.data!.cutoffs, (snapshot.data!.averages != null && snapshot.data!.summaries!.league.rank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.rank] : (snapshot.data!.averages != null && snapshot.data!.summaries!.league.percentileRank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.percentileRank] : null, snapshot.data!.states, snapshot.data!.playerPos, width),
|
||||
CardMod.info => getTetraLeagueCard(snapshot.data!.summaries!.league, snapshot.data!.cutoffs, (snapshot.data!.averages != null && snapshot.data!.summaries!.league.rank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.rank] : (snapshot.data!.averages != null && snapshot.data!.summaries!.league.percentileRank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.percentileRank] : null, snapshot.data!.states, snapshot.data!.playerPos, width, tlAchievements),
|
||||
CardMod.ex => getPreviousSeasonsList(snapshot.data!.summaries!.pastLeague, width),
|
||||
CardMod.records => getRecentTLrecords(widget.constraints, snapshot.data!.player!.userId),
|
||||
_ => const Center(child: Text("huh?"))
|
||||
},
|
||||
Cards.quickPlay => switch (cardMod){
|
||||
CardMod.info => ZenithCard(snapshot.data?.summaries?.zenith != null ? snapshot.data!.summaries!.zenith : snapshot.data!.summaries?.zenithCareerBest, snapshot.data!.summaries?.zenith == null, width: width),
|
||||
CardMod.info => ZenithCard(snapshot.data?.summaries?.zenith != null ? snapshot.data!.summaries!.zenith : snapshot.data!.summaries?.zenithCareerBest, snapshot.data!.summaries?.zenith == null, qpAchievements, width: width),
|
||||
CardMod.records => getListOfRecords("zenith/recent", "zenith/top", widget.constraints),
|
||||
CardMod.ex => ZenithCard(snapshot.data?.summaries?.zenithEx != null ? snapshot.data!.summaries!.zenithEx : snapshot.data!.summaries?.zenithExCareerBest, snapshot.data!.summaries?.zenithEx == null, width: width),
|
||||
CardMod.ex => ZenithCard(snapshot.data?.summaries?.zenithEx != null ? snapshot.data!.summaries!.zenithEx : snapshot.data!.summaries?.zenithExCareerBest, snapshot.data!.summaries?.zenithEx == null, qpExAchievements, width: width),
|
||||
CardMod.exRecords => getListOfRecords("zenithex/recent", "zenithex/top", widget.constraints),
|
||||
},
|
||||
Cards.sprint => switch (cardMod){
|
||||
|
@ -1224,6 +1235,48 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
closestAverageBlitz = blitzAverages.entries.last;
|
||||
blitzBetterThanClosestAverage = false;
|
||||
}
|
||||
List<Achievement> tlAchievements = snapshot.data!.summaries!.achievements.isNotEmpty ? <Achievement>[
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 10),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 12),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 13),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 14),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 15),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 47),
|
||||
] : [];
|
||||
List<Achievement> qpAchievements = snapshot.data!.summaries!.achievements.isNotEmpty ? <Achievement>[
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 16),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 17),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 18),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 20),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 21),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 22),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 23),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 24),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 25),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 26),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 27),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 28),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 29),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 30),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 33),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 41),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 43),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 44),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 45),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 46),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 51),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 54),
|
||||
] : [];
|
||||
List<Achievement> qpExAchievements = snapshot.data!.summaries!.achievements.isNotEmpty ? <Achievement>[
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 19),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 31),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 32),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 34),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 40),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 49),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 50),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 53),
|
||||
] : [];
|
||||
List<Achievement> sprintAchievements = snapshot.data!.summaries!.achievements.isNotEmpty ? <Achievement>[
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 5),
|
||||
snapshot.data!.summaries!.achievements.firstWhere((e) => e.k == 7),
|
||||
|
@ -1293,7 +1346,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
child: SlideTransition(
|
||||
position: _offsetAnimation,
|
||||
child: SingleChildScrollView(
|
||||
child: rigthCard(snapshot, sprintAchievements, blitzAchievements, width - 450),
|
||||
child: rigthCard(snapshot, sprintAchievements, blitzAchievements, tlAchievements, qpAchievements, qpExAchievements, width - 450),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@ -1351,7 +1404,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
if (snapshot.data!.player!.role == "bot") FakeDistinguishmentThingy(bot: true, botMaintainers: snapshot.data!.player!.botmaster),
|
||||
if (snapshot.data!.player!.role == "banned") FakeDistinguishmentThingy(banned: true)
|
||||
else if (snapshot.data!.player!.badstanding == true) FakeDistinguishmentThingy(badStanding: true),
|
||||
rigthCard(snapshot, sprintAchievements, blitzAchievements, width),
|
||||
rigthCard(snapshot, sprintAchievements, blitzAchievements, tlAchievements, qpAchievements, qpExAchievements, width),
|
||||
if (rightCard == Cards.overview) Card(
|
||||
child: Column(
|
||||
children: [
|
||||
|
|
|
@ -32,8 +32,8 @@ class SingleplayerRecordView extends StatelessWidget {
|
|||
maxWidth: 768
|
||||
),
|
||||
child: switch (record.gamemode){
|
||||
"zenith" => ZenithCard(record, false, width: MediaQuery.of(context).size.width),
|
||||
"zenithex" => ZenithCard(record, false, width: MediaQuery.of(context).size.width),
|
||||
"zenith" => ZenithCard(record, false, [], width: MediaQuery.of(context).size.width),
|
||||
"zenithex" => ZenithCard(record, false, [], width: MediaQuery.of(context).size.width),
|
||||
_ => SingleplayerRecord(record: record, hideTitle: true)
|
||||
},
|
||||
),
|
||||
|
|
|
@ -55,19 +55,19 @@ class TetraLeagueThingy extends StatelessWidget{
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
print(ranks2.indexOf(league.rank != "z" ? league.rank : league.percentileRank)-1);
|
||||
return Card(
|
||||
//surfaceTintColor: rankColors[league.rank],
|
||||
child: Column(
|
||||
children: [
|
||||
TLRatingThingy(userID: league.id, tlData: league, oldTl: toCompare, showPositions: true),
|
||||
if (league.gamesPlayed > 9) TLProgress(
|
||||
tlData: league,
|
||||
previousRankTRcutoff: cutoffs != null ? cutoffs!.tr[league.rank != "z" ? league.rank : league.percentileRank] : null,
|
||||
nextRankTRcutoff: cutoffs != null ? (league.rank != "z" ? league.rank == "x+" : league.percentileRank == "x+") ? 25000 : cutoffs!.tr[ranks.elementAtOrNull(ranks.indexOf(league.rank != "z" ? league.rank : league.percentileRank)+1)] : null,
|
||||
nextRankTRcutoff: cutoffs != null ? cutoffs!.tr[ranks2[ranks2.indexOf(league.rank != "z" ? league.rank : league.percentileRank)-1]] : null,
|
||||
previousRankTRcutoffTarget: league.rank != "z" ? rankTargets[league.rank] : null,
|
||||
nextRankTRcutoffTarget: (league.rank != "z" && league.rank != "x+") ? rankTargets[ranks.elementAtOrNull(ranks.indexOf(league.rank)+1)] : null,
|
||||
nextRankTRcutoffTarget: (league.rank != "z" && league.rank != "x+") ? rankTargets[ranks2[ranks2.indexOf(league.rank != "z" ? league.rank : league.percentileRank)-1]] : null,
|
||||
previousGlickoCutoff: cutoffs != null ? cutoffs!.glicko[league.rank != "z" ? league.rank : league.percentileRank] : null,
|
||||
nextRankGlickoCutoff: cutoffs != null ? (league.rank != "z" ? league.rank == "x+" : league.percentileRank == "x+") ? 25000 : cutoffs!.glicko[ranks.elementAtOrNull(ranks.indexOf(league.rank != "z" ? league.rank : league.percentileRank)+1)] : null,
|
||||
nextRankGlickoCutoff: cutoffs != null ? cutoffs!.glicko[ranks2[ranks2.indexOf(league.rank != "z" ? league.rank : league.percentileRank)-1]] : null,
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
import 'dart:math';
|
||||
import 'dart:ui' as ui;
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/widgets.dart' show Size;
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
||||
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||
|
@ -16,6 +18,45 @@ import 'package:tetra_stats/views/compare_view_tiles.dart';
|
|||
import 'package:tetra_stats/widgets/text_timestamp.dart';
|
||||
import 'package:transparent_image/transparent_image.dart';
|
||||
|
||||
Future<ui.Image> osksFuture = loadImage(Uri.https("tetr.io", "/user-content/banners/5e32fc85ab319c2ab1beb07c.jpg", {"rv": "1628366386763"}));
|
||||
|
||||
Future<ui.Image> loadImage(Uri url) async {
|
||||
final response = await teto.client.get(url);
|
||||
return await decodeImageFromList(response.bodyBytes);
|
||||
}
|
||||
|
||||
Widget createCustomImage(ui.Image image) {
|
||||
return SizedBox(
|
||||
width: image.width.toDouble(),
|
||||
height: image.height.toDouble()/64,
|
||||
child: CustomPaint(
|
||||
size: Size(128.0, 128.0),
|
||||
painter: ImagePainter(image),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
class ImagePainter extends CustomPainter {
|
||||
ImagePainter(ui.Image this.image);
|
||||
final ui.Image image;
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
final paint = Paint()
|
||||
..color = Colors.red
|
||||
..strokeWidth = 5
|
||||
..style = PaintingStyle.stroke;
|
||||
|
||||
canvas.translate(-240, 0);
|
||||
canvas.scale(0.5);
|
||||
canvas.drawImage(image, Offset.zero, paint);
|
||||
}
|
||||
|
||||
@override
|
||||
bool shouldRepaint(ImagePainter oldDelegate) =>
|
||||
image != oldDelegate.image;
|
||||
}
|
||||
|
||||
class UserThingy extends StatefulWidget {
|
||||
final TetrioPlayer player;
|
||||
final bool showStateTimestamp;
|
||||
|
@ -103,14 +144,30 @@ class _UserThingyState extends State<UserThingy> with SingleTickerProviderStateM
|
|||
constraints: const BoxConstraints(maxWidth: 960),
|
||||
height: widget.player.bannerRevision != null ? 218.0 : 138.0,
|
||||
child: Stack(
|
||||
//clipBehavior: Clip.none,
|
||||
children: [
|
||||
// TODO: osk banner can cause memory leak
|
||||
if (widget.player.bannerRevision != null) FadeInImage.memoryNetwork(image: kIsWeb ? "https://ts.dan63.by/oskware_bridge.php?endpoint=TetrioBanner&user=${widget.player.userId}&rv=${widget.player.bannerRevision}" : "https://tetr.io/user-content/banners/${widget.player.userId}.jpg?rv=${widget.player.bannerRevision}",
|
||||
// Very weird solution to draw only the first frame of the gif
|
||||
if (widget.player.userId == "5e32fc85ab319c2ab1beb07c") FutureBuilder<ui.Image>(
|
||||
future: osksFuture,
|
||||
builder: (context, snapshot) {
|
||||
switch (snapshot.connectionState){
|
||||
case ConnectionState.none:
|
||||
case ConnectionState.waiting:
|
||||
case ConnectionState.active:
|
||||
return SizedBox(width: 960);
|
||||
case ConnectionState.done:
|
||||
return createCustomImage(snapshot.data!);
|
||||
}
|
||||
},
|
||||
) // If not osk, using a normal widget like a normal human being
|
||||
else if (widget.player.bannerRevision != null) FadeInImage.memoryNetwork(
|
||||
image: kIsWeb ? "https://ts.dan63.by/oskware_bridge.php?endpoint=TetrioBanner&user=${widget.player.userId}&rv=${widget.player.bannerRevision}" : "https://tetr.io/user-content/banners/${widget.player.userId}.jpg?rv=${widget.player.bannerRevision}",
|
||||
placeholder: kTransparentImage,
|
||||
fit: BoxFit.cover,
|
||||
height: 120,
|
||||
fadeInCurve: Easing.standard, fadeInDuration: Durations.long4
|
||||
fadeInCurve: Easing.standard, fadeInDuration: Durations.long4,
|
||||
imageErrorBuilder: (context, object, trace){
|
||||
return SizedBox(width: 960);
|
||||
}
|
||||
),
|
||||
Positioned(
|
||||
top: widget.player.bannerRevision != null ? 90.0 : 10.0,
|
||||
|
|
|
@ -2,7 +2,7 @@ name: tetra_stats
|
|||
description: Track your and other player stats in TETR.IO
|
||||
publish_to: 'none'
|
||||
|
||||
version: 2.0.0-beta+339
|
||||
version: 2.0.0-beta2+40
|
||||
|
||||
environment:
|
||||
sdk: '>=3.0.0'
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
"nerdStats": "Nerd Stats",
|
||||
"playstyles": "Playstyles",
|
||||
"horoscopes": "Horoscopes",
|
||||
"relatedAchievements": "Related Achievements",
|
||||
"season": "Season",
|
||||
"smooth": "Smooth",
|
||||
"dateAndTime": "Date & Time",
|
||||
|
@ -286,7 +287,7 @@
|
|||
"settingsDestination": {
|
||||
"title": "Settings",
|
||||
"general": "General",
|
||||
"customization": "Custonization",
|
||||
"customization": "Customization",
|
||||
"database": "Local database",
|
||||
"checking": "Checking...",
|
||||
"enterToSubmit": "Press Enter to submit",
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
"nerdStats": "Для Задротов",
|
||||
"playstyles": "Стили игры",
|
||||
"horoscopes": "Гороскопы",
|
||||
"relatedAchievements": "Достижения режима",
|
||||
"season": "Сезон",
|
||||
"smooth": "Сглаживание",
|
||||
"dateAndTime": "Дата и время",
|
||||
|
|
Loading…
Reference in New Issue