mirror of
https://github.com/dan63047/TetraStats.git
synced 2026-06-14 07:58:36 +00:00
Damage calc update, displaying progress of munching on main view
This commit is contained in:
Vendored
+3
-3
@@ -1,4 +1,4 @@
|
||||
flutter_app:
|
||||
flutter_app:
|
||||
command: tetra_stats
|
||||
arch: x64
|
||||
parent: /usr/local/lib
|
||||
@@ -6,10 +6,10 @@ flutter_app:
|
||||
|
||||
control:
|
||||
Package: tetra-stats
|
||||
Version: 2.0.8
|
||||
Version: 2.1.0
|
||||
Architecture: amd64
|
||||
Essential: no
|
||||
Priority: optional
|
||||
Depends:
|
||||
Maintainer: dan63047
|
||||
Description: Track your and other player stats in TETR.IO
|
||||
Description: Track your and other player stats in TETR.IO
|
||||
|
||||
Vendored
+2
-2
@@ -1,9 +1,9 @@
|
||||
[Desktop Entry]
|
||||
Version=2.0.8
|
||||
Version=2.1.0
|
||||
Name=Tetra Stats
|
||||
GenericName=Tetra Stats
|
||||
Comment=Track your and other player stats in TETR.IO
|
||||
Terminal=false
|
||||
Type=Application
|
||||
Categories=Utility
|
||||
Keywords=TETR.IO;tetrio;stats;
|
||||
Keywords=TETR.IO;tetrio;stats;
|
||||
|
||||
@@ -14,58 +14,20 @@ const double vsapmWeight = 60;
|
||||
const double cheeseWeight = 1.25;
|
||||
const double gbeWeight = 315;
|
||||
|
||||
const Map<int, double> xpTableScuffed = { // level: xp required
|
||||
05000: 67009018.4885772,
|
||||
10000: 763653437.386,
|
||||
15000: 2337651144.54149,
|
||||
20000: 4572735210.50902,
|
||||
25000: 7376166347.04745,
|
||||
const Map<int, double> xpTableScuffed = {
|
||||
// level: xp required
|
||||
05000: 67009018.4885772,
|
||||
10000: 763653437.386,
|
||||
15000: 2337651144.54149,
|
||||
20000: 4572735210.50902,
|
||||
25000: 7376166347.04745,
|
||||
30000: 10693620096.2168,
|
||||
40000: 18728882739.482,
|
||||
50000: 28468683855.2853
|
||||
};
|
||||
|
||||
const List<String> ranks = [
|
||||
"d",
|
||||
"d+",
|
||||
"c-",
|
||||
"c",
|
||||
"c+",
|
||||
"b-",
|
||||
"b",
|
||||
"b+",
|
||||
"a-",
|
||||
"a",
|
||||
"a+",
|
||||
"s-",
|
||||
"s",
|
||||
"s+",
|
||||
"ss",
|
||||
"u",
|
||||
"x",
|
||||
"x+"
|
||||
];
|
||||
const List<String> ranks2 = [
|
||||
"top1",
|
||||
"x+",
|
||||
"x",
|
||||
"u",
|
||||
"ss",
|
||||
"s+",
|
||||
"s",
|
||||
"s-",
|
||||
"a+",
|
||||
"a",
|
||||
"a-",
|
||||
"b+",
|
||||
"b",
|
||||
"b-",
|
||||
"c+",
|
||||
"c",
|
||||
"c-",
|
||||
"d+",
|
||||
"d"
|
||||
];
|
||||
const List<String> ranks = ["d", "d+", "c-", "c", "c+", "b-", "b", "b+", "a-", "a", "a+", "s-", "s", "s+", "ss", "u", "x", "x+"];
|
||||
const List<String> ranks2 = ["top1", "x+", "x", "u", "ss", "s+", "s", "s-", "a+", "a", "a-", "b+", "b", "b-", "c+", "c", "c-", "d+", "d"];
|
||||
const Map<String, double> rankCutoffs = {
|
||||
"x+": 0.002,
|
||||
"x": 0.01,
|
||||
@@ -223,46 +185,46 @@ const List<Color> lineClearsColors = [
|
||||
];
|
||||
|
||||
const Map<String, Duration> sprintAverages = {
|
||||
// based on https://discord.com/channels/673303546107658242/1260605501754839060/1329448681539244094
|
||||
'x+': Duration(seconds: 19, milliseconds: 223),
|
||||
'x': Duration(seconds: 24, milliseconds: 832),
|
||||
'u': Duration(seconds: 32, milliseconds: 586),
|
||||
'ss': Duration(seconds: 40, milliseconds: 011),
|
||||
's+': Duration(seconds: 47, milliseconds: 963),
|
||||
's': Duration(seconds: 54, milliseconds: 413),
|
||||
's-': Duration(seconds: 61, milliseconds: 740),
|
||||
'a+': Duration(seconds: 70, milliseconds: 101),
|
||||
'a': Duration(seconds: 73, milliseconds: 294),
|
||||
'a-': Duration(seconds: 81, milliseconds: 773),
|
||||
'b+': Duration(seconds: 88, milliseconds: 647),
|
||||
'b': Duration(seconds: 97, milliseconds: 699),
|
||||
'b-': Duration(seconds: 105, milliseconds: 721),
|
||||
'c+': Duration(seconds: 113, milliseconds: 229),
|
||||
'c': Duration(seconds: 124, milliseconds: 740),
|
||||
'c-': Duration(seconds: 129, milliseconds: 382),
|
||||
'd+': Duration(seconds: 138, milliseconds: 947),
|
||||
'd': Duration(seconds: 155, milliseconds: 190),
|
||||
// based on https://discord.com/channels/673303546107658242/1260605501754839060/1379885551263420498
|
||||
'x+': Duration(seconds: 19, milliseconds: 335),
|
||||
'x': Duration(seconds: 24, milliseconds: 075),
|
||||
'u': Duration(seconds: 31, milliseconds: 293),
|
||||
'ss': Duration(seconds: 40, milliseconds: 283),
|
||||
's+': Duration(seconds: 47, milliseconds: 511),
|
||||
's': Duration(seconds: 54, milliseconds: 210),
|
||||
's-': Duration(seconds: 60, milliseconds: 496),
|
||||
'a+': Duration(seconds: 68, milliseconds: 767),
|
||||
'a': Duration(seconds: 74, milliseconds: 417),
|
||||
'a-': Duration(seconds: 77, milliseconds: 619),
|
||||
'b+': Duration(seconds: 89, milliseconds: 294),
|
||||
'b': Duration(seconds: 98, milliseconds: 297),
|
||||
'b-': Duration(seconds: 105, milliseconds: 210),
|
||||
'c+': Duration(seconds: 109, milliseconds: 148),
|
||||
'c': Duration(seconds: 128, milliseconds: 228),
|
||||
'c-': Duration(seconds: 138, milliseconds: 100),
|
||||
'd+': Duration(seconds: 143, milliseconds: 767),
|
||||
'd': Duration(seconds: 163, milliseconds: 389),
|
||||
};
|
||||
|
||||
const Map<String, int> blitzAverages = {
|
||||
'x+': 886046,
|
||||
'x': 631014,
|
||||
'u': 428799,
|
||||
'ss': 296430,
|
||||
's+': 212237,
|
||||
's': 157234,
|
||||
's-': 122791,
|
||||
'a+': 103031,
|
||||
'a': 90174,
|
||||
'a-': 73474,
|
||||
'b+': 60655,
|
||||
'b': 52463,
|
||||
'b-': 43877,
|
||||
'c+': 36594,
|
||||
'c': 34014,
|
||||
'c-': 29613,
|
||||
'd+': 31521,
|
||||
'd': 23437,
|
||||
'x+': 912418,
|
||||
'x': 635169,
|
||||
'u': 449225,
|
||||
'ss': 294776,
|
||||
's+': 212162,
|
||||
's': 148476,
|
||||
's-': 121513,
|
||||
'a+': 104008,
|
||||
'a': 79753,
|
||||
'a-': 71817,
|
||||
'b+': 61266,
|
||||
'b': 51073,
|
||||
'b-': 45213,
|
||||
'c+': 40732,
|
||||
'c': 30889,
|
||||
'c-': 28593,
|
||||
'd+': 25075,
|
||||
'd': 20438,
|
||||
};
|
||||
|
||||
List<DateTime> seasonStarts = [
|
||||
@@ -276,9 +238,32 @@ List<DateTime> seasonEnds = [
|
||||
|
||||
/// Stolen directly from TETR.IO, redone for the sake of me
|
||||
|
||||
const List<String> clearNames = ["Zero", "Single", "Double", "Triple", "Quad", "Penta", "Hexa", "Hepta", "Octa", "Ennea", "Deca", "Hendeca", "Dodeca", "Triadeca", "Tessaradeca", "Pentedeca", "Hexadeca", "Heptadeca", "Octadeca", "Enneadeca", "Eicosa", "Kagaris"];
|
||||
const List<String> clearNames = [
|
||||
"Zero",
|
||||
"Single",
|
||||
"Double",
|
||||
"Triple",
|
||||
"Quad",
|
||||
"Penta",
|
||||
"Hexa",
|
||||
"Hepta",
|
||||
"Octa",
|
||||
"Ennea",
|
||||
"Deca",
|
||||
"Hendeca",
|
||||
"Dodeca",
|
||||
"Triadeca",
|
||||
"Tessaradeca",
|
||||
"Pentedeca",
|
||||
"Hexadeca",
|
||||
"Heptadeca",
|
||||
"Octadeca",
|
||||
"Enneadeca",
|
||||
"Eicosa",
|
||||
"Kagaris"
|
||||
];
|
||||
|
||||
enum Lineclears{
|
||||
enum Lineclears {
|
||||
ZERO,
|
||||
SINGLE,
|
||||
DOUBLE,
|
||||
@@ -298,12 +283,7 @@ enum Lineclears{
|
||||
TSPIN_PENTA,
|
||||
}
|
||||
|
||||
enum ComboTables{
|
||||
none,
|
||||
classic,
|
||||
modern,
|
||||
multiplier
|
||||
}
|
||||
enum ComboTables { none, classic, modern, multiplier }
|
||||
|
||||
Map<ComboTables, String> comboTablesNames = {
|
||||
ComboTables.none: "None",
|
||||
@@ -339,7 +319,7 @@ const Map<Lineclears, int> garbage = {
|
||||
};
|
||||
|
||||
const Map<ComboTables, List<int>> combotable = {
|
||||
ComboTables.none: [0],
|
||||
ComboTables.classic: [0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5],
|
||||
ComboTables.modern: [0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4]
|
||||
ComboTables.none: [0],
|
||||
ComboTables.classic: [0, 1, 1, 2, 2, 3, 3, 4, 4, 4, 5],
|
||||
ComboTables.modern: [0, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3, 4]
|
||||
};
|
||||
|
||||
@@ -38,7 +38,7 @@ import 'package:tetra_stats/services/sqlite_db_controller.dart';
|
||||
import 'package:csv/csv.dart';
|
||||
|
||||
const String dbName = "TetraStats.db";
|
||||
const String webVersionDomain = "ts.dan63.by";
|
||||
const String webVersionDomain = "tsbeta.dan63.by";
|
||||
const String tetrioUsersTable = "tetrioUsers";
|
||||
const String tetrioUsersToTrackTable = "tetrioUsersToTrack";
|
||||
const String tetraLeagueMatchesTable = "tetrioAlphaLeagueMathces";
|
||||
@@ -185,7 +185,7 @@ class CacheController {
|
||||
}
|
||||
} on StateError{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (int.parse(objectEntry.key.substring(id.length)) <= DateTime.now().millisecondsSinceEpoch){
|
||||
_cache.remove(objectEntry.key);
|
||||
return null;
|
||||
@@ -203,6 +203,14 @@ class CacheController {
|
||||
}
|
||||
}
|
||||
|
||||
class MunchProgress{
|
||||
List<BetaRecord> avaliable = [];
|
||||
List<MinomuncherRaw> munched = [];
|
||||
MinomuncherRaw? result;
|
||||
|
||||
toString() => "${munched.length}/${avaliable.length}, $result";
|
||||
}
|
||||
|
||||
class TetrioService extends DB {
|
||||
final Map<String, String> _players = {};
|
||||
final _cache = CacheController.init(); // I'm trying to send as less requests, as possible, so i'm caching the results of those requests.
|
||||
@@ -319,7 +327,7 @@ class TetrioService extends DB {
|
||||
DateTime now = DateTime.now();
|
||||
_cache.store(replay, now.millisecondsSinceEpoch + 3600000);
|
||||
return replay;
|
||||
// if not 200 - throw a unique for each code exception
|
||||
// if not 200 - throw a unique for each code exception
|
||||
case 404:
|
||||
throw SzyNotFound();
|
||||
case 403:
|
||||
@@ -397,16 +405,16 @@ class TetrioService extends DB {
|
||||
Future<List<MinomuncherRaw>> minomuncherPostReplay(RawReplay replay, {String? id}) async {
|
||||
List<MinomuncherRaw>? cached = _cache.get(replay.id, List<MinomuncherRaw>);
|
||||
if (cached != null) return cached;
|
||||
|
||||
|
||||
Uri url;
|
||||
if (kIsWeb) {
|
||||
url = Uri.https(webVersionDomain, 'oskware_bridge.php', {"endpoint": "Minomuncher"}); // Not exist for now, TODO
|
||||
url = Uri.https(webVersionDomain, 'oskware_bridge.php', {"endpoint": "Minomuncher"});
|
||||
} else {
|
||||
url = Uri.https('REDACTED', 'api/replay'); // TODO: change it on release to oskware bridge
|
||||
}
|
||||
try {
|
||||
final response = await client.post(
|
||||
url,
|
||||
url,
|
||||
headers: <String, String>{
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
},
|
||||
@@ -445,18 +453,33 @@ class TetrioService extends DB {
|
||||
}
|
||||
}
|
||||
|
||||
Future<MinomuncherRaw> minomuncherMunchByID(String id) async {
|
||||
Stream<MunchProgress> minomuncherMunchByIDStream(String id) async* {
|
||||
MunchProgress progress = MunchProgress();
|
||||
yield progress;
|
||||
MinomuncherRaw? cached = _cache.get(id, MinomuncherRaw);
|
||||
if (cached != null) return cached;
|
||||
TetraLeagueBetaStream stream = await fetchTLStream(id);
|
||||
List<BetaRecord> avaliable = stream.records;
|
||||
avaliable.removeWhere((element) => element.stub);
|
||||
if (avaliable.isEmpty) throw TetrioNoReplays();
|
||||
List<List<MinomuncherRaw>> raws = [for (BetaRecord e in avaliable.take(10)) await minomuncherPostReplay(await szyGetReplay(e.replayID))];
|
||||
List<MinomuncherRaw> ourId = [for (List<MinomuncherRaw> e in raws) e.firstWhere((element) => element.nick == id)];
|
||||
MinomuncherRaw output = ourId.reduce((a, b) => a + b);
|
||||
_cache.store(output, DateTime.now().millisecondsSinceEpoch + 300000, id: id+"minomuncher");
|
||||
return output;
|
||||
if (cached != null){
|
||||
progress.result = cached;
|
||||
yield progress;
|
||||
} else{
|
||||
TetraLeagueBetaStream stream = await fetchTLStream(id);
|
||||
List<BetaRecord> avaliable = stream.records;
|
||||
avaliable.removeWhere((element) => element.stub);
|
||||
if (avaliable.isEmpty) throw TetrioNoReplays();
|
||||
progress.avaliable = avaliable.take(10).toList();
|
||||
yield progress;
|
||||
for (BetaRecord record in progress.avaliable){
|
||||
// MinomuncherRaw? cached = _cache.get(record.replayID, MinomuncherRaw);
|
||||
// if (cached != null){
|
||||
// progress.result = cached;
|
||||
// yield progress;
|
||||
// }
|
||||
List<MinomuncherRaw> raw = await minomuncherPostReplay(await szyGetReplay(record.replayID));
|
||||
progress.munched.add(raw.firstWhere((element) => element.nick == id));
|
||||
yield progress;
|
||||
}
|
||||
progress.result = progress.munched.reduce((a, b) => a + b);
|
||||
yield progress;
|
||||
}
|
||||
}
|
||||
|
||||
/// Retrieves avaliable Tetra League matches from Tetra Channel api. Returns stream object (fake stream).
|
||||
@@ -464,7 +487,7 @@ class TetrioService extends DB {
|
||||
Future<SingleplayerStream> fetchStream(String userID, String stream) async {
|
||||
SingleplayerStream? cached = _cache.get(stream+userID, SingleplayerStream);
|
||||
if (cached != null) return cached;
|
||||
|
||||
|
||||
Uri url;
|
||||
if (kIsWeb) {
|
||||
url = Uri.https(webVersionDomain, 'oskware_bridge.php', {"endpoint": "singleplayerStream", "user": userID.toLowerCase().trim(), "stream": stream});
|
||||
@@ -532,7 +555,7 @@ class TetrioService extends DB {
|
||||
developer.log("fetchTopTR: Probably, player doesn't have top TR", name: "services/tetrio_crud", error: response.statusCode);
|
||||
_cache.store(result, DateTime.now().millisecondsSinceEpoch + 300000);
|
||||
return result;
|
||||
// if not 200 or 404 - throw a unique for each code exception
|
||||
// if not 200 or 404 - throw a unique for each code exception
|
||||
case 403:
|
||||
throw P1nkl0bst3rForbidden();
|
||||
case 429:
|
||||
@@ -583,7 +606,7 @@ class TetrioService extends DB {
|
||||
case 404:
|
||||
developer.log("fetchCutoffsTetrio: Cutoffs are gone", name: "services/tetrio_crud", error: response.statusCode);
|
||||
return null;
|
||||
// if not 200 or 404 - throw a unique for each code exception
|
||||
// if not 200 or 404 - throw a unique for each code exception
|
||||
case 403:
|
||||
throw TetrioForbidden();
|
||||
case 429:
|
||||
@@ -630,7 +653,7 @@ class TetrioService extends DB {
|
||||
case 404:
|
||||
developer.log("fetchCutoffsBeanserver: Cutoffs are gone", name: "services/tetrio_crud", error: response.statusCode);
|
||||
return null;
|
||||
// if not 200 or 404 - throw a unique for each code exception
|
||||
// if not 200 or 404 - throw a unique for each code exception
|
||||
case 403:
|
||||
throw P1nkl0bst3rForbidden();
|
||||
case 429:
|
||||
@@ -685,7 +708,7 @@ class TetrioService extends DB {
|
||||
case 404:
|
||||
developer.log("fetchCutoffsHistory: Cutoffs are gone", name: "services/tetrio_crud", error: response.statusCode);
|
||||
return [];
|
||||
// if not 200 or 404 - throw a unique for each code exception
|
||||
// if not 200 or 404 - throw a unique for each code exception
|
||||
case 403:
|
||||
throw P1nkl0bst3rForbidden();
|
||||
case 429:
|
||||
@@ -730,7 +753,7 @@ class TetrioService extends DB {
|
||||
return result;
|
||||
case 404:
|
||||
throw TetrioPlayerNotExist();
|
||||
// if not 200 or 404 - throw a unique for each code exception
|
||||
// if not 200 or 404 - throw a unique for each code exception
|
||||
case 403:
|
||||
throw TetrioForbidden();
|
||||
case 429:
|
||||
@@ -774,7 +797,7 @@ class TetrioService extends DB {
|
||||
Batch batch = db.batch();
|
||||
for (List<dynamic> entry in csv){ // each entry is one state
|
||||
TetraLeague state = TetraLeague(
|
||||
id: id,
|
||||
id: id,
|
||||
timestamp: DateTime.parse(entry[9]),
|
||||
apm: entry[6] != '' ? entry[6] : null,
|
||||
pps: entry[7] != '' ? entry[7] : null,
|
||||
@@ -973,7 +996,7 @@ class TetrioService extends DB {
|
||||
Future<List<TetrioPlayerFromLeaderboard>> fetchTetrioLeaderboard({String? prisecter, String? lb, String? country}) async {
|
||||
// TetrioPlayersLeaderboard? cached = _cache.get("league", TetrioPlayersLeaderboard);
|
||||
// if (cached != null) return cached;
|
||||
|
||||
|
||||
Uri url;
|
||||
if (kIsWeb) {
|
||||
url = Uri.https(webVersionDomain, 'oskware_bridge.php', {
|
||||
@@ -1094,7 +1117,7 @@ class TetrioService extends DB {
|
||||
Future<News> fetchNews(String userID) async{
|
||||
News? cached = _cache.get("user_$userID", News);
|
||||
if (cached != null) return cached;
|
||||
|
||||
|
||||
Uri url;
|
||||
if (kIsWeb) {
|
||||
url = Uri.https(webVersionDomain, 'oskware_bridge.php', {"endpoint": "tetrioNews", "user": userID.toLowerCase().trim(), "limit": "100"});
|
||||
@@ -1142,7 +1165,7 @@ class TetrioService extends DB {
|
||||
Future<TetraLeagueBetaStream> fetchTLStream(String userID, {String? prisecter}) async {
|
||||
// TetraLeagueBetaStream? cached = _cache.get(userID, TetraLeagueBetaStream);
|
||||
// if (cached != null) return cached;
|
||||
|
||||
|
||||
Uri url;
|
||||
if (kIsWeb) {
|
||||
url = Uri.https(webVersionDomain, 'oskware_bridge.php', {
|
||||
@@ -1215,18 +1238,18 @@ class TetrioService extends DB {
|
||||
await ensureDbIsOpen();
|
||||
final db = getDatabaseOrThrow();
|
||||
await db.execute("""
|
||||
DELETE FROM $tetraLeagueMatchesTable
|
||||
WHERE
|
||||
DELETE FROM $tetraLeagueMatchesTable
|
||||
WHERE
|
||||
$idCol IN (
|
||||
SELECT
|
||||
$idCol
|
||||
SELECT
|
||||
$idCol
|
||||
FROM (
|
||||
SELECT
|
||||
SELECT
|
||||
$idCol,
|
||||
ROW_NUMBER() OVER (
|
||||
PARTITION BY $replayID
|
||||
ORDER BY $replayID) AS row_num
|
||||
FROM $tetraLeagueMatchesTable
|
||||
FROM $tetraLeagueMatchesTable
|
||||
) t
|
||||
WHERE row_num > 1
|
||||
);
|
||||
@@ -1534,7 +1557,7 @@ class TetrioService extends DB {
|
||||
throw http.ClientException(e.message, e.uri);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// finally going to obtain
|
||||
Uri url;
|
||||
if (kIsWeb) {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+104
-79
@@ -7,6 +7,7 @@ import 'package:flutter_markdown/flutter_markdown.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:tetra_stats/services/crud_exceptions.dart';
|
||||
import 'package:tetra_stats/services/tetrio_crud.dart' show MunchProgress;
|
||||
import 'package:tetra_stats/widgets/apl_ranges.dart';
|
||||
import 'package:tetra_stats/widgets/apm_pps_ranges.dart';
|
||||
import 'package:tetra_stats/widgets/clear_types_thingy.dart';
|
||||
@@ -15,8 +16,7 @@ import 'package:tetra_stats/widgets/etr_thingy.dart';
|
||||
import 'package:tetra_stats/widgets/kills_deaths_thingy.dart';
|
||||
import 'package:tetra_stats/widgets/pps_distribution_thingy.dart';
|
||||
import 'package:tetra_stats/widgets/pps_surge_radars_thingy.dart';
|
||||
import 'package:tetra_stats/widgets/sankey_graph.dart';
|
||||
import 'package:syncfusion_flutter_charts/charts.dart';
|
||||
|
||||
import 'package:syncfusion_flutter_gauges/gauges.dart';
|
||||
import 'package:tetra_stats/data_objects/achievement.dart';
|
||||
import 'package:tetra_stats/data_objects/cutoff_tetrio.dart';
|
||||
@@ -138,6 +138,7 @@ Map<Cards, List<ButtonSegment<CardMod>>> modeButtons = {
|
||||
)
|
||||
]
|
||||
};
|
||||
double freyhoeStreamTextOpacity = 1.0;
|
||||
|
||||
class ZenithCard extends StatelessWidget {
|
||||
final RecordSingle? record;
|
||||
@@ -290,7 +291,7 @@ class RecordCard extends StatelessWidget {
|
||||
final double width;
|
||||
|
||||
const RecordCard(this.record, this.achievements, this.betterThanRankAverage, this.closestAverage, this.betterThanClosestAverage, this.rank, {this.width = double.infinity});
|
||||
|
||||
|
||||
Widget result(){
|
||||
TextStyle tableTextStyle = TextStyle(fontSize: width > 768.0 ? 21 : 18);
|
||||
return Card(
|
||||
@@ -514,7 +515,7 @@ class RecordSummary extends StatelessWidget{
|
||||
final double width;
|
||||
|
||||
const RecordSummary({super.key, required this.record, this.betterThanRankAverage, this.closestAverage, this.old = false, this.betterThanClosestAverage, this.rank, this.hideRank = false, this.width = double.infinity});
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Row(
|
||||
@@ -669,7 +670,7 @@ class AchievementSummary extends StatelessWidget{
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class LeagueCard extends StatelessWidget{
|
||||
@@ -994,73 +995,98 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
||||
);
|
||||
}
|
||||
|
||||
Widget getFreyhoeAnalysis(String id, double width){
|
||||
return FutureBuilder<MinomuncherRaw>(
|
||||
future: teto.minomuncherMunchByID(id),
|
||||
void _changefreyhoeStreamTextOpacity() {
|
||||
setState(() => freyhoeStreamTextOpacity = freyhoeStreamTextOpacity == 0 ? 1.0 : 0.0);
|
||||
}
|
||||
|
||||
Widget freyhoeStreamNotOnTwitch(String id, double width){
|
||||
return StreamBuilder<MunchProgress>(
|
||||
stream: teto.minomuncherMunchByIDStream(id),
|
||||
builder: (context, snapshot) {
|
||||
switch (snapshot.connectionState){
|
||||
case ConnectionState.none:
|
||||
case ConnectionState.waiting:
|
||||
case ConnectionState.active:
|
||||
return const Center(child: CircularProgressIndicator());
|
||||
case ConnectionState.done:
|
||||
if (snapshot.hasData){
|
||||
MinomuncherData data = snapshot.data!.data;
|
||||
const EdgeInsets paddings = const EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 8.0);
|
||||
return Column(
|
||||
children: [
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text("Analysis", style: widget.constraints.maxWidth > 768.0 ? Theme.of(context).textTheme.titleLarge : Theme.of(context).textTheme.titleMedium),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4.0),
|
||||
child: Text("via MinoMuncher by Freyhoe", textAlign: TextAlign.center, style: TextStyle(fontSize: widget.constraints.maxWidth > 768.0 ? null : 12.0, color: Colors.grey)),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
ApmPpsThingy([ApmPps(data.nick, data.openerAPM, data.APM, data.midgameAPM, data.openerPPS, data.PPS, data.midgamePPS)]),
|
||||
AplThingy([Apl(data.nick, data.upstackAPL, data.downstackAPL, data.cheeseAPL)], width > 768.0),
|
||||
EffThingy([Eff(data.nick, data.iEfficiency, data.tEfficiency, data.allspinEfficiency)], width > 768.0),
|
||||
ClearTypesThingy([data.clearTypes], width),
|
||||
WellColumnsThingy([data.wellColumns], [data.nick], width),
|
||||
PPSSurgeThingy([data], width),
|
||||
SankeyThingy([data], width),
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: paddings,
|
||||
child: SizedBox(
|
||||
height: 256.0,
|
||||
width: 256.0,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(1000),
|
||||
child: Container(
|
||||
switch (snapshot.connectionState){
|
||||
case ConnectionState.none:
|
||||
case ConnectionState.waiting:
|
||||
case ConnectionState.active:
|
||||
return Center(child: Column(
|
||||
children: [
|
||||
CircularProgressIndicator(),
|
||||
AnimatedOpacity(
|
||||
opacity: freyhoeStreamTextOpacity,
|
||||
duration: Duration(seconds:1),
|
||||
onEnd: _changefreyhoeStreamTextOpacity,
|
||||
child: Text(
|
||||
snapshot.data!.avaliable.isEmpty ? "Fetching Records..." : "Munching...",
|
||||
style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)
|
||||
),
|
||||
),
|
||||
if (snapshot.data!.avaliable.isNotEmpty) RichText(
|
||||
text: TextSpan(
|
||||
style: TextStyle(fontFamily: "Eurostile Round", color: Colors.white),
|
||||
children: [
|
||||
TextSpan(text: "${snapshot.data!.munched.length} ", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)),
|
||||
TextSpan(text: "out of"),
|
||||
TextSpan(text: " ${snapshot.data!.avaliable.length}\n", style: TextStyle(fontFamily: "Eurostile Round Extended", fontSize: 28)),
|
||||
TextSpan(text: "replays")
|
||||
]
|
||||
)
|
||||
),
|
||||
]
|
||||
));
|
||||
case ConnectionState.done:
|
||||
if (snapshot.hasData){
|
||||
MinomuncherData data = snapshot.data!.result!.data;
|
||||
const EdgeInsets paddings = const EdgeInsets.fromLTRB(16.0, 0.0, 16.0, 8.0);
|
||||
return Column(
|
||||
children: [
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(bottom: 4.0),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
Text("Analysis", style: widget.constraints.maxWidth > 768.0 ? Theme.of(context).textTheme.titleLarge : Theme.of(context).textTheme.titleMedium),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4.0),
|
||||
child: Text("via MinoMuncher by Freyhoe", textAlign: TextAlign.center, style: TextStyle(fontSize: widget.constraints.maxWidth > 768.0 ? null : 12.0, color: Colors.grey)),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
ApmPpsThingy([ApmPps(data.nick, data.openerAPM, data.APM, data.midgameAPM, data.openerPPS, data.PPS, data.midgamePPS)]),
|
||||
AplThingy([Apl(data.nick, data.upstackAPL, data.downstackAPL, data.cheeseAPL)], width > 768.0),
|
||||
EffThingy([Eff(data.nick, data.iEfficiency, data.tEfficiency, data.allspinEfficiency)], width > 768.0),
|
||||
ClearTypesThingy([data.clearTypes], width),
|
||||
WellColumnsThingy([data.wellColumns], [data.nick], width),
|
||||
PPSSurgeThingy([data], width),
|
||||
SankeyThingy([data], width),
|
||||
Card(
|
||||
child: Padding(
|
||||
padding: paddings,
|
||||
child: ClipRRect(
|
||||
borderRadius: BorderRadius.circular(1000),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(gradient: RadialGradient(colors: [Colors.black12.withAlpha(100), Colors.black], radius: 0.6)),
|
||||
child: SfRadialGauge(
|
||||
axes: [
|
||||
RadialAxis(
|
||||
startAngle: 190,
|
||||
endAngle: 350,
|
||||
startAngle: 220,
|
||||
endAngle: 320,
|
||||
showLabels: false,
|
||||
showTicks: true,
|
||||
canScaleToFit: true,
|
||||
radiusFactor: 1,
|
||||
centerY: 0.5,
|
||||
minimum: 0,
|
||||
maximum: 1,
|
||||
ranges: [
|
||||
GaugeRange(startValue: 0, endValue: 0.2, color: Colors.red),
|
||||
GaugeRange(startValue: 0.2, endValue: 0.4, color: Colors.yellow),
|
||||
GaugeRange(startValue: 0.4, endValue: 0.6, color: Colors.green),
|
||||
GaugeRange(startValue: 0.6, endValue: 0.8, color: Colors.blue),
|
||||
GaugeRange(startValue: 0.8, endValue: 1, color: Colors.purple),
|
||||
GaugeRange(startValue: 0, endValue: 0.2, color: Colors.blueGrey),
|
||||
GaugeRange(startValue: 0.2, endValue: 0.4, color: Colors.greenAccent),
|
||||
GaugeRange(startValue: 0.4, endValue: 0.6, color: Colors.yellowAccent),
|
||||
GaugeRange(startValue: 0.6, endValue: 0.8, color: Colors.orangeAccent),
|
||||
GaugeRange(startValue: 0.8, endValue: 1, color: Colors.redAccent),
|
||||
],
|
||||
pointers: [
|
||||
NeedlePointer(
|
||||
@@ -1092,21 +1118,20 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
)
|
||||
),
|
||||
KillsDeathsThingy([KD(data.nick, data.killStats, data.deathStats)], width),
|
||||
PPSDistributionThingy([data.ppsSegments], [data.nick], width)
|
||||
],
|
||||
);
|
||||
}
|
||||
if (snapshot.hasError){
|
||||
if (snapshot.error is TetrioNoReplays) return SizedBox(height: 720.0, child: ErrorThingy(data: FetchResults(false, null, [], null, null, null, null, null, false, snapshot.error as Exception)));
|
||||
return SizedBox(height: 720.0, child: FutureError(snapshot));
|
||||
}
|
||||
)
|
||||
),
|
||||
KillsDeathsThingy([KD(data.nick, data.killStats, data.deathStats)], width),
|
||||
PPSDistributionThingy([data.ppsSegments], [data.nick], width)
|
||||
],
|
||||
);
|
||||
}
|
||||
return const Text("what?");
|
||||
},
|
||||
if (snapshot.hasError){
|
||||
if (snapshot.error is TetrioNoReplays) return SizedBox(height: 720.0, child: ErrorThingy(data: FetchResults(false, null, [], null, null, null, null, null, false, snapshot.error as Exception)));
|
||||
return SizedBox(height: 720.0, child: FutureError(snapshot));
|
||||
}
|
||||
}
|
||||
return const Text("what?");
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1263,7 +1288,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
||||
)
|
||||
],
|
||||
),
|
||||
)
|
||||
)
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -1309,7 +1334,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
||||
Cards.overview => getOverviewCard(snapshot.data!.summaries!, (snapshot.data!.averages != null && snapshot.data!.summaries!.league.rank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.rank] : (snapshot.data!.averages != null && snapshot.data!.summaries!.league.percentileRank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.percentileRank] : null, width),
|
||||
Cards.tetraLeague => switch (cardMod){
|
||||
CardMod.info => getTetraLeagueCard(snapshot.data!.summaries!.league, snapshot.data!.cutoffs, (snapshot.data!.averages != null && snapshot.data!.summaries!.league.rank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.rank] : (snapshot.data!.averages != null && snapshot.data!.summaries!.league.percentileRank != "z") ? snapshot.data!.averages!.data[snapshot.data!.summaries!.league.percentileRank] : null, snapshot.data!.states, snapshot.data!.playerPos, width, tlAchievements),
|
||||
CardMod.exRecords => getFreyhoeAnalysis(snapshot.data!.player!.username, width),
|
||||
CardMod.exRecords => freyhoeStreamNotOnTwitch(snapshot.data!.player!.username, width),
|
||||
CardMod.ex => getPreviousSeasonsList(snapshot.data!.summaries!.pastLeague, width),
|
||||
CardMod.records => getRecentTLrecords(widget.constraints, snapshot.data!.player!.userId),
|
||||
_ => const Center(child: Text("huh?"))
|
||||
@@ -1402,7 +1427,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Spacer(),
|
||||
const Spacer(),
|
||||
Text(t.bio, style: const TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||
const Spacer()
|
||||
],
|
||||
@@ -1493,7 +1518,7 @@ class _DestinationHomeState extends State<DestinationHome> with SingleTickerProv
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
const Spacer(),
|
||||
const Spacer(),
|
||||
Text(t.bio, style: const TextStyle(fontFamily: "Eurostile Round Extended")),
|
||||
const Spacer()
|
||||
],
|
||||
|
||||
+132
-134
@@ -1,134 +1,132 @@
|
||||
name: tetra_stats
|
||||
description: Track your and other player stats in TETR.IO
|
||||
publish_to: 'none'
|
||||
|
||||
version: 2.0.8+49
|
||||
|
||||
environment:
|
||||
sdk: '>=3.0.0'
|
||||
|
||||
# Dependencies specify other packages that your package needs in order to work.
|
||||
# To automatically upgrade your package dependencies to the latest versions
|
||||
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
||||
# dependencies can be manually updated by changing the version numbers below to
|
||||
# the latest version available on pub.dev. To see which dependencies have newer
|
||||
# versions available, run `flutter pub outdated`.
|
||||
dependencies:
|
||||
http:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
transparent_image: ^2.0.1
|
||||
cupertino_icons: ^1.0.2
|
||||
vector_math: any
|
||||
sqflite: ^2.2.8+2
|
||||
sqflite_common_ffi: any
|
||||
sqlite3_flutter_libs: ^0.5.15
|
||||
sqflite_common_ffi_web: '>=0.1.0-dev.1'
|
||||
path_provider: ^2.0.15
|
||||
path: ^1.8.2
|
||||
fl_chart: ^0.66.0
|
||||
package_info_plus: ^5.0.1
|
||||
shared_preferences: ^2.1.1
|
||||
intl: ^0.19.0
|
||||
syncfusion_flutter_gauges: ^24.1.41
|
||||
file_selector: ^1.0.1
|
||||
file_picker: ^6.1.1
|
||||
slang: ^3.20.0
|
||||
slang_flutter: ^3.20.0
|
||||
csv: ^5.0.2
|
||||
url_launcher: ^6.1.12
|
||||
flutter_svg: any
|
||||
window_manager: ^0.3.7
|
||||
flutter_markdown: ^0.6.18
|
||||
flutter_colorpicker: ^1.0.3
|
||||
flutter_layout_grid: ^2.0.0
|
||||
go_router: ^13.0.0
|
||||
syncfusion_flutter_charts: ^24.2.9
|
||||
flutter_to_debian: ^2.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^3.0.1
|
||||
flutter_launcher_icons: "^0.13.1"
|
||||
test: ^1.24.9
|
||||
|
||||
|
||||
flutter_launcher_icons:
|
||||
android: "launcher_icon"
|
||||
ios: true
|
||||
image_path: "res/icons/app.png"
|
||||
min_sdk_android: 19 # android min sdk min:16, default 21
|
||||
web:
|
||||
generate: true
|
||||
image_path: "res/icons/app.png"
|
||||
background_color: "#000000"
|
||||
theme_color: "#000000"
|
||||
windows:
|
||||
generate: true
|
||||
image_path: "res/icons/app.png"
|
||||
icon_size: 256 # min:48, max:256, default: 48
|
||||
macos:
|
||||
generate: true
|
||||
image_path: "res/icons/app.png"
|
||||
|
||||
targets:
|
||||
$default:
|
||||
builders:
|
||||
slang_build_runner:
|
||||
options:
|
||||
input_directory: res/i18n
|
||||
output_directory: lib/i18n
|
||||
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
assets:
|
||||
- res/avatars/
|
||||
- res/icons/
|
||||
- res/tetrio_tl_alpha_ranks/
|
||||
- res/images/
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
|
||||
# For details regarding adding assets from package dependencies, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
fonts:
|
||||
- family: Eurostile Round
|
||||
fonts:
|
||||
- asset: res/fonts/EurostileRound-Black.ttf
|
||||
- asset: res/fonts/EurostileRound-BlackItalic.ttf
|
||||
- asset: res/fonts/EurostileRound-Bold.ttf
|
||||
- asset: res/fonts/EurostileRound-BoldItalic.ttf
|
||||
- asset: res/fonts/EurostileRound-Heavy.ttf
|
||||
weight: 900
|
||||
- asset: res/fonts/EurostileRound-HeavyItalic.ttf
|
||||
weight: 900
|
||||
style: italic
|
||||
- asset: res/fonts/EurostileRound-Italic.ttf
|
||||
style: italic
|
||||
- asset: res/fonts/EurostileRound-Medium.ttf
|
||||
- asset: res/fonts/EurostileRound-MediumItalic.ttf
|
||||
weight: 500
|
||||
style: italic
|
||||
- asset: res/fonts/EurostileRound-Regular.ttf
|
||||
- family: Eurostile Round Condensed
|
||||
fonts:
|
||||
- asset: res/fonts/EurostileRoundCondensed-Heavy.ttf
|
||||
- asset: res/fonts/EurostileRoundCondensed-HeavyItalic.ttf
|
||||
- asset: res/fonts/EurostileRoundCondensed-Italic.ttf
|
||||
- asset: res/fonts/EurostileRoundCondensed-Regular.ttf
|
||||
- family: Eurostile Round Extended
|
||||
fonts:
|
||||
- asset: res/fonts/EurostileRoundExtended-Black.ttf
|
||||
- asset: res/fonts/EurostileRoundExtended-BlackItalic.ttf
|
||||
weight: 900
|
||||
style: italic
|
||||
- asset: res/fonts/EurostileRoundExtended-Italic.ttf
|
||||
style: italic
|
||||
- asset: res/fonts/EurostileRoundExtended-Medium.ttf
|
||||
weight: 500
|
||||
- asset: res/fonts/EurostileRoundExtended-Regular.ttf
|
||||
name: tetra_stats
|
||||
description: Track your and other player stats in TETR.IO
|
||||
publish_to: "none"
|
||||
|
||||
version: 2.1.0+50
|
||||
|
||||
environment:
|
||||
sdk: ">=3.0.0"
|
||||
|
||||
# Dependencies specify other packages that your package needs in order to work.
|
||||
# To automatically upgrade your package dependencies to the latest versions
|
||||
# consider running `flutter pub upgrade --major-versions`. Alternatively,
|
||||
# dependencies can be manually updated by changing the version numbers below to
|
||||
# the latest version available on pub.dev. To see which dependencies have newer
|
||||
# versions available, run `flutter pub outdated`.
|
||||
dependencies:
|
||||
http:
|
||||
flutter:
|
||||
sdk: flutter
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
transparent_image: ^2.0.1
|
||||
cupertino_icons: ^1.0.2
|
||||
vector_math: any
|
||||
sqflite: ^2.2.8+2
|
||||
sqflite_common_ffi: any
|
||||
sqlite3_flutter_libs: ^0.5.15
|
||||
sqflite_common_ffi_web: ">=0.1.0-dev.1"
|
||||
path_provider: ^2.0.15
|
||||
path: ^1.8.2
|
||||
fl_chart: ^0.66.0
|
||||
package_info_plus: ^5.0.1
|
||||
shared_preferences: ^2.1.1
|
||||
intl: ^0.19.0
|
||||
syncfusion_flutter_gauges: ^24.1.41
|
||||
file_selector: ^1.0.1
|
||||
file_picker: ^6.1.1
|
||||
slang: ^3.20.0
|
||||
slang_flutter: ^3.20.0
|
||||
csv: ^5.0.2
|
||||
url_launcher: ^6.1.12
|
||||
flutter_svg: any
|
||||
window_manager: ^0.3.7
|
||||
flutter_markdown: ^0.6.18
|
||||
flutter_colorpicker: ^1.0.3
|
||||
flutter_layout_grid: ^2.0.0
|
||||
go_router: ^13.0.0
|
||||
syncfusion_flutter_charts: ^24.2.9
|
||||
flutter_to_debian: ^2.0.2
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
sdk: flutter
|
||||
flutter_lints: ^3.0.1
|
||||
flutter_launcher_icons: "^0.13.1"
|
||||
test: ^1.24.9
|
||||
|
||||
flutter_launcher_icons:
|
||||
android: "launcher_icon"
|
||||
ios: true
|
||||
image_path: "res/icons/app.png"
|
||||
min_sdk_android: 19 # android min sdk min:16, default 21
|
||||
web:
|
||||
generate: true
|
||||
image_path: "res/icons/app.png"
|
||||
background_color: "#000000"
|
||||
theme_color: "#000000"
|
||||
windows:
|
||||
generate: true
|
||||
image_path: "res/icons/app.png"
|
||||
icon_size: 256 # min:48, max:256, default: 48
|
||||
macos:
|
||||
generate: true
|
||||
image_path: "res/icons/app.png"
|
||||
|
||||
targets:
|
||||
$default:
|
||||
builders:
|
||||
slang_build_runner:
|
||||
options:
|
||||
input_directory: res/i18n
|
||||
output_directory: lib/i18n
|
||||
|
||||
flutter:
|
||||
uses-material-design: true
|
||||
assets:
|
||||
- res/avatars/
|
||||
- res/icons/
|
||||
- res/tetrio_tl_alpha_ranks/
|
||||
- res/images/
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
|
||||
# For details regarding adding assets from package dependencies, see
|
||||
# https://flutter.dev/assets-and-images/#from-packages
|
||||
fonts:
|
||||
- family: Eurostile Round
|
||||
fonts:
|
||||
- asset: res/fonts/EurostileRound-Black.ttf
|
||||
- asset: res/fonts/EurostileRound-BlackItalic.ttf
|
||||
- asset: res/fonts/EurostileRound-Bold.ttf
|
||||
- asset: res/fonts/EurostileRound-BoldItalic.ttf
|
||||
- asset: res/fonts/EurostileRound-Heavy.ttf
|
||||
weight: 900
|
||||
- asset: res/fonts/EurostileRound-HeavyItalic.ttf
|
||||
weight: 900
|
||||
style: italic
|
||||
- asset: res/fonts/EurostileRound-Italic.ttf
|
||||
style: italic
|
||||
- asset: res/fonts/EurostileRound-Medium.ttf
|
||||
- asset: res/fonts/EurostileRound-MediumItalic.ttf
|
||||
weight: 500
|
||||
style: italic
|
||||
- asset: res/fonts/EurostileRound-Regular.ttf
|
||||
- family: Eurostile Round Condensed
|
||||
fonts:
|
||||
- asset: res/fonts/EurostileRoundCondensed-Heavy.ttf
|
||||
- asset: res/fonts/EurostileRoundCondensed-HeavyItalic.ttf
|
||||
- asset: res/fonts/EurostileRoundCondensed-Italic.ttf
|
||||
- asset: res/fonts/EurostileRoundCondensed-Regular.ttf
|
||||
- family: Eurostile Round Extended
|
||||
fonts:
|
||||
- asset: res/fonts/EurostileRoundExtended-Black.ttf
|
||||
- asset: res/fonts/EurostileRoundExtended-BlackItalic.ttf
|
||||
weight: 900
|
||||
style: italic
|
||||
- asset: res/fonts/EurostileRoundExtended-Italic.ttf
|
||||
style: italic
|
||||
- asset: res/fonts/EurostileRoundExtended-Medium.ttf
|
||||
weight: 500
|
||||
- asset: res/fonts/EurostileRoundExtended-Regular.ttf
|
||||
|
||||
Reference in New Issue
Block a user