diff --git a/lib/data_objects/freyhoe_test.dart b/lib/data_objects/freyhoe_test.dart index e92fd96..6b74a6b 100644 --- a/lib/data_objects/freyhoe_test.dart +++ b/lib/data_objects/freyhoe_test.dart @@ -1,551 +1,551 @@ -import 'dart:convert'; -import 'dart:developer' as developer; -import 'dart:ffi'; -import 'dart:math'; -import 'package:logging/logging.dart' as logging; -import 'package:vector_math/vector_math_64.dart'; -import 'dart:io'; -import 'tetrio_multiplayer_replay.dart'; +// import 'dart:convert'; +// import 'dart:developer' as developer; +// import 'dart:ffi'; +// import 'dart:math'; +// import 'package:logging/logging.dart' as logging; +// import 'package:vector_math/vector_math_64.dart'; +// import 'dart:io'; +// import 'tetrio_multiplayer_replay.dart'; -class HandlingHandler{ - double das; - double arr; - late double dasLeft; // frames - late double arrLeft; // frames - bool sdfActive = false; - bool activeLeft = false; - bool activeRight = false; - int direction = 0; // -1 - left, 1 - right, 0 - none +// class HandlingHandler{ +// double das; +// double arr; +// late double dasLeft; // frames +// late double arrLeft; // frames +// bool sdfActive = false; +// bool activeLeft = false; +// bool activeRight = false; +// int direction = 0; // -1 - left, 1 - right, 0 - none - HandlingHandler(this.das, this.arr){ - dasLeft = das; - arrLeft = arr; - } +// HandlingHandler(this.das, this.arr){ +// dasLeft = das; +// arrLeft = arr; +// } - @override - String toString(){ - return "das: ${das}f; arr: ${arr}f"; - } +// @override +// String toString(){ +// return "das: ${das}f; arr: ${arr}f"; +// } - int movementKeyPressed(bool left, bool right, double subframe){ - if (left) { - activeLeft = left; - direction = -1; - } - if (right) { - activeRight = right; - direction = 1; - } - dasLeft = das - (1 - subframe); - return direction; - } +// int movementKeyPressed(bool left, bool right, double subframe){ +// if (left) { +// activeLeft = left; +// direction = -1; +// } +// if (right) { +// activeRight = right; +// direction = 1; +// } +// dasLeft = das - (1 - subframe); +// return direction; +// } - void movementKeyReleased(bool left, bool right, double subframe){ - if (left) { - activeLeft = !left; - } - if (right) { - activeRight = !right; - } - if (activeLeft) { - direction = -1; - } - if (activeRight) { - direction = 1; - } - if (activeLeft && activeRight){ - arrLeft = arr; - dasLeft = das; - direction = 0; - } - } +// void movementKeyReleased(bool left, bool right, double subframe){ +// if (left) { +// activeLeft = !left; +// } +// if (right) { +// activeRight = !right; +// } +// if (activeLeft) { +// direction = -1; +// } +// if (activeRight) { +// direction = 1; +// } +// if (activeLeft && activeRight){ +// arrLeft = arr; +// dasLeft = das; +// direction = 0; +// } +// } - int processMovenent(double delta){ - if (!activeLeft && !activeRight) return 0; - if (dasLeft > 0.0) { - dasLeft -= delta; - if (dasLeft < 0.0) { - arrLeft += dasLeft; - dasLeft = 0.0; - return direction; - }else{ - return 0; - } - }else{ - arrLeft -= delta; - if (arr == 0.0) return direction*10; - if (arrLeft < 0.0) { - arrLeft += arr; - return direction; - }else { - return 0; - } - } - } -} +// int processMovenent(double delta){ +// if (!activeLeft && !activeRight) return 0; +// if (dasLeft > 0.0) { +// dasLeft -= delta; +// if (dasLeft < 0.0) { +// arrLeft += dasLeft; +// dasLeft = 0.0; +// return direction; +// }else{ +// return 0; +// } +// }else{ +// arrLeft -= delta; +// if (arr == 0.0) return direction*10; +// if (arrLeft < 0.0) { +// arrLeft += arr; +// return direction; +// }else { +// return 0; +// } +// } +// } +// } -class Board{ - int width; - int height; - int bufferHeight; - late List> board; - late int totalHeight; +// class Board{ +// int width; +// int height; +// int bufferHeight; +// late List> board; +// late int totalHeight; - Board(this.width, this.height, this.bufferHeight){ - totalHeight = height+bufferHeight; - board = [for (var i = 0 ; i < totalHeight; i++) [for (var i = 0 ; i < width; i++) Tetromino.empty]]; - } +// Board(this.width, this.height, this.bufferHeight){ +// totalHeight = height+bufferHeight; +// board = [for (var i = 0 ; i < totalHeight; i++) [for (var i = 0 ; i < width; i++) Tetromino.empty]]; +// } - @override - String toString() { - String result = ""; - for (var row in board.reversed){ - for (var cell in row) result += cell.name[0]; - result += "\n"; - } - return result; - } +// @override +// String toString() { +// String result = ""; +// for (var row in board.reversed){ +// for (var cell in row) result += cell.name[0]; +// result += "\n"; +// } +// return result; +// } - bool isOccupied(Coords coords) - { - if (coords.x < 0 || coords.x >= width || - coords.y < 0 || coords.y >= totalHeight || - board[coords.y][coords.x] != Tetromino.empty) return true; - return false; - } +// bool isOccupied(Coords coords) +// { +// if (coords.x < 0 || coords.x >= width || +// coords.y < 0 || coords.y >= totalHeight || +// board[coords.y][coords.x] != Tetromino.empty) return true; +// return false; +// } - bool positionIsValid(Tetromino type, Coords coords, int r){ - List shape = shapes[type.index][r]; - for (Coords mino in shape){ - if (isOccupied(coords+mino)) return false; - } - return true; - } +// bool positionIsValid(Tetromino type, Coords coords, int r){ +// List shape = shapes[type.index][r]; +// for (Coords mino in shape){ +// if (isOccupied(coords+mino)) return false; +// } +// return true; +// } - bool wasATSpin(Tetromino type, Coords coords, int rot){ - 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) || - positionIsValid(type, Coords(coords.x, coords.y-1), rot)) - ){ - return true; - } - return false; - } +// bool wasATSpin(Tetromino type, Coords coords, int rot){ +// 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) || +// positionIsValid(type, Coords(coords.x, coords.y-1), rot)) +// ){ +// return true; +// } +// return false; +// } - void writeToBoard(Tetromino type, Coords coords, int rot) { - if (!positionIsValid(type, coords, rot)) throw Exception("Attempted to write $type to $coords in $rot rot"); - List shape = shapes[type.index][rot]; - for (Coords mino in shape){ - var finalCoords = coords+mino; - board[finalCoords.y][finalCoords.x] = type; - } - } +// void writeToBoard(Tetromino type, Coords coords, int rot) { +// if (!positionIsValid(type, coords, rot)) throw Exception("Attempted to write $type to $coords in $rot rot"); +// List shape = shapes[type.index][rot]; +// for (Coords mino in shape){ +// var finalCoords = coords+mino; +// board[finalCoords.y][finalCoords.x] = type; +// } +// } - void writeGarbage(GarbageData data, [int? amt]){ - List> garbage = [for (int i = 0; i < (amt??data.amt!); i++) [for (int k = 0; k < width; k++) k == data.column! ? Tetromino.empty : Tetromino.garbage]]; - board.insertAll(0, garbage); - board.removeRange(height-garbage.length, height); - } +// void writeGarbage(GarbageData data, [int? amt]){ +// List> garbage = [for (int i = 0; i < (amt??data.amt!); i++) [for (int k = 0; k < width; k++) k == data.column! ? Tetromino.empty : Tetromino.garbage]]; +// board.insertAll(0, garbage); +// board.removeRange(height-garbage.length, height); +// } - List clearFullLines(){ - int linesCleared = 0; - int garbageLines = 0; - int difficultLineClear = 0; - for (int i = 0; i < board.length; i++){ - if (board[i-linesCleared].every((element) => element != Tetromino.empty)){ - if (board[i-linesCleared].any((element) => element == Tetromino.garbage)) garbageLines++; - board.removeAt(i-linesCleared); - List emptyRow = [for (int t = 0; t < width; t++) Tetromino.empty]; - board.add(emptyRow); - linesCleared += 1; - } - } - if (linesCleared >= 4) difficultLineClear = 1; - return [linesCleared, garbageLines, difficultLineClear]; - } -} +// List clearFullLines(){ +// int linesCleared = 0; +// int garbageLines = 0; +// int difficultLineClear = 0; +// for (int i = 0; i < board.length; i++){ +// if (board[i-linesCleared].every((element) => element != Tetromino.empty)){ +// if (board[i-linesCleared].any((element) => element == Tetromino.garbage)) garbageLines++; +// board.removeAt(i-linesCleared); +// List emptyRow = [for (int t = 0; t < width; t++) Tetromino.empty]; +// board.add(emptyRow); +// linesCleared += 1; +// } +// } +// if (linesCleared >= 4) difficultLineClear = 1; +// return [linesCleared, garbageLines, difficultLineClear]; +// } +// } -class IncomingGarbage{ - int? frameOfThreat; // will enter board after this frame, null if unconfirmed - GarbageData data; +// class IncomingGarbage{ +// int? frameOfThreat; // will enter board after this frame, null if unconfirmed +// GarbageData data; - IncomingGarbage(this.data); +// IncomingGarbage(this.data); - @override - String toString(){ - return "f$frameOfThreat: col${data.column} amt${data.amt}"; - } +// @override +// String toString(){ +// return "f$frameOfThreat: col${data.column} amt${data.amt}"; +// } - void confirm(int confirmationFrame, int garbageSpeed){ - frameOfThreat = confirmationFrame+garbageSpeed; - } -} +// void confirm(int confirmationFrame, int garbageSpeed){ +// frameOfThreat = confirmationFrame+garbageSpeed; +// } +// } -class LineClearResult{ - int linesCleared; - Tetromino piece; - bool spin; - int garbageCleared; - int column; - int attackProduced; +// class LineClearResult{ +// int linesCleared; +// Tetromino piece; +// bool spin; +// int garbageCleared; +// int column; +// int attackProduced; - LineClearResult(this.linesCleared, this.piece, this.spin, this.garbageCleared, this.column, this.attackProduced); -} +// LineClearResult(this.linesCleared, this.piece, this.spin, this.garbageCleared, this.column, this.attackProduced); +// } -class Stats{ - int combo = -1; - int btb = -1; - int attackRecived = 0; - int attackTanked = 0; +// class Stats{ +// int combo = -1; +// int btb = -1; +// int attackRecived = 0; +// 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: - if (spinWasLastMove && tspin) { - attack = garbage['t-spin']!; - } - break; - case 1: - if (spinWasLastMove && tspin) { - attack = garbage['t-spin single']!; - }else{ - attack = garbage['single']!; - } - break; - case 2: - if (spinWasLastMove && tspin) { - attack = garbage['t-spin double']!; - }else{ - attack = garbage['double']!; - } - break; - case 3: - if (spinWasLastMove && tspin) { - attack = garbage['t-spin triple']!; - }else{ - attack = garbage['triple']!; - } - break; - case 4: - if (spinWasLastMove && tspin) { - attack = garbage['t-spin quad']!; - }else{ - attack = garbage['quad']!; - } - break; - case 5: - if (spinWasLastMove && tspin) { - attack = garbage['t-spin penta']!; - }else{ - attack = garbage['penta']!; - } - break; - case _: - developer.log("${clearFullLinesResult[0]} lines cleared"); - break; - } - return LineClearResult(clearFullLinesResult[0], Tetromino.empty, false, clearFullLinesResult[1], 0, attack); - } -} +// 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: +// if (spinWasLastMove && tspin) { +// attack = garbage['t-spin']!; +// } +// break; +// case 1: +// if (spinWasLastMove && tspin) { +// attack = garbage['t-spin single']!; +// }else{ +// attack = garbage['single']!; +// } +// break; +// case 2: +// if (spinWasLastMove && tspin) { +// attack = garbage['t-spin double']!; +// }else{ +// attack = garbage['double']!; +// } +// break; +// case 3: +// if (spinWasLastMove && tspin) { +// attack = garbage['t-spin triple']!; +// }else{ +// attack = garbage['triple']!; +// } +// break; +// case 4: +// if (spinWasLastMove && tspin) { +// attack = garbage['t-spin quad']!; +// }else{ +// attack = garbage['quad']!; +// } +// break; +// case 5: +// if (spinWasLastMove && tspin) { +// attack = garbage['t-spin penta']!; +// }else{ +// attack = garbage['penta']!; +// } +// break; +// case _: +// developer.log("${clearFullLinesResult[0]} lines cleared"); +// break; +// } +// return LineClearResult(clearFullLinesResult[0], Tetromino.empty, false, clearFullLinesResult[1], 0, attack); +// } +// } -class Simulation{ +// class Simulation{ -} +// } -// That thing allows me to test my new staff i'm trying to implement -void main() async { - var replayJson = jsonDecode(File("/home/dan63047/Документы/replays/6550eecf2ffc5604e6224fc5.ttrm").readAsStringSync()); - // frame 994: garbage lost - // frame 1550: T-spin failed - ReplayData replay = ReplayData.fromJson(replayJson); - TetrioRNG rng = TetrioRNG(replay.stats[0][0].seed); - List queue = rng.shuffleList(tetrominoes.toList()); - List events = readEventList(replay.rawJson); - DataFullOptions? settings; - HandlingHandler? handling; - Map activeKeypresses = {}; - int currentFrame = 0; - double subframesWent = 0; - events.removeAt(0); // get rig of Event.start - Event nextEvent = events.removeAt(0); - Stats stats = Stats(); - Board board = Board(10, 20, 20); - KicksetBase kickset = SRSPlus(); - List garbageQueue = []; - Tetromino? hold; - int rot = 0; - bool spinWasLastMove = false; - Coords coords = Coords(3, 21); - double lockDelay = 30; // frames - int lockResets = 15; - bool floored = false; - double gravityBucket = 1.0; +// // That thing allows me to test my new staff i'm trying to implement +// void main() async { +// var replayJson = jsonDecode(File("/home/dan63047/Документы/replays/6550eecf2ffc5604e6224fc5.ttrm").readAsStringSync()); +// // frame 994: garbage lost +// // frame 1550: T-spin failed +// ReplayData replay = ReplayData.fromJson(replayJson); +// TetrioRNG rng = TetrioRNG(replay.stats[0][0].seed); +// List queue = rng.shuffleList(tetrominoes.toList()); +// List events = readEventList(replay.rawJson); +// DataFullOptions? settings; +// HandlingHandler? handling; +// Map activeKeypresses = {}; +// int currentFrame = 0; +// double subframesWent = 0; +// events.removeAt(0); // get rig of Event.start +// Event nextEvent = events.removeAt(0); +// Stats stats = Stats(); +// Board board = Board(10, 20, 20); +// KicksetBase kickset = SRSPlus(); +// List garbageQueue = []; +// Tetromino? hold; +// int rot = 0; +// bool spinWasLastMove = false; +// Coords coords = Coords(3, 21); +// double lockDelay = 30; // frames +// int lockResets = 15; +// bool floored = false; +// double gravityBucket = 1.0; - 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("Seed is ${replay.stats[0][0].seed}, first bag is $queue"); +// Tetromino current = queue.removeAt(0); +// //developer.log("Second bag is ${rng.shuffleList(tetrominoes)}"); - int sonicDrop(){ - int height = coords.y; - while (board.positionIsValid(current, Coords(coords.x, height), rot)){ - height -= 1; - } - height += 1; - return height; - } +// int sonicDrop(){ +// int height = coords.y; +// while (board.positionIsValid(current, Coords(coords.x, height), rot)){ +// height -= 1; +// } +// height += 1; +// return height; +// } - Tetromino getNewOne(){ +// Tetromino getNewOne(){ - if (queue.length <= 1) { - List nextPieces = rng.shuffleList(tetrominoes.toList()); - queue.addAll(nextPieces); - } - //developer.log("Next queue is $queue"); - rot = 0; - lockResets = 15; - lockDelay = 30; - floored = false; - gravityBucket = 1.0; - return queue.removeAt(0); - } +// if (queue.length <= 1) { +// List nextPieces = rng.shuffleList(tetrominoes.toList()); +// queue.addAll(nextPieces); +// } +// //developer.log("Next queue is $queue"); +// rot = 0; +// lockResets = 15; +// lockDelay = 30; +// floored = false; +// gravityBucket = 1.0; +// return queue.removeAt(0); +// } - bool handleRotation(int r){ - if (r == 0) return true; - int futureRotation = (rot + r) % 4; - List tests = (current == Tetromino.I ? kickset.kickTableI : kickset.kickTable)[rot][r == -1 ? 0 : r]; - for (Coords test in tests){ - if (board.positionIsValid(current, coords+test, futureRotation)){ - coords += test; - rot = futureRotation; - return true; - } - } - return false; - } +// bool handleRotation(int r){ +// if (r == 0) return true; +// int futureRotation = (rot + r) % 4; +// List tests = (current == Tetromino.I ? kickset.kickTableI : kickset.kickTable)[rot][r == -1 ? 0 : r]; +// for (Coords test in tests){ +// if (board.positionIsValid(current, coords+test, futureRotation)){ +// coords += test; +// rot = futureRotation; +// return true; +// } +// } +// return false; +// } - void handleHardDrop(){ - 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 (garbageQueue.isNotEmpty) { - if (lineClear.linesCleared > 0){ - int garbageToDelete = lineClear.attackProduced; - for (IncomingGarbage garbage in garbageQueue){ - if (garbage.data.amt! >= garbageToDelete) { - garbageToDelete -= garbage.data.amt!; - lineClear.attackProduced = garbageToDelete; - garbage.data.amt = 0; - }else{ - garbage.data.amt = garbage.data.amt! - garbageToDelete; - lineClear.attackProduced = 0; - break; - } - } - }else{ - int needToTake = settings!.garbageCap!; - for (IncomingGarbage garbage in garbageQueue){ - if ((garbage.frameOfThreat??99999999) > currentFrame) break; - if (garbage.data.amt! > needToTake) { - board.writeGarbage(garbage.data, needToTake); - garbage.data.amt = garbage.data.amt! - needToTake; - break; - } else { - board.writeGarbage(garbage.data); - needToTake -= garbage.data.amt!; - garbage.data.amt = 0; - } - } - } - garbageQueue.removeWhere((element) => element.data.amt == 0); - } - current = getNewOne(); - coords = Coords(3, 21) + spawnPositionFixes[current.index]; - } +// void handleHardDrop(){ +// 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 (garbageQueue.isNotEmpty) { +// if (lineClear.linesCleared > 0){ +// int garbageToDelete = lineClear.attackProduced; +// for (IncomingGarbage garbage in garbageQueue){ +// if (garbage.data.amt! >= garbageToDelete) { +// garbageToDelete -= garbage.data.amt!; +// lineClear.attackProduced = garbageToDelete; +// garbage.data.amt = 0; +// }else{ +// garbage.data.amt = garbage.data.amt! - garbageToDelete; +// lineClear.attackProduced = 0; +// break; +// } +// } +// }else{ +// int needToTake = settings!.garbageCap!; +// for (IncomingGarbage garbage in garbageQueue){ +// if ((garbage.frameOfThreat??99999999) > currentFrame) break; +// if (garbage.data.amt! > needToTake) { +// board.writeGarbage(garbage.data, needToTake); +// garbage.data.amt = garbage.data.amt! - needToTake; +// break; +// } else { +// board.writeGarbage(garbage.data); +// needToTake -= garbage.data.amt!; +// garbage.data.amt = 0; +// } +// } +// } +// garbageQueue.removeWhere((element) => element.data.amt == 0); +// } +// current = getNewOne(); +// coords = Coords(3, 21) + spawnPositionFixes[current.index]; +// } - 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; - int gravityImpact = 0; - if (gravityBucket >= 1.0){ - gravityImpact = gravityBucket.truncate(); - gravityBucket -= gravityBucket.truncate(); - } - while (gravityImpact > 0){ - if (board.positionIsValid(current, Coords(coords.x, coords.y-1), rot)) {coords.y -= 1; floored = false;} - else floored = true; - gravityImpact--; - } - if (floored) lockDelay -= frames; - if (lockDelay <= 0 && floored){ - handleHardDrop(); - } - } +// 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; +// int gravityImpact = 0; +// if (gravityBucket >= 1.0){ +// gravityImpact = gravityBucket.truncate(); +// gravityBucket -= gravityBucket.truncate(); +// } +// while (gravityImpact > 0){ +// if (board.positionIsValid(current, Coords(coords.x, coords.y-1), rot)) {coords.y -= 1; floored = false;} +// else floored = true; +// gravityImpact--; +// } +// if (floored) lockDelay -= frames; +// if (lockDelay <= 0 && floored){ +// handleHardDrop(); +// } +// } - void handleMovement(double frames){ - if (frames == 0 || handling == null) return; - int movement = handling.processMovenent(frames); - while (movement.abs() > 0){ - if (board.positionIsValid(current, Coords(movement.isNegative ? coords.x-1 : coords.x+1, coords.y), rot)) movement.isNegative ? coords.x-- : coords.x++; - movement.isNegative ? movement++ : movement--; - } - } +// void handleMovement(double frames){ +// if (frames == 0 || handling == null) return; +// int movement = handling.processMovenent(frames); +// while (movement.abs() > 0){ +// if (board.positionIsValid(current, Coords(movement.isNegative ? coords.x-1 : coords.x+1, coords.y), rot)) movement.isNegative ? coords.x-- : coords.x++; +// movement.isNegative ? movement++ : movement--; +// } +// } - coords += spawnPositionFixes[current.index]; - for (currentFrame; currentFrame <= replay.roundLengths[0]; currentFrame++){ - handleMovement(1-subframesWent); - handleGravity(1-subframesWent); - subframesWent = 0; +// coords += spawnPositionFixes[current.index]; +// for (currentFrame; currentFrame <= replay.roundLengths[0]; currentFrame++){ +// handleMovement(1-subframesWent); +// handleGravity(1-subframesWent); +// 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"); - switch (nextEvent.type){ - case EventType.start: - developer.log("go"); - break; - case EventType.full: - settings = (nextEvent as EventFull).data.options; - handling = HandlingHandler(settings!.handling!.das.toDouble(), settings.handling!.arr.toDouble()); - lockDelay = settings.locktime!.toDouble(); - lockResets = settings.lockresets!; - break; - case EventType.keydown: - nextEvent as EventKeyPress; - double subframesDiff = nextEvent.data.subframe - subframesWent; - subframesWent += subframesDiff; - handleMovement(subframesDiff); - handleGravity(subframesDiff); - //activeKeypresses[nextEvent.data.key] = nextEvent; - switch (nextEvent.data.key){ - case KeyType.rotateCCW: - handleRotation(-1); - break; - case KeyType.rotateCW: - handleRotation(1); - break; - case KeyType.rotate180: - handleRotation(2); - break; - case KeyType.moveLeft: - case KeyType.moveRight: - int pontencialMovement = handling!.movementKeyPressed(nextEvent.data.key == KeyType.moveLeft, nextEvent.data.key == KeyType.moveRight, nextEvent.data.subframe); - if (board.positionIsValid(current, Coords(coords.x+pontencialMovement, coords.y), rot)) coords.x += pontencialMovement; - break; - case KeyType.softDrop: - handling!.sdfActive = true; - break; - case KeyType.hardDrop: - coords.y = sonicDrop(); - handleHardDrop(); - case KeyType.hold: - switch (hold){ - case null: - hold = current; - current = getNewOne(); - break; - case _: - Tetromino temp; - temp = hold; - hold = current; - current = temp; - rot = 0; - lockResets = 15; - lockDelay = 30; - gravityBucket = 1.0; - floored = false; - coords = Coords(3, 21) + spawnPositionFixes[current.index]; - break; - } - break; - case KeyType.chat: - // TODO: Handle this case. - case KeyType.exit: - // TODO: Handle this case. - case KeyType.retry: - // TODO: Handle this case. - default: - developer.log(nextEvent.data.key.name); - } - if (nextEvent.data.key == KeyType.rotateCW && nextEvent.data.key == KeyType.rotateCW && nextEvent.data.key == KeyType.rotateCW){ - spinWasLastMove = true; - }else{ - spinWasLastMove = false; - } - break; - case EventType.keyup: - nextEvent as EventKeyPress; - double subframesDiff = nextEvent.data.subframe - subframesWent; - subframesWent += subframesDiff; - handleMovement(subframesDiff); - handleGravity(subframesDiff); - switch (nextEvent.data.key){ - case KeyType.moveLeft: - case KeyType.moveRight: - handling!.movementKeyReleased(nextEvent.data.key == KeyType.moveLeft, nextEvent.data.key == KeyType.moveRight, nextEvent.data.subframe); - break; - case KeyType.softDrop: - handling?.sdfActive = false; - break; - case KeyType.rotateCCW: - // TODO: Handle this case. - case KeyType.rotateCW: - // TODO: Handle this case. - case KeyType.rotate180: - // TODO: Handle this case. - case KeyType.hardDrop: - // TODO: Handle this case. - case KeyType.hold: - // TODO: Handle this case. - case KeyType.chat: - // TODO: Handle this case. - case KeyType.exit: - // TODO: Handle this case. - case KeyType.retry: - // TODO: Handle this case. - } - activeKeypresses.remove(nextEvent.data.key); - break; - case EventType.end: - currentFrame = replay.roundLengths[0]+1; - break; - case EventType.ige: - nextEvent as EventIGE; - switch (nextEvent.data.data.type){ - case "interaction": - garbageQueue.add(IncomingGarbage((nextEvent.data.data as IGEdataInteraction).data)); - case "interaction_confirm": - GarbageData data = (nextEvent.data.data as IGEdataInteraction).data; - if(data.type != "targeted") garbageQueue.firstWhere((element) => element.data.iid == data.iid).confirm(currentFrame, settings!.garbageSpeed!); - case "allow_targeting": - case "target": - default: - developer.log("Unknown IGE type: ${nextEvent.data.type}", level: 900); - break; - } - // garbage speed counts from interaction comfirm - break; - default: - developer.log("Event wasn't processed: ${nextEvent}", level: 900); - } - try{ - nextEvent = events.removeAt(0); - } - catch (e){ - developer.log(e.toString()); - } - } - //developer.log("Next is: $nextEvent"); - } - } - exit(0); -} \ No newline at end of file +// 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"); +// switch (nextEvent.type){ +// case EventType.start: +// developer.log("go"); +// break; +// case EventType.full: +// settings = (nextEvent as EventFull).data.options; +// handling = HandlingHandler(settings!.handling!.das.toDouble(), settings.handling!.arr.toDouble()); +// lockDelay = settings.locktime!.toDouble(); +// lockResets = settings.lockresets!; +// break; +// case EventType.keydown: +// nextEvent as EventKeyPress; +// double subframesDiff = nextEvent.data.subframe - subframesWent; +// subframesWent += subframesDiff; +// handleMovement(subframesDiff); +// handleGravity(subframesDiff); +// //activeKeypresses[nextEvent.data.key] = nextEvent; +// switch (nextEvent.data.key){ +// case KeyType.rotateCCW: +// handleRotation(-1); +// break; +// case KeyType.rotateCW: +// handleRotation(1); +// break; +// case KeyType.rotate180: +// handleRotation(2); +// break; +// case KeyType.moveLeft: +// case KeyType.moveRight: +// int pontencialMovement = handling!.movementKeyPressed(nextEvent.data.key == KeyType.moveLeft, nextEvent.data.key == KeyType.moveRight, nextEvent.data.subframe); +// if (board.positionIsValid(current, Coords(coords.x+pontencialMovement, coords.y), rot)) coords.x += pontencialMovement; +// break; +// case KeyType.softDrop: +// handling!.sdfActive = true; +// break; +// case KeyType.hardDrop: +// coords.y = sonicDrop(); +// handleHardDrop(); +// case KeyType.hold: +// switch (hold){ +// case null: +// hold = current; +// current = getNewOne(); +// break; +// case _: +// Tetromino temp; +// temp = hold; +// hold = current; +// current = temp; +// rot = 0; +// lockResets = 15; +// lockDelay = 30; +// gravityBucket = 1.0; +// floored = false; +// coords = Coords(3, 21) + spawnPositionFixes[current.index]; +// break; +// } +// break; +// case KeyType.chat: +// // TODO: Handle this case. +// case KeyType.exit: +// // TODO: Handle this case. +// case KeyType.retry: +// // TODO: Handle this case. +// default: +// developer.log(nextEvent.data.key.name); +// } +// if (nextEvent.data.key == KeyType.rotateCW && nextEvent.data.key == KeyType.rotateCW && nextEvent.data.key == KeyType.rotateCW){ +// spinWasLastMove = true; +// }else{ +// spinWasLastMove = false; +// } +// break; +// case EventType.keyup: +// nextEvent as EventKeyPress; +// double subframesDiff = nextEvent.data.subframe - subframesWent; +// subframesWent += subframesDiff; +// handleMovement(subframesDiff); +// handleGravity(subframesDiff); +// switch (nextEvent.data.key){ +// case KeyType.moveLeft: +// case KeyType.moveRight: +// handling!.movementKeyReleased(nextEvent.data.key == KeyType.moveLeft, nextEvent.data.key == KeyType.moveRight, nextEvent.data.subframe); +// break; +// case KeyType.softDrop: +// handling?.sdfActive = false; +// break; +// case KeyType.rotateCCW: +// // TODO: Handle this case. +// case KeyType.rotateCW: +// // TODO: Handle this case. +// case KeyType.rotate180: +// // TODO: Handle this case. +// case KeyType.hardDrop: +// // TODO: Handle this case. +// case KeyType.hold: +// // TODO: Handle this case. +// case KeyType.chat: +// // TODO: Handle this case. +// case KeyType.exit: +// // TODO: Handle this case. +// case KeyType.retry: +// // TODO: Handle this case. +// } +// activeKeypresses.remove(nextEvent.data.key); +// break; +// case EventType.end: +// currentFrame = replay.roundLengths[0]+1; +// break; +// case EventType.ige: +// nextEvent as EventIGE; +// switch (nextEvent.data.data.type){ +// case "interaction": +// garbageQueue.add(IncomingGarbage((nextEvent.data.data as IGEdataInteraction).data)); +// case "interaction_confirm": +// GarbageData data = (nextEvent.data.data as IGEdataInteraction).data; +// if(data.type != "targeted") garbageQueue.firstWhere((element) => element.data.iid == data.iid).confirm(currentFrame, settings!.garbageSpeed!); +// case "allow_targeting": +// case "target": +// default: +// developer.log("Unknown IGE type: ${nextEvent.data.type}", level: 900); +// break; +// } +// // garbage speed counts from interaction comfirm +// break; +// default: +// developer.log("Event wasn't processed: ${nextEvent}", level: 900); +// } +// try{ +// nextEvent = events.removeAt(0); +// } +// catch (e){ +// developer.log(e.toString()); +// } +// } +// //developer.log("Next is: $nextEvent"); +// } +// } +// exit(0); +// } \ No newline at end of file diff --git a/lib/data_objects/tetrio.dart b/lib/data_objects/tetrio.dart index e89b2cf..eeff63b 100644 --- a/lib/data_objects/tetrio.dart +++ b/lib/data_objects/tetrio.dart @@ -897,9 +897,9 @@ class TetraLeagueAlphaRecord{ TetraLeagueAlphaRecord({required this.replayId, required this.ownId, required this.timestamp, required this.endContext, required this.replayAvalable}); TetraLeagueAlphaRecord.fromJson(Map json) { - ownId = json['_id']; endContext = [EndContextMulti.fromJson(json['endcontext'][0]), EndContextMulti.fromJson(json['endcontext'][1])]; replayId = json['replayid']; + ownId = json['_id']??replayId; timestamp = DateTime.parse(json['ts']); replayAvalable = true; } @@ -973,19 +973,19 @@ class EndContextMulti { EndContextMulti.fromJson(Map json) { userId = json['id'] ?? json['user']['_id']; username = json['username'] ?? json['user']['username']; - handling = Handling.fromJson(json['handling']); + handling = json['handling'] != null ? Handling.fromJson(json['handling']) : Handling(arr: -1, das: -1, sdf: -1, dcd: 0, cancel: true, safeLock: true); success = json['success']; - inputs = json['inputs']; - piecesPlaced = json['piecesplaced']; + inputs = json['inputs'] ?? -1; + piecesPlaced = json['piecesplaced'] ?? -1; naturalOrder = json['naturalorder']; wins = json['wins']; points = json['points']['primary']; secondary = json['points']['secondary'].toDouble(); tertiary = json['points']['tertiary'].toDouble(); - secondaryTracking = json['points']['secondaryAvgTracking'].map((e) => e.toDouble()).toList(); - tertiaryTracking = json['points']['tertiaryAvgTracking'].map((e) => e.toDouble()).toList(); + secondaryTracking = json['points']['secondaryAvgTracking'] != null ? json['points']['secondaryAvgTracking'].map((e) => e.toDouble()).toList() : []; + tertiaryTracking = json['points']['tertiaryAvgTracking'] != null ? json['points']['tertiaryAvgTracking'].map((e) => e.toDouble()).toList() : []; extra = json['points']['extra']['vs'].toDouble(); - extraTracking = json['points']['extraAvgTracking']['aggregatestats___vsscore'].map((e) => e.toDouble()).toList(); + extraTracking = json['points']['extraAvgTracking'] != null ? json['points']['extraAvgTracking']['aggregatestats___vsscore'].map((e) => e.toDouble()).toList() : []; nerdStats = NerdStats(secondary, tertiary, extra); nerdStatsTracking = [for (int i = 0; i < secondaryTracking.length; i++) NerdStats(secondaryTracking[i], tertiaryTracking[i], extraTracking[i])]; estTr = EstTr(secondary, tertiary, extra, nerdStats.app, nerdStats.dss, nerdStats.dsp, nerdStats.gbe); diff --git a/lib/data_objects/tetrio_multiplayer_replay.dart b/lib/data_objects/tetrio_multiplayer_replay.dart index 7f1a7a8..9b521ad 100644 --- a/lib/data_objects/tetrio_multiplayer_replay.dart +++ b/lib/data_objects/tetrio_multiplayer_replay.dart @@ -269,633 +269,633 @@ class ReplayData{ // can't belive i have to implement that difficult shit -List readEventList(Map json){ - List events = []; - int id = 0; - for (var event in json['data'][0]['replays'][0]['events']){ - int frame = event["frame"]; - EventType type = EventType.values.byName(event['type']); - switch (type) { - case EventType.start: - events.add(Event(id, frame, type)); - break; - case EventType.full: - events.add(EventFull(id, frame, type, DataFull.fromJson(event["data"]))); - break; - case EventType.targets: - events.add(EventTargets(id, frame, type, Targets.fromJson(event["data"]))); - break; - case EventType.keydown: - events.add(EventKeyPress(id, frame, type, - Keypress( - KeyType.values.byName(event['data']['key']), - event['data']['subframe'], - false) - )); - break; - case EventType.keyup: - events.add(EventKeyPress(id, frame, type, - Keypress( - KeyType.values.byName(event['data']['key']), - event['data']['subframe'], - true) - )); - break; - case EventType.end: - events.add(EventEnd(id, frame, type, EndData(event['data']['reason'], DataFull.fromJson(event['data']['export'])))); - break; - case EventType.ige: - events.add(EventIGE(id, frame, type, IGE( - event['data']['id'], - event['data']['frame'], - event['data']['type'], - event['data']['data'] - )) - ); - break; - case EventType.exit: - events.add(Event(id, frame, type)); - break; - } - id++; - } - return events; -} +// List readEventList(Map json){ +// List events = []; +// int id = 0; +// for (var event in json['data'][0]['replays'][0]['events']){ +// int frame = event["frame"]; +// EventType type = EventType.values.byName(event['type']); +// switch (type) { +// case EventType.start: +// events.add(Event(id, frame, type)); +// break; +// case EventType.full: +// events.add(EventFull(id, frame, type, DataFull.fromJson(event["data"]))); +// break; +// case EventType.targets: +// events.add(EventTargets(id, frame, type, Targets.fromJson(event["data"]))); +// break; +// case EventType.keydown: +// events.add(EventKeyPress(id, frame, type, +// Keypress( +// KeyType.values.byName(event['data']['key']), +// event['data']['subframe'], +// false) +// )); +// break; +// case EventType.keyup: +// events.add(EventKeyPress(id, frame, type, +// Keypress( +// KeyType.values.byName(event['data']['key']), +// event['data']['subframe'], +// true) +// )); +// break; +// case EventType.end: +// events.add(EventEnd(id, frame, type, EndData(event['data']['reason'], DataFull.fromJson(event['data']['export'])))); +// break; +// case EventType.ige: +// events.add(EventIGE(id, frame, type, IGE( +// event['data']['id'], +// event['data']['frame'], +// event['data']['type'], +// event['data']['data'] +// )) +// ); +// break; +// case EventType.exit: +// events.add(Event(id, frame, type)); +// break; +// } +// id++; +// } +// return events; +// } -enum EventType -{ - start, - end, - full, - keydown, - keyup, - targets, - ige, - exit -} +// enum EventType +// { +// start, +// end, +// full, +// keydown, +// keyup, +// targets, +// ige, +// exit +// } -enum KeyType -{ - moveLeft, - moveRight, - softDrop, - rotateCCW, - rotateCW, - rotate180, - hardDrop, - hold, - chat, - exit, - retry -} +// enum KeyType +// { +// moveLeft, +// moveRight, +// softDrop, +// rotateCCW, +// rotateCW, +// rotate180, +// hardDrop, +// hold, +// chat, +// exit, +// retry +// } -class Event{ - int id; - int frame; - EventType type; - //dynamic data; +// class Event{ +// int id; +// int frame; +// EventType type; +// //dynamic data; - Event(this.id, this.frame, this.type); +// Event(this.id, this.frame, this.type); - @override - String toString(){ - return "E#$id f#$frame: $type"; - } -} +// @override +// String toString(){ +// return "E#$id f#$frame: $type"; +// } +// } -class Keypress{ - KeyType key; - late double subframe; - bool released; +// class Keypress{ +// KeyType key; +// late double subframe; +// bool released; - Keypress(this.key, num sframe, this.released){ - subframe = sframe.toDouble(); - } -} +// Keypress(this.key, num sframe, this.released){ +// subframe = sframe.toDouble(); +// } +// } -class EventKeyPress extends Event{ - Keypress data; +// class EventKeyPress extends Event{ +// Keypress data; - EventKeyPress(super.id, super.frame, super.type, this.data); -} +// EventKeyPress(super.id, super.frame, super.type, this.data); +// } -class Targets{ - String? id; - int? frame; - String? type; - List? data; +// class Targets{ +// String? id; +// int? frame; +// String? type; +// List? data; - Targets(this.id, this.frame, this.type, this.data); +// Targets(this.id, this.frame, this.type, this.data); - Targets.fromJson(Map json){ - id = json["id"]; - frame = json["frame"]; - type = json["type"]; - data = json["data"]; - } -} +// Targets.fromJson(Map json){ +// id = json["id"]; +// frame = json["frame"]; +// type = json["type"]; +// data = json["data"]; +// } +// } -class EventTargets extends Event{ - Targets data; +// class EventTargets extends Event{ +// Targets data; - EventTargets(super.id, super.frame, super.type, this.data); -} +// EventTargets(super.id, super.frame, super.type, this.data); +// } -class IGEdata{ - late String type; - late String? gameid; - late int? frame; +// class IGEdata{ +// late String type; +// late String? gameid; +// late int? frame; - IGEdata.fromJson(Map d){ - type = d['type']; - gameid = d['gameid']; - frame = d['frame']; - } -} +// IGEdata.fromJson(Map d){ +// type = d['type']; +// gameid = d['gameid']; +// frame = d['frame']; +// } +// } -enum GarbageStatus -{ - sleeping, - caution, - spawn, - danger -} +// enum GarbageStatus +// { +// sleeping, +// caution, +// spawn, +// danger +// } -class GarbageData{ - int? id; - int? iid; - int? ackiid; - String? username; - late String type; - bool? active; - GarbageStatus? status; - int? delay; - bool? queued; - int? amt; - int? x; - int? y; - int? size; - int? column; - int? cid; - bool? firstcycle; - int? gid; - bool? value; +// class GarbageData{ +// int? id; +// int? iid; +// int? ackiid; +// String? username; +// late String type; +// bool? active; +// GarbageStatus? status; +// int? delay; +// bool? queued; +// int? amt; +// int? x; +// int? y; +// int? size; +// int? column; +// int? cid; +// bool? firstcycle; +// int? gid; +// bool? value; - GarbageData.fromJson(Map data){ - id = data['id']; - iid = data['iid']; - ackiid = data['ackiid']; - username = data['username']; - type = data['type']; - active = data['active']; - status = data['status'] != null ? GarbageStatus.values[data['status']] : null; - delay = data['delay']; - queued = data['queued']; - amt = data['amt']; - x = data['x']; - y = data['y']; - size = data['size']; - column = data['column']; - cid = data['cid']; - firstcycle = data['firstcycle']; - gid = data['gid']; - value = data['value']; - } -} +// GarbageData.fromJson(Map data){ +// id = data['id']; +// iid = data['iid']; +// ackiid = data['ackiid']; +// username = data['username']; +// type = data['type']; +// active = data['active']; +// status = data['status'] != null ? GarbageStatus.values[data['status']] : null; +// delay = data['delay']; +// queued = data['queued']; +// amt = data['amt']; +// x = data['x']; +// y = data['y']; +// size = data['size']; +// column = data['column']; +// cid = data['cid']; +// firstcycle = data['firstcycle']; +// gid = data['gid']; +// value = data['value']; +// } +// } -class IGEdataTarget extends IGEdata{ - late List targets; +// class IGEdataTarget extends IGEdata{ +// late List targets; - GarbageData? data; - //compatibility for v15 targets event - String? sender_id; +// GarbageData? data; +// //compatibility for v15 targets event +// String? sender_id; - IGEdataTarget.fromJson(Map d) : super.fromJson(d){ - targets = d['targets']; - data = d['data'] != null ? GarbageData.fromJson(d['data']) : null; - } -} +// IGEdataTarget.fromJson(Map d) : super.fromJson(d){ +// targets = d['targets']; +// data = d['data'] != null ? GarbageData.fromJson(d['data']) : null; +// } +// } -class IGEdataAllowTargeting extends IGEdata{ - late bool value; +// class IGEdataAllowTargeting extends IGEdata{ +// late bool value; - IGEdataAllowTargeting.fromJson(Map d) : super.fromJson(d){ - value = d['value']; - frame = d['frame']; - } -} +// IGEdataAllowTargeting.fromJson(Map d) : super.fromJson(d){ +// value = d['value']; +// frame = d['frame']; +// } +// } -class IGEdataInteraction extends IGEdata{ - late GarbageData data; - String? sender; - String? senderID; - int? sentFrame; - bool confirm = false; +// class IGEdataInteraction extends IGEdata{ +// late GarbageData data; +// String? sender; +// String? senderID; +// int? sentFrame; +// bool confirm = false; - IGEdataInteraction.fromJson(Map d) : super.fromJson(d){ - //data = Targeted(d['data']['targeted'], d['data']['value']); - data = GarbageData.fromJson(d['data']); - sender = d['sender']; - senderID = d['sender_id']; - confirm = type == "interaction_confirm"; - } -} +// IGEdataInteraction.fromJson(Map d) : super.fromJson(d){ +// //data = Targeted(d['data']['targeted'], d['data']['value']); +// data = GarbageData.fromJson(d['data']); +// sender = d['sender']; +// senderID = d['sender_id']; +// confirm = type == "interaction_confirm"; +// } +// } -class IGE{ - int id; - int frame; - String type; - late IGEdata data; +// class IGE{ +// int id; +// int frame; +// String type; +// late IGEdata data; - IGE(this.id, this.frame, this.type, Map d){ - data = switch (d["type"] as String) { - "interaction" => IGEdataInteraction.fromJson(d), - "interaction_confirm" => IGEdataInteraction.fromJson(d), - "target" => IGEdataTarget.fromJson(d), - "allow_targeting" => IGEdataAllowTargeting.fromJson(d), - _ => IGEdata.fromJson(d), - }; - } -} +// IGE(this.id, this.frame, this.type, Map d){ +// data = switch (d["type"] as String) { +// "interaction" => IGEdataInteraction.fromJson(d), +// "interaction_confirm" => IGEdataInteraction.fromJson(d), +// "target" => IGEdataTarget.fromJson(d), +// "allow_targeting" => IGEdataAllowTargeting.fromJson(d), +// _ => IGEdata.fromJson(d), +// }; +// } +// } -class EventIGE extends Event{ - IGE data; +// class EventIGE extends Event{ +// IGE data; - EventIGE(super.id, super.frame, super.type, this.data); -} +// EventIGE(super.id, super.frame, super.type, this.data); +// } -class EndData { - String reason; - DataFull export; +// class EndData { +// String reason; +// DataFull export; - EndData(this.reason, this.export); -} +// EndData(this.reason, this.export); +// } -class EventEnd extends Event{ - EndData data; +// class EventEnd extends Event{ +// EndData data; - EventEnd(super.id, super.frame, super.type, this.data); -} +// EventEnd(super.id, super.frame, super.type, this.data); +// } -class Hold -{ - String? piece; - bool locked; +// class Hold +// { +// String? piece; +// bool locked; - Hold(this.piece, this.locked); -} +// Hold(this.piece, this.locked); +// } -class DataFullOptions{ - int? version; - bool? seedRandom; - int? seed; - double? g; - int? stock; - int? gMargin; - double? gIncrease; - double? garbageMultiplier; - int? garbageMargin; - double? garbageIncrease; - int? garbageCap; - double? garbageCapIncrease; - int? garbageCapMax; - int? garbageHoleSize; - String? garbageBlocking; // TODO: enum - bool? hasGarbage; - int? locktime; - int? garbageSpeed; - int? forfeitTime; - int? are; - int? areLineclear; - bool? infiniteMovement; - int? lockresets; - bool? allow180; - bool? btbChaining; - bool? allclears; - bool? clutch; - bool? noLockout; - String? passthrough; - int? boardwidth; - int? boardheight; - Handling? handling; - int? boardbuffer; +// class DataFullOptions{ +// int? version; +// bool? seedRandom; +// int? seed; +// double? g; +// int? stock; +// int? gMargin; +// double? gIncrease; +// double? garbageMultiplier; +// int? garbageMargin; +// double? garbageIncrease; +// int? garbageCap; +// double? garbageCapIncrease; +// int? garbageCapMax; +// int? garbageHoleSize; +// String? garbageBlocking; // TODO: enum +// bool? hasGarbage; +// int? locktime; +// int? garbageSpeed; +// int? forfeitTime; +// int? are; +// int? areLineclear; +// bool? infiniteMovement; +// int? lockresets; +// bool? allow180; +// bool? btbChaining; +// bool? allclears; +// bool? clutch; +// bool? noLockout; +// String? passthrough; +// int? boardwidth; +// int? boardheight; +// Handling? handling; +// int? boardbuffer; - DataFullOptions.fromJson(Map json){ - version = json["version"]; - seedRandom = json["seed_random"]; - seed = json["seed"]; - g = json["g"]; - stock = json["stock"]; - gMargin = json["gmargin"]; - gIncrease = json["gincrease"]; - garbageMultiplier = json["garbagemultiplier"].toDouble(); - garbageCap = json["garbagecap"]; - garbageCapIncrease = json["garbagecapincrease"].toDouble(); - garbageCapMax = json["garbagecapmax"]; - garbageHoleSize = json["garbageholesize"]; - garbageBlocking = json["garbageblocking"]; - hasGarbage = json["hasgarbage"]; - locktime = json["locktime"]; - garbageSpeed = json["garbagespeed"]; - forfeitTime = json["forfeit_time"]; - are = json["are"]; - areLineclear = json["lineclear_are"]; - infiniteMovement = json["infinitemovement"]; - lockresets = json["lockresets"]; - allow180 = json["allow180"]; - btbChaining = json["b2bchaining"]; - allclears = json["allclears"]; - clutch = json["clutch"]; - noLockout = json["nolockout"]; - passthrough = json["passthrough"]; - boardwidth = json["boardwidth"]; - boardheight = json["boardheight"]; - handling = Handling.fromJson(json["handling"]); - boardbuffer = json["boardbuffer"]; - } -} +// DataFullOptions.fromJson(Map json){ +// version = json["version"]; +// seedRandom = json["seed_random"]; +// seed = json["seed"]; +// g = json["g"]; +// stock = json["stock"]; +// gMargin = json["gmargin"]; +// gIncrease = json["gincrease"]; +// garbageMultiplier = json["garbagemultiplier"].toDouble(); +// garbageCap = json["garbagecap"]; +// garbageCapIncrease = json["garbagecapincrease"].toDouble(); +// garbageCapMax = json["garbagecapmax"]; +// garbageHoleSize = json["garbageholesize"]; +// garbageBlocking = json["garbageblocking"]; +// hasGarbage = json["hasgarbage"]; +// locktime = json["locktime"]; +// garbageSpeed = json["garbagespeed"]; +// forfeitTime = json["forfeit_time"]; +// are = json["are"]; +// areLineclear = json["lineclear_are"]; +// infiniteMovement = json["infinitemovement"]; +// lockresets = json["lockresets"]; +// allow180 = json["allow180"]; +// btbChaining = json["b2bchaining"]; +// allclears = json["allclears"]; +// clutch = json["clutch"]; +// noLockout = json["nolockout"]; +// passthrough = json["passthrough"]; +// boardwidth = json["boardwidth"]; +// boardheight = json["boardheight"]; +// handling = Handling.fromJson(json["handling"]); +// boardbuffer = json["boardbuffer"]; +// } +// } -class DataFullStats - { - int? seed; - int? lines; - int? levelLines; - int? levelLinesNeeded; - int? inputs; - int? holds; - int? score; - int? zenLevel; - int? zenProgress; - int? level; - int? combo; - int? currentComboPower; - int? topCombo; - int? btb; - int? topbtb; - int? tspins; - int? piecesPlaced; - Clears? clears; - Garbage? garbage; - int? kills; - Finesse? finesse; +// class DataFullStats +// { +// int? seed; +// int? lines; +// int? levelLines; +// int? levelLinesNeeded; +// int? inputs; +// int? holds; +// int? score; +// int? zenLevel; +// int? zenProgress; +// int? level; +// int? combo; +// int? currentComboPower; +// int? topCombo; +// int? btb; +// int? topbtb; +// int? tspins; +// int? piecesPlaced; +// Clears? clears; +// Garbage? garbage; +// int? kills; +// Finesse? finesse; - DataFullStats.fromJson(Map json){ - seed = json["seed"]; - lines = json["lines"]; - levelLines = json["level_lines"]; - levelLinesNeeded = json["level_lines_needed"]; - inputs = json["inputs"]; - holds = json["holds"]; - score = json["score"]; - zenLevel = json["zenlevel"]; - zenProgress = json["zenprogress"]; - level = json["level"]; - combo = json["combo"]; - currentComboPower = json["currentcombopower"]; - topCombo = json["topcombo"]; - btb = json["btb"]; - topbtb = json["topbtb"]; - tspins = json["tspins"]; - piecesPlaced = json["piecesplaced"]; - clears = Clears.fromJson(json["clears"]); - garbage = Garbage.fromJson(json["garbage"]); - kills = json["kills"]; - finesse = Finesse.fromJson(json["finesse"]); - } - } +// DataFullStats.fromJson(Map json){ +// seed = json["seed"]; +// lines = json["lines"]; +// levelLines = json["level_lines"]; +// levelLinesNeeded = json["level_lines_needed"]; +// inputs = json["inputs"]; +// holds = json["holds"]; +// score = json["score"]; +// zenLevel = json["zenlevel"]; +// zenProgress = json["zenprogress"]; +// level = json["level"]; +// combo = json["combo"]; +// currentComboPower = json["currentcombopower"]; +// topCombo = json["topcombo"]; +// btb = json["btb"]; +// topbtb = json["topbtb"]; +// tspins = json["tspins"]; +// piecesPlaced = json["piecesplaced"]; +// clears = Clears.fromJson(json["clears"]); +// garbage = Garbage.fromJson(json["garbage"]); +// kills = json["kills"]; +// finesse = Finesse.fromJson(json["finesse"]); +// } +// } -class DataFullGame - { - List? board; - List? bag; - double? g; - bool? playing; - Hold? hold; - String? piece; - Handling? handling; +// class DataFullGame +// { +// List? board; +// List? bag; +// double? g; +// bool? playing; +// Hold? hold; +// String? piece; +// Handling? handling; - DataFullGame.fromJson(Map json){ - board = json["board"]; - bag = json["bag"]; - hold = Hold(json["hold"]["piece"], json["hold"]["locked"]); - g = json["g"]; - handling = Handling.fromJson(json["handling"]); - } - } +// DataFullGame.fromJson(Map json){ +// board = json["board"]; +// bag = json["bag"]; +// hold = Hold(json["hold"]["piece"], json["hold"]["locked"]); +// g = json["g"]; +// handling = Handling.fromJson(json["handling"]); +// } +// } -class DataFull{ - bool? successful; - String? gameOverReason; - int? fire; - DataFullOptions? options; - DataFullStats? stats; - DataFullGame? game; +// class DataFull{ +// bool? successful; +// String? gameOverReason; +// int? fire; +// DataFullOptions? options; +// DataFullStats? stats; +// DataFullGame? game; - DataFull.fromJson(Map json){ - successful = json["successful"]; - gameOverReason = json["gameoverreason"]; - fire = json["fire"]; - options = DataFullOptions.fromJson(json["options"]); - stats = DataFullStats.fromJson(json["stats"]); - game = DataFullGame.fromJson(json["game"]); - } -} +// DataFull.fromJson(Map json){ +// successful = json["successful"]; +// gameOverReason = json["gameoverreason"]; +// fire = json["fire"]; +// options = DataFullOptions.fromJson(json["options"]); +// stats = DataFullStats.fromJson(json["stats"]); +// game = DataFullGame.fromJson(json["game"]); +// } +// } -class EventFull extends Event{ - DataFull data; +// class EventFull extends Event{ +// DataFull data; - EventFull(super.id, super.frame, super.type, this.data); -} +// EventFull(super.id, super.frame, super.type, this.data); +// } -class TetrioRNG{ - late double _t; +// class TetrioRNG{ +// late double _t; - TetrioRNG(int seed){ - _t = seed % 2147483647; - if (_t <= 0) _t += 2147483646; - } +// TetrioRNG(int seed){ +// _t = seed % 2147483647; +// if (_t <= 0) _t += 2147483646; +// } - int next(){ - _t = 16807 * _t % 2147483647; - return _t.toInt(); - } +// int next(){ +// _t = 16807 * _t % 2147483647; +// return _t.toInt(); +// } - double nextFloat(){ - return (next() - 1) / 2147483646; - } +// double nextFloat(){ +// return (next() - 1) / 2147483646; +// } - List shuffleList(List array){ - int length = array.length; - if (length == 0) return []; +// List shuffleList(List array){ +// int length = array.length; +// if (length == 0) return []; - for (; --length > 0;){ - int swapIndex = ((nextFloat()) * (length + 1)).toInt(); - Tetromino tmp = array[length]; - array[length] = array[swapIndex]; - array[swapIndex] = tmp; - } - return array; - } -} +// for (; --length > 0;){ +// int swapIndex = ((nextFloat()) * (length + 1)).toInt(); +// Tetromino tmp = array[length]; +// array[length] = array[swapIndex]; +// array[swapIndex] = tmp; +// } +// return array; +// } +// } -enum Tetromino{ - Z, - L, - O, - S, - I, - J, - T, - garbage, - empty -} +// enum Tetromino{ +// Z, +// L, +// O, +// S, +// I, +// J, +// T, +// garbage, +// empty +// } -class Coords{ - int x; - int y; +// class Coords{ +// int x; +// int y; - Coords(this.x, this.y); +// Coords(this.x, this.y); - @override - String toString() { - return "($x; $y)"; - } +// @override +// String toString() { +// return "($x; $y)"; +// } - Coords operator+(Coords other){ - return Coords(x+other.x, y+other.y); - } +// Coords operator+(Coords other){ +// return Coords(x+other.x, y+other.y); +// } - Coords operator-(Coords other){ - return Coords(x-other.x, y-other.y); - } -} +// Coords operator-(Coords other){ +// return Coords(x-other.x, y-other.y); +// } +// } -List tetrominoes = [Tetromino.Z, Tetromino.L, Tetromino.O, Tetromino.S, Tetromino.I, Tetromino.J, Tetromino.T]; -List>> shapes = [ - [ // Z - [Coords(0, 2), Coords(1, 2), Coords(1, 1), Coords(2, 1)], - [Coords(2, 2), Coords(2, 1), Coords(1, 1), Coords(1, 0)], - [Coords(2, 0), Coords(1, 0), Coords(1, 1), Coords(0, 1)], - [Coords(0, 0), Coords(0, 1), Coords(1, 1), Coords(1, 2)] - ], - [ // L - [Coords(2, 2), Coords(2, 1), Coords(1, 1), Coords(0, 1)], - [Coords(2, 0), Coords(1, 0), Coords(1, 1), Coords(1, 2)], - [Coords(0, 0), Coords(0, 1), Coords(1, 1), Coords(2, 1)], - [Coords(0, 2), Coords(1, 2), Coords(1, 1), Coords(1, 0)] - ], - [ // O - [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)], - [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)], - [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)], - [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)] - ], - [ // S - [Coords(2, 2), Coords(1, 2), Coords(1, 1), Coords(0, 1)], - [Coords(2, 0), Coords(2, 1), Coords(1, 1), Coords(1, 2)], - [Coords(0, 0), Coords(1, 0), Coords(1, 1), Coords(2, 1)], - [Coords(0, 2), Coords(0, 1), Coords(1, 1), Coords(1, 0)] - ], - [ // I - [Coords(0, 2), Coords(1, 2), Coords(2, 2), Coords(3, 2)], - [Coords(2, 3), Coords(2, 2), Coords(2, 1), Coords(2, 0)], - [Coords(3, 1), Coords(2, 1), Coords(1, 1), Coords(0, 1)], - [Coords(1, 0), Coords(1, 1), Coords(1, 2), Coords(1, 3)] - ], - [ // J - [Coords(0, 2), Coords(0, 1), Coords(1, 1), Coords(2, 1)], - [Coords(2, 2), Coords(1, 2), Coords(1, 1), Coords(1, 0)], - [Coords(2, 0), Coords(2, 1), Coords(1, 1), Coords(0, 1)], - [Coords(0, 0), Coords(1, 0), Coords(1, 1), Coords(1, 2)] - ], - [ // T - [Coords(1, 2), Coords(0, 1), Coords(1, 1), Coords(2, 1)], - [Coords(2, 1), Coords(1, 2), Coords(1, 1), Coords(1, 0)], - [Coords(1, 0), Coords(2, 1), Coords(1, 1), Coords(0, 1)], - [Coords(0, 1), Coords(1, 0), Coords(1, 1), Coords(1, 2)] - ] -]; -List spawnPositionFixes = [Coords(0, 0), Coords(0, 0), Coords(1, 1), Coords(0, 0), Coords(0, -1), Coords(0, 0), Coords(0, 0)]; +// List tetrominoes = [Tetromino.Z, Tetromino.L, Tetromino.O, Tetromino.S, Tetromino.I, Tetromino.J, Tetromino.T]; +// List>> shapes = [ +// [ // Z +// [Coords(0, 2), Coords(1, 2), Coords(1, 1), Coords(2, 1)], +// [Coords(2, 2), Coords(2, 1), Coords(1, 1), Coords(1, 0)], +// [Coords(2, 0), Coords(1, 0), Coords(1, 1), Coords(0, 1)], +// [Coords(0, 0), Coords(0, 1), Coords(1, 1), Coords(1, 2)] +// ], +// [ // L +// [Coords(2, 2), Coords(2, 1), Coords(1, 1), Coords(0, 1)], +// [Coords(2, 0), Coords(1, 0), Coords(1, 1), Coords(1, 2)], +// [Coords(0, 0), Coords(0, 1), Coords(1, 1), Coords(2, 1)], +// [Coords(0, 2), Coords(1, 2), Coords(1, 1), Coords(1, 0)] +// ], +// [ // O +// [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)], +// [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)], +// [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)], +// [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)] +// ], +// [ // S +// [Coords(2, 2), Coords(1, 2), Coords(1, 1), Coords(0, 1)], +// [Coords(2, 0), Coords(2, 1), Coords(1, 1), Coords(1, 2)], +// [Coords(0, 0), Coords(1, 0), Coords(1, 1), Coords(2, 1)], +// [Coords(0, 2), Coords(0, 1), Coords(1, 1), Coords(1, 0)] +// ], +// [ // I +// [Coords(0, 2), Coords(1, 2), Coords(2, 2), Coords(3, 2)], +// [Coords(2, 3), Coords(2, 2), Coords(2, 1), Coords(2, 0)], +// [Coords(3, 1), Coords(2, 1), Coords(1, 1), Coords(0, 1)], +// [Coords(1, 0), Coords(1, 1), Coords(1, 2), Coords(1, 3)] +// ], +// [ // J +// [Coords(0, 2), Coords(0, 1), Coords(1, 1), Coords(2, 1)], +// [Coords(2, 2), Coords(1, 2), Coords(1, 1), Coords(1, 0)], +// [Coords(2, 0), Coords(2, 1), Coords(1, 1), Coords(0, 1)], +// [Coords(0, 0), Coords(1, 0), Coords(1, 1), Coords(1, 2)] +// ], +// [ // T +// [Coords(1, 2), Coords(0, 1), Coords(1, 1), Coords(2, 1)], +// [Coords(2, 1), Coords(1, 2), Coords(1, 1), Coords(1, 0)], +// [Coords(1, 0), Coords(2, 1), Coords(1, 1), Coords(0, 1)], +// [Coords(0, 1), Coords(1, 0), Coords(1, 1), Coords(1, 2)] +// ] +// ]; +// List spawnPositionFixes = [Coords(0, 0), Coords(0, 0), Coords(1, 1), Coords(0, 0), Coords(0, -1), Coords(0, 0), Coords(0, 0)]; -const Map garbage = { - "single": 0, - "double": 1, - "triple": 2, - "quad": 4, - "penta": 5, - "t-spin": 0, - "t-spin single": 2, - "t-spin double": 4, - "t-spin triple": 6, - "t-spin quad": 10, - "t-spin penta": 12, - "t-spin mini": 0, - "t-spin mini single": 0, - "t-spin mini double": 1, - "allclear": 10 -}; -int btbBonus = 1; -double btbLog = 0.8; -double comboBonus = 0.25; -int comboMinifier = 1; -double comboMinifierLog = 1.25; -List comboTable = [0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5]; +// const Map garbage = { +// "single": 0, +// "double": 1, +// "triple": 2, +// "quad": 4, +// "penta": 5, +// "t-spin": 0, +// "t-spin single": 2, +// "t-spin double": 4, +// "t-spin triple": 6, +// "t-spin quad": 10, +// "t-spin penta": 12, +// "t-spin mini": 0, +// "t-spin mini single": 0, +// "t-spin mini double": 1, +// "allclear": 10 +// }; +// int btbBonus = 1; +// double btbLog = 0.8; +// double comboBonus = 0.25; +// int comboMinifier = 1; +// double comboMinifierLog = 1.25; +// List comboTable = [0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5]; -class KicksetBase { - List? additionalOffsets; - late List additionalOffsetEmpty; - List? spawnRotation; - late List>> kickTable; //kickTable[initRot][rotDirection-1][kick] - late List>> kickTableI; -} +// class KicksetBase { +// List? additionalOffsets; +// late List additionalOffsetEmpty; +// List? spawnRotation; +// late List>> kickTable; //kickTable[initRot][rotDirection-1][kick] +// late List>> kickTableI; +// } -class SRSPlus extends KicksetBase{ - SRSPlus(){ - kickTable = [ - [ - [Coords( 0, 0), Coords( 1, 0), Coords( 1, 1), Coords( 0,-2), Coords( 1,-2)], // 0 -> 270 - [Coords( 0, 0), Coords(-1, 0), Coords(-1, 1), Coords( 0,-2), Coords(-1,-2)], // 0 -> 90 - [Coords( 0, 0), Coords( 0, 1), Coords( 1, 1), Coords(-1, 1), Coords( 1, 0), Coords(-1, 0)], // 0 -> 180 - ], - [ - [Coords( 0, 0), Coords( 1, 0), Coords( 1,-1), Coords( 0, 2), Coords( 1, 2)], // 90 -> 0 - [Coords( 0, 0), Coords( 1, 0), Coords( 1,-1), Coords( 0, 2), Coords( 1, 2)], // 90 -> 180 - [Coords( 0, 0), Coords( 1, 0), Coords( 1, 2), Coords( 1, 1), Coords( 0, 2), Coords( 0, 1)], // 90 -> 270 - ], - [ - [Coords( 0, 0), Coords(-1, 0), Coords(-1, 1), Coords( 0,-2), Coords(-1,-2)], // 180 -> 90 - [Coords( 0, 0), Coords( 1, 0), Coords( 1, 1), Coords( 0,-2), Coords( 1,-2)], // 180 -> 270 - [Coords( 0, 0), Coords( 0,-1), Coords(-1,-1), Coords( 1,-1), Coords(-1, 0), Coords( 1, 0)], // 180 -> 0 - ], - [ - [Coords( 0, 0), Coords(-1, 0), Coords(-1,-1), Coords( 0, 2), Coords(-1, 2)], // 270 -> 180 - [Coords( 0, 0), Coords(-1, 0), Coords(-1,-1), Coords( 0, 2), Coords(-1, 2)], // 270 -> 0 - [Coords( 0, 0), Coords(-1, 0), Coords(-1, 2), Coords(-1, 1), Coords( 0, 2), Coords( 0, 1)], // 270 -> 90 - ] - ]; - kickTableI = [ - [ - [Coords( 0, 0), Coords(-1, 0), Coords( 2, 0), Coords( 2,-1), Coords(-1, 2)], // 0 -> 270 - [Coords( 0, 0), Coords( 1, 0), Coords( 2, 0), Coords(-1,-1), Coords( 1, 2)], // 0 -> 90 - [Coords( 0, 0), Coords( 0, 1)], // 0 -> 180 - ], - [ - [Coords( 0, 0), Coords(-1, 0), Coords( 2, 0), Coords(-1,-2), Coords( 2,-1)], // 90 -> 0 - [Coords( 0, 0), Coords(-1, 0), Coords( 2, 0), Coords(-1, 2), Coords( 2, 1)], // 90 -> 180 - [Coords( 0, 0), Coords( 1, 0)], // 90 -> 270 - ], - [ - [Coords( 0, 0), Coords(-2, 0), Coords( 1, 0), Coords(-2, 1), Coords( 1,-2)], // 180 -> 90 - [Coords( 0, 0), Coords(-2, 0), Coords(-1, 0), Coords( 2, 1), Coords(-1,-2)], // 180 -> 270 - [Coords( 0, 0), Coords( 0,-1)], // 180 -> 0 - ], - [ - [Coords( 0, 0), Coords( 1, 0), Coords(-2, 0), Coords( 1, 2), Coords(-2,-1)], // 270 -> 180 - [Coords( 0, 0), Coords( 1, 0), Coords(-2, 0), Coords( 1,-2), Coords(-2, 1)], // 270 -> 0 - [Coords( 0, 0), Coords(-1, 0)], // 270 -> 90 - ] - ]; - additionalOffsetEmpty = [Coords( 0, 0),Coords( 0, 0),Coords( 0, 0),Coords( 0, 0)]; - } -} +// class SRSPlus extends KicksetBase{ +// SRSPlus(){ +// kickTable = [ +// [ +// [Coords( 0, 0), Coords( 1, 0), Coords( 1, 1), Coords( 0,-2), Coords( 1,-2)], // 0 -> 270 +// [Coords( 0, 0), Coords(-1, 0), Coords(-1, 1), Coords( 0,-2), Coords(-1,-2)], // 0 -> 90 +// [Coords( 0, 0), Coords( 0, 1), Coords( 1, 1), Coords(-1, 1), Coords( 1, 0), Coords(-1, 0)], // 0 -> 180 +// ], +// [ +// [Coords( 0, 0), Coords( 1, 0), Coords( 1,-1), Coords( 0, 2), Coords( 1, 2)], // 90 -> 0 +// [Coords( 0, 0), Coords( 1, 0), Coords( 1,-1), Coords( 0, 2), Coords( 1, 2)], // 90 -> 180 +// [Coords( 0, 0), Coords( 1, 0), Coords( 1, 2), Coords( 1, 1), Coords( 0, 2), Coords( 0, 1)], // 90 -> 270 +// ], +// [ +// [Coords( 0, 0), Coords(-1, 0), Coords(-1, 1), Coords( 0,-2), Coords(-1,-2)], // 180 -> 90 +// [Coords( 0, 0), Coords( 1, 0), Coords( 1, 1), Coords( 0,-2), Coords( 1,-2)], // 180 -> 270 +// [Coords( 0, 0), Coords( 0,-1), Coords(-1,-1), Coords( 1,-1), Coords(-1, 0), Coords( 1, 0)], // 180 -> 0 +// ], +// [ +// [Coords( 0, 0), Coords(-1, 0), Coords(-1,-1), Coords( 0, 2), Coords(-1, 2)], // 270 -> 180 +// [Coords( 0, 0), Coords(-1, 0), Coords(-1,-1), Coords( 0, 2), Coords(-1, 2)], // 270 -> 0 +// [Coords( 0, 0), Coords(-1, 0), Coords(-1, 2), Coords(-1, 1), Coords( 0, 2), Coords( 0, 1)], // 270 -> 90 +// ] +// ]; +// kickTableI = [ +// [ +// [Coords( 0, 0), Coords(-1, 0), Coords( 2, 0), Coords( 2,-1), Coords(-1, 2)], // 0 -> 270 +// [Coords( 0, 0), Coords( 1, 0), Coords( 2, 0), Coords(-1,-1), Coords( 1, 2)], // 0 -> 90 +// [Coords( 0, 0), Coords( 0, 1)], // 0 -> 180 +// ], +// [ +// [Coords( 0, 0), Coords(-1, 0), Coords( 2, 0), Coords(-1,-2), Coords( 2,-1)], // 90 -> 0 +// [Coords( 0, 0), Coords(-1, 0), Coords( 2, 0), Coords(-1, 2), Coords( 2, 1)], // 90 -> 180 +// [Coords( 0, 0), Coords( 1, 0)], // 90 -> 270 +// ], +// [ +// [Coords( 0, 0), Coords(-2, 0), Coords( 1, 0), Coords(-2, 1), Coords( 1,-2)], // 180 -> 90 +// [Coords( 0, 0), Coords(-2, 0), Coords(-1, 0), Coords( 2, 1), Coords(-1,-2)], // 180 -> 270 +// [Coords( 0, 0), Coords( 0,-1)], // 180 -> 0 +// ], +// [ +// [Coords( 0, 0), Coords( 1, 0), Coords(-2, 0), Coords( 1, 2), Coords(-2,-1)], // 270 -> 180 +// [Coords( 0, 0), Coords( 1, 0), Coords(-2, 0), Coords( 1,-2), Coords(-2, 1)], // 270 -> 0 +// [Coords( 0, 0), Coords(-1, 0)], // 270 -> 90 +// ] +// ]; +// additionalOffsetEmpty = [Coords( 0, 0),Coords( 0, 0),Coords( 0, 0),Coords( 0, 0)]; +// } +// } diff --git a/lib/gen/strings.g.dart b/lib/gen/strings.g.dart index 6b05e47..42e4e73 100644 --- a/lib/gen/strings.g.dart +++ b/lib/gen/strings.g.dart @@ -6,7 +6,7 @@ /// Locales: 2 /// Strings: 1182 (591 per locale) /// -/// Built on 2024-06-16 at 21:03 UTC +/// Built on 2024-07-10 at 15:23 UTC // coverage:ignore-file // ignore_for_file: type=lint @@ -321,7 +321,7 @@ class Translations implements BaseTranslations { String get fromBeginning => 'From beginning'; String get calc => 'Calc'; String get calcViewNoValues => 'Enter values to calculate the stats'; - String get rankAveragesViewTitle => 'Ranks cutoff and average stats'; + String get rankAveragesViewTitle => 'Ranks cutoffs'; String get sprintAndBlitsViewTitle => '40 lines and Blitz averages'; String sprintAndBlitsRelevance({required Object date}) => 'Relevance: ${date}'; String get rank => 'Rank'; @@ -1016,7 +1016,7 @@ class _StringsRu implements Translations { @override String get fromBeginning => 'С начала'; @override String get calc => 'Считать'; @override String get calcViewNoValues => 'Введите значения, чтобы посчитать статистику'; - @override String get rankAveragesViewTitle => 'Требования рангов и средние значения'; + @override String get rankAveragesViewTitle => 'Требования рангов'; @override String get sprintAndBlitsViewTitle => 'Средние результаты 40 линий и блица'; @override String sprintAndBlitsRelevance({required Object date}) => 'Актуальность: ${date}'; @override String get rank => 'Ранг'; @@ -1703,7 +1703,7 @@ extension on Translations { case 'fromBeginning': return 'From beginning'; case 'calc': return 'Calc'; case 'calcViewNoValues': return 'Enter values to calculate the stats'; - case 'rankAveragesViewTitle': return 'Ranks cutoff and average stats'; + case 'rankAveragesViewTitle': return 'Ranks cutoffs'; case 'sprintAndBlitsViewTitle': return '40 lines and Blitz averages'; case 'sprintAndBlitsRelevance': return ({required Object date}) => 'Relevance: ${date}'; case 'rank': return 'Rank'; @@ -2314,7 +2314,7 @@ extension on _StringsRu { case 'fromBeginning': return 'С начала'; case 'calc': return 'Считать'; case 'calcViewNoValues': return 'Введите значения, чтобы посчитать статистику'; - case 'rankAveragesViewTitle': return 'Требования рангов и средние значения'; + case 'rankAveragesViewTitle': return 'Требования рангов'; case 'sprintAndBlitsViewTitle': return 'Средние результаты 40 линий и блица'; case 'sprintAndBlitsRelevance': return ({required Object date}) => 'Актуальность: ${date}'; case 'rank': return 'Ранг'; diff --git a/lib/services/tetrio_crud.dart b/lib/services/tetrio_crud.dart index df67f3d..d949867 100644 --- a/lib/services/tetrio_crud.dart +++ b/lib/services/tetrio_crud.dart @@ -606,7 +606,7 @@ class TetrioService extends DB { if (kIsWeb) { url = Uri.https('ts.dan63.by', 'oskware_bridge.php', {"endpoint": "TLMatches", "user": userID}); } else { - url = Uri.https('api.p1nkl0bst3r.xyz', 'tlmatches/$userID'); + url = Uri.https('api.p1nkl0bst3r.xyz', 'tlmatches/$userID', {"before": "66749c93ffcbce61b2a1d912"}); } try{ @@ -614,62 +614,9 @@ class TetrioService extends DB { switch (response.statusCode) { case 200: - // that one api returns csv instead of json - List> csv = const CsvToListConverter().convert(response.body)..removeAt(0); - List matches = []; - - // parsing data into TetraLeagueAlphaRecord objects - for (var entry in csv){ - TetraLeagueAlphaRecord match = TetraLeagueAlphaRecord( - replayId: entry[0].toString(), - ownId: entry[0].toString(), // i gonna disting p1nkl0bst3r entries with it - timestamp: DateTime.parse(entry[1]), - endContext: [ - EndContextMulti( - userId: entry[2].toString(), - username: entry[3].toString(), - naturalOrder: 0, - inputs: -1, - piecesPlaced: -1, - handling: Handling(arr: -1, das: -1, sdf: -1, dcd: 0, cancel: true, safeLock: true), - points: entry[4], - wins: entry[4], - secondary: entry[6], - secondaryTracking: [], - tertiary: entry[5], - tertiaryTracking: [], - extra: entry[7], - extraTracking: [], - success: true - ), - EndContextMulti( - userId: entry[8].toString(), - username: entry[9].toString(), - naturalOrder: 1, - inputs: -1, - piecesPlaced: -1, - handling: Handling(arr: -1, das: -1, sdf: -1, dcd: 0, cancel: true, safeLock: true), - points: entry[10], - wins: entry[10], - secondary: entry[12], - secondaryTracking: [], - tertiary: entry[11], - tertiaryTracking: [], - extra: entry[13], - extraTracking: [], - success: false - ) - ], - replayAvalable: false - ); - matches.add(match); - } - - // trying to dump it to local DB - TetraLeagueAlphaStream fakeStream = TetraLeagueAlphaStream(userId: userID, records: matches); - saveTLMatchesFromStream(fakeStream); - - return matches; + TetraLeagueAlphaStream stream = TetraLeagueAlphaStream.fromJson(jsonDecode(response.body)['data']['records'], userID); + saveTLMatchesFromStream(stream); + return stream.records; case 404: developer.log("fetchAndSaveOldTLmatches: Probably, history doesn't exist", name: "services/tetrio_crud", error: response.statusCode); throw TetrioHistoryNotExist(); diff --git a/lib/views/main_view.dart b/lib/views/main_view.dart index b3a845f..a95ff9b 100644 --- a/lib/views/main_view.dart +++ b/lib/views/main_view.dart @@ -306,7 +306,7 @@ class _MainState extends State with TickerProviderStateMixin { }); } - return [me, records, states, tlMatches, compareWith, isTracking, news, topTR, recent, sprint, blitz]; + return [me, records, states, tlMatches, compareWith, isTracking, news, topTR, recent, sprint, blitz, tlMatches.elementAtOrNull(0)?.timestamp]; } /// Triggers widgets rebuild @@ -459,6 +459,7 @@ class _MainState extends State with TickerProviderStateMixin { userID: snapshot.data![0].userId, states: snapshot.data![2], topTR: snapshot.data![7]?.tr, + lastMatchPlayed: snapshot.data![11], bot: snapshot.data![0].role == "bot", guest: snapshot.data![0].role == "anon", thatRankCutoff: thatRankCutoff, diff --git a/lib/views/ranks_averages_view.dart b/lib/views/ranks_averages_view.dart index 5b481b3..dbfa0e9 100644 --- a/lib/views/ranks_averages_view.dart +++ b/lib/views/ranks_averages_view.dart @@ -49,14 +49,13 @@ class RanksAverages extends State { child: averages.isEmpty ? const Center(child: Text('Fetching...')) : ListView.builder( itemCount: averages.length, itemBuilder: (context, index){ - bool bigScreen = MediaQuery.of(context).size.width > 768; List keys = averages.keys.toList(); return ListTile( leading: Image.asset("res/tetrio_tl_alpha_ranks/${keys[index]}.png", height: 48), title: Text(t.players(n: averages[keys[index]]?[1]["players"]), style: const TextStyle(fontFamily: "Eurostile Round Extended")), subtitle: Text("${f2.format(averages[keys[index]]?[0].apm)} APM, ${f2.format(averages[keys[index]]?[0].pps)} PPS, ${f2.format(averages[keys[index]]?[0].vs)} VS, ${f2.format(averages[keys[index]]?[0].nerdStats.app)} APP, ${f2.format(averages[keys[index]]?[0].nerdStats.vsapm)} VS/APM", - style: const TextStyle(fontFamily: "Eurostile Round Condensed", color: Colors.grey)), - trailing: Text("${f2.format(averages[keys[index]]?[1]["toEnterTR"])} TR", style: bigScreen ? const TextStyle(fontSize: 28) : null), + style: const TextStyle(fontFamily: "Eurostile Round Condensed", color: Colors.grey, fontSize: 13)), + trailing: Text("${f2.format(averages[keys[index]]?[1]["toEnterTR"])} TR", style: const TextStyle(fontSize: 28, fontFamily: "Eurostile Round")), onTap: (){ if (averages[keys[index]]?[1]["players"] > 0) { Navigator.push( diff --git a/lib/views/tl_leaderboard_view.dart b/lib/views/tl_leaderboard_view.dart index d69bff8..8b16a28 100644 --- a/lib/views/tl_leaderboard_view.dart +++ b/lib/views/tl_leaderboard_view.dart @@ -58,7 +58,7 @@ class TLLeaderboardState extends State { ); }, icon: const Icon(Icons.compress), - tooltip: t.averages, + tooltip: t.rankAveragesViewTitle, ), ], ), @@ -102,11 +102,11 @@ class TLLeaderboardState extends State { ), TextButton(onPressed: (){ Navigator.push( - context, - MaterialPageRoute( - builder: (context) => RankView(rank: snapshot.data!.getAverageOfRank("")), - ), - ); + context, + MaterialPageRoute( + builder: (context) => RankView(rank: snapshot.data!.getAverageOfRank("")), + ), + ); }, child: Text(t.everyoneAverages, style: const TextStyle(fontSize: 25))) ],) @@ -184,12 +184,12 @@ class TLLeaderboardState extends State { style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: bigScreen ? 28 : 24, height: 0.9) ), title: Text(allPlayers[index].username, style: TextStyle(fontFamily: bigScreen ? "Eurostile Round Extended" : "Eurostile Round", height: 0.9)), - subtitle: Text(_sortBy == Stats.tr ? "${f2.format(allPlayers[index].apm)} APM, ${f2.format(allPlayers[index].pps)} PPS, ${f2.format(allPlayers[index].vs)} VS, ${f2.format(allPlayers[index].nerdStats.app)} APP, ${f2.format(allPlayers[index].nerdStats.vsapm)} VS/APM" : "${_f4.format(allPlayers[index].getStatByEnum(_sortBy))} ${chartsShortTitles[_sortBy]}", - style: TextStyle(fontFamily: "Eurostile Round Condensed", fontSize: bigScreen ? null : 12, color: _sortBy == Stats.tr ? Colors.grey : null)), + subtitle: (bigScreen || _sortBy != Stats.tr) ? Text(_sortBy == Stats.tr ? "${f2.format(allPlayers[index].apm)} APM, ${f2.format(allPlayers[index].pps)} PPS, ${f2.format(allPlayers[index].vs)} VS, ${f2.format(allPlayers[index].nerdStats.app)} APP, ${f2.format(allPlayers[index].nerdStats.vsapm)} VS/APM" : "${_f4.format(allPlayers[index].getStatByEnum(_sortBy))} ${chartsShortTitles[_sortBy]}", + style: TextStyle(fontFamily: "Eurostile Round Condensed", fontSize: bigScreen ? null : 13, color: _sortBy == Stats.tr ? Colors.grey : null)) : null, trailing: Row( mainAxisSize: MainAxisSize.min, children: [ - Text("${f2.format(allPlayers[index].rating)} TR", style: TextStyle(fontSize: bigScreen ? 28 : 22)), + Text("${f2.format(allPlayers[index].rating)} TR", style: const TextStyle(fontSize: 28)), Image.asset("res/tetrio_tl_alpha_ranks/${allPlayers[index].rank}.png", height: bigScreen ? 48 : 36), ], ), diff --git a/lib/views/tl_match_view.dart b/lib/views/tl_match_view.dart index 96d23ae..7d001ae 100644 --- a/lib/views/tl_match_view.dart +++ b/lib/views/tl_match_view.dart @@ -269,7 +269,7 @@ class TlMatchResultState extends State { label: "Sent", higherIsBetter: true), CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].garbage.recived : snapshot.data!.stats[roundSelector][greenSidePlayer].garbage.recived, redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].garbage.recived : snapshot.data!.stats[roundSelector][redSidePlayer].garbage.recived, - label: "Recived", higherIsBetter: true), + label: "Received", higherIsBetter: true), CompareThingy(greenSide: roundSelector.isNegative ? snapshot.data!.totalStats[greenSidePlayer].garbage.attack : snapshot.data!.stats[roundSelector][greenSidePlayer].garbage.attack, redSide: roundSelector.isNegative ? snapshot.data!.totalStats[redSidePlayer].garbage.attack : snapshot.data!.stats[roundSelector][redSidePlayer].garbage.attack, label: "Attack", higherIsBetter: true), diff --git a/lib/widgets/tl_rating_thingy.dart b/lib/widgets/tl_rating_thingy.dart index 735b06c..f5c3e7e 100644 --- a/lib/widgets/tl_rating_thingy.dart +++ b/lib/widgets/tl_rating_thingy.dart @@ -1,3 +1,5 @@ +import 'dart:math'; + import 'package:flutter/material.dart'; import 'package:intl/intl.dart'; import 'package:tetra_stats/data_objects/tetrio.dart'; @@ -6,14 +8,16 @@ 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; final TetraLeagueAlpha tlData; final TetraLeagueAlpha? oldTl; final double? topTR; + final DateTime? lastMatchPlayed; - const TLRatingThingy({super.key, required this.userID, required this.tlData, this.oldTl, this.topTR}); + const TLRatingThingy({super.key, required this.userID, required this.tlData, this.oldTl, this.topTR, this.lastMatchPlayed}); @override Widget build(BuildContext context) { @@ -23,6 +27,11 @@ class TLRatingThingy extends StatelessWidget{ List formatedTR = f4.format(tlData.rating).split(decimalSeparator); List formatedGlicko = f4.format(tlData.glicko).split(decimalSeparator); List formatedPercentile = f4.format(tlData.percentile * 100).split(decimalSeparator); + 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, alignment: WrapAlignment.spaceAround, @@ -83,7 +92,8 @@ class TLRatingThingy extends StatelessWidget{ if (topTR != null) TextSpan(text: " (${f2.format(topTR)} TR)"), TextSpan(text: " • ${prefs.getInt("ratingMode") == 1 ? "${f2.format(tlData.rating)} TR • RD: " : "Glicko: ${f2.format(tlData.glicko!)}±"}"), TextSpan(text: f2.format(tlData.rd!), style: tlData.decaying ? TextStyle(color: tlData.rd! > 98 ? Colors.red : Colors.yellow) : null), - if (tlData.decaying) WidgetSpan(child: Icon(Icons.trending_up, color: tlData.rd! > 98 ? Colors.red : Colors.yellow,), alignment: PlaceholderAlignment.middle, baseline: TextBaseline.alphabetic) + if (tlData.decaying) WidgetSpan(child: Icon(Icons.trending_up, color: tlData.rd! > 98 ? Colors.red : Colors.yellow,), alignment: PlaceholderAlignment.middle, baseline: TextBaseline.alphabetic), + if (beforeS1end) tlData.rd! <= safeRD ? TextSpan(text: " (Safe)", style: TextStyle(color: Colors.greenAccent)) : TextSpan(text: " (> ${safeRD} RD !!!)", style: TextStyle(color: Colors.redAccent)) ], ), ), diff --git a/lib/widgets/tl_thingy.dart b/lib/widgets/tl_thingy.dart index 71f674e..95ffe97 100644 --- a/lib/widgets/tl_thingy.dart +++ b/lib/widgets/tl_thingy.dart @@ -31,7 +31,8 @@ class TLThingy extends StatefulWidget { final double? nextRankCutoff; final double? nextRankCutoffGlicko; final double? nextRankTarget; - const TLThingy({super.key, required this.tl, required this.userID, required this.states, this.showTitle = true, this.bot=false, this.guest=false, this.topTR, this.lbPositions, this.averages, this.nextRankCutoff, this.thatRankCutoff, this.thatRankCutoffGlicko, this.nextRankCutoffGlicko, this.nextRankTarget, this.thatRankTarget}); + final DateTime? lastMatchPlayed; + const TLThingy({super.key, required this.tl, required this.userID, required this.states, this.showTitle = true, this.bot=false, this.guest=false, this.topTR, this.lbPositions, this.averages, this.nextRankCutoff, this.thatRankCutoff, this.thatRankCutoffGlicko, this.nextRankCutoffGlicko, this.nextRankTarget, this.thatRankTarget, this.lastMatchPlayed}); @override State createState() => _TLThingyState(); @@ -92,7 +93,7 @@ class _TLThingyState extends State { }); }, ), - if (currentTl.gamesPlayed >= 10) TLRatingThingy(userID: widget.userID, tlData: currentTl, oldTl: oldTl, topTR: widget.topTR), + if (currentTl.gamesPlayed > 9) TLRatingThingy(userID: widget.userID, tlData: currentTl, oldTl: oldTl, topTR: widget.topTR, lastMatchPlayed: widget.lastMatchPlayed), if (currentTl.gamesPlayed > 9) TLProgress( tlData: currentTl, previousRankTRcutoff: widget.thatRankCutoff, diff --git a/pubspec.yaml b/pubspec.yaml index 24111e6..2007d63 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.0+20 +version: 1.6.1+21 environment: sdk: '>=3.0.0' diff --git a/res/i18n/strings.i18n.json b/res/i18n/strings.i18n.json index 3136a87..8dd3631 100644 --- a/res/i18n/strings.i18n.json +++ b/res/i18n/strings.i18n.json @@ -186,7 +186,7 @@ "fromBeginning": "From beginning", "calc": "Calc", "calcViewNoValues": "Enter values to calculate the stats", - "rankAveragesViewTitle": "Ranks cutoff and average stats", + "rankAveragesViewTitle": "Ranks cutoffs", "sprintAndBlitsViewTitle": "40 lines and Blitz averages", "sprintAndBlitsRelevance": "Relevance: ${date}", "rank": "Rank", diff --git a/res/i18n/strings_ru.i18n.json b/res/i18n/strings_ru.i18n.json index 00dbc00..63c49d5 100644 --- a/res/i18n/strings_ru.i18n.json +++ b/res/i18n/strings_ru.i18n.json @@ -186,7 +186,7 @@ "fromBeginning": "С начала", "calc": "Считать", "calcViewNoValues": "Введите значения, чтобы посчитать статистику", - "rankAveragesViewTitle": "Требования рангов и средние значения", + "rankAveragesViewTitle": "Требования рангов", "sprintAndBlitsViewTitle": "Средние результаты 40 линий и блица", "sprintAndBlitsRelevance": "Актуальность: ${date}", "rank": "Ранг", diff --git a/web/index.html b/web/index.html index ad7b67e..5626d5d 100644 --- a/web/index.html +++ b/web/index.html @@ -150,7 +150,7 @@ let tip = document.querySelector("#tip"); const tips = [ // Promoting Tetra Stats "native" - "Want a better perfomance?
Try out Tetra Stats Native", + "Want a better perfomance?
Try out Tetra Stats \"Native\"", "Imagine a world, where Tetra Stats was written in JS", "Welcome to fullscreen canvas", @@ -172,6 +172,7 @@ let appRunner = await engineInitializer.initializeEngine(); await appRunner.runApp(); preloader.classList.add("hidden"); + tip.classList.add("hidden"); } }); } catch (e){