I'm not sure about my decisions
This commit is contained in:
parent
874d5a2e5c
commit
bf72c4cee3
|
@ -6,7 +6,7 @@
|
|||
/// Locales: 3
|
||||
/// Strings: 1818 (606 per locale)
|
||||
///
|
||||
/// Built on 2024-11-16 at 13:39 UTC
|
||||
/// Built on 2024-11-21 at 21:18 UTC
|
||||
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
|
@ -220,7 +220,7 @@ class Translations implements BaseTranslations<AppLocale, Translations> {
|
|||
String comparingWith({required Object newDate, required Object oldDate}) => 'Data from ${newDate} comparing with ${oldDate}';
|
||||
String get top => 'Top';
|
||||
String get topRank => 'Top rank';
|
||||
String verdictGeneral({required Object n, required Object verdict, required Object rank}) => '${n} ${verdict} than ${rank} rank average';
|
||||
String verdictGeneral({required Object n, required Object verdict, required Object rank}) => '${n} ${verdict} ${rank} rank avg';
|
||||
String get verdictBetter => 'better';
|
||||
String get verdictWorse => 'worse';
|
||||
String get smooth => 'Smooth';
|
||||
|
@ -2348,7 +2348,7 @@ extension on Translations {
|
|||
case 'comparingWith': return ({required Object newDate, required Object oldDate}) => 'Data from ${newDate} comparing with ${oldDate}';
|
||||
case 'top': return 'Top';
|
||||
case 'topRank': return 'Top rank';
|
||||
case 'verdictGeneral': return ({required Object n, required Object verdict, required Object rank}) => '${n} ${verdict} than ${rank} rank average';
|
||||
case 'verdictGeneral': return ({required Object n, required Object verdict, required Object rank}) => '${n} ${verdict} ${rank} rank avg';
|
||||
case 'verdictBetter': return 'better';
|
||||
case 'verdictWorse': return 'worse';
|
||||
case 'smooth': return 'Smooth';
|
||||
|
|
|
@ -46,6 +46,7 @@ ThemeData theme = ThemeData(
|
|||
),
|
||||
segmentedButtonTheme: SegmentedButtonThemeData(
|
||||
style: ButtonStyle(
|
||||
visualDensity: VisualDensity(horizontal: -4.0, vertical: -4.0),
|
||||
side: const WidgetStatePropertyAll(BorderSide(color: Colors.transparent)),
|
||||
surfaceTintColor: const WidgetStatePropertyAll(Colors.cyanAccent),
|
||||
iconColor: const WidgetStatePropertyAll(Colors.cyanAccent),
|
||||
|
|
|
@ -13,6 +13,7 @@ final NumberFormat f2l = NumberFormat.decimalPatternDigits(locale: LocaleSetting
|
|||
final NumberFormat f1 = NumberFormat.decimalPatternDigits(locale: LocaleSettings.currentLocale.languageCode, decimalDigits: 1);
|
||||
final NumberFormat f0 = NumberFormat.decimalPattern(LocaleSettings.currentLocale.languageCode);
|
||||
final NumberFormat percentage = NumberFormat.percentPattern(LocaleSettings.currentLocale.languageCode)..maximumFractionDigits = 2;
|
||||
final NumberFormat percentagef4 = NumberFormat.percentPattern(LocaleSettings.currentLocale.languageCode)..maximumFractionDigits = 4;
|
||||
|
||||
/// Readable [a] - [b], without sign
|
||||
String readableIntDifference(int a, int b){
|
||||
|
|
|
@ -27,6 +27,8 @@ enum CalcCards{
|
|||
damage
|
||||
}
|
||||
|
||||
CalcCards calcCard = CalcCards.calc;
|
||||
|
||||
class ClearData{
|
||||
final String title;
|
||||
final Lineclears lineclear;
|
||||
|
@ -131,6 +133,7 @@ class Rules{
|
|||
const TextStyle mainToggleInRules = TextStyle(fontSize: 18, fontWeight: ui.FontWeight.w800);
|
||||
|
||||
class _DestinationCalculatorState extends State<DestinationCalculator> {
|
||||
// Stats calculator variables
|
||||
double? apm;
|
||||
double? pps;
|
||||
double? vs;
|
||||
|
@ -141,6 +144,25 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
TextEditingController apmController = TextEditingController();
|
||||
TextEditingController vsController = TextEditingController();
|
||||
|
||||
// Damage Calculator variables
|
||||
List<Widget> rSideWidgets = [];
|
||||
List<Widget> lSideWidgets = [];
|
||||
int combo = -1;
|
||||
int b2b = -1;
|
||||
int previousB2B = -1;
|
||||
int totalDamage = 0;
|
||||
int normalDamage = 0;
|
||||
int comboDamage = 0;
|
||||
int b2bDamage = 0;
|
||||
int surgeDamage = 0;
|
||||
int pcDamage = 0;
|
||||
|
||||
// values for "the bar"
|
||||
late double sec2end;
|
||||
late double sec3end;
|
||||
late double sec4end;
|
||||
late double sec5end;
|
||||
|
||||
List<ClearData> clears = [];
|
||||
Map<String, int> customClearsChoice = {
|
||||
"No Spin Clears": 5,
|
||||
|
@ -149,8 +171,6 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
int idCounter = 0;
|
||||
Rules rules = Rules();
|
||||
|
||||
CalcCards card = CalcCards.calc;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
@ -175,17 +195,11 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
}
|
||||
}
|
||||
|
||||
// void calcDamage(){
|
||||
// for (ClearData lineclear in clears){
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
Widget getCalculator(){
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Card(
|
||||
if (widget.constraints.maxWidth > 768.0) Card(
|
||||
child: Center(child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Column(
|
||||
|
@ -200,14 +214,16 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
padding: const EdgeInsets.fromLTRB(16.0, 8.0, 16.0, 8.0),
|
||||
child: Row(
|
||||
children: [
|
||||
//TODO: animate those TextFields
|
||||
Expanded(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(12.0, 0.0, 12.0, 0.0),
|
||||
child: TextField(
|
||||
onSubmitted: (value) => calc(),
|
||||
onChanged: (value) {setState(() {});},
|
||||
controller: apmController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(suffix: Text("APM"), alignLabelWithHint: true, hintText: "Enter your APM"),
|
||||
decoration: InputDecoration(suffix: apmController.value.text.isNotEmpty ? Text("APM") : null, alignLabelWithHint: true, hintText: widget.constraints.maxWidth > 768.0 ? "Enter your APM" : "APM"),
|
||||
),
|
||||
)
|
||||
),
|
||||
|
@ -216,9 +232,10 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
padding: const EdgeInsets.fromLTRB(12.0, 0.0, 12.0, 0.0),
|
||||
child: TextField(
|
||||
onSubmitted: (value) => calc(),
|
||||
onChanged: (value) {setState(() {});},
|
||||
controller: ppsController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(suffix: Text("PPS"), alignLabelWithHint: true, hintText: "Enter your PPS"),
|
||||
decoration: InputDecoration(suffix: ppsController.value.text.isNotEmpty ? Text("PPS") : null, alignLabelWithHint: true, hintText: widget.constraints.maxWidth > 768.0 ? "Enter your PPS" : "PPS"),
|
||||
),
|
||||
)
|
||||
),
|
||||
|
@ -227,9 +244,10 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
padding: const EdgeInsets.fromLTRB(12.0, 0.0, 12.0, 0.0),
|
||||
child: TextField(
|
||||
onSubmitted: (value) => calc(),
|
||||
onChanged: (value) {setState(() {});},
|
||||
controller: vsController,
|
||||
keyboardType: TextInputType.number,
|
||||
decoration: const InputDecoration(suffix: Text("VS"), alignLabelWithHint: true, hintText: "Enter your VS"),
|
||||
decoration: InputDecoration(suffix: vsController.value.text.isNotEmpty ? Text("VS") : null, alignLabelWithHint: true, hintText: widget.constraints.maxWidth > 768.0 ? "Enter your VS" : "VS"),
|
||||
),
|
||||
)
|
||||
),
|
||||
|
@ -242,7 +260,7 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
),
|
||||
),
|
||||
if (nerdStats != null) Card(
|
||||
child: NerdStatsThingy(nerdStats: nerdStats!)
|
||||
child: NerdStatsThingy(nerdStats: nerdStats!, width: widget.constraints.minWidth)
|
||||
),
|
||||
if (playstyle != null) Card(
|
||||
child: Graphs(apm!, pps!, vs!, nerdStats!, playstyle!)
|
||||
|
@ -253,10 +271,102 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget getDamageCalculator(){
|
||||
List<Widget> rSideWidgets = [];
|
||||
List<Widget> lSideWidgets = [];
|
||||
Widget rSideDamageCalculator(double width, bool hasSidebar){
|
||||
return SizedBox(
|
||||
width: width - (hasSidebar ? 80 : 0),
|
||||
height: widget.constraints.maxHeight - (hasSidebar ? 108 : 178),
|
||||
child: clears.isEmpty ? InfoThingy("Click on the actions on the left to add them here") :
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ReorderableListView(
|
||||
onReorder: (oldIndex, newIndex) {
|
||||
setState((){
|
||||
if (oldIndex < newIndex) {
|
||||
newIndex -= 1;
|
||||
}
|
||||
final ClearData item = clears.removeAt(oldIndex);
|
||||
clears.insert(newIndex, item);
|
||||
});
|
||||
},
|
||||
children: lSideWidgets,
|
||||
),
|
||||
),
|
||||
Divider(),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16.0, 0.0, 34.0, 0.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Total damage:", style: TextStyle(fontSize: 36, fontWeight: ui.FontWeight.w100)),
|
||||
Spacer(),
|
||||
Text(intf.format(totalDamage), style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, fontWeight: ui.FontWeight.w100))
|
||||
],
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Text("Lineclears: ${intf.format(normalDamage)}"),
|
||||
Text("Combo: ${intf.format(comboDamage)}"),
|
||||
Text("B2B: ${intf.format(b2bDamage)}"),
|
||||
Text("Surge: ${intf.format(surgeDamage)}"),
|
||||
Text("PCs: ${intf.format(pcDamage)}")
|
||||
],
|
||||
),
|
||||
if (totalDamage > 0) SfLinearGauge(
|
||||
minimum: 0,
|
||||
maximum: totalDamage.toDouble(),
|
||||
showLabels: false,
|
||||
showTicks: false,
|
||||
ranges: [
|
||||
LinearGaugeRange(
|
||||
color: Colors.green,
|
||||
startValue: 0,
|
||||
endValue: normalDamage.toDouble(),
|
||||
position: LinearElementPosition.cross,
|
||||
),
|
||||
LinearGaugeRange(
|
||||
color: Colors.yellow,
|
||||
startValue: normalDamage.toDouble(),
|
||||
endValue: sec2end,
|
||||
position: LinearElementPosition.cross,
|
||||
),
|
||||
LinearGaugeRange(
|
||||
color: Colors.blue,
|
||||
startValue: sec2end,
|
||||
endValue: sec3end,
|
||||
position: LinearElementPosition.cross,
|
||||
),
|
||||
LinearGaugeRange(
|
||||
color: Colors.red,
|
||||
startValue: sec3end,
|
||||
endValue: sec4end,
|
||||
position: LinearElementPosition.cross,
|
||||
),
|
||||
LinearGaugeRange(
|
||||
color: Colors.orange,
|
||||
startValue: sec4end,
|
||||
endValue: sec5end,
|
||||
position: LinearElementPosition.cross,
|
||||
),
|
||||
],
|
||||
),
|
||||
ElevatedButton.icon(onPressed: (){setState((){clears.clear();});}, icon: const Icon(Icons.clear), label: Text("Clear all"), style: const ButtonStyle(shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12.0))))))
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget getDamageCalculator(){
|
||||
rSideWidgets = [];
|
||||
lSideWidgets = [];
|
||||
for (var key in clearsExisting.keys){
|
||||
rSideWidgets.add(Text(key));
|
||||
for (ClearData data in clearsExisting[key]!) rSideWidgets.add(Card(
|
||||
|
@ -299,15 +409,15 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
rSideWidgets.add(const Divider());
|
||||
}
|
||||
|
||||
int combo = -1;
|
||||
int b2b = -1;
|
||||
int previousB2B = -1;
|
||||
int totalDamage = 0;
|
||||
int normalDamage = 0;
|
||||
int comboDamage = 0;
|
||||
int b2bDamage = 0;
|
||||
int surgeDamage = 0;
|
||||
int pcDamage = 0;
|
||||
combo = -1;
|
||||
b2b = -1;
|
||||
previousB2B = -1;
|
||||
totalDamage = 0;
|
||||
normalDamage = 0;
|
||||
comboDamage = 0;
|
||||
b2bDamage = 0;
|
||||
surgeDamage = 0;
|
||||
pcDamage = 0;
|
||||
|
||||
for (ClearData lineclear in clears){
|
||||
previousB2B = b2b;
|
||||
|
@ -345,13 +455,13 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
pcDamage += pcDmg;
|
||||
}
|
||||
// values for "the bar"
|
||||
double sec2end = normalDamage.toDouble()+comboDamage.toDouble();
|
||||
double sec3end = normalDamage.toDouble()+comboDamage.toDouble()+b2bDamage.toDouble();
|
||||
double sec4end = normalDamage.toDouble()+comboDamage.toDouble()+b2bDamage.toDouble()+surgeDamage.toDouble();
|
||||
double sec5end = normalDamage.toDouble()+comboDamage.toDouble()+b2bDamage.toDouble()+surgeDamage.toDouble()+pcDamage.toDouble();
|
||||
sec2end = normalDamage.toDouble()+comboDamage.toDouble();
|
||||
sec3end = normalDamage.toDouble()+comboDamage.toDouble()+b2bDamage.toDouble();
|
||||
sec4end = normalDamage.toDouble()+comboDamage.toDouble()+b2bDamage.toDouble()+surgeDamage.toDouble();
|
||||
sec5end = normalDamage.toDouble()+comboDamage.toDouble()+b2bDamage.toDouble()+surgeDamage.toDouble()+pcDamage.toDouble();
|
||||
return Column(
|
||||
children: [
|
||||
Card(
|
||||
if (widget.constraints.maxWidth > 768.0) Card(
|
||||
child: Center(child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: Column(
|
||||
|
@ -361,216 +471,133 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
),
|
||||
)),
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 350.0,
|
||||
child: DefaultTabController(length: 2,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
child: TabBar(tabs: [
|
||||
Tab(text: "Actions"),
|
||||
Tab(text: "Rules"),
|
||||
]),
|
||||
),
|
||||
SizedBox(
|
||||
height: widget.constraints.maxHeight - 164,
|
||||
child: TabBarView(children: [
|
||||
SingleChildScrollView(
|
||||
child: Column(
|
||||
children: rSideWidgets,
|
||||
),
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text("Multiplier", style: mainToggleInRules),
|
||||
trailing: SizedBox(width: 90.0, child: TextField(
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[0-9.]'))],
|
||||
decoration: InputDecoration(hintText: rules.multiplier.toString()),
|
||||
onChanged: (value) => setState((){rules.multiplier = double.parse(value);}),
|
||||
)),
|
||||
),
|
||||
ListTile(
|
||||
title: Text("Perfect Clear Damage"),
|
||||
trailing: SizedBox(width: 90.0, child: TextField(
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))],
|
||||
decoration: InputDecoration(hintText: rules.pcDamage.toString()),
|
||||
onChanged: (value) => setState((){rules.pcDamage = int.parse(value);}),
|
||||
)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text("Combo", style: mainToggleInRules),
|
||||
trailing: Switch(value: rules.combo, onChanged: (v) => setState((){rules.combo = v;})),
|
||||
),
|
||||
if (rules.combo) ListTile(
|
||||
title: Text("Combo Table"),
|
||||
trailing: DropdownButton(
|
||||
items: [for (var v in ComboTables.values) if (v != ComboTables.none) DropdownMenuItem(value: v.index, child: Text(comboTablesNames[v]!))],
|
||||
value: rules.comboTable.index,
|
||||
onChanged: (v) => setState((){rules.comboTable = ComboTables.values[v!];}),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text("Back-To-Back (B2B)", style: mainToggleInRules),
|
||||
trailing: Switch(value: rules.b2b, onChanged: (v) => setState((){rules.b2b = v;})),
|
||||
),
|
||||
if (rules.b2b) ListTile(
|
||||
title: Text("Back-To-Back Chaining"),
|
||||
trailing: Switch(value: rules.b2bChaining, onChanged: (v) => setState((){rules.b2bChaining = v;})),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text("Surge", style: mainToggleInRules),
|
||||
trailing: Switch(value: rules.surge, onChanged: (v) => setState((){rules.surge = v;})),
|
||||
),
|
||||
if (rules.surge) ListTile(
|
||||
title: Text("Starts at B2B"),
|
||||
trailing: SizedBox(width: 90.0, child: TextField(
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
decoration: InputDecoration(hintText: rules.surgeInitAtB2b.toString()),
|
||||
onChanged: (value) => setState((){rules.surgeInitAtB2b = int.parse(value);}),
|
||||
)),
|
||||
),
|
||||
if (rules.surge) ListTile(
|
||||
title: Text("Start amount"),
|
||||
trailing: SizedBox(width: 90.0, child: TextField(
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
decoration: InputDecoration(hintText: rules.surgeInitAmount.toString()),
|
||||
onChanged: (value) => setState((){rules.surgeInitAmount = int.parse(value);}),
|
||||
)),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
]),
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: widget.constraints.maxWidth - 350 - 80,
|
||||
height: widget.constraints.maxHeight - 108,
|
||||
child: clears.isEmpty ? InfoThingy("Click on the actions on the left to add them here") :
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
Expanded(
|
||||
child: ReorderableListView(
|
||||
onReorder: (oldIndex, newIndex) {
|
||||
setState((){
|
||||
if (oldIndex < newIndex) {
|
||||
newIndex -= 1;
|
||||
}
|
||||
final ClearData item = clears.removeAt(oldIndex);
|
||||
clears.insert(newIndex, item);
|
||||
});
|
||||
},
|
||||
children: lSideWidgets,
|
||||
Expanded(
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: widget.constraints.maxWidth > 768.0 ? 350.0 : widget.constraints.maxWidth,
|
||||
child: DefaultTabController(length: widget.constraints.maxWidth > 768.0 ? 2 : 3,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
child: TabBar(tabs: [
|
||||
Tab(text: "Actions"),
|
||||
if (widget.constraints.maxWidth <= 768.0) Tab(text: "Results"),
|
||||
Tab(text: "Rules"),
|
||||
]),
|
||||
),
|
||||
),
|
||||
Divider(),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.fromLTRB(16.0, 0.0, 34.0, 0.0),
|
||||
child: Row(
|
||||
children: [
|
||||
Text("Total damage:", style: TextStyle(fontSize: 36, fontWeight: ui.FontWeight.w100)),
|
||||
Spacer(),
|
||||
Text(intf.format(totalDamage), style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, fontWeight: ui.FontWeight.w100))
|
||||
],
|
||||
SizedBox(
|
||||
height: widget.constraints.maxHeight - 164,
|
||||
child: TabBarView(children: [
|
||||
SingleChildScrollView(
|
||||
child: Column(
|
||||
children: rSideWidgets,
|
||||
),
|
||||
),
|
||||
),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Text("Lineclears: ${intf.format(normalDamage)}"),
|
||||
Text("Combo: ${intf.format(comboDamage)}"),
|
||||
Text("B2B: ${intf.format(b2bDamage)}"),
|
||||
Text("Surge: ${intf.format(surgeDamage)}"),
|
||||
Text("PCs: ${intf.format(pcDamage)}")
|
||||
],
|
||||
),
|
||||
if (totalDamage > 0) SfLinearGauge(
|
||||
minimum: 0,
|
||||
maximum: totalDamage.toDouble(),
|
||||
showLabels: false,
|
||||
showTicks: false,
|
||||
ranges: [
|
||||
LinearGaugeRange(
|
||||
color: Colors.green,
|
||||
startValue: 0,
|
||||
endValue: normalDamage.toDouble(),
|
||||
position: LinearElementPosition.cross,
|
||||
if (widget.constraints.maxWidth <= 768.0) SingleChildScrollView(
|
||||
child: rSideDamageCalculator(widget.constraints.minWidth, false),
|
||||
),
|
||||
SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text("Multiplier", style: mainToggleInRules),
|
||||
trailing: SizedBox(width: 90.0, child: TextField(
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[0-9.]'))],
|
||||
decoration: InputDecoration(hintText: rules.multiplier.toString()),
|
||||
onChanged: (value) => setState((){rules.multiplier = double.parse(value);}),
|
||||
)),
|
||||
),
|
||||
ListTile(
|
||||
title: Text("Perfect Clear Damage"),
|
||||
trailing: SizedBox(width: 90.0, child: TextField(
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.allow(RegExp(r'[0-9]'))],
|
||||
decoration: InputDecoration(hintText: rules.pcDamage.toString()),
|
||||
onChanged: (value) => setState((){rules.pcDamage = int.parse(value);}),
|
||||
)),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text("Combo", style: mainToggleInRules),
|
||||
trailing: Switch(value: rules.combo, onChanged: (v) => setState((){rules.combo = v;})),
|
||||
),
|
||||
if (rules.combo) ListTile(
|
||||
title: Text("Combo Table"),
|
||||
trailing: DropdownButton(
|
||||
items: [for (var v in ComboTables.values) if (v != ComboTables.none) DropdownMenuItem(value: v.index, child: Text(comboTablesNames[v]!))],
|
||||
value: rules.comboTable.index,
|
||||
onChanged: (v) => setState((){rules.comboTable = ComboTables.values[v!];}),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text("Back-To-Back (B2B)", style: mainToggleInRules),
|
||||
trailing: Switch(value: rules.b2b, onChanged: (v) => setState((){rules.b2b = v;})),
|
||||
),
|
||||
if (rules.b2b) ListTile(
|
||||
title: Text("Back-To-Back Chaining"),
|
||||
trailing: Switch(value: rules.b2bChaining, onChanged: (v) => setState((){rules.b2bChaining = v;})),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text("Surge", style: mainToggleInRules),
|
||||
trailing: Switch(value: rules.surge, onChanged: (v) => setState((){rules.surge = v;})),
|
||||
),
|
||||
if (rules.surge) ListTile(
|
||||
title: Text("Starts at B2B"),
|
||||
trailing: SizedBox(width: 90.0, child: TextField(
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
decoration: InputDecoration(hintText: rules.surgeInitAtB2b.toString()),
|
||||
onChanged: (value) => setState((){rules.surgeInitAtB2b = int.parse(value);}),
|
||||
)),
|
||||
),
|
||||
if (rules.surge) ListTile(
|
||||
title: Text("Start amount"),
|
||||
trailing: SizedBox(width: 90.0, child: TextField(
|
||||
keyboardType: TextInputType.number,
|
||||
inputFormatters: [FilteringTextInputFormatter.digitsOnly],
|
||||
decoration: InputDecoration(hintText: rules.surgeInitAmount.toString()),
|
||||
onChanged: (value) => setState((){rules.surgeInitAmount = int.parse(value);}),
|
||||
)),
|
||||
),
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
LinearGaugeRange(
|
||||
color: Colors.yellow,
|
||||
startValue: normalDamage.toDouble(),
|
||||
endValue: sec2end,
|
||||
position: LinearElementPosition.cross,
|
||||
),
|
||||
LinearGaugeRange(
|
||||
color: Colors.blue,
|
||||
startValue: sec2end,
|
||||
endValue: sec3end,
|
||||
position: LinearElementPosition.cross,
|
||||
),
|
||||
LinearGaugeRange(
|
||||
color: Colors.red,
|
||||
startValue: sec3end,
|
||||
endValue: sec4end,
|
||||
position: LinearElementPosition.cross,
|
||||
),
|
||||
LinearGaugeRange(
|
||||
color: Colors.orange,
|
||||
startValue: sec4end,
|
||||
endValue: sec5end,
|
||||
position: LinearElementPosition.cross,
|
||||
),
|
||||
],
|
||||
),
|
||||
ElevatedButton.icon(onPressed: (){setState((){clears.clear();});}, icon: const Icon(Icons.clear), label: Text("Clear all"), style: const ButtonStyle(shape: WidgetStatePropertyAll(RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(12.0))))))
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
]),
|
||||
)
|
||||
],
|
||||
)
|
||||
),
|
||||
),
|
||||
)
|
||||
],
|
||||
if (widget.constraints.maxWidth > 768.0) rSideDamageCalculator(widget.constraints.maxWidth - 350, true)
|
||||
],
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
@ -581,13 +608,13 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
return Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
height: widget.constraints.maxHeight -32,
|
||||
child: switch (card){
|
||||
height: widget.constraints.maxHeight - (widget.constraints.maxWidth > 768.0 ? 32 : 133),
|
||||
child: switch (calcCard){
|
||||
CalcCards.calc => getCalculator(),
|
||||
CalcCards.damage => getDamageCalculator()
|
||||
}
|
||||
),
|
||||
SegmentedButton<CalcCards>(
|
||||
if (widget.constraints.maxWidth > 768.0) SegmentedButton<CalcCards>(
|
||||
showSelectedIcon: false,
|
||||
segments: <ButtonSegment<CalcCards>>[
|
||||
const ButtonSegment<CalcCards>(
|
||||
|
@ -599,10 +626,10 @@ class _DestinationCalculatorState extends State<DestinationCalculator> {
|
|||
label: Text('Damage Calculator'),
|
||||
),
|
||||
],
|
||||
selected: <CalcCards>{card},
|
||||
selected: <CalcCards>{calcCard},
|
||||
onSelectionChanged: (Set<CalcCards> newSelection) {
|
||||
setState(() {
|
||||
card = newSelection.first;
|
||||
calcCard = newSelection.first;
|
||||
});})
|
||||
],
|
||||
);
|
||||
|
|
|
@ -157,136 +157,139 @@ class _DestinationCutoffsState extends State<DestinationCutoffs> {
|
|||
),
|
||||
),
|
||||
),
|
||||
Table(
|
||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||
border: TableBorder.all(color: Colors.grey.shade900),
|
||||
columnWidths: const {
|
||||
0: FixedColumnWidth(48),
|
||||
1: FixedColumnWidth(155),
|
||||
2: FixedColumnWidth(140),
|
||||
3: FixedColumnWidth(160),
|
||||
4: FixedColumnWidth(150),
|
||||
5: FixedColumnWidth(90),
|
||||
6: FixedColumnWidth(130),
|
||||
7: FixedColumnWidth(120),
|
||||
8: FixedColumnWidth(125),
|
||||
9: FixedColumnWidth(70),
|
||||
},
|
||||
children: [
|
||||
TableRow(
|
||||
children: [
|
||||
Text("Rank", textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: Text("Cutoff TR", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: Text("Target TR", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 24, fontWeight: FontWeight.w100, color: Colors.white)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text("State", textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: Text("APM", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: Text("PPS", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: Text("VS", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: Text("Advanced", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text("Players (${intf.format(snapshot.data!.total)})", textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: TextButton(child: Text("More Info", textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500)), onPressed: () {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => RankView(rank: "", nextRankTR: snapshot.data!.data["top1"]!.tr, nextRankPercentile: 0.00, nextRankTargetTR: 25000.00, totalPlayers: snapshot.data!.total, cutoffTetrio: CutoffTetrio(apm: 0, pps: 0, vs: 0, pos: 0, percentile: 1, count: snapshot.data!.total, countPercentile: 1, tr: snapshot.data!.data["d"]!.tr, targetTr: snapshot.data!.data['d']!.targetTr)),
|
||||
),
|
||||
);
|
||||
},),
|
||||
),
|
||||
]
|
||||
),
|
||||
for (String rank in snapshot.data!.data.keys) if (rank != "top1") TableRow(
|
||||
decoration: BoxDecoration(gradient: LinearGradient(colors: [rankColors[rank]!.withAlpha(200), rankColors[rank]!.withAlpha(100)])),
|
||||
children: [
|
||||
Container(decoration: BoxDecoration(boxShadow: [BoxShadow(color: Colors.black.withAlpha(132), blurRadius: 32.0, blurStyle: BlurStyle.inner)]), child: Image.asset("res/tetrio_tl_alpha_ranks/$rank.png", height: 48)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text(f2.format(snapshot.data!.data[rank]!.tr), textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white, shadows: textShadow)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text(f2.format(snapshot.data!.data[rank]!.targetTr), textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 24, fontWeight: FontWeight.w100, color: Colors.white, shadows: textShadow)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: RichText(
|
||||
textAlign: TextAlign.right,
|
||||
text: TextSpan(
|
||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100, color: Colors.white, shadows: textShadow),
|
||||
children: [
|
||||
if (rank == "x+") TextSpan(text: "№ 1 is ${f2.format(snapshot.data!.data["top1"]!.tr)} TR", style: const TextStyle(color: Colors.white60, shadows: null))
|
||||
else TextSpan(text: snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr > snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr ? "Inflated on ${f2.format(snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr - snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr)} TR" : "Not inflated", style: TextStyle(color: snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr > snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr ? Colors.white :Colors.white60, shadows: null)),
|
||||
TextSpan(text: "\n", style: const TextStyle(color: Colors.white60, shadows: null)),
|
||||
if (rank == "d") TextSpan(text: "Well...", style: const TextStyle(color: Colors.white60, shadows: null))
|
||||
else TextSpan(text: snapshot.data!.data[rank]!.tr < snapshot.data!.data[rank]!.targetTr ? "Deflated on ${f2.format(snapshot.data!.data[rank]!.targetTr - snapshot.data!.data[rank]!.tr)} TR" : "Not deflated", style: TextStyle(color: snapshot.data!.data[rank]!.tr < snapshot.data!.data[rank]!.targetTr ? Colors.white : Colors.white60, shadows: null))
|
||||
]
|
||||
)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text(snapshot.data?.data[rank]?.apm != null ? f2.format(snapshot.data!.data[rank]!.apm) : "-.--", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w100, color: snapshot.data?.data[rank]?.apm != null ? Colors.white : Colors.grey, shadows: textShadow)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text(snapshot.data?.data[rank]?.pps != null ? f2.format(snapshot.data!.data[rank]!.pps) : "-.--", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w100, color: snapshot.data?.data[rank]?.pps != null ? Colors.white : Colors.grey, shadows: textShadow)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text(snapshot.data?.data[rank]?.vs != null ? f2.format(snapshot.data!.data[rank]!.vs) : "-.--", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w100, color: snapshot.data?.data[rank]?.vs != null ? Colors.white : Colors.grey, shadows: textShadow)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text("${snapshot.data?.data[rank]?.apm != null && snapshot.data?.data[rank]?.pps != null ? f3.format(snapshot.data!.data[rank]!.apm! / (snapshot.data!.data[rank]!.pps! * 60)) : "-.---"} APP\n${snapshot.data?.data[rank]?.apm != null && snapshot.data?.data[rank]?.vs != null ? f3.format(snapshot.data!.data[rank]!.vs! / snapshot.data!.data[rank]!.apm!) : "-.---"} VS/APM", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100, color: snapshot.data?.data[rank]?.apm != null && snapshot.data?.data[rank]?.pps != null && snapshot.data?.data[rank]?.vs != null ? Colors.white : Colors.grey, shadows: textShadow)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: RichText(
|
||||
textAlign: TextAlign.right,
|
||||
text: TextSpan(
|
||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100, color: Colors.white, shadows: textShadow),
|
||||
children: [
|
||||
TextSpan(text: intf.format(snapshot.data!.data[rank]!.count)),
|
||||
TextSpan(text: " (${f2.format(snapshot.data!.data[rank]!.countPercentile * 100)}%)", style: const TextStyle(color: Colors.white60, shadows: null)),
|
||||
TextSpan(text: "\n(from № ${intf.format(snapshot.data!.data[rank]!.pos)})", style: const TextStyle(color: Colors.white60, shadows: null))
|
||||
]
|
||||
))
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: TextButton(child: Text("View", textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500)), onPressed: () {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => RankView(rank: rank, nextRankTR: rank == "x+" ? snapshot.data!.data["top1"]!.tr : snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr, nextRankPercentile: rank == "x+" ? 0.00 : snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.percentile, nextRankTargetTR: rank == "x+" ? 25000.00 : snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr, totalPlayers: snapshot.data!.total, cutoffTetrio: snapshot.data!.data[rank]!),
|
||||
),
|
||||
);
|
||||
},),
|
||||
),
|
||||
]
|
||||
)
|
||||
],
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Table(
|
||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||
border: TableBorder.all(color: Colors.grey.shade900),
|
||||
columnWidths: const {
|
||||
0: FixedColumnWidth(48),
|
||||
1: FixedColumnWidth(155),
|
||||
2: FixedColumnWidth(140),
|
||||
3: FixedColumnWidth(160),
|
||||
4: FixedColumnWidth(150),
|
||||
5: FixedColumnWidth(90),
|
||||
6: FixedColumnWidth(130),
|
||||
7: FixedColumnWidth(120),
|
||||
8: FixedColumnWidth(125),
|
||||
9: FixedColumnWidth(70),
|
||||
},
|
||||
children: [
|
||||
TableRow(
|
||||
children: [
|
||||
Text("Rank", textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: Text("Cutoff TR", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: Text("Target TR", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 24, fontWeight: FontWeight.w100, color: Colors.white)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text("State", textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: Text("APM", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: Text("PPS", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: Text("VS", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
const Padding(
|
||||
padding: EdgeInsets.only(right: 8.0),
|
||||
child: Text("Advanced", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text("Players (${intf.format(snapshot.data!.total)})", textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500, color: Colors.white)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: TextButton(child: Text("More Info", textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500)), onPressed: () {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => RankView(rank: "", nextRankTR: snapshot.data!.data["top1"]!.tr, nextRankPercentile: 0.00, nextRankTargetTR: 25000.00, totalPlayers: snapshot.data!.total, cutoffTetrio: CutoffTetrio(apm: 0, pps: 0, vs: 0, pos: 0, percentile: 1, count: snapshot.data!.total, countPercentile: 1, tr: snapshot.data!.data["d"]!.tr, targetTr: snapshot.data!.data['d']!.targetTr)),
|
||||
),
|
||||
);
|
||||
},),
|
||||
),
|
||||
]
|
||||
),
|
||||
for (String rank in snapshot.data!.data.keys) if (rank != "top1") TableRow(
|
||||
decoration: BoxDecoration(gradient: LinearGradient(colors: [rankColors[rank]!.withAlpha(200), rankColors[rank]!.withAlpha(100)])),
|
||||
children: [
|
||||
Container(decoration: BoxDecoration(boxShadow: [BoxShadow(color: Colors.black.withAlpha(132), blurRadius: 32.0, blurStyle: BlurStyle.inner)]), child: Image.asset("res/tetrio_tl_alpha_ranks/$rank.png", height: 48)),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text(f2.format(snapshot.data!.data[rank]!.tr), textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w500, color: Colors.white, shadows: textShadow)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text(f2.format(snapshot.data!.data[rank]!.targetTr), textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 24, fontWeight: FontWeight.w100, color: Colors.white, shadows: textShadow)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: RichText(
|
||||
textAlign: TextAlign.right,
|
||||
text: TextSpan(
|
||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100, color: Colors.white, shadows: textShadow),
|
||||
children: [
|
||||
if (rank == "x+") TextSpan(text: "№ 1 is ${f2.format(snapshot.data!.data["top1"]!.tr)} TR", style: const TextStyle(color: Colors.white60, shadows: null))
|
||||
else TextSpan(text: snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr > snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr ? "Inflated on ${f2.format(snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr - snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr)} TR" : "Not inflated", style: TextStyle(color: snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr > snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr ? Colors.white :Colors.white60, shadows: null)),
|
||||
TextSpan(text: "\n", style: const TextStyle(color: Colors.white60, shadows: null)),
|
||||
if (rank == "d") TextSpan(text: "Well...", style: const TextStyle(color: Colors.white60, shadows: null))
|
||||
else TextSpan(text: snapshot.data!.data[rank]!.tr < snapshot.data!.data[rank]!.targetTr ? "Deflated on ${f2.format(snapshot.data!.data[rank]!.targetTr - snapshot.data!.data[rank]!.tr)} TR" : "Not deflated", style: TextStyle(color: snapshot.data!.data[rank]!.tr < snapshot.data!.data[rank]!.targetTr ? Colors.white : Colors.white60, shadows: null))
|
||||
]
|
||||
)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text(snapshot.data?.data[rank]?.apm != null ? f2.format(snapshot.data!.data[rank]!.apm) : "-.--", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w100, color: snapshot.data?.data[rank]?.apm != null ? Colors.white : Colors.grey, shadows: textShadow)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text(snapshot.data?.data[rank]?.pps != null ? f2.format(snapshot.data!.data[rank]!.pps) : "-.--", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w100, color: snapshot.data?.data[rank]?.pps != null ? Colors.white : Colors.grey, shadows: textShadow)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text(snapshot.data?.data[rank]?.vs != null ? f2.format(snapshot.data!.data[rank]!.vs) : "-.--", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 28, fontWeight: FontWeight.w100, color: snapshot.data?.data[rank]?.vs != null ? Colors.white : Colors.grey, shadows: textShadow)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Text("${snapshot.data?.data[rank]?.apm != null && snapshot.data?.data[rank]?.pps != null ? f3.format(snapshot.data!.data[rank]!.apm! / (snapshot.data!.data[rank]!.pps! * 60)) : "-.---"} APP\n${snapshot.data?.data[rank]?.apm != null && snapshot.data?.data[rank]?.vs != null ? f3.format(snapshot.data!.data[rank]!.vs! / snapshot.data!.data[rank]!.apm!) : "-.---"} VS/APM", textAlign: TextAlign.right, style: TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100, color: snapshot.data?.data[rank]?.apm != null && snapshot.data?.data[rank]?.pps != null && snapshot.data?.data[rank]?.vs != null ? Colors.white : Colors.grey, shadows: textShadow)),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: RichText(
|
||||
textAlign: TextAlign.right,
|
||||
text: TextSpan(
|
||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w100, color: Colors.white, shadows: textShadow),
|
||||
children: [
|
||||
TextSpan(text: intf.format(snapshot.data!.data[rank]!.count)),
|
||||
TextSpan(text: " (${f2.format(snapshot.data!.data[rank]!.countPercentile * 100)}%)", style: const TextStyle(color: Colors.white60, shadows: null)),
|
||||
TextSpan(text: "\n(from № ${intf.format(snapshot.data!.data[rank]!.pos)})", style: const TextStyle(color: Colors.white60, shadows: null))
|
||||
]
|
||||
))
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 8.0),
|
||||
child: TextButton(child: Text("View", textAlign: TextAlign.right, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, fontWeight: FontWeight.w500)), onPressed: () {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => RankView(rank: rank, nextRankTR: rank == "x+" ? snapshot.data!.data["top1"]!.tr : snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.tr, nextRankPercentile: rank == "x+" ? 0.00 : snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.percentile, nextRankTargetTR: rank == "x+" ? 25000.00 : snapshot.data!.data[ranks[ranks.indexOf(rank)+1]]!.targetTr, totalPlayers: snapshot.data!.total, cutoffTetrio: snapshot.data!.data[rank]!),
|
||||
),
|
||||
);
|
||||
},),
|
||||
),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
]
|
||||
),
|
||||
|
|
|
@ -19,13 +19,17 @@ class DestinationGraphs extends StatefulWidget{
|
|||
final String searchFor;
|
||||
//final Function setState;
|
||||
final BoxConstraints constraints;
|
||||
final bool noSidebar;
|
||||
|
||||
const DestinationGraphs({super.key, required this.searchFor, required this.constraints});
|
||||
const DestinationGraphs({super.key, required this.searchFor, required this.constraints, required this.noSidebar});
|
||||
|
||||
@override
|
||||
State<DestinationGraphs> createState() => _DestinationGraphsState();
|
||||
}
|
||||
|
||||
Graph graph = Graph.history;
|
||||
Stats Ychart = Stats.tr;
|
||||
|
||||
enum Graph{
|
||||
history,
|
||||
leagueState,
|
||||
|
@ -42,14 +46,12 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
String yAxisTitle = "";
|
||||
bool _smooth = false;
|
||||
final List<DropdownMenuItem<Stats>> _yAxis = [for (MapEntry e in chartsShortTitles.entries) DropdownMenuItem(value: e.key, child: Text(e.value))];
|
||||
Graph _graph = Graph.history;
|
||||
Stats _Ychart = Stats.tr;
|
||||
Stats _Xchart = Stats.tr;
|
||||
int _season = currentSeason-1;
|
||||
ValueNotifier<String> historyPlayerUsername = ValueNotifier("");
|
||||
ValueNotifier<String> historyPlayerAvatarRevizion = ValueNotifier("");
|
||||
List<String> excludeRanks = [];
|
||||
late Future<List<_MyScatterSpot>> futureLeague = getTetraLeagueData(_Xchart, _Ychart);
|
||||
late Future<List<_MyScatterSpot>> futureLeague = getTetraLeagueData(_Xchart, Ychart);
|
||||
String searchLeague = "";
|
||||
//Duration postSeasonLeft = seasonStart.difference(DateTime.now());
|
||||
|
||||
|
@ -99,7 +101,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 20),
|
||||
),
|
||||
),
|
||||
Text('${f4.format(data.x)} ${chartsShortTitles[_Xchart]}\n${f4.format(data.y)} ${chartsShortTitles[_Ychart]}')
|
||||
Text('${f4.format(data.x)} ${chartsShortTitles[_Xchart]}\n${f4.format(data.y)} ${chartsShortTitles[Ychart]}')
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -207,8 +209,8 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
case ConnectionState.done:
|
||||
if (snapshot.hasData){
|
||||
if (snapshot.data!.isEmpty || !snapshot.data!.containsKey(_season)) return ErrorThingy(eText: "Not enough data");
|
||||
List<_HistoryChartSpot> selectedGraph = snapshot.data![_season]![_Ychart]!;
|
||||
yAxisTitle = chartsShortTitles[_Ychart]!;
|
||||
List<_HistoryChartSpot> selectedGraph = snapshot.data![_season]![Ychart]!;
|
||||
yAxisTitle = chartsShortTitles[Ychart]!;
|
||||
return SfCartesianChart(
|
||||
tooltipBehavior: _historyTooltipBehavior,
|
||||
zoomPanBehavior: _zoomPanBehavior,
|
||||
|
@ -306,14 +308,14 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
return const Center(child: CircularProgressIndicator());
|
||||
case ConnectionState.done:
|
||||
if (snapshot.hasData){
|
||||
yAxisTitle = chartsShortTitles[_Ychart]!;
|
||||
yAxisTitle = chartsShortTitles[Ychart]!;
|
||||
return SfCartesianChart(
|
||||
tooltipBehavior: _leagueTooltipBehavior,
|
||||
zoomPanBehavior: _zoomPanBehavior,
|
||||
primaryXAxis: const DateTimeAxis(),
|
||||
primaryYAxis: NumericAxis(
|
||||
// isInversed: true,
|
||||
maximum: switch (_Ychart){
|
||||
maximum: switch (Ychart){
|
||||
Stats.tr => 25000.0,
|
||||
Stats.gxe => 100.00,
|
||||
_ => null
|
||||
|
@ -327,7 +329,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
animationDuration: 0,
|
||||
//opacity: 0.5,
|
||||
xValueMapper: (Cutoffs data, _) => data.ts,
|
||||
yValueMapper: (Cutoffs data, _) => switch (_Ychart){
|
||||
yValueMapper: (Cutoffs data, _) => switch (Ychart){
|
||||
Stats.glicko => data.glicko[rank],
|
||||
Stats.gxe => data.gxe[rank],
|
||||
_ => data.tr[rank]
|
||||
|
@ -344,20 +346,20 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: Column(
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Card(
|
||||
child: Wrap(
|
||||
spacing: 20,
|
||||
crossAxisAlignment: WrapCrossAlignment.center,
|
||||
alignment: WrapAlignment.center,
|
||||
children: [
|
||||
if (_graph == Graph.history) Row(
|
||||
if (graph == Graph.history) Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(Icons.person),
|
||||
|
@ -372,7 +374,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
),
|
||||
],
|
||||
),
|
||||
if (_graph == Graph.leagueState) SizedBox(
|
||||
if (graph == Graph.leagueState) SizedBox(
|
||||
width: 300,
|
||||
child: TextField(
|
||||
style: TextStyle(fontSize: 18.0000),
|
||||
|
@ -385,11 +387,11 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
},
|
||||
onSubmitted: (v){
|
||||
searchLeague = v;
|
||||
setState((){futureLeague = getTetraLeagueData(_Xchart, _Ychart);});
|
||||
setState((){futureLeague = getTetraLeagueData(_Xchart, Ychart);});
|
||||
},
|
||||
)
|
||||
),
|
||||
if (_graph == Graph.history) Row(
|
||||
if (graph == Graph.history) Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Padding(padding: EdgeInsets.all(8.0), child: Text("Season:", style: TextStyle(fontSize: 22))),
|
||||
|
@ -404,20 +406,20 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
),
|
||||
],
|
||||
),
|
||||
if (_graph != Graph.leagueCutoffs) Row(
|
||||
if (graph != Graph.leagueCutoffs) Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const Padding(padding: EdgeInsets.all(8.0), child: Text("X:", style: TextStyle(fontSize: 22))),
|
||||
DropdownButton(
|
||||
items: switch (_graph){
|
||||
items: switch (graph){
|
||||
Graph.history => [DropdownMenuItem(value: false, child: Text("Date & Time")), DropdownMenuItem(value: true, child: Text("Games Played"))],
|
||||
Graph.leagueState => _yAxis,
|
||||
Graph.leagueCutoffs => [],
|
||||
},
|
||||
value: _graph == Graph.history ? _gamesPlayedInsteadOfDateAndTime : _Xchart,
|
||||
value: graph == Graph.history ? _gamesPlayedInsteadOfDateAndTime : _Xchart,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
if (_graph == Graph.history)
|
||||
if (graph == Graph.history)
|
||||
_gamesPlayedInsteadOfDateAndTime = value! as bool;
|
||||
else _Xchart = value! as Stats;
|
||||
});
|
||||
|
@ -430,17 +432,17 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
children: [
|
||||
const Padding(padding: EdgeInsets.all(8.0), child: Text("Y:", style: TextStyle(fontSize: 22))),
|
||||
DropdownButton<Stats>(
|
||||
items: _graph == Graph.leagueCutoffs ? [DropdownMenuItem(value: Stats.tr, child: Text(chartsShortTitles[Stats.tr]!)), DropdownMenuItem(value: Stats.glicko, child: Text(chartsShortTitles[Stats.glicko]!)), DropdownMenuItem(value: Stats.gxe, child: Text(chartsShortTitles[Stats.gxe]!))] : _yAxis,
|
||||
value: _Ychart,
|
||||
items: graph == Graph.leagueCutoffs ? [DropdownMenuItem(value: Stats.tr, child: Text(chartsShortTitles[Stats.tr]!)), DropdownMenuItem(value: Stats.glicko, child: Text(chartsShortTitles[Stats.glicko]!)), DropdownMenuItem(value: Stats.gxe, child: Text(chartsShortTitles[Stats.gxe]!))] : _yAxis,
|
||||
value: Ychart,
|
||||
onChanged: (value) {
|
||||
setState(() {
|
||||
_Ychart = value!;
|
||||
Ychart = value!;
|
||||
});
|
||||
}
|
||||
),
|
||||
],
|
||||
),
|
||||
if (_graph == Graph.history) Row(
|
||||
if (graph == Graph.history) Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Checkbox(value: _smooth,
|
||||
|
@ -453,7 +455,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
Text(t.smooth, style: const TextStyle(color: Colors.white, fontSize: 22))
|
||||
],
|
||||
),
|
||||
if (_graph == Graph.leagueState) IconButton(
|
||||
if (graph == Graph.leagueState) IconButton(
|
||||
color: excludeRanks.isNotEmpty ? Theme.of(context).colorScheme.primary : null,
|
||||
onPressed: (){
|
||||
showDialog(context: context, builder: (BuildContext context) {
|
||||
|
@ -492,7 +494,7 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: const Text("Apply"),
|
||||
onPressed: () {Navigator.of(context).pop(); setState((){futureLeague = getTetraLeagueData(_Xchart, _Ychart);});}
|
||||
onPressed: () {Navigator.of(context).pop(); setState((){futureLeague = getTetraLeagueData(_Xchart, Ychart);});}
|
||||
)
|
||||
]
|
||||
);
|
||||
|
@ -506,10 +508,10 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
),
|
||||
Card(
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width - 88,
|
||||
width: MediaQuery.of(context).size.width - (widget.noSidebar ? 0 : 88),
|
||||
height: MediaQuery.of(context).size.height - 96,
|
||||
child: Padding( padding: const EdgeInsets.fromLTRB(40, 30, 40, 30),
|
||||
child: switch (_graph){
|
||||
child: switch (graph){
|
||||
Graph.history => getHistoryGraph(),
|
||||
Graph.leagueState => getLeagueState(),
|
||||
Graph.leagueCutoffs => getCutoffsHistory()
|
||||
|
@ -519,34 +521,34 @@ class _DestinationGraphsState extends State<DestinationGraphs> {
|
|||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SegmentedButton<Graph>(
|
||||
showSelectedIcon: false,
|
||||
segments: <ButtonSegment<Graph>>[
|
||||
const ButtonSegment<Graph>(
|
||||
value: Graph.history,
|
||||
label: Text('Player History')),
|
||||
ButtonSegment<Graph>(
|
||||
value: Graph.leagueState,
|
||||
label: Text('League State')),
|
||||
ButtonSegment<Graph>(
|
||||
value: Graph.leagueCutoffs,
|
||||
label: Text('League Cutoffs'),
|
||||
),
|
||||
],
|
||||
selected: <Graph>{_graph},
|
||||
onSelectionChanged: (Set<Graph> newSelection) {
|
||||
setState(() {
|
||||
_graph = newSelection.first;
|
||||
switch (newSelection.first){
|
||||
case Graph.leagueCutoffs:
|
||||
case Graph.history:
|
||||
_Ychart = Stats.tr;
|
||||
case Graph.leagueState:
|
||||
_Ychart = Stats.apm;
|
||||
}
|
||||
});})
|
||||
],
|
||||
if (!widget.noSidebar) SegmentedButton<Graph>(
|
||||
showSelectedIcon: false,
|
||||
segments: <ButtonSegment<Graph>>[
|
||||
const ButtonSegment<Graph>(
|
||||
value: Graph.history,
|
||||
label: Text('Player History')),
|
||||
ButtonSegment<Graph>(
|
||||
value: Graph.leagueState,
|
||||
label: Text('League State')),
|
||||
ButtonSegment<Graph>(
|
||||
value: Graph.leagueCutoffs,
|
||||
label: Text('League Cutoffs'),
|
||||
),
|
||||
],
|
||||
selected: <Graph>{graph},
|
||||
onSelectionChanged: (Set<Graph> newSelection) {
|
||||
setState(() {
|
||||
graph = newSelection.first;
|
||||
switch (newSelection.first){
|
||||
case Graph.leagueCutoffs:
|
||||
case Graph.history:
|
||||
Ychart = Stats.tr;
|
||||
case Graph.leagueState:
|
||||
Ychart = Stats.apm;
|
||||
}
|
||||
});})
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -125,58 +125,60 @@ class ZenithCard extends StatelessWidget {
|
|||
|
||||
Widget splitsCard(){
|
||||
return Card(
|
||||
child: SizedBox(
|
||||
width: 300,
|
||||
height: 318,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Stack(
|
||||
alignment: AlignmentDirectional.bottomStart,
|
||||
children: [
|
||||
const Text("T", style: TextStyle(
|
||||
fontStyle: FontStyle.italic,
|
||||
fontSize: 65,
|
||||
height: 1.2,
|
||||
)),
|
||||
const Positioned(left: 25, top: 20, child: Text("otal time", style: TextStyle(fontFamily: "Eurostile Round Extended"))),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 10.0),
|
||||
child: Text(getMoreNormalTime(record!.stats.finalTime), style: const TextStyle(
|
||||
shadows: textShadow,
|
||||
fontFamily: "Eurostile Round Extended",
|
||||
fontSize: 36,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white
|
||||
)),
|
||||
)
|
||||
],
|
||||
),
|
||||
SizedBox(
|
||||
width: 300.0,
|
||||
child: Table(
|
||||
columnWidths: const {
|
||||
0: FixedColumnWidth(36)
|
||||
},
|
||||
child: Center(
|
||||
child: SizedBox(
|
||||
width: 300,
|
||||
height: 318,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Stack(
|
||||
alignment: AlignmentDirectional.bottomStart,
|
||||
children: [
|
||||
const TableRow(
|
||||
children: [
|
||||
Text("Floor"),
|
||||
Text("Split", textAlign: TextAlign.right),
|
||||
Text("Total", textAlign: TextAlign.right),
|
||||
]
|
||||
),
|
||||
for (int i = 0; i < record!.stats.zenith!.splits.length; i++) TableRow(
|
||||
children: [
|
||||
Text((i+1).toString()),
|
||||
Text(record!.stats.zenith!.splits[i] != Duration.zero ? getMoreNormalTime(record!.stats.zenith!.splits[i]-(i-1 != -1 ? record!.stats.zenith!.splits[i-1] : Duration.zero)) : "--:--.---", textAlign: TextAlign.right),
|
||||
Text(record!.stats.zenith!.splits[i] != Duration.zero ? getMoreNormalTime(record!.stats.zenith!.splits[i]) : "--:--.---", textAlign: TextAlign.right),
|
||||
]
|
||||
const Text("T", style: TextStyle(
|
||||
fontStyle: FontStyle.italic,
|
||||
fontSize: 65,
|
||||
height: 1.2,
|
||||
)),
|
||||
const Positioned(left: 25, top: 20, child: Text("otal time", style: TextStyle(fontFamily: "Eurostile Round Extended"))),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 10.0),
|
||||
child: Text(getMoreNormalTime(record!.stats.finalTime), style: const TextStyle(
|
||||
shadows: textShadow,
|
||||
fontFamily: "Eurostile Round Extended",
|
||||
fontSize: 36,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Colors.white
|
||||
)),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
SizedBox(
|
||||
width: 300.0,
|
||||
child: Table(
|
||||
columnWidths: const {
|
||||
0: FixedColumnWidth(36)
|
||||
},
|
||||
children: [
|
||||
const TableRow(
|
||||
children: [
|
||||
Text("Floor"),
|
||||
Text("Split", textAlign: TextAlign.right),
|
||||
Text("Total", textAlign: TextAlign.right),
|
||||
]
|
||||
),
|
||||
for (int i = 0; i < record!.stats.zenith!.splits.length; i++) TableRow(
|
||||
children: [
|
||||
Text((i+1).toString()),
|
||||
Text(record!.stats.zenith!.splits[i] != Duration.zero ? getMoreNormalTime(record!.stats.zenith!.splits[i]-(i-1 != -1 ? record!.stats.zenith!.splits[i-1] : Duration.zero)) : "--:--.---", textAlign: TextAlign.right),
|
||||
Text(record!.stats.zenith!.splits[i] != Duration.zero ? getMoreNormalTime(record!.stats.zenith!.splits[i]) : "--:--.---", textAlign: TextAlign.right),
|
||||
]
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@ -257,8 +259,155 @@ class RecordCard extends StatelessWidget {
|
|||
final MapEntry? closestAverage;
|
||||
final bool? betterThanClosestAverage;
|
||||
final String? rank;
|
||||
final double width;
|
||||
|
||||
const RecordCard(this.record, this.achievements, this.betterThanRankAverage, this.closestAverage, this.betterThanClosestAverage, this.rank);
|
||||
const RecordCard(this.record, this.achievements, this.betterThanRankAverage, this.closestAverage, this.betterThanClosestAverage, this.rank, {this.width = double.infinity});
|
||||
|
||||
Widget result(){
|
||||
return Card(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (closestAverage != null) Padding(padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Image.asset("res/tetrio_tl_alpha_ranks/${closestAverage!.key}.png", height: 96)
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
RichText(text: TextSpan(
|
||||
text: switch(record!.gamemode){
|
||||
"40l" => get40lTime(record!.stats.finalTime.inMicroseconds),
|
||||
"blitz" => NumberFormat.decimalPattern().format(record!.stats.score),
|
||||
"5mblast" => get40lTime(record!.stats.finalTime.inMicroseconds),
|
||||
_ => record!.stats.score.toString()
|
||||
},
|
||||
style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, fontWeight: FontWeight.w500, color: Colors.white),
|
||||
),
|
||||
),
|
||||
RichText(text: TextSpan(
|
||||
text: "",
|
||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey),
|
||||
children: [
|
||||
if (rank != null && rank != "z") TextSpan(text: "${t.verdictGeneral(n: switch(record!.gamemode){
|
||||
"40l" => readableTimeDifference(record!.stats.finalTime, sprintAverages[rank]!),
|
||||
"blitz" => readableIntDifference(record!.stats.score, blitzAverages[rank]!),
|
||||
_ => record!.stats.score.toString()
|
||||
}, verdict: betterThanRankAverage??false ? t.verdictBetter : t.verdictWorse, rank: rank!.toUpperCase())}\n", style: TextStyle(
|
||||
color: betterThanClosestAverage??false ? Colors.greenAccent : Colors.redAccent
|
||||
))
|
||||
else if ((rank == null || rank == "z" || rank == "x+") && closestAverage != null) TextSpan(text: "${t.verdictGeneral(n: switch(record!.gamemode){
|
||||
"40l" => readableTimeDifference(record!.stats.finalTime, closestAverage!.value),
|
||||
"blitz" => readableIntDifference(record!.stats.score, closestAverage!.value),
|
||||
_ => record!.stats.score.toString()
|
||||
}, verdict: betterThanClosestAverage??false ? t.verdictBetter : t.verdictWorse, rank: closestAverage!.key.toUpperCase())}\n", style: TextStyle(
|
||||
color: betterThanClosestAverage??false ? Colors.greenAccent : Colors.redAccent
|
||||
)),
|
||||
if (record!.rank != -1) TextSpan(text: "№ ${intf.format(record!.rank)}", style: TextStyle(color: getColorOfRank(record!.rank))),
|
||||
if (record!.rank != -1) const TextSpan(text: " • "),
|
||||
if (record!.countryRank != -1) TextSpan(text: "№ ${intf.format(record!.countryRank)} local", style: TextStyle(color: getColorOfRank(record!.countryRank))),
|
||||
if (record!.countryRank != -1) const TextSpan(text: " • "),
|
||||
TextSpan(text: timestamp(record!.timestamp)),
|
||||
]
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Table(
|
||||
defaultColumnWidth:const IntrinsicColumnWidth(),
|
||||
children: [
|
||||
TableRow(children: [
|
||||
Text(switch(record!.gamemode){
|
||||
"40l" => record!.stats.piecesPlaced.toString(),
|
||||
"blitz" => record!.stats.level.toString(),
|
||||
"5mblast" => NumberFormat.decimalPattern().format(record!.stats.spp),
|
||||
_ => "What if "
|
||||
}, textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
Text(switch(record!.gamemode){
|
||||
"40l" => " Pieces",
|
||||
"blitz" => " Level",
|
||||
"5mblast" => " SPP",
|
||||
_ => " i wanted to"
|
||||
}, textAlign: TextAlign.left, style: const TextStyle(fontSize: 21)),
|
||||
]),
|
||||
TableRow(children: [
|
||||
Text(f2.format(record!.stats.pps), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
const Text(" PPS", textAlign: TextAlign.left, style: TextStyle(fontSize: 21)),
|
||||
]),
|
||||
TableRow(children: [
|
||||
Text(switch(record!.gamemode){
|
||||
"40l" => f2.format(record!.stats.kpp),
|
||||
"blitz" => f2.format(record!.stats.spp),
|
||||
"5mblast" => record!.stats.piecesPlaced.toString(),
|
||||
_ => "but god said"
|
||||
}, textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
Text(switch(record!.gamemode){
|
||||
"40l" => " KPP",
|
||||
"blitz" => " SPP",
|
||||
"5mblast" => " Pieces",
|
||||
_ => " no"
|
||||
}, textAlign: TextAlign.left, style: const TextStyle(fontSize: 21)),
|
||||
])
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Table(
|
||||
defaultColumnWidth:const IntrinsicColumnWidth(),
|
||||
children: [
|
||||
TableRow(children: [
|
||||
Text(intf.format(record!.stats.inputs), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
const Text(" Key presses", textAlign: TextAlign.left, style: TextStyle(fontSize: 21)),
|
||||
]),
|
||||
TableRow(children: [
|
||||
Text(f2.format(record!.stats.kps), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
const Text(" KPS", textAlign: TextAlign.left, style: TextStyle(fontSize: 21)),
|
||||
]),
|
||||
TableRow(children: [
|
||||
Text(switch(record!.gamemode){
|
||||
"40l" => " ",
|
||||
"blitz" => record!.stats.piecesPlaced.toString(),
|
||||
"5mblast" => record!.stats.piecesPlaced.toString(),
|
||||
_ => "but god said"
|
||||
}, textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
Text(switch(record!.gamemode){
|
||||
"40l" => " ",
|
||||
"blitz" => " Pieces",
|
||||
"5mblast" => " Pieces",
|
||||
_ => " no"
|
||||
}, textAlign: TextAlign.left, style: const TextStyle(fontSize: 21)),
|
||||
])
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget hjsdj(){
|
||||
return Card(
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
FinesseThingy(record!.stats.finesse, record!.stats.finessePercentage),
|
||||
LineclearsThingy(record!.stats.clears, record!.stats.lines, record!.stats.holds, record!.stats.tSpins),
|
||||
if (record!.gamemode == 'blitz') Text("${f2.format(record!.stats.kpp)} KPP")
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -288,149 +437,15 @@ class RecordCard extends StatelessWidget {
|
|||
),
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (closestAverage != null) Padding(padding: const EdgeInsets.only(right: 8.0),
|
||||
child: Image.asset("res/tetrio_tl_alpha_ranks/${closestAverage!.key}.png", height: 96)
|
||||
),
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
RichText(text: TextSpan(
|
||||
text: switch(record!.gamemode){
|
||||
"40l" => get40lTime(record!.stats.finalTime.inMicroseconds),
|
||||
"blitz" => NumberFormat.decimalPattern().format(record!.stats.score),
|
||||
"5mblast" => get40lTime(record!.stats.finalTime.inMicroseconds),
|
||||
_ => record!.stats.score.toString()
|
||||
},
|
||||
style: const TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 36, fontWeight: FontWeight.w500, color: Colors.white),
|
||||
),
|
||||
),
|
||||
RichText(text: TextSpan(
|
||||
text: "",
|
||||
style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 14, color: Colors.grey),
|
||||
children: [
|
||||
if (rank != null && rank != "z") TextSpan(text: "${t.verdictGeneral(n: switch(record!.gamemode){
|
||||
"40l" => readableTimeDifference(record!.stats.finalTime, sprintAverages[rank]!),
|
||||
"blitz" => readableIntDifference(record!.stats.score, blitzAverages[rank]!),
|
||||
_ => record!.stats.score.toString()
|
||||
}, verdict: betterThanRankAverage??false ? t.verdictBetter : t.verdictWorse, rank: rank!.toUpperCase())}\n", style: TextStyle(
|
||||
color: betterThanClosestAverage??false ? Colors.greenAccent : Colors.redAccent
|
||||
))
|
||||
else if ((rank == null || rank == "z" || rank == "x+") && closestAverage != null) TextSpan(text: "${t.verdictGeneral(n: switch(record!.gamemode){
|
||||
"40l" => readableTimeDifference(record!.stats.finalTime, closestAverage!.value),
|
||||
"blitz" => readableIntDifference(record!.stats.score, closestAverage!.value),
|
||||
_ => record!.stats.score.toString()
|
||||
}, verdict: betterThanClosestAverage??false ? t.verdictBetter : t.verdictWorse, rank: closestAverage!.key.toUpperCase())}\n", style: TextStyle(
|
||||
color: betterThanClosestAverage??false ? Colors.greenAccent : Colors.redAccent
|
||||
)),
|
||||
if (record!.rank != -1) TextSpan(text: "№ ${intf.format(record!.rank)}", style: TextStyle(color: getColorOfRank(record!.rank))),
|
||||
if (record!.rank != -1) const TextSpan(text: " • "),
|
||||
if (record!.countryRank != -1) TextSpan(text: "№ ${intf.format(record!.countryRank)} local", style: TextStyle(color: getColorOfRank(record!.countryRank))),
|
||||
if (record!.countryRank != -1) const TextSpan(text: " • "),
|
||||
TextSpan(text: timestamp(record!.timestamp)),
|
||||
]
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Table(
|
||||
defaultColumnWidth:const IntrinsicColumnWidth(),
|
||||
children: [
|
||||
TableRow(children: [
|
||||
Text(switch(record!.gamemode){
|
||||
"40l" => record!.stats.piecesPlaced.toString(),
|
||||
"blitz" => record!.stats.level.toString(),
|
||||
"5mblast" => NumberFormat.decimalPattern().format(record!.stats.spp),
|
||||
_ => "What if "
|
||||
}, textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
Text(switch(record!.gamemode){
|
||||
"40l" => " Pieces",
|
||||
"blitz" => " Level",
|
||||
"5mblast" => " SPP",
|
||||
_ => " i wanted to"
|
||||
}, textAlign: TextAlign.left, style: const TextStyle(fontSize: 21)),
|
||||
]),
|
||||
TableRow(children: [
|
||||
Text(f2.format(record!.stats.pps), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
const Text(" PPS", textAlign: TextAlign.left, style: TextStyle(fontSize: 21)),
|
||||
]),
|
||||
TableRow(children: [
|
||||
Text(switch(record!.gamemode){
|
||||
"40l" => f2.format(record!.stats.kpp),
|
||||
"blitz" => f2.format(record!.stats.spp),
|
||||
"5mblast" => record!.stats.piecesPlaced.toString(),
|
||||
_ => "but god said"
|
||||
}, textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
Text(switch(record!.gamemode){
|
||||
"40l" => " KPP",
|
||||
"blitz" => " SPP",
|
||||
"5mblast" => " Pieces",
|
||||
_ => " no"
|
||||
}, textAlign: TextAlign.left, style: const TextStyle(fontSize: 21)),
|
||||
])
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Table(
|
||||
defaultColumnWidth:const IntrinsicColumnWidth(),
|
||||
children: [
|
||||
TableRow(children: [
|
||||
Text(intf.format(record!.stats.inputs), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
const Text(" Key presses", textAlign: TextAlign.left, style: TextStyle(fontSize: 21)),
|
||||
]),
|
||||
TableRow(children: [
|
||||
Text(f2.format(record!.stats.kps), textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
const Text(" KPS", textAlign: TextAlign.left, style: TextStyle(fontSize: 21)),
|
||||
]),
|
||||
TableRow(children: [
|
||||
Text(switch(record!.gamemode){
|
||||
"40l" => " ",
|
||||
"blitz" => record!.stats.piecesPlaced.toString(),
|
||||
"5mblast" => record!.stats.piecesPlaced.toString(),
|
||||
_ => "but god said"
|
||||
}, textAlign: TextAlign.right, style: const TextStyle(fontSize: 21)),
|
||||
Text(switch(record!.gamemode){
|
||||
"40l" => " ",
|
||||
"blitz" => " Pieces",
|
||||
"5mblast" => " Pieces",
|
||||
_ => " no"
|
||||
}, textAlign: TextAlign.left, style: const TextStyle(fontSize: 21)),
|
||||
])
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
Card(
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
FinesseThingy(record!.stats.finesse, record!.stats.finessePercentage),
|
||||
LineclearsThingy(record!.stats.clears, record!.stats.lines, record!.stats.holds, record!.stats.tSpins),
|
||||
if (record!.gamemode == 'blitz') Text("${f2.format(record!.stats.kpp)} KPP")
|
||||
],
|
||||
),
|
||||
),
|
||||
Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [result(), hjsdj()],
|
||||
),
|
||||
Wrap(
|
||||
direction: Axis.horizontal,
|
||||
children: [
|
||||
for (Achievement achievement in achievements) FractionallySizedBox(widthFactor: 0.5, child: AchievementSummary(achievement: achievement)),
|
||||
for (Achievement achievement in achievements) FractionallySizedBox(widthFactor: 1/((width/600).ceil()), child: AchievementSummary(achievement: achievement)),
|
||||
],
|
||||
),
|
||||
]
|
||||
|
@ -461,8 +476,9 @@ class RecordSummary extends StatelessWidget{
|
|||
final MapEntry? closestAverage;
|
||||
final bool? betterThanClosestAverage;
|
||||
final String? rank;
|
||||
final double width;
|
||||
|
||||
const RecordSummary({super.key, required this.record, this.betterThanRankAverage, this.closestAverage, this.old = false, this.betterThanClosestAverage, this.rank, this.hideRank = false});
|
||||
const RecordSummary({super.key, required this.record, this.betterThanRankAverage, this.closestAverage, this.old = false, this.betterThanClosestAverage, this.rank, this.hideRank = false, this.width = double.infinity});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -597,7 +613,7 @@ class AchievementSummary extends StatelessWidget{
|
|||
if (achievement!.vt == 4) TextSpan(text: " • "),
|
||||
if (achievement!.vt != 5) TextSpan(text: (achievement?.pos != null && !achievement!.pos!.isNegative) ? "№ ${intf.format(achievement!.pos!+1)}" : "№ ---", style: TextStyle(color: achievement?.pos != null ? getColorOfRank(achievement!.pos!+1) : Colors.grey)),
|
||||
if (achievement!.vt != 5) TextSpan(text: " • ", style: TextStyle(color: achievement?.pos != null ? getColorOfRank(achievement!.pos!+1) : Colors.grey)),
|
||||
TextSpan(text: "Top ${achievement?.pos != null ? percentage.format(achievement!.pos! / achievement!.total!) : "---%"}", style: TextStyle(color: achievement?.pos != null ? getColorOfRank(achievement!.pos!+1) : Colors.grey)),
|
||||
TextSpan(text: "Top ${achievement?.pos != null ? percentagef4.format(achievement!.pos! / achievement!.total!) : "---%"}", style: TextStyle(color: achievement?.pos != null ? getColorOfRank(achievement!.pos!+1) : Colors.grey)),
|
||||
]
|
||||
),
|
||||
),
|
||||
|
@ -1134,12 +1150,12 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
CardMod.exRecords => getListOfRecords("zenithex/recent", "zenithex/top", widget.constraints),
|
||||
},
|
||||
Cards.sprint => switch (cardMod){
|
||||
CardMod.info => RecordCard(snapshot.data?.summaries!.sprint, sprintAchievements, sprintBetterThanRankAverage, closestAverageSprint, sprintBetterThanClosestAverage, snapshot.data!.summaries!.league.rank),
|
||||
CardMod.info => RecordCard(snapshot.data?.summaries!.sprint, sprintAchievements, sprintBetterThanRankAverage, closestAverageSprint, sprintBetterThanClosestAverage, snapshot.data!.summaries!.league.rank, width: width),
|
||||
CardMod.records => getListOfRecords("40l/recent", "40l/top", widget.constraints),
|
||||
_ => const Center(child: Text("huh?"))
|
||||
},
|
||||
Cards.blitz => switch (cardMod){
|
||||
CardMod.info => RecordCard(snapshot.data?.summaries!.blitz, blitzAchievements, blitzBetterThanRankAverage, closestAverageBlitz, blitzBetterThanClosestAverage, snapshot.data!.summaries!.league.rank),
|
||||
CardMod.info => RecordCard(snapshot.data?.summaries!.blitz, blitzAchievements, blitzBetterThanRankAverage, closestAverageBlitz, blitzBetterThanClosestAverage, snapshot.data!.summaries!.league.rank, width: width),
|
||||
CardMod.records => getListOfRecords("blitz/recent", "blitz/top", widget.constraints),
|
||||
_ => const Center(child: Text("huh?"))
|
||||
},
|
||||
|
@ -1307,22 +1323,22 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
|||
else if (snapshot.data!.player!.badstanding == true) FakeDistinguishmentThingy(badStanding: true),
|
||||
rigthCard(snapshot, sprintAchievements, blitzAchievements, width),
|
||||
if (rightCard == Cards.overview) Card(
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Spacer(),
|
||||
Text(t.bio, style: const TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||
const Spacer()
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: MarkdownBody(data: snapshot.data!.player!.bio!, styleSheet: MarkdownStyleSheet(textAlign: WrapAlignment.center)),
|
||||
)
|
||||
],
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Spacer(),
|
||||
Text(t.bio, style: const TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||
const Spacer()
|
||||
],
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(bottom: 8.0),
|
||||
child: MarkdownBody(data: snapshot.data!.player!.bio!, styleSheet: MarkdownStyleSheet(textAlign: WrapAlignment.center)),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
if (rightCard == Cards.overview) NewsThingy(snapshot.data!.news!)
|
||||
],
|
||||
)
|
||||
|
|
|
@ -17,19 +17,20 @@ class DestinationInfo extends StatefulWidget{
|
|||
|
||||
class InfoCard extends StatelessWidget {
|
||||
final double height;
|
||||
final double viewportWidth;
|
||||
final String assetLink;
|
||||
final String? assetLinkOnFocus;
|
||||
final String title;
|
||||
final String description;
|
||||
final void Function() onPressed;
|
||||
|
||||
const InfoCard({required this.height, required this.assetLink, required this.title, required this.description, this.assetLinkOnFocus, required this.onPressed});
|
||||
const InfoCard({required this.height, this.viewportWidth = double.infinity, required this.assetLink, required this.title, required this.description, this.assetLinkOnFocus, required this.onPressed});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Card(
|
||||
clipBehavior: Clip.hardEdge,
|
||||
child: SizedBox(
|
||||
child: viewportWidth > 768.0 ? SizedBox(
|
||||
width: 450,
|
||||
height: height,
|
||||
child: Column(
|
||||
|
@ -43,6 +44,26 @@ class InfoCard extends StatelessWidget {
|
|||
Spacer()
|
||||
],
|
||||
),
|
||||
) : SizedBox(
|
||||
width: viewportWidth,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Image.asset(assetLink, fit: BoxFit.cover, width: 200.0),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
TextButton(child: Text(title, style: Theme.of(context).textTheme.titleLarge!.copyWith(decoration: TextDecoration.underline, decorationColor: Colors.white70, decorationStyle: TextDecorationStyle.dotted, fontSize: 28), textAlign: TextAlign.center), onPressed: onPressed),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(12.0),
|
||||
child: Text(description),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -52,6 +73,43 @@ class InfoCard extends StatelessWidget {
|
|||
class _DestinationInfo extends State<DestinationInfo> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
List<Widget> cards = [
|
||||
InfoCard(
|
||||
height: widget.constraints.maxHeight - 77,
|
||||
viewportWidth: widget.constraints.maxWidth,
|
||||
assetLink: "res/images/info card 1 focus.png",
|
||||
title: "40 Lines & Blitz Averages",
|
||||
description: "Since calculating 40 Lines & Blitz averages is tedious process, it gets updated only once in a while. Click on the title of this card to see the full 40 Lines & Blitz averages table\n\n${t.sprintAndBlitsRelevance(date: DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).format(sprintAndBlitzRelevance))}",
|
||||
onPressed: (){
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => SprintAndBlitzView(),
|
||||
));
|
||||
}
|
||||
),
|
||||
InfoCard(
|
||||
height: widget.constraints.maxHeight - 77,
|
||||
viewportWidth: widget.constraints.maxWidth,
|
||||
assetLink: "res/images/Снимок экрана_2023-11-06_01-00-50.png",
|
||||
title: "Tetra Stats Wiki",
|
||||
description: "Find more information about Tetra Stats functions and statictic, that it provides",
|
||||
onPressed: (){
|
||||
launchInBrowser(Uri.https("github.com", "dan63047/TetraStats/wiki"));
|
||||
}
|
||||
),
|
||||
InfoCard(
|
||||
height: widget.constraints.maxHeight - 77,
|
||||
viewportWidth: widget.constraints.maxWidth,
|
||||
assetLink: "res/images/Снимок экрана_2023-11-06_01-00-50.png",
|
||||
title: "About Tetra Stats",
|
||||
description: "Developed by dan63\n",
|
||||
onPressed: (){
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => AboutView(),
|
||||
));
|
||||
},
|
||||
),
|
||||
];
|
||||
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
|
@ -60,41 +118,7 @@ class _DestinationInfo extends State<DestinationInfo> {
|
|||
),
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children: [
|
||||
InfoCard(
|
||||
height: widget.constraints.maxHeight - 77,
|
||||
assetLink: "res/images/info card 1 focus.png",
|
||||
title: "40 Lines & Blitz Averages",
|
||||
description: "Since calculating 40 Lines & Blitz averages is tedious process, it gets updated only once in a while. Click on the title of this card to see the full 40 Lines & Blitz averages table\n\n${t.sprintAndBlitsRelevance(date: DateFormat.yMMMd(LocaleSettings.currentLocale.languageCode).format(sprintAndBlitzRelevance))}",
|
||||
onPressed: (){
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => SprintAndBlitzView(),
|
||||
));
|
||||
}
|
||||
),
|
||||
InfoCard(
|
||||
height: widget.constraints.maxHeight - 77,
|
||||
assetLink: "res/images/Снимок экрана_2023-11-06_01-00-50.png",
|
||||
title: "Tetra Stats Wiki",
|
||||
description: "Find more information about Tetra Stats functions and statictic, that it provides",
|
||||
onPressed: (){
|
||||
launchInBrowser(Uri.https("github.com", "dan63047/TetraStats/wiki"));
|
||||
}
|
||||
),
|
||||
InfoCard(
|
||||
height: widget.constraints.maxHeight - 77,
|
||||
assetLink: "res/images/Снимок экрана_2023-11-06_01-00-50.png",
|
||||
title: "About Tetra Stats",
|
||||
description: "Developed by dan63\n",
|
||||
onPressed: (){
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => AboutView(),
|
||||
));
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
child: widget.constraints.maxWidth > 768.0 ? Row(children: cards) : Column(children: cards),
|
||||
)
|
||||
],
|
||||
);
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:ffi';
|
||||
import 'dart:math';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:tetra_stats/data_objects/tetrio_constants.dart';
|
||||
|
@ -12,13 +13,16 @@ import 'package:tetra_stats/widgets/future_error.dart';
|
|||
|
||||
class DestinationLeaderboards extends StatefulWidget{
|
||||
final BoxConstraints constraints;
|
||||
final bool noSidebar;
|
||||
|
||||
const DestinationLeaderboards({super.key, required this.constraints});
|
||||
const DestinationLeaderboards({super.key, required this.constraints, required this.noSidebar});
|
||||
|
||||
@override
|
||||
State<DestinationLeaderboards> createState() => _DestinationLeaderboardsState();
|
||||
}
|
||||
|
||||
const double transformThreshold = 768.0;
|
||||
|
||||
enum Leaderboards{
|
||||
tl,
|
||||
fullTL,
|
||||
|
@ -116,14 +120,220 @@ class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
|
|||
});
|
||||
}
|
||||
|
||||
static TextStyle trailingStyle = TextStyle(fontSize: 28);
|
||||
Widget rightSide(double width){
|
||||
print(width);
|
||||
const double eukjsakjas = 450;
|
||||
TextStyle trailingStyle = TextStyle(fontSize: 28, fontFamily: width < eukjsakjas ? "Eurostile Round Condensed" : null);
|
||||
return SizedBox(
|
||||
width: width,
|
||||
child: Card(
|
||||
child: StreamBuilder<List<dynamic>>(
|
||||
stream: dataStream,
|
||||
builder:(context, snapshot) {
|
||||
switch (snapshot.connectionState){
|
||||
case ConnectionState.none:
|
||||
case ConnectionState.waiting:
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
case ConnectionState.active:
|
||||
case ConnectionState.done:
|
||||
if (snapshot.hasData){
|
||||
return Column(
|
||||
children: [
|
||||
Text(leaderboards[_currentLb]!, style: Theme.of(context).textTheme.titleSmall, textAlign: TextAlign.center),
|
||||
Wrap(
|
||||
alignment: WrapAlignment.center,
|
||||
children: [
|
||||
DropdownMenu(
|
||||
leadingIcon: Icon(Icons.public),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
isDense: true,
|
||||
),
|
||||
textStyle: TextStyle(fontSize: 14, height: 0.9),
|
||||
dropdownMenuEntries: _countries,
|
||||
initialSelection: "",
|
||||
onSelected: ((value) {
|
||||
_country = value as String?;
|
||||
list.clear();
|
||||
prisecter = null;
|
||||
_isFetchingData = false;
|
||||
_reachedTheEnd = false;
|
||||
setState((){_fetchData();});
|
||||
})
|
||||
),
|
||||
if (_currentLb == Leaderboards.fullTL) SizedBox(width: 5.0),
|
||||
if (_currentLb == Leaderboards.fullTL) DropdownMenu(
|
||||
leadingIcon: Icon(Icons.sort),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
isDense: true,
|
||||
),
|
||||
textStyle: TextStyle(fontSize: 14, height: 0.9),
|
||||
dropdownMenuEntries: _stats,
|
||||
initialSelection: stat,
|
||||
onSelected: ((value) {
|
||||
stat = value;
|
||||
list.clear();
|
||||
prisecter = null;
|
||||
_isFetchingData = false;
|
||||
_reachedTheEnd = false;
|
||||
setState((){_fetchData();});
|
||||
})
|
||||
),
|
||||
if (_currentLb == Leaderboards.fullTL) IconButton(
|
||||
color: _excludeRanks.isNotEmpty ? Theme.of(context).colorScheme.primary : null,
|
||||
onPressed: (){
|
||||
showDialog(context: context, builder: (BuildContext context) {
|
||||
return StatefulBuilder(
|
||||
builder: (context, StateSetter setAlertState) {
|
||||
return AlertDialog(
|
||||
title: Text("Filter", textAlign: TextAlign.center),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
CheckboxListTile(value: getTotalFilterValue(), tristate: true, title: Text("All", style: TextStyle(fontFamily: "Eurostile Round Extended")), onChanged: (value){
|
||||
setAlertState(
|
||||
(){
|
||||
if (_excludeRanks.length*2 > ranks.length){
|
||||
_excludeRanks.clear();
|
||||
}else{
|
||||
_excludeRanks = List.of(ranks);
|
||||
}
|
||||
}
|
||||
);
|
||||
}),
|
||||
for(String rank in ranks.reversed) CheckboxListTile(value: _excludeRanks.indexOf(rank) == -1, onChanged: (value){
|
||||
setAlertState(
|
||||
(){
|
||||
if (_excludeRanks.indexOf(rank) == -1){
|
||||
_excludeRanks.add(rank);
|
||||
}else{
|
||||
_excludeRanks.remove(rank);
|
||||
}
|
||||
}
|
||||
);
|
||||
}, title: Text(rank.toUpperCase()),)
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: const Text("Apply"),
|
||||
onPressed: () {Navigator.of(context).pop(); setState((){
|
||||
_currentLb = Leaderboards.fullTL;
|
||||
list.clear();
|
||||
prisecter = null;
|
||||
_fetchData();});
|
||||
}
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
}, icon: Icon(Icons.filter_alt)),
|
||||
if (_currentLb == Leaderboards.fullTL) IconButton(
|
||||
color: _reverse ? Theme.of(context).colorScheme.primary : null,
|
||||
icon: Transform.rotate(angle: _reverse ? pi : 0.0, child: Icon(Icons.filter_list)),
|
||||
onPressed: (){
|
||||
setState((){
|
||||
_reverse = !_reverse;
|
||||
_currentLb = Leaderboards.fullTL;
|
||||
list.clear();
|
||||
prisecter = null;
|
||||
_fetchData();
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
const Divider(),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
itemCount: list.length,
|
||||
prototypeItem: ListTile(
|
||||
leading: Text("0"),
|
||||
title: Text("ehhh...", style: TextStyle(fontSize: 22)),
|
||||
trailing: SizedBox(height: 36, width: 1),
|
||||
subtitle: const Text("eh...", style: TextStyle(color: Colors.grey, fontSize: 12)),
|
||||
),
|
||||
itemBuilder: (BuildContext context, int index){
|
||||
return ListTile(
|
||||
leading: Text(intf.format(index+1)),
|
||||
title: Text(snapshot.data![index].username, style: TextStyle(fontSize: 22)),
|
||||
trailing: switch (_currentLb){
|
||||
Leaderboards.tl => Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text("${f2.format(snapshot.data![index].tr)} TR", style: trailingStyle),
|
||||
Image.asset("res/tetrio_tl_alpha_ranks/${snapshot.data![index].rank}.png", height: 36)
|
||||
],
|
||||
),
|
||||
Leaderboards.fullTL => switch (stat) {
|
||||
Stats.tr => Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text("${f2.format(snapshot.data![index].tr)} TR", style: trailingStyle),
|
||||
Image.asset("res/tetrio_tl_alpha_ranks/${snapshot.data![index].rank}.png", height: 36)
|
||||
],
|
||||
),
|
||||
Stats.gp => Text("${intf.format(snapshot.data![index].getStatByEnum(stat))} ${chartsShortTitles[stat]}", style: trailingStyle),
|
||||
Stats.gw => Text("${intf.format(snapshot.data![index].getStatByEnum(stat))} ${chartsShortTitles[stat]}", style: trailingStyle),
|
||||
Stats.apm => Text("${f2.format(snapshot.data![index].getStatByEnum(stat))} ${chartsShortTitles[stat]}", style: trailingStyle),
|
||||
Stats.pps => Text("${f2.format(snapshot.data![index].getStatByEnum(stat))} ${chartsShortTitles[stat]}", style: trailingStyle),
|
||||
Stats.vs => Text("${f2.format(snapshot.data![index].getStatByEnum(stat))} ${chartsShortTitles[stat]}", style: trailingStyle),
|
||||
_ => Text("${f4.format(snapshot.data![index].getStatByEnum(stat))} ${chartsShortTitles[stat]}", style: trailingStyle)
|
||||
},
|
||||
Leaderboards.xp => Text("LVL ${f2.format(snapshot.data![index].level)}", style: trailingStyle),
|
||||
Leaderboards.ar => Text("${intf.format(snapshot.data![index].ar)} AR", style: trailingStyle),
|
||||
Leaderboards.sprint => Text(get40lTime(snapshot.data![index].stats.finalTime.inMicroseconds), style: trailingStyle),
|
||||
Leaderboards.blitz => Text(intf.format(snapshot.data![index].stats.score), style: trailingStyle),
|
||||
Leaderboards.zenith => Text("${f2.format(snapshot.data![index].stats.zenith!.altitude)} m", style: trailingStyle),
|
||||
Leaderboards.zenithex => Text("${f2.format(snapshot.data![index].stats.zenith!.altitude)} m", style: trailingStyle)
|
||||
},
|
||||
subtitle: width >= eukjsakjas ? Text(switch (_currentLb){
|
||||
Leaderboards.tl => "${f2.format(snapshot.data![index].apm)} APM, ${f2.format(snapshot.data![index].pps)} PPS, ${f2.format(snapshot.data![index].vs)} VS, ${f2.format(snapshot.data![index].nerdStats.app)} APP, ${f2.format(snapshot.data![index].nerdStats.vsapm)} VS/APM",
|
||||
Leaderboards.fullTL => switch (stat) {
|
||||
Stats.tr => "${f2.format(snapshot.data![index].apm)} APM, ${f2.format(snapshot.data![index].pps)} PPS, ${f2.format(snapshot.data![index].vs)} VS, ${f2.format(snapshot.data![index].nerdStats.app)} APP, ${f2.format(snapshot.data![index].nerdStats.vsapm)} VS/APM",
|
||||
_ => "${f2.format(snapshot.data![index].tr)} TR, ${snapshot.data![index].rank.toUpperCase()} rank"
|
||||
},
|
||||
Leaderboards.xp => "${f2.format(snapshot.data![index].xp)} XP${snapshot.data![index].playtime.isNegative ? "" : ", ${playtime(snapshot.data![index].playtime)} of gametime"}",
|
||||
Leaderboards.ar => "${snapshot.data![index].ar_counts}",
|
||||
Leaderboards.sprint => "${intf.format(snapshot.data![index].stats.finesse.faults)} FF, ${f2.format(snapshot.data![index].stats.kpp)} KPP, ${f2.format(snapshot.data![index].stats.kps)} KPS, ${f2.format(snapshot.data![index].stats.pps)} PPS, ${intf.format(snapshot.data![index].stats.piecesPlaced)} P",
|
||||
Leaderboards.blitz => "lvl ${snapshot.data![index].stats.level}, ${f2.format(snapshot.data![index].stats.pps)} PPS, ${f2.format(snapshot.data![index].stats.spp)} SPP",
|
||||
Leaderboards.zenith => "${f2.format(snapshot.data![index].aggregateStats.apm)} APM, ${f2.format(snapshot.data![index].aggregateStats.pps)} PPS, ${intf.format(snapshot.data![index].stats.kills)} KO's, ${f2.format(snapshot.data![index].stats.cps)} climb speed (${f2.format(snapshot.data![index].stats.zenith!.peakrank)} peak), ${intf.format(snapshot.data![index].stats.topBtB)} B2B",
|
||||
Leaderboards.zenithex => "${f2.format(snapshot.data![index].aggregateStats.apm)} APM, ${f2.format(snapshot.data![index].aggregateStats.pps)} PPS, ${intf.format(snapshot.data![index].stats.kills)} KO's, ${f2.format(snapshot.data![index].stats.cps)} climb speed (${f2.format(snapshot.data![index].stats.zenith!.peakrank)} peak), ${intf.format(snapshot.data![index].stats.topBtB)} B2B"
|
||||
}, style: TextStyle(color: Colors.grey, fontSize: 12)) : null,
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => UserView(searchFor: snapshot.data![index].userId),
|
||||
maintainState: false,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
if (snapshot.hasError){ return FutureError(snapshot); }
|
||||
}
|
||||
return Text("huh?");
|
||||
},
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 350.0,
|
||||
width: widget.constraints.maxWidth > transformThreshold ? 300.0 : widget.constraints.maxWidth,
|
||||
height: widget.constraints.maxHeight,
|
||||
child: Column(
|
||||
children: [
|
||||
|
@ -132,7 +342,7 @@ class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
|
|||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Spacer(),
|
||||
Text("Leaderboards", style: Theme.of(context).textTheme.headlineMedium),
|
||||
Text("Leaderboards", style: Theme.of(context).textTheme.headlineMedium!.copyWith(fontSize: 32)),
|
||||
Spacer()
|
||||
],
|
||||
),
|
||||
|
@ -147,6 +357,26 @@ class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
|
|||
trailing: Icon(Icons.arrow_right, color: _currentLb.index == index ? Colors.white : Colors.grey),
|
||||
subtitle: index == 1 ? Text("Heavy, but allows you to sort players by their stats and filter them by ranks", style: TextStyle(color: Colors.grey, fontSize: 12)) : null,
|
||||
onTap: () {
|
||||
if (widget.constraints.maxWidth <= transformThreshold) Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Scaffold(
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
|
||||
floatingActionButton: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 0.0),
|
||||
child: FloatingActionButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
tooltip: 'Fuck go back',
|
||||
child: const Icon(Icons.arrow_back),
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: rightSide(widget.constraints.maxWidth)
|
||||
)
|
||||
),
|
||||
maintainState: false,
|
||||
),
|
||||
);
|
||||
_currentLb = leaderboards.keys.elementAt(index);
|
||||
list.clear();
|
||||
prisecter = null;
|
||||
|
@ -161,208 +391,7 @@ class _DestinationLeaderboardsState extends State<DestinationLeaderboards> {
|
|||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: widget.constraints.maxWidth - 350 - 88,
|
||||
child: Card(
|
||||
child: StreamBuilder<List<dynamic>>(
|
||||
stream: dataStream,
|
||||
builder:(context, snapshot) {
|
||||
switch (snapshot.connectionState){
|
||||
case ConnectionState.none:
|
||||
case ConnectionState.waiting:
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
case ConnectionState.active:
|
||||
case ConnectionState.done:
|
||||
if (snapshot.hasData){
|
||||
return Column(
|
||||
children: [
|
||||
Text(leaderboards[_currentLb]!, style: Theme.of(context).textTheme.titleSmall),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
DropdownMenu(
|
||||
leadingIcon: Icon(Icons.public),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
isDense: true,
|
||||
),
|
||||
textStyle: TextStyle(fontSize: 14, height: 0.9),
|
||||
dropdownMenuEntries: _countries,
|
||||
initialSelection: "",
|
||||
onSelected: ((value) {
|
||||
_country = value as String?;
|
||||
list.clear();
|
||||
prisecter = null;
|
||||
_isFetchingData = false;
|
||||
_reachedTheEnd = false;
|
||||
setState((){_fetchData();});
|
||||
})
|
||||
),
|
||||
if (_currentLb == Leaderboards.fullTL) SizedBox(width: 5.0),
|
||||
if (_currentLb == Leaderboards.fullTL) DropdownMenu(
|
||||
leadingIcon: Icon(Icons.sort),
|
||||
inputDecorationTheme: InputDecorationTheme(
|
||||
isDense: true,
|
||||
),
|
||||
textStyle: TextStyle(fontSize: 14, height: 0.9),
|
||||
dropdownMenuEntries: _stats,
|
||||
initialSelection: stat,
|
||||
onSelected: ((value) {
|
||||
stat = value;
|
||||
list.clear();
|
||||
prisecter = null;
|
||||
_isFetchingData = false;
|
||||
_reachedTheEnd = false;
|
||||
setState((){_fetchData();});
|
||||
})
|
||||
),
|
||||
if (_currentLb == Leaderboards.fullTL) IconButton(
|
||||
color: _excludeRanks.isNotEmpty ? Theme.of(context).colorScheme.primary : null,
|
||||
onPressed: (){
|
||||
showDialog(context: context, builder: (BuildContext context) {
|
||||
return StatefulBuilder(
|
||||
builder: (context, StateSetter setAlertState) {
|
||||
return AlertDialog(
|
||||
title: Text("Filter", textAlign: TextAlign.center),
|
||||
content: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
CheckboxListTile(value: getTotalFilterValue(), tristate: true, title: Text("All", style: TextStyle(fontFamily: "Eurostile Round Extended")), onChanged: (value){
|
||||
setAlertState(
|
||||
(){
|
||||
if (_excludeRanks.length*2 > ranks.length){
|
||||
_excludeRanks.clear();
|
||||
}else{
|
||||
_excludeRanks = List.of(ranks);
|
||||
}
|
||||
}
|
||||
);
|
||||
}),
|
||||
for(String rank in ranks.reversed) CheckboxListTile(value: _excludeRanks.indexOf(rank) == -1, onChanged: (value){
|
||||
setAlertState(
|
||||
(){
|
||||
if (_excludeRanks.indexOf(rank) == -1){
|
||||
_excludeRanks.add(rank);
|
||||
}else{
|
||||
_excludeRanks.remove(rank);
|
||||
}
|
||||
}
|
||||
);
|
||||
}, title: Text(rank.toUpperCase()),)
|
||||
],
|
||||
),
|
||||
),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
child: const Text("Apply"),
|
||||
onPressed: () {Navigator.of(context).pop(); setState((){
|
||||
_currentLb = Leaderboards.fullTL;
|
||||
list.clear();
|
||||
prisecter = null;
|
||||
_fetchData();});
|
||||
}
|
||||
)
|
||||
]
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
}, icon: Icon(Icons.filter_alt)),
|
||||
if (_currentLb == Leaderboards.fullTL) IconButton(
|
||||
color: _reverse ? Theme.of(context).colorScheme.primary : null,
|
||||
icon: Transform.rotate(angle: _reverse ? pi : 0.0, child: Icon(Icons.filter_list)),
|
||||
onPressed: (){
|
||||
setState((){
|
||||
_reverse = !_reverse;
|
||||
_currentLb = Leaderboards.fullTL;
|
||||
list.clear();
|
||||
prisecter = null;
|
||||
_fetchData();
|
||||
});
|
||||
},
|
||||
)
|
||||
],
|
||||
),
|
||||
const Divider(),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
controller: _scrollController,
|
||||
itemCount: list.length,
|
||||
prototypeItem: ListTile(
|
||||
leading: Text("0"),
|
||||
title: Text("ehhh...", style: TextStyle(fontSize: 22)),
|
||||
trailing: SizedBox(height: 36, width: 1),
|
||||
subtitle: const Text("eh...", style: TextStyle(color: Colors.grey, fontSize: 12)),
|
||||
),
|
||||
itemBuilder: (BuildContext context, int index){
|
||||
return ListTile(
|
||||
leading: Text(intf.format(index+1)),
|
||||
title: Text(snapshot.data![index].username, style: TextStyle(fontSize: 22)),
|
||||
trailing: switch (_currentLb){
|
||||
Leaderboards.tl => Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text("${f2.format(snapshot.data![index].tr)} TR", style: trailingStyle),
|
||||
Image.asset("res/tetrio_tl_alpha_ranks/${snapshot.data![index].rank}.png", height: 36)
|
||||
],
|
||||
),
|
||||
Leaderboards.fullTL => switch (stat) {
|
||||
Stats.tr => Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text("${f2.format(snapshot.data![index].tr)} TR", style: trailingStyle),
|
||||
Image.asset("res/tetrio_tl_alpha_ranks/${snapshot.data![index].rank}.png", height: 36)
|
||||
],
|
||||
),
|
||||
Stats.gp => Text("${intf.format(snapshot.data![index].getStatByEnum(stat))} ${chartsShortTitles[stat]}", style: trailingStyle),
|
||||
Stats.gw => Text("${intf.format(snapshot.data![index].getStatByEnum(stat))} ${chartsShortTitles[stat]}", style: trailingStyle),
|
||||
Stats.apm => Text("${f2.format(snapshot.data![index].getStatByEnum(stat))} ${chartsShortTitles[stat]}", style: trailingStyle),
|
||||
Stats.pps => Text("${f2.format(snapshot.data![index].getStatByEnum(stat))} ${chartsShortTitles[stat]}", style: trailingStyle),
|
||||
Stats.vs => Text("${f2.format(snapshot.data![index].getStatByEnum(stat))} ${chartsShortTitles[stat]}", style: trailingStyle),
|
||||
_ => Text("${f4.format(snapshot.data![index].getStatByEnum(stat))} ${chartsShortTitles[stat]}", style: trailingStyle)
|
||||
},
|
||||
Leaderboards.xp => Text("LVL ${f2.format(snapshot.data![index].level)}", style: trailingStyle),
|
||||
Leaderboards.ar => Text("${intf.format(snapshot.data![index].ar)} AR", style: trailingStyle),
|
||||
Leaderboards.sprint => Text(get40lTime(snapshot.data![index].stats.finalTime.inMicroseconds), style: trailingStyle),
|
||||
Leaderboards.blitz => Text(intf.format(snapshot.data![index].stats.score), style: trailingStyle),
|
||||
Leaderboards.zenith => Text("${f2.format(snapshot.data![index].stats.zenith!.altitude)} m", style: trailingStyle),
|
||||
Leaderboards.zenithex => Text("${f2.format(snapshot.data![index].stats.zenith!.altitude)} m", style: trailingStyle)
|
||||
},
|
||||
subtitle: Text(switch (_currentLb){
|
||||
Leaderboards.tl => "${f2.format(snapshot.data![index].apm)} APM, ${f2.format(snapshot.data![index].pps)} PPS, ${f2.format(snapshot.data![index].vs)} VS, ${f2.format(snapshot.data![index].nerdStats.app)} APP, ${f2.format(snapshot.data![index].nerdStats.vsapm)} VS/APM",
|
||||
Leaderboards.fullTL => switch (stat) {
|
||||
Stats.tr => "${f2.format(snapshot.data![index].apm)} APM, ${f2.format(snapshot.data![index].pps)} PPS, ${f2.format(snapshot.data![index].vs)} VS, ${f2.format(snapshot.data![index].nerdStats.app)} APP, ${f2.format(snapshot.data![index].nerdStats.vsapm)} VS/APM",
|
||||
_ => "${f2.format(snapshot.data![index].tr)} TR, ${snapshot.data![index].rank.toUpperCase()} rank"
|
||||
},
|
||||
Leaderboards.xp => "${f2.format(snapshot.data![index].xp)} XP${snapshot.data![index].playtime.isNegative ? "" : ", ${playtime(snapshot.data![index].playtime)} of gametime"}",
|
||||
Leaderboards.ar => "${snapshot.data![index].ar_counts}",
|
||||
Leaderboards.sprint => "${intf.format(snapshot.data![index].stats.finesse.faults)} FF, ${f2.format(snapshot.data![index].stats.kpp)} KPP, ${f2.format(snapshot.data![index].stats.kps)} KPS, ${f2.format(snapshot.data![index].stats.pps)} PPS, ${intf.format(snapshot.data![index].stats.piecesPlaced)} P",
|
||||
Leaderboards.blitz => "lvl ${snapshot.data![index].stats.level}, ${f2.format(snapshot.data![index].stats.pps)} PPS, ${f2.format(snapshot.data![index].stats.spp)} SPP",
|
||||
Leaderboards.zenith => "${f2.format(snapshot.data![index].aggregateStats.apm)} APM, ${f2.format(snapshot.data![index].aggregateStats.pps)} PPS, ${intf.format(snapshot.data![index].stats.kills)} KO's, ${f2.format(snapshot.data![index].stats.cps)} climb speed (${f2.format(snapshot.data![index].stats.zenith!.peakrank)} peak), ${intf.format(snapshot.data![index].stats.topBtB)} B2B",
|
||||
Leaderboards.zenithex => "${f2.format(snapshot.data![index].aggregateStats.apm)} APM, ${f2.format(snapshot.data![index].aggregateStats.pps)} PPS, ${intf.format(snapshot.data![index].stats.kills)} KO's, ${f2.format(snapshot.data![index].stats.cps)} climb speed (${f2.format(snapshot.data![index].stats.zenith!.peakrank)} peak), ${intf.format(snapshot.data![index].stats.topBtB)} B2B"
|
||||
}, style: TextStyle(color: Colors.grey, fontSize: 12)),
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => UserView(searchFor: snapshot.data![index].userId),
|
||||
maintainState: false,
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
if (snapshot.hasError){ return FutureError(snapshot); }
|
||||
}
|
||||
return Text("huh?");
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
if (widget.constraints.maxWidth > transformThreshold) rightSide(widget.constraints.maxWidth - 300 - (widget.noSidebar ? 0 : 88)),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -58,6 +58,69 @@ class _DestinationSavedData extends State<DestinationSavedData> {
|
|||
);
|
||||
}
|
||||
|
||||
Widget rightSide(double width, bool hasSidebar){
|
||||
return SizedBox(
|
||||
width: width - (hasSidebar ? 80.0 : 0.00),
|
||||
child: selectedID != null ? FutureBuilder<(List<TetraLeague>, List<TetraLeague>, List<TetraLeagueAlphaRecord>)>(
|
||||
future: getDataAbout(selectedID!),
|
||||
builder: (context, snapshot) {
|
||||
switch(snapshot.connectionState){
|
||||
case ConnectionState.none:
|
||||
case ConnectionState.waiting:
|
||||
case ConnectionState.active:
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
case ConnectionState.done:
|
||||
if (snapshot.hasError){ return FutureError(snapshot); }
|
||||
if (snapshot.hasData){
|
||||
return DefaultTabController(
|
||||
length: 3,
|
||||
child: Card(
|
||||
child: Column(
|
||||
children: [
|
||||
Card(
|
||||
child: TabBar(
|
||||
labelStyle: Theme.of(context).textTheme.titleMedium!.copyWith(fontSize: 28),
|
||||
labelColor: Theme.of(context).colorScheme.primary,
|
||||
tabs: [
|
||||
Tab(text: "S${currentSeason} TL States"),
|
||||
Tab(text: "S1 TL States"),
|
||||
Tab(text: "TL Records")
|
||||
]),
|
||||
),
|
||||
SizedBox(
|
||||
height: widget.constraints.maxHeight - 64,
|
||||
child: TabBarView(children: [
|
||||
ListView.builder(
|
||||
itemCount: snapshot.data!.$1.length,
|
||||
itemBuilder: (context, index) {
|
||||
return getTetraLeagueListTile(snapshot.data!.$1[index]);
|
||||
},),
|
||||
ListView.builder(
|
||||
itemCount: snapshot.data!.$2.length,
|
||||
itemBuilder: (context, index) {
|
||||
return getTetraLeagueListTile(snapshot.data!.$2[index]);
|
||||
},),
|
||||
ListView.builder(
|
||||
itemCount: snapshot.data!.$3.length,
|
||||
itemBuilder: (context, index) {
|
||||
return AlphaLeagueEntryThingy(snapshot.data!.$3[index], selectedID!);
|
||||
},),
|
||||
]
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Text("what?");
|
||||
}
|
||||
}
|
||||
) :
|
||||
InfoThingy("Select nickname on the left to see data assosiated with it")
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return FutureBuilder<Map<String, String>>(
|
||||
|
@ -74,7 +137,7 @@ class _DestinationSavedData extends State<DestinationSavedData> {
|
|||
return Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 450,
|
||||
width: widget.constraints.maxWidth > 900.0 ? 350 : widget.constraints.maxWidth - (widget.constraints.maxWidth <= 768.0 ? 0 : 80),
|
||||
child: Column(
|
||||
children: [
|
||||
Card(
|
||||
|
@ -93,72 +156,33 @@ class _DestinationSavedData extends State<DestinationSavedData> {
|
|||
//subtitle: Text("NaN states, NaN TL records", style: TextStyle(color: Colors.grey)),
|
||||
onTap: () => setState(() {
|
||||
selectedID = id;
|
||||
if (widget.constraints.maxWidth <= 900.0) Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Scaffold(
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
|
||||
floatingActionButton: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 0.0),
|
||||
child: FloatingActionButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
tooltip: 'Fuck go back',
|
||||
child: const Icon(Icons.arrow_back),
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: rightSide(widget.constraints.maxWidth, false)
|
||||
)
|
||||
),
|
||||
maintainState: false,
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: widget.constraints.maxWidth - 450 - 80,
|
||||
child: selectedID != null ? FutureBuilder<(List<TetraLeague>, List<TetraLeague>, List<TetraLeagueAlphaRecord>)>(
|
||||
future: getDataAbout(selectedID!),
|
||||
builder: (context, snapshot) {
|
||||
switch(snapshot.connectionState){
|
||||
case ConnectionState.none:
|
||||
case ConnectionState.waiting:
|
||||
case ConnectionState.active:
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
case ConnectionState.done:
|
||||
if (snapshot.hasError){ return FutureError(snapshot); }
|
||||
if (snapshot.hasData){
|
||||
return DefaultTabController(
|
||||
length: 3,
|
||||
child: Card(
|
||||
child: Column(
|
||||
children: [
|
||||
Card(
|
||||
child: TabBar(
|
||||
labelStyle: Theme.of(context).textTheme.titleMedium!.copyWith(fontSize: 28),
|
||||
labelColor: Theme.of(context).colorScheme.primary,
|
||||
tabs: [
|
||||
Tab(text: "S${currentSeason} TL States"),
|
||||
Tab(text: "S1 TL States"),
|
||||
Tab(text: "TL Records")
|
||||
]),
|
||||
),
|
||||
SizedBox(
|
||||
height: widget.constraints.maxHeight - 64,
|
||||
child: TabBarView(children: [
|
||||
ListView.builder(
|
||||
itemCount: snapshot.data!.$1.length,
|
||||
itemBuilder: (context, index) {
|
||||
return getTetraLeagueListTile(snapshot.data!.$1[index]);
|
||||
},),
|
||||
ListView.builder(
|
||||
itemCount: snapshot.data!.$2.length,
|
||||
itemBuilder: (context, index) {
|
||||
return getTetraLeagueListTile(snapshot.data!.$2[index]);
|
||||
},),
|
||||
ListView.builder(
|
||||
itemCount: snapshot.data!.$3.length,
|
||||
itemBuilder: (context, index) {
|
||||
return AlphaLeagueEntryThingy(snapshot.data!.$3[index], selectedID!);
|
||||
},),
|
||||
]
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
return Text("what?");
|
||||
}
|
||||
}
|
||||
) :
|
||||
InfoThingy("Select nickname on the left to see data assosiated with it")
|
||||
)
|
||||
if (widget.constraints.maxWidth > 900.0) rightSide(widget.constraints.maxWidth - 350, true)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -607,6 +607,19 @@ class _DestinationSettings extends State<DestinationSettings> with SingleTickerP
|
|||
);
|
||||
}
|
||||
|
||||
Widget rightSide(double width, bool hasSidebar){
|
||||
return SizedBox(
|
||||
width: width - (hasSidebar ? 80 : 0),
|
||||
child: SingleChildScrollView(
|
||||
child: switch (mod){
|
||||
SettingsCardMod.general => getGeneralSettings(),
|
||||
SettingsCardMod.customization => getCustomizationSettings(),
|
||||
SettingsCardMod.database => getDatabaseSettings(),
|
||||
},
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final t = Translations.of(context);
|
||||
|
@ -618,7 +631,7 @@ class _DestinationSettings extends State<DestinationSettings> with SingleTickerP
|
|||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
SizedBox(
|
||||
width: 450,
|
||||
width: widget.constraints.maxWidth > 900.0 ? 350 : widget.constraints.maxWidth - (widget.constraints.maxWidth <= 768.0 ? 0 : 80),
|
||||
child: Column(
|
||||
children: [
|
||||
Card(
|
||||
|
@ -639,22 +652,33 @@ class _DestinationSettings extends State<DestinationSettings> with SingleTickerP
|
|||
setState(() {
|
||||
mod = m;
|
||||
});
|
||||
if (widget.constraints.maxWidth <= 900.0) Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => Scaffold(
|
||||
floatingActionButtonLocation: FloatingActionButtonLocation.endFloat,
|
||||
floatingActionButton: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(0.0, 12.0, 0.0, 0.0),
|
||||
child: FloatingActionButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
tooltip: 'Fuck go back',
|
||||
child: const Icon(Icons.arrow_back),
|
||||
),
|
||||
),
|
||||
body: SafeArea(
|
||||
child: rightSide(widget.constraints.maxWidth, false)
|
||||
)
|
||||
),
|
||||
maintainState: false,
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: widget.constraints.maxWidth - 450 - 80,
|
||||
child: SingleChildScrollView(
|
||||
child: switch (mod){
|
||||
SettingsCardMod.general => getGeneralSettings(),
|
||||
SettingsCardMod.customization => getCustomizationSettings(),
|
||||
SettingsCardMod.database => getDatabaseSettings(),
|
||||
},
|
||||
)
|
||||
)
|
||||
if (widget.constraints.maxWidth > 900.0) rightSide(widget.constraints.maxWidth - 350, true)
|
||||
],
|
||||
);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,10 @@ late Future<FetchResults> _data;
|
|||
TetrioPlayersLeaderboard? _everyone;
|
||||
int destination = 0;
|
||||
|
||||
// TODO: Redesign some widgets, so they could look nice on mobile view
|
||||
// - stats below TL progress bar & similar parts in other widgets
|
||||
// - APP and VS/APM gadget
|
||||
|
||||
Future<FetchResults> getData(String searchFor) async {
|
||||
TetrioPlayer player;
|
||||
try{
|
||||
|
@ -160,6 +164,102 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
);
|
||||
}
|
||||
|
||||
Widget pickers(int destination){
|
||||
return switch (destination) {
|
||||
0 => Column(
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: SegmentedButton<CardMod>(
|
||||
showSelectedIcon: false,
|
||||
selected: <CardMod>{cardMod},
|
||||
segments: modeButtons[rightCard]!,
|
||||
onSelectionChanged: (p0) {
|
||||
setState(() {
|
||||
cardMod = p0.first;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
SegmentedButton<Cards>(
|
||||
showSelectedIcon: false,
|
||||
segments: <ButtonSegment<Cards>>[
|
||||
const ButtonSegment<Cards>(
|
||||
value: Cards.overview,
|
||||
tooltip: 'Overview',
|
||||
icon: Icon(Icons.calendar_view_day)),
|
||||
ButtonSegment<Cards>(
|
||||
value: Cards.tetraLeague,
|
||||
tooltip: 'Tetra League',
|
||||
icon: SvgPicture.asset("res/icons/league.svg", height: 16, colorFilter: ColorFilter.mode(theme.colorScheme.primary, BlendMode.modulate))),
|
||||
ButtonSegment<Cards>(
|
||||
value: Cards.quickPlay,
|
||||
tooltip: 'Quick Play',
|
||||
icon: SvgPicture.asset("res/icons/qp.svg", height: 16, colorFilter: ColorFilter.mode(theme.colorScheme.primary, BlendMode.modulate))),
|
||||
ButtonSegment<Cards>(
|
||||
value: Cards.sprint,
|
||||
tooltip: '40 Lines',
|
||||
icon: SvgPicture.asset("res/icons/40l.svg", height: 16, colorFilter: ColorFilter.mode(theme.colorScheme.primary, BlendMode.modulate))),
|
||||
ButtonSegment<Cards>(
|
||||
value: Cards.blitz,
|
||||
tooltip: 'Blitz',
|
||||
icon: SvgPicture.asset("res/icons/blitz.svg", height: 16, colorFilter: ColorFilter.mode(theme.colorScheme.primary, BlendMode.modulate))),
|
||||
],
|
||||
selected: <Cards>{rightCard},
|
||||
onSelectionChanged: (Set<Cards> newSelection) {
|
||||
setState(() {
|
||||
cardMod = CardMod.info;
|
||||
rightCard = newSelection.first;
|
||||
});})
|
||||
],
|
||||
),
|
||||
1 => SegmentedButton<Graph>(
|
||||
showSelectedIcon: false,
|
||||
segments: <ButtonSegment<Graph>>[
|
||||
const ButtonSegment<Graph>(
|
||||
value: Graph.history,
|
||||
label: Text('Player History')),
|
||||
ButtonSegment<Graph>(
|
||||
value: Graph.leagueState,
|
||||
label: Text('League State')),
|
||||
ButtonSegment<Graph>(
|
||||
value: Graph.leagueCutoffs,
|
||||
label: Text('League Cutoffs'),
|
||||
),
|
||||
],
|
||||
selected: <Graph>{graph},
|
||||
onSelectionChanged: (Set<Graph> newSelection) {
|
||||
setState(() {
|
||||
graph = newSelection.first;
|
||||
switch (newSelection.first){
|
||||
case Graph.leagueCutoffs:
|
||||
case Graph.history:
|
||||
Ychart = Stats.tr;
|
||||
case Graph.leagueState:
|
||||
Ychart = Stats.apm;
|
||||
}
|
||||
});}),
|
||||
4 => SegmentedButton<CalcCards>(
|
||||
showSelectedIcon: false,
|
||||
segments: <ButtonSegment<CalcCards>>[
|
||||
const ButtonSegment<CalcCards>(
|
||||
value: CalcCards.calc,
|
||||
label: Text('Stats Calculator'),
|
||||
),
|
||||
ButtonSegment<CalcCards>(
|
||||
value: CalcCards.damage,
|
||||
label: Text('Damage Calculator'),
|
||||
),
|
||||
],
|
||||
selected: <CalcCards>{calcCard},
|
||||
onSelectionChanged: (Set<CalcCards> newSelection) {
|
||||
setState(() {
|
||||
calcCard = newSelection.first;
|
||||
});}),
|
||||
_ => Container()
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LayoutBuilder(
|
||||
|
@ -185,58 +285,10 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
},
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: SegmentedButton<CardMod>(
|
||||
showSelectedIcon: false,
|
||||
selected: <CardMod>{cardMod},
|
||||
segments: modeButtons[rightCard]!,
|
||||
onSelectionChanged: (p0) {
|
||||
setState(() {
|
||||
cardMod = p0.first;
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
SegmentedButton<Cards>(
|
||||
showSelectedIcon: false,
|
||||
segments: <ButtonSegment<Cards>>[
|
||||
const ButtonSegment<Cards>(
|
||||
value: Cards.overview,
|
||||
tooltip: 'Overview',
|
||||
icon: Icon(Icons.calendar_view_day)),
|
||||
ButtonSegment<Cards>(
|
||||
value: Cards.tetraLeague,
|
||||
tooltip: 'Tetra League',
|
||||
icon: SvgPicture.asset("res/icons/league.svg", height: 16, colorFilter: ColorFilter.mode(theme.colorScheme.primary, BlendMode.modulate))),
|
||||
ButtonSegment<Cards>(
|
||||
value: Cards.quickPlay,
|
||||
tooltip: 'Quick Play',
|
||||
icon: SvgPicture.asset("res/icons/qp.svg", height: 16, colorFilter: ColorFilter.mode(theme.colorScheme.primary, BlendMode.modulate))),
|
||||
ButtonSegment<Cards>(
|
||||
value: Cards.sprint,
|
||||
tooltip: '40 Lines',
|
||||
icon: SvgPicture.asset("res/icons/40l.svg", height: 16, colorFilter: ColorFilter.mode(theme.colorScheme.primary, BlendMode.modulate))),
|
||||
ButtonSegment<Cards>(
|
||||
value: Cards.blitz,
|
||||
tooltip: 'Blitz',
|
||||
icon: SvgPicture.asset("res/icons/blitz.svg", height: 16, colorFilter: ColorFilter.mode(theme.colorScheme.primary, BlendMode.modulate))),
|
||||
],
|
||||
selected: <Cards>{rightCard},
|
||||
onSelectionChanged: (Set<Cards> newSelection) {
|
||||
setState(() {
|
||||
cardMod = CardMod.info;
|
||||
rightCard = newSelection.first;
|
||||
});})
|
||||
],
|
||||
),
|
||||
child: pickers(destination),
|
||||
),
|
||||
IconButton(
|
||||
tooltip: 'Fake "Open navigation menu" button\nHere only for symmetry',
|
||||
icon: const Icon(Icons.menu, color: Colors.transparent),
|
||||
onPressed: () {},
|
||||
SizedBox(
|
||||
width: 40.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -259,7 +311,7 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
leading: FloatingActionButton(
|
||||
elevation: 0,
|
||||
onPressed: () {
|
||||
Scaffold.of(context).openDrawer();
|
||||
_scaffoldKey.currentState!.openDrawer();
|
||||
},
|
||||
child: const Icon(Icons.search),
|
||||
),
|
||||
|
@ -300,8 +352,8 @@ class _MainState extends State<MainView> with TickerProviderStateMixin {
|
|||
Expanded(
|
||||
child: switch (destination){
|
||||
0 => DestinationHome(searchFor: _searchFor, constraints: constraints, dataFuture: _data, noSidebar: !screenIsBig),
|
||||
1 => DestinationGraphs(searchFor: _searchFor, constraints: constraints),
|
||||
2 => DestinationLeaderboards(constraints: constraints),
|
||||
1 => DestinationGraphs(searchFor: _searchFor, constraints: constraints, noSidebar: !screenIsBig),
|
||||
2 => DestinationLeaderboards(constraints: constraints, noSidebar: !screenIsBig),
|
||||
3 => DestinationCutoffs(constraints: constraints),
|
||||
4 => DestinationCalculator(constraints: constraints),
|
||||
5 => DestinationInfo(constraints: constraints),
|
||||
|
|
|
@ -84,7 +84,7 @@
|
|||
"comparingWith": "Data from ${newDate} comparing with ${oldDate}",
|
||||
"top": "Top",
|
||||
"topRank": "Top rank",
|
||||
"verdictGeneral": "$n $verdict than $rank rank average",
|
||||
"verdictGeneral": "$n $verdict $rank rank avg",
|
||||
"verdictBetter": "better",
|
||||
"verdictWorse": "worse",
|
||||
"smooth": "Smooth",
|
||||
|
|
Loading…
Reference in New Issue