diff --git a/.gitignore b/.gitignore
index 5836224..0946412 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,44 +1,44 @@
-# Miscellaneous
-*.class
-*.log
-*.pyc
-*.swp
-.DS_Store
-.atom/
-.buildlog/
-.history
-.svn/
-migrate_working_dir/
-
-# IntelliJ related
-*.iml
-*.ipr
-*.iws
-.idea/
-
-# The .vscode folder contains launch configuration and tasks you configure in
-# VS Code which you may wish to be included in version control, so this line
-# is commented out by default.
-.vscode/
-
-# Flutter/Dart/Pub related
-**/doc/api/
-**/ios/Flutter/.last_build_id
-.dart_tool/
-.flutter-plugins
-.flutter-plugins-dependencies
-.packages
-.pub-cache/
-.pub/
-/build/
-
-# Symbolication related
-app.*.symbols
-
-# Obfuscation related
-app.*.map.json
-
-# Android Studio will place build artifacts here
-/android/app/debug
-/android/app/profile
-/android/app/release
+# Miscellaneous
+*.class
+*.log
+*.pyc
+*.swp
+.DS_Store
+.atom/
+.buildlog/
+.history
+.svn/
+migrate_working_dir/
+
+# IntelliJ related
+*.iml
+*.ipr
+*.iws
+.idea/
+
+# The .vscode folder contains launch configuration and tasks you configure in
+# VS Code which you may wish to be included in version control, so this line
+# is commented out by default.
+.vscode/
+
+# Flutter/Dart/Pub related
+**/doc/api/
+**/ios/Flutter/.last_build_id
+.dart_tool/
+.flutter-plugins
+.flutter-plugins-dependencies
+.packages
+.pub-cache/
+.pub/
+/build/
+
+# Symbolication related
+app.*.symbols
+
+# Obfuscation related
+app.*.map.json
+
+# Android Studio will place build artifacts here
+/android/app/debug
+/android/app/profile
+/android/app/release
diff --git a/README.md b/README.md
index f17f43e..5aa643d 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,30 @@
-# tetra_stats
-
-Track your and other players stats in TETR.IO
-
-## I just only started, idk when this gonna be done.
+# Tetra Stats
+
+
Track your and other players stats in TETR.IO
+
+![Screenshot of the app](https://imgur.com/GGL0fux.png)
+
+# Development Roadmap
+- ~~Ability to fetch player~~
+- ~~Serialization/Deserialization~~
+- ~~Sqlite Database and service, that can work with it~~ *v0.0.2*
+- ~~Ability to track player~~
+- ~~Ability to compare 2 players~~ *v0.1.0, we are here*
+- ~~Stats Calculator~~ *dev build are here*
+- Ability to compare player with himself in past
+- Tetra League matches history
+- Tetra League historic charts for tracked players (maybe even same sh*t for 40l and blitz well see)
+- Better UI with delta and hints for stats *that will be v0.2.0*
+- Ability to compare player with APM-PPS-VS stats
+- Ability to fetch Tetra League leaderboard
+- Average stats for ranks
+- Ability to compare player with avgRank
+- UI Animations
+- i18n, EN and RU locales
+- Talk with osk about CORS and EndContext in TL matches
+- RELEASE ???
+
+---
+
+Special thanks to kerrmunism for formulas
+and to osk for TETR.IO
\ No newline at end of file
diff --git a/analysis_options.yaml b/analysis_options.yaml
index 61b6c4d..a7acf24 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -1,29 +1,29 @@
-# This file configures the analyzer, which statically analyzes Dart code to
-# check for errors, warnings, and lints.
-#
-# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
-# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
-# invoked from the command line by running `flutter analyze`.
-
-# The following line activates a set of recommended lints for Flutter apps,
-# packages, and plugins designed to encourage good coding practices.
-include: package:flutter_lints/flutter.yaml
-
-linter:
- # The lint rules applied to this project can be customized in the
- # section below to disable rules from the `package:flutter_lints/flutter.yaml`
- # included above or to enable additional rules. A list of all available lints
- # and their documentation is published at
- # https://dart-lang.github.io/linter/lints/index.html.
- #
- # Instead of disabling a lint rule for the entire project in the
- # section below, it can also be suppressed for a single line of code
- # or a specific dart file by using the `// ignore: name_of_lint` and
- # `// ignore_for_file: name_of_lint` syntax on the line or in the file
- # producing the lint.
- rules:
- # avoid_print: false # Uncomment to disable the `avoid_print` rule
- # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
-
-# Additional information about this file can be found at
-# https://dart.dev/guides/language/analysis-options
+# This file configures the analyzer, which statically analyzes Dart code to
+# check for errors, warnings, and lints.
+#
+# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
+# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
+# invoked from the command line by running `flutter analyze`.
+
+# The following line activates a set of recommended lints for Flutter apps,
+# packages, and plugins designed to encourage good coding practices.
+include: package:flutter_lints/flutter.yaml
+
+linter:
+ # The lint rules applied to this project can be customized in the
+ # section below to disable rules from the `package:flutter_lints/flutter.yaml`
+ # included above or to enable additional rules. A list of all available lints
+ # and their documentation is published at
+ # https://dart-lang.github.io/linter/lints/index.html.
+ #
+ # Instead of disabling a lint rule for the entire project in the
+ # section below, it can also be suppressed for a single line of code
+ # or a specific dart file by using the `// ignore: name_of_lint` and
+ # `// ignore_for_file: name_of_lint` syntax on the line or in the file
+ # producing the lint.
+ rules:
+ # avoid_print: false # Uncomment to disable the `avoid_print` rule
+ # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
+
+# Additional information about this file can be found at
+# https://dart.dev/guides/language/analysis-options
diff --git a/android/.gitignore b/android/.gitignore
index 6f56801..5d99765 100644
--- a/android/.gitignore
+++ b/android/.gitignore
@@ -1,13 +1,13 @@
-gradle-wrapper.jar
-/.gradle
-/captures/
-/gradlew
-/gradlew.bat
-/local.properties
-GeneratedPluginRegistrant.java
-
-# Remember to never publicly share your keystore.
-# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
-key.properties
-**/*.keystore
-**/*.jks
+gradle-wrapper.jar
+/.gradle
+/captures/
+/gradlew
+/gradlew.bat
+/local.properties
+GeneratedPluginRegistrant.java
+
+# Remember to never publicly share your keystore.
+# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
+key.properties
+**/*.keystore
+**/*.jks
diff --git a/android/app/build.gradle b/android/app/build.gradle
index cc022d3..3863f27 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -1,71 +1,71 @@
-def localProperties = new Properties()
-def localPropertiesFile = rootProject.file('local.properties')
-if (localPropertiesFile.exists()) {
- localPropertiesFile.withReader('UTF-8') { reader ->
- localProperties.load(reader)
- }
-}
-
-def flutterRoot = localProperties.getProperty('flutter.sdk')
-if (flutterRoot == null) {
- throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
-}
-
-def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
-if (flutterVersionCode == null) {
- flutterVersionCode = '1'
-}
-
-def flutterVersionName = localProperties.getProperty('flutter.versionName')
-if (flutterVersionName == null) {
- flutterVersionName = '1.0'
-}
-
-apply plugin: 'com.android.application'
-apply plugin: 'kotlin-android'
-apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
-
-android {
- compileSdkVersion flutter.compileSdkVersion
- ndkVersion flutter.ndkVersion
-
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-
- kotlinOptions {
- jvmTarget = '1.8'
- }
-
- sourceSets {
- main.java.srcDirs += 'src/main/kotlin'
- }
-
- defaultConfig {
- // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
- applicationId "com.dan63.tetra_stats"
- // You can update the following values to match your application needs.
- // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
- minSdkVersion 19
- targetSdkVersion flutter.targetSdkVersion
- versionCode flutterVersionCode.toInteger()
- versionName flutterVersionName
- }
-
- buildTypes {
- release {
- // TODO: Add your own signing config for the release build.
- // Signing with the debug keys for now, so `flutter run --release` works.
- signingConfig signingConfigs.debug
- }
- }
-}
-
-flutter {
- source '../..'
-}
-
-dependencies {
- implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
-}
+def localProperties = new Properties()
+def localPropertiesFile = rootProject.file('local.properties')
+if (localPropertiesFile.exists()) {
+ localPropertiesFile.withReader('UTF-8') { reader ->
+ localProperties.load(reader)
+ }
+}
+
+def flutterRoot = localProperties.getProperty('flutter.sdk')
+if (flutterRoot == null) {
+ throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
+}
+
+def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
+if (flutterVersionCode == null) {
+ flutterVersionCode = '1'
+}
+
+def flutterVersionName = localProperties.getProperty('flutter.versionName')
+if (flutterVersionName == null) {
+ flutterVersionName = '1.0'
+}
+
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
+
+android {
+ compileSdkVersion flutter.compileSdkVersion
+ ndkVersion flutter.ndkVersion
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+
+ kotlinOptions {
+ jvmTarget = '1.8'
+ }
+
+ sourceSets {
+ main.java.srcDirs += 'src/main/kotlin'
+ }
+
+ defaultConfig {
+ // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
+ applicationId "com.dan63.tetra_stats"
+ // You can update the following values to match your application needs.
+ // For more information, see: https://docs.flutter.dev/deployment/android#reviewing-the-gradle-build-configuration.
+ minSdkVersion 19
+ targetSdkVersion flutter.targetSdkVersion
+ versionCode flutterVersionCode.toInteger()
+ versionName flutterVersionName
+ }
+
+ buildTypes {
+ release {
+ // TODO: Add your own signing config for the release build.
+ // Signing with the debug keys for now, so `flutter run --release` works.
+ signingConfig signingConfigs.debug
+ }
+ }
+}
+
+flutter {
+ source '../..'
+}
+
+dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
+}
diff --git a/android/app/src/debug/AndroidManifest.xml b/android/app/src/debug/AndroidManifest.xml
index 10a0745..d8b5582 100644
--- a/android/app/src/debug/AndroidManifest.xml
+++ b/android/app/src/debug/AndroidManifest.xml
@@ -1,8 +1,8 @@
-
-
-
-
+
+
+
+
diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml
index 7b9af76..fa17825 100644
--- a/android/app/src/main/AndroidManifest.xml
+++ b/android/app/src/main/AndroidManifest.xml
@@ -1,35 +1,35 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/kotlin/com/dan63/tetrastats/tetra_stats/MainActivity.kt b/android/app/src/main/kotlin/com/dan63/tetrastats/tetra_stats/MainActivity.kt
index 86557c9..83f8e7c 100644
--- a/android/app/src/main/kotlin/com/dan63/tetrastats/tetra_stats/MainActivity.kt
+++ b/android/app/src/main/kotlin/com/dan63/tetrastats/tetra_stats/MainActivity.kt
@@ -1,6 +1,6 @@
-package com.dan63.tetrastats.tetra_stats
-
-import io.flutter.embedding.android.FlutterActivity
-
-class MainActivity: FlutterActivity() {
-}
+package com.dan63.tetrastats.tetra_stats
+
+import io.flutter.embedding.android.FlutterActivity
+
+class MainActivity: FlutterActivity() {
+}
diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml
index f74085f..1cb7aa2 100644
--- a/android/app/src/main/res/drawable-v21/launch_background.xml
+++ b/android/app/src/main/res/drawable-v21/launch_background.xml
@@ -1,12 +1,12 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml
index 304732f..8403758 100644
--- a/android/app/src/main/res/drawable/launch_background.xml
+++ b/android/app/src/main/res/drawable/launch_background.xml
@@ -1,12 +1,12 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml
index 06952be..360a160 100644
--- a/android/app/src/main/res/values-night/styles.xml
+++ b/android/app/src/main/res/values-night/styles.xml
@@ -1,18 +1,18 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml
index cb1ef88..5fac679 100644
--- a/android/app/src/main/res/values/styles.xml
+++ b/android/app/src/main/res/values/styles.xml
@@ -1,18 +1,18 @@
-
-
-
-
-
-
-
+
+
+
+
+
+
+
diff --git a/android/app/src/profile/AndroidManifest.xml b/android/app/src/profile/AndroidManifest.xml
index 10a0745..d8b5582 100644
--- a/android/app/src/profile/AndroidManifest.xml
+++ b/android/app/src/profile/AndroidManifest.xml
@@ -1,8 +1,8 @@
-
-
-
-
+
+
+
+
diff --git a/android/build.gradle b/android/build.gradle
index 58a8c74..6b815dd 100644
--- a/android/build.gradle
+++ b/android/build.gradle
@@ -1,31 +1,31 @@
-buildscript {
- ext.kotlin_version = '1.7.10'
- repositories {
- google()
- mavenCentral()
- }
-
- dependencies {
- classpath 'com.android.tools.build:gradle:7.2.0'
- classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
- }
-}
-
-allprojects {
- repositories {
- google()
- mavenCentral()
- }
-}
-
-rootProject.buildDir = '../build'
-subprojects {
- project.buildDir = "${rootProject.buildDir}/${project.name}"
-}
-subprojects {
- project.evaluationDependsOn(':app')
-}
-
-task clean(type: Delete) {
- delete rootProject.buildDir
-}
+buildscript {
+ ext.kotlin_version = '1.7.10'
+ repositories {
+ google()
+ mavenCentral()
+ }
+
+ dependencies {
+ classpath 'com.android.tools.build:gradle:7.2.0'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ mavenCentral()
+ }
+}
+
+rootProject.buildDir = '../build'
+subprojects {
+ project.buildDir = "${rootProject.buildDir}/${project.name}"
+}
+subprojects {
+ project.evaluationDependsOn(':app')
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/android/gradle.properties b/android/gradle.properties
index 94adc3a..46c1f16 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,3 +1,3 @@
-org.gradle.jvmargs=-Xmx1536M
-android.useAndroidX=true
-android.enableJetifier=true
+org.gradle.jvmargs=-Xmx1536M
+android.useAndroidX=true
+android.enableJetifier=true
diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties
index 3c472b9..eabb85f 100644
--- a/android/gradle/wrapper/gradle-wrapper.properties
+++ b/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-all.zip
diff --git a/android/settings.gradle b/android/settings.gradle
index 44e62bc..33f0745 100644
--- a/android/settings.gradle
+++ b/android/settings.gradle
@@ -1,11 +1,11 @@
-include ':app'
-
-def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
-def properties = new Properties()
-
-assert localPropertiesFile.exists()
-localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
-
-def flutterSdkPath = properties.getProperty("flutter.sdk")
-assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
-apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
+include ':app'
+
+def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
+def properties = new Properties()
+
+assert localPropertiesFile.exists()
+localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
+
+def flutterSdkPath = properties.getProperty("flutter.sdk")
+assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
+apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
diff --git a/ios/.gitignore b/ios/.gitignore
index 7a7f987..ad322bc 100644
--- a/ios/.gitignore
+++ b/ios/.gitignore
@@ -1,34 +1,34 @@
-**/dgph
-*.mode1v3
-*.mode2v3
-*.moved-aside
-*.pbxuser
-*.perspectivev3
-**/*sync/
-.sconsign.dblite
-.tags*
-**/.vagrant/
-**/DerivedData/
-Icon?
-**/Pods/
-**/.symlinks/
-profile
-xcuserdata
-**/.generated/
-Flutter/App.framework
-Flutter/Flutter.framework
-Flutter/Flutter.podspec
-Flutter/Generated.xcconfig
-Flutter/ephemeral/
-Flutter/app.flx
-Flutter/app.zip
-Flutter/flutter_assets/
-Flutter/flutter_export_environment.sh
-ServiceDefinitions.json
-Runner/GeneratedPluginRegistrant.*
-
-# Exceptions to above rules.
-!default.mode1v3
-!default.mode2v3
-!default.pbxuser
-!default.perspectivev3
+**/dgph
+*.mode1v3
+*.mode2v3
+*.moved-aside
+*.pbxuser
+*.perspectivev3
+**/*sync/
+.sconsign.dblite
+.tags*
+**/.vagrant/
+**/DerivedData/
+Icon?
+**/Pods/
+**/.symlinks/
+profile
+xcuserdata
+**/.generated/
+Flutter/App.framework
+Flutter/Flutter.framework
+Flutter/Flutter.podspec
+Flutter/Generated.xcconfig
+Flutter/ephemeral/
+Flutter/app.flx
+Flutter/app.zip
+Flutter/flutter_assets/
+Flutter/flutter_export_environment.sh
+ServiceDefinitions.json
+Runner/GeneratedPluginRegistrant.*
+
+# Exceptions to above rules.
+!default.mode1v3
+!default.mode2v3
+!default.pbxuser
+!default.perspectivev3
diff --git a/ios/Flutter/AppFrameworkInfo.plist b/ios/Flutter/AppFrameworkInfo.plist
index 9625e10..0d9747f 100644
--- a/ios/Flutter/AppFrameworkInfo.plist
+++ b/ios/Flutter/AppFrameworkInfo.plist
@@ -1,26 +1,26 @@
-
-
-
-
- CFBundleDevelopmentRegion
- en
- CFBundleExecutable
- App
- CFBundleIdentifier
- io.flutter.flutter.app
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- App
- CFBundlePackageType
- FMWK
- CFBundleShortVersionString
- 1.0
- CFBundleSignature
- ????
- CFBundleVersion
- 1.0
- MinimumOSVersion
- 11.0
-
-
+
+
+
+
+ CFBundleDevelopmentRegion
+ en
+ CFBundleExecutable
+ App
+ CFBundleIdentifier
+ io.flutter.flutter.app
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ App
+ CFBundlePackageType
+ FMWK
+ CFBundleShortVersionString
+ 1.0
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ 1.0
+ MinimumOSVersion
+ 11.0
+
+
diff --git a/ios/Flutter/Debug.xcconfig b/ios/Flutter/Debug.xcconfig
index 592ceee..0b2d479 100644
--- a/ios/Flutter/Debug.xcconfig
+++ b/ios/Flutter/Debug.xcconfig
@@ -1 +1 @@
-#include "Generated.xcconfig"
+#include "Generated.xcconfig"
diff --git a/ios/Flutter/Release.xcconfig b/ios/Flutter/Release.xcconfig
index 592ceee..0b2d479 100644
--- a/ios/Flutter/Release.xcconfig
+++ b/ios/Flutter/Release.xcconfig
@@ -1 +1 @@
-#include "Generated.xcconfig"
+#include "Generated.xcconfig"
diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj
index 7ae2d93..69eddb0 100644
--- a/ios/Runner.xcodeproj/project.pbxproj
+++ b/ios/Runner.xcodeproj/project.pbxproj
@@ -1,483 +1,483 @@
-// !$*UTF8*$!
-{
- archiveVersion = 1;
- classes = {
- };
- objectVersion = 54;
- objects = {
-
-/* Begin PBXBuildFile section */
- 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
- 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
- 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
- 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
- 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
- 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
-/* End PBXBuildFile section */
-
-/* Begin PBXCopyFilesBuildPhase section */
- 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
- isa = PBXCopyFilesBuildPhase;
- buildActionMask = 2147483647;
- dstPath = "";
- dstSubfolderSpec = 10;
- files = (
- );
- name = "Embed Frameworks";
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXCopyFilesBuildPhase section */
-
-/* Begin PBXFileReference section */
- 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
- 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
- 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
- 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
- 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
- 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
- 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
- 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
- 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
- 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
- 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
- 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
- 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
-/* End PBXFileReference section */
-
-/* Begin PBXFrameworksBuildPhase section */
- 97C146EB1CF9000F007C117D /* Frameworks */ = {
- isa = PBXFrameworksBuildPhase;
- buildActionMask = 2147483647;
- files = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXFrameworksBuildPhase section */
-
-/* Begin PBXGroup section */
- 9740EEB11CF90186004384FC /* Flutter */ = {
- isa = PBXGroup;
- children = (
- 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
- 9740EEB21CF90195004384FC /* Debug.xcconfig */,
- 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
- 9740EEB31CF90195004384FC /* Generated.xcconfig */,
- );
- name = Flutter;
- sourceTree = "";
- };
- 97C146E51CF9000F007C117D = {
- isa = PBXGroup;
- children = (
- 9740EEB11CF90186004384FC /* Flutter */,
- 97C146F01CF9000F007C117D /* Runner */,
- 97C146EF1CF9000F007C117D /* Products */,
- );
- sourceTree = "";
- };
- 97C146EF1CF9000F007C117D /* Products */ = {
- isa = PBXGroup;
- children = (
- 97C146EE1CF9000F007C117D /* Runner.app */,
- );
- name = Products;
- sourceTree = "";
- };
- 97C146F01CF9000F007C117D /* Runner */ = {
- isa = PBXGroup;
- children = (
- 97C146FA1CF9000F007C117D /* Main.storyboard */,
- 97C146FD1CF9000F007C117D /* Assets.xcassets */,
- 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
- 97C147021CF9000F007C117D /* Info.plist */,
- 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
- 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
- 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
- 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
- );
- path = Runner;
- sourceTree = "";
- };
-/* End PBXGroup section */
-
-/* Begin PBXNativeTarget section */
- 97C146ED1CF9000F007C117D /* Runner */ = {
- isa = PBXNativeTarget;
- buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
- buildPhases = (
- 9740EEB61CF901F6004384FC /* Run Script */,
- 97C146EA1CF9000F007C117D /* Sources */,
- 97C146EB1CF9000F007C117D /* Frameworks */,
- 97C146EC1CF9000F007C117D /* Resources */,
- 9705A1C41CF9048500538489 /* Embed Frameworks */,
- 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
- );
- buildRules = (
- );
- dependencies = (
- );
- name = Runner;
- productName = Runner;
- productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
- productType = "com.apple.product-type.application";
- };
-/* End PBXNativeTarget section */
-
-/* Begin PBXProject section */
- 97C146E61CF9000F007C117D /* Project object */ = {
- isa = PBXProject;
- attributes = {
- LastUpgradeCheck = 1300;
- ORGANIZATIONNAME = "";
- TargetAttributes = {
- 97C146ED1CF9000F007C117D = {
- CreatedOnToolsVersion = 7.3.1;
- LastSwiftMigration = 1100;
- };
- };
- };
- buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
- compatibilityVersion = "Xcode 9.3";
- developmentRegion = en;
- hasScannedForEncodings = 0;
- knownRegions = (
- en,
- Base,
- );
- mainGroup = 97C146E51CF9000F007C117D;
- productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
- projectDirPath = "";
- projectRoot = "";
- targets = (
- 97C146ED1CF9000F007C117D /* Runner */,
- );
- };
-/* End PBXProject section */
-
-/* Begin PBXResourcesBuildPhase section */
- 97C146EC1CF9000F007C117D /* Resources */ = {
- isa = PBXResourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
- 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
- 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
- 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXResourcesBuildPhase section */
-
-/* Begin PBXShellScriptBuildPhase section */
- 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
- isa = PBXShellScriptBuildPhase;
- alwaysOutOfDate = 1;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "Thin Binary";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
- };
- 9740EEB61CF901F6004384FC /* Run Script */ = {
- isa = PBXShellScriptBuildPhase;
- alwaysOutOfDate = 1;
- buildActionMask = 2147483647;
- files = (
- );
- inputPaths = (
- );
- name = "Run Script";
- outputPaths = (
- );
- runOnlyForDeploymentPostprocessing = 0;
- shellPath = /bin/sh;
- shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
- };
-/* End PBXShellScriptBuildPhase section */
-
-/* Begin PBXSourcesBuildPhase section */
- 97C146EA1CF9000F007C117D /* Sources */ = {
- isa = PBXSourcesBuildPhase;
- buildActionMask = 2147483647;
- files = (
- 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
- 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
- );
- runOnlyForDeploymentPostprocessing = 0;
- };
-/* End PBXSourcesBuildPhase section */
-
-/* Begin PBXVariantGroup section */
- 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
- isa = PBXVariantGroup;
- children = (
- 97C146FB1CF9000F007C117D /* Base */,
- );
- name = Main.storyboard;
- sourceTree = "";
- };
- 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
- isa = PBXVariantGroup;
- children = (
- 97C147001CF9000F007C117D /* Base */,
- );
- name = LaunchScreen.storyboard;
- sourceTree = "";
- };
-/* End PBXVariantGroup section */
-
-/* Begin XCBuildConfiguration section */
- 249021D3217E4FDB00AE95B9 /* Profile */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
- CLANG_CXX_LIBRARY = "libc++";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_COMMA = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INFINITE_RECURSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
- CLANG_WARN_STRICT_PROTOTYPES = YES;
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- COPY_PHASE_STRIP = NO;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- ENABLE_NS_ASSERTIONS = NO;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
- MTL_ENABLE_DEBUG_INFO = NO;
- SDKROOT = iphoneos;
- SUPPORTED_PLATFORMS = iphoneos;
- TARGETED_DEVICE_FAMILY = "1,2";
- VALIDATE_PRODUCT = YES;
- };
- name = Profile;
- };
- 249021D4217E4FDB00AE95B9 /* Profile */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
- ENABLE_BITCODE = NO;
- INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- );
- PRODUCT_BUNDLE_IDENTIFIER = com.dan63.tetrastats.tetraStats;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
- SWIFT_VERSION = 5.0;
- VERSIONING_SYSTEM = "apple-generic";
- };
- name = Profile;
- };
- 97C147031CF9000F007C117D /* Debug */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
- CLANG_CXX_LIBRARY = "libc++";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_COMMA = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INFINITE_RECURSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
- CLANG_WARN_STRICT_PROTOTYPES = YES;
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- COPY_PHASE_STRIP = NO;
- DEBUG_INFORMATION_FORMAT = dwarf;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- ENABLE_TESTABILITY = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_DYNAMIC_NO_PIC = NO;
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_OPTIMIZATION_LEVEL = 0;
- GCC_PREPROCESSOR_DEFINITIONS = (
- "DEBUG=1",
- "$(inherited)",
- );
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
- MTL_ENABLE_DEBUG_INFO = YES;
- ONLY_ACTIVE_ARCH = YES;
- SDKROOT = iphoneos;
- TARGETED_DEVICE_FAMILY = "1,2";
- };
- name = Debug;
- };
- 97C147041CF9000F007C117D /* Release */ = {
- isa = XCBuildConfiguration;
- buildSettings = {
- ALWAYS_SEARCH_USER_PATHS = NO;
- CLANG_ANALYZER_NONNULL = YES;
- CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
- CLANG_CXX_LIBRARY = "libc++";
- CLANG_ENABLE_MODULES = YES;
- CLANG_ENABLE_OBJC_ARC = YES;
- CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
- CLANG_WARN_BOOL_CONVERSION = YES;
- CLANG_WARN_COMMA = YES;
- CLANG_WARN_CONSTANT_CONVERSION = YES;
- CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
- CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
- CLANG_WARN_EMPTY_BODY = YES;
- CLANG_WARN_ENUM_CONVERSION = YES;
- CLANG_WARN_INFINITE_RECURSION = YES;
- CLANG_WARN_INT_CONVERSION = YES;
- CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
- CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
- CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
- CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
- CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
- CLANG_WARN_STRICT_PROTOTYPES = YES;
- CLANG_WARN_SUSPICIOUS_MOVE = YES;
- CLANG_WARN_UNREACHABLE_CODE = YES;
- CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
- "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
- COPY_PHASE_STRIP = NO;
- DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
- ENABLE_NS_ASSERTIONS = NO;
- ENABLE_STRICT_OBJC_MSGSEND = YES;
- GCC_C_LANGUAGE_STANDARD = gnu99;
- GCC_NO_COMMON_BLOCKS = YES;
- GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
- GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
- GCC_WARN_UNDECLARED_SELECTOR = YES;
- GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
- GCC_WARN_UNUSED_FUNCTION = YES;
- GCC_WARN_UNUSED_VARIABLE = YES;
- IPHONEOS_DEPLOYMENT_TARGET = 11.0;
- MTL_ENABLE_DEBUG_INFO = NO;
- SDKROOT = iphoneos;
- SUPPORTED_PLATFORMS = iphoneos;
- SWIFT_COMPILATION_MODE = wholemodule;
- SWIFT_OPTIMIZATION_LEVEL = "-O";
- TARGETED_DEVICE_FAMILY = "1,2";
- VALIDATE_PRODUCT = YES;
- };
- name = Release;
- };
- 97C147061CF9000F007C117D /* Debug */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
- ENABLE_BITCODE = NO;
- INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- );
- PRODUCT_BUNDLE_IDENTIFIER = com.dan63.tetrastats.tetraStats;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
- SWIFT_OPTIMIZATION_LEVEL = "-Onone";
- SWIFT_VERSION = 5.0;
- VERSIONING_SYSTEM = "apple-generic";
- };
- name = Debug;
- };
- 97C147071CF9000F007C117D /* Release */ = {
- isa = XCBuildConfiguration;
- baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
- buildSettings = {
- ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
- CLANG_ENABLE_MODULES = YES;
- CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
- ENABLE_BITCODE = NO;
- INFOPLIST_FILE = Runner/Info.plist;
- LD_RUNPATH_SEARCH_PATHS = (
- "$(inherited)",
- "@executable_path/Frameworks",
- );
- PRODUCT_BUNDLE_IDENTIFIER = com.dan63.tetrastats.tetraStats;
- PRODUCT_NAME = "$(TARGET_NAME)";
- SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
- SWIFT_VERSION = 5.0;
- VERSIONING_SYSTEM = "apple-generic";
- };
- name = Release;
- };
-/* End XCBuildConfiguration section */
-
-/* Begin XCConfigurationList section */
- 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 97C147031CF9000F007C117D /* Debug */,
- 97C147041CF9000F007C117D /* Release */,
- 249021D3217E4FDB00AE95B9 /* Profile */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
- 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
- isa = XCConfigurationList;
- buildConfigurations = (
- 97C147061CF9000F007C117D /* Debug */,
- 97C147071CF9000F007C117D /* Release */,
- 249021D4217E4FDB00AE95B9 /* Profile */,
- );
- defaultConfigurationIsVisible = 0;
- defaultConfigurationName = Release;
- };
-/* End XCConfigurationList section */
- };
- rootObject = 97C146E61CF9000F007C117D /* Project object */;
-}
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 54;
+ objects = {
+
+/* Begin PBXBuildFile section */
+ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
+ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
+ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
+ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
+ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXCopyFilesBuildPhase section */
+ 9705A1C41CF9048500538489 /* Embed Frameworks */ = {
+ isa = PBXCopyFilesBuildPhase;
+ buildActionMask = 2147483647;
+ dstPath = "";
+ dstSubfolderSpec = 10;
+ files = (
+ );
+ name = "Embed Frameworks";
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXCopyFilesBuildPhase section */
+
+/* Begin PBXFileReference section */
+ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = ""; };
+ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = ""; };
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = ""; };
+ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = ""; };
+ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = ""; };
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = ""; };
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = ""; };
+ 97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
+ 97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; };
+ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 97C146EB1CF9000F007C117D /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 9740EEB11CF90186004384FC /* Flutter */ = {
+ isa = PBXGroup;
+ children = (
+ 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
+ 9740EEB21CF90195004384FC /* Debug.xcconfig */,
+ 7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
+ 9740EEB31CF90195004384FC /* Generated.xcconfig */,
+ );
+ name = Flutter;
+ sourceTree = "";
+ };
+ 97C146E51CF9000F007C117D = {
+ isa = PBXGroup;
+ children = (
+ 9740EEB11CF90186004384FC /* Flutter */,
+ 97C146F01CF9000F007C117D /* Runner */,
+ 97C146EF1CF9000F007C117D /* Products */,
+ );
+ sourceTree = "";
+ };
+ 97C146EF1CF9000F007C117D /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146EE1CF9000F007C117D /* Runner.app */,
+ );
+ name = Products;
+ sourceTree = "";
+ };
+ 97C146F01CF9000F007C117D /* Runner */ = {
+ isa = PBXGroup;
+ children = (
+ 97C146FA1CF9000F007C117D /* Main.storyboard */,
+ 97C146FD1CF9000F007C117D /* Assets.xcassets */,
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,
+ 97C147021CF9000F007C117D /* Info.plist */,
+ 1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
+ 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
+ 74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
+ 74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
+ );
+ path = Runner;
+ sourceTree = "";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXNativeTarget section */
+ 97C146ED1CF9000F007C117D /* Runner */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
+ buildPhases = (
+ 9740EEB61CF901F6004384FC /* Run Script */,
+ 97C146EA1CF9000F007C117D /* Sources */,
+ 97C146EB1CF9000F007C117D /* Frameworks */,
+ 97C146EC1CF9000F007C117D /* Resources */,
+ 9705A1C41CF9048500538489 /* Embed Frameworks */,
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = Runner;
+ productName = Runner;
+ productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
+ productType = "com.apple.product-type.application";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 97C146E61CF9000F007C117D /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastUpgradeCheck = 1300;
+ ORGANIZATIONNAME = "";
+ TargetAttributes = {
+ 97C146ED1CF9000F007C117D = {
+ CreatedOnToolsVersion = 7.3.1;
+ LastSwiftMigration = 1100;
+ };
+ };
+ };
+ buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
+ compatibilityVersion = "Xcode 9.3";
+ developmentRegion = en;
+ hasScannedForEncodings = 0;
+ knownRegions = (
+ en,
+ Base,
+ );
+ mainGroup = 97C146E51CF9000F007C117D;
+ productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 97C146ED1CF9000F007C117D /* Runner */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 97C146EC1CF9000F007C117D /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
+ 3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
+ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,
+ 97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Thin Binary";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
+ };
+ 9740EEB61CF901F6004384FC /* Run Script */ = {
+ isa = PBXShellScriptBuildPhase;
+ alwaysOutOfDate = 1;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Run Script";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 97C146EA1CF9000F007C117D /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
+ 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXVariantGroup section */
+ 97C146FA1CF9000F007C117D /* Main.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 97C146FB1CF9000F007C117D /* Base */,
+ );
+ name = Main.storyboard;
+ sourceTree = "";
+ };
+ 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 97C147001CF9000F007C117D /* Base */,
+ );
+ name = LaunchScreen.storyboard;
+ sourceTree = "";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 249021D3217E4FDB00AE95B9 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Profile;
+ };
+ 249021D4217E4FDB00AE95B9 /* Profile */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.dan63.tetrastats.tetraStats;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Profile;
+ };
+ 97C147031CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = dwarf;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ ENABLE_TESTABILITY = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_DYNAMIC_NO_PIC = NO;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = (
+ "DEBUG=1",
+ "$(inherited)",
+ );
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ MTL_ENABLE_DEBUG_INFO = YES;
+ ONLY_ACTIVE_ARCH = YES;
+ SDKROOT = iphoneos;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 97C147041CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = NO;
+ CLANG_ANALYZER_NONNULL = YES;
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
+ CLANG_CXX_LIBRARY = "libc++";
+ CLANG_ENABLE_MODULES = YES;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
+ CLANG_WARN_BOOL_CONVERSION = YES;
+ CLANG_WARN_COMMA = YES;
+ CLANG_WARN_CONSTANT_CONVERSION = YES;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
+ CLANG_WARN_EMPTY_BODY = YES;
+ CLANG_WARN_ENUM_CONVERSION = YES;
+ CLANG_WARN_INFINITE_RECURSION = YES;
+ CLANG_WARN_INT_CONVERSION = YES;
+ CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
+ CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
+ CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
+ CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
+ CLANG_WARN_STRICT_PROTOTYPES = YES;
+ CLANG_WARN_SUSPICIOUS_MOVE = YES;
+ CLANG_WARN_UNREACHABLE_CODE = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ COPY_PHASE_STRIP = NO;
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
+ ENABLE_NS_ASSERTIONS = NO;
+ ENABLE_STRICT_OBJC_MSGSEND = YES;
+ GCC_C_LANGUAGE_STANDARD = gnu99;
+ GCC_NO_COMMON_BLOCKS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ IPHONEOS_DEPLOYMENT_TARGET = 11.0;
+ MTL_ENABLE_DEBUG_INFO = NO;
+ SDKROOT = iphoneos;
+ SUPPORTED_PLATFORMS = iphoneos;
+ SWIFT_COMPILATION_MODE = wholemodule;
+ SWIFT_OPTIMIZATION_LEVEL = "-O";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ VALIDATE_PRODUCT = YES;
+ };
+ name = Release;
+ };
+ 97C147061CF9000F007C117D /* Debug */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.dan63.tetrastats.tetraStats;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Debug;
+ };
+ 97C147071CF9000F007C117D /* Release */ = {
+ isa = XCBuildConfiguration;
+ baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ CLANG_ENABLE_MODULES = YES;
+ CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
+ ENABLE_BITCODE = NO;
+ INFOPLIST_FILE = Runner/Info.plist;
+ LD_RUNPATH_SEARCH_PATHS = (
+ "$(inherited)",
+ "@executable_path/Frameworks",
+ );
+ PRODUCT_BUNDLE_IDENTIFIER = com.dan63.tetrastats.tetraStats;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
+ SWIFT_VERSION = 5.0;
+ VERSIONING_SYSTEM = "apple-generic";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 97C147031CF9000F007C117D /* Debug */,
+ 97C147041CF9000F007C117D /* Release */,
+ 249021D3217E4FDB00AE95B9 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 97C147061CF9000F007C117D /* Debug */,
+ 97C147071CF9000F007C117D /* Release */,
+ 249021D4217E4FDB00AE95B9 /* Profile */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 97C146E61CF9000F007C117D /* Project object */;
+}
diff --git a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
index 919434a..c4b79bd 100644
--- a/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
+++ b/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -1,7 +1,7 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
index 18d9810..fc6bf80 100644
--- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -1,8 +1,8 @@
-
-
-
-
- IDEDidComputeMac32BitWarning
-
-
-
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
index f9b0d7c..af0309c 100644
--- a/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ b/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -1,8 +1,8 @@
-
-
-
-
- PreviewsEnabled
-
-
-
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
index c87d15a..f9cbb25 100644
--- a/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
+++ b/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme
@@ -1,87 +1,87 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ios/Runner.xcworkspace/contents.xcworkspacedata b/ios/Runner.xcworkspace/contents.xcworkspacedata
index 1d526a1..59c6d39 100644
--- a/ios/Runner.xcworkspace/contents.xcworkspacedata
+++ b/ios/Runner.xcworkspace/contents.xcworkspacedata
@@ -1,7 +1,7 @@
-
-
-
-
-
+
+
+
+
+
diff --git a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
index 18d9810..fc6bf80 100644
--- a/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
+++ b/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist
@@ -1,8 +1,8 @@
-
-
-
-
- IDEDidComputeMac32BitWarning
-
-
-
+
+
+
+
+ IDEDidComputeMac32BitWarning
+
+
+
diff --git a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
index f9b0d7c..af0309c 100644
--- a/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
+++ b/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -1,8 +1,8 @@
-
-
-
-
- PreviewsEnabled
-
-
-
+
+
+
+
+ PreviewsEnabled
+
+
+
diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift
index 70693e4..3763683 100644
--- a/ios/Runner/AppDelegate.swift
+++ b/ios/Runner/AppDelegate.swift
@@ -1,13 +1,13 @@
-import UIKit
-import Flutter
-
-@UIApplicationMain
-@objc class AppDelegate: FlutterAppDelegate {
- override func application(
- _ application: UIApplication,
- didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
- ) -> Bool {
- GeneratedPluginRegistrant.register(with: self)
- return super.application(application, didFinishLaunchingWithOptions: launchOptions)
- }
-}
+import UIKit
+import Flutter
+
+@UIApplicationMain
+@objc class AppDelegate: FlutterAppDelegate {
+ override func application(
+ _ application: UIApplication,
+ didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
+ ) -> Bool {
+ GeneratedPluginRegistrant.register(with: self)
+ return super.application(application, didFinishLaunchingWithOptions: launchOptions)
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
index d36b1fa..1950fd8 100644
--- a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
+++ b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
@@ -1,122 +1,122 @@
-{
- "images" : [
- {
- "size" : "20x20",
- "idiom" : "iphone",
- "filename" : "Icon-App-20x20@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "20x20",
- "idiom" : "iphone",
- "filename" : "Icon-App-20x20@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "Icon-App-29x29@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "Icon-App-29x29@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "29x29",
- "idiom" : "iphone",
- "filename" : "Icon-App-29x29@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "40x40",
- "idiom" : "iphone",
- "filename" : "Icon-App-40x40@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "40x40",
- "idiom" : "iphone",
- "filename" : "Icon-App-40x40@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "60x60",
- "idiom" : "iphone",
- "filename" : "Icon-App-60x60@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "60x60",
- "idiom" : "iphone",
- "filename" : "Icon-App-60x60@3x.png",
- "scale" : "3x"
- },
- {
- "size" : "20x20",
- "idiom" : "ipad",
- "filename" : "Icon-App-20x20@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "20x20",
- "idiom" : "ipad",
- "filename" : "Icon-App-20x20@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "29x29",
- "idiom" : "ipad",
- "filename" : "Icon-App-29x29@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "29x29",
- "idiom" : "ipad",
- "filename" : "Icon-App-29x29@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "40x40",
- "idiom" : "ipad",
- "filename" : "Icon-App-40x40@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "40x40",
- "idiom" : "ipad",
- "filename" : "Icon-App-40x40@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "76x76",
- "idiom" : "ipad",
- "filename" : "Icon-App-76x76@1x.png",
- "scale" : "1x"
- },
- {
- "size" : "76x76",
- "idiom" : "ipad",
- "filename" : "Icon-App-76x76@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "83.5x83.5",
- "idiom" : "ipad",
- "filename" : "Icon-App-83.5x83.5@2x.png",
- "scale" : "2x"
- },
- {
- "size" : "1024x1024",
- "idiom" : "ios-marketing",
- "filename" : "Icon-App-1024x1024@1x.png",
- "scale" : "1x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
+{
+ "images" : [
+ {
+ "size" : "20x20",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-20x20@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "20x20",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-20x20@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-29x29@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-29x29@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-29x29@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-40x40@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-40x40@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-60x60@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "Icon-App-60x60@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "size" : "20x20",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-20x20@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "20x20",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-20x20@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-29x29@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "29x29",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-29x29@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-40x40@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "40x40",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-40x40@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-76x76@1x.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-76x76@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "83.5x83.5",
+ "idiom" : "ipad",
+ "filename" : "Icon-App-83.5x83.5@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "1024x1024",
+ "idiom" : "ios-marketing",
+ "filename" : "Icon-App-1024x1024@1x.png",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
index 0bedcf2..d08a4de 100644
--- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
+++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
@@ -1,23 +1,23 @@
-{
- "images" : [
- {
- "idiom" : "universal",
- "filename" : "LaunchImage.png",
- "scale" : "1x"
- },
- {
- "idiom" : "universal",
- "filename" : "LaunchImage@2x.png",
- "scale" : "2x"
- },
- {
- "idiom" : "universal",
- "filename" : "LaunchImage@3x.png",
- "scale" : "3x"
- }
- ],
- "info" : {
- "version" : 1,
- "author" : "xcode"
- }
-}
+{
+ "images" : [
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage.png",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "universal",
+ "filename" : "LaunchImage@3x.png",
+ "scale" : "3x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+}
diff --git a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
index 89c2725..65a94b5 100644
--- a/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
+++ b/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md
@@ -1,5 +1,5 @@
-# Launch Screen Assets
-
-You can customize the launch screen with your own desired assets by replacing the image files in this directory.
-
+# Launch Screen Assets
+
+You can customize the launch screen with your own desired assets by replacing the image files in this directory.
+
You can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images.
\ No newline at end of file
diff --git a/ios/Runner/Base.lproj/LaunchScreen.storyboard b/ios/Runner/Base.lproj/LaunchScreen.storyboard
index f2e259c..497371e 100644
--- a/ios/Runner/Base.lproj/LaunchScreen.storyboard
+++ b/ios/Runner/Base.lproj/LaunchScreen.storyboard
@@ -1,37 +1,37 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ios/Runner/Base.lproj/Main.storyboard b/ios/Runner/Base.lproj/Main.storyboard
index f3c2851..bbb83ca 100644
--- a/ios/Runner/Base.lproj/Main.storyboard
+++ b/ios/Runner/Base.lproj/Main.storyboard
@@ -1,26 +1,26 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist
index 8bc9e69..24bf7e5 100644
--- a/ios/Runner/Info.plist
+++ b/ios/Runner/Info.plist
@@ -1,51 +1,51 @@
-
-
-
-
- CFBundleDevelopmentRegion
- $(DEVELOPMENT_LANGUAGE)
- CFBundleDisplayName
- Tetra Stats
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- Tetra Stats
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- $(FLUTTER_BUILD_NAME)
- CFBundleSignature
- ????
- CFBundleVersion
- $(FLUTTER_BUILD_NUMBER)
- LSRequiresIPhoneOS
-
- UILaunchStoryboardName
- LaunchScreen
- UIMainStoryboardFile
- Main
- UISupportedInterfaceOrientations
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UISupportedInterfaceOrientations~ipad
-
- UIInterfaceOrientationPortrait
- UIInterfaceOrientationPortraitUpsideDown
- UIInterfaceOrientationLandscapeLeft
- UIInterfaceOrientationLandscapeRight
-
- UIViewControllerBasedStatusBarAppearance
-
- CADisableMinimumFrameDurationOnPhone
-
- UIApplicationSupportsIndirectInputEvents
-
-
-
+
+
+
+
+ CFBundleDevelopmentRegion
+ $(DEVELOPMENT_LANGUAGE)
+ CFBundleDisplayName
+ Tetra Stats
+ CFBundleExecutable
+ $(EXECUTABLE_NAME)
+ CFBundleIdentifier
+ $(PRODUCT_BUNDLE_IDENTIFIER)
+ CFBundleInfoDictionaryVersion
+ 6.0
+ CFBundleName
+ Tetra Stats
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ $(FLUTTER_BUILD_NAME)
+ CFBundleSignature
+ ????
+ CFBundleVersion
+ $(FLUTTER_BUILD_NUMBER)
+ LSRequiresIPhoneOS
+
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
+ UISupportedInterfaceOrientations
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UISupportedInterfaceOrientations~ipad
+
+ UIInterfaceOrientationPortrait
+ UIInterfaceOrientationPortraitUpsideDown
+ UIInterfaceOrientationLandscapeLeft
+ UIInterfaceOrientationLandscapeRight
+
+ UIViewControllerBasedStatusBarAppearance
+
+ CADisableMinimumFrameDurationOnPhone
+
+ UIApplicationSupportsIndirectInputEvents
+
+
+
diff --git a/ios/Runner/Runner-Bridging-Header.h b/ios/Runner/Runner-Bridging-Header.h
index 308a2a5..fae207f 100644
--- a/ios/Runner/Runner-Bridging-Header.h
+++ b/ios/Runner/Runner-Bridging-Header.h
@@ -1 +1 @@
-#import "GeneratedPluginRegistrant.h"
+#import "GeneratedPluginRegistrant.h"
diff --git a/lib/data_objects/tetrio.dart b/lib/data_objects/tetrio.dart
index 505b8ff..535303d 100644
--- a/lib/data_objects/tetrio.dart
+++ b/lib/data_objects/tetrio.dart
@@ -1,830 +1,830 @@
-import 'dart:math';
-import 'package:flutter/foundation.dart';
-import 'package:vector_math/vector_math.dart';
-import 'dart:developer' as developer;
-import 'package:http/http.dart' as http;
-import 'dart:convert';
-
-Duration doubleSecondsToDuration(double value) {
- value = value * 1000000;
- return Duration(microseconds: value.floor());
-}
-
-Duration doubleMillisecondsToDuration(double value) {
- value = value * 1000;
- return Duration(microseconds: value.floor());
-}
-
-class TetrioPlayer {
- late String userId;
- late String username;
- late DateTime state;
- late String role;
- int? avatarRevision;
- int? bannerRevision;
- DateTime? registrationTime;
- List badges = [];
- String? bio;
- String? country;
- late int friendCount;
- late int gamesPlayed;
- late int gamesWon;
- late Duration gameTime;
- late double xp;
- late int supporterTier;
- late bool verified;
- bool? badstanding;
- String? botmaster;
- late Connections connections;
- late TetraLeagueAlpha tlSeason1;
- List sprint = [];
- List blitz = [];
- TetrioZen? zen;
- Distinguishment? distinguishment;
-
- TetrioPlayer({
- required this.userId,
- required this.username,
- required this.role,
- required this.state,
- this.avatarRevision,
- this.bannerRevision,
- this.registrationTime,
- required this.badges,
- this.bio,
- this.country,
- required this.friendCount,
- required this.gamesPlayed,
- required this.gamesWon,
- required this.gameTime,
- required this.xp,
- required this.supporterTier,
- required this.verified,
- this.badstanding,
- this.botmaster,
- required this.connections,
- required this.tlSeason1,
- required this.sprint,
- required this.blitz,
- this.zen,
- this.distinguishment,
- });
-
- double get level => pow((xp / 500), 0.6) + (xp / (5000 + (max(0, xp - 4 * pow(10, 6)) / 5000))) + 1;
-
- TetrioPlayer.fromJson(Map json, DateTime stateTime, bool fetchRecords) {
- //developer.log("TetrioPlayer.fromJson $stateTime: $json", name: "data_objects/tetrio");
- userId = json['_id'];
- username = json['username'];
- state = stateTime;
- role = json['role'];
- registrationTime = json['ts'] != null ? DateTime.parse(json['ts']) : null;
- if (json['badges'] != null) {
- json['badges'].forEach((v) {
- badges.add(Badge.fromJson(v));
- });
- }
- xp = json['xp'].toDouble();
- gamesPlayed = json['gamesplayed'];
- gamesWon = json['gameswon'];
- gameTime = doubleSecondsToDuration(json['gametime'].toDouble());
- country = json['country'];
- supporterTier = json['supporter_tier'];
- verified = json['verified'];
- tlSeason1 = TetraLeagueAlpha.fromJson(json['league']);
- avatarRevision = json['avatar_revision'];
- bannerRevision = json['banner_revision'];
- bio = json['bio'];
- connections = Connections.fromJson(json['connections']);
- distinguishment = json['distinguishment'] != null ? Distinguishment.fromJson(json['distinguishment']) : null;
- friendCount = json['friend_count'] ?? 0;
- badstanding = json['badstanding'];
- botmaster = json['botmaster'];
- if (fetchRecords) {
- var url = Uri.https('ch.tetr.io', 'api/users/$userId/records');
- Future response = http.get(url);
- response.then((value) {
- if (value.statusCode == 200) {
- Map jsonRecords = jsonDecode(value.body);
- sprint = jsonRecords['data']['records']['40l']['record'] != null
- ? [RecordSingle.fromJson(jsonRecords['data']['records']['40l']['record'], jsonRecords['data']['records']['40l']['rank'])]
- : [];
- blitz = jsonRecords['data']['records']['blitz']['record'] != null
- ? [RecordSingle.fromJson(jsonRecords['data']['records']['blitz']['record'], jsonRecords['data']['records']['blitz']['rank'])]
- : [];
- zen = TetrioZen.fromJson(jsonRecords['data']['zen']);
- } else {
- developer.log("TetrioPlayer.fromJson exception", name: "data_objects/tetrio", error: value.statusCode);
- throw Exception('Failed to fetch player');
- }
- });
- }
- }
-
- Map toJson() {
- final Map data = {};
- data['_id'] = userId;
- data['username'] = username;
- data['role'] = role;
- if (registrationTime != null) data['ts'] = registrationTime?.toString();
- data['badges'] = badges.map((v) => v.toJson()).toList();
- data['xp'] = xp;
- data['gamesplayed'] = gamesPlayed;
- data['gameswon'] = gamesWon;
- data['gametime'] = gameTime.inMicroseconds / 1000000;
- if (country != null) data['country'] = country;
- data['supporter_tier'] = supporterTier;
- data['verified'] = verified;
- data['league'] = tlSeason1.toJson();
- if (distinguishment != null) data['distinguishment'] = distinguishment?.toJson();
- if (avatarRevision != null) data['avatar_revision'] = avatarRevision;
- if (bannerRevision != null) data['banner_revision'] = bannerRevision;
- if (data['bio'] != null) data['bio'] = bio;
- data['connections'] = connections.toJson();
- data['friend_count'] = friendCount;
- if (badstanding != null) data['badstanding'] = badstanding;
- if (botmaster != null) data['botmaster'] = botmaster;
- //developer.log("TetrioPlayer.toJson: $data", name: "data_objects/tetrio");
- return data;
- }
-
- bool isSameState(TetrioPlayer other) {
- if (userId != other.userId) return false;
- if (username != other.username) return false;
- if (role != other.role) return false;
- if (listEquals(badges, other.badges) == false) return false;
- //if (bio != other.bio) return false;
- if (country != other.country) return false;
- if (friendCount != other.friendCount) return false;
- if (gamesPlayed != other.gamesPlayed) return false;
- if (gamesWon != other.gamesWon) return false;
- if (gameTime != other.gameTime) return false;
- if (xp != other.xp) return false;
- if (supporterTier != other.supporterTier) return false;
- if (verified != other.verified) return false;
- if (badstanding != other.badstanding) return false;
- if (botmaster != other.botmaster) return false;
- if (connections != other.connections) return false;
- if (tlSeason1 != other.tlSeason1) return false;
- if (distinguishment != other.distinguishment) return false;
- return true;
- }
-
- @override
- String toString() {
- return "$username ($state)";
- }
-
- @override
- int get hashCode => state.hashCode;
-
- @override
- bool operator ==(covariant TetrioPlayer other) => (userId == other.userId);
-}
-
-class Badge {
- late String badgeId;
- late String label;
- DateTime? ts;
-
- Badge({required this.badgeId, required this.label, this.ts});
-
- Badge.fromJson(Map json) {
- badgeId = json['id'];
- label = json['label'];
- ts = (json['ts'] != null && json['ts'] is String) ? DateTime.parse(json['ts']) : null; // man i love osk
- }
-
- Map toJson() {
- final Map data = {};
- data['id'] = badgeId;
- data['label'] = label;
- data['ts'] = ts?.toString();
- return data;
- }
-
- @override
- String toString() {
- return "Badge $label ($badgeId)";
- }
-
- @override
- int get hashCode => badgeId.hashCode;
-
- @override
- bool operator ==(covariant Badge other) => badgeId == other.badgeId;
-}
-
-class Connections {
- Discord? discord;
-
- Connections({this.discord});
-
- Connections.fromJson(Map json) {
- discord = json['discord'] != null ? Discord.fromJson(json['discord']) : null;
- }
- @override
- bool operator ==(covariant Connections other) => discord == other.discord;
-
- Map toJson() {
- final Map data = {};
- if (discord != null) {
- data['discord'] = discord!.toJson();
- }
- return data;
- }
-}
-
-class Clears {
- late int singles;
- late int doubles;
- late int triples;
- late int quads;
- late int allClears;
- late int tSpinZeros;
- late int tSpinSingles;
- late int tSpinDoubles;
- late int tSpinTriples;
- late int tSpinQuads;
- late int tSpinMiniZeros;
- late int tSpinMiniSingles;
- late int tSpinMiniDoubles;
-
- Clears(
- {required this.singles,
- required this.doubles,
- required this.triples,
- required this.quads,
- required this.allClears,
- required this.tSpinZeros,
- required this.tSpinSingles,
- required this.tSpinDoubles,
- required this.tSpinTriples,
- required this.tSpinQuads,
- required this.tSpinMiniZeros,
- required this.tSpinMiniSingles,
- required this.tSpinMiniDoubles});
-
- Clears.fromJson(Map json) {
- singles = json['singles'];
- doubles = json['doubles'];
- triples = json['triples'];
- quads = json['quads'];
- tSpinZeros = json['realtspins'];
- tSpinMiniZeros = json['minitspins'];
- tSpinMiniSingles = json['minitspinsingles'];
- tSpinSingles = json['tspinsingles'];
- tSpinMiniDoubles = json['minitspindoubles'];
- tSpinDoubles = json['tspindoubles'];
- tSpinTriples = json['tspintriples'];
- tSpinQuads = json['tspinquads'];
- allClears = json['allclear'];
- }
-
- Map toJson() {
- final Map data = {};
- data['singles'] = singles;
- data['doubles'] = doubles;
- data['triples'] = triples;
- data['quads'] = quads;
- data['realtspins'] = tSpinZeros;
- data['minitspins'] = tSpinMiniZeros;
- data['minitspinsingles'] = tSpinMiniSingles;
- data['tspinsingles'] = tSpinSingles;
- data['minitspindoubles'] = tSpinMiniDoubles;
- data['tspindoubles'] = tSpinDoubles;
- data['tspintriples'] = tSpinTriples;
- data['tspinquads'] = tSpinQuads;
- data['allclear'] = allClears;
- return data;
- }
-}
-
-class Discord {
- late String id;
- late String username;
-
- Discord({required this.id, required this.username});
-
- Discord.fromJson(Map json) {
- id = json['id'];
- username = json['username'];
- }
-
- @override
- bool operator ==(covariant Discord other) => id == other.id;
-
- Map toJson() {
- final Map data = {};
- data['id'] = id;
- data['username'] = username;
- return data;
- }
-}
-
-class Finesse {
- late int combo;
- late int faults;
- late int perfectPieces;
-
- Finesse({required this.combo, required this.faults, required this.perfectPieces});
-
- Finesse.fromJson(Map json) {
- combo = json['combo'];
- faults = json['faults'];
- perfectPieces = json['perfectpieces'];
- }
-
- Map toJson() {
- final Map data = {};
- data['combo'] = combo;
- data['faults'] = faults;
- data['perfectpieces'] = perfectPieces;
- return data;
- }
-}
-
-class EndContextSingle {
- late String gameType;
- late int topBtB;
- late int topCombo;
- late int holds;
- late int inputs;
- late int level;
- late int piecesPlaced;
- late int lines;
- late int score;
- late int seed;
- late Duration finalTime;
- late int tSpins;
- late Clears clears;
- late Finesse finesse;
-
- double get pps => piecesPlaced / (finalTime.inMicroseconds / 1000000);
- double get kpp => inputs / piecesPlaced;
- double get spp => score / piecesPlaced;
- double get kps => inputs / (finalTime.inMicroseconds / 1000000);
- double get finessePercentage => finesse.perfectPieces / piecesPlaced;
-
- EndContextSingle(
- {required this.gameType,
- required this.topBtB,
- required this.topCombo,
- required this.holds,
- required this.inputs,
- required this.level,
- required this.piecesPlaced,
- required this.lines,
- required this.score,
- required this.seed,
- required this.finalTime,
- required this.tSpins,
- required this.clears,
- required this.finesse});
-
- EndContextSingle.fromJson(Map json) {
- seed = json['seed'];
- lines = json['lines'];
- inputs = json['inputs'];
- holds = json['holds'] ?? 0;
- finalTime = doubleMillisecondsToDuration(json['finalTime'].toDouble());
- score = json['score'];
- level = json['level'];
- topCombo = json['topcombo'];
- topBtB = json['topbtb'];
- tSpins = json['tspins'];
- piecesPlaced = json['piecesplaced'];
- clears = Clears.fromJson(json['clears']);
- finesse = Finesse.fromJson(json['finesse']);
- gameType = json['gametype'];
- }
-
- Map toJson() {
- final Map data = {};
- data['seed'] = seed;
- data['lines'] = lines;
- data['inputs'] = inputs;
- data['holds'] = holds;
- data['score'] = score;
- data['level'] = level;
- data['topcombo'] = topCombo;
- data['topbtb'] = topBtB;
- data['tspins'] = tSpins;
- data['piecesplaced'] = piecesPlaced;
- data['clears'] = clears.toJson();
- data['finesse'] = finesse.toJson();
- data['finalTime'] = finalTime;
- data['gametype'] = gameType;
- return data;
- }
-}
-
-class Handling {
- late double arr;
- late double das;
- late int sdf;
- late int dcd;
- late bool cancel;
- late bool safeLock;
-
- Handling({required this.arr, required this.das, required this.sdf, required this.dcd, required this.cancel, required this.safeLock});
-
- Handling.fromJson(Map json) {
- arr = json['arr'];
- das = json['das'];
- dcd = json['dcd'];
- sdf = json['sdf'];
- safeLock = json['safelock'];
- cancel = json['cancel'];
- }
-
- Map toJson() {
- final Map data = {};
- data['arr'] = arr;
- data['das'] = das;
- data['dcd'] = dcd;
- data['sdf'] = sdf;
- data['safelock'] = safeLock;
- data['cancel'] = cancel;
- return data;
- }
-}
-
-class NerdStats {
- final double _apm;
- final double _pps;
- final double _vs;
- late double app;
- late double vsapm;
- late double dss;
- late double dsp;
- late double appdsp;
- late double cheese;
- late double gbe;
- late double nyaapp;
- late double area;
-
- NerdStats(this._apm, this._pps, this._vs) {
- app = _apm / (_pps * 60);
- vsapm = _vs / _apm;
- dss = (_vs / 100) - (_apm / 60);
- dsp = ((_vs / 100) - (_apm / 60)) / _pps;
- appdsp = app + dsp;
- cheese = (dsp * 150) + (((_vs / _apm) - 2) * 50) + (0.6 - app) * 125;
- gbe = ((app * dss) / _pps) * 2;
- nyaapp = app - 5 * tan(radians((cheese / -30) + 1));
- area = _apm * 1 + _pps * 45 + _vs * 0.444 + app * 185 + dss * 175 + dsp * 450 + gbe * 315;
- }
-}
-
-class EstTr {
- final double _apm;
- final double _pps;
- final double _vs;
- final double _rd;
- final double _app;
- final double _dss;
- final double _dsp;
- final double _gbe;
- late double esttr;
- late double srarea;
- late double statrank;
-
- EstTr(this._apm, this._pps, this._vs, this._rd, this._app, this._dss, this._dsp, this._gbe) {
- srarea = (_apm * 0) + (_pps * 135) + (_vs * 0) + (_app * 290) + (_dss * 0) + (_dsp * 700) + (_gbe * 0);
- statrank = 11.2 * atan((srarea - 93) / 130) + 1;
- if (statrank <= 0) statrank = 0.001;
- double estglicko = (4.0867 * srarea + 186.68);
- double temp = (1500 - estglicko) * pi;
- double temp2 = pow((15.9056943314 * (pow(_rd, 2)) + 3527584.25978), 0.5) as double;
- double temp3 = 1 + pow(10, (temp / temp2)) as double;
- esttr = 25000 / temp3;
- }
-}
-
-class Playstyle {
- final double _apm;
- final double _pps;
- //final double _vs;
- final double _app;
- final double _vsapm;
- //final double _dss;
- final double _dsp;
- final double _gbe;
- final double _srarea;
- final double _statrank;
- late double opener;
- late double plonk;
- late double stride;
- late double infds;
-
- Playstyle(this._apm, this._pps, this._app, this._vsapm, this._dsp, this._gbe, this._srarea, this._statrank) {
- double nmapm = ((_apm / _srarea) / ((0.069 * pow(1.0017, (pow(_statrank, 5) / 4700))) + _statrank / 360)) - 1;
- double nmpps = ((_pps / _srarea) / (0.0084264 * pow(2.14, (-2 * (_statrank / 2.7 + 1.03))) - _statrank / 5750 + 0.0067)) - 1;
- //double nmvs = ((_vs / _srarea) / (0.1333 * pow(1.0021, ((pow(_statrank, 7) * (_statrank / 16.5)) / 1400000)) + _statrank / 133)) - 1;
- double nmapp = (_app / (0.1368803292 * pow(1.0024, (pow(_statrank, 5) / 2800)) + _statrank / 54)) - 1;
- //double nmdss = (_dss / (0.01436466667 * pow(4.1, ((_statrank - 9.6) / 2.9)) + _statrank / 140 + 0.01)) - 1;
- double nmdsp = (_dsp / (0.02136327583 * pow(14, ((_statrank - 14.75) / 3.9)) + _statrank / 152 + 0.022)) - 1;
- double nmgbe = (_gbe / (_statrank / 350 + 0.005948424455 * pow(3.8, ((_statrank - 6.1) / 4)) + 0.006)) - 1;
- double nmvsapm = (_vsapm / (-pow(((_statrank - 16) / 36), 2) + 2.133)) - 1;
- opener = ((nmapm + nmpps * 0.75 + nmvsapm * -10 + nmapp * 0.75 + nmdsp * -0.25) / 3.5) + 0.5;
- plonk = ((nmgbe + nmapp + nmdsp * 0.75 + nmpps * -1) / 2.73) + 0.5;
- stride = ((nmapm * -0.25 + nmpps + nmapp * -2 + nmdsp * -0.5) * 0.79) + 0.5;
- infds = ((nmdsp + nmapp * -0.75 + nmapm * 0.5 + nmvsapm * 1.5 + nmpps * 0.5) * 0.9) + 0.5;
- }
-}
-
-class EndContextMulti {
- String? userId;
- int? naturalOrder;
- int? inputs;
- int? piecesPlaced;
- Handling? handling;
- int? points;
- int? wins;
- double? secondary;
- List? secondaryTracking;
- double? tertiary;
- List? tertiaryTracking;
- double? extra;
- List? extraTracking;
- bool? success;
-
- EndContextMulti(
- {this.userId,
- this.naturalOrder,
- this.inputs,
- this.piecesPlaced,
- this.handling,
- this.points,
- this.wins,
- this.secondary,
- this.secondaryTracking,
- this.tertiary,
- this.tertiaryTracking,
- this.extra,
- this.extraTracking,
- this.success});
-
- EndContextMulti.fromJson(Map json) {
- userId = json['user']['_id'];
- handling = json['handling'] != null ? Handling.fromJson(json['handling']) : null;
- success = json['success'];
- inputs = json['inputs'];
- piecesPlaced = json['piecesplaced'];
- naturalOrder = json['naturalorder'];
- wins = json['wins'];
- points = json['points']['primary'];
- secondary = json['points']['secondary'];
- tertiary = json['points']['tertiary'];
- secondaryTracking = json['points']['secondaryAvgTracking'].cast();
- tertiaryTracking = json['points']['tertiaryAvgTracking'].cast();
- extra = json['points']['extra']['vs'];
- extraTracking = json['points']['extraAvgTracking']['aggregatestats___vsscore'].cast();
- }
-
- Map toJson() {
- final Map data = {};
- data['user'] = userId;
- if (handling != null) {
- data['handling'] = handling!.toJson();
- }
- data['success'] = success;
- data['inputs'] = inputs;
- data['piecesplaced'] = piecesPlaced;
- data['naturalorder'] = naturalOrder;
- data['wins'] = wins;
- data['points']['primary'] = points;
- data['points']['secondary'] = secondary;
- data['points']['tertiary'] = tertiary;
- data['points']['extra']['vs'] = extra;
- data['points']['extraAvgTracking']['aggregatestats___vsscore'] = extraTracking;
- return data;
- }
-}
-
-class TetraLeagueAlpha {
- late int gamesPlayed;
- late int gamesWon;
- late String bestRank;
- late bool decaying;
- late double rating;
- late String rank;
- double? glicko;
- double? rd;
- late String percentileRank;
- late double percentile;
- late int standing;
- late int standingLocal;
- String? nextRank;
- late int nextAt;
- String? prevRank;
- late int prevAt;
- double? apm;
- double? pps;
- double? vs;
- NerdStats? nerdStats;
- EstTr? estTr;
- Playstyle? playstyle;
- List? records;
-
- TetraLeagueAlpha(
- {required this.gamesPlayed,
- required this.gamesWon,
- required this.bestRank,
- required this.decaying,
- required this.rating,
- required this.rank,
- this.glicko,
- this.rd,
- required this.percentileRank,
- required this.percentile,
- required this.standing,
- required this.standingLocal,
- this.nextRank,
- required this.nextAt,
- this.prevRank,
- required this.prevAt,
- this.apm,
- this.pps,
- this.vs,
- this.records});
-
- double get winrate => gamesWon / gamesPlayed;
-
- TetraLeagueAlpha.fromJson(Map json) {
- gamesPlayed = json['gamesplayed'];
- gamesWon = json['gameswon'];
- rating = json['rating'].toDouble();
- glicko = json['glicko']?.toDouble();
- rd = json['rd']?.toDouble();
- rank = json['rank'];
- bestRank = json['bestrank'].toString();
- apm = json['apm']?.toDouble();
- pps = json['pps']?.toDouble();
- vs = json['vs']?.toDouble();
- decaying = json['decaying'];
- standing = json['standing'];
- percentile = json['percentile'].toDouble();
- standingLocal = json['standing_local'];
- prevRank = json['prev_rank'];
- prevAt = json['prev_at'];
- nextRank = json['next_rank'];
- nextAt = json['next_at'];
- percentileRank = json['percentile_rank'];
- nerdStats = (apm != null && pps != null && apm != null) ? NerdStats(apm!, pps!, vs!) : null;
- estTr = (nerdStats != null) ? EstTr(apm!, pps!, vs!, (rd != null) ? rd! : 69, nerdStats!.app, nerdStats!.dss, nerdStats!.dsp, nerdStats!.gbe) : null;
- playstyle =
- (nerdStats != null) ? Playstyle(apm!, pps!, nerdStats!.app, nerdStats!.vsapm, nerdStats!.dsp, nerdStats!.gbe, estTr!.srarea, estTr!.statrank) : null;
- }
-
- @override
- bool operator ==(covariant TetraLeagueAlpha other) => gamesPlayed == other.gamesPlayed && rd == other.rd;
-
- double? get esttracc => (estTr != null) ? estTr!.esttr - rating : null;
-
- Map toJson() {
- final Map data = {};
- data['gamesplayed'] = gamesPlayed;
- data['gameswon'] = gamesWon;
- data['rating'] = rating;
- if (glicko != null) data['glicko'] = glicko;
- if (rd != null) data['rd'] = rd;
- data['rank'] = rank;
- data['bestrank'] = bestRank;
- if (apm != null) data['apm'] = apm;
- if (pps != null) data['pps'] = pps;
- if (vs != null) data['vs'] = vs;
- data['decaying'] = decaying;
- data['standing'] = standing;
- data['percentile'] = percentile;
- data['standing_local'] = standingLocal;
- if (prevRank != null) data['prev_rank'] = prevRank;
- data['prev_at'] = prevAt;
- if (nextRank != null) data['next_rank'] = nextRank;
- data['next_at'] = nextAt;
- data['percentile_rank'] = percentileRank;
- return data;
- }
-}
-
-class RecordSingle {
- late String userId;
- late String replayId;
- late String ownId;
- late String stream;
- DateTime? timestamp;
- EndContextSingle? endContext;
- int? rank;
-
- RecordSingle({required this.userId, required this.replayId, required this.ownId, this.timestamp, this.endContext, this.rank});
-
- RecordSingle.fromJson(Map json, int? ran) {
- //developer.log("RecordSingle.fromJson: $json", name: "data_objects/tetrio");
- ownId = json['_id'];
- endContext = json['endcontext'] != null ? EndContextSingle.fromJson(json['endcontext']) : null;
- replayId = json['replayid'];
- stream = json['stream'];
- timestamp = DateTime.parse(json['ts']);
- userId = json['user']['_id'];
- rank = ran;
- }
-
- Map toJson() {
- final Map data = {};
- data['_id'] = ownId;
- if (endContext != null) {
- data['endcontext'] = endContext!.toJson();
- }
- data['ismulti'] = false;
- data['replayid'] = replayId;
- data['ts'] = timestamp;
- data['user_id'] = userId;
- return data;
- }
-}
-
-class TetrioZen {
- late int level;
- late int score;
-
- TetrioZen({required this.level, required this.score});
-
- TetrioZen.fromJson(Map json) {
- level = json['level'];
- score = json['score'];
- }
-
- Map toJson() {
- final Map data = {};
- data['level'] = level;
- data['score'] = score;
- return data;
- }
-}
-
-class Distinguishment {
- late String type;
- String? detail;
- String? header;
- String? footer;
-
- Distinguishment({required this.type, this.detail, this.header, this.footer});
-
- Distinguishment.fromJson(Map json) {
- type = json['type'];
- detail = json['detail'];
- header = json['header'];
- footer = json['footer'];
- }
-
- @override
- bool operator ==(covariant Distinguishment other) => type == other.type && detail == other.detail && header == other.header && footer == other.footer;
-
- Map toJson() {
- final Map data = {};
- data['type'] = type;
- data['detail'] = detail;
- data['header'] = header;
- data['footer'] = footer;
- return data;
- }
-}
-
-class TetrioPlayersLeaderboard {
- late String type;
- late List leaderboard;
-
- TetrioPlayersLeaderboard(this.type, this.leaderboard);
-
- TetrioPlayersLeaderboard.fromJson(Map json, String type) {
- type = type;
- for (Map entry in json['users']) {
- leaderboard.add(TetrioPlayerFromLeaderboard.fromJson(entry));
- }
- }
-}
-
-class TetrioPlayerFromLeaderboard {
- late String userId;
- late String username;
- late String role;
- late double xp;
- String? country;
- late bool supporter;
- late bool verified;
- late TetraLeagueAlpha league;
-
- TetrioPlayerFromLeaderboard(this.userId, this.username, this.role, this.xp, this.country, this.supporter, this.verified, this.league);
-
- TetrioPlayerFromLeaderboard.fromJson(Map json) {
- userId = json['_id'];
- username = json['username'];
- role = json['role'];
- xp = json['xp'].toDouble();
- country = json['country '];
- supporter = json['supporter'];
- verified = json['verified'];
- league = TetraLeagueAlpha.fromJson(json['league']);
- }
-}
+import 'dart:math';
+import 'package:flutter/foundation.dart';
+import 'package:vector_math/vector_math.dart';
+import 'dart:developer' as developer;
+import 'package:http/http.dart' as http;
+import 'dart:convert';
+
+Duration doubleSecondsToDuration(double value) {
+ value = value * 1000000;
+ return Duration(microseconds: value.floor());
+}
+
+Duration doubleMillisecondsToDuration(double value) {
+ value = value * 1000;
+ return Duration(microseconds: value.floor());
+}
+
+class TetrioPlayer {
+ late String userId;
+ late String username;
+ late DateTime state;
+ late String role;
+ int? avatarRevision;
+ int? bannerRevision;
+ DateTime? registrationTime;
+ List badges = [];
+ String? bio;
+ String? country;
+ late int friendCount;
+ late int gamesPlayed;
+ late int gamesWon;
+ late Duration gameTime;
+ late double xp;
+ late int supporterTier;
+ late bool verified;
+ bool? badstanding;
+ String? botmaster;
+ late Connections connections;
+ late TetraLeagueAlpha tlSeason1;
+ List sprint = [];
+ List blitz = [];
+ TetrioZen? zen;
+ Distinguishment? distinguishment;
+
+ TetrioPlayer({
+ required this.userId,
+ required this.username,
+ required this.role,
+ required this.state,
+ this.avatarRevision,
+ this.bannerRevision,
+ this.registrationTime,
+ required this.badges,
+ this.bio,
+ this.country,
+ required this.friendCount,
+ required this.gamesPlayed,
+ required this.gamesWon,
+ required this.gameTime,
+ required this.xp,
+ required this.supporterTier,
+ required this.verified,
+ this.badstanding,
+ this.botmaster,
+ required this.connections,
+ required this.tlSeason1,
+ required this.sprint,
+ required this.blitz,
+ this.zen,
+ this.distinguishment,
+ });
+
+ double get level => pow((xp / 500), 0.6) + (xp / (5000 + (max(0, xp - 4 * pow(10, 6)) / 5000))) + 1;
+
+ TetrioPlayer.fromJson(Map json, DateTime stateTime, bool fetchRecords) {
+ //developer.log("TetrioPlayer.fromJson $stateTime: $json", name: "data_objects/tetrio");
+ userId = json['_id'];
+ username = json['username'];
+ state = stateTime;
+ role = json['role'];
+ registrationTime = json['ts'] != null ? DateTime.parse(json['ts']) : null;
+ if (json['badges'] != null) {
+ json['badges'].forEach((v) {
+ badges.add(Badge.fromJson(v));
+ });
+ }
+ xp = json['xp'].toDouble();
+ gamesPlayed = json['gamesplayed'];
+ gamesWon = json['gameswon'];
+ gameTime = doubleSecondsToDuration(json['gametime'].toDouble());
+ country = json['country'];
+ supporterTier = json['supporter_tier'];
+ verified = json['verified'];
+ tlSeason1 = TetraLeagueAlpha.fromJson(json['league']);
+ avatarRevision = json['avatar_revision'];
+ bannerRevision = json['banner_revision'];
+ bio = json['bio'];
+ connections = Connections.fromJson(json['connections']);
+ distinguishment = json['distinguishment'] != null ? Distinguishment.fromJson(json['distinguishment']) : null;
+ friendCount = json['friend_count'] ?? 0;
+ badstanding = json['badstanding'];
+ botmaster = json['botmaster'];
+ if (fetchRecords) {
+ var url = Uri.https('ch.tetr.io', 'api/users/$userId/records');
+ Future response = http.get(url);
+ response.then((value) {
+ if (value.statusCode == 200) {
+ Map jsonRecords = jsonDecode(value.body);
+ sprint = jsonRecords['data']['records']['40l']['record'] != null
+ ? [RecordSingle.fromJson(jsonRecords['data']['records']['40l']['record'], jsonRecords['data']['records']['40l']['rank'])]
+ : [];
+ blitz = jsonRecords['data']['records']['blitz']['record'] != null
+ ? [RecordSingle.fromJson(jsonRecords['data']['records']['blitz']['record'], jsonRecords['data']['records']['blitz']['rank'])]
+ : [];
+ zen = TetrioZen.fromJson(jsonRecords['data']['zen']);
+ } else {
+ developer.log("TetrioPlayer.fromJson exception", name: "data_objects/tetrio", error: value.statusCode);
+ throw Exception('Failed to fetch player');
+ }
+ });
+ }
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['_id'] = userId;
+ data['username'] = username;
+ data['role'] = role;
+ if (registrationTime != null) data['ts'] = registrationTime?.toString();
+ data['badges'] = badges.map((v) => v.toJson()).toList();
+ data['xp'] = xp;
+ data['gamesplayed'] = gamesPlayed;
+ data['gameswon'] = gamesWon;
+ data['gametime'] = gameTime.inMicroseconds / 1000000;
+ if (country != null) data['country'] = country;
+ data['supporter_tier'] = supporterTier;
+ data['verified'] = verified;
+ data['league'] = tlSeason1.toJson();
+ if (distinguishment != null) data['distinguishment'] = distinguishment?.toJson();
+ if (avatarRevision != null) data['avatar_revision'] = avatarRevision;
+ if (bannerRevision != null) data['banner_revision'] = bannerRevision;
+ if (data['bio'] != null) data['bio'] = bio;
+ data['connections'] = connections.toJson();
+ data['friend_count'] = friendCount;
+ if (badstanding != null) data['badstanding'] = badstanding;
+ if (botmaster != null) data['botmaster'] = botmaster;
+ //developer.log("TetrioPlayer.toJson: $data", name: "data_objects/tetrio");
+ return data;
+ }
+
+ bool isSameState(TetrioPlayer other) {
+ if (userId != other.userId) return false;
+ if (username != other.username) return false;
+ if (role != other.role) return false;
+ if (listEquals(badges, other.badges) == false) return false;
+ //if (bio != other.bio) return false;
+ if (country != other.country) return false;
+ if (friendCount != other.friendCount) return false;
+ if (gamesPlayed != other.gamesPlayed) return false;
+ if (gamesWon != other.gamesWon) return false;
+ if (gameTime != other.gameTime) return false;
+ if (xp != other.xp) return false;
+ if (supporterTier != other.supporterTier) return false;
+ if (verified != other.verified) return false;
+ if (badstanding != other.badstanding) return false;
+ if (botmaster != other.botmaster) return false;
+ if (connections != other.connections) return false;
+ if (tlSeason1 != other.tlSeason1) return false;
+ if (distinguishment != other.distinguishment) return false;
+ return true;
+ }
+
+ @override
+ String toString() {
+ return "$username ($state)";
+ }
+
+ @override
+ int get hashCode => state.hashCode;
+
+ @override
+ bool operator ==(covariant TetrioPlayer other) => (userId == other.userId);
+}
+
+class Badge {
+ late String badgeId;
+ late String label;
+ DateTime? ts;
+
+ Badge({required this.badgeId, required this.label, this.ts});
+
+ Badge.fromJson(Map json) {
+ badgeId = json['id'];
+ label = json['label'];
+ ts = (json['ts'] != null && json['ts'] is String) ? DateTime.parse(json['ts']) : null; // man i love osk
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['id'] = badgeId;
+ data['label'] = label;
+ data['ts'] = ts?.toString();
+ return data;
+ }
+
+ @override
+ String toString() {
+ return "Badge $label ($badgeId)";
+ }
+
+ @override
+ int get hashCode => badgeId.hashCode;
+
+ @override
+ bool operator ==(covariant Badge other) => badgeId == other.badgeId;
+}
+
+class Connections {
+ Discord? discord;
+
+ Connections({this.discord});
+
+ Connections.fromJson(Map json) {
+ discord = json['discord'] != null ? Discord.fromJson(json['discord']) : null;
+ }
+ @override
+ bool operator ==(covariant Connections other) => discord == other.discord;
+
+ Map toJson() {
+ final Map data = {};
+ if (discord != null) {
+ data['discord'] = discord!.toJson();
+ }
+ return data;
+ }
+}
+
+class Clears {
+ late int singles;
+ late int doubles;
+ late int triples;
+ late int quads;
+ late int allClears;
+ late int tSpinZeros;
+ late int tSpinSingles;
+ late int tSpinDoubles;
+ late int tSpinTriples;
+ late int tSpinQuads;
+ late int tSpinMiniZeros;
+ late int tSpinMiniSingles;
+ late int tSpinMiniDoubles;
+
+ Clears(
+ {required this.singles,
+ required this.doubles,
+ required this.triples,
+ required this.quads,
+ required this.allClears,
+ required this.tSpinZeros,
+ required this.tSpinSingles,
+ required this.tSpinDoubles,
+ required this.tSpinTriples,
+ required this.tSpinQuads,
+ required this.tSpinMiniZeros,
+ required this.tSpinMiniSingles,
+ required this.tSpinMiniDoubles});
+
+ Clears.fromJson(Map json) {
+ singles = json['singles'];
+ doubles = json['doubles'];
+ triples = json['triples'];
+ quads = json['quads'];
+ tSpinZeros = json['realtspins'];
+ tSpinMiniZeros = json['minitspins'];
+ tSpinMiniSingles = json['minitspinsingles'];
+ tSpinSingles = json['tspinsingles'];
+ tSpinMiniDoubles = json['minitspindoubles'];
+ tSpinDoubles = json['tspindoubles'];
+ tSpinTriples = json['tspintriples'];
+ tSpinQuads = json['tspinquads'];
+ allClears = json['allclear'];
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['singles'] = singles;
+ data['doubles'] = doubles;
+ data['triples'] = triples;
+ data['quads'] = quads;
+ data['realtspins'] = tSpinZeros;
+ data['minitspins'] = tSpinMiniZeros;
+ data['minitspinsingles'] = tSpinMiniSingles;
+ data['tspinsingles'] = tSpinSingles;
+ data['minitspindoubles'] = tSpinMiniDoubles;
+ data['tspindoubles'] = tSpinDoubles;
+ data['tspintriples'] = tSpinTriples;
+ data['tspinquads'] = tSpinQuads;
+ data['allclear'] = allClears;
+ return data;
+ }
+}
+
+class Discord {
+ late String id;
+ late String username;
+
+ Discord({required this.id, required this.username});
+
+ Discord.fromJson(Map json) {
+ id = json['id'];
+ username = json['username'];
+ }
+
+ @override
+ bool operator ==(covariant Discord other) => id == other.id;
+
+ Map toJson() {
+ final Map data = {};
+ data['id'] = id;
+ data['username'] = username;
+ return data;
+ }
+}
+
+class Finesse {
+ late int combo;
+ late int faults;
+ late int perfectPieces;
+
+ Finesse({required this.combo, required this.faults, required this.perfectPieces});
+
+ Finesse.fromJson(Map json) {
+ combo = json['combo'];
+ faults = json['faults'];
+ perfectPieces = json['perfectpieces'];
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['combo'] = combo;
+ data['faults'] = faults;
+ data['perfectpieces'] = perfectPieces;
+ return data;
+ }
+}
+
+class EndContextSingle {
+ late String gameType;
+ late int topBtB;
+ late int topCombo;
+ late int holds;
+ late int inputs;
+ late int level;
+ late int piecesPlaced;
+ late int lines;
+ late int score;
+ late int seed;
+ late Duration finalTime;
+ late int tSpins;
+ late Clears clears;
+ late Finesse finesse;
+
+ double get pps => piecesPlaced / (finalTime.inMicroseconds / 1000000);
+ double get kpp => inputs / piecesPlaced;
+ double get spp => score / piecesPlaced;
+ double get kps => inputs / (finalTime.inMicroseconds / 1000000);
+ double get finessePercentage => finesse.perfectPieces / piecesPlaced;
+
+ EndContextSingle(
+ {required this.gameType,
+ required this.topBtB,
+ required this.topCombo,
+ required this.holds,
+ required this.inputs,
+ required this.level,
+ required this.piecesPlaced,
+ required this.lines,
+ required this.score,
+ required this.seed,
+ required this.finalTime,
+ required this.tSpins,
+ required this.clears,
+ required this.finesse});
+
+ EndContextSingle.fromJson(Map json) {
+ seed = json['seed'];
+ lines = json['lines'];
+ inputs = json['inputs'];
+ holds = json['holds'] ?? 0;
+ finalTime = doubleMillisecondsToDuration(json['finalTime'].toDouble());
+ score = json['score'];
+ level = json['level'];
+ topCombo = json['topcombo'];
+ topBtB = json['topbtb'];
+ tSpins = json['tspins'];
+ piecesPlaced = json['piecesplaced'];
+ clears = Clears.fromJson(json['clears']);
+ finesse = Finesse.fromJson(json['finesse']);
+ gameType = json['gametype'];
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['seed'] = seed;
+ data['lines'] = lines;
+ data['inputs'] = inputs;
+ data['holds'] = holds;
+ data['score'] = score;
+ data['level'] = level;
+ data['topcombo'] = topCombo;
+ data['topbtb'] = topBtB;
+ data['tspins'] = tSpins;
+ data['piecesplaced'] = piecesPlaced;
+ data['clears'] = clears.toJson();
+ data['finesse'] = finesse.toJson();
+ data['finalTime'] = finalTime;
+ data['gametype'] = gameType;
+ return data;
+ }
+}
+
+class Handling {
+ late double arr;
+ late double das;
+ late int sdf;
+ late int dcd;
+ late bool cancel;
+ late bool safeLock;
+
+ Handling({required this.arr, required this.das, required this.sdf, required this.dcd, required this.cancel, required this.safeLock});
+
+ Handling.fromJson(Map json) {
+ arr = json['arr'];
+ das = json['das'];
+ dcd = json['dcd'];
+ sdf = json['sdf'];
+ safeLock = json['safelock'];
+ cancel = json['cancel'];
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['arr'] = arr;
+ data['das'] = das;
+ data['dcd'] = dcd;
+ data['sdf'] = sdf;
+ data['safelock'] = safeLock;
+ data['cancel'] = cancel;
+ return data;
+ }
+}
+
+class NerdStats {
+ final double _apm;
+ final double _pps;
+ final double _vs;
+ late double app;
+ late double vsapm;
+ late double dss;
+ late double dsp;
+ late double appdsp;
+ late double cheese;
+ late double gbe;
+ late double nyaapp;
+ late double area;
+
+ NerdStats(this._apm, this._pps, this._vs) {
+ app = _apm / (_pps * 60);
+ vsapm = _vs / _apm;
+ dss = (_vs / 100) - (_apm / 60);
+ dsp = ((_vs / 100) - (_apm / 60)) / _pps;
+ appdsp = app + dsp;
+ cheese = (dsp * 150) + (((_vs / _apm) - 2) * 50) + (0.6 - app) * 125;
+ gbe = ((app * dss) / _pps) * 2;
+ nyaapp = app - 5 * tan(radians((cheese / -30) + 1));
+ area = _apm * 1 + _pps * 45 + _vs * 0.444 + app * 185 + dss * 175 + dsp * 450 + gbe * 315;
+ }
+}
+
+class EstTr {
+ final double _apm;
+ final double _pps;
+ final double _vs;
+ final double _rd;
+ final double _app;
+ final double _dss;
+ final double _dsp;
+ final double _gbe;
+ late double esttr;
+ late double srarea;
+ late double statrank;
+
+ EstTr(this._apm, this._pps, this._vs, this._rd, this._app, this._dss, this._dsp, this._gbe) {
+ srarea = (_apm * 0) + (_pps * 135) + (_vs * 0) + (_app * 290) + (_dss * 0) + (_dsp * 700) + (_gbe * 0);
+ statrank = 11.2 * atan((srarea - 93) / 130) + 1;
+ if (statrank <= 0) statrank = 0.001;
+ double estglicko = (4.0867 * srarea + 186.68);
+ double temp = (1500 - estglicko) * pi;
+ double temp2 = pow((15.9056943314 * (pow(_rd, 2)) + 3527584.25978), 0.5) as double;
+ double temp3 = 1 + pow(10, (temp / temp2)) as double;
+ esttr = 25000 / temp3;
+ }
+}
+
+class Playstyle {
+ final double _apm;
+ final double _pps;
+ //final double _vs;
+ final double _app;
+ final double _vsapm;
+ //final double _dss;
+ final double _dsp;
+ final double _gbe;
+ final double _srarea;
+ final double _statrank;
+ late double opener;
+ late double plonk;
+ late double stride;
+ late double infds;
+
+ Playstyle(this._apm, this._pps, this._app, this._vsapm, this._dsp, this._gbe, this._srarea, this._statrank) {
+ double nmapm = ((_apm / _srarea) / ((0.069 * pow(1.0017, (pow(_statrank, 5) / 4700))) + _statrank / 360)) - 1;
+ double nmpps = ((_pps / _srarea) / (0.0084264 * pow(2.14, (-2 * (_statrank / 2.7 + 1.03))) - _statrank / 5750 + 0.0067)) - 1;
+ //double nmvs = ((_vs / _srarea) / (0.1333 * pow(1.0021, ((pow(_statrank, 7) * (_statrank / 16.5)) / 1400000)) + _statrank / 133)) - 1;
+ double nmapp = (_app / (0.1368803292 * pow(1.0024, (pow(_statrank, 5) / 2800)) + _statrank / 54)) - 1;
+ //double nmdss = (_dss / (0.01436466667 * pow(4.1, ((_statrank - 9.6) / 2.9)) + _statrank / 140 + 0.01)) - 1;
+ double nmdsp = (_dsp / (0.02136327583 * pow(14, ((_statrank - 14.75) / 3.9)) + _statrank / 152 + 0.022)) - 1;
+ double nmgbe = (_gbe / (_statrank / 350 + 0.005948424455 * pow(3.8, ((_statrank - 6.1) / 4)) + 0.006)) - 1;
+ double nmvsapm = (_vsapm / (-pow(((_statrank - 16) / 36), 2) + 2.133)) - 1;
+ opener = ((nmapm + nmpps * 0.75 + nmvsapm * -10 + nmapp * 0.75 + nmdsp * -0.25) / 3.5) + 0.5;
+ plonk = ((nmgbe + nmapp + nmdsp * 0.75 + nmpps * -1) / 2.73) + 0.5;
+ stride = ((nmapm * -0.25 + nmpps + nmapp * -2 + nmdsp * -0.5) * 0.79) + 0.5;
+ infds = ((nmdsp + nmapp * -0.75 + nmapm * 0.5 + nmvsapm * 1.5 + nmpps * 0.5) * 0.9) + 0.5;
+ }
+}
+
+class EndContextMulti {
+ String? userId;
+ int? naturalOrder;
+ int? inputs;
+ int? piecesPlaced;
+ Handling? handling;
+ int? points;
+ int? wins;
+ double? secondary;
+ List? secondaryTracking;
+ double? tertiary;
+ List? tertiaryTracking;
+ double? extra;
+ List? extraTracking;
+ bool? success;
+
+ EndContextMulti(
+ {this.userId,
+ this.naturalOrder,
+ this.inputs,
+ this.piecesPlaced,
+ this.handling,
+ this.points,
+ this.wins,
+ this.secondary,
+ this.secondaryTracking,
+ this.tertiary,
+ this.tertiaryTracking,
+ this.extra,
+ this.extraTracking,
+ this.success});
+
+ EndContextMulti.fromJson(Map json) {
+ userId = json['user']['_id'];
+ handling = json['handling'] != null ? Handling.fromJson(json['handling']) : null;
+ success = json['success'];
+ inputs = json['inputs'];
+ piecesPlaced = json['piecesplaced'];
+ naturalOrder = json['naturalorder'];
+ wins = json['wins'];
+ points = json['points']['primary'];
+ secondary = json['points']['secondary'];
+ tertiary = json['points']['tertiary'];
+ secondaryTracking = json['points']['secondaryAvgTracking'].cast();
+ tertiaryTracking = json['points']['tertiaryAvgTracking'].cast();
+ extra = json['points']['extra']['vs'];
+ extraTracking = json['points']['extraAvgTracking']['aggregatestats___vsscore'].cast();
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['user'] = userId;
+ if (handling != null) {
+ data['handling'] = handling!.toJson();
+ }
+ data['success'] = success;
+ data['inputs'] = inputs;
+ data['piecesplaced'] = piecesPlaced;
+ data['naturalorder'] = naturalOrder;
+ data['wins'] = wins;
+ data['points']['primary'] = points;
+ data['points']['secondary'] = secondary;
+ data['points']['tertiary'] = tertiary;
+ data['points']['extra']['vs'] = extra;
+ data['points']['extraAvgTracking']['aggregatestats___vsscore'] = extraTracking;
+ return data;
+ }
+}
+
+class TetraLeagueAlpha {
+ late int gamesPlayed;
+ late int gamesWon;
+ late String bestRank;
+ late bool decaying;
+ late double rating;
+ late String rank;
+ double? glicko;
+ double? rd;
+ late String percentileRank;
+ late double percentile;
+ late int standing;
+ late int standingLocal;
+ String? nextRank;
+ late int nextAt;
+ String? prevRank;
+ late int prevAt;
+ double? apm;
+ double? pps;
+ double? vs;
+ NerdStats? nerdStats;
+ EstTr? estTr;
+ Playstyle? playstyle;
+ List? records;
+
+ TetraLeagueAlpha(
+ {required this.gamesPlayed,
+ required this.gamesWon,
+ required this.bestRank,
+ required this.decaying,
+ required this.rating,
+ required this.rank,
+ this.glicko,
+ this.rd,
+ required this.percentileRank,
+ required this.percentile,
+ required this.standing,
+ required this.standingLocal,
+ this.nextRank,
+ required this.nextAt,
+ this.prevRank,
+ required this.prevAt,
+ this.apm,
+ this.pps,
+ this.vs,
+ this.records});
+
+ double get winrate => gamesWon / gamesPlayed;
+
+ TetraLeagueAlpha.fromJson(Map json) {
+ gamesPlayed = json['gamesplayed'];
+ gamesWon = json['gameswon'];
+ rating = json['rating'].toDouble();
+ glicko = json['glicko']?.toDouble();
+ rd = json['rd']?.toDouble();
+ rank = json['rank'];
+ bestRank = json['bestrank'].toString();
+ apm = json['apm']?.toDouble();
+ pps = json['pps']?.toDouble();
+ vs = json['vs']?.toDouble();
+ decaying = json['decaying'];
+ standing = json['standing'];
+ percentile = json['percentile'].toDouble();
+ standingLocal = json['standing_local'];
+ prevRank = json['prev_rank'];
+ prevAt = json['prev_at'];
+ nextRank = json['next_rank'];
+ nextAt = json['next_at'];
+ percentileRank = json['percentile_rank'];
+ nerdStats = (apm != null && pps != null && apm != null) ? NerdStats(apm!, pps!, vs!) : null;
+ estTr = (nerdStats != null) ? EstTr(apm!, pps!, vs!, (rd != null) ? rd! : 69, nerdStats!.app, nerdStats!.dss, nerdStats!.dsp, nerdStats!.gbe) : null;
+ playstyle =
+ (nerdStats != null) ? Playstyle(apm!, pps!, nerdStats!.app, nerdStats!.vsapm, nerdStats!.dsp, nerdStats!.gbe, estTr!.srarea, estTr!.statrank) : null;
+ }
+
+ @override
+ bool operator ==(covariant TetraLeagueAlpha other) => gamesPlayed == other.gamesPlayed && rd == other.rd;
+
+ double? get esttracc => (estTr != null) ? estTr!.esttr - rating : null;
+
+ Map toJson() {
+ final Map data = {};
+ data['gamesplayed'] = gamesPlayed;
+ data['gameswon'] = gamesWon;
+ data['rating'] = rating;
+ if (glicko != null) data['glicko'] = glicko;
+ if (rd != null) data['rd'] = rd;
+ data['rank'] = rank;
+ data['bestrank'] = bestRank;
+ if (apm != null) data['apm'] = apm;
+ if (pps != null) data['pps'] = pps;
+ if (vs != null) data['vs'] = vs;
+ data['decaying'] = decaying;
+ data['standing'] = standing;
+ data['percentile'] = percentile;
+ data['standing_local'] = standingLocal;
+ if (prevRank != null) data['prev_rank'] = prevRank;
+ data['prev_at'] = prevAt;
+ if (nextRank != null) data['next_rank'] = nextRank;
+ data['next_at'] = nextAt;
+ data['percentile_rank'] = percentileRank;
+ return data;
+ }
+}
+
+class RecordSingle {
+ late String userId;
+ late String replayId;
+ late String ownId;
+ late String stream;
+ DateTime? timestamp;
+ EndContextSingle? endContext;
+ int? rank;
+
+ RecordSingle({required this.userId, required this.replayId, required this.ownId, this.timestamp, this.endContext, this.rank});
+
+ RecordSingle.fromJson(Map json, int? ran) {
+ //developer.log("RecordSingle.fromJson: $json", name: "data_objects/tetrio");
+ ownId = json['_id'];
+ endContext = json['endcontext'] != null ? EndContextSingle.fromJson(json['endcontext']) : null;
+ replayId = json['replayid'];
+ stream = json['stream'];
+ timestamp = DateTime.parse(json['ts']);
+ userId = json['user']['_id'];
+ rank = ran;
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['_id'] = ownId;
+ if (endContext != null) {
+ data['endcontext'] = endContext!.toJson();
+ }
+ data['ismulti'] = false;
+ data['replayid'] = replayId;
+ data['ts'] = timestamp;
+ data['user_id'] = userId;
+ return data;
+ }
+}
+
+class TetrioZen {
+ late int level;
+ late int score;
+
+ TetrioZen({required this.level, required this.score});
+
+ TetrioZen.fromJson(Map json) {
+ level = json['level'];
+ score = json['score'];
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['level'] = level;
+ data['score'] = score;
+ return data;
+ }
+}
+
+class Distinguishment {
+ late String type;
+ String? detail;
+ String? header;
+ String? footer;
+
+ Distinguishment({required this.type, this.detail, this.header, this.footer});
+
+ Distinguishment.fromJson(Map json) {
+ type = json['type'];
+ detail = json['detail'];
+ header = json['header'];
+ footer = json['footer'];
+ }
+
+ @override
+ bool operator ==(covariant Distinguishment other) => type == other.type && detail == other.detail && header == other.header && footer == other.footer;
+
+ Map toJson() {
+ final Map data = {};
+ data['type'] = type;
+ data['detail'] = detail;
+ data['header'] = header;
+ data['footer'] = footer;
+ return data;
+ }
+}
+
+class TetrioPlayersLeaderboard {
+ late String type;
+ late List leaderboard;
+
+ TetrioPlayersLeaderboard(this.type, this.leaderboard);
+
+ TetrioPlayersLeaderboard.fromJson(Map json, String type) {
+ type = type;
+ for (Map entry in json['users']) {
+ leaderboard.add(TetrioPlayerFromLeaderboard.fromJson(entry));
+ }
+ }
+}
+
+class TetrioPlayerFromLeaderboard {
+ late String userId;
+ late String username;
+ late String role;
+ late double xp;
+ String? country;
+ late bool supporter;
+ late bool verified;
+ late TetraLeagueAlpha league;
+
+ TetrioPlayerFromLeaderboard(this.userId, this.username, this.role, this.xp, this.country, this.supporter, this.verified, this.league);
+
+ TetrioPlayerFromLeaderboard.fromJson(Map json) {
+ userId = json['_id'];
+ username = json['username'];
+ role = json['role'];
+ xp = json['xp'].toDouble();
+ country = json['country '];
+ supporter = json['supporter'];
+ verified = json['verified'];
+ league = TetraLeagueAlpha.fromJson(json['league']);
+ }
+}
diff --git a/lib/main.dart b/lib/main.dart
index 88c92a0..65a1168 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,21 +1,21 @@
-import 'dart:io';
-import 'package:flutter/material.dart';
-import 'package:sqflite_common_ffi/sqflite_ffi.dart';
-import 'package:tetra_stats/views/main_view.dart';
-import 'package:tetra_stats/views/settings_view.dart';
-import 'package:tetra_stats/views/tracked_players_view.dart';
-import 'package:tetra_stats/views/calc_view.dart';
-
-void main() {
- if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) {
- sqfliteFfiInit();
- databaseFactory = databaseFactoryFfi;
- }
- runApp(MaterialApp(
- home: const MainView(),
- routes: {"/settings": (context) => const SettingsView(), "/states": (context) => const TrackedPlayersView(), "/calc": (context) => const CalcView()},
- theme: ThemeData(
- fontFamily: 'Eurostile Round',
- colorScheme: const ColorScheme.dark(primary: Colors.cyanAccent, secondary: Colors.purpleAccent),
- scaffoldBackgroundColor: Colors.black)));
-}
+import 'dart:io';
+import 'package:flutter/material.dart';
+import 'package:sqflite_common_ffi/sqflite_ffi.dart';
+import 'package:tetra_stats/views/main_view.dart';
+import 'package:tetra_stats/views/settings_view.dart';
+import 'package:tetra_stats/views/tracked_players_view.dart';
+import 'package:tetra_stats/views/calc_view.dart';
+
+void main() {
+ if (Platform.isWindows || Platform.isLinux || Platform.isMacOS) {
+ sqfliteFfiInit();
+ databaseFactory = databaseFactoryFfi;
+ }
+ runApp(MaterialApp(
+ home: const MainView(),
+ routes: {"/settings": (context) => const SettingsView(), "/states": (context) => const TrackedPlayersView(), "/calc": (context) => const CalcView()},
+ theme: ThemeData(
+ fontFamily: 'Eurostile Round',
+ colorScheme: const ColorScheme.dark(primary: Colors.cyanAccent, secondary: Colors.purpleAccent),
+ scaffoldBackgroundColor: Colors.black)));
+}
diff --git a/lib/services/crud_exceptions.dart b/lib/services/crud_exceptions.dart
index 1443869..7804022 100644
--- a/lib/services/crud_exceptions.dart
+++ b/lib/services/crud_exceptions.dart
@@ -1,13 +1,13 @@
-class DatabaseAlreadyOpen implements Exception {}
-
-class DatabaseIsNotOpen implements Exception {}
-
-class UnableToGetDocuments implements Exception {}
-
-class CouldNotDeletePlayer implements Exception {}
-
-class CouldNotUpdatePlayer implements Exception {}
-
-class TetrioPlayerAlreadyExist implements Exception {}
-
-class TetrioPlayerNotExist implements Exception {}
+class DatabaseAlreadyOpen implements Exception {}
+
+class DatabaseIsNotOpen implements Exception {}
+
+class UnableToGetDocuments implements Exception {}
+
+class CouldNotDeletePlayer implements Exception {}
+
+class CouldNotUpdatePlayer implements Exception {}
+
+class TetrioPlayerAlreadyExist implements Exception {}
+
+class TetrioPlayerNotExist implements Exception {}
diff --git a/lib/services/sqlite_db_controller.dart b/lib/services/sqlite_db_controller.dart
index 5d8f6d4..0c878b0 100644
--- a/lib/services/sqlite_db_controller.dart
+++ b/lib/services/sqlite_db_controller.dart
@@ -1,54 +1,54 @@
-import 'dart:async';
-import 'package:sqflite/sqflite.dart';
-import 'package:path_provider/path_provider.dart' show MissingPlatformDirectoryException, getApplicationDocumentsDirectory;
-import 'package:tetra_stats/services/crud_exceptions.dart';
-import 'package:tetra_stats/services/tetrio_crud.dart';
-import 'package:path/path.dart' show join;
-
-const String dbName = "TetraStats.db";
-
-class DB {
- Database? _db;
- Future open() async {
- if (_db != null) {
- throw DatabaseAlreadyOpen();
- }
- try {
- final docsPath = await getApplicationDocumentsDirectory();
- final dbPath = join(docsPath.path, dbName);
- final db = await openDatabase(dbPath);
- _db = db;
- await db.execute(createTetrioUsersTable);
- await db.execute(createTetrioUsersToTrack);
- } on MissingPlatformDirectoryException {
- throw UnableToGetDocuments();
- }
- }
-
- Future close() async {
- final db = _db;
- if (db == null) {
- throw DatabaseIsNotOpen();
- } else {
- await db.close();
- _db = null;
- }
- }
-
- Database getDatabaseOrThrow() {
- final db = _db;
- if (db == null) {
- throw DatabaseIsNotOpen();
- } else {
- return db;
- }
- }
-
- Future ensureDbIsOpen() async {
- try {
- await open();
- } on DatabaseAlreadyOpen {
- // empty
- }
- }
-}
+import 'dart:async';
+import 'package:sqflite/sqflite.dart';
+import 'package:path_provider/path_provider.dart' show MissingPlatformDirectoryException, getApplicationDocumentsDirectory;
+import 'package:tetra_stats/services/crud_exceptions.dart';
+import 'package:tetra_stats/services/tetrio_crud.dart';
+import 'package:path/path.dart' show join;
+
+const String dbName = "TetraStats.db";
+
+class DB {
+ Database? _db;
+ Future open() async {
+ if (_db != null) {
+ throw DatabaseAlreadyOpen();
+ }
+ try {
+ final docsPath = await getApplicationDocumentsDirectory();
+ final dbPath = join(docsPath.path, dbName);
+ final db = await openDatabase(dbPath);
+ _db = db;
+ await db.execute(createTetrioUsersTable);
+ await db.execute(createTetrioUsersToTrack);
+ } on MissingPlatformDirectoryException {
+ throw UnableToGetDocuments();
+ }
+ }
+
+ Future close() async {
+ final db = _db;
+ if (db == null) {
+ throw DatabaseIsNotOpen();
+ } else {
+ await db.close();
+ _db = null;
+ }
+ }
+
+ Database getDatabaseOrThrow() {
+ final db = _db;
+ if (db == null) {
+ throw DatabaseIsNotOpen();
+ } else {
+ return db;
+ }
+ }
+
+ Future ensureDbIsOpen() async {
+ try {
+ await open();
+ } on DatabaseAlreadyOpen {
+ // empty
+ }
+ }
+}
diff --git a/lib/services/tetrio_crud.dart b/lib/services/tetrio_crud.dart
index c23d487..d064b28 100644
--- a/lib/services/tetrio_crud.dart
+++ b/lib/services/tetrio_crud.dart
@@ -1,224 +1,224 @@
-import 'dart:async';
-import 'dart:convert';
-import 'dart:developer' as developer;
-import 'package:http/http.dart' as http;
-import 'package:tetra_stats/services/crud_exceptions.dart';
-import 'package:tetra_stats/services/sqlite_db_controller.dart';
-import 'package:tetra_stats/data_objects/tetrio.dart';
-
-const String dbName = "TetraStats.db";
-const String tetrioUsersTable = "tetrioUsers";
-const String tetrioUsersToTrackTable = "tetrioUsersToTrack";
-const String idCol = "id";
-const String nickCol = "nickname";
-const String statesCol = "jsonStates";
-const String createTetrioUsersTable = '''
- CREATE TABLE IF NOT EXISTS "tetrioUsers" (
- "id" TEXT UNIQUE,
- "nickname" TEXT,
- "jsonStates" TEXT,
- PRIMARY KEY("id")
- );''';
-const String createTetrioUsersToTrack = '''
- CREATE TABLE IF NOT EXISTS "tetrioUsersToTrack" (
- "id" TEXT NOT NULL UNIQUE,
- PRIMARY KEY("ID")
- )
-''';
-
-class TetrioService extends DB {
- Map> _players = {};
- static final TetrioService _shared = TetrioService._sharedInstance();
- factory TetrioService() => _shared;
- late final StreamController