Compare commits

...

2 Commits

Author SHA1 Message Date
dan63047 8f5b7c018d Localization update 2024-07-20 16:27:22 +03:00
dan63047 86ac390e05 It's the final countdown 2024-07-20 16:21:14 +03:00
11 changed files with 83 additions and 29 deletions

View File

@ -123,6 +123,7 @@
// }
// bool wasATSpin(Tetromino type, Coords coords, int rot){
// if (type != Tetromino.T) return false;
// if (!(positionIsValid(type, Coords(coords.x+1, coords.y), rot) ||
// positionIsValid(type, Coords(coords.x-1, coords.y), rot) ||
// positionIsValid(type, Coords(coords.x, coords.y+1), rot) ||
@ -200,10 +201,6 @@
// int attackTanked = 0;
// LineClearResult processLineClear(List<int> clearFullLinesResult, Tetromino current, Coords pos, bool spinWasLastMove, bool tspin){
// if (clearFullLinesResult[0] > 0) combo++;
// else combo = -1;
// if (clearFullLinesResult[2] > 0) btb++;
// else btb = -1;
// int attack = 0;
// switch (clearFullLinesResult[0]){
// case 0:
@ -215,7 +212,8 @@
// if (spinWasLastMove && tspin) {
// attack = garbage['t-spin single']!;
// }else{
// attack = garbage['single']!;
// if (combo == -1) attack = garbage['single']!;
// else attack = comboTable[combo];
// }
// break;
// case 2:
@ -250,6 +248,10 @@
// developer.log("${clearFullLinesResult[0]} lines cleared");
// break;
// }
// if (clearFullLinesResult[0] > 0) combo++;
// else combo = -1;
// if (clearFullLinesResult[2] > 0) btb++;
// else btb = -1;
// return LineClearResult(clearFullLinesResult[0], Tetromino.empty, false, clearFullLinesResult[1], 0, attack);
// }
// }
@ -269,7 +271,7 @@
// List<Event> events = readEventList(replay.rawJson);
// DataFullOptions? settings;
// HandlingHandler? handling;
// Map<KeyType, EventKeyPress> activeKeypresses = {};
// //Map<KeyType, EventKeyPress> activeKeypresses = {};
// int currentFrame = 0;
// double subframesWent = 0;
// events.removeAt(0); // get rig of Event.start
@ -278,6 +280,7 @@
// Board board = Board(10, 20, 20);
// KicksetBase kickset = SRSPlus();
// List<IncomingGarbage> garbageQueue = [];
// List<GarbageData> outcomingGarbage = [];
// Tetromino? hold;
// int rot = 0;
// bool spinWasLastMove = false;
@ -287,9 +290,9 @@
// bool floored = false;
// double gravityBucket = 1.0;
// developer.log("Seed is ${replay.stats[0][0].seed}, first bag is $queue");
// //developer.log("Seed is ${replay.stats[0][0].seed}, first bag is $queue");
// Tetromino current = queue.removeAt(0);
// //developer.log("Second bag is ${rng.shuffleList(tetrominoes)}");
// //developer.log("Handling is ");
// int sonicDrop(){
// int height = coords.y;
@ -333,12 +336,13 @@
// board.writeToBoard(current, coords, rot);
// bool tspin = board.wasATSpin(current, coords, rot);
// LineClearResult lineClear = stats.processLineClear(board.clearFullLines(), current, coords, spinWasLastMove, tspin);
// print("${lineClear.linesCleared} lines, ${lineClear.garbageCleared} garbage");
// //if (lineClear.attackProduced > 0) outcomingGarbage.add(GarbageData());
// //print("${lineClear.linesCleared} lines, ${lineClear.garbageCleared} garbage");
// if (garbageQueue.isNotEmpty) {
// if (lineClear.linesCleared > 0){
// int garbageToDelete = lineClear.attackProduced;
// for (IncomingGarbage garbage in garbageQueue){
// if (garbage.data.amt! >= garbageToDelete) {
// if (garbage.data.amt! < garbageToDelete) {
// garbageToDelete -= garbage.data.amt!;
// lineClear.attackProduced = garbageToDelete;
// garbage.data.amt = 0;
@ -367,11 +371,17 @@
// }
// current = getNewOne();
// coords = Coords(3, 21) + spawnPositionFixes[current.index];
// print("${lineClear.linesCleared} lines, ${lineClear.attackProduced} atk, ${lineClear.spin}, combo ${stats.combo}, btb ${stats.btb}");
// }
// void handleGravity(double frames){
// if (frames == 0) return;
// gravityBucket += settings != null ? (handling!.sdfActive ? max(settings.g! * settings.handling!.sdf, 0.05 * settings.handling!.sdf) : settings.g!) * frames : 0;
// gravityBucket += settings != null ?
// (handling!.sdfActive ?
// max(settings.g! * settings.handling!.sdf, 0.05 * settings.handling!.sdf) :
// settings.g!
// ) * frames
// : 0;
// int gravityImpact = 0;
// if (gravityBucket >= 1.0){
// gravityImpact = gravityBucket.truncate();
@ -404,17 +414,17 @@
// subframesWent = 0;
// if (settings?.handling?.sdf == 41) coords.y = sonicDrop();
// print("$currentFrame: $current at $coords\n$board");
// //print(stats.combo);
// if (currentFrame == nextEvent.frame){
// while (currentFrame == nextEvent.frame){
// print("Processing $nextEvent");
// //print("Processing $nextEvent");
// switch (nextEvent.type){
// case EventType.start:
// developer.log("go");
// break;
// case EventType.full:
// settings = (nextEvent as EventFull).data.options;
// developer.log("SDF is ${settings?.handling?.sdf}, replay version is ${settings?.version}");
// handling = HandlingHandler(settings!.handling!.das.toDouble(), settings.handling!.arr.toDouble());
// lockDelay = settings.locktime!.toDouble();
// lockResets = settings.lockresets!;
@ -446,6 +456,7 @@
// break;
// case KeyType.hardDrop:
// coords.y = sonicDrop();
// print("$currentFrame: $current at $coords, garbage queue $garbageQueue\n$board");
// handleHardDrop();
// case KeyType.hold:
// switch (hold){
@ -513,7 +524,7 @@
// case KeyType.retry:
// // TODO: Handle this case.
// }
// activeKeypresses.remove(nextEvent.data.key);
// //activeKeypresses.remove(nextEvent.data.key);
// break;
// case EventType.end:
// currentFrame = replay.roundLengths[0]+1;

