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

View File

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

View File

@ -4,9 +4,9 @@
/// To regenerate, run: `dart run slang` /// To regenerate, run: `dart run slang`
/// ///
/// Locales: 2 /// 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 // coverage:ignore-file
// ignore_for_file: type=lint // ignore_for_file: type=lint
@ -222,6 +222,8 @@ class Translations implements BaseTranslations<AppLocale, Translations> {
String get verdictBetter => 'better'; String get verdictBetter => 'better';
String get verdictWorse => 'worse'; String get verdictWorse => 'worse';
String get smooth => 'Smooth'; 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 gamesUntilRanked({required Object left}) => '${left} games until being ranked';
String numOfVictories({required Object wins}) => '~${wins} victories'; String numOfVictories({required Object wins}) => '~${wins} victories';
String get promotionOnNextWin => 'Promotion on next win'; String get promotionOnNextWin => 'Promotion on next win';
@ -917,6 +919,8 @@ class _StringsRu implements Translations {
@override String get verdictBetter => 'Лучше'; @override String get verdictBetter => 'Лучше';
@override String get verdictWorse => 'Хуже'; @override String get verdictWorse => 'Хуже';
@override String get smooth => 'Гладкий'; @override String get smooth => 'Гладкий';
@override String seasonEnds({required Object countdown}) => 'Сезон закончится через ${countdown}';
@override String get seasonEnded => 'Сезон закончился';
@override String gamesUntilRanked({required Object left}) => '${left} матчей до получения рейтинга'; @override String gamesUntilRanked({required Object left}) => '${left} матчей до получения рейтинга';
@override String numOfVictories({required Object wins}) => '~${wins} побед'; @override String numOfVictories({required Object wins}) => '~${wins} побед';
@override String get promotionOnNextWin => 'Повышение после следующей победы'; @override String get promotionOnNextWin => 'Повышение после следующей победы';
@ -1604,6 +1608,8 @@ extension on Translations {
case 'verdictBetter': return 'better'; case 'verdictBetter': return 'better';
case 'verdictWorse': return 'worse'; case 'verdictWorse': return 'worse';
case 'smooth': return 'Smooth'; 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 'gamesUntilRanked': return ({required Object left}) => '${left} games until being ranked';
case 'numOfVictories': return ({required Object wins}) => '~${wins} victories'; case 'numOfVictories': return ({required Object wins}) => '~${wins} victories';
case 'promotionOnNextWin': return 'Promotion on next win'; case 'promotionOnNextWin': return 'Promotion on next win';
@ -2215,6 +2221,8 @@ extension on _StringsRu {
case 'verdictBetter': return 'Лучше'; case 'verdictBetter': return 'Лучше';
case 'verdictWorse': return 'Хуже'; case 'verdictWorse': return 'Хуже';
case 'smooth': return 'Гладкий'; case 'smooth': return 'Гладкий';
case 'seasonEnds': return ({required Object countdown}) => 'Сезон закончится через ${countdown}';
case 'seasonEnded': return 'Сезон закончился';
case 'gamesUntilRanked': return ({required Object left}) => '${left} матчей до получения рейтинга'; case 'gamesUntilRanked': return ({required Object left}) => '${left} матчей до получения рейтинга';
case 'numOfVictories': return ({required Object wins}) => '~${wins} побед'; case 'numOfVictories': return ({required Object wins}) => '~${wins} побед';
case 'promotionOnNextWin': return 'Повышение после следующей победы'; 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'; import 'package:tetra_stats/utils/numers_formats.dart';
final NumberFormat secs = NumberFormat("00.###", LocaleSettings.currentLocale.languageCode); final NumberFormat secs = NumberFormat("00.###", LocaleSettings.currentLocale.languageCode);
final NumberFormat nonsecs = NumberFormat("00.###", LocaleSettings.currentLocale.languageCode);
final NumberFormat _timeInSec = NumberFormat("#,###.###s.", LocaleSettings.currentLocale.languageCode); final NumberFormat _timeInSec = NumberFormat("#,###.###s.", LocaleSettings.currentLocale.languageCode);
/// Returns string, that represents time difference between [dateTime] and now /// Returns string, that represents time difference between [dateTime] and now
@ -73,4 +74,8 @@ String readableTimeDifference(Duration a, Duration b){
Duration result = a - b; Duration result = a - b;
return NumberFormat("0.000s;0.000s", LocaleSettings.currentLocale.languageCode).format(result.inMilliseconds/1000); 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 @override
Widget build(BuildContext context) { 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 MapEntry closestAverageBlitz;
late bool blitzBetterThanClosestAverage; late bool blitzBetterThanClosestAverage;
bool? blitzBetterThanRankAverage = (rank != null && rank != "z" && blitz != null) ? blitz!.endContext.score > blitzAverages[rank]! : null; 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, mainAxisSize: MainAxisSize.min,
children: [ children: [
for (int i = 1; i < blitzStream.records.length; i++) ListTile( for (int i = 1; i < blitzStream.records.length; i++) ListTile(
onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => SingleplayerRecordView(record: blitzStream.records[i]))), 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) ), 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", title: Text("${NumberFormat.decimalPattern().format(blitzStream.records[i].endContext.score)} points",
style: const TextStyle(fontSize: 18)), style: const TextStyle(fontSize: 18)),
subtitle: Text(timestamp(blitzStream.records[i].timestamp), style: const TextStyle(color: Colors.grey, height: 0.85)), subtitle: Text(timestamp(blitzStream.records[i].timestamp), style: const TextStyle(color: Colors.grey, height: 0.85)),
trailing: SpTrailingStats(blitzStream.records[i].endContext) 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'; import 'package:tetra_stats/utils/numers_formats.dart';
var fDiff = NumberFormat("+#,###.####;-#,###.####"); var fDiff = NumberFormat("+#,###.####;-#,###.####");
DateTime seasonEnd = DateTime.utc(2024, 07, 26);
class TLRatingThingy extends StatelessWidget{ class TLRatingThingy extends StatelessWidget{
final String userID; final String userID;
@ -30,7 +29,6 @@ class TLRatingThingy extends StatelessWidget{
DateTime now = DateTime.now(); DateTime now = DateTime.now();
bool beforeS1end = now.isBefore(seasonEnd); bool beforeS1end = now.isBefore(seasonEnd);
int daysLeft = seasonEnd.difference(now).inDays; 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()); 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( return Wrap(
direction: Axis.horizontal, direction: Axis.horizontal,

View File

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

View File

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

View File

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

View File

@ -152,12 +152,18 @@
// Promoting Tetra Stats "native" // Promoting Tetra Stats "native"
"Want a better perfomance?<br><a href=\"https://github.com/dan63047/TetraStats/releases\">Try out Tetra Stats \"Native\"</a>", "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", "Imagine a world, where Tetra Stats was written in JS",
"Did you know, that Flutter for web sucks?",
"Welcome to fullscreen canvas", "Welcome to fullscreen canvas",
// An actual tips // An actual tips
"You can interact with most objects that have an accent color", "You can interact with most objects that have an accent color",
"Like Sheetbot graphs? Go to three dots menu → Settings → Customization", "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)]; tip.innerHTML = tips[Math.floor(Math.random() * tips.length)];
try{ try{