From 57ecb393d28f29b10d59f149ce53d4ca25df8fc8 Mon Sep 17 00:00:00 2001 From: mytja Date: Sun, 8 Sep 2024 01:46:33 +0200 Subject: [PATCH] various bug fixes Red symbols blend with coloured background - resolves https://github.com/mytja/Tarok/issues/72 Highlight leading/winning player in a round - resolves https://github.com/mytja/Tarok/issues/77 --- stockskis/lib/src/stockskis_base.dart | 18 +- tarok/README.md | 2 +- tarok/lib/constants.dart | 10 +- tarok/lib/game/game.dart | 51 +++-- tarok/lib/game/game_controller.dart | 206 ++++++++++++++---- tarok/lib/internationalization/languages.dart | 9 + tarok/lib/main.dart | 1 + tarok/lib/settings.dart | 14 ++ 8 files changed, 241 insertions(+), 70 deletions(-) diff --git a/stockskis/lib/src/stockskis_base.dart b/stockskis/lib/src/stockskis_base.dart index 69d1131..5c57934 100644 --- a/stockskis/lib/src/stockskis_base.dart +++ b/stockskis/lib/src/stockskis_base.dart @@ -335,7 +335,7 @@ class StockSkis { for (int i = 0; i < stihi.length; i++) { if (stihi[i].isEmpty) continue; Card prvaKarta = stihi[i].first; - StihAnalysis? s = analyzeStih(stihi[i]); + StihAnalysis? s = analyzeStih(stihi[i], gamemode); if (s != null && !allPlaying.contains(s.cardPicks.user) && stihi[i].length >= users.length) { @@ -683,7 +683,7 @@ class StockSkis { } } else { String cardType = stih.first.card.asset.split("/")[1]; - StihAnalysis analysis = analyzeStih(stih)!; + StihAnalysis analysis = analyzeStih(stih, gamemode)!; bool hasColor = false; bool hasTarocks = false; for (int n = 0; n < user.cards.length; n++) { @@ -953,7 +953,7 @@ class StockSkis { // ali bot šenka punte pravi osebi? List currentStih = [...stih, card]; - StihAnalysis newAnalysis = analyzeStih(currentStih)!; + StihAnalysis newAnalysis = analyzeStih(currentStih, gamemode)!; debugPrint( "Analysis ${newAnalysis.cardPicks.user} ${newAnalysis.cardPicks.card.asset} for player $userId, whereas stih consists of ${currentStih.map((e) => e.card.asset).join(" ")}", ); @@ -1053,7 +1053,7 @@ class StockSkis { } */ - StihAnalysis? analyzeStih(List stih) { + static StihAnalysis? analyzeStih(List stih, int gamemode) { if (stih.isEmpty) return null; Card first = stih.first; @@ -2071,7 +2071,7 @@ class StockSkis { String stihPickedUpBy(List stih) { if (stih.isEmpty) throw Exception("stih's length is 0"); - StihAnalysis analysis = analyzeStih(stih)!; + StihAnalysis analysis = analyzeStih(stih, gamemode)!; return analysis.cardPicks.user; } @@ -2806,7 +2806,7 @@ class StockSkis { // pagata ni not v štihu if (!pagatInside) return 0; - StihAnalysis analysis = analyzeStih(stih)!; + StihAnalysis analysis = analyzeStih(stih, gamemode)!; // pagat ni pobral if (analysis.cardPicks.card.asset != "/taroki/pagat") { @@ -2917,7 +2917,7 @@ class StockSkis { for (int i = 0; i < stihi.length; i++) { List stih = stihi[i]; if (stih.isEmpty) continue; - StihAnalysis analysis = analyzeStih(stih)!; + StihAnalysis analysis = analyzeStih(stih, gamemode)!; if (analysis.cardPicks.card.asset == selectedKing && analysis.cardPicks.user == actuallyPlayingUser.id) { // zaruf, prištejemo talon @@ -2943,7 +2943,7 @@ class StockSkis { //debugPrint(i); //debugPrint(stih.map((e) => e.card.asset)); //debugPrint(stih.length); - StihAnalysis analysis = analyzeStih(stih)!; + StihAnalysis analysis = analyzeStih(stih, gamemode)!; stihiMessage.add( MessagesStih( @@ -3648,7 +3648,7 @@ class StockSkis { List notPlayingPickedUpCards = [...talon]; for (int i = 0; i < stihi.length; i++) { if (stihi[i].isEmpty) continue; - StihAnalysis by = analyzeStih(stihi[i])!; + StihAnalysis by = analyzeStih(stihi[i], gamemode)!; for (int n = 0; n < stihi[i].length; n++) { if (playing.contains(by.cardPicks.user)) { playingPickedUpCards.add(stihi[i][n]); diff --git a/tarok/README.md b/tarok/README.md index 7ec0a95..4274350 100644 --- a/tarok/README.md +++ b/tarok/README.md @@ -36,4 +36,4 @@ I made use of [Twemoji](https://github.com/twitter/twemoji), which is licensed u These cards are licensed under [CC0](https://creativecommons.org/publicdomain/zero/1.0/legalcode). ### Other pictures -- F-Droid logo. (c) Andrew Nayenko. CC-BY-SA 3.0, available [here](https://gitlab.com/fdroid/artwork/-/blob/master/fdroid-logo-2015/fdroid-logo.svg). \ No newline at end of file +- F-Droid logo. (c) Andrew Nayenko. CC-BY-SA 3.0, available [here](https://gitlab.com/fdroid/artwork/-/blob/master/fdroid-logo-2015/fdroid-logo.svg). diff --git a/tarok/lib/constants.dart b/tarok/lib/constants.dart index a7118dd..b049f23 100644 --- a/tarok/lib/constants.dart +++ b/tarok/lib/constants.dart @@ -52,6 +52,7 @@ bool RED_FILTER = true; bool COUNTERCLOCKWISE_GAME = false; bool POINTS_TOOLTIP = false; bool SHOW_EVALUATION = true; +bool SHOW_MOST_POWERFUL_CARD = false; String THEME = ""; Locale LOCALE = Get.deviceLocale ?? const Locale("sl", "SI"); @@ -83,12 +84,17 @@ void parseBackendUrls() { } class CardWidget { - const CardWidget( - {required this.position, required this.widget, required this.angle}); + const CardWidget({ + required this.position, + required this.widget, + required this.angle, + required this.asset, + }); final int position; final Widget widget; final double angle; + final String asset; } const GAME_DESC = [ diff --git a/tarok/lib/game/game.dart b/tarok/lib/game/game.dart index eeb6c94..c50e179 100644 --- a/tarok/lib/game/game.dart +++ b/tarok/lib/game/game.dart @@ -81,6 +81,7 @@ class Game extends StatelessWidget { // REZULTATI // KLEPET // CHAT + // LEADERBOARD Container( alignment: Alignment.topRight, child: Card( @@ -700,6 +701,7 @@ class Game extends StatelessWidget { ), // ŠTIHI + // CARDS if (controller.playing == 3 && !(controller.bots && SLEPI_TAROK)) ...controller.stihi3( @@ -1073,26 +1075,35 @@ class Game extends StatelessWidget { ), DataColumn( label: Expanded( - child: Text( - "points_prediction".trParams( - { - "points": (stockskis - .GAMES[controller - .currentPredictions - .value! - .gamemode + - 1] - .worth * - pow( - 2, - controller - .currentPredictions - .value! - .igraKontra)) - .toString(), - }, - ), - ), + child: stockskis + .GAMES[controller + .currentPredictions + .value! + .gamemode + + 1] + .worth != + 0 + ? Text( + "points_prediction".trParams( + { + "points": (stockskis + .GAMES[controller + .currentPredictions + .value! + .gamemode + + 1] + .worth * + pow( + 2, + controller + .currentPredictions + .value! + .igraKontra)) + .toString(), + }, + ), + ) + : const Text("-"), ), ), ], diff --git a/tarok/lib/game/game_controller.dart b/tarok/lib/game/game_controller.dart index d5e83d2..d3a0213 100644 --- a/tarok/lib/game/game_controller.dart +++ b/tarok/lib/game/game_controller.dart @@ -37,6 +37,7 @@ import 'package:tarok/stockskis_compatibility/interfaces/predictions.dart'; import 'package:tarok/stockskis_compatibility/interfaces/results.dart'; import 'package:tarok/stockskis_compatibility/interfaces/start_predictions.dart'; import 'package:tarok/timer.dart'; +import 'package:twemoji_v2/twemoji_v2.dart'; import 'package:web_socket_client/web_socket_client.dart'; class GameController extends GetxController { @@ -298,6 +299,18 @@ class GameController extends GetxController { cards.refresh(); } + int getGamemode() { + if (stockskisContext != null) { + return stockskisContext!.gamemode; + } + int gamemode = -1; + for (int i = 0; i < users.length; i++) { + stockskis.SimpleUser user = users[i]; + gamemode = max(gamemode, user.licitiral); + } + return gamemode; + } + void validCards() { if (stash.value) { for (int i = 0; i < cards.length; i++) { @@ -311,11 +324,7 @@ class GameController extends GetxController { "Poklicana funkcija validCards, firstCard=${firstCard.value?.asset}, cardStih=$cardStih", ); - int gamemode = -1; - for (int i = 0; i < users.length; i++) { - stockskis.SimpleUser user = users[i]; - gamemode = max(gamemode, user.licitiral); - } + int gamemode = getGamemode(); int taroki = 0; bool imaBarvo = false; bool imaVecje = false; @@ -443,6 +452,7 @@ class GameController extends GetxController { image: AssetImage("assets/tarok${card.card.asset}.webp"), ), angle: (Random().nextDouble() - 0.5) / ANGLE, + asset: card.card.asset, )); } } @@ -887,6 +897,7 @@ class GameController extends GetxController { position: 100, widget: Image(image: AssetImage("assets/tarok$card.webp")), angle: (Random().nextDouble() - 0.5) / ANGLE, + asset: card, )); return false; } @@ -901,6 +912,7 @@ class GameController extends GetxController { image: AssetImage("assets/tarok$card.webp"), ), angle: (Random().nextDouble() - 0.5) / ANGLE, + asset: card, )); await Future.delayed(const Duration(milliseconds: 20), () { stihBoolValues[position] = true; @@ -2021,8 +2033,10 @@ class GameController extends GetxController { Future bCleanStih() async { if (zaruf.value) { List zadnjiStih = stockskisContext!.stihi.last; - stockskis.StihAnalysis? analysis = - stockskisContext!.analyzeStih(zadnjiStih); + stockskis.StihAnalysis? analysis = stockskis.StockSkis.analyzeStih( + zadnjiStih, + getGamemode(), + ); if (analysis == null) throw Exception("Štih is empty"); debugPrint( "Zaruf analiza: ${analysis.cardPicks.card.asset} $selectedKing ${zadnjiStih.map((e) => e.card.asset)}", @@ -2067,7 +2081,10 @@ class GameController extends GetxController { break; } } - final analysis = stockskisContext!.analyzeStih(zadnjiStih); + final analysis = stockskis.StockSkis.analyzeStih( + zadnjiStih, + getGamemode(), + ); debugPrint( "Cleaning. Picked up by $pickedUpBy. ${analysis!.cardPicks.card.asset}/${analysis.cardPicks.user}", ); @@ -2367,9 +2384,18 @@ class GameController extends GetxController { double fullWidth, ) { BorderRadius radius = BorderRadius.circular(10 * (fullWidth / 1000)); + BorderRadius radiusInner = BorderRadius.circular(10 * (fullWidth / 2000)); double cardHeight = m * cardK; double cardWidth = cardHeight * 0.57; + List cards = cardStih + .map((e) => stockskis.Card(card: stockskis.CARDS_MAP[e]!, user: "")) + .toList(); + final analysis = stockskis.StockSkis.analyzeStih( + cards, + getGamemode(), + ); + List widgets = []; for (int i = 0; i < stih.length; i++) { CardWidget e = stih[i]; @@ -2387,12 +2413,26 @@ class GameController extends GetxController { child: AnimatedRotation( duration: const Duration(milliseconds: ANIMATION_TIME), turns: stihBoolValues[0] != true ? 0.35 : 0.35 + e.angle, - child: ClipRRect( - borderRadius: radius, + child: Container( + decoration: BoxDecoration( + border: analysis != null && + analysis.cardPicks.card.asset == e.asset + ? Border.all( + width: 10.0, + color: Colors.red, + ) + : null, + borderRadius: radius, + ), + height: cardHeight, + width: cardWidth, child: Stack( children: [ Container( - color: Colors.white, + decoration: BoxDecoration( + borderRadius: radiusInner, + color: Colors.white, + ), height: cardHeight, width: cardWidth, ), @@ -2423,12 +2463,24 @@ class GameController extends GetxController { child: AnimatedRotation( duration: const Duration(milliseconds: ANIMATION_TIME), turns: stihBoolValues[1] != true ? -0.35 : -0.35 + e.angle, - child: ClipRRect( - borderRadius: radius, + child: Container( + decoration: BoxDecoration( + border: analysis != null && + analysis.cardPicks.card.asset == e.asset + ? Border.all( + width: 10.0, + color: Colors.red, + ) + : null, + borderRadius: radius, + ), child: Stack( children: [ Container( - color: Colors.white, + decoration: BoxDecoration( + borderRadius: radiusInner, + color: Colors.white, + ), height: cardHeight, width: cardWidth, ), @@ -2486,12 +2538,24 @@ class GameController extends GetxController { child: AnimatedRotation( duration: const Duration(milliseconds: ANIMATION_TIME), turns: stihBoolValues[3] != true ? 0 : e.angle, - child: ClipRRect( - borderRadius: radius, + child: Container( + decoration: BoxDecoration( + border: + analysis != null && analysis.cardPicks.card.asset == e.asset + ? Border.all( + width: 10.0, + color: Colors.red, + ) + : null, + borderRadius: radius, + ), child: Stack( children: [ Container( - color: Colors.white, + decoration: BoxDecoration( + borderRadius: radiusInner, + color: Colors.white, + ), height: cardHeight, width: cardWidth, ), @@ -2519,9 +2583,18 @@ class GameController extends GetxController { double fullWidth, ) { BorderRadius radius = BorderRadius.circular(10 * (fullWidth / 1000)); + BorderRadius radiusInner = BorderRadius.circular(10 * (fullWidth / 2000)); double cardHeight = m * cardK; double cardWidth = cardHeight * 0.57; + List cards = cardStih + .map((e) => stockskis.Card(card: stockskis.CARDS_MAP[e]!, user: "")) + .toList(); + final analysis = stockskis.StockSkis.analyzeStih( + cards, + getGamemode(), + ); + List widgets = []; for (int i = 0; i < stih.length; i++) { CardWidget e = stih[i]; @@ -2535,12 +2608,24 @@ class GameController extends GetxController { child: AnimatedRotation( duration: const Duration(milliseconds: ANIMATION_TIME), turns: stihBoolValues[0] != true ? 0.2 : 0.25 + e.angle, - child: ClipRRect( - borderRadius: radius, + child: Container( + decoration: BoxDecoration( + border: analysis != null && + analysis.cardPicks.card.asset == e.asset + ? Border.all( + width: 10.0, + color: Colors.red, + ) + : null, + borderRadius: radius, + ), child: Stack( children: [ Container( - color: Colors.white, + decoration: BoxDecoration( + borderRadius: radiusInner, + color: Colors.white, + ), height: cardHeight, width: cardWidth, ), @@ -2569,12 +2654,24 @@ class GameController extends GetxController { child: AnimatedRotation( duration: const Duration(milliseconds: ANIMATION_TIME), turns: stihBoolValues[1] != true ? 0 : e.angle, - child: ClipRRect( - borderRadius: radius, + child: Container( + decoration: BoxDecoration( + border: analysis != null && + analysis.cardPicks.card.asset == e.asset + ? Border.all( + width: 10.0, + color: Colors.red, + ) + : null, + borderRadius: radius, + ), child: Stack( children: [ Container( - color: Colors.white, + decoration: BoxDecoration( + borderRadius: radiusInner, + color: Colors.white, + ), height: cardHeight, width: cardWidth, ), @@ -2603,12 +2700,24 @@ class GameController extends GetxController { child: AnimatedRotation( duration: const Duration(milliseconds: ANIMATION_TIME), turns: stihBoolValues[2] != true ? 0.25 : 0.25 + e.angle, - child: ClipRRect( - borderRadius: radius, + child: Container( + decoration: BoxDecoration( + border: analysis != null && + analysis.cardPicks.card.asset == e.asset + ? Border.all( + width: 10.0, + color: Colors.red, + ) + : null, + borderRadius: radius, + ), child: Stack( children: [ Container( - color: Colors.white, + decoration: BoxDecoration( + borderRadius: radiusInner, + color: Colors.white, + ), height: cardHeight, width: cardWidth, ), @@ -2666,12 +2775,24 @@ class GameController extends GetxController { child: AnimatedRotation( duration: const Duration(milliseconds: ANIMATION_TIME), turns: stihBoolValues[3] != true ? 0 : e.angle, - child: ClipRRect( - borderRadius: radius, + child: Container( + decoration: BoxDecoration( + border: + analysis != null && analysis.cardPicks.card.asset == e.asset + ? Border.all( + width: 10.0, + color: Colors.red, + ) + : null, + borderRadius: radius, + ), child: Stack( children: [ Container( - color: Colors.white, + decoration: BoxDecoration( + borderRadius: radiusInner, + color: Colors.white, + ), height: cardHeight, width: cardWidth, ), @@ -3088,15 +3209,18 @@ class GameController extends GetxController { ), ), child: Center( - child: Text( - selectedKing.value == "/pik/kralj" + child: TwemojiText( + text: selectedKing.value == "/pik/kralj" ? "♠️" : (selectedKing.value == "/src/kralj" ? "❤️" : (selectedKing.value == "/kriz/kralj" ? "♣️" : "♦️")), - style: TextStyle(fontSize: 0.3 * userSquareSize)), + style: TextStyle( + fontSize: 0.3 * userSquareSize, + color: Colors.white, + )), ), ), ), @@ -3247,15 +3371,18 @@ class GameController extends GetxController { ), ), child: Center( - child: Text( - selectedKing.value == "/pik/kralj" + child: TwemojiText( + text: selectedKing.value == "/pik/kralj" ? "♠️" : (selectedKing.value == "/src/kralj" ? "❤️" : (selectedKing.value == "/kriz/kralj" ? "♣️" : "♦️")), - style: TextStyle(fontSize: 0.3 * userSquareSize)), + style: TextStyle( + fontSize: 0.3 * userSquareSize, + color: Colors.white, + )), ), ), ), @@ -3404,13 +3531,16 @@ class GameController extends GetxController { ), ), child: Center( - child: Text( - selectedKing.value == "/pik/kralj" + child: TwemojiText( + text: selectedKing.value == "/pik/kralj" ? "♠️" : (selectedKing.value == "/src/kralj" ? "❤️" : (selectedKing.value == "/kriz/kralj" ? "♣️" : "♦️")), - style: TextStyle(fontSize: 0.3 * userSquareSize), + style: TextStyle( + fontSize: 0.3 * userSquareSize, + color: Colors.white, + ), ), ), ), diff --git a/tarok/lib/internationalization/languages.dart b/tarok/lib/internationalization/languages.dart index 369695f..9f8a9c9 100644 --- a/tarok/lib/internationalization/languages.dart +++ b/tarok/lib/internationalization/languages.dart @@ -477,6 +477,9 @@ class Messages extends Translations { "show_evaluation": "Show evaluation", "show_evaluation_desc": "Shows current StockŠkis evaluation in an evaluation bar in offline (bot) games.", + "show_most_powerful_card": "Show most powerful card", + "show_most_powerful_card_desc": + "Marks the currently most powerful card in the round with red.", }, "fr_FR": { "login": "Connexion", @@ -945,6 +948,9 @@ class Messages extends Translations { "show_evaluation": "Show evaluation", "show_evaluation_desc": "Shows current StockŠkis evaluation in an evaluation bar in offline (bot) games.", + "show_most_powerful_card": "Show most powerful card", + "show_most_powerful_card_desc": + "Marks the currently most powerful card in the round with red.", }, "sl_SI": { "login": "Prijava", @@ -1401,6 +1407,9 @@ class Messages extends Translations { "show_evaluation": "Prikaži evaluacijo", "show_evaluation_desc": "Prikaže trenutno StockŠkis evaluacijo v igrah brez internetne povezave (offline/z boti).", + "show_most_powerful_card": "Prikaži najbolj močno karto", + "show_most_powerful_card_desc": + "Označi trenutno najbolj močno karto v rundi z rdečo.", } }; } diff --git a/tarok/lib/main.dart b/tarok/lib/main.dart index b90a313..8602d0d 100644 --- a/tarok/lib/main.dart +++ b/tarok/lib/main.dart @@ -87,6 +87,7 @@ void main() async { COUNTERCLOCKWISE_GAME = prefs.getBool("counterclockwise_game") ?? false; POINTS_TOOLTIP = prefs.getBool("points_tooltip") ?? false; SHOW_EVALUATION = prefs.getBool("show_evaluation") ?? true; + SHOW_MOST_POWERFUL_CARD = prefs.getBool("show_most_powerful_card") ?? false; if (kReleaseMode) { BACKEND_URL = prefs.getString("api_url") ?? "https://palcka.si/api"; diff --git a/tarok/lib/settings.dart b/tarok/lib/settings.dart index c74a1c1..9696b02 100644 --- a/tarok/lib/settings.dart +++ b/tarok/lib/settings.dart @@ -191,6 +191,20 @@ class _SettingsState extends State { title: Text("enable_points_tooltip".tr), description: Text("enable_points_tooltip_desc".tr), ), + SettingsTile.switchTile( + onToggle: (value) async { + final SharedPreferences prefs = + await SharedPreferences.getInstance(); + await prefs.setBool("show_most_powerful_card", value); + SHOW_MOST_POWERFUL_CARD = + prefs.getBool("show_most_powerful_card") ?? false; + setState(() {}); + }, + initialValue: SHOW_MOST_POWERFUL_CARD, + leading: const Icon(Icons.bolt), + title: Text("show_most_powerful_card".tr), + description: Text("show_most_powerful_card_desc".tr), + ), ], ), if (!kIsWeb && (Platform.isLinux || Platform.isWindows))