Leaderboard sorting + some UI reworks
This commit is contained in:
parent
dbe875150f
commit
2b2b9ff7d5
|
@ -67,6 +67,35 @@ enum Stats {
|
|||
openerMinusInfDS
|
||||
}
|
||||
|
||||
const Map<Stats, String> chartsShortTitles = {
|
||||
Stats.tr: "TR",
|
||||
Stats.glicko: "Glicko",
|
||||
Stats.rd: "RD",
|
||||
Stats.gp: "GP",
|
||||
Stats.gw: "GW",
|
||||
Stats.wr: "WR%",
|
||||
Stats.apm: "APM",
|
||||
Stats.pps: "PPS",
|
||||
Stats.vs: "VS",
|
||||
Stats.app: "APP",
|
||||
Stats.dss: "DS/S",
|
||||
Stats.dsp: "DS/P",
|
||||
Stats.appdsp: "APP + DS/P",
|
||||
Stats.vsapm: "VS/APM",
|
||||
Stats.cheese: "Cheese",
|
||||
Stats.gbe: "GbE",
|
||||
Stats.nyaapp: "wAPP",
|
||||
Stats.area: "Area",
|
||||
Stats.eTR: "eTR",
|
||||
Stats.acceTR: "±eTR",
|
||||
Stats.opener: "Opener",
|
||||
Stats.plonk: "Plonk",
|
||||
Stats.infDS: "Inf. DS",
|
||||
Stats.stride: "Stride",
|
||||
Stats.stridemMinusPlonk: "Stride - Plonk",
|
||||
Stats.openerMinusInfDS: "Opener - Inf. DS"
|
||||
};
|
||||
|
||||
const Map<String, Color> rankColors = { // thanks osk for const rankColors at https://ch.tetr.io/res/js/base.js:418
|
||||
'x': Color(0xFFFF45FF),
|
||||
'u': Color(0xFFFF3813),
|
||||
|
@ -1009,10 +1038,21 @@ class TetrioPlayersLeaderboard {
|
|||
|
||||
TetrioPlayersLeaderboard(this.type, this.leaderboard);
|
||||
|
||||
List<num> getStatRanking(List<TetrioPlayerFromLeaderboard> leaderboard, Stats stat){
|
||||
var lb = leaderboard.map((e) => e.getStatByEnum(stat)).toList();
|
||||
lb.sort();
|
||||
return lb.reversed.toList();
|
||||
List<TetrioPlayerFromLeaderboard> getStatRanking(List<TetrioPlayerFromLeaderboard> leaderboard, Stats stat, {bool reversed = false, String country = ""}){
|
||||
List<TetrioPlayerFromLeaderboard> lb = List.from(leaderboard);
|
||||
if (country.isNotEmpty){
|
||||
lb.removeWhere((element) => element.country != country);
|
||||
}
|
||||
lb.sort(((a, b) {
|
||||
if (a.getStatByEnum(stat) > b.getStatByEnum(stat)){
|
||||
return reversed ? 1 : -1;
|
||||
}else if (a.getStatByEnum(stat) == b.getStatByEnum(stat)){
|
||||
return 0;
|
||||
}else{
|
||||
return reversed ? -1 : 1;
|
||||
}
|
||||
}));
|
||||
return lb;
|
||||
}
|
||||
|
||||
List<dynamic> getAverageOfRank(String rank){ // i tried to refactor it and that's was terrible
|
||||
|
@ -1689,7 +1729,7 @@ class TetrioPlayerFromLeaderboard {
|
|||
username = json['username'];
|
||||
role = json['role'];
|
||||
xp = json['xp'].toDouble();
|
||||
country = json['country '];
|
||||
country = json['country'];
|
||||
supporter = json['supporter'];
|
||||
verified = json['verified'];
|
||||
timestamp = ts;
|
||||
|
@ -1722,7 +1762,7 @@ class TetrioPlayerFromLeaderboard {
|
|||
case Stats.gw:
|
||||
return gamesWon;
|
||||
case Stats.wr:
|
||||
return winrate;
|
||||
return winrate*100;
|
||||
case Stats.apm:
|
||||
return apm;
|
||||
case Stats.pps:
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
/// To regenerate, run: `dart run slang`
|
||||
///
|
||||
/// Locales: 2
|
||||
/// Strings: 898 (449 per locale)
|
||||
/// Strings: 906 (453 per locale)
|
||||
///
|
||||
/// Built on 2023-08-21 at 09:52 UTC
|
||||
/// Built on 2023-09-02 at 21:37 UTC
|
||||
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
|
@ -251,10 +251,13 @@ class _StringsEn implements BaseTranslations<AppLocale, _StringsEn> {
|
|||
String get calcViewNoValues => 'Enter values to calculate the stats';
|
||||
String get rankAveragesViewTitle => 'Ranks cutoff and average stats';
|
||||
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}.';
|
||||
String get lbViewZeroEntrys => 'Empty list';
|
||||
String get lbViewOneEntry => 'There is only one player';
|
||||
String lbViewManyEntrys({required Object numberOfPlayers}) => 'There are ${numberOfPlayers}';
|
||||
String get everyoneAverages => 'Values for leaderboard';
|
||||
String get sortBy => 'Sort by';
|
||||
String get reversed => 'Reversed';
|
||||
String get country => 'Country';
|
||||
String rankAverages({required Object rank}) => 'Values for ${rank} rank';
|
||||
String players({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('en'))(n,
|
||||
zero: '${n} players',
|
||||
|
@ -290,6 +293,7 @@ class _StringsEn implements BaseTranslations<AppLocale, _StringsEn> {
|
|||
late final _StringsPopupActionsEn popupActions = _StringsPopupActionsEn._(_root);
|
||||
late final _StringsErrorsEn errors = _StringsErrorsEn._(_root);
|
||||
Map<String, String> get countries => {
|
||||
'': 'Not selected',
|
||||
'AF': 'Afghanistan',
|
||||
'AX': 'Åland Islands',
|
||||
'AL': 'Albania',
|
||||
|
@ -775,10 +779,13 @@ class _StringsRu implements _StringsEn {
|
|||
@override String get calcViewNoValues => 'Введите значения, чтобы посчитать статистику';
|
||||
@override String get rankAveragesViewTitle => 'Требования рангов и средние значения';
|
||||
@override String get averages => 'Средние значения';
|
||||
@override String get lbViewZeroEntrys => 'Рейтинговая таблица пуста. Похоже, что-то здесь не так...';
|
||||
@override String get lbViewOneEntry => 'В рейтинговой таблице всего один игрок... Чего?';
|
||||
@override String lbViewManyEntrys({required Object numberOfPlayers}) => 'В рейтинговой таблице находится ${numberOfPlayers}.';
|
||||
@override String get lbViewZeroEntrys => 'Рейтинговая таблица пуста';
|
||||
@override String get lbViewOneEntry => 'В рейтинговой таблице всего один игрок';
|
||||
@override String lbViewManyEntrys({required Object numberOfPlayers}) => 'В рейтинговой таблице находится ${numberOfPlayers}';
|
||||
@override String get everyoneAverages => 'Значения таблицы';
|
||||
@override String get sortBy => 'Cортировать по';
|
||||
@override String get reversed => 'Наоборот';
|
||||
@override String get country => 'Страна';
|
||||
@override String rankAverages({required Object rank}) => 'Значения для ${rank} ранга';
|
||||
@override String players({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n,
|
||||
zero: '${n} игроков',
|
||||
|
@ -814,6 +821,7 @@ class _StringsRu implements _StringsEn {
|
|||
@override late final _StringsPopupActionsRu popupActions = _StringsPopupActionsRu._(_root);
|
||||
@override late final _StringsErrorsRu errors = _StringsErrorsRu._(_root);
|
||||
@override Map<String, String> get countries => {
|
||||
'': 'Не выбрана',
|
||||
'AF': 'Афганистан',
|
||||
'AX': 'Аландские острова',
|
||||
'AL': 'Албания',
|
||||
|
@ -1278,10 +1286,13 @@ extension on _StringsEn {
|
|||
case 'calcViewNoValues': return 'Enter values to calculate the stats';
|
||||
case 'rankAveragesViewTitle': return 'Ranks cutoff and average stats';
|
||||
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}.';
|
||||
case 'lbViewZeroEntrys': return 'Empty list';
|
||||
case 'lbViewOneEntry': return 'There is only one player';
|
||||
case 'lbViewManyEntrys': return ({required Object numberOfPlayers}) => 'There are ${numberOfPlayers}';
|
||||
case 'everyoneAverages': return 'Values for leaderboard';
|
||||
case 'sortBy': return 'Sort by';
|
||||
case 'reversed': return 'Reversed';
|
||||
case 'country': return 'Country';
|
||||
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',
|
||||
|
@ -1372,6 +1383,7 @@ extension on _StringsEn {
|
|||
case 'errors.connection': return ({required Object code, required Object message}) => 'Some issue with connection: ${code} ${message}';
|
||||
case 'errors.noSuchUser': return 'No such user';
|
||||
case 'errors.socketException': return ({required Object host, required Object message}) => 'Can\'t connect with ${host}: ${message}';
|
||||
case 'countries.': return 'Not selected';
|
||||
case 'countries.AF': return 'Afghanistan';
|
||||
case 'countries.AX': return 'Åland Islands';
|
||||
case 'countries.AL': return 'Albania';
|
||||
|
@ -1737,10 +1749,13 @@ extension on _StringsRu {
|
|||
case 'calcViewNoValues': return 'Введите значения, чтобы посчитать статистику';
|
||||
case 'rankAveragesViewTitle': return 'Требования рангов и средние значения';
|
||||
case 'averages': return 'Средние значения';
|
||||
case 'lbViewZeroEntrys': return 'Рейтинговая таблица пуста. Похоже, что-то здесь не так...';
|
||||
case 'lbViewOneEntry': return 'В рейтинговой таблице всего один игрок... Чего?';
|
||||
case 'lbViewManyEntrys': return ({required Object numberOfPlayers}) => 'В рейтинговой таблице находится ${numberOfPlayers}.';
|
||||
case 'lbViewZeroEntrys': return 'Рейтинговая таблица пуста';
|
||||
case 'lbViewOneEntry': return 'В рейтинговой таблице всего один игрок';
|
||||
case 'lbViewManyEntrys': return ({required Object numberOfPlayers}) => 'В рейтинговой таблице находится ${numberOfPlayers}';
|
||||
case 'everyoneAverages': return 'Значения таблицы';
|
||||
case 'sortBy': return 'Cортировать по';
|
||||
case 'reversed': return 'Наоборот';
|
||||
case 'country': return 'Страна';
|
||||
case 'rankAverages': return ({required Object rank}) => 'Значения для ${rank} ранга';
|
||||
case 'players': return ({required num n}) => (_root.$meta.cardinalResolver ?? PluralResolvers.cardinal('ru'))(n,
|
||||
zero: '${n} игроков',
|
||||
|
@ -1831,6 +1846,7 @@ extension on _StringsRu {
|
|||
case 'errors.connection': return ({required Object code, required Object message}) => 'Проблема с подключением: ${code} ${message}';
|
||||
case 'errors.noSuchUser': return 'Нет такого пользователя';
|
||||
case 'errors.socketException': return ({required Object host, required Object message}) => 'Невозможно подключиться к ${host}: ${message}';
|
||||
case 'countries.': return 'Не выбрана';
|
||||
case 'countries.AF': return 'Афганистан';
|
||||
case 'countries.AX': return 'Аландские острова';
|
||||
case 'countries.AL': return 'Албания';
|
||||
|
|
|
@ -10,6 +10,7 @@ double? vs;
|
|||
NerdStats? nerdStats;
|
||||
EstTr? estTr;
|
||||
Playstyle? playstyle;
|
||||
final NumberFormat f2 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 2);
|
||||
|
||||
class CalcView extends StatefulWidget {
|
||||
const CalcView({Key? key}) : super(key: key);
|
||||
|
@ -129,10 +130,10 @@ class CalcState extends State<CalcView> {
|
|||
clipBehavior: Clip.hardEdge,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 48),
|
||||
padding: const EdgeInsets.fromLTRB(18, 0, 18, 44),
|
||||
child: SizedBox(
|
||||
height: 300,
|
||||
width: 300,
|
||||
height: 310,
|
||||
width: 310,
|
||||
child: RadarChart(
|
||||
RadarChartData(
|
||||
radarShape: RadarShape.polygon,
|
||||
|
@ -154,21 +155,21 @@ class CalcState extends State<CalcView> {
|
|||
angle: angle,
|
||||
);
|
||||
case 2:
|
||||
return RadarChartTitle(text: 'VS', angle: angle);
|
||||
return RadarChartTitle(text: 'VS', angle: angle, positionPercentageOffset: 0.05);
|
||||
case 3:
|
||||
return RadarChartTitle(text: 'APP', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'APP', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 4:
|
||||
return RadarChartTitle(text: 'DS/S', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'DS/S', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 5:
|
||||
return RadarChartTitle(text: 'DS/P', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'DS/P', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 6:
|
||||
return RadarChartTitle(text: 'APP+DS/P', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'APP+DS/P', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 7:
|
||||
return RadarChartTitle(text: 'VS/APM', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'VS/APM', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 8:
|
||||
return RadarChartTitle(text: 'Cheese', angle: angle);
|
||||
return RadarChartTitle(text: 'Cheese', angle: angle, positionPercentageOffset: 0.05);
|
||||
case 9:
|
||||
return RadarChartTitle(text: 'Gb Eff.', angle: angle);
|
||||
return RadarChartTitle(text: 'Gb Eff.', angle: angle, positionPercentageOffset: 0.05);
|
||||
default:
|
||||
return const RadarChartTitle(text: '');
|
||||
}
|
||||
|
@ -212,34 +213,30 @@ class CalcState extends State<CalcView> {
|
|||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 48),
|
||||
padding: const EdgeInsets.fromLTRB(18, 0, 18, 44),
|
||||
child: SizedBox(
|
||||
height: 300,
|
||||
width: 300,
|
||||
height: 310,
|
||||
width: 310,
|
||||
child: RadarChart(
|
||||
RadarChartData(
|
||||
radarShape: RadarShape.polygon,
|
||||
tickCount: 4,
|
||||
ticksTextStyle: const TextStyle(color: Colors.transparent, fontSize: 10),
|
||||
ticksTextStyle: const TextStyle(color: Colors.white24, fontSize: 10),
|
||||
radarBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
gridBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
tickBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
titleTextStyle: const TextStyle(height: 1.1),
|
||||
radarTouchData: RadarTouchData(),
|
||||
getTitle: (index, angle) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return RadarChartTitle(
|
||||
text: 'Opener',
|
||||
angle: angle,
|
||||
);
|
||||
return RadarChartTitle(text: 'Opener\n${f2.format(playstyle!.opener)}', angle: 0, positionPercentageOffset: 0.05);
|
||||
case 1:
|
||||
return RadarChartTitle(
|
||||
text: 'Stride',
|
||||
angle: angle,
|
||||
);
|
||||
return RadarChartTitle(text: 'Stride\n${f2.format(playstyle!.stride)}', angle: 0, positionPercentageOffset: 0.05);
|
||||
case 2:
|
||||
return RadarChartTitle(text: 'Inf Ds', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'Inf Ds\n${f2.format(playstyle!.infds)}', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 3:
|
||||
return RadarChartTitle(text: 'Plonk', angle: angle);
|
||||
return RadarChartTitle(text: 'Plonk\n${f2.format(playstyle!.plonk)}', angle: 0, positionPercentageOffset: 0.05);
|
||||
default:
|
||||
return const RadarChartTitle(text: '');
|
||||
}
|
||||
|
|
|
@ -620,49 +620,51 @@ class CompareState extends State<CompareView> {
|
|||
clipBehavior: Clip.hardEdge,
|
||||
children: [
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.fromLTRB(20, 20, 20, 20),
|
||||
child: SizedBox(
|
||||
height: 300,
|
||||
width: 300,
|
||||
child: RadarChart(
|
||||
RadarChartData(
|
||||
radarShape: RadarShape.polygon,
|
||||
tickCount: 4,
|
||||
ticksTextStyle: const TextStyle(
|
||||
color: Colors.transparent,
|
||||
fontSize: 10),
|
||||
radarBorderData: const BorderSide(
|
||||
color: Colors.transparent, width: 1),
|
||||
gridBorderData: const BorderSide(
|
||||
color: Colors.white24, width: 1),
|
||||
tickBorderData: const BorderSide(
|
||||
color: Colors.transparent, width: 1),
|
||||
getTitle: (index, angle) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return RadarChartTitle(text: 'APM', angle: angle);
|
||||
case 1:
|
||||
return RadarChartTitle(text: 'PPS', angle: angle);
|
||||
case 2:
|
||||
return RadarChartTitle(text: 'VS', angle: angle);
|
||||
case 3:
|
||||
return RadarChartTitle(text: 'APP', angle: angle + 180);
|
||||
case 4:
|
||||
return RadarChartTitle(text: 'DS/S', angle: angle + 180);
|
||||
case 5:
|
||||
return RadarChartTitle(text: 'DS/P', angle: angle + 180);
|
||||
case 6:
|
||||
return RadarChartTitle(text: 'APP+DS/P', angle: angle + 180);
|
||||
case 7:
|
||||
return RadarChartTitle(text: 'VS/APM', angle: angle + 180);
|
||||
case 8:
|
||||
return RadarChartTitle(text: 'Cheese', angle: angle);
|
||||
case 9:
|
||||
return RadarChartTitle(text: 'Gb Eff.', angle: angle);
|
||||
default:
|
||||
return const RadarChartTitle(text: '');
|
||||
}
|
||||
padding: const EdgeInsets.fromLTRB(18, 0, 18, 44),
|
||||
child: SizedBox(
|
||||
height: 310,
|
||||
width: 310,
|
||||
child: RadarChart(
|
||||
RadarChartData(
|
||||
radarShape: RadarShape.polygon,
|
||||
tickCount: 4,
|
||||
ticksTextStyle: const TextStyle(color: Colors.transparent, fontSize: 10),
|
||||
radarBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
gridBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
tickBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
getTitle: (index, angle) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return RadarChartTitle(
|
||||
text: 'APM',
|
||||
angle: angle,
|
||||
positionPercentageOffset: 0.05
|
||||
);
|
||||
case 1:
|
||||
return RadarChartTitle(
|
||||
text: 'PPS',
|
||||
angle: angle,
|
||||
positionPercentageOffset: 0.05
|
||||
);
|
||||
case 2:
|
||||
return RadarChartTitle(text: 'VS', angle: angle, positionPercentageOffset: 0.05);
|
||||
case 3:
|
||||
return RadarChartTitle(text: 'APP', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 4:
|
||||
return RadarChartTitle(text: 'DS/S', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 5:
|
||||
return RadarChartTitle(text: 'DS/P', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 6:
|
||||
return RadarChartTitle(text: 'APP+DS/P', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 7:
|
||||
return RadarChartTitle(text: 'VS/APM', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 8:
|
||||
return RadarChartTitle(text: 'Cheese', angle: angle, positionPercentageOffset: 0.05);
|
||||
case 9:
|
||||
return RadarChartTitle(text: 'Gb Eff.', angle: angle, positionPercentageOffset: 0.05);
|
||||
default:
|
||||
return const RadarChartTitle(text: '');
|
||||
}
|
||||
},
|
||||
dataSets: [
|
||||
RadarDataSet(
|
||||
|
@ -721,34 +723,30 @@ class CompareState extends State<CompareView> {
|
|||
),
|
||||
),
|
||||
Padding(
|
||||
padding:
|
||||
const EdgeInsets.fromLTRB(20, 20, 20, 20),
|
||||
child: SizedBox(
|
||||
height: 300,
|
||||
width: 300,
|
||||
child: RadarChart(
|
||||
RadarChartData(
|
||||
radarShape: RadarShape.polygon,
|
||||
tickCount: 4,
|
||||
ticksTextStyle: const TextStyle(
|
||||
color: Colors.transparent,
|
||||
fontSize: 10),
|
||||
radarBorderData: const BorderSide(
|
||||
color: Colors.transparent, width: 1),
|
||||
gridBorderData: const BorderSide(
|
||||
color: Colors.white24, width: 1),
|
||||
tickBorderData: const BorderSide(
|
||||
color: Colors.transparent, width: 1),
|
||||
padding: const EdgeInsets.fromLTRB(18, 0, 18, 44),
|
||||
child: SizedBox(
|
||||
height: 310,
|
||||
width: 310,
|
||||
child: RadarChart(
|
||||
RadarChartData(
|
||||
radarShape: RadarShape.polygon,
|
||||
tickCount: 4,
|
||||
ticksTextStyle: const TextStyle(color: Colors.white24, fontSize: 10),
|
||||
radarBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
gridBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
tickBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
titleTextStyle: const TextStyle(height: 1.1),
|
||||
radarTouchData: RadarTouchData(),
|
||||
getTitle: (index, angle) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return RadarChartTitle(text: 'Opener',angle: angle);
|
||||
return RadarChartTitle(text: 'Opener',angle: angle, positionPercentageOffset: 0.05);
|
||||
case 1:
|
||||
return RadarChartTitle(text: 'Stride', angle: angle);
|
||||
return RadarChartTitle(text: 'Stride', angle: angle, positionPercentageOffset: 0.05);
|
||||
case 2:
|
||||
return RadarChartTitle(text: 'Inf Ds', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'Inf Ds', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 3:
|
||||
return RadarChartTitle(text: 'Plonk', angle: angle);
|
||||
return RadarChartTitle(text: 'Plonk', angle: angle, positionPercentageOffset: 0.05);
|
||||
default:
|
||||
return const RadarChartTitle(text: '');
|
||||
}
|
||||
|
@ -849,7 +847,7 @@ class CompareState extends State<CompareView> {
|
|||
)
|
||||
],
|
||||
)
|
||||
] : [Text(t.compareViewNoValues(avgR: "\$avdR"))], // This is so fucked up holy shit
|
||||
] : [Text(t.compareViewNoValues(avgR: "\$avgR"))], // This is so fucked up holy shit
|
||||
)
|
||||
),
|
||||
),
|
||||
|
|
|
@ -23,7 +23,7 @@ String _titleNickname = "dan63047";
|
|||
final TetrioService teto = TetrioService();
|
||||
late SharedPreferences prefs;
|
||||
var chartsData = <DropdownMenuItem<List<FlSpot>>>[];
|
||||
List chartsShortTitles = ["TR", "Glicko", "RD", "APM", "PPS", "VS", "APP", "DS/S", "DS/P", "APP + DS/P", "VS/APM", "Cheese", "GbE", "wAPP", "Area", "eTR", "±eTR"];
|
||||
List historyShortTitles = ["TR", "Glicko", "RD", "APM", "PPS", "VS", "APP", "DS/S", "DS/P", "APP + DS/P", "VS/APM", "Cheese", "GbE", "wAPP", "Area", "eTR", "±eTR"];
|
||||
int chartsIndex = 0;
|
||||
const allowedHeightForPlayerIdInPixels = 40.0;
|
||||
const allowedHeightForPlayerBioInPixels = 30.0;
|
||||
|
@ -508,12 +508,18 @@ class _TLRecords extends StatelessWidget {
|
|||
fontSize: 28,)),
|
||||
title: Text("vs. ${value.endContext.firstWhere((element) => element.userId != userID).username}"),
|
||||
subtitle: Text(dateFormat.format(value.timestamp)),
|
||||
trailing: Column(mainAxisAlignment: MainAxisAlignment.center,
|
||||
trailing: Table(defaultColumnWidth: IntrinsicColumnWidth(),
|
||||
defaultVerticalAlignment: TableCellVerticalAlignment.baseline,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
columnWidths: {
|
||||
0: FixedColumnWidth(50),
|
||||
2: FixedColumnWidth(50),
|
||||
},
|
||||
children: [
|
||||
Text("${f2.format(value.endContext.firstWhere((element) => element.userId == userID).secondary)} : ${f2.format(value.endContext.firstWhere((element) => element.userId != userID).secondary)} APM", style: const TextStyle(height: 1.1)),
|
||||
Text("${f2.format(value.endContext.firstWhere((element) => element.userId == userID).tertiary)} : ${f2.format(value.endContext.firstWhere((element) => element.userId != userID).tertiary)} PPS", style: const TextStyle(height: 1.1)),
|
||||
Text("${f2.format(value.endContext.firstWhere((element) => element.userId == userID).extra)} : ${f2.format(value.endContext.firstWhere((element) => element.userId != userID).extra)} VS", style: const TextStyle(height: 1.1)),
|
||||
]),
|
||||
TableRow(children: [Text(f2.format(value.endContext.firstWhere((element) => element.userId == userID).secondary), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" :", style: const TextStyle(height: 1.1)), Text(f2.format(value.endContext.firstWhere((element) => element.userId != userID).secondary), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" APM", textAlign: TextAlign.right, style: const TextStyle(height: 1.1))]),
|
||||
TableRow(children: [Text(f2.format(value.endContext.firstWhere((element) => element.userId == userID).tertiary), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" :", style: const TextStyle(height: 1.1)), Text(f2.format(value.endContext.firstWhere((element) => element.userId != userID).tertiary), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" PPS", textAlign: TextAlign.right, style: const TextStyle(height: 1.1))]),
|
||||
TableRow(children: [Text(f2.format(value.endContext.firstWhere((element) => element.userId == userID).extra), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" :", style: const TextStyle(height: 1.1)), Text(f2.format(value.endContext.firstWhere((element) => element.userId != userID).extra), textAlign: TextAlign.right, style: const TextStyle(height: 1.1)), const Text(" VS", textAlign: TextAlign.right, style: const TextStyle(height: 1.1))]),
|
||||
],),
|
||||
onTap: (){Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
|
@ -546,7 +552,7 @@ class _History extends StatelessWidget{
|
|||
update();
|
||||
}
|
||||
),
|
||||
if(chartsData[chartsIndex].value!.length > 1) _HistoryChartThigy(data: chartsData[chartsIndex].value!, title: "ss", yAxisTitle: chartsShortTitles[chartsIndex], bigScreen: bigScreen, leftSpace: bigScreen? 80 : 45, yFormat: bigScreen? f2 : NumberFormat.compact(),)
|
||||
if(chartsData[chartsIndex].value!.length > 1) _HistoryChartThigy(data: chartsData[chartsIndex].value!, title: "ss", yAxisTitle: historyShortTitles[chartsIndex], bigScreen: bigScreen, leftSpace: bigScreen? 80 : 45, yFormat: bigScreen? f2 : NumberFormat.compact(),)
|
||||
else Center(child: Text(t.notEnoughData, style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)))
|
||||
],
|
||||
),
|
||||
|
|
|
@ -6,39 +6,9 @@ import 'package:tetra_stats/data_objects/tetrio.dart';
|
|||
import 'package:tetra_stats/gen/strings.g.dart';
|
||||
import 'package:tetra_stats/views/main_view.dart' show MainView, f4, f2;
|
||||
|
||||
const List chartsShortTitles = [
|
||||
"TR",
|
||||
"Glicko",
|
||||
"RD",
|
||||
"GP",
|
||||
"GW",
|
||||
"WR%",
|
||||
"APM",
|
||||
"PPS",
|
||||
"VS",
|
||||
"APP",
|
||||
"DS/S",
|
||||
"DS/P",
|
||||
"APP + DS/P",
|
||||
"VS/APM",
|
||||
"Cheese",
|
||||
"GbE",
|
||||
"wAPP",
|
||||
"Area",
|
||||
"eTR",
|
||||
"±eTR",
|
||||
"Opener",
|
||||
"Plonk",
|
||||
"Inf. DS",
|
||||
"Stride",
|
||||
"Stride - Plonk",
|
||||
"Opener - Inf. DS"
|
||||
];
|
||||
var chartsShortTitlesDropdowns = <DropdownMenuItem>[for (String e in chartsShortTitles) DropdownMenuItem(value: e,child: Text(e),)];
|
||||
int chartsIndexX = 0;
|
||||
int chartsIndexY = 6;
|
||||
//final DateFormat dateFormat = DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).add_Hms();
|
||||
double pfpHeight = 128;
|
||||
var chartsShortTitlesDropdowns = <DropdownMenuItem>[for (MapEntry e in chartsShortTitles.entries) DropdownMenuItem(value: e.key, child: Text(e.value),)];
|
||||
Stats chartsX = Stats.tr;
|
||||
Stats chartsY = Stats.apm;
|
||||
|
||||
class RankView extends StatefulWidget {
|
||||
final List rank;
|
||||
|
@ -154,9 +124,9 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
|
|||
child: Text(t.currentAxis(axis: "X"), style: const TextStyle(fontSize: 22))),
|
||||
DropdownButton(
|
||||
items: chartsShortTitlesDropdowns,
|
||||
value: chartsShortTitlesDropdowns[chartsIndexX].value,
|
||||
value: chartsX,
|
||||
onChanged: (value) {
|
||||
chartsIndexX = chartsShortTitlesDropdowns.indexWhere((element) => element.value == value);
|
||||
chartsX = value;
|
||||
_justUpdate();
|
||||
}
|
||||
),
|
||||
|
@ -174,9 +144,9 @@ class RankState extends State<RankView> with SingleTickerProviderStateMixin {
|
|||
),
|
||||
DropdownButton(
|
||||
items: chartsShortTitlesDropdowns,
|
||||
value: chartsShortTitlesDropdowns[chartsIndexY].value,
|
||||
value: chartsY,
|
||||
onChanged: (value) {
|
||||
chartsIndexY = chartsShortTitlesDropdowns.indexWhere((element) => element.value == value);
|
||||
chartsY = value;
|
||||
_justUpdate();
|
||||
}
|
||||
),
|
||||
|
@ -195,11 +165,11 @@ class RankState extends State<RankView> 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(entry.getStatByEnum(chartsX) as double, entry.getStatByEnum(chartsY) as double, entry.userId, entry.username, color: rankColors[entry.rank])],
|
||||
scatterTouchData: ScatterTouchData(touchTooltipData: ScatterTouchTooltipData(
|
||||
fitInsideHorizontally: true, fitInsideVertically: true, getTooltipItems: (touchedSpot) {
|
||||
touchedSpot as _MyScatterSpot;
|
||||
return ScatterTooltipItem("${touchedSpot.nickname}\n", textStyle: const TextStyle(fontFamily: "Eurostile Round Extended"), children: [TextSpan(text: "${f4.format(touchedSpot.x)} ${chartsShortTitles[chartsIndexX]}\n${f4.format(touchedSpot.y)} ${chartsShortTitles[chartsIndexY]}", style: const TextStyle(fontFamily: "Eurostile Round"))]);
|
||||
return ScatterTooltipItem("${touchedSpot.nickname}\n", textStyle: const TextStyle(fontFamily: "Eurostile Round Extended"), children: [TextSpan(text: "${f4.format(touchedSpot.x)} ${chartsShortTitles[chartsX]}\n${f4.format(touchedSpot.y)} ${chartsShortTitles[chartsY]}", style: const TextStyle(fontFamily: "Eurostile Round"))]);
|
||||
}),
|
||||
touchCallback:(event, response) {
|
||||
if (event.runtimeType == FlTapDownEvent && response?.touchedSpot?.spot != null){
|
||||
|
@ -956,66 +926,6 @@ class _ListEntry extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
|
||||
double takeStat(TetrioPlayerFromLeaderboard entry, String stat) {
|
||||
switch (stat) {
|
||||
case "TR":
|
||||
return entry.rating;
|
||||
case "Glicko":
|
||||
return entry.glicko;
|
||||
case "RD":
|
||||
return entry.rd;
|
||||
case "GP":
|
||||
return entry.gamesPlayed.toDouble();
|
||||
case "GW":
|
||||
return entry.gamesWon.toDouble();
|
||||
case "WR%":
|
||||
return entry.winrate*100;
|
||||
case "APM":
|
||||
return entry.apm;
|
||||
case "PPS":
|
||||
return entry.pps;
|
||||
case "VS":
|
||||
return entry.vs;
|
||||
case "APP":
|
||||
return entry.nerdStats.app;
|
||||
case "DS/S":
|
||||
return entry.nerdStats.dss;
|
||||
case "DS/P":
|
||||
return entry.nerdStats.dsp;
|
||||
case "APP + DS/P":
|
||||
return entry.nerdStats.appdsp;
|
||||
case "VS/APM":
|
||||
return entry.nerdStats.vsapm;
|
||||
case "Cheese":
|
||||
return entry.nerdStats.cheese;
|
||||
case "GbE":
|
||||
return entry.nerdStats.gbe;
|
||||
case "wAPP":
|
||||
return entry.nerdStats.nyaapp;
|
||||
case "Area":
|
||||
return entry.nerdStats.area;
|
||||
case "eTR":
|
||||
return entry.estTr.esttr;
|
||||
case "±eTR":
|
||||
return entry.esttracc;
|
||||
case "Opener":
|
||||
return entry.playstyle.opener;
|
||||
case "Plonk":
|
||||
return entry.playstyle.plonk;
|
||||
case "Inf. DS":
|
||||
return entry.playstyle.infds;
|
||||
case "Stride":
|
||||
return entry.playstyle.stride;
|
||||
case "Stride - Plonk":
|
||||
return entry.playstyle.stride - entry.playstyle.plonk;
|
||||
case "Opener - Inf. DS":
|
||||
return entry.playstyle.opener - entry.playstyle.infds;
|
||||
default:
|
||||
throw ArgumentError.value(stat, "Incorrect stat", "We don't have that stat");
|
||||
}
|
||||
}
|
||||
|
||||
class _MyScatterSpot extends ScatterSpot{
|
||||
String id;
|
||||
String nickname;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
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/main_view.dart';
|
||||
|
@ -7,6 +8,11 @@ import 'package:tetra_stats/views/rank_averages_view.dart';
|
|||
import 'package:tetra_stats/views/ranks_averages_view.dart';
|
||||
|
||||
final TetrioService teto = TetrioService();
|
||||
List<DropdownMenuItem> itemStats = [for (MapEntry e in chartsShortTitles.entries) DropdownMenuItem(value: e.key, child: Text(e.value))];
|
||||
Stats sortBy = Stats.tr;
|
||||
bool reversed = false;
|
||||
List<DropdownMenuItem> itemCountries = [for (MapEntry e in t.countries.entries) DropdownMenuItem(value: e.key, child: Text(e.value))];
|
||||
String country = "";
|
||||
|
||||
class TLLeaderboardView extends StatefulWidget {
|
||||
const TLLeaderboardView({Key? key}) : super(key: key);
|
||||
|
@ -51,7 +57,7 @@ class TLLeaderboardState extends State<TLLeaderboardView> {
|
|||
case ConnectionState.active:
|
||||
return const Center(child: Text('Fetching...'));
|
||||
case ConnectionState.done:
|
||||
final allPlayers = snapshot.data?.leaderboard;
|
||||
final allPlayers = snapshot.data?.getStatRanking(snapshot.data!.leaderboard, sortBy, reversed: reversed, country: country);
|
||||
return NestedScrollView(
|
||||
headerSliverBuilder: (context, value) {
|
||||
String howManyPlayers(int numberOfPlayers) => Intl.plural(
|
||||
|
@ -87,6 +93,61 @@ class TLLeaderboardState extends State<TLLeaderboardView> {
|
|||
style: const TextStyle(fontSize: 25)))
|
||||
],)
|
||||
)),
|
||||
SliverToBoxAdapter(child: Padding(
|
||||
padding: const EdgeInsets.only(left: 16),
|
||||
child: Wrap(
|
||||
direction: Axis.horizontal,
|
||||
alignment: WrapAlignment.start,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
spacing: 16,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
children: [
|
||||
Text("${t.sortBy}: ",
|
||||
style: const TextStyle(color: Colors.white, fontSize: 25)),
|
||||
DropdownButton(items: itemStats, value: sortBy, onChanged: ((value) {
|
||||
sortBy = value;
|
||||
setState(() {});
|
||||
}),),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
children: [
|
||||
Text("${t.reversed}: ",
|
||||
style: const TextStyle(color: Colors.white, fontSize: 25)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0, 5.5, 0, 7.5),
|
||||
child: Checkbox(value: reversed,
|
||||
checkColor: Colors.black,
|
||||
onChanged: ((value) {
|
||||
reversed = value!;
|
||||
setState(() {});
|
||||
}),),
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
children: [
|
||||
Text("${t.country}: ",
|
||||
style: const TextStyle(color: Colors.white, fontSize: 25)),
|
||||
DropdownButton(items: itemCountries, value: country, onChanged: ((value) {
|
||||
country = value;
|
||||
setState(() {});
|
||||
}),),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),),
|
||||
const SliverToBoxAdapter(child: Divider())
|
||||
];
|
||||
},
|
||||
|
@ -98,7 +159,7 @@ class TLLeaderboardState extends State<TLLeaderboardView> {
|
|||
leading: Text((index+1).toString(), style: bigScreen ? const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28) : null),
|
||||
title: Text(allPlayers[index].username, style: const TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||
subtitle: Text(
|
||||
"${f2.format(allPlayers[index].apm)} APM, ${f2.format(allPlayers[index].pps)} PPS, ${f2.format(allPlayers[index].vs)} VS, ${f2.format(allPlayers[index].nerdStats.app)} APP, ${f2.format(allPlayers[index].nerdStats.vsapm)} VS/APM"),
|
||||
sortBy == Stats.tr ? "${f2.format(allPlayers[index].apm)} APM, ${f2.format(allPlayers[index].pps)} PPS, ${f2.format(allPlayers[index].vs)} VS, ${f2.format(allPlayers[index].nerdStats.app)} APP, ${f2.format(allPlayers[index].nerdStats.vsapm)} VS/APM" : "${f4.format(allPlayers[index].getStatByEnum(sortBy))} ${chartsShortTitles[sortBy]}"),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
|
|
|
@ -69,7 +69,8 @@ class TLThingy extends StatelessWidget {
|
|||
maximum: tl.prevAt.toDouble(),
|
||||
interval: tl.prevAt.toDouble() - tl.nextAt.toDouble(),
|
||||
ranges: [LinearGaugeRange(startValue: tl.standing.toDouble() <= tl.prevAt.toDouble() ? tl.standing.toDouble() : tl.prevAt.toDouble(), endValue: tl.prevAt.toDouble(), color: Colors.cyanAccent,)],
|
||||
//barPointers: [LinearBarPointer(value: 80)],
|
||||
markerPointers: [LinearShapePointer(value: tl.standing.toDouble() <= tl.prevAt.toDouble() ? tl.standing.toDouble() : tl.prevAt.toDouble(), position: LinearElementPosition.inside, shapeType: LinearShapePointerType.triangle, color: Colors.white, height: 20),
|
||||
LinearWidgetPointer(offset: 4, position: LinearElementPosition.outside, value: tl.standing.toDouble() <= tl.prevAt.toDouble() ? tl.standing.toDouble() : tl.prevAt.toDouble(), child: Text(NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 0).format(tl.standing)))],
|
||||
isAxisInversed: true,
|
||||
isMirrored: true,
|
||||
showTicks: true,
|
||||
|
@ -97,7 +98,6 @@ class TLThingy extends StatelessWidget {
|
|||
if (tl.apm != null) StatCellNum(playerStat: tl.apm!, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.apm, higherIsBetter: true, oldPlayerStat: oldTl?.apm),
|
||||
if (tl.pps != null) StatCellNum(playerStat: tl.pps!, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.pps, higherIsBetter: true, oldPlayerStat: oldTl?.pps),
|
||||
if (tl.vs != null) StatCellNum(playerStat: tl.vs!, isScreenBig: bigScreen, fractionDigits: 2, playerStatLabel: t.statCellNum.vs, higherIsBetter: true, oldPlayerStat: oldTl?.vs),
|
||||
if (tl.standing > 0) StatCellNum(playerStat: tl.standing, isScreenBig: bigScreen, playerStatLabel: t.statCellNum.lbp, higherIsBetter: false, oldPlayerStat: oldTl?.standing),
|
||||
if (tl.standingLocal > 0) StatCellNum(playerStat: tl.standingLocal, isScreenBig: bigScreen, playerStatLabel: t.statCellNum.lbpc, higherIsBetter: false, oldPlayerStat: oldTl?.standingLocal),
|
||||
StatCellNum(playerStat: tl.gamesPlayed, isScreenBig: bigScreen, playerStatLabel: t.statCellNum.gamesPlayed, higherIsBetter: true, oldPlayerStat: oldTl?.gamesPlayed),
|
||||
StatCellNum(playerStat: tl.gamesWon, isScreenBig: bigScreen, playerStatLabel: t.statCellNum.gamesWonTL, higherIsBetter: true, oldPlayerStat: oldTl?.gamesWon),
|
||||
|
@ -352,10 +352,10 @@ class TLThingy extends StatelessWidget {
|
|||
clipBehavior: Clip.hardEdge,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 48),
|
||||
padding: const EdgeInsets.fromLTRB(18, 0, 18, 44),
|
||||
child: SizedBox(
|
||||
height: 300,
|
||||
width: 300,
|
||||
height: 310,
|
||||
width: 310,
|
||||
child: RadarChart(
|
||||
RadarChartData(
|
||||
radarShape: RadarShape.polygon,
|
||||
|
@ -377,21 +377,21 @@ class TLThingy extends StatelessWidget {
|
|||
angle: angle,
|
||||
);
|
||||
case 2:
|
||||
return RadarChartTitle(text: 'VS', angle: angle);
|
||||
return RadarChartTitle(text: 'VS', angle: angle, positionPercentageOffset: 0.05);
|
||||
case 3:
|
||||
return RadarChartTitle(text: 'APP', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'APP', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 4:
|
||||
return RadarChartTitle(text: 'DS/S', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'DS/S', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 5:
|
||||
return RadarChartTitle(text: 'DS/P', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'DS/P', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 6:
|
||||
return RadarChartTitle(text: 'APP+DS/P', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'APP+DS/P', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 7:
|
||||
return RadarChartTitle(text: 'VS/APM', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'VS/APM', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 8:
|
||||
return RadarChartTitle(text: 'Cheese', angle: angle);
|
||||
return RadarChartTitle(text: 'Cheese', angle: angle, positionPercentageOffset: 0.05);
|
||||
case 9:
|
||||
return RadarChartTitle(text: 'Gb Eff.', angle: angle);
|
||||
return RadarChartTitle(text: 'Gb Eff.', angle: angle, positionPercentageOffset: 0.05);
|
||||
default:
|
||||
return const RadarChartTitle(text: '');
|
||||
}
|
||||
|
@ -435,34 +435,30 @@ class TLThingy extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(20, 0, 20, 48),
|
||||
padding: const EdgeInsets.fromLTRB(18, 0, 18, 44),
|
||||
child: SizedBox(
|
||||
height: 300,
|
||||
width: 300,
|
||||
height: 310,
|
||||
width: 310,
|
||||
child: RadarChart(
|
||||
RadarChartData(
|
||||
radarShape: RadarShape.polygon,
|
||||
tickCount: 4,
|
||||
ticksTextStyle: const TextStyle(color: Colors.transparent, fontSize: 10),
|
||||
ticksTextStyle: const TextStyle(color: Colors.white24, fontSize: 10),
|
||||
radarBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
gridBorderData: const BorderSide(color: Colors.white24, width: 1),
|
||||
tickBorderData: const BorderSide(color: Colors.transparent, width: 1),
|
||||
titleTextStyle: const TextStyle(height: 1.1),
|
||||
radarTouchData: RadarTouchData(),
|
||||
getTitle: (index, angle) {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return RadarChartTitle(
|
||||
text: 'Opener',
|
||||
angle: angle,
|
||||
);
|
||||
return RadarChartTitle(text: 'Opener\n${f2.format(tl.playstyle!.opener)}', angle: 0, positionPercentageOffset: 0.05);
|
||||
case 1:
|
||||
return RadarChartTitle(
|
||||
text: 'Stride',
|
||||
angle: angle,
|
||||
);
|
||||
return RadarChartTitle(text: 'Stride\n${f2.format(tl.playstyle!.stride)}', angle: 0, positionPercentageOffset: 0.05);
|
||||
case 2:
|
||||
return RadarChartTitle(text: 'Inf Ds', angle: angle + 180);
|
||||
return RadarChartTitle(text: 'Inf Ds\n${f2.format(tl.playstyle!.infds)}', angle: angle + 180, positionPercentageOffset: 0.05);
|
||||
case 3:
|
||||
return RadarChartTitle(text: 'Plonk', angle: angle);
|
||||
return RadarChartTitle(text: 'Plonk\n${f2.format(tl.playstyle!.plonk)}', angle: 0, positionPercentageOffset: 0.05);
|
||||
default:
|
||||
return const RadarChartTitle(text: '');
|
||||
}
|
||||
|
|
|
@ -100,10 +100,13 @@
|
|||
"calcViewNoValues": "Enter values to calculate the stats",
|
||||
"rankAveragesViewTitle": "Ranks cutoff and average stats",
|
||||
"averages": "Averages",
|
||||
"lbViewZeroEntrys": "Empty list. Looks like something is wrong...",
|
||||
"lbViewOneEntry": "There is only one player... What?",
|
||||
"lbViewManyEntrys": "There are ${numberOfPlayers}.",
|
||||
"lbViewZeroEntrys": "Empty list",
|
||||
"lbViewOneEntry": "There is only one player",
|
||||
"lbViewManyEntrys": "There are ${numberOfPlayers}",
|
||||
"everyoneAverages": "Values for leaderboard",
|
||||
"sortBy": "Sort by",
|
||||
"reversed": "Reversed",
|
||||
"country": "Country",
|
||||
"rankAverages": "Values for $rank rank",
|
||||
"players":{
|
||||
"zero": "$n players",
|
||||
|
@ -205,6 +208,8 @@
|
|||
"socketException": "Can't connect with ${host}: ${message}"
|
||||
},
|
||||
"countries(map)": {
|
||||
"": "Not selected",
|
||||
|
||||
"AF": "Afghanistan",
|
||||
"AX": "\u00c5land Islands",
|
||||
"AL": "Albania",
|
||||
|
|
|
@ -100,10 +100,13 @@
|
|||
"calcViewNoValues": "Введите значения, чтобы посчитать статистику",
|
||||
"rankAveragesViewTitle": "Требования рангов и средние значения",
|
||||
"averages": "Средние значения",
|
||||
"lbViewZeroEntrys": "Рейтинговая таблица пуста. Похоже, что-то здесь не так...",
|
||||
"lbViewOneEntry": "В рейтинговой таблице всего один игрок... Чего?",
|
||||
"lbViewManyEntrys": "В рейтинговой таблице находится ${numberOfPlayers}.",
|
||||
"lbViewZeroEntrys": "Рейтинговая таблица пуста",
|
||||
"lbViewOneEntry": "В рейтинговой таблице всего один игрок",
|
||||
"lbViewManyEntrys": "В рейтинговой таблице находится ${numberOfPlayers}",
|
||||
"everyoneAverages": "Значения таблицы",
|
||||
"sortBy": "Cортировать по",
|
||||
"reversed": "Наоборот",
|
||||
"country": "Страна",
|
||||
"rankAverages": "Значения для $rank ранга",
|
||||
"players":{
|
||||
"zero": "$n игроков",
|
||||
|
@ -205,6 +208,8 @@
|
|||
"socketException": "Невозможно подключиться к ${host}: ${message}"
|
||||
},
|
||||
"countries(map)": {
|
||||
"": "Не выбрана",
|
||||
|
||||
"AF": "Афганистан",
|
||||
"AX": "Аландские острова",
|
||||
"AL": "Албания",
|
||||
|
|
Loading…
Reference in New Issue