Continuing to implement i18n

This commit is contained in:
dan63047 2023-07-12 18:14:25 +03:00
parent 079c922b29
commit 1db203b3a5
11 changed files with 440 additions and 108 deletions

View File

@ -59,7 +59,7 @@ jobs:
prerelease: true
allowUpdates: true
discussionCategory: autobuilded-releases
artifacts: "build/app/outputs/apk/debug/*"
artifacts: "build/app/outputs/apk/flutter-apk/*"
tag: Auto-${{ github.run_number }}
body: This build was builded with GitHub Action workflow
token: ${{ secrets.TOKEN }}

View File

@ -1,9 +1,9 @@
/// Generated file. Do not edit.
///
/// Locales: 2
/// Strings: 680 (340 per locale)
/// Strings: 788 (394 per locale)
///
/// Built on 2023-07-11 at 16:43 UTC
/// Built on 2023-07-12 at 15:02 UTC
// coverage:ignore-file
// ignore_for_file: type=lint
@ -193,6 +193,37 @@ class _StringsEn implements BaseTranslations<AppLocale, _StringsEn> {
String gamesUntilRanked({required Object left}) => '${left} games until being ranked';
String get nerdStats => 'Nerd Stats';
String get playersYouTrack => 'Players you track';
String get formula => 'Formula';
String get exactValue => 'Exact value';
String get neverPlayedTL => 'That user never played Tetra League';
String get exportDB => 'Export local database';
String get exportDBDescription => 'It contains states and Tetra League records of the tracked players and list of tracked players.';
String get desktopExportAlertTitle => 'Desktop export';
String get desktopExportText => 'It seems like you using this app on desktop. Check your documents folder, you should find "TetraStats.db". Copy it somewhere';
String get androidExportAlertTitle => 'Android export';
String androidExportText({required Object exportedDB}) => 'Exported.\n${exportedDB}';
String get importDB => 'Import local database';
String get importDBDescription => 'Restore your backup. Notice that already stored database will be overwritten.';
String get importWrongFileType => 'Wrong file type';
String get importCancelled => 'Operation was cancelled';
String get importSuccess => 'Import successful';
String get yourID => 'Your TETR.IO account';
String get yourIDAlertTitle => 'Your TETR.IO account nickname or ID';
String get yourIDText => 'Every time when app loads, stats of that player will be fetched. Please prefer ID over nickname because nickname can be changed.';
String get language => 'Language';
String get aboutApp => 'About app';
String aboutAppText({required Object appName, required Object packageName, required Object version, required Object buildNumber}) => '${appName} (${packageName}) Version ${version} Build ${buildNumber}\n\nDeveloped by dan63047\nFormulas provided by kerrmunism';
String stateViewTitle({required Object nickname, required Object date}) => '${nickname} account on ${date}';
String statesViewTitle({required Object number, required Object nickname}) => '${number} states of ${nickname} account';
String statesViewEntry({required Object level, required Object gameTime, required Object friends, required Object rd}) => 'Level ${level}, ${gameTime} of gametime, ${friends} friends, ${rd} RD';
String stateRemoved({required Object date}) => '${date} state was removed from database!';
String get trackedPlayersViewTitle => 'Stored data';
String get trackedPlayersZeroEntrys => 'Empty list. Press "Track" button in previous view to add current player here';
String get trackedPlayersOneEntry => 'There is only one player';
String trackedPlayersManyEntrys({required Object numberOfPlayers}) => 'There are ${numberOfPlayers} players';
String trackedPlayersEntry({required Object nickname, required Object numberOfStates}) => '${nickname}: ${numberOfStates} states';
String trackedPlayersDescription({required Object firstStateDate, required Object lastStateDate}) => 'From ${firstStateDate} until ${lastStateDate}';
String trackedPlayersStatesDeleted({required Object nickname}) => '${nickname} states was removed from database!';
late final _StringsStatCellNumEn statCellNum = _StringsStatCellNumEn._(_root);
Map<String, String> get playerRole => {
'user': 'User',
@ -477,6 +508,8 @@ class _StringsStatCellNumEn {
// Translations
String get xpLevel => 'XP Level';
String get xpProgress => 'Progress to next level';
String get xpFrom0To5000 => 'Progress from 0 XP to level 5000';
String get hoursPlayed => 'Hours\nPlayed';
String get onlineGames => 'Online\nGames';
String get gamesWon => 'Games\nWon';
@ -498,6 +531,25 @@ class _StringsStatCellNumEn {
String get keys => 'Key\nPresses';
String get kpp => 'KP Per\nPiece';
String get kps => 'KP Per\nSecond';
String get app => 'Attack Per Piece';
String get appDescription => '(Abbreviated as APP) Main efficiency metric. Tells how many attack you producing per piece';
String get vsapmDescription => 'Basically, tells how much and how efficient you using garbage in your attacks';
String get dss => 'Downstack\nPer Second';
String get dssDescription => 'Downstack per Second measures how many garbage lines you clear in a second.';
String get dsp => 'Downstack\nPer Piece';
String get dspDescription => 'Downstack per Piece measures how many garbage lines you clear per piece.';
String get appdsp => 'APP + DS/P';
String get appdspDescription => 'Just a sum of Attack per Piece and Downstack per Piece.';
String get cheese => 'Cheese\nIndex';
String get cheeseDescription => 'Cheese Index is an approximation how much clean / cheese garbage player sends. Lower = more clean. Higher = more cheese.\nInvented by kerrmunism';
String get gbe => 'Garbage\nEfficiency';
String get gbeDescription => 'Garbage Efficiency measures how well player uses their garbage. Higher = better or they use their garbage more. Lower = they mostly send their garbage back at cheese or rarely clear garbage.\nInvented by Zepheniah and Dragonboy.';
String get nyaapp => 'Weighted\nAPP';
String get nyaappDescription => 'Essentially, a measure of your ability to send cheese while still maintaining a high APP.\nInvented by Wertj.';
String get area => 'Area';
String get areaDescription => 'How much space your shape takes up on the graph, if you exclude the cheese and vs/apm sections';
String get estOfTR => 'Est. of TR';
String get accOfEst => 'Accuracy';
}
// Path: numOfGameActions
@ -520,6 +572,8 @@ class _StringsPopupActionsEn {
final _StringsEn _root; // ignore: unused_field
// Translations
String get cancel => 'Cancel';
String get submit => 'Submit';
String get ok => 'OK';
}
@ -606,6 +660,37 @@ class _StringsRu implements _StringsEn {
@override String gamesUntilRanked({required Object left}) => '${left} матчей до получения рейтинга';
@override String get nerdStats => 'Для задротов';
@override String get playersYouTrack => 'Отслеживаемые игроки';
@override String get formula => 'Формула';
@override String get exactValue => 'Точное значение';
@override String get neverPlayedTL => 'Этот игрок никогда не играл в Тетра Лигу';
@override String get exportDB => 'Экспортировать локальную базу данных';
@override String get exportDBDescription => 'Она содержит состояния аккаунтов и их матчей в Тетра Лиге для отслеживаемых игроков и список таких игроков.';
@override String get desktopExportAlertTitle => 'Экспорт на десктопе';
@override String get desktopExportText => 'Похоже, вы используете десктопную версию. Проверьте папку "Документы", там вы должны найти файл "TetraStats.db". Скопируйте его куда-нибудь';
@override String get androidExportAlertTitle => 'Экспорт на Android';
@override String androidExportText({required Object exportedDB}) => 'Экспортировано.\n${exportedDB}';
@override String get importDB => 'Импортировать локальную базу данных';
@override String get importDBDescription => 'Восстановите свою резеврную копию. Обратите внимание, что текущая база данных будет перезаписана.';
@override String get importWrongFileType => 'Неверный тип файла';
@override String get importCancelled => 'Операция была отменена';
@override String get importSuccess => 'Успешно импортировано';
@override String get yourID => 'Ваш аккаунт в TETR.IO';
@override String get yourIDAlertTitle => 'Никнейм или ID вашего аккаунта в TETR.IO';
@override String get yourIDText => 'Каждый раз, когда приложение запускается, приложение будет получать статистику этого игрока. Пожалуйста, отдайте предпочтение ID, так как никнейм можно изменить.';
@override String get language => 'Язык (Language)';
@override String get aboutApp => 'О приложении';
@override String aboutAppText({required Object appName, required Object packageName, required Object version, required Object buildNumber}) => '${appName} (${packageName}) Версия ${version} Сборка ${buildNumber}\n\nРазработал dan63047\nФормулы предоставил kerrmunism';
@override String stateViewTitle({required Object nickname, required Object date}) => 'Аккаунт ${nickname} ${date}';
@override String statesViewTitle({required Object number, required Object nickname}) => '${number} состояний аккаунта ${nickname}';
@override String statesViewEntry({required Object level, required Object gameTime, required Object friends, required Object rd}) => '${level} уровень, ${gameTime} сыграно, ${friends} друзей, ${rd} RD';
@override String stateRemoved({required Object }) => '${}Состояние от {date} было удалено из локальной базы данных!';
@override String get trackedPlayersViewTitle => 'Сохранённые данные';
@override String get trackedPlayersZeroEntrys => 'Пустой список. Вернитесь на предыдущий экран и нажмите кнопку "Отслеживать", чтобы текущий игрок появился здесь';
@override String get trackedPlayersOneEntry => 'В списке только один игрок';
@override String trackedPlayersManyEntrys({required Object numberOfPlayers}) => 'В списке ${numberOfPlayers} игроков';
@override String trackedPlayersEntry({required Object nickname, required Object numberOfStates}) => '${nickname}: ${numberOfStates} состояний';
@override String trackedPlayersDescription({required Object firstStateDate, required Object lastStateDate}) => 'Начиная с ${firstStateDate} и заканчивая ${lastStateDate}';
@override String trackedPlayersStatesDeleted({required Object nickname}) => 'Состояния аккаунта ${nickname} были удалены из локальной базы данных!';
@override late final _StringsStatCellNumRu statCellNum = _StringsStatCellNumRu._(_root);
@override Map<String, String> get playerRole => {
'user': 'Пользователь',
@ -890,6 +975,8 @@ class _StringsStatCellNumRu implements _StringsStatCellNumEn {
// Translations
@override String get xpLevel => 'Уровень\nопыта';
@override String get xpProgress => 'Прогресс до следующего уровня';
@override String get xpFrom0To5000 => 'Прогресс от 0 XP до 5000 уровня';
@override String get hoursPlayed => 'Часов\nСыграно';
@override String get onlineGames => 'Онлайн\nИгр';
@override String get gamesWon => 'Онлайн\nПобед';
@ -911,6 +998,25 @@ class _StringsStatCellNumRu implements _StringsStatCellNumEn {
@override String get keys => 'Нажатий\nКлавиш';
@override String get kpp => 'Нажатий\nна Фигуру';
@override String get kps => 'Нажатий\nв Секунду';
@override String get app => 'Атака на Фигуру';
@override String get appDescription => '(Сокращенно APP) Главный показатель эффективности. Показывает, сколько атаки приходится на одну фигуру';
@override String get vsapmDescription => 'В основном, показывает как много мусора игрок использует в своих атаках и насколько эффективно.';
@override String get dss => 'Downstack\nв Секунду';
@override String get dssDescription => '(Сокращенно DS/S) Downstack (спуск вниз) в Секунду показывает как много мусорных линий в среднем игрок убирает за одну секунду.';
@override String get dsp => 'Downstack\nна Фигуру';
@override String get dspDescription => '(Сокращенно DS/P) Downstack (спуск вниз) на Фигуру показывает как много мусорных линий в среднем игрок убирает одну фигуру.';
@override String get appdsp => 'APP + DS/P';
@override String get appdspDescription => 'Просто сумма Атаки на Фигуру и Downstack на Фигуру.';
@override String get cheese => 'Индекс сыра';
@override String get cheeseDescription => '(Сокращенно Cheese) Индекс сыра является аппроксимацией того, насколько чистый / дырявый мусор игрок отправляет. Меньше = более чистый. Больше = более дырявый.\nПридумал kerrmunism';
@override String get gbe => 'Garbage\nEfficiency';
@override String get gbeDescription => '(Сокращенно Gb Eff.) Garbage Efficiency показывает насколько хорошо игрок использует свой мусор. Больше = лучше (или он использует больше мусора). Меньше = в основном отправляют сыр (или он редко чистит мусор).\nПридумали Zepheniah и Dragonboy.';
@override String get nyaapp => 'Взвешенный\nAPP';
@override String get nyaappDescription => '(Сокращенно wAPP) По сути, показывает способность отправлять сыр, сохраняя при этом высокую эффективность.\nПридумал Wertj.';
@override String get area => 'Area';
@override String get areaDescription => 'Какую площадь занимает диаграмма, если не брать в расчёт индекс сыра и VS/APM';
@override String get estOfTR => 'Расчётный TR';
@override String get accOfEst => 'Точность расчёта';
}
// Path: numOfGameActions
@ -933,6 +1039,8 @@ class _StringsPopupActionsRu implements _StringsPopupActionsEn {
@override final _StringsRu _root; // ignore: unused_field
// Translations
@override String get cancel => 'Отменить';
@override String get submit => 'Подтвердить';
@override String get ok => 'OK';
}
@ -998,7 +1106,40 @@ extension on _StringsEn {
case 'gamesUntilRanked': return ({required Object left}) => '${left} games until being ranked';
case 'nerdStats': return 'Nerd Stats';
case 'playersYouTrack': return 'Players you track';
case 'formula': return 'Formula';
case 'exactValue': return 'Exact value';
case 'neverPlayedTL': return 'That user never played Tetra League';
case 'exportDB': return 'Export local database';
case 'exportDBDescription': return 'It contains states and Tetra League records of the tracked players and list of tracked players.';
case 'desktopExportAlertTitle': return 'Desktop export';
case 'desktopExportText': return 'It seems like you using this app on desktop. Check your documents folder, you should find "TetraStats.db". Copy it somewhere';
case 'androidExportAlertTitle': return 'Android export';
case 'androidExportText': return ({required Object exportedDB}) => 'Exported.\n${exportedDB}';
case 'importDB': return 'Import local database';
case 'importDBDescription': return 'Restore your backup. Notice that already stored database will be overwritten.';
case 'importWrongFileType': return 'Wrong file type';
case 'importCancelled': return 'Operation was cancelled';
case 'importSuccess': return 'Import successful';
case 'yourID': return 'Your TETR.IO account';
case 'yourIDAlertTitle': return 'Your TETR.IO account nickname or ID';
case 'yourIDText': return 'Every time when app loads, stats of that player will be fetched. Please prefer ID over nickname because nickname can be changed.';
case 'language': return 'Language';
case 'aboutApp': return 'About app';
case 'aboutAppText': return ({required Object appName, required Object packageName, required Object version, required Object buildNumber}) => '${appName} (${packageName}) Version ${version} Build ${buildNumber}\n\nDeveloped by dan63047\nFormulas provided by kerrmunism';
case 'stateViewTitle': return ({required Object nickname, required Object date}) => '${nickname} account on ${date}';
case 'statesViewTitle': return ({required Object number, required Object nickname}) => '${number} states of ${nickname} account';
case 'statesViewEntry': return ({required Object level, required Object gameTime, required Object friends, required Object rd}) => 'Level ${level}, ${gameTime} of gametime, ${friends} friends, ${rd} RD';
case 'stateRemoved': return ({required Object date}) => '${date} state was removed from database!';
case 'trackedPlayersViewTitle': return 'Stored data';
case 'trackedPlayersZeroEntrys': return 'Empty list. Press "Track" button in previous view to add current player here';
case 'trackedPlayersOneEntry': return 'There is only one player';
case 'trackedPlayersManyEntrys': return ({required Object numberOfPlayers}) => 'There are ${numberOfPlayers} players';
case 'trackedPlayersEntry': return ({required Object nickname, required Object numberOfStates}) => '${nickname}: ${numberOfStates} states';
case 'trackedPlayersDescription': return ({required Object firstStateDate, required Object lastStateDate}) => 'From ${firstStateDate} until ${lastStateDate}';
case 'trackedPlayersStatesDeleted': return ({required Object nickname}) => '${nickname} states was removed from database!';
case 'statCellNum.xpLevel': return 'XP Level';
case 'statCellNum.xpProgress': return 'Progress to next level';
case 'statCellNum.xpFrom0To5000': return 'Progress from 0 XP to level 5000';
case 'statCellNum.hoursPlayed': return 'Hours\nPlayed';
case 'statCellNum.onlineGames': return 'Online\nGames';
case 'statCellNum.gamesWon': return 'Games\nWon';
@ -1020,6 +1161,25 @@ extension on _StringsEn {
case 'statCellNum.keys': return 'Key\nPresses';
case 'statCellNum.kpp': return 'KP Per\nPiece';
case 'statCellNum.kps': return 'KP Per\nSecond';
case 'statCellNum.app': return 'Attack Per Piece';
case 'statCellNum.appDescription': return '(Abbreviated as APP) Main efficiency metric. Tells how many attack you producing per piece';
case 'statCellNum.vsapmDescription': return 'Basically, tells how much and how efficient you using garbage in your attacks';
case 'statCellNum.dss': return 'Downstack\nPer Second';
case 'statCellNum.dssDescription': return 'Downstack per Second measures how many garbage lines you clear in a second.';
case 'statCellNum.dsp': return 'Downstack\nPer Piece';
case 'statCellNum.dspDescription': return 'Downstack per Piece measures how many garbage lines you clear per piece.';
case 'statCellNum.appdsp': return 'APP + DS/P';
case 'statCellNum.appdspDescription': return 'Just a sum of Attack per Piece and Downstack per Piece.';
case 'statCellNum.cheese': return 'Cheese\nIndex';
case 'statCellNum.cheeseDescription': return 'Cheese Index is an approximation how much clean / cheese garbage player sends. Lower = more clean. Higher = more cheese.\nInvented by kerrmunism';
case 'statCellNum.gbe': return 'Garbage\nEfficiency';
case 'statCellNum.gbeDescription': return 'Garbage Efficiency measures how well player uses their garbage. Higher = better or they use their garbage more. Lower = they mostly send their garbage back at cheese or rarely clear garbage.\nInvented by Zepheniah and Dragonboy.';
case 'statCellNum.nyaapp': return 'Weighted\nAPP';
case 'statCellNum.nyaappDescription': return 'Essentially, a measure of your ability to send cheese while still maintaining a high APP.\nInvented by Wertj.';
case 'statCellNum.area': return 'Area';
case 'statCellNum.areaDescription': return 'How much space your shape takes up on the graph, if you exclude the cheese and vs/apm sections';
case 'statCellNum.estOfTR': return 'Est. of TR';
case 'statCellNum.accOfEst': return 'Accuracy';
case 'playerRole.user': return 'User';
case 'playerRole.banned': return 'Banned';
case 'playerRole.bot': return 'Bot';
@ -1032,6 +1192,8 @@ extension on _StringsEn {
case 'numOfGameActions.hold': return 'Holds';
case 'numOfGameActions.tspinsTotal': return 'T-spins total';
case 'numOfGameActions.lineClears': return 'Line clears';
case 'popupActions.cancel': return 'Cancel';
case 'popupActions.submit': return 'Submit';
case 'popupActions.ok': return 'OK';
case 'errors.connection': return ({required Object code, required Object message}) => 'Some issue with connection: ${code} ${message}';
case 'errors.noSuchUser': return 'No such user';
@ -1346,7 +1508,40 @@ extension on _StringsRu {
case 'gamesUntilRanked': return ({required Object left}) => '${left} матчей до получения рейтинга';
case 'nerdStats': return 'Для задротов';
case 'playersYouTrack': return 'Отслеживаемые игроки';
case 'formula': return 'Формула';
case 'exactValue': return 'Точное значение';
case 'neverPlayedTL': return 'Этот игрок никогда не играл в Тетра Лигу';
case 'exportDB': return 'Экспортировать локальную базу данных';
case 'exportDBDescription': return 'Она содержит состояния аккаунтов и их матчей в Тетра Лиге для отслеживаемых игроков и список таких игроков.';
case 'desktopExportAlertTitle': return 'Экспорт на десктопе';
case 'desktopExportText': return 'Похоже, вы используете десктопную версию. Проверьте папку "Документы", там вы должны найти файл "TetraStats.db". Скопируйте его куда-нибудь';
case 'androidExportAlertTitle': return 'Экспорт на Android';
case 'androidExportText': return ({required Object exportedDB}) => 'Экспортировано.\n${exportedDB}';
case 'importDB': return 'Импортировать локальную базу данных';
case 'importDBDescription': return 'Восстановите свою резеврную копию. Обратите внимание, что текущая база данных будет перезаписана.';
case 'importWrongFileType': return 'Неверный тип файла';
case 'importCancelled': return 'Операция была отменена';
case 'importSuccess': return 'Успешно импортировано';
case 'yourID': return 'Ваш аккаунт в TETR.IO';
case 'yourIDAlertTitle': return 'Никнейм или ID вашего аккаунта в TETR.IO';
case 'yourIDText': return 'Каждый раз, когда приложение запускается, приложение будет получать статистику этого игрока. Пожалуйста, отдайте предпочтение ID, так как никнейм можно изменить.';
case 'language': return 'Язык (Language)';
case 'aboutApp': return 'О приложении';
case 'aboutAppText': return ({required Object appName, required Object packageName, required Object version, required Object buildNumber}) => '${appName} (${packageName}) Версия ${version} Сборка ${buildNumber}\n\nРазработал dan63047\nФормулы предоставил kerrmunism';
case 'stateViewTitle': return ({required Object nickname, required Object date}) => 'Аккаунт ${nickname} ${date}';
case 'statesViewTitle': return ({required Object number, required Object nickname}) => '${number} состояний аккаунта ${nickname}';
case 'statesViewEntry': return ({required Object level, required Object gameTime, required Object friends, required Object rd}) => '${level} уровень, ${gameTime} сыграно, ${friends} друзей, ${rd} RD';
case 'stateRemoved': return ({required Object }) => '${}Состояние от {date} было удалено из локальной базы данных!';
case 'trackedPlayersViewTitle': return 'Сохранённые данные';
case 'trackedPlayersZeroEntrys': return 'Пустой список. Вернитесь на предыдущий экран и нажмите кнопку "Отслеживать", чтобы текущий игрок появился здесь';
case 'trackedPlayersOneEntry': return 'В списке только один игрок';
case 'trackedPlayersManyEntrys': return ({required Object numberOfPlayers}) => 'В списке ${numberOfPlayers} игроков';
case 'trackedPlayersEntry': return ({required Object nickname, required Object numberOfStates}) => '${nickname}: ${numberOfStates} состояний';
case 'trackedPlayersDescription': return ({required Object firstStateDate, required Object lastStateDate}) => 'Начиная с ${firstStateDate} и заканчивая ${lastStateDate}';
case 'trackedPlayersStatesDeleted': return ({required Object nickname}) => 'Состояния аккаунта ${nickname} были удалены из локальной базы данных!';
case 'statCellNum.xpLevel': return 'Уровень\nопыта';
case 'statCellNum.xpProgress': return 'Прогресс до следующего уровня';
case 'statCellNum.xpFrom0To5000': return 'Прогресс от 0 XP до 5000 уровня';
case 'statCellNum.hoursPlayed': return 'Часов\nСыграно';
case 'statCellNum.onlineGames': return 'Онлайн\nИгр';
case 'statCellNum.gamesWon': return 'Онлайн\nПобед';
@ -1368,6 +1563,25 @@ extension on _StringsRu {
case 'statCellNum.keys': return 'Нажатий\nКлавиш';
case 'statCellNum.kpp': return 'Нажатий\nна Фигуру';
case 'statCellNum.kps': return 'Нажатий\nв Секунду';
case 'statCellNum.app': return 'Атака на Фигуру';
case 'statCellNum.appDescription': return '(Сокращенно APP) Главный показатель эффективности. Показывает, сколько атаки приходится на одну фигуру';
case 'statCellNum.vsapmDescription': return 'В основном, показывает как много мусора игрок использует в своих атаках и насколько эффективно.';
case 'statCellNum.dss': return 'Downstack\nв Секунду';
case 'statCellNum.dssDescription': return '(Сокращенно DS/S) Downstack (спуск вниз) в Секунду показывает как много мусорных линий в среднем игрок убирает за одну секунду.';
case 'statCellNum.dsp': return 'Downstack\nна Фигуру';
case 'statCellNum.dspDescription': return '(Сокращенно DS/P) Downstack (спуск вниз) на Фигуру показывает как много мусорных линий в среднем игрок убирает одну фигуру.';
case 'statCellNum.appdsp': return 'APP + DS/P';
case 'statCellNum.appdspDescription': return 'Просто сумма Атаки на Фигуру и Downstack на Фигуру.';
case 'statCellNum.cheese': return 'Индекс сыра';
case 'statCellNum.cheeseDescription': return '(Сокращенно Cheese) Индекс сыра является аппроксимацией того, насколько чистый / дырявый мусор игрок отправляет. Меньше = более чистый. Больше = более дырявый.\nПридумал kerrmunism';
case 'statCellNum.gbe': return 'Garbage\nEfficiency';
case 'statCellNum.gbeDescription': return '(Сокращенно Gb Eff.) Garbage Efficiency показывает насколько хорошо игрок использует свой мусор. Больше = лучше (или он использует больше мусора). Меньше = в основном отправляют сыр (или он редко чистит мусор).\nПридумали Zepheniah и Dragonboy.';
case 'statCellNum.nyaapp': return 'Взвешенный\nAPP';
case 'statCellNum.nyaappDescription': return '(Сокращенно wAPP) По сути, показывает способность отправлять сыр, сохраняя при этом высокую эффективность.\nПридумал Wertj.';
case 'statCellNum.area': return 'Area';
case 'statCellNum.areaDescription': return 'Какую площадь занимает диаграмма, если не брать в расчёт индекс сыра и VS/APM';
case 'statCellNum.estOfTR': return 'Расчётный TR';
case 'statCellNum.accOfEst': return 'Точность расчёта';
case 'playerRole.user': return 'Пользователь';
case 'playerRole.banned': return 'Заблокированный пользователь';
case 'playerRole.bot': return 'Бот';
@ -1380,6 +1594,8 @@ extension on _StringsRu {
case 'numOfGameActions.hold': return 'В запас';
case 'numOfGameActions.tspinsTotal': return 'T-spins всего';
case 'numOfGameActions.lineClears': return 'Линий очищено';
case 'popupActions.cancel': return 'Отменить';
case 'popupActions.submit': return 'Подтвердить';
case 'popupActions.ok': return 'OK';
case 'errors.connection': return ({required Object code, required Object message}) => 'Проблема с подключением: ${code} ${message}';
case 'errors.noSuchUser': return 'Нет такого пользователя';

View File

@ -74,33 +74,31 @@ class SettingsState extends State<SettingsView> {
}
return Scaffold(
appBar: AppBar(
title: const Text("Settings"),
title: Text(t.settings),
),
backgroundColor: Colors.black,
body: SafeArea(
child: ListView(
children: [
ListTile(
title: const Text("Export local database"),
subtitle: const Text(
"It contains states and Tetra League records of the tracked players and list of tracked players."),
title: Text(t.exportDB),
subtitle: Text(t.exportDBDescription),
onTap: () {
if (Platform.isLinux || Platform.isWindows) {
showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text("Desktop export",
style: TextStyle(
title: Text(t.desktopExportAlertTitle,
style: const TextStyle(
fontFamily: "Eurostile Round Extended")),
content: const SingleChildScrollView(
content: SingleChildScrollView(
child: ListBody(children: [
Text(
"It seems like you using this app on desktop. Check your documents folder, you should find \"TetraStats.db\". Copy it somewhere")
Text(t.desktopExportText)
]),
),
actions: <Widget>[
TextButton(
child: const Text('OK'),
child: Text(t.popupActions.ok),
onPressed: () {
Navigator.of(context).pop();
},
@ -116,15 +114,15 @@ class SettingsState extends State<SettingsView> {
showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text("Android export",
style: TextStyle(
title: Text(t.androidExportAlertTitle,
style: const TextStyle(
fontFamily: "Eurostile Round Extended")),
content: SingleChildScrollView(
child: ListBody(children: [Text("Exported.\n$exportedDB")]),
child: ListBody(children: [Text(t.androidExportText(exportedDB: exportedDB))]),
),
actions: <Widget>[
TextButton(
child: const Text('OK'),
child: Text(t.popupActions.ok),
onPressed: () {
Navigator.of(context).pop();
},
@ -136,8 +134,8 @@ class SettingsState extends State<SettingsView> {
},
),
ListTile(
title: const Text("Import local database"),
subtitle: const Text("Restore your backup. Notice that already stored database will be overwritten."),
title: Text(t.importDB),
subtitle: Text(t.importDBDescription),
onTap: () {
if(Platform.isAndroid){
FilePicker.platform.pickFiles(
@ -147,18 +145,18 @@ class SettingsState extends State<SettingsView> {
var newDB = value.paths[0]!;
teto.close().then((value){
if(!newDB.endsWith("db")){
return ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Wrong file type")));
return ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.importWrongFileType)));
}
getApplicationDocumentsDirectory().then((value){
var oldDB = File("${value.path}/TetraStats.db");
oldDB.writeAsBytes(File(newDB).readAsBytesSync(), flush: true).then((value){
teto.open();
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Import successful")));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.importSuccess)));
});
});
});
} else {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Operation was cancelled")));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.importCancelled)));
}
});
}else{
@ -174,42 +172,41 @@ class SettingsState extends State<SettingsView> {
var oldDB = File("${value.path}/TetraStats.db");
oldDB.writeAsBytes(File(newDB).readAsBytesSync()).then((value){
teto.open();
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Import successful")));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.importSuccess)));
});
});
});
} else {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("Operation was cancelled")));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.importCancelled)));
}
});
}
},
),
ListTile(
title: const Text("Your TETR.IO account"),
title: Text(t.yourID),
trailing: Text(defaultNickname),
onTap: () => showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text("Your TETR.IO account nickname or ID",
style: TextStyle(
title: Text(t.yourIDAlertTitle,
style: const TextStyle(
fontFamily: "Eurostile Round Extended")),
content: SingleChildScrollView(
child: ListBody(children: [
const Text(
"Every time when app loads, stats of that player will be fetched. Please prefer ID over nickname because nickname can be changed."),
Text(t.yourIDText),
TextField(controller: _playertext, maxLength: 25)
]),
),
actions: <Widget>[
TextButton(
child: const Text('Cancel'),
child: Text(t.popupActions.cancel),
onPressed: () {
Navigator.of(context).pop();
},
),
TextButton(
child: const Text('Submit'),
child: Text(t.popupActions.submit),
onPressed: () {
_setPlayer(_playertext.text.toLowerCase().trim());
Navigator.of(context).pop();
@ -220,7 +217,7 @@ class SettingsState extends State<SettingsView> {
)),
),
ListTile(
title: const Text("Language"),
title: Text(t.language),
trailing: DropdownButton(
items: locales,
value: LocaleSettings.currentLocale,
@ -229,13 +226,8 @@ class SettingsState extends State<SettingsView> {
),
const Divider(),
ListTile(
title: const Text("About app"),
subtitle: Text("""
${_packageInfo.appName} (${_packageInfo.packageName}) Version ${_packageInfo.version} Build ${_packageInfo.buildNumber}
Developed by dan63047
Formulas provided by kerrmunism
"""),
title: Text(t.aboutApp),
subtitle: Text(t.aboutAppText(appName: _packageInfo.appName, packageName: _packageInfo.packageName, version: _packageInfo.version, buildNumber: _packageInfo.buildNumber)),
),
],
)),

View File

@ -1,8 +1,12 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:tetra_stats/data_objects/tetrio.dart';
import 'package:tetra_stats/gen/strings.g.dart';
import 'package:tetra_stats/widgets/tl_thingy.dart';
import 'package:tetra_stats/widgets/user_thingy.dart';
final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
class StateView extends StatefulWidget {
final TetrioPlayer state;
const StateView({Key? key, required this.state}) : super(key: key);
@ -26,9 +30,10 @@ class StateState extends State<StateView> {
@override
Widget build(BuildContext context) {
final t = Translations.of(context);
return Scaffold(
appBar: AppBar(
title: Text("${widget.state.username.toUpperCase()} account on ${widget.state.state}"),
title: Text(t.stateViewTitle(nickname: widget.state.username.toUpperCase(), date: dateFormat.format(widget.state.state))),
),
backgroundColor: Colors.black,
body: SafeArea(

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:tetra_stats/data_objects/tetrio.dart';
import 'package:tetra_stats/gen/strings.g.dart';
import 'package:tetra_stats/views/compare_view.dart';
import 'package:tetra_stats/views/state_view.dart';
@ -12,14 +13,14 @@ class StatesView extends StatefulWidget {
State<StatefulWidget> createState() => StatesState();
}
final DateFormat dateFormat = DateFormat.yMMMd().add_Hms();
class StatesState extends State<StatesView> {
@override
Widget build(BuildContext context) {
final t = Translations.of(context);
final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
return Scaffold(
appBar: AppBar(
title: Text("${widget.states.length} states of ${widget.states.last.username.toUpperCase()} account"),
title: Text(t.statesViewTitle(number: widget.states.length, nickname: widget.states.last.username.toUpperCase())),
),
backgroundColor: Colors.black,
body: SafeArea(
@ -27,14 +28,14 @@ class StatesState extends State<StatesView> {
itemCount: widget.states.length,
itemBuilder: (context, index) {
return ListTile(
title: Text("On ${dateFormat.format(widget.states[index].state)}"),
subtitle: Text("Level ${widget.states[index].level.toStringAsFixed(2)}, ${widget.states[index].gameTime} of gametime, ${widget.states[index].friendCount} friends, ${NumberFormat.compact().format(widget.states[index].tlSeason1.rd)} RD"),
title: Text(dateFormat.format(widget.states[index].state)),
subtitle: Text(t.statesViewEntry(level: widget.states[index].level.toStringAsFixed(2), gameTime: widget.states[index].gameTime, friends: widget.states[index].friendCount, rd: NumberFormat.compact().format(widget.states[index].tlSeason1.rd))),
trailing: IconButton(
icon: const Icon(Icons.delete_forever),
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!")));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.stateRemoved(date: dateFormat.format(nn)))));
}));
},
),

View File

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:tetra_stats/data_objects/tetrio.dart';
import 'package:tetra_stats/gen/strings.g.dart';
import 'package:tetra_stats/services/tetrio_crud.dart';
import 'package:tetra_stats/views/states_view.dart';
@ -13,14 +14,14 @@ class TrackedPlayersView extends StatefulWidget {
State<StatefulWidget> createState() => TrackedPlayersState();
}
final DateFormat dateFormat = DateFormat.yMMMd().add_Hms();
class TrackedPlayersState extends State<TrackedPlayersView> {
@override
Widget build(BuildContext context) {
final t = Translations.of(context);
final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
return Scaffold(
appBar: AppBar(
title: const Text("Stored data"),
title: Text(t.trackedPlayersViewTitle),
),
backgroundColor: Colors.black,
body: SafeArea(
@ -38,9 +39,9 @@ class TrackedPlayersState extends State<TrackedPlayersView> {
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',
zero: t.trackedPlayersZeroEntrys,
one: t.trackedPlayersOneEntry,
other: t.trackedPlayersManyEntrys(numberOfPlayers: numberOfPlayers),
name: 'howManyPeople',
args: [numberOfPlayers],
desc: 'Description of how many people are seen in a place.',
@ -62,15 +63,14 @@ class TrackedPlayersState extends State<TrackedPlayersView> {
itemCount: allPlayers.length,
itemBuilder: (context, index) {
return ListTile(
title: Text("${allPlayers[keys[index]]?.last.username}: ${allPlayers[keys[index]]?.length} states"),
subtitle: Text(
"From ${dateFormat.format(allPlayers[keys[index]]!.first.state)} until ${dateFormat.format(allPlayers[keys[index]]!.last.state)}"),
title: Text(t.trackedPlayersEntry(nickname: allPlayers[keys[index]]!.last.username, numberOfStates: allPlayers[keys[index]]!.length)),
subtitle: Text(t.trackedPlayersDescription(firstStateDate: dateFormat.format(allPlayers[keys[index]]!.first.state), lastStateDate: dateFormat.format(allPlayers[keys[index]]!.last.state))),
trailing: IconButton(
icon: const Icon(Icons.delete_forever),
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!")));
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(t.trackedPlayersStatesDeleted(nickname: nn))));
},
),
onTap: () {

View File

@ -8,12 +8,16 @@ class StatCellNum extends StatelessWidget {
required this.playerStatLabel,
required this.isScreenBig,
this.alertWidgets,
this.fractionDigits, this.oldPlayerStat, required this.higherIsBetter});
this.fractionDigits,
this.oldPlayerStat,
required this.higherIsBetter,
this.okText});
final num playerStat;
final num? oldPlayerStat;
final bool higherIsBetter;
final String playerStatLabel;
final String? okText;
final bool isScreenBig;
final List<Widget>? alertWidgets;
final int? fractionDigits;
@ -58,10 +62,8 @@ class StatCellNum extends StatelessWidget {
),
actions: <Widget>[
TextButton(
child: const Text('OK'),
onPressed: () {
Navigator.of(context).pop();
},
child: Text(okText??"OK"),
onPressed: () {Navigator.of(context).pop();}
)
],
));

View File

@ -121,7 +121,7 @@ class TLThingy extends StatelessWidget {
width: 200,
height: 120,
child: SfRadialGauge(
title: const GaugeTitle(text: "Attack Per Piece"),
title: GaugeTitle(text: t.statCellNum.app),
axes: [RadialAxis(
startAngle: 180,
endAngle: 360,
@ -155,18 +155,18 @@ class TLThingy extends StatelessWidget {
showDialog(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text("Attack Per Piece",
style: TextStyle(
title: Text(t.statCellNum.app,
style: const TextStyle(
fontFamily: "Eurostile Round Extended")),
content: SingleChildScrollView(
child: ListBody(children: [
const Text("Main efficiency metric. Tells how many attack you producing per piece"),
Text("Raw value: ${tl.nerdStats!.app}")
Text(t.statCellNum.appDescription),
Text("${t.exactValue}: ${tl.nerdStats!.app}")
]),
),
actions: <Widget>[
TextButton(
child: const Text('OK'),
child: Text(t.popupActions.ok),
onPressed: () {
Navigator.of(context).pop();
},
@ -222,13 +222,13 @@ class TLThingy extends StatelessWidget {
fontFamily: "Eurostile Round Extended")),
content: SingleChildScrollView(
child: ListBody(children: [
const Text("Basically, tells how much and how efficient you using garbage in your attacks"),
Text("Raw value: ${tl.nerdStats!.vsapm}")
Text(t.statCellNum.vsapmDescription),
Text("${t.exactValue}: ${tl.nerdStats!.vsapm}")
]),
),
actions: <Widget>[
TextButton(
child: const Text('OK'),
child: Text(t.popupActions.ok),
onPressed: () {
Navigator.of(context).pop();
},
@ -251,46 +251,53 @@ class TLThingy extends StatelessWidget {
crossAxisAlignment: WrapCrossAlignment.start,
clipBehavior: Clip.hardEdge,
children: [
StatCellNum(playerStat: tl.nerdStats!.dss, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Downstack\nPer Second",
alertWidgets: [const Text("Downstack per Second measures how many garbage lines you clear in a second."),
const Text("Formula: (VS / 100) - (APM / 60)"),
Text("Raw value: ${tl.nerdStats!.dss}"),],
StatCellNum(playerStat: tl.nerdStats!.dss, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.dss,
alertWidgets: [Text(t.statCellNum.dssDescription),
Text("${t.formula}: (VS / 100) - (APM / 60)"),
Text("${t.exactValue}: ${tl.nerdStats!.dss}"),],
okText: t.popupActions.ok,
higherIsBetter: true,
oldPlayerStat: oldTl?.nerdStats?.dss,),
StatCellNum(playerStat: tl.nerdStats!.dsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Downstack\nPer Piece",
alertWidgets: [const Text("Downstack per Piece measures how many garbage lines you clear per piece."),
const Text("Formula: DS/S / PPS"),
Text("Raw value: ${tl.nerdStats!.dsp}"),],
StatCellNum(playerStat: tl.nerdStats!.dsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.dsp,
alertWidgets: [Text(t.statCellNum.dspDescription),
Text("${t.formula}: DS/S / PPS"),
Text("${t.exactValue}: ${tl.nerdStats!.dsp}"),],
okText: t.popupActions.ok,
higherIsBetter: true,
oldPlayerStat: oldTl?.nerdStats?.dsp,),
StatCellNum(playerStat: tl.nerdStats!.appdsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "APP + DS/P",
alertWidgets: [const Text("Just a sum of Attack per Piece and Downstack per Piece."),
const Text("Formula: APP + DS/P"),
Text("Raw value: ${tl.nerdStats!.appdsp}"),],
StatCellNum(playerStat: tl.nerdStats!.appdsp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.appdsp,
alertWidgets: [Text(t.statCellNum.appdspDescription),
Text("${t.formula}: APP + DS/P"),
Text("${t.exactValue}: ${tl.nerdStats!.appdsp}"),],
okText: t.popupActions.ok,
higherIsBetter: true,
oldPlayerStat: oldTl?.nerdStats?.appdsp,),
StatCellNum(playerStat: tl.nerdStats!.cheese, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: "Cheese\nIndex",
alertWidgets: [const Text("Cheese Index is an approximation how much clean / cheese garbage player sends. Lower = more clean. Higher = more cheese.\nInvented by kerrmunism"),
const Text("Formula: (DS/P * 150) + ((VS/APM - 2) * 50) + (0.6 - APP) * 125"),
Text("Raw value: ${tl.nerdStats!.cheese}"),],
StatCellNum(playerStat: tl.nerdStats!.cheese, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.cheese,
alertWidgets: [Text(t.statCellNum.cheeseDescription),
Text("${t.formula}: (DS/P * 150) + ((VS/APM - 2) * 50) + (0.6 - APP) * 125"),
Text("${t.exactValue}: ${tl.nerdStats!.cheese}"),],
okText: t.popupActions.ok,
higherIsBetter: true,
oldPlayerStat: oldTl?.nerdStats?.cheese,),
StatCellNum(playerStat: tl.nerdStats!.gbe, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Garbage\nEfficiency",
alertWidgets: [const Text("Garbage Efficiency measures how well player uses their garbage. Higher = better or they use their garbage more. Lower = they mostly send their garbage back at cheese or rarely clear garbage.\nInvented by Zepheniah and Dragonboy."),
const Text("Formula: ((APP * DS/S) / PPS) * 2"),
Text("Raw value: ${tl.nerdStats!.gbe}"),],
StatCellNum(playerStat: tl.nerdStats!.gbe, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.gbe,
alertWidgets: [Text(t.statCellNum.gbeDescription),
Text("${t.formula}: ((APP * DS/S) / PPS) * 2"),
Text("${t.exactValue}: ${tl.nerdStats!.gbe}"),],
okText: t.popupActions.ok,
higherIsBetter: true,
oldPlayerStat: oldTl?.nerdStats?.gbe,),
StatCellNum(playerStat: tl.nerdStats!.nyaapp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: "Weighted\nAPP",
alertWidgets: [const Text("Essentially, a measure of your ability to send cheese while still maintaining a high APP.\nInvented by Wertj."),
const Text("Formula: APP - 5 * tan(radians((Cheese Index / -30) + 1))"),
Text("Raw value: ${tl.nerdStats!.nyaapp}"),],
StatCellNum(playerStat: tl.nerdStats!.nyaapp, isScreenBig: bigScreen, fractionDigits: 3, playerStatLabel: t.statCellNum.nyaapp,
alertWidgets: [Text(t.statCellNum.nyaappDescription),
Text("${t.formula}: APP - 5 * tan(radians((Cheese Index / -30) + 1))"),
Text("${t.exactValue}: ${tl.nerdStats!.nyaapp}"),],
okText: t.popupActions.ok,
higherIsBetter: true,
oldPlayerStat: oldTl?.nerdStats?.nyaapp,),
StatCellNum(playerStat: tl.nerdStats!.area, isScreenBig: bigScreen, fractionDigits: 1, playerStatLabel: "Area",
alertWidgets: [const Text("How much space your shape takes up on the graph, if you exclude the cheese and vs/apm sections"),
const Text("Formula: APM * 1 + PPS * 45 + VS * 0.444 + APP * 185 + DS/S * 175 + DS/P * 450 + Garbage Effi * 315"),
Text("Raw value: ${tl.nerdStats!.area}"),],
StatCellNum(playerStat: tl.nerdStats!.area, isScreenBig: bigScreen, fractionDigits: 1, playerStatLabel: t.statCellNum.area,
alertWidgets: [Text(t.statCellNum.areaDescription),
Text("${t.formula}: APM * 1 + PPS * 45 + VS * 0.444 + APP * 185 + DS/S * 175 + DS/P * 450 + Garbage Effi * 315"),
Text("${t.exactValue}: ${tl.nerdStats!.area}"),],
okText: t.popupActions.ok,
higherIsBetter: true,
oldPlayerStat: oldTl?.nerdStats?.area,)
])
@ -307,9 +314,9 @@ class TLThingy extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Est. of TR:",
style: TextStyle(fontSize: 24),
Text(
"${t.statCellNum.estOfTR}:",
style: const TextStyle(fontSize: 24),
),
Text(
f2.format(tl.estTr!.esttr),
@ -321,9 +328,9 @@ class TLThingy extends StatelessWidget {
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Text(
"Accuracy:",
style: TextStyle(fontSize: 24),
Text(
"${t.statCellNum.accOfEst}:",
style: const TextStyle(fontSize: 24),
),
Text(
fDiff.format(tl.esttracc!),
@ -499,7 +506,7 @@ class TLThingy extends StatelessWidget {
)
]
: [
const Text("That user never played Tetra League", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)),
Text(t.neverPlayedTL, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)),
],
);
},

View File

@ -170,7 +170,8 @@ class UserThingy extends StatelessWidget {
playerStat: player.level,
playerStatLabel: t.statCellNum.xpLevel,
isScreenBig: bigScreen,
alertWidgets: [Text("${NumberFormat.decimalPatternDigits(decimalDigits: 2).format(player.xp)} XP", style: const TextStyle(fontFamily: "Eurostile Round Extended"),), Text("Progress to next level: ${((player.level - player.level.floor()) * 100).toStringAsFixed(2)} %"), Text("Progress from 0 XP to level 5000: ${((player.xp / 67009017.7589378) * 100).toStringAsFixed(2)} %")],
alertWidgets: [Text("${NumberFormat.decimalPatternDigits(decimalDigits: 2).format(player.xp)} XP", style: const TextStyle(fontFamily: "Eurostile Round Extended"),), Text("${t.statCellNum.xpProgress}: ${((player.level - player.level.floor()) * 100).toStringAsFixed(2)} %"), Text("${t.statCellNum.xpFrom0To5000}: ${((player.xp / 67009017.7589378) * 100).toStringAsFixed(2)} %")],
okText: t.popupActions.ok,
higherIsBetter: true,
),
if (player.gameTime >= Duration.zero)

View File

@ -45,8 +45,41 @@
"gamesUntilRanked": "${left} games until being ranked",
"nerdStats": "Nerd Stats",
"playersYouTrack": "Players you track",
"formula": "Formula",
"exactValue": "Exact value",
"neverPlayedTL": "That user never played Tetra League",
"exportDB": "Export local database",
"exportDBDescription": "It contains states and Tetra League records of the tracked players and list of tracked players.",
"desktopExportAlertTitle": "Desktop export",
"desktopExportText": "It seems like you using this app on desktop. Check your documents folder, you should find \"TetraStats.db\". Copy it somewhere",
"androidExportAlertTitle": "Android export",
"androidExportText": "Exported.\n${exportedDB}",
"importDB": "Import local database",
"importDBDescription": "Restore your backup. Notice that already stored database will be overwritten.",
"importWrongFileType": "Wrong file type",
"importCancelled": "Operation was cancelled",
"importSuccess": "Import successful",
"yourID": "Your TETR.IO account",
"yourIDAlertTitle": "Your TETR.IO account nickname or ID",
"yourIDText": "Every time when app loads, stats of that player will be fetched. Please prefer ID over nickname because nickname can be changed.",
"language": "Language",
"aboutApp": "About app",
"aboutAppText": "${appName} (${packageName}) Version ${version} Build ${buildNumber}\n\nDeveloped by dan63047\nFormulas provided by kerrmunism",
"stateViewTitle": "${nickname} account on ${date}",
"statesViewTitle": "${number} states of ${nickname} account",
"statesViewEntry": "Level ${level}, ${gameTime} of gametime, ${friends} friends, ${rd} RD",
"stateRemoved": "${date} state was removed from database!",
"trackedPlayersViewTitle": "Stored data",
"trackedPlayersZeroEntrys": "Empty list. Press \"Track\" button in previous view to add current player here",
"trackedPlayersOneEntry": "There is only one player",
"trackedPlayersManyEntrys": "There are ${numberOfPlayers} players",
"trackedPlayersEntry": "${nickname}: ${numberOfStates} states",
"trackedPlayersDescription": "From ${firstStateDate} until ${lastStateDate}",
"trackedPlayersStatesDeleted": "${nickname} states was removed from database!",
"statCellNum":{
"xpLevel": "XP Level",
"xpProgress": "Progress to next level",
"xpFrom0To5000": "Progress from 0 XP to level 5000",
"hoursPlayed": "Hours\nPlayed",
"onlineGames": "Online\nGames",
"gamesWon": "Games\nWon",
@ -67,7 +100,26 @@
"finessePercentage": "Finesse\nPercentage",
"keys": "Key\nPresses",
"kpp": "KP Per\nPiece",
"kps": "KP Per\nSecond"
"kps": "KP Per\nSecond",
"app": "Attack Per Piece",
"appDescription": "(Abbreviated as APP) Main efficiency metric. Tells how many attack you producing per piece",
"vsapmDescription": "Basically, tells how much and how efficient you using garbage in your attacks",
"dss": "Downstack\nPer Second",
"dssDescription": "Downstack per Second measures how many garbage lines you clear in a second.",
"dsp": "Downstack\nPer Piece",
"dspDescription": "Downstack per Piece measures how many garbage lines you clear per piece.",
"appdsp": "APP + DS/P",
"appdspDescription": "Just a sum of Attack per Piece and Downstack per Piece.",
"cheese": "Cheese\nIndex",
"cheeseDescription": "Cheese Index is an approximation how much clean / cheese garbage player sends. Lower = more clean. Higher = more cheese.\nInvented by kerrmunism",
"gbe": "Garbage\nEfficiency",
"gbeDescription": "Garbage Efficiency measures how well player uses their garbage. Higher = better or they use their garbage more. Lower = they mostly send their garbage back at cheese or rarely clear garbage.\nInvented by Zepheniah and Dragonboy.",
"nyaapp": "Weighted\nAPP",
"nyaappDescription": "Essentially, a measure of your ability to send cheese while still maintaining a high APP.\nInvented by Wertj.",
"area": "Area",
"areaDescription": "How much space your shape takes up on the graph, if you exclude the cheese and vs/apm sections",
"estOfTR": "Est. of TR",
"accOfEst": "Accuracy"
},
"playerRole(map)": {
"user": "User",
@ -86,6 +138,8 @@
"lineClears": "Line clears"
},
"popupActions":{
"cancel": "Cancel",
"submit": "Submit",
"ok": "OK"
},
"errors":{

View File

@ -45,8 +45,41 @@
"gamesUntilRanked": "${left} матчей до получения рейтинга",
"nerdStats": "Для задротов",
"playersYouTrack": "Отслеживаемые игроки",
"formula": "Формула",
"exactValue": "Точное значение",
"neverPlayedTL": "Этот игрок никогда не играл в Тетра Лигу",
"exportDB": "Экспортировать локальную базу данных",
"exportDBDescription": "Она содержит состояния аккаунтов и их матчей в Тетра Лиге для отслеживаемых игроков и список таких игроков.",
"desktopExportAlertTitle": "Экспорт на десктопе",
"desktopExportText": "Похоже, вы используете десктопную версию. Проверьте папку \"Документы\", там вы должны найти файл \"TetraStats.db\". Скопируйте его куда-нибудь",
"androidExportAlertTitle": "Экспорт на Android",
"androidExportText": "Экспортировано.\n${exportedDB}",
"importDB": "Импортировать локальную базу данных",
"importDBDescription": "Восстановите свою резеврную копию. Обратите внимание, что текущая база данных будет перезаписана.",
"importWrongFileType": "Неверный тип файла",
"importCancelled": "Операция была отменена",
"importSuccess": "Успешно импортировано",
"yourID": "Ваш аккаунт в TETR.IO",
"yourIDAlertTitle": "Никнейм или ID вашего аккаунта в TETR.IO",
"yourIDText": "Каждый раз, когда приложение запускается, приложение будет получать статистику этого игрока. Пожалуйста, отдайте предпочтение ID, так как никнейм можно изменить.",
"language": "Язык (Language)",
"aboutApp": "О приложении",
"aboutAppText": "${appName} (${packageName}) Версия ${version} Сборка ${buildNumber}\n\nРазработал dan63047\nФормулы предоставил kerrmunism",
"stateViewTitle": "Аккаунт ${nickname} ${date}",
"statesViewTitle": "${number} состояний аккаунта ${nickname}",
"statesViewEntry": "${level} уровень, ${gameTime} сыграно, ${friends} друзей, ${rd} RD",
"stateRemoved": "$Состояние от {date} было удалено из локальной базы данных!",
"trackedPlayersViewTitle": "Сохранённые данные",
"trackedPlayersZeroEntrys": "Пустой список. Вернитесь на предыдущий экран и нажмите кнопку \"Отслеживать\", чтобы текущий игрок появился здесь",
"trackedPlayersOneEntry": "В списке только один игрок",
"trackedPlayersManyEntrys": "В списке ${numberOfPlayers} игроков",
"trackedPlayersEntry": "${nickname}: ${numberOfStates} состояний",
"trackedPlayersDescription": "Начиная с ${firstStateDate} и заканчивая ${lastStateDate}",
"trackedPlayersStatesDeleted": "Состояния аккаунта ${nickname} были удалены из локальной базы данных!",
"statCellNum": {
"xpLevel": "Уровень\nопыта",
"xpProgress": "Прогресс до следующего уровня",
"xpFrom0To5000": "Прогресс от 0 XP до 5000 уровня",
"hoursPlayed": "Часов\nСыграно",
"onlineGames": "Онлайн\nИгр",
"gamesWon": "Онлайн\nПобед",
@ -67,7 +100,26 @@
"finessePercentage": "% Качества\nТехники",
"keys": "Нажатий\nКлавиш",
"kpp": "Нажатий\nна Фигуру",
"kps": "Нажатий\nв Секунду"
"kps": "Нажатий\nв Секунду",
"app": "Атака на Фигуру",
"appDescription": "(Сокращенно APP) Главный показатель эффективности. Показывает, сколько атаки приходится на одну фигуру",
"vsapmDescription": "В основном, показывает как много мусора игрок использует в своих атаках и насколько эффективно.",
"dss": "Downstack\nв Секунду",
"dssDescription": "(Сокращенно DS/S) Downstack (спуск вниз) в Секунду показывает как много мусорных линий в среднем игрок убирает за одну секунду.",
"dsp": "Downstack\nна Фигуру",
"dspDescription": "(Сокращенно DS/P) Downstack (спуск вниз) на Фигуру показывает как много мусорных линий в среднем игрок убирает одну фигуру.",
"appdsp": "APP + DS/P",
"appdspDescription": "Просто сумма Атаки на Фигуру и Downstack на Фигуру.",
"cheese": "Индекс сыра",
"cheeseDescription": "(Сокращенно Cheese) Индекс сыра является аппроксимацией того, насколько чистый / дырявый мусор игрок отправляет. Меньше = более чистый. Больше = более дырявый.\nПридумал kerrmunism",
"gbe": "Garbage\nEfficiency",
"gbeDescription": "(Сокращенно Gb Eff.) Garbage Efficiency показывает насколько хорошо игрок использует свой мусор. Больше = лучше (или он использует больше мусора). Меньше = в основном отправляют сыр (или он редко чистит мусор).\nПридумали Zepheniah и Dragonboy.",
"nyaapp": "Взвешенный\nAPP",
"nyaappDescription": "(Сокращенно wAPP) По сути, показывает способность отправлять сыр, сохраняя при этом высокую эффективность.\nПридумал Wertj.",
"area": "Area",
"areaDescription": "Какую площадь занимает диаграмма, если не брать в расчёт индекс сыра и VS/APM",
"estOfTR": "Расчётный TR",
"accOfEst": "Точность расчёта"
},
"playerRole(map)": {
"user": "Пользователь",
@ -86,6 +138,8 @@
"lineClears": "Линий очищено"
},
"popupActions":{
"cancel": "Отменить",
"submit": "Подтвердить",
"ok": "OK"
},
"errors":{