Compare commits
15 Commits
5652efa02f
...
3bd5d94cef
Author | SHA1 | Date |
---|---|---|
dan63047 | 3bd5d94cef | |
dan63047 | 54a5cc683c | |
dan63047 | 29ac38c034 | |
dan63047 | 0e89b2bf3e | |
dan63047 | d34b072fcd | |
dan63047 | 1c29cce71b | |
dan63047 | f5baf493ca | |
dan63047 | f0d4d809a3 | |
dan63047 | ccb4909021 | |
dan63047 | 836f533e3a | |
dan63047 | f7a08286f8 | |
dan63047 | f42fcfc5f6 | |
dan63047 | 9096c423ce | |
dan63047 | 1824e353c3 | |
dan63047 | 232aa71e75 |
|
@ -1,25 +1,551 @@
|
|||
//import 'dart:convert';
|
||||
//import 'dart:io';
|
||||
// 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 'package:path_provider/path_provider.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
|
||||
|
||||
//import 'tetrio_multiplayer_replay.dart';
|
||||
// HandlingHandler(this.das, this.arr){
|
||||
// dasLeft = das;
|
||||
// arrLeft = arr;
|
||||
// }
|
||||
|
||||
/// That thing allows me to test my new staff i'm trying to implement
|
||||
//void main() async {
|
||||
// List<Tetromino> queue = List.from(tetrominoes);
|
||||
// TetrioRNG rng = TetrioRNG(0);
|
||||
// queue = rng.shuffleList(queue);
|
||||
// print(queue);
|
||||
// queue = List.from(tetrominoes);
|
||||
// queue = rng.shuffleList(queue);
|
||||
// print(queue);
|
||||
// @override
|
||||
// String toString(){
|
||||
// return "das: ${das}f; arr: ${arr}f";
|
||||
// }
|
||||
|
||||
// var downloadPath = await getDownloadsDirectory();
|
||||
// ReplayData replay = ReplayData.fromJson(jsonDecode(File("${downloadPath!.path}/65b504a9ade6d287b8427af0").readAsStringSync()));
|
||||
// List<List<Tetromino>> board = [for (var i = 0 ; i < 40; i++) [for (var i = 0 ; i < 10; i++) Tetromino.empty]];
|
||||
// print(replay.rawJson);
|
||||
// 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;
|
||||
// }
|
||||
|
||||
//print("");
|
||||
// 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;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// class Board{
|
||||
// int width;
|
||||
// int height;
|
||||
// int bufferHeight;
|
||||
// late List<List<Tetromino>> 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]];
|
||||
// }
|
||||
|
||||
// @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 positionIsValid(Tetromino type, Coords coords, int r){
|
||||
// List<Coords> 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;
|
||||
// }
|
||||
|
||||
// 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<Coords> 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<List<Tetromino>> 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<int> 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<Tetromino> 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;
|
||||
|
||||
// IncomingGarbage(this.data);
|
||||
|
||||
// @override
|
||||
// String toString(){
|
||||
// return "f$frameOfThreat: col${data.column} amt${data.amt}";
|
||||
// }
|
||||
|
||||
// void confirm(int confirmationFrame, int garbageSpeed){
|
||||
// frameOfThreat = confirmationFrame+garbageSpeed;
|
||||
// }
|
||||
// }
|
||||
|
||||
// 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);
|
||||
// }
|
||||
|
||||
// class Stats{
|
||||
// int combo = -1;
|
||||
// int btb = -1;
|
||||
// int attackRecived = 0;
|
||||
// int attackTanked = 0;
|
||||
|
||||
// LineClearResult processLineClear(List<int> 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{
|
||||
|
||||
// }
|
||||
|
||||
// // 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<Tetromino> queue = rng.shuffleList(tetrominoes.toList());
|
||||
// List<Event> events = readEventList(replay.rawJson);
|
||||
// DataFullOptions? settings;
|
||||
// HandlingHandler? handling;
|
||||
// Map<KeyType, EventKeyPress> 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<IncomingGarbage> 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)}");
|
||||
|
||||
// int sonicDrop(){
|
||||
// int height = coords.y;
|
||||
// while (board.positionIsValid(current, Coords(coords.x, height), rot)){
|
||||
// height -= 1;
|
||||
// }
|
||||
// height += 1;
|
||||
// return height;
|
||||
// }
|
||||
|
||||
// Tetromino getNewOne(){
|
||||
|
||||
// if (queue.length <= 1) {
|
||||
// List<Tetromino> 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<Coords> 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 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--;
|
||||
// }
|
||||
// }
|
||||
|
||||
// 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);
|
||||
//}
|
||||
// }
|
|
@ -897,11 +897,11 @@ class TetraLeagueAlphaRecord{
|
|||
TetraLeagueAlphaRecord({required this.replayId, required this.ownId, required this.timestamp, required this.endContext, required this.replayAvalable});
|
||||
|
||||
TetraLeagueAlphaRecord.fromJson(Map<String, dynamic> 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;
|
||||
replayAvalable = ownId != replayId;
|
||||
}
|
||||
|
||||
Map<String, dynamic> toJson() {
|
||||
|
@ -973,19 +973,19 @@ class EndContextMulti {
|
|||
EndContextMulti.fromJson(Map<String, dynamic> 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);
|
||||
|
|
|
@ -16,14 +16,14 @@ int biggestSpikeFromReplay(events){
|
|||
spikeCounter = event['data']['data']['data']['amt'];
|
||||
biggestSpike = spikeCounter;
|
||||
}else{
|
||||
if (event['data']['data']['frame'] - previousIGEeventFrame < 60){
|
||||
if ((event['data']['data']['frame']??event['data']['frame']) - previousIGEeventFrame < 60){
|
||||
spikeCounter = spikeCounter + event['data']['data']['data']['amt'] as int;
|
||||
}else{
|
||||
spikeCounter = event['data']['data']['data']['amt'];
|
||||
}
|
||||
biggestSpike = max(biggestSpike, spikeCounter);
|
||||
}
|
||||
previousIGEeventFrame = event['data']['data']['frame'];
|
||||
previousIGEeventFrame = event['data']['data']['frame']??event['data']['frame'];
|
||||
}
|
||||
}
|
||||
return biggestSpike;
|
||||
|
@ -216,8 +216,8 @@ class ReplayData{
|
|||
List<double> KPSmultipliedByWeights = [0, 0];
|
||||
totalStats = [ReplayStats.createEmpty(), ReplayStats.createEmpty()];
|
||||
for(var round in json['data']) {
|
||||
int firstInEndContext = round['replays'][0]["events"].last['data']['export']['options']['gameid'].startsWith(endcontext[0].userId) ? 0 : 1;
|
||||
int secondInEndContext = round['replays'][1]["events"].last['data']['export']['options']['gameid'].startsWith(endcontext[1].userId) ? 1 : 0;
|
||||
int firstInEndContext = round['replays'][0]["events"].last['data']['export']['options']['username'].startsWith(endcontext[0].username) ? 0 : 1;
|
||||
int secondInEndContext = round['replays'][1]["events"].last['data']['export']['options']['username'].startsWith(endcontext[1].username) ? 1 : 0;
|
||||
int roundLength = max(round['replays'][0]['frames'], round['replays'][1]['frames']);
|
||||
roundLengths.add(roundLength);
|
||||
totalLength = totalLength + max(round['replays'][0]['frames'], round['replays'][1]['frames']);
|
||||
|
@ -228,7 +228,7 @@ class ReplayData{
|
|||
VSmultipliedByWeights[0] += endcontext[0].extraTracking[roundID]*roundLength;
|
||||
VSmultipliedByWeights[1] += endcontext[1].extraTracking[roundID]*roundLength;
|
||||
int winner = round['board'].indexWhere((element) => element['success'] == true);
|
||||
roundWinners.add([round['board'][winner]['id'], round['board'][winner]['username']]);
|
||||
roundWinners.add([round['board'][winner]['id']??round['board'][winner]['user']['_id'], round['board'][winner]['username']??round['board'][winner]['user']['username']]);
|
||||
ReplayStats playerOne = ReplayStats.fromJson(round['replays'][firstInEndContext]['events'].last['data']['export']['stats'], biggestSpikeFromReplay(round['replays'][secondInEndContext]['events']), round['replays'][firstInEndContext]['frames']); // (events contain recived attacks)
|
||||
ReplayStats playerTwo = ReplayStats.fromJson(round['replays'][secondInEndContext]['events'].last['data']['export']['stats'], biggestSpikeFromReplay(round['replays'][firstInEndContext]['events']), round['replays'][secondInEndContext]['frames']);
|
||||
SPPmultipliedByWeights[0] += playerOne.spp*roundLength;
|
||||
|
@ -283,7 +283,7 @@ class ReplayData{
|
|||
// events.add(EventFull(id, frame, type, DataFull.fromJson(event["data"])));
|
||||
// break;
|
||||
// case EventType.targets:
|
||||
// // TODO
|
||||
// events.add(EventTargets(id, frame, type, Targets.fromJson(event["data"])));
|
||||
// break;
|
||||
// case EventType.keydown:
|
||||
// events.add(EventKeyPress(id, frame, type,
|
||||
|
@ -302,15 +302,24 @@ class ReplayData{
|
|||
// ));
|
||||
// break;
|
||||
// case EventType.end:
|
||||
// // TODO: Handle this case.
|
||||
// events.add(EventEnd(id, frame, type, EndData(event['data']['reason'], DataFull.fromJson(event['data']['export']))));
|
||||
// break;
|
||||
// case EventType.ige:
|
||||
// // TODO: Handle this case.
|
||||
// events.add(EventIGE(id, frame, type, IGE(
|
||||
// event['data']['id'],
|
||||
// event['data']['frame'],
|
||||
// event['data']['type'],
|
||||
// event['data']['data']
|
||||
// ))
|
||||
// );
|
||||
// break;
|
||||
// case EventType.exit:
|
||||
// // TODO: Handle this case.
|
||||
// events.add(Event(id, frame, type));
|
||||
// break;
|
||||
// }
|
||||
// id++;
|
||||
// }
|
||||
// return [];
|
||||
// return events;
|
||||
// }
|
||||
|
||||
// enum EventType
|
||||
|
@ -356,10 +365,12 @@ class ReplayData{
|
|||
|
||||
// class Keypress{
|
||||
// KeyType key;
|
||||
// double subframe;
|
||||
// late double subframe;
|
||||
// bool released;
|
||||
|
||||
// Keypress(this.key, this.subframe, this.released);
|
||||
// Keypress(this.key, num sframe, this.released){
|
||||
// subframe = sframe.toDouble();
|
||||
// }
|
||||
// }
|
||||
|
||||
// class EventKeyPress extends Event{
|
||||
|
@ -368,13 +379,144 @@ class ReplayData{
|
|||
// EventKeyPress(super.id, super.frame, super.type, this.data);
|
||||
// }
|
||||
|
||||
// class Targets{
|
||||
// String? id;
|
||||
// int? frame;
|
||||
// String? type;
|
||||
// List<dynamic>? data;
|
||||
|
||||
// Targets(this.id, this.frame, this.type, this.data);
|
||||
|
||||
// Targets.fromJson(Map<String, dynamic> json){
|
||||
// id = json["id"];
|
||||
// frame = json["frame"];
|
||||
// type = json["type"];
|
||||
// data = json["data"];
|
||||
// }
|
||||
// }
|
||||
|
||||
// class EventTargets extends Event{
|
||||
// Targets data;
|
||||
|
||||
// EventTargets(super.id, super.frame, super.type, this.data);
|
||||
// }
|
||||
|
||||
// class IGEdata{
|
||||
// late String type;
|
||||
// late String? gameid;
|
||||
// late int? frame;
|
||||
|
||||
// IGEdata.fromJson(Map<String, dynamic> d){
|
||||
// type = d['type'];
|
||||
// gameid = d['gameid'];
|
||||
// frame = d['frame'];
|
||||
// }
|
||||
// }
|
||||
|
||||
// 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;
|
||||
|
||||
// GarbageData.fromJson(Map<String, dynamic> 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<dynamic> targets;
|
||||
|
||||
// GarbageData? data;
|
||||
// //compatibility for v15 targets event
|
||||
// String? sender_id;
|
||||
|
||||
// IGEdataTarget.fromJson(Map<String, dynamic> d) : super.fromJson(d){
|
||||
// targets = d['targets'];
|
||||
// data = d['data'] != null ? GarbageData.fromJson(d['data']) : null;
|
||||
// }
|
||||
// }
|
||||
|
||||
// class IGEdataAllowTargeting extends IGEdata{
|
||||
// late bool value;
|
||||
|
||||
// IGEdataAllowTargeting.fromJson(Map<String, dynamic> 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;
|
||||
|
||||
|
||||
// IGEdataInteraction.fromJson(Map<String, dynamic> 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;
|
||||
// int amount;
|
||||
// late IGEdata data;
|
||||
|
||||
// IGE(this.id, this.frame, this.type, this.amount);
|
||||
// IGE(this.id, this.frame, this.type, Map<String, dynamic> 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{
|
||||
|
@ -383,6 +525,19 @@ class ReplayData{
|
|||
// EventIGE(super.id, super.frame, super.type, this.data);
|
||||
// }
|
||||
|
||||
// class EndData {
|
||||
// String reason;
|
||||
// DataFull export;
|
||||
|
||||
// EndData(this.reason, this.export);
|
||||
// }
|
||||
|
||||
// class EventEnd extends Event{
|
||||
// EndData data;
|
||||
|
||||
// EventEnd(super.id, super.frame, super.type, this.data);
|
||||
// }
|
||||
|
||||
// class Hold
|
||||
// {
|
||||
// String? piece;
|
||||
|
@ -434,8 +589,9 @@ class ReplayData{
|
|||
// stock = json["stock"];
|
||||
// gMargin = json["gmargin"];
|
||||
// gIncrease = json["gincrease"];
|
||||
// garbageMultiplier = json["garbagemultiplier"];
|
||||
// garbageCapIncrease = json["garbagecapincrease"];
|
||||
// garbageMultiplier = json["garbagemultiplier"].toDouble();
|
||||
// garbageCap = json["garbagecap"];
|
||||
// garbageCapIncrease = json["garbagecapincrease"].toDouble();
|
||||
// garbageCapMax = json["garbagecapmax"];
|
||||
// garbageHoleSize = json["garbageholesize"];
|
||||
// garbageBlocking = json["garbageblocking"];
|
||||
|
@ -462,7 +618,7 @@ class ReplayData{
|
|||
|
||||
// class DataFullStats
|
||||
// {
|
||||
// double? seed;
|
||||
// int? seed;
|
||||
// int? lines;
|
||||
// int? levelLines;
|
||||
// int? levelLinesNeeded;
|
||||
|
@ -511,8 +667,8 @@ class ReplayData{
|
|||
|
||||
// class DataFullGame
|
||||
// {
|
||||
// List<List<String?>>? board;
|
||||
// List<String>? bag;
|
||||
// List<dynamic>? board;
|
||||
// List<dynamic>? bag;
|
||||
// double? g;
|
||||
// bool? playing;
|
||||
// Hold? hold;
|
||||
|
@ -595,54 +751,74 @@ class ReplayData{
|
|||
// empty
|
||||
// }
|
||||
|
||||
// class Coords{
|
||||
// int x;
|
||||
// int y;
|
||||
|
||||
// Coords(this.x, this.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);
|
||||
// }
|
||||
// }
|
||||
|
||||
// List<Tetromino> tetrominoes = [Tetromino.Z, Tetromino.L, Tetromino.O, Tetromino.S, Tetromino.I, Tetromino.J, Tetromino.T];
|
||||
// List<List<List<Vector2>>> shapes = [
|
||||
// List<List<List<Coords>>> shapes = [
|
||||
// [ // Z
|
||||
// [Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(2, 1)],
|
||||
// [Vector2(2, 0), Vector2(1, 1), Vector2(2, 1), Vector2(1, 2)],
|
||||
// [Vector2(0, 1), Vector2(1, 1), Vector2(1, 2), Vector2(2, 2)],
|
||||
// [Vector2(1, 0), Vector2(0, 1), Vector2(1, 1), Vector2(0, 2)]
|
||||
// [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
|
||||
// [Vector2(2, 0), Vector2(0, 1), Vector2(1, 1), Vector2(2, 1)],
|
||||
// [Vector2(1, 0), Vector2(1, 1), Vector2(1, 2), Vector2(2, 2)],
|
||||
// [Vector2(0, 1), Vector2(1, 1), Vector2(2, 1), Vector2(0, 2)],
|
||||
// [Vector2(0, 0), Vector2(1, 0), Vector2(1, 1), Vector2(1, 2)]
|
||||
// [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
|
||||
// [Vector2(0, 0), Vector2(1, 0), Vector2(0, 1), Vector2(1, 1)],
|
||||
// [Vector2(0, 0), Vector2(1, 0), Vector2(0, 1), Vector2(1, 1)],
|
||||
// [Vector2(0, 0), Vector2(1, 0), Vector2(0, 1), Vector2(1, 1)],
|
||||
// [Vector2(0, 0), Vector2(1, 0), Vector2(0, 1), Vector2(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)],
|
||||
// [Coords(0, 0), Coords(1, 0), Coords(0, 1), Coords(1, 1)]
|
||||
// ],
|
||||
// [ // S
|
||||
// [Vector2(1, 0), Vector2(2, 0), Vector2(0, 1), Vector2(1, 1)],
|
||||
// [Vector2(1, 0), Vector2(1, 1), Vector2(2, 1), Vector2(2, 2)],
|
||||
// [Vector2(1, 1), Vector2(2, 1), Vector2(0, 2), Vector2(1, 2)],
|
||||
// [Vector2(0, 0), Vector2(0, 1), Vector2(1, 1), Vector2(1, 2)]
|
||||
// [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
|
||||
// [Vector2(0, 1), Vector2(1, 1), Vector2(2, 1), Vector2(3, 1)],
|
||||
// [Vector2(2, 0), Vector2(2, 1), Vector2(2, 2), Vector2(2, 3)],
|
||||
// [Vector2(0, 2), Vector2(1, 2), Vector2(2, 2), Vector2(3, 2)],
|
||||
// [Vector2(1, 0), Vector2(1, 1), Vector2(1, 2), Vector2(1, 3)]
|
||||
// [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
|
||||
// [Vector2(0, 0), Vector2(0, 1), Vector2(1, 1), Vector2(2, 1)],
|
||||
// [Vector2(1, 0), Vector2(2, 0), Vector2(1, 1), Vector2(1, 2)],
|
||||
// [Vector2(0, 1), Vector2(1, 1), Vector2(2, 1), Vector2(2, 2)],
|
||||
// [Vector2(1, 0), Vector2(1, 1), Vector2(0, 2), Vector2(1, 2)]
|
||||
// [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
|
||||
// [Vector2(1, 0), Vector2(0, 1), Vector2(1, 1), Vector2(2, 1)],
|
||||
// [Vector2(1, 0), Vector2(1, 1), Vector2(2, 1), Vector2(1, 2)],
|
||||
// [Vector2(0, 1), Vector2(1, 1), Vector2(2, 1), Vector2(1, 2)],
|
||||
// [Vector2(1, 0), Vector2(0, 1), Vector2(1, 1), Vector2(1, 2)]
|
||||
// [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<Vector2> spawnPositionFixes = [Vector2(1, 1), Vector2(1, 1), Vector2(0, 1), Vector2(1, 1), Vector2(1, 1), Vector2(1, 1), Vector2(1, 1)];
|
||||
// List<Coords> spawnPositionFixes = [Coords(0, 0), Coords(0, 0), Coords(1, 1), Coords(0, 0), Coords(0, -1), Coords(0, 0), Coords(0, 0)];
|
||||
|
||||
// const Map<String, double> garbage = {
|
||||
// const Map<String, int> garbage = {
|
||||
// "single": 0,
|
||||
// "double": 1,
|
||||
// "triple": 2,
|
||||
|
@ -665,3 +841,61 @@ class ReplayData{
|
|||
// int comboMinifier = 1;
|
||||
// double comboMinifierLog = 1.25;
|
||||
// List<int> comboTable = [0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5];
|
||||
|
||||
// class KicksetBase {
|
||||
// List<Coords>? additionalOffsets;
|
||||
// late List<Coords> additionalOffsetEmpty;
|
||||
// List<int>? spawnRotation;
|
||||
// late List<List<List<Coords>>> kickTable; //kickTable[initRot][rotDirection-1][kick]
|
||||
// late List<List<List<Coords>>> 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)];
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -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<AppLocale, Translations> {
|
|||
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 'Ранг';
|
||||
|
|
|
@ -379,7 +379,6 @@ class TetrioService extends DB {
|
|||
TopTr result = TopTr(id, null);
|
||||
developer.log("fetchTopTR: Probably, player doesn't have top TR", name: "services/tetrio_crud", error: response.statusCode);
|
||||
_cache.store(result, DateTime.now().millisecondsSinceEpoch + 300000);
|
||||
//_topTRcache[(DateTime.now().millisecondsSinceEpoch + 300000).toString()] = {id: null};
|
||||
return result;
|
||||
// if not 200 or 404 - throw a unique for each code exception
|
||||
case 403:
|
||||
|
@ -392,7 +391,10 @@ class TetrioService extends DB {
|
|||
case 502:
|
||||
case 503:
|
||||
case 504:
|
||||
throw P1nkl0bst3rInternalProblem();
|
||||
TopTr result = TopTr(id, null);
|
||||
developer.log("fetchTopTR: API returned ${response.statusCode}", name: "services/tetrio_crud", error: response.statusCode);
|
||||
//_cache.store(result, DateTime.now().millisecondsSinceEpoch + 300000);
|
||||
return result;
|
||||
default:
|
||||
developer.log("fetchTopTR: Failed to fetch top TR", name: "services/tetrio_crud", error: response.statusCode);
|
||||
throw ConnectionIssue(response.statusCode, response.reasonPhrase??"No reason");
|
||||
|
@ -445,7 +447,8 @@ class TetrioService extends DB {
|
|||
case 502:
|
||||
case 503:
|
||||
case 504:
|
||||
throw P1nkl0bst3rInternalProblem();
|
||||
developer.log("fetchCutoffs: Cutoffs are unavalable (${response.statusCode})", name: "services/tetrio_crud", error: response.statusCode);
|
||||
return null;
|
||||
default:
|
||||
developer.log("fetchCutoffs: Failed to fetch top Cutoffs", name: "services/tetrio_crud", error: response.statusCode);
|
||||
throw ConnectionIssue(response.statusCode, response.reasonPhrase??"No reason");
|
||||
|
@ -603,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": "0", "count": "9000"});
|
||||
}
|
||||
|
||||
try{
|
||||
|
@ -611,62 +614,9 @@ class TetrioService extends DB {
|
|||
|
||||
switch (response.statusCode) {
|
||||
case 200:
|
||||
// that one api returns csv instead of json
|
||||
List<List<dynamic>> csv = const CsvToListConverter().convert(response.body)..removeAt(0);
|
||||
List<TetraLeagueAlphaRecord> 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();
|
||||
|
|
|
@ -306,7 +306,7 @@ class _MainState extends State<MainView> 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<MainView> 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,
|
||||
|
@ -1084,7 +1085,7 @@ class _TwoRecordsThingy extends StatelessWidget {
|
|||
if (sprint != null) FinesseThingy(sprint?.endContext.finesse, sprint?.endContext.finessePercentage),
|
||||
if (sprint != null) LineclearsThingy(sprint!.endContext.clears, sprint!.endContext.lines, sprint!.endContext.holds, sprint!.endContext.tSpins),
|
||||
if (sprint != null) Text("${sprint!.endContext.inputs} KP • ${f2.format(sprint!.endContext.kps)} KPS"),
|
||||
Wrap(
|
||||
if (sprint != null) Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
crossAxisAlignment: WrapCrossAlignment.start,
|
||||
spacing: 20,
|
||||
|
@ -1170,7 +1171,7 @@ class _TwoRecordsThingy extends StatelessWidget {
|
|||
if (blitz != null) FinesseThingy(blitz?.endContext.finesse, blitz?.endContext.finessePercentage),
|
||||
if (blitz != null) LineclearsThingy(blitz!.endContext.clears, blitz!.endContext.lines, blitz!.endContext.holds, blitz!.endContext.tSpins),
|
||||
if (blitz != null) Text("${blitz!.endContext.piecesPlaced} P • ${blitz!.endContext.inputs} KP • ${f2.format(blitz!.endContext.kpp)} KPP • ${f2.format(blitz!.endContext.kps)} KPS"),
|
||||
Wrap(
|
||||
if (blitz != null) Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
crossAxisAlignment: WrapCrossAlignment.start,
|
||||
spacing: 20,
|
||||
|
@ -1184,7 +1185,7 @@ class _TwoRecordsThingy extends StatelessWidget {
|
|||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
for (int i = 1; i < sprintStream.records.length; i++) ListTile(
|
||||
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",
|
||||
|
|
|
@ -49,14 +49,13 @@ class RanksAverages extends State<RankAveragesView> {
|
|||
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<String> 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(
|
||||
|
|
|
@ -288,6 +288,13 @@ class SettingsState extends State<SettingsView> {
|
|||
subtitle: Text(t.aboutAppText(appName: packageInfo.appName, packageName: packageInfo.packageName, version: packageInfo.version, buildNumber: packageInfo.buildNumber)),
|
||||
trailing: const Icon(Icons.arrow_right)
|
||||
),
|
||||
// Wrap(
|
||||
// alignment: WrapAlignment.center,
|
||||
// spacing: 8,
|
||||
// children: [
|
||||
// TextButton(child: Text("Donate to me"), onPressed: (){},),TextButton(child: Text("Donate to NOT me"), onPressed: (){},),TextButton(child: Text("Donate to someone else"), onPressed: (){},),
|
||||
// ],
|
||||
// ),
|
||||
],
|
||||
)),
|
||||
);
|
||||
|
|
|
@ -58,7 +58,7 @@ class TLLeaderboardState extends State<TLLeaderboardView> {
|
|||
);
|
||||
},
|
||||
icon: const Icon(Icons.compress),
|
||||
tooltip: t.averages,
|
||||
tooltip: t.rankAveragesViewTitle,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
@ -102,11 +102,11 @@ class TLLeaderboardState extends State<TLLeaderboardView> {
|
|||
),
|
||||
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<TLLeaderboardView> {
|
|||
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),
|
||||
],
|
||||
),
|
||||
|
|
|
@ -269,7 +269,7 @@ class TlMatchResultState extends State<TlMatchResultView> {
|
|||
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),
|
||||
|
|
|
@ -126,7 +126,7 @@ class SingleplayerRecord extends StatelessWidget {
|
|||
LineclearsThingy(record!.endContext.clears, record!.endContext.lines, record!.endContext.holds, record!.endContext.tSpins),
|
||||
if (record!.endContext.gameType == "40l") Text("${record!.endContext.inputs} KP • ${f2.format(record!.endContext.kps)} KPS"),
|
||||
if (record!.endContext.gameType == "blitz") Text("${record!.endContext.piecesPlaced} P • ${record!.endContext.inputs} KP • ${f2.format(record!.endContext.kpp)} KPP • ${f2.format(record!.endContext.kps)} KPS"),
|
||||
Wrap(
|
||||
if (record != null) Wrap(
|
||||
alignment: WrapAlignment.spaceBetween,
|
||||
crossAxisAlignment: WrapCrossAlignment.start,
|
||||
spacing: 20,
|
||||
|
|
|
@ -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<String> formatedTR = f4.format(tlData.rating).split(decimalSeparator);
|
||||
List<String> formatedGlicko = f4.format(tlData.glicko).split(decimalSeparator);
|
||||
List<String> 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))
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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<TLThingy> createState() => _TLThingyState();
|
||||
|
@ -57,8 +58,8 @@ class _TLThingyState extends State<TLThingy> {
|
|||
Widget build(BuildContext context) {
|
||||
final t = Translations.of(context);
|
||||
String decimalSeparator = f2.symbols.DECIMAL_SEP;
|
||||
List<String> estTRformated = f2.format(currentTl.estTr!.esttr).split(decimalSeparator);
|
||||
List<String> estTRaccFormated = intFDiff.format(currentTl.esttracc!).split(".");
|
||||
List<String> estTRformated = currentTl.estTr != null ? f2.format(currentTl.estTr!.esttr).split(decimalSeparator) : [];
|
||||
List<String> estTRaccFormated = currentTl.esttracc != null ? intFDiff.format(currentTl.esttracc!).split(".") : [];
|
||||
if (currentTl.gamesPlayed == 0) return Center(child: Text(widget.guest ? t.anonTL : widget.bot ? t.botTL : t.neverPlayedTL, style: const TextStyle(fontFamily: "Eurostile Round", fontSize: 28), textAlign: TextAlign.center,));
|
||||
return LayoutBuilder(builder: (context, constraints) {
|
||||
bool bigScreen = constraints.maxWidth >= 768;
|
||||
|
@ -92,7 +93,7 @@ class _TLThingyState extends State<TLThingy> {
|
|||
});
|
||||
},
|
||||
),
|
||||
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,
|
||||
|
|
|
@ -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'
|
||||
|
|
|
@ -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",
|
||||
|
|
|
@ -186,7 +186,7 @@
|
|||
"fromBeginning": "С начала",
|
||||
"calc": "Считать",
|
||||
"calcViewNoValues": "Введите значения, чтобы посчитать статистику",
|
||||
"rankAveragesViewTitle": "Требования рангов и средние значения",
|
||||
"rankAveragesViewTitle": "Требования рангов",
|
||||
"sprintAndBlitsViewTitle": "Средние результаты 40 линий и блица",
|
||||
"sprintAndBlitsRelevance": "Актуальность: ${date}",
|
||||
"rank": "Ранг",
|
||||
|
|
|
@ -80,6 +80,9 @@
|
|||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
a{
|
||||
color: aqua;
|
||||
}
|
||||
#preloader{
|
||||
display: flex;
|
||||
width: fit-content;
|
||||
|
@ -111,6 +114,15 @@
|
|||
padding-top: 8px;
|
||||
animation: 1s cubic-bezier(.46,.03,.52,.96) infinite alternate breathing;
|
||||
}
|
||||
.error{
|
||||
color: red;
|
||||
}
|
||||
#tip{
|
||||
position: absolute;
|
||||
bottom: 5%;
|
||||
color: gray;
|
||||
text-align: center;
|
||||
}
|
||||
@media (max-width: 502px){
|
||||
#preloader{
|
||||
flex-direction: column;
|
||||
|
@ -130,24 +142,45 @@
|
|||
<p id="progress">Loading...</p>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
<p id="tip"></p>
|
||||
<script>
|
||||
window.addEventListener('load', function(ev) {
|
||||
let progress = document.querySelector("#progress");
|
||||
let preloader = document.querySelector("#preloader");
|
||||
// Download main.dart.js
|
||||
_flutter.loader.loadEntrypoint({
|
||||
serviceWorker: {
|
||||
serviceWorkerVersion: serviceWorkerVersion,
|
||||
},
|
||||
onEntrypointLoaded: async function(engineInitializer) {
|
||||
console.log(serviceWorkerVersion);
|
||||
let appRunner = await engineInitializer.initializeEngine();
|
||||
progress.innerHTML = "Booting...";
|
||||
await appRunner.runApp();
|
||||
preloader.classList.add("hidden");
|
||||
}
|
||||
});
|
||||
});
|
||||
let progress = document.querySelector("#progress");
|
||||
let preloader = document.querySelector("#preloader");
|
||||
let tip = document.querySelector("#tip");
|
||||
const tips = [
|
||||
// Promoting Tetra Stats "native"
|
||||
"Want a better perfomance?<br><a href=\"https://github.com/dan63047/TetraStats/releases\">Try out Tetra Stats \"Native\"</a>",
|
||||
"Imagine a world, where Tetra Stats was written in JS",
|
||||
"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"
|
||||
];
|
||||
tip.innerHTML = tips[Math.floor(Math.random() * tips.length)];
|
||||
try{
|
||||
// Download main.dart.js
|
||||
_flutter.loader.loadEntrypoint({
|
||||
serviceWorker: {
|
||||
serviceWorkerVersion: serviceWorkerVersion,
|
||||
},
|
||||
onEntrypointLoaded: async function(engineInitializer) {
|
||||
console.log(serviceWorkerVersion);
|
||||
progress.innerHTML = "Booting...";
|
||||
let appRunner = await engineInitializer.initializeEngine();
|
||||
await appRunner.runApp();
|
||||
preloader.classList.add("hidden");
|
||||
tip.classList.add("hidden");
|
||||
}
|
||||
});
|
||||
} catch (e){
|
||||
progress.classList.add("error");
|
||||
document.getAnimations()[0].cancel();
|
||||
progress.innerHTML = "fuck: "+e;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
Loading…
Reference in New Issue