From 1ef2d7af4a4da03a80d66370c3e23371a5f87ed1 Mon Sep 17 00:00:00 2001 From: dan63047 Date: Mon, 21 Aug 2023 00:57:01 +0300 Subject: [PATCH] i18n for rank averages view --- lib/data_objects/tetrio.dart | 7 +- lib/gen/strings.g.dart | 100 +++++++++++++++- lib/views/rank_averages_view.dart | 180 ++++++++++++++--------------- lib/views/ranks_averages_view.dart | 2 +- lib/views/tl_leaderboard_view.dart | 4 +- lib/widgets/tl_thingy.dart | 5 +- res/i18n/strings.i18n.json | 24 +++- res/i18n/strings_ru.i18n.json | 24 +++- 8 files changed, 235 insertions(+), 111 deletions(-) diff --git a/lib/data_objects/tetrio.dart b/lib/data_objects/tetrio.dart index cdc6c27..6a4fbfd 100644 --- a/lib/data_objects/tetrio.dart +++ b/lib/data_objects/tetrio.dart @@ -32,7 +32,8 @@ const Map rankCutoffs = { "c-": 0.95, "d+": 0.975, "d": 1, - "z": -1 + "z": -1, + "": 0.5 }; const Map rankColors = { // thanks osk for const rankColors at https://ch.tetr.io/res/js/base.js:418 'x': Color(0xFFFF45FF), @@ -921,8 +922,6 @@ class TetrioPlayersLeaderboard { List filtredLeaderboard = List.from(leaderboard); if (rank.isNotEmpty) { filtredLeaderboard.removeWhere((element) => element.rank != rank); - } else { - rank = "z"; } if (filtredLeaderboard.isNotEmpty){ double avgAPM = 0, @@ -1334,7 +1333,7 @@ class TetrioPlayersLeaderboard { avgInfDS /= filtredLeaderboard.length; avgGamesPlayed = (totalGamesPlayed / filtredLeaderboard.length).floor(); avgGamesWon = (totalGamesWon / filtredLeaderboard.length).floor(); - return [TetraLeagueAlpha(timestamp: DateTime.now(), apm: avgAPM, pps: avgPPS, vs: avgVS, glicko: avgGlicko, rd: avgRD, gamesPlayed: avgGamesPlayed, gamesWon: avgGamesWon, bestRank: rank, decaying: false, rating: avgTR, rank: rank, percentileRank: rank, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1), + return [TetraLeagueAlpha(timestamp: DateTime.now(), apm: avgAPM, pps: avgPPS, vs: avgVS, glicko: avgGlicko, rd: avgRD, gamesPlayed: avgGamesPlayed, gamesWon: avgGamesWon, bestRank: rank, decaying: false, rating: avgTR, rank: rank == "" ? "z" : rank, percentileRank: rank, percentile: rankCutoffs[rank]!, standing: -1, standingLocal: -1, nextAt: -1, prevAt: -1), { "everyone": rank == "", "totalGamesPlayed": totalGamesPlayed, diff --git a/lib/gen/strings.g.dart b/lib/gen/strings.g.dart index 20c39fb..da4e39a 100644 --- a/lib/gen/strings.g.dart +++ b/lib/gen/strings.g.dart @@ -4,9 +4,9 @@ /// To regenerate, run: `dart run slang` /// /// Locales: 2 -/// Strings: 856 (428 per locale) +/// Strings: 896 (448 per locale) /// -/// Built on 2023-07-20 at 16:26 UTC +/// Built on 2023-08-20 at 21:53 UTC // coverage:ignore-file // ignore_for_file: type=lint @@ -252,7 +252,26 @@ class _StringsEn implements BaseTranslations { String get averages => 'Averages'; String get lbViewZeroEntrys => 'Empty list. Looks like something is wrong...'; String get lbViewOneEntry => 'There is only one player... What?'; - String lbViewManyEntrys({required Object numberOfPlayers}) => 'There are ${numberOfPlayers} ranked players.'; + String lbViewManyEntrys({required Object numberOfPlayers}) => 'There are ${numberOfPlayers}.'; + String get everyoneAverages => 'Values for leaderboard'; + String rankAverages({required Object rank}) => 'Values for ${rank} rank'; + String players({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + zero: '${n} players', + one: '${n} player', + two: '${n} players', + few: '${n} players', + many: '${n} players', + other: '${n} players', + ); + String get chart => 'Chart'; + String get entries => 'Entries'; + String get minimums => 'Minimums'; + String get maximums => 'Maximums'; + String get lowestValues => 'Lowest Values'; + String get averageValues => 'Average Values'; + String get highestValues => 'Highest Values'; + String forPlayer({required Object username}) => 'for player ${username}'; + String currentAxis({required Object axis}) => '${axis} axis:'; String get p1nkl0bst3rAlert => 'That data was retrived from third party API maintained by p1nkl0bst3r'; String get notForWeb => 'Function is not available for web version'; late final _StringsStatCellNumEn statCellNum = _StringsStatCellNumEn._(_root); @@ -544,6 +563,8 @@ class _StringsStatCellNumEn { String get hoursPlayed => 'Hours\nPlayed'; String get onlineGames => 'Online\nGames'; String get gamesWon => 'Games\nWon'; + String get totalGames => 'Total Games Played'; + String get totalWon => 'Total Games Won'; String get friends => 'Friends'; String get apm => 'Attack\nPer Minute'; String get vs => 'Versus\nScore'; @@ -566,6 +587,7 @@ class _StringsStatCellNumEn { String get kpp => 'KP Per\nPiece'; String get kps => 'KP Per\nSecond'; String get tr => 'Tetra Rating'; + String get rd => 'Rating Deviation'; 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'; @@ -753,7 +775,26 @@ class _StringsRu implements _StringsEn { @override String get averages => 'Средние значения'; @override String get lbViewZeroEntrys => 'Рейтинговая таблица пуста. Похоже, что-то здесь не так...'; @override String get lbViewOneEntry => 'В рейтинговой таблице всего один игрок... Чего?'; - @override String lbViewManyEntrys({required Object numberOfPlayers}) => 'В рейтинговой таблице находится ${numberOfPlayers} игроков.'; + @override String lbViewManyEntrys({required Object numberOfPlayers}) => 'В рейтинговой таблице находится ${numberOfPlayers}.'; + @override String get everyoneAverages => 'Значения таблицы'; + @override String rankAverages({required Object rank}) => 'Значения для ${rank} ранга'; + @override String players({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, + zero: '${n} игроков', + one: '${n} игрок', + two: '${n} игрока', + few: '${n} игрока', + many: '${n} игроков', + other: '${n} игроков', + ); + @override String get chart => 'График'; + @override String get entries => 'Список'; + @override String get minimums => 'Минимумы'; + @override String get maximums => 'Максимумы'; + @override String get lowestValues => 'Самые низкие показатели'; + @override String get averageValues => 'Средние значения показателей'; + @override String get highestValues => 'Самые высокие показатели'; + @override String forPlayer({required Object username}) => 'для игрока ${username}'; + @override String currentAxis({required Object axis}) => 'Ось ${axis}:'; @override String get p1nkl0bst3rAlert => 'Эти данные были получены из стороннего API, который поддерживается p1nkl0bst3r'; @override String get notForWeb => 'Функция недоступна для веб версии'; @override late final _StringsStatCellNumRu statCellNum = _StringsStatCellNumRu._(_root); @@ -1045,6 +1086,8 @@ class _StringsStatCellNumRu implements _StringsStatCellNumEn { @override String get hoursPlayed => 'Часов\nСыграно'; @override String get onlineGames => 'Онлайн\nИгр'; @override String get gamesWon => 'Онлайн\nПобед'; + @override String get totalGames => 'Всего матчей'; + @override String get totalWon => 'Всего побед'; @override String get friends => 'Друзей'; @override String get apm => 'Атака в\nМинуту'; @override String get vs => 'Показатель\nVersus'; @@ -1067,6 +1110,7 @@ class _StringsStatCellNumRu implements _StringsStatCellNumEn { @override String get kpp => 'Нажатий\nна Фигуру'; @override String get kps => 'Нажатий\nв Секунду'; @override String get tr => 'Тетра Рейтинг'; + @override String get rd => 'Отклонение рейтинга'; @override String get app => 'Атака на Фигуру'; @override String get appDescription => '(Сокращенно APP) Главный показатель эффективности. Показывает, сколько атаки приходится на одну фигуру'; @override String get vsapmDescription => 'В основном, показывает как много мусора игрок использует в своих атаках и насколько эффективно.'; @@ -1233,7 +1277,26 @@ extension on _StringsEn { case 'averages': return 'Averages'; case 'lbViewZeroEntrys': return 'Empty list. Looks like something is wrong...'; case 'lbViewOneEntry': return 'There is only one player... What?'; - case 'lbViewManyEntrys': return ({required Object numberOfPlayers}) => 'There are ${numberOfPlayers} ranked players.'; + case 'lbViewManyEntrys': return ({required Object numberOfPlayers}) => 'There are ${numberOfPlayers}.'; + case 'everyoneAverages': return 'Values for leaderboard'; + case 'rankAverages': return ({required Object rank}) => 'Values for ${rank} rank'; + case 'players': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n, + zero: '${n} players', + one: '${n} player', + two: '${n} players', + few: '${n} players', + many: '${n} players', + other: '${n} players', + ); + case 'chart': return 'Chart'; + case 'entries': return 'Entries'; + case 'minimums': return 'Minimums'; + case 'maximums': return 'Maximums'; + case 'lowestValues': return 'Lowest Values'; + case 'averageValues': return 'Average Values'; + case 'highestValues': return 'Highest Values'; + case 'forPlayer': return ({required Object username}) => 'for player ${username}'; + case 'currentAxis': return ({required Object axis}) => '${axis} axis:'; case 'p1nkl0bst3rAlert': return 'That data was retrived from third party API maintained by p1nkl0bst3r'; case 'notForWeb': return 'Function is not available for web version'; case 'statCellNum.xpLevel': return 'XP Level'; @@ -1242,6 +1305,8 @@ extension on _StringsEn { case 'statCellNum.hoursPlayed': return 'Hours\nPlayed'; case 'statCellNum.onlineGames': return 'Online\nGames'; case 'statCellNum.gamesWon': return 'Games\nWon'; + case 'statCellNum.totalGames': return 'Total Games Played'; + case 'statCellNum.totalWon': return 'Total Games Won'; case 'statCellNum.friends': return 'Friends'; case 'statCellNum.apm': return 'Attack\nPer Minute'; case 'statCellNum.vs': return 'Versus\nScore'; @@ -1264,6 +1329,7 @@ extension on _StringsEn { case 'statCellNum.kpp': return 'KP Per\nPiece'; case 'statCellNum.kps': return 'KP Per\nSecond'; case 'statCellNum.tr': return 'Tetra Rating'; + case 'statCellNum.rd': return 'Rating Deviation'; 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'; @@ -1669,7 +1735,26 @@ extension on _StringsRu { case 'averages': return 'Средние значения'; case 'lbViewZeroEntrys': return 'Рейтинговая таблица пуста. Похоже, что-то здесь не так...'; case 'lbViewOneEntry': return 'В рейтинговой таблице всего один игрок... Чего?'; - case 'lbViewManyEntrys': return ({required Object numberOfPlayers}) => 'В рейтинговой таблице находится ${numberOfPlayers} игроков.'; + case 'lbViewManyEntrys': return ({required Object numberOfPlayers}) => 'В рейтинговой таблице находится ${numberOfPlayers}.'; + case 'everyoneAverages': return 'Значения таблицы'; + case 'rankAverages': return ({required Object rank}) => 'Значения для ${rank} ранга'; + case 'players': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n, + zero: '${n} игроков', + one: '${n} игрок', + two: '${n} игрока', + few: '${n} игрока', + many: '${n} игроков', + other: '${n} игроков', + ); + case 'chart': return 'График'; + case 'entries': return 'Список'; + case 'minimums': return 'Минимумы'; + case 'maximums': return 'Максимумы'; + case 'lowestValues': return 'Самые низкие показатели'; + case 'averageValues': return 'Средние значения показателей'; + case 'highestValues': return 'Самые высокие показатели'; + case 'forPlayer': return ({required Object username}) => 'для игрока ${username}'; + case 'currentAxis': return ({required Object axis}) => 'Ось ${axis}:'; case 'p1nkl0bst3rAlert': return 'Эти данные были получены из стороннего API, который поддерживается p1nkl0bst3r'; case 'notForWeb': return 'Функция недоступна для веб версии'; case 'statCellNum.xpLevel': return 'Уровень\nопыта'; @@ -1678,6 +1763,8 @@ extension on _StringsRu { case 'statCellNum.hoursPlayed': return 'Часов\nСыграно'; case 'statCellNum.onlineGames': return 'Онлайн\nИгр'; case 'statCellNum.gamesWon': return 'Онлайн\nПобед'; + case 'statCellNum.totalGames': return 'Всего матчей'; + case 'statCellNum.totalWon': return 'Всего побед'; case 'statCellNum.friends': return 'Друзей'; case 'statCellNum.apm': return 'Атака в\nМинуту'; case 'statCellNum.vs': return 'Показатель\nVersus'; @@ -1700,6 +1787,7 @@ extension on _StringsRu { case 'statCellNum.kpp': return 'Нажатий\nна Фигуру'; case 'statCellNum.kps': return 'Нажатий\nв Секунду'; case 'statCellNum.tr': return 'Тетра Рейтинг'; + case 'statCellNum.rd': return 'Отклонение рейтинга'; case 'statCellNum.app': return 'Атака на Фигуру'; case 'statCellNum.appDescription': return '(Сокращенно APP) Главный показатель эффективности. Показывает, сколько атаки приходится на одну фигуру'; case 'statCellNum.vsapmDescription': return 'В основном, показывает как много мусора игрок использует в своих атаках и насколько эффективно.'; diff --git a/lib/views/rank_averages_view.dart b/lib/views/rank_averages_view.dart index d3eb750..5cf3819 100644 --- a/lib/views/rank_averages_view.dart +++ b/lib/views/rank_averages_view.dart @@ -81,7 +81,7 @@ class RankState extends State with SingleTickerProviderStateMixin { bool bigScreen = MediaQuery.of(context).size.width > 768; return Scaffold( appBar: AppBar( - title: Text(widget.rank[0].rank.toUpperCase()), + title: Text(widget.rank[1]["everyone"] ? t.everyoneAverages : t.rankAverages(rank: widget.rank[0].rank.toUpperCase())), ), backgroundColor: Colors.black, body: SafeArea( @@ -110,12 +110,12 @@ class RankState extends State with SingleTickerProviderStateMixin { child: Column( children: [ Text( - "Values for ${widget.rank[0].rank.toUpperCase()} rank", + widget.rank[1]["everyone"] ? t.everyoneAverages : t.rankAverages(rank: widget.rank[0].rank.toUpperCase()), style: TextStyle( fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), Text( - "${widget.rank[1]["entries"].length} players", + t.players(n: widget.rank[1]["entries"].length), style: TextStyle( fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), @@ -123,48 +123,19 @@ class RankState extends State with SingleTickerProviderStateMixin { )), ], ), - // Wrap( - // direction: Axis.horizontal, - // alignment: WrapAlignment.center, - // spacing: 25, - // crossAxisAlignment: WrapCrossAlignment.start, - // clipBehavior: Clip.hardEdge, // hard WHAT??? - // children: [ - // StatCellNum( - // playerStat: widget.rank[1]["totalGamesPlayed"], - // playerStatLabel: "Total games\nplayed", - // isScreenBig: bigScreen, - // higherIsBetter: true, - // ), - // StatCellNum( - // playerStat: widget.rank[1]["totalGamesWon"], - // playerStatLabel: "Total games\nwon", - // isScreenBig: bigScreen, - // higherIsBetter: true, - // ), - // StatCellNum( - // playerStat: (widget.rank[1]["totalGamesWon"] / - // widget.rank[1]["totalGamesPlayed"]) * - // 100, - // playerStatLabel: t.statCellNum.winrate, - // fractionDigits: 3, - // isScreenBig: bigScreen, - // higherIsBetter: true) - // ], - // ), ], )), SliverToBoxAdapter( child: TabBar( controller: _tabController, isScrollable: true, - tabs: const [ - Tab(text: "Chart"), - Tab(text: "Entries"), - Tab(text: "Minimums"), - Tab(text: "Averages"), - Tab(text: "Maximums"), - Tab(text: "Other"), + tabs: [ + Tab(text: t.chart), + Tab(text: t.entries), + Tab(text: t.minimums), + Tab(text: t.averages), + Tab(text: t.maximums), + Tab(text: t.other), ], )), ]; @@ -174,15 +145,18 @@ class RankState extends State with SingleTickerProviderStateMixin { children: [ Column( children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, + Wrap( + direction: Axis.horizontal, + alignment: WrapAlignment.center, + spacing: 25, children: [Column( children: [ Row( + mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.all(8.0), - child: Text("X axis:", style: const TextStyle(fontSize: 22))), + child: Text(t.currentAxis(axis: "X"), style: const TextStyle(fontSize: 22))), DropdownButton( items: chartsShortTitlesDropdowns, value: chartsShortTitlesDropdowns[chartsIndexX].value, @@ -197,10 +171,11 @@ class RankState extends State with SingleTickerProviderStateMixin { ),Column( children: [ Row( + mainAxisSize: MainAxisSize.min, children: [ Padding( padding: const EdgeInsets.all(8.0), - child: Text("Y axis:", style: const TextStyle(fontSize: 22)), + child: Text(t.currentAxis(axis: "Y"), style: const TextStyle(fontSize: 22)), ), DropdownButton( items: chartsShortTitlesDropdowns, @@ -225,15 +200,15 @@ class RankState extends State with SingleTickerProviderStateMixin { : const EdgeInsets.fromLTRB(0, 40, 16, 48), child: ScatterChart( ScatterChartData( - scatterSpots: [ for (TetrioPlayerFromLeaderboard entry in widget.rank[1]["entries"]) MyScatterSpot(takeStat(entry, chartsShortTitles[chartsIndexX]), takeStat(entry, chartsShortTitles[chartsIndexY]), entry.userId, entry.username, color: rankColors[entry.rank])], + scatterSpots: [ for (TetrioPlayerFromLeaderboard entry in widget.rank[1]["entries"]) _MyScatterSpot(takeStat(entry, chartsShortTitles[chartsIndexX]), takeStat(entry, chartsShortTitles[chartsIndexY]), entry.userId, entry.username, color: rankColors[entry.rank])], scatterTouchData: ScatterTouchData(touchTooltipData: ScatterTouchTooltipData( fitInsideHorizontally: true, fitInsideVertically: true, getTooltipItems: (touchedSpot) { - touchedSpot as MyScatterSpot; + touchedSpot as _MyScatterSpot; return ScatterTooltipItem("${touchedSpot.nickname}\n", textStyle: TextStyle(fontFamily: "Eurostile Round Extended"), children: [TextSpan(text: "${f4.format(touchedSpot.x)} ${chartsShortTitles[chartsIndexX]}\n${f4.format(touchedSpot.y)} ${chartsShortTitles[chartsIndexY]}", style: TextStyle(fontFamily: "Eurostile Round"))]); }), touchCallback:(event, response) { if (event.runtimeType == FlTapDownEvent && response?.touchedSpot?.spot != null){ - var spot = response?.touchedSpot?.spot as MyScatterSpot; + var spot = response?.touchedSpot?.spot as _MyScatterSpot; Navigator.push( context, MaterialPageRoute( @@ -255,7 +230,7 @@ class RankState extends State with SingleTickerProviderStateMixin { ), Column( children: [ - Text("Entries", + Text(t.entries, style: TextStyle( fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), @@ -305,7 +280,7 @@ class RankState extends State with SingleTickerProviderStateMixin { ), Column( children: [ - Text("Lowest Values", + Text(t.lowestValues, style: TextStyle( fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), @@ -314,7 +289,8 @@ class RankState extends State with SingleTickerProviderStateMixin { children: [ _ListEntry( value: widget.rank[1]["lowestTR"], - label: "Tetra Rating", + label: t.statCellNum.tr + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestTRid"], username: widget.rank[1]["lowestTRnick"], approximate: false, @@ -328,49 +304,56 @@ class RankState extends State with SingleTickerProviderStateMixin { fractionDigits: 2), _ListEntry( value: widget.rank[1]["lowestRD"], - label: "Rating Deviation", + label: t.statCellNum.rd + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestRdID"], username: widget.rank[1]["lowestRdNick"], approximate: false, fractionDigits: 3), _ListEntry( value: widget.rank[1]["lowestGamesPlayed"], - label: "Games Played", + label: t.statCellNum.gamesPlayed + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestGamesPlayedID"], username: widget.rank[1] ["lowestGamesPlayedNick"], approximate: false), _ListEntry( value: widget.rank[1]["lowestGamesWon"], - label: "Games Won", + label: t.statCellNum.gamesWonTL + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestGamesWonID"], username: widget.rank[1] ["lowestGamesWonNick"], approximate: false), _ListEntry( value: widget.rank[1]["lowestWinrate"] * 100, - label: "Winrate Percentage", + label: t.statCellNum.winrate + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestWinrateID"], username: widget.rank[1]["lowestWinrateNick"], approximate: false, fractionDigits: 2), _ListEntry( value: widget.rank[1]["lowestAPM"], - label: "Attack Per Minute", + label: t.statCellNum.apm + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestAPMid"], username: widget.rank[1]["lowestAPMnick"], approximate: false, fractionDigits: 2), _ListEntry( value: widget.rank[1]["lowestPPS"], - label: "Pieces Per Second", + label: t.statCellNum.pps + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestPPSid"], username: widget.rank[1]["lowestPPSnick"], approximate: false, fractionDigits: 2), _ListEntry( value: widget.rank[1]["lowestVS"], - label: "Versus Score", + label: t.statCellNum.vs + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["lowestVSid"], username: widget.rank[1]["lowestVSnick"], approximate: false, @@ -485,7 +468,7 @@ class RankState extends State with SingleTickerProviderStateMixin { fractionDigits: 3), _ListEntry( value: widget.rank[1]["lowestInfDS"], - label: "InfDS", + label: "Inf. DS", id: widget.rank[1]["lowestInfDSid"], username: widget.rank[1]["lowestInfDSnick"], approximate: false, @@ -497,7 +480,7 @@ class RankState extends State with SingleTickerProviderStateMixin { ), Column( children: [ - Text("Average Values", + Text(t.averageValues, style: TextStyle( fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), @@ -505,7 +488,8 @@ class RankState extends State with SingleTickerProviderStateMixin { child: ListView(children: [ _ListEntry( value: widget.rank[0].rating, - label: "Tetra Rating", + label: t.statCellNum.tr + .replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, @@ -519,56 +503,64 @@ class RankState extends State with SingleTickerProviderStateMixin { fractionDigits: 2), _ListEntry( value: widget.rank[0].rd, - label: "Rating Deviation", + label: t.statCellNum.rd + .replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 3), _ListEntry( value: widget.rank[0].gamesPlayed, - label: "Games Played", + label: t.statCellNum.gamesPlayed + .replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 0), _ListEntry( value: widget.rank[0].gamesWon, - label: "Games Won", + label: t.statCellNum.gamesWonTL + .replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 0), _ListEntry( value: widget.rank[0].winrate * 100, - label: "Winrate", + label: t.statCellNum.winrate + .replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 2), _ListEntry( value: widget.rank[0].apm, - label: "Attack per Minute", + label: t.statCellNum.apm + .replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 2), _ListEntry( value: widget.rank[0].pps, - label: "Pieces per Second", + label: t.statCellNum.pps + .replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 2), _ListEntry( value: widget.rank[0].vs, - label: "Versus Score", + label: t.statCellNum.vs + .replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 2), _ListEntry( value: widget.rank[1]["avgAPP"], - label: "Attack Per Piece", + label: t.statCellNum.app + .replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, @@ -675,7 +667,7 @@ class RankState extends State with SingleTickerProviderStateMixin { fractionDigits: 3), _ListEntry( value: widget.rank[1]["avgInfDS"], - label: "InfDS", + label: "Inf. DS", id: "", username: "", approximate: true, @@ -685,7 +677,7 @@ class RankState extends State with SingleTickerProviderStateMixin { ), Column( children: [ - Text("Highest Values", + Text(t.highestValues, style: TextStyle( fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), @@ -694,7 +686,8 @@ class RankState extends State with SingleTickerProviderStateMixin { children: [ _ListEntry( value: widget.rank[1]["highestTR"], - label: "Tetra Rating", + label: t.statCellNum.tr + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestTRid"], username: widget.rank[1]["highestTRnick"], approximate: false, @@ -708,28 +701,32 @@ class RankState extends State with SingleTickerProviderStateMixin { fractionDigits: 2), _ListEntry( value: widget.rank[1]["highestRD"], - label: "Rating Deviation", + label: t.statCellNum.rd + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestRdID"], username: widget.rank[1]["highestRdNick"], approximate: false, fractionDigits: 3), _ListEntry( value: widget.rank[1]["highestGamesPlayed"], - label: "Games Played", + label: t.statCellNum.gamesPlayed + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestGamesPlayedID"], username: widget.rank[1] ["highestGamesPlayedNick"], approximate: false), _ListEntry( value: widget.rank[1]["highestGamesWon"], - label: "Games Won", + label: t.statCellNum.gamesWonTL + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestGamesWonID"], username: widget.rank[1] ["highestGamesWonNick"], approximate: false), _ListEntry( value: widget.rank[1]["highestWinrate"] * 100, - label: "Winrate Percentage", + label: t.statCellNum.winrate + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestWinrateID"], username: widget.rank[1] ["highestWinrateNick"], @@ -737,21 +734,24 @@ class RankState extends State with SingleTickerProviderStateMixin { fractionDigits: 2), _ListEntry( value: widget.rank[1]["highestAPM"], - label: "Attack Per Minute", + label: t.statCellNum.apm + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestAPMid"], username: widget.rank[1]["highestAPMnick"], approximate: false, fractionDigits: 2), _ListEntry( value: widget.rank[1]["highestPPS"], - label: "Pieces Per Second", + label: t.statCellNum.pps + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestPPSid"], username: widget.rank[1]["highestPPSnick"], approximate: false, fractionDigits: 2), _ListEntry( value: widget.rank[1]["highestVS"], - label: "Versus Score", + label: t.statCellNum.vs + .replaceAll(RegExp(r'\n'), " "), id: widget.rank[1]["highestVSid"], username: widget.rank[1]["highestVSnick"], approximate: false, @@ -866,7 +866,7 @@ class RankState extends State with SingleTickerProviderStateMixin { fractionDigits: 3), _ListEntry( value: widget.rank[1]["highestInfDS"], - label: "InfDS", + label: "Inf. DS", id: widget.rank[1]["highestInfDSid"], username: widget.rank[1]["highestInfDSnick"], approximate: false, @@ -883,14 +883,14 @@ class RankState extends State with SingleTickerProviderStateMixin { children: [ _ListEntry( value: widget.rank[1]["totalGamesPlayed"], - label: "Total Games Played", + label: t.statCellNum.totalGames, id: "", username: "", approximate: true, fractionDigits: 0), _ListEntry( value: widget.rank[1]["totalGamesWon"], - label: "Total Games Won", + label: t.statCellNum.totalWon, id: "", username: "", approximate: true, @@ -899,21 +899,13 @@ class RankState extends State with SingleTickerProviderStateMixin { value: (widget.rank[1]["totalGamesWon"] / widget.rank[1]["totalGamesPlayed"]) * 100, - label: "Winrate", + label: t.statCellNum.winrate + .replaceAll(RegExp(r'\n'), " "), id: "", username: "", approximate: true, fractionDigits: 3), - Center( - child: Text("Typical TL profile", - style: TextStyle( - fontFamily: "Eurostile Round Extended", - fontSize: bigScreen ? 42 : 28)), - ), - SizedBox( - height: 800, - child: TLThingy(tl: widget.rank[0], userID: ""), - ) + ] ) ) @@ -952,7 +944,7 @@ class _ListEntry extends StatelessWidget { children: [ Text(f.format(value), style: const TextStyle(fontSize: 22, height: 0.9)), - if (id.isNotEmpty) Text('for player $username') + if (id.isNotEmpty) Text(t.forPlayer(username: username)) ], ), onTap: id.isNotEmpty @@ -1029,10 +1021,10 @@ double takeStat(TetrioPlayerFromLeaderboard entry, String stat) { } } -class MyScatterSpot extends ScatterSpot{ +class _MyScatterSpot extends ScatterSpot{ String id; String nickname; - MyScatterSpot(super.x, super.y, this.id, this.nickname, {super.color}); + _MyScatterSpot(super.x, super.y, this.id, this.nickname, {super.color}); } \ No newline at end of file diff --git a/lib/views/ranks_averages_view.dart b/lib/views/ranks_averages_view.dart index 03d49ec..53d711f 100644 --- a/lib/views/ranks_averages_view.dart +++ b/lib/views/ranks_averages_view.dart @@ -40,7 +40,7 @@ class RanksAverages extends State { List keys = averages.keys.toList(); return ListTile( leading: Image.asset("res/tetrio_tl_alpha_ranks/${keys[index]}.png", height: 48), - title: Text("${averages[keys[index]]?[1]["players"]} players", style: const TextStyle(fontFamily: "Eurostile Round Extended")), + title: Text(t.players(n: averages[keys[index]]?[1]["players"]), style: const TextStyle(fontFamily: "Eurostile Round Extended")), subtitle: Text("${f2.format(averages[keys[index]]?[0].apm)} APM, ${f2.format(averages[keys[index]]?[0].pps)} PPS, ${f2.format(averages[keys[index]]?[0].vs)} VS, ${f2.format(averages[keys[index]]?[0].nerdStats.app)} APP, ${f2.format(averages[keys[index]]?[0].nerdStats.vsapm)} VS/APM"), trailing: Text("${f2.format(averages[keys[index]]?[1]["toEnterTR"])} TR", style: bigScreen ? const TextStyle(fontSize: 28) : null), onTap: (){ diff --git a/lib/views/tl_leaderboard_view.dart b/lib/views/tl_leaderboard_view.dart index 114e3d3..683c93a 100644 --- a/lib/views/tl_leaderboard_view.dart +++ b/lib/views/tl_leaderboard_view.dart @@ -58,7 +58,7 @@ class TLLeaderboardState extends State { numberOfPlayers, zero: t.lbViewZeroEntrys, one: t.lbViewOneEntry, - other: t.lbViewManyEntrys(numberOfPlayers: numberOfPlayers), + other: t.lbViewManyEntrys(numberOfPlayers: t.players(n: numberOfPlayers)), name: 'howManyPeople', args: [numberOfPlayers], desc: 'Description of how many people are seen in a place.', @@ -82,7 +82,7 @@ class TLLeaderboardState extends State { builder: (context) => RankView(rank: snapshot.data!.getAverageOfRank("")), ), ); - }, child: Text("Values for everyone", + }, child: Text(t.everyoneAverages, style: const TextStyle(fontSize: 25))) ],) )), diff --git a/lib/widgets/tl_thingy.dart b/lib/widgets/tl_thingy.dart index 4a80995..cf9e21e 100644 --- a/lib/widgets/tl_thingy.dart +++ b/lib/widgets/tl_thingy.dart @@ -12,7 +12,8 @@ class TLThingy extends StatelessWidget { final TetraLeagueAlpha tl; final String userID; final TetraLeagueAlpha? oldTl; - const TLThingy({Key? key, required this.tl, required this.userID, this.oldTl}) : super(key: key); + final bool showTitle; + const TLThingy({Key? key, required this.tl, required this.userID, this.oldTl, this.showTitle = true}) : super(key: key); @override Widget build(BuildContext context) { @@ -29,7 +30,7 @@ class TLThingy extends StatelessWidget { return Column( children: (tl.gamesPlayed > 0) ? [ - Text(t.tetraLeague, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), + if (showTitle) Text(t.tetraLeague, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), if (oldTl != null) Text(t.comparingWith(date: dateFormat.format(oldTl!.timestamp))), if (tl.gamesPlayed >= 10) Wrap( diff --git a/res/i18n/strings.i18n.json b/res/i18n/strings.i18n.json index 246ea0a..0e6c384 100644 --- a/res/i18n/strings.i18n.json +++ b/res/i18n/strings.i18n.json @@ -101,7 +101,26 @@ "averages": "Averages", "lbViewZeroEntrys": "Empty list. Looks like something is wrong...", "lbViewOneEntry": "There is only one player... What?", - "lbViewManyEntrys": "There are ${numberOfPlayers} ranked players.", + "lbViewManyEntrys": "There are ${numberOfPlayers}.", + "everyoneAverages": "Values for leaderboard", + "rankAverages": "Values for $rank rank", + "players":{ + "zero": "$n players", + "one": "$n player", + "two": "$n players", + "few": "$n players", + "many": "$n players", + "other": "$n players" + }, + "chart": "Chart", + "entries": "Entries", + "minimums": "Minimums", + "maximums": "Maximums", + "lowestValues": "Lowest Values", + "averageValues": "Average Values", + "highestValues": "Highest Values", + "forPlayer": "for player $username", + "currentAxis": "$axis axis:", "p1nkl0bst3rAlert": "That data was retrived from third party API maintained by p1nkl0bst3r", "notForWeb": "Function is not available for web version", "statCellNum":{ @@ -111,6 +130,8 @@ "hoursPlayed": "Hours\nPlayed", "onlineGames": "Online\nGames", "gamesWon": "Games\nWon", + "totalGames": "Total Games Played", + "totalWon": "Total Games Won", "friends": "Friends", "apm": "Attack\nPer Minute", "vs": "Versus\nScore", @@ -133,6 +154,7 @@ "kpp": "KP Per\nPiece", "kps": "KP Per\nSecond", "tr": "Tetra Rating", + "rd": "Rating Deviation", "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", diff --git a/res/i18n/strings_ru.i18n.json b/res/i18n/strings_ru.i18n.json index 1102f1e..70d7942 100644 --- a/res/i18n/strings_ru.i18n.json +++ b/res/i18n/strings_ru.i18n.json @@ -101,7 +101,26 @@ "averages": "Средние значения", "lbViewZeroEntrys": "Рейтинговая таблица пуста. Похоже, что-то здесь не так...", "lbViewOneEntry": "В рейтинговой таблице всего один игрок... Чего?", - "lbViewManyEntrys": "В рейтинговой таблице находится ${numberOfPlayers} игроков.", + "lbViewManyEntrys": "В рейтинговой таблице находится ${numberOfPlayers}.", + "everyoneAverages": "Значения таблицы", + "rankAverages": "Значения для $rank ранга", + "players":{ + "zero": "$n игроков", + "one": "$n игрок", + "two": "$n игрока", + "few": "$n игрока", + "many": "$n игроков", + "other": "$n игроков" + }, + "chart": "График", + "entries": "Список", + "minimums": "Минимумы", + "maximums": "Максимумы", + "lowestValues": "Самые низкие показатели", + "averageValues": "Средние значения показателей", + "highestValues": "Самые высокие показатели", + "forPlayer": "для игрока $username", + "currentAxis": "Ось $axis:", "p1nkl0bst3rAlert": "Эти данные были получены из стороннего API, который поддерживается p1nkl0bst3r", "notForWeb": "Функция недоступна для веб версии", "statCellNum": { @@ -111,6 +130,8 @@ "hoursPlayed": "Часов\nСыграно", "onlineGames": "Онлайн\nИгр", "gamesWon": "Онлайн\nПобед", + "totalGames": "Всего матчей", + "totalWon": "Всего побед", "friends": "Друзей", "apm": "Атака в\nМинуту", "vs": "Показатель\nVersus", @@ -133,6 +154,7 @@ "kpp": "Нажатий\nна Фигуру", "kps": "Нажатий\nв Секунду", "tr": "Тетра Рейтинг", + "rd": "Отклонение рейтинга", "app": "Атака на Фигуру", "appDescription": "(Сокращенно APP) Главный показатель эффективности. Показывает, сколько атаки приходится на одну фигуру", "vsapmDescription": "В основном, показывает как много мусора игрок использует в своих атаках и насколько эффективно.",