View File

@ -60,6 +60,7 @@ const Map<String, double> rankTargets = {
"d+": 606,
"d": 0,
};
DateTime seasonEnd = DateTime.utc(2024, 07, 26, 15);
enum Stats {
tr,
glicko,

View File

@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang`
///
/// Locales: 2
/// Strings: 1182 (591 per locale)
/// Strings: 1186 (593 per locale)
///
/// Built on 2024-07-10 at 15:23 UTC
/// Built on 2024-07-20 at 13:24 UTC
// coverage:ignore-file
// ignore_for_file: type=lint
@ -222,6 +222,8 @@ class Translations implements BaseTranslations<AppLocale, Translations> {
String get verdictBetter => 'better';
String get verdictWorse => 'worse';
String get smooth => 'Smooth';
String seasonEnds({required Object countdown}) => 'Season ends in ${countdown}';
String get seasonEnded => 'Season has ended';
String gamesUntilRanked({required Object left}) => '${left} games until being ranked';
String numOfVictories({required Object wins}) => '~${wins} victories';
String get promotionOnNextWin => 'Promotion on next win';
@ -917,6 +919,8 @@ class _StringsRu implements Translations {
@override String get verdictBetter => 'Лучше';
@override String get verdictWorse => 'Хуже';
@override String get smooth => 'Гладкий';
@override String seasonEnds({required Object countdown}) => 'Сезон закончится через ${countdown}';
@override String get seasonEnded => 'Сезон закончился';
@override String gamesUntilRanked({required Object left}) => '${left} матчей до получения рейтинга';
@override String numOfVictories({required Object wins}) => '~${wins} побед';
@override String get promotionOnNextWin => 'Повышение после следующей победы';
@ -1604,6 +1608,8 @@ extension on Translations {
case 'verdictBetter': return 'better';
case 'verdictWorse': return 'worse';
case 'smooth': return 'Smooth';
case 'seasonEnds': return ({required Object countdown}) => 'Season ends in ${countdown}';
case 'seasonEnded': return 'Season has ended';
case 'gamesUntilRanked': return ({required Object left}) => '${left} games until being ranked';
case 'numOfVictories': return ({required Object wins}) => '~${wins} victories';
case 'promotionOnNextWin': return 'Promotion on next win';
@ -2215,6 +2221,8 @@ extension on _StringsRu {
case 'verdictBetter': return 'Лучше';
case 'verdictWorse': return 'Хуже';
case 'smooth': return 'Гладкий';
case 'seasonEnds': return ({required Object countdown}) => 'Сезон закончится через ${countdown}';
case 'seasonEnded': return 'Сезон закончился';
case 'gamesUntilRanked': return ({required Object left}) => '${left} матчей до получения рейтинга';
case 'numOfVictories': return ({required Object wins}) => '~${wins} побед';
case 'promotionOnNextWin': return 'Повышение после следующей победы';

View File

@ -3,6 +3,7 @@ import 'package:tetra_stats/gen/strings.g.dart';
import 'package:tetra_stats/utils/numers_formats.dart';
final NumberFormat secs = NumberFormat("00.###", LocaleSettings.currentLocale.languageCode);
final NumberFormat nonsecs = NumberFormat("00.###", LocaleSettings.currentLocale.languageCode);
final NumberFormat _timeInSec = NumberFormat("#,###.###s.", LocaleSettings.currentLocale.languageCode);
/// Returns string, that represents time difference between [dateTime] and now
@ -73,4 +74,8 @@ String readableTimeDifference(Duration a, Duration b){
Duration result = a - b;
return NumberFormat("0.000s;0.000s", LocaleSettings.currentLocale.languageCode).format(result.inMilliseconds/1000);
}
String countdown(Duration difference){
return "${difference.inDays}:${nonsecs.format(difference.inHours%24)}:${nonsecs.format(difference.inMinutes%60)}:${secs.format(difference.inSeconds%60)}";
}

View File

@ -1013,7 +1013,6 @@ class _TwoRecordsThingy extends StatelessWidget {
@override
Widget build(BuildContext context) {
//if (record == null) return Center(child: Text(t.noRecord, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28)));
late MapEntry closestAverageBlitz;
late bool blitzBetterThanClosestAverage;
bool? blitzBetterThanRankAverage = (rank != null && rank != "z" && blitz != null) ? blitz!.endContext.score > blitzAverages[rank]! : null;
@ -1186,13 +1185,13 @@ class _TwoRecordsThingy extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
children: [
for (int i = 1; i < blitzStream.records.length; i++) ListTile(
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => SingleplayerRecordView(record: blitzStream.records[i]))),
leading: Text("#${i+1}", style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28, shadows: textShadow, height: 0.9) ),
title: Text("${NumberFormat.decimalPattern().format(blitzStream.records[i].endContext.score)} points",
style: const TextStyle(fontSize: 18)),
subtitle: Text(timestamp(blitzStream.records[i].timestamp), style: const TextStyle(color: Colors.grey, height: 0.85)),
trailing: SpTrailingStats(blitzStream.records[i].endContext)
)
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => SingleplayerRecordView(record: blitzStream.records[i]))),
leading: Text("#${i+1}", style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28, shadows: textShadow, height: 0.9) ),
title: Text("${NumberFormat.decimalPattern().format(blitzStream.records[i].endContext.score)} points",
style: const TextStyle(fontSize: 18)),
subtitle: Text(timestamp(blitzStream.records[i].timestamp), style: const TextStyle(color: Colors.grey, height: 0.85)),
trailing: SpTrailingStats(blitzStream.records[i].endContext)
)
],
),
)

View File

@ -8,7 +8,6 @@ import 'package:tetra_stats/main.dart' show prefs;
import 'package:tetra_stats/utils/numers_formats.dart';
var fDiff = NumberFormat("+#,###.####;-#,###.####");
DateTime seasonEnd = DateTime.utc(2024, 07, 26);
class TLRatingThingy extends StatelessWidget{
final String userID;
@ -30,7 +29,6 @@ class TLRatingThingy extends StatelessWidget{
DateTime now = DateTime.now();
bool beforeS1end = now.isBefore(seasonEnd);
int daysLeft = seasonEnd.difference(now).inDays;
print(max(0, 7 - (lastMatchPlayed != null ? now.difference(lastMatchPlayed!).inDays : 7)));
int safeRD = min(100, (100 + ((tlData.rd! >= 100 && tlData.decaying) ? 7 : max(0, 7 - (lastMatchPlayed != null ? now.difference(lastMatchPlayed!).inDays : 7))) - daysLeft).toInt());
return Wrap(
direction: Axis.horizontal,

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:tetra_stats/data_objects/tetrio.dart';
@ -5,6 +7,7 @@ import 'package:syncfusion_flutter_gauges/gauges.dart';
import 'package:tetra_stats/gen/strings.g.dart';
import 'package:tetra_stats/utils/colors_functions.dart';
import 'package:tetra_stats/utils/numers_formats.dart';
import 'package:tetra_stats/utils/relative_timestamps.dart';
import 'package:tetra_stats/widgets/gauget_num.dart';
import 'package:tetra_stats/widgets/graphs.dart';
import 'package:tetra_stats/widgets/stat_sell_num.dart';
@ -38,12 +41,14 @@ class TLThingy extends StatefulWidget {
State<TLThingy> createState() => _TLThingyState();
}
class _TLThingyState extends State<TLThingy> {
class _TLThingyState extends State<TLThingy> with TickerProviderStateMixin {
late bool oskKagariGimmick;
late TetraLeagueAlpha? oldTl;
late TetraLeagueAlpha currentTl;
late RangeValues _currentRangeValues;
late List<TetrioPlayer> sortedStates;
late Timer _countdownTimer;
Duration seasonLeft = seasonEnd.difference(DateTime.now());
@override
void initState() {
@ -52,8 +57,23 @@ class _TLThingyState extends State<TLThingy> {
oldTl = sortedStates.elementAtOrNull(1)?.tlSeason1;
currentTl = widget.tl;
super.initState();
_countdownTimer = Timer.periodic(
Durations.extralong4,
(Timer timer) {
setState(() {
seasonLeft = seasonEnd.difference(DateTime.now());
});
},
);
}
@override
void dispose() {
_countdownTimer.cancel();
super.dispose();
}
@override
Widget build(BuildContext context) {
final t = Translations.of(context);
@ -70,6 +90,8 @@ class _TLThingyState extends State<TLThingy> {
return Column(
children: [
if (widget.showTitle) Text(t.tetraLeague, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)),
if (DateTime.now().isBefore(seasonEnd)) Text(t.seasonEnds(countdown: countdown(seasonLeft)))
else Text(t.seasonEnded),
if (oldTl != null) Text(t.comparingWith(newDate: timestamp(currentTl.timestamp), oldDate: timestamp(oldTl!.timestamp)),
textAlign: TextAlign.center,),
if (oldTl != null) RangeSlider(values: _currentRangeValues, max: widget.states.length.toDouble(),

View File

@ -2,7 +2,7 @@ name: tetra_stats
description: Track your and other player stats in TETR.IO
publish_to: 'none'
version: 1.6.1+21
version: 1.6.2+22
environment:
sdk: '>=3.0.0'

View File

@ -87,6 +87,8 @@
"verdictBetter": "better",
"verdictWorse": "worse",
"smooth": "Smooth",
"seasonEnds": "Season ends in ${countdown}",
"seasonEnded": "Season has ended",
"gamesUntilRanked": "${left} games until being ranked",
"numOfVictories": "~${wins} victories",
"promotionOnNextWin": "Promotion on next win",

View File

@ -87,6 +87,8 @@
"verdictBetter": "Лучше",
"verdictWorse": "Хуже",
"smooth": "Гладкий",
"seasonEnds": "Сезон закончится через ${countdown}",
"seasonEnded": "Сезон закончился",
"gamesUntilRanked": "${left} матчей до получения рейтинга",
"numOfVictories": "~${wins} побед",
"promotionOnNextWin": "Повышение после следующей победы",

View File

@ -152,12 +152,18 @@
// Promoting Tetra Stats "native"
"Want a better perfomance?<br><a href=\"https://github.com/dan63047/TetraStats/releases\">Try out Tetra Stats \"Native\"</a>",
"Imagine a world, where Tetra Stats was written in JS",
"Did you know, that Flutter for web sucks?",
"Welcome to fullscreen canvas",
// An actual tips
"You can interact with most objects that have an accent color",
"Like Sheetbot graphs? Go to three dots menu → Settings → Customization",
"Click and hold on line chart graph, then start dragging to zoom in"
"Click and hold on line chart graph, then start dragging to zoom in",
"Discord userID ≠ Discord username. It should look like a bunch of digits",
// :droidsmile:
"Is she real?",
"Check out <a href=\"https://github.com/dan63047/TetraStats/wiki\">wiki</a> for more information"
];
tip.innerHTML = tips[Math.floor(Math.random() * tips.length)];
try{