diff --git a/lib/l10n/app_de.arb b/lib/l10n/app_de.arb index 4d2f85b..3cb8c5e 100644 --- a/lib/l10n/app_de.arb +++ b/lib/l10n/app_de.arb @@ -64,7 +64,12 @@ "done": "Fertig", "next_round": "Nächste Runde", - "game_statistics": "Spielstatistiken", + "statistics": "Statistiken", + "delete_game": "Spiel löschen", + "new_game_same_settings": "Neues Spiel mit gleichen Einstellungen", + "export_game": "Spiel exportieren", + + "game_process": "Spielverlauf", "settings": "Einstellungen", "cabo_penalty": "Cabo-Strafe", diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 5a7da91..f76e04a 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -14,6 +14,7 @@ "player": "Player", "players": "Players", "name": "Name", + "back": "Back", "home": "Home", "about": "About", @@ -63,6 +64,13 @@ "done": "Done", "next_round": "Next Round", + "statistics": "Statistics", + "delete_game": "Delete Game", + "new_game_same_settings": "New Game with same Settings", + "export_game": "Export Game", + + "game_process": "Spielverlauf", + "settings": "Settings", "cabo_penalty": "Cabo Penalty", "cabo_penalty_subtitle": "... for falsely calling Cabo.", @@ -80,5 +88,6 @@ "app_version": "App Version", "load_version": "Loading version...", "build": "Build", + "about_text": "Hey :) Thanks for being one of the first users of my app! I’ve put a lot of work into this project, and even though I tried to think of everything, it might not work perfectly just yet. So if you discover any bugs or have feedback on the design or usability, please let me know via the TestFlight app or by sending me a message or email. Thank you very much!" } diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index e6279c2..1751ab7 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -362,11 +362,35 @@ abstract class AppLocalizations { /// **'Nächste Runde'** String get next_round; - /// No description provided for @game_statistics. + /// No description provided for @statistics. /// /// In de, this message translates to: - /// **'Spielstatistiken'** - String get game_statistics; + /// **'Statistiken'** + String get statistics; + + /// No description provided for @delete_game. + /// + /// In de, this message translates to: + /// **'Spiel löschen'** + String get delete_game; + + /// No description provided for @new_game_same_settings. + /// + /// In de, this message translates to: + /// **'Neues Spiel mit gleichen Einstellungen'** + String get new_game_same_settings; + + /// No description provided for @export_game. + /// + /// In de, this message translates to: + /// **'Spiel exportieren'** + String get export_game; + + /// No description provided for @game_process. + /// + /// In de, this message translates to: + /// **'Spielverlauf'** + String get game_process; /// No description provided for @settings. /// diff --git a/lib/l10n/app_localizations_de.dart b/lib/l10n/app_localizations_de.dart index f6df27f..434b5f1 100644 --- a/lib/l10n/app_localizations_de.dart +++ b/lib/l10n/app_localizations_de.dart @@ -150,7 +150,19 @@ class AppLocalizationsDe extends AppLocalizations { String get next_round => 'Nächste Runde'; @override - String get game_statistics => 'Spielstatistiken'; + String get statistics => 'Statistiken'; + + @override + String get delete_game => 'Spiel löschen'; + + @override + String get new_game_same_settings => 'Neues Spiel mit gleichen Einstellungen'; + + @override + String get export_game => 'Spiel exportieren'; + + @override + String get game_process => 'Spielverlauf'; @override String get settings => 'Einstellungen'; diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index 07c3bba..64cdb77 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -48,7 +48,7 @@ class AppLocalizationsEn extends AppLocalizations { String get name => 'Name'; @override - String get back => 'Zurück'; + String get back => 'Back'; @override String get home => 'Home'; @@ -147,7 +147,19 @@ class AppLocalizationsEn extends AppLocalizations { String get next_round => 'Next Round'; @override - String get game_statistics => 'Spielstatistiken'; + String get statistics => 'Statistics'; + + @override + String get delete_game => 'Delete Game'; + + @override + String get new_game_same_settings => 'New Game with same Settings'; + + @override + String get export_game => 'Export Game'; + + @override + String get game_process => 'Spielverlauf'; @override String get settings => 'Settings'; diff --git a/lib/l10n/untranslated_messages.json b/lib/l10n/untranslated_messages.json index 7c9f0f2..9e26dfe 100644 --- a/lib/l10n/untranslated_messages.json +++ b/lib/l10n/untranslated_messages.json @@ -1,6 +1 @@ -{ - "en": [ - "back", - "game_statistics" - ] -} +{} \ No newline at end of file diff --git a/lib/views/active_game_view.dart b/lib/views/active_game_view.dart index c768eb2..6266348 100644 --- a/lib/views/active_game_view.dart +++ b/lib/views/active_game_view.dart @@ -82,6 +82,8 @@ class _ActiveGameViewState extends State { return Padding( padding: const EdgeInsets.all(1), child: CupertinoListTile( + backgroundColorActivated: + CustomTheme.backgroundColor, title: Text( '${AppLocalizations.of(context).round} ${index + 1}', ), @@ -119,17 +121,39 @@ class _ActiveGameViewState extends State { Column( children: [ CupertinoListTile( - title: const Text('Statistiken'), + backgroundColorActivated: + CustomTheme.backgroundColor, + title: Text( + AppLocalizations.of(context).statistics, + ), onTap: () => Navigator.push( context, MaterialPageRoute( - builder: (_) => const GraphView()))), - const CupertinoListTile(title: Text('Spiel löschen')), - const CupertinoListTile( + builder: (_) => GraphView( + gameSession: widget.gameSession, + )))), + CupertinoListTile( + title: + Text(AppLocalizations.of(context).delete_game, + style: const TextStyle( + color: Colors.white30, + )), + onTap: () {}, + ), + CupertinoListTile( title: Text( - 'Neues Spiel mit gleichen Einstellungen')), - const CupertinoListTile( - title: Text('Spiel exportieren')), + AppLocalizations.of(context) + .new_game_same_settings, + style: const TextStyle( + color: Colors.white30, + ))), + CupertinoListTile( + title: + Text(AppLocalizations.of(context).export_game, + style: const TextStyle( + color: Colors.white30, + )), + ), ], ) ], diff --git a/lib/views/graph_view.dart b/lib/views/graph_view.dart index 00dff72..345c670 100644 --- a/lib/views/graph_view.dart +++ b/lib/views/graph_view.dart @@ -1,22 +1,84 @@ +import 'package:cabo_counter/data/game_session.dart'; import 'package:cabo_counter/l10n/app_localizations.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:syncfusion_flutter_charts/charts.dart'; class GraphView extends StatefulWidget { - const GraphView({super.key}); + final GameSession gameSession; + + const GraphView({super.key, required this.gameSession}); @override State createState() => _GraphViewState(); } class _GraphViewState extends State { + /// List of colors for the graph lines. + List lineColors = [ + Colors.red, + Colors.blue, + Colors.orange.shade400, + Colors.purple, + Colors.green, + ]; + @override Widget build(BuildContext context) { return CupertinoPageScaffold( navigationBar: CupertinoNavigationBar( - middle: Text(AppLocalizations.of(context).game_statistics), + middle: Text(AppLocalizations.of(context).game_process), previousPageTitle: AppLocalizations.of(context).back, ), - child: const Center(child: Text('GraphView')), + child: Padding( + padding: const EdgeInsets.fromLTRB(0, 100, 0, 0), + child: SfCartesianChart( + legend: + const Legend(isVisible: true, position: LegendPosition.bottom), + primaryXAxis: const NumericAxis(), + primaryYAxis: const NumericAxis(), + series: getCumulativeScores(), + ), + ), ); } + + /// Returns a list of LineSeries representing the cumulative scores of each player. + /// Each series contains data points for each round, showing the cumulative score up to that round. + /// The x-axis represents the round number, and the y-axis represents the cumulative score. + List> getCumulativeScores() { + final rounds = widget.gameSession.roundList; + final playerCount = widget.gameSession.players.length; + final playerNames = widget.gameSession.players; + + List> cumulativeScores = List.generate(playerCount, (_) => []); + List runningTotals = List.filled(playerCount, 0); + + for (var round in rounds) { + for (int i = 0; i < playerCount; i++) { + runningTotals[i] += round.scores[i]; + cumulativeScores[i].add(runningTotals[i]); + } + } + + /// Create a list of LineSeries for each player + /// Each series contains data points for each round + return List.generate(playerCount, (i) { + final data = List.generate( + cumulativeScores[i].length, + (j) => (j + 1, cumulativeScores[i][j]), // (round, score) + ); + + /// Create a LineSeries for the player + /// The xValueMapper maps the round number, and the yValueMapper maps the cumulative score. + return LineSeries<(int, int), int>( + name: playerNames[i], + dataSource: data, + xValueMapper: (record, _) => record.$1, // Runde + yValueMapper: (record, _) => record.$2, // Punktestand + markerSettings: const MarkerSettings(isVisible: true), + color: lineColors[i], + ); + }); + } } diff --git a/pubspec.yaml b/pubspec.yaml index ff80cad..b0bf86a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: cabo_counter description: "Mobile app for the card game Cabo" publish_to: 'none' -version: 0.3.1+239 +version: 0.3.2+244 environment: sdk: ^3.5.4 @@ -25,6 +25,7 @@ dependencies: flutter_localizations: sdk: flutter intl: any + syncfusion_flutter_charts: ^30.1.37 dev_dependencies: flutter_test: