diff --git a/lib/data_objects/freyhoe_test.dart b/lib/data_objects/freyhoe_test.dart index 6b74a6b..6794458 100644 --- a/lib/data_objects/freyhoe_test.dart +++ b/lib/data_objects/freyhoe_test.dart @@ -123,6 +123,7 @@ // } // bool wasATSpin(Tetromino type, Coords coords, int rot){ +// if (type != Tetromino.T) return false; // if (!(positionIsValid(type, Coords(coords.x+1, coords.y), rot) || // positionIsValid(type, Coords(coords.x-1, coords.y), rot) || // positionIsValid(type, Coords(coords.x, coords.y+1), rot) || @@ -200,10 +201,6 @@ // int attackTanked = 0; // LineClearResult processLineClear(List clearFullLinesResult, Tetromino current, Coords pos, bool spinWasLastMove, bool tspin){ -// if (clearFullLinesResult[0] > 0) combo++; -// else combo = -1; -// if (clearFullLinesResult[2] > 0) btb++; -// else btb = -1; // int attack = 0; // switch (clearFullLinesResult[0]){ // case 0: @@ -215,7 +212,8 @@ // if (spinWasLastMove && tspin) { // attack = garbage['t-spin single']!; // }else{ -// attack = garbage['single']!; +// if (combo == -1) attack = garbage['single']!; +// else attack = comboTable[combo]; // } // break; // case 2: @@ -250,6 +248,10 @@ // developer.log("${clearFullLinesResult[0]} lines cleared"); // break; // } +// if (clearFullLinesResult[0] > 0) combo++; +// else combo = -1; +// if (clearFullLinesResult[2] > 0) btb++; +// else btb = -1; // return LineClearResult(clearFullLinesResult[0], Tetromino.empty, false, clearFullLinesResult[1], 0, attack); // } // } @@ -269,7 +271,7 @@ // List events = readEventList(replay.rawJson); // DataFullOptions? settings; // HandlingHandler? handling; -// Map activeKeypresses = {}; +// //Map activeKeypresses = {}; // int currentFrame = 0; // double subframesWent = 0; // events.removeAt(0); // get rig of Event.start @@ -278,6 +280,7 @@ // Board board = Board(10, 20, 20); // KicksetBase kickset = SRSPlus(); // List garbageQueue = []; +// List outcomingGarbage = []; // Tetromino? hold; // int rot = 0; // bool spinWasLastMove = false; @@ -287,9 +290,9 @@ // bool floored = false; // double gravityBucket = 1.0; -// developer.log("Seed is ${replay.stats[0][0].seed}, first bag is $queue"); +// //developer.log("Seed is ${replay.stats[0][0].seed}, first bag is $queue"); // Tetromino current = queue.removeAt(0); -// //developer.log("Second bag is ${rng.shuffleList(tetrominoes)}"); +// //developer.log("Handling is "); // int sonicDrop(){ // int height = coords.y; @@ -333,12 +336,13 @@ // board.writeToBoard(current, coords, rot); // bool tspin = board.wasATSpin(current, coords, rot); // LineClearResult lineClear = stats.processLineClear(board.clearFullLines(), current, coords, spinWasLastMove, tspin); -// print("${lineClear.linesCleared} lines, ${lineClear.garbageCleared} garbage"); +// //if (lineClear.attackProduced > 0) outcomingGarbage.add(GarbageData()); +// //print("${lineClear.linesCleared} lines, ${lineClear.garbageCleared} garbage"); // if (garbageQueue.isNotEmpty) { // if (lineClear.linesCleared > 0){ // int garbageToDelete = lineClear.attackProduced; // for (IncomingGarbage garbage in garbageQueue){ -// if (garbage.data.amt! >= garbageToDelete) { +// if (garbage.data.amt! < garbageToDelete) { // garbageToDelete -= garbage.data.amt!; // lineClear.attackProduced = garbageToDelete; // garbage.data.amt = 0; @@ -367,11 +371,17 @@ // } // current = getNewOne(); // coords = Coords(3, 21) + spawnPositionFixes[current.index]; +// print("${lineClear.linesCleared} lines, ${lineClear.attackProduced} atk, ${lineClear.spin}, combo ${stats.combo}, btb ${stats.btb}"); // } // void handleGravity(double frames){ // if (frames == 0) return; -// gravityBucket += settings != null ? (handling!.sdfActive ? max(settings.g! * settings.handling!.sdf, 0.05 * settings.handling!.sdf) : settings.g!) * frames : 0; +// gravityBucket += settings != null ? +// (handling!.sdfActive ? +// max(settings.g! * settings.handling!.sdf, 0.05 * settings.handling!.sdf) : +// settings.g! +// ) * frames +// : 0; // int gravityImpact = 0; // if (gravityBucket >= 1.0){ // gravityImpact = gravityBucket.truncate(); @@ -404,17 +414,17 @@ // subframesWent = 0; // if (settings?.handling?.sdf == 41) coords.y = sonicDrop(); -// print("$currentFrame: $current at $coords\n$board"); // //print(stats.combo); // if (currentFrame == nextEvent.frame){ // while (currentFrame == nextEvent.frame){ -// print("Processing $nextEvent"); +// //print("Processing $nextEvent"); // switch (nextEvent.type){ // case EventType.start: // developer.log("go"); // break; // case EventType.full: // settings = (nextEvent as EventFull).data.options; +// developer.log("SDF is ${settings?.handling?.sdf}, replay version is ${settings?.version}"); // handling = HandlingHandler(settings!.handling!.das.toDouble(), settings.handling!.arr.toDouble()); // lockDelay = settings.locktime!.toDouble(); // lockResets = settings.lockresets!; @@ -446,6 +456,7 @@ // break; // case KeyType.hardDrop: // coords.y = sonicDrop(); +// print("$currentFrame: $current at $coords, garbage queue $garbageQueue\n$board"); // handleHardDrop(); // case KeyType.hold: // switch (hold){ @@ -513,7 +524,7 @@ // case KeyType.retry: // // TODO: Handle this case. // } -// activeKeypresses.remove(nextEvent.data.key); +// //activeKeypresses.remove(nextEvent.data.key); // break; // case EventType.end: // currentFrame = replay.roundLengths[0]+1; diff --git a/lib/data_objects/tetrio.dart b/lib/data_objects/tetrio.dart index 8ff586c..45ab41d 100644 --- a/lib/data_objects/tetrio.dart +++ b/lib/data_objects/tetrio.dart @@ -60,6 +60,7 @@ const Map rankTargets = { "d+": 606, "d": 0, }; +DateTime seasonEnd = DateTime.utc(2024, 07, 26, 15); enum Stats { tr, glicko, diff --git a/lib/utils/relative_timestamps.dart b/lib/utils/relative_timestamps.dart index 0e9260f..833c33e 100644 --- a/lib/utils/relative_timestamps.dart +++ b/lib/utils/relative_timestamps.dart @@ -3,6 +3,7 @@ import 'package:tetra_stats/gen/strings.g.dart'; import 'package:tetra_stats/utils/numers_formats.dart'; final NumberFormat secs = NumberFormat("00.###", LocaleSettings.currentLocale.languageCode); +final NumberFormat nonsecs = NumberFormat("00.###", LocaleSettings.currentLocale.languageCode); final NumberFormat _timeInSec = NumberFormat("#,###.###s.", LocaleSettings.currentLocale.languageCode); /// Returns string, that represents time difference between [dateTime] and now @@ -73,4 +74,8 @@ String readableTimeDifference(Duration a, Duration b){ Duration result = a - b; return NumberFormat("0.000s;0.000s", LocaleSettings.currentLocale.languageCode).format(result.inMilliseconds/1000); +} + +String countdown(Duration difference){ + return "${difference.inDays}:${nonsecs.format(difference.inHours%24)}:${nonsecs.format(difference.inMinutes%60)}:${secs.format(difference.inSeconds%60)}"; } \ No newline at end of file diff --git a/lib/views/main_view.dart b/lib/views/main_view.dart index 14ab269..d5a0d95 100644 --- a/lib/views/main_view.dart +++ b/lib/views/main_view.dart @@ -1013,7 +1013,6 @@ class _TwoRecordsThingy extends StatelessWidget { @override Widget build(BuildContext context) { - //if (record == null) return Center(child: Text(t.noRecord, textAlign: TextAlign.center, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28))); late MapEntry closestAverageBlitz; late bool blitzBetterThanClosestAverage; bool? blitzBetterThanRankAverage = (rank != null && rank != "z" && blitz != null) ? blitz!.endContext.score > blitzAverages[rank]! : null; @@ -1186,13 +1185,13 @@ class _TwoRecordsThingy extends StatelessWidget { mainAxisSize: MainAxisSize.min, children: [ for (int i = 1; i < blitzStream.records.length; i++) ListTile( - onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => SingleplayerRecordView(record: blitzStream.records[i]))), - leading: Text("#${i+1}", style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28, shadows: textShadow, height: 0.9) ), - title: Text("${NumberFormat.decimalPattern().format(blitzStream.records[i].endContext.score)} points", - style: const TextStyle(fontSize: 18)), - subtitle: Text(timestamp(blitzStream.records[i].timestamp), style: const TextStyle(color: Colors.grey, height: 0.85)), - trailing: SpTrailingStats(blitzStream.records[i].endContext) - ) + onTap: () => Navigator.push(context, MaterialPageRoute(builder: (context) => SingleplayerRecordView(record: blitzStream.records[i]))), + leading: Text("#${i+1}", style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28, shadows: textShadow, height: 0.9) ), + title: Text("${NumberFormat.decimalPattern().format(blitzStream.records[i].endContext.score)} points", + style: const TextStyle(fontSize: 18)), + subtitle: Text(timestamp(blitzStream.records[i].timestamp), style: const TextStyle(color: Colors.grey, height: 0.85)), + trailing: SpTrailingStats(blitzStream.records[i].endContext) + ) ], ), ) diff --git a/lib/widgets/tl_rating_thingy.dart b/lib/widgets/tl_rating_thingy.dart index f5c3e7e..0ebaecb 100644 --- a/lib/widgets/tl_rating_thingy.dart +++ b/lib/widgets/tl_rating_thingy.dart @@ -8,7 +8,6 @@ import 'package:tetra_stats/main.dart' show prefs; import 'package:tetra_stats/utils/numers_formats.dart'; var fDiff = NumberFormat("+#,###.####;-#,###.####"); -DateTime seasonEnd = DateTime.utc(2024, 07, 26); class TLRatingThingy extends StatelessWidget{ final String userID; @@ -30,7 +29,6 @@ class TLRatingThingy extends StatelessWidget{ DateTime now = DateTime.now(); bool beforeS1end = now.isBefore(seasonEnd); int daysLeft = seasonEnd.difference(now).inDays; - print(max(0, 7 - (lastMatchPlayed != null ? now.difference(lastMatchPlayed!).inDays : 7))); int safeRD = min(100, (100 + ((tlData.rd! >= 100 && tlData.decaying) ? 7 : max(0, 7 - (lastMatchPlayed != null ? now.difference(lastMatchPlayed!).inDays : 7))) - daysLeft).toInt()); return Wrap( direction: Axis.horizontal, diff --git a/lib/widgets/tl_thingy.dart b/lib/widgets/tl_thingy.dart index 95ffe97..a1016b9 100644 --- a/lib/widgets/tl_thingy.dart +++ b/lib/widgets/tl_thingy.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:tetra_stats/data_objects/tetrio.dart'; @@ -5,6 +7,7 @@ import 'package:syncfusion_flutter_gauges/gauges.dart'; import 'package:tetra_stats/gen/strings.g.dart'; import 'package:tetra_stats/utils/colors_functions.dart'; import 'package:tetra_stats/utils/numers_formats.dart'; +import 'package:tetra_stats/utils/relative_timestamps.dart'; import 'package:tetra_stats/widgets/gauget_num.dart'; import 'package:tetra_stats/widgets/graphs.dart'; import 'package:tetra_stats/widgets/stat_sell_num.dart'; @@ -38,12 +41,14 @@ class TLThingy extends StatefulWidget { State createState() => _TLThingyState(); } -class _TLThingyState extends State { +class _TLThingyState extends State with TickerProviderStateMixin { late bool oskKagariGimmick; late TetraLeagueAlpha? oldTl; late TetraLeagueAlpha currentTl; late RangeValues _currentRangeValues; late List sortedStates; + late Timer _countdownTimer; + Duration seasonLeft = seasonEnd.difference(DateTime.now()); @override void initState() { @@ -52,8 +57,23 @@ class _TLThingyState extends State { oldTl = sortedStates.elementAtOrNull(1)?.tlSeason1; currentTl = widget.tl; super.initState(); + _countdownTimer = Timer.periodic( + Durations.extralong4, + (Timer timer) { + setState(() { + seasonLeft = seasonEnd.difference(DateTime.now()); + }); + }, + ); } + @override + void dispose() { + _countdownTimer.cancel(); + super.dispose(); + } + + @override Widget build(BuildContext context) { final t = Translations.of(context); @@ -70,6 +90,8 @@ class _TLThingyState extends State { return Column( children: [ if (widget.showTitle) Text(t.tetraLeague, style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 42 : 28)), + if (DateTime.now().isBefore(seasonEnd)) Text("Season ends in ${countdown(seasonLeft)}") + else Text("Season has ended"), if (oldTl != null) Text(t.comparingWith(newDate: timestamp(currentTl.timestamp), oldDate: timestamp(oldTl!.timestamp)), textAlign: TextAlign.center,), if (oldTl != null) RangeSlider(values: _currentRangeValues, max: widget.states.length.toDouble(), diff --git a/pubspec.yaml b/pubspec.yaml index 2007d63..023ea82 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: tetra_stats description: Track your and other player stats in TETR.IO publish_to: 'none' -version: 1.6.1+21 +version: 1.6.2+22 environment: sdk: '>=3.0.0' diff --git a/web/index.html b/web/index.html index 5626d5d..66c6956 100644 --- a/web/index.html +++ b/web/index.html @@ -152,12 +152,18 @@ // Promoting Tetra Stats "native" "Want a better perfomance?
Try out Tetra Stats \"Native\"", "Imagine a world, where Tetra Stats was written in JS", + "Did you know, that Flutter for web sucks?", "Welcome to fullscreen canvas", // An actual tips "You can interact with most objects that have an accent color", "Like Sheetbot graphs? Go to three dots menu → Settings → Customization", - "Click and hold on line chart graph, then start dragging to zoom in" + "Click and hold on line chart graph, then start dragging to zoom in", + "Discord userID ≠ Discord username. It should look like a bunch of digits", + + // :droidsmile: + "Is she real?", + "Check out wiki for more information" ]; tip.innerHTML = tips[Math.floor(Math.random() * tips.length)]; try{