From d78da0145feb2318ff24c9f36858b16f99e2162a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr>
Date: Wed, 6 Jul 2022 18:18:45 +0200
Subject: [PATCH] Save current game state, allow resume/restart game

---
 android/gradle.properties                     |   4 +-
 assets/icons/button_delete_saved_game.png     | Bin 0 -> 5813 bytes
 assets/icons/button_resume_game.png           | Bin 0 -> 3659 bytes
 assets/icons/button_start.png                 | Bin 3999 -> 3666 bytes
 .../metadata/android/en-US/changelogs/57.txt  |   1 +
 .../metadata/android/fr-FR/changelogs/57.txt  |   1 +
 icons/build_game_icons.sh                     |   2 +
 icons/button_delete_saved_game.svg            |   2 +
 icons/button_resume_game.svg                  |   2 +
 icons/button_start.svg                        |   2 +-
 lib/layout/game.dart                          |   2 +-
 lib/layout/parameters.dart                    | 110 +++++++++++++-----
 lib/provider/data.dart                        |  84 ++++++++++++-
 lib/screens/home.dart                         |   3 +-
 lib/utils/board_utils.dart                    |  24 ++++
 lib/utils/game_utils.dart                     |  41 ++++++-
 16 files changed, 236 insertions(+), 42 deletions(-)
 create mode 100644 assets/icons/button_delete_saved_game.png
 create mode 100644 assets/icons/button_resume_game.png
 create mode 100644 fastlane/metadata/android/en-US/changelogs/57.txt
 create mode 100644 fastlane/metadata/android/fr-FR/changelogs/57.txt
 create mode 100644 icons/button_delete_saved_game.svg
 create mode 100644 icons/button_resume_game.svg

diff --git a/android/gradle.properties b/android/gradle.properties
index f05da2a..23d76d0 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=0.1.7
-app.versionCode=56
+app.versionName=0.1.8
+app.versionCode=57
diff --git a/assets/icons/button_delete_saved_game.png b/assets/icons/button_delete_saved_game.png
new file mode 100644
index 0000000000000000000000000000000000000000..5e4f217689b11e444b7163557d7e5d68f3bbfe7d
GIT binary patch
literal 5813
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

literal 0
HcmV?d00001

diff --git a/assets/icons/button_resume_game.png b/assets/icons/button_resume_game.png
new file mode 100644
index 0000000000000000000000000000000000000000..b2ea0a02d05e42377eb551a4b51428b511a32f5d
GIT binary patch
literal 3659
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

literal 0
HcmV?d00001

diff --git a/assets/icons/button_start.png b/assets/icons/button_start.png
index 6845e2f5c21598ab61f1684d2075aeec0334bf23..f0ead9744e59874fa15d70d7e5e49336a15009dd 100644
GIT binary patch
delta 3551
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

delta 3898
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

diff --git a/fastlane/metadata/android/en-US/changelogs/57.txt b/fastlane/metadata/android/en-US/changelogs/57.txt
new file mode 100644
index 0000000..36b3521
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/57.txt
@@ -0,0 +1 @@
+Autosave current game, allow to continue current game on home screen
diff --git a/fastlane/metadata/android/fr-FR/changelogs/57.txt b/fastlane/metadata/android/fr-FR/changelogs/57.txt
new file mode 100644
index 0000000..f655421
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/57.txt
@@ -0,0 +1 @@
+Sauvegarde automatique de la partie en cours, proposition de continuer sur l'écran d'accueil
diff --git a/icons/build_game_icons.sh b/icons/build_game_icons.sh
index 8a6aa2a..4f0f02f 100755
--- a/icons/build_game_icons.sh
+++ b/icons/build_game_icons.sh
@@ -18,6 +18,8 @@ ICON_SIZE=192
 AVAILABLE_GAME_IMAGES="
   button_back
   button_start
+  button_resume_game
+  button_delete_saved_game
   button_help
   button_show_conflicts
   game_win
diff --git a/icons/button_delete_saved_game.svg b/icons/button_delete_saved_game.svg
new file mode 100644
index 0000000..ac7eefe
--- /dev/null
+++ b/icons/button_delete_saved_game.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#ee7d49" stroke="#fff" stroke-width=".238"/><path d="m61.07 35.601-1.7399 27.837c-0.13442 2.1535-1.9205 3.8312-4.0781 3.8312h-16.84c-2.1576 0-3.9437-1.6777-4.0781-3.8312l-1.7399-27.837h-2.6176c-0.84621 0-1.5323-0.68613-1.5323-1.5323 0-0.84655 0.68613-1.5323 1.5323-1.5323h33.711c0.84621 0 1.5323 0.68578 1.5323 1.5323 0 0.84621-0.68613 1.5323-1.5323 1.5323zm-3.2617 0h-21.953l1.4715 26.674c0.05985 1.0829 0.95531 1.9305 2.0403 1.9305h14.929c1.085 0 1.9804-0.84757 2.0403-1.9305zm-10.977 3.0647c0.78977 0 1.4301 0.6403 1.4301 1.4301v19.614c0 0.78977-0.6403 1.4301-1.4301 1.4301s-1.4301-0.6403-1.4301-1.4301v-19.614c0-0.78977 0.6403-1.4301 1.4301-1.4301zm-6.1293 0c0.80004 0 1.4588 0.62935 1.495 1.4286l0.89647 19.719c0.03182 0.70016-0.50998 1.2933-1.2101 1.3255-0.01915 7.02e-4 -0.03831 1e-3 -0.05781 1e-3 -0.74462 0-1.3596-0.58215-1.4003-1.3261l-1.0757-19.719c-0.0407-0.74701 0.53188-1.3852 1.2786-1.4259 0.02462-0.0014 0.04926-2e-3 0.07388-2e-3zm12.259 0c0.74804 0 1.3541 0.60609 1.3541 1.3541 0 0.02462-3.28e-4 0.04926-0.0017 0.07388l-1.0703 19.618c-0.04379 0.80106-0.70597 1.4281-1.5081 1.4281-0.74804 0-1.3541-0.60609-1.3541-1.3541 0-0.02462 3.49e-4 -0.04925 0.0017-0.07388l1.0703-19.618c0.04379-0.80106 0.70597-1.4281 1.5081-1.4281zm-10.216-12.259h8.1728c2.2567 0 4.086 1.8293 4.086 4.086v2.0433h-16.344v-2.0433c0-2.2567 1.8293-4.086 4.086-4.086zm0.20453 3.0647c-0.67725 0-1.2259 0.54863-1.2259 1.2259v1.8388h10.215v-1.8388c0-0.67725-0.54863-1.2259-1.2259-1.2259z" fill="#fff" fill-rule="evenodd" stroke="#bd4812" stroke-width=".75383"/></svg>
diff --git a/icons/button_resume_game.svg b/icons/button_resume_game.svg
new file mode 100644
index 0000000..6ad8b64
--- /dev/null
+++ b/icons/button_resume_game.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m39.211 31.236c-0.84086-0.84489-2.9911-0.84489-2.9911 0v34.329c0 0.84594 2.1554 0.84594 2.9993 0l28.178-15.637c0.84392-0.84086 0.85812-2.2091 0.01623-3.053z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="6.1726"/><path d="m40.355 33.714c-0.71948-0.72294-2.5594-0.72294-2.5594 0v29.373c0 0.72383 1.8442 0.72383 2.5663 0l24.11-13.38c0.7221-0.71948 0.73426-1.8902 0.01389-2.6124z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="3.225"/><path d="m28.369 66.919v-37.591" fill="#105ca2" stroke="#105ca2" stroke-linecap="round" stroke-width="4.0337"/></svg>
diff --git a/icons/button_start.svg b/icons/button_start.svg
index e9d49d2..633a634 100644
--- a/icons/button_start.svg
+++ b/icons/button_start.svg
@@ -1,2 +1,2 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m34.852 25.44c-1.1248-1.1302-4.0012-1.1302-4.0012 0v45.921c0 1.1316 2.8832 1.1316 4.0121 0l37.693-20.918c1.1289-1.1248 1.1479-2.9551 0.02171-4.084z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m36.382 28.754c-0.96243-0.96706-3.4236-0.96706-3.4236 0v39.292c0 0.96825 2.467 0.96825 3.4329 0l32.252-17.898c0.96594-0.96243 0.9822-2.5285 0.01858-3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><g transform="matrix(.8268 0 0 .8268 9.0269 8.3829)" fill="#fefeff" stroke-linecap="round" stroke-linejoin="round"><path d="m34.852 25.44c-1.1248-1.1302-4.0012-1.1302-4.0012 0v45.921c0 1.1316 2.8832 1.1316 4.0121 0l37.693-20.918c1.1289-1.1248 1.1479-2.9551 0.02171-4.084z" stroke="#105ca1" stroke-width="8.257"/><path d="m36.382 28.754c-0.96243-0.96706-3.4236-0.96706-3.4236 0v39.292c0 0.96825 2.467 0.96825 3.4329 0l32.252-17.898c0.96594-0.96243 0.9822-2.5285 0.01858-3.4945z" stroke="#feffff" stroke-width="4.314"/></g></svg>
diff --git a/lib/layout/game.dart b/lib/layout/game.dart
index 189d212..9417d48 100644
--- a/lib/layout/game.dart
+++ b/lib/layout/game.dart
@@ -75,7 +75,7 @@ class Game {
           fit: BoxFit.fill,
         ),
       ),
-      onPressed: () => GameUtils.resetGame(myProvider),
+      onPressed: () => GameUtils.quitGame(myProvider),
     );
   }
 
diff --git a/lib/layout/parameters.dart b/lib/layout/parameters.dart
index 8543b36..163c3d2 100644
--- a/lib/layout/parameters.dart
+++ b/lib/layout/parameters.dart
@@ -20,16 +20,21 @@ class Parameters {
 
     List parameters = myProvider.availableParameters;
     for (var index = 0; index < parameters.length; index++) {
-      lines.add(Parameters.buildParameterSelector(myProvider, parameters[index]));
-      lines.add(SizedBox(height: Parameters.separatorHeight));
+      lines.add(buildParameterSelector(myProvider, parameters[index]));
+      lines.add(SizedBox(height: separatorHeight));
     }
 
+    myProvider.loadCurrentSavedState();
+    Widget buttonsBlock = myProvider.hasCurrentSavedState()
+        ? buildResumeGameButton(myProvider)
+        : buildStartNewGameButton(myProvider);
+
     return Container(
       child: Column(
         mainAxisAlignment: MainAxisAlignment.start,
         crossAxisAlignment: CrossAxisAlignment.center,
         children: [
-          SizedBox(height: Parameters.separatorHeight),
+          SizedBox(height: separatorHeight),
           Expanded(
             child: Column(
               mainAxisSize: MainAxisSize.min,
@@ -37,45 +42,91 @@ class Parameters {
               children: lines,
             ),
           ),
-          SizedBox(height: Parameters.separatorHeight),
+          SizedBox(height: separatorHeight),
           Container(
-            child: Parameters.buildStartGameButton(myProvider),
+            child: buttonsBlock,
           ),
         ],
       ),
     );
   }
 
-  static Container buildStartGameButton(Data myProvider) {
-    Column decorationImage = Column(
+  static Image buildImageWidget(String imageAssetCode) {
+    return Image(
+      image: AssetImage('assets/icons/' + imageAssetCode + '.png'),
+      fit: BoxFit.fill,
+    );
+  }
+
+  static Container buildImageContainerWidget(String imageAssetCode) {
+    return Container(
+      child: buildImageWidget(imageAssetCode),
+    );
+  }
+
+  static Column buildDecorationImageWidget() {
+    return Column(
       children: [
-        Image(image: AssetImage('assets/icons/placeholder.png'), fit: BoxFit.fill),
+        TextButton(
+          child: buildImageContainerWidget('placeholder'),
+          onPressed: () => null,
+        ),
       ],
     );
+  }
+
+  static Container buildStartNewGameButton(Data myProvider) {
+    return Container(
+      margin: EdgeInsets.all(blockMargin),
+      padding: EdgeInsets.all(blockPadding),
+      child: Table(
+        defaultColumnWidth: IntrinsicColumnWidth(),
+        children: [
+          TableRow(
+            children: [
+              buildDecorationImageWidget(),
+              Column(
+                children: [
+                  TextButton(
+                    child: buildImageContainerWidget('button_start'),
+                    onPressed: () => GameUtils.startNewGame(myProvider),
+                  ),
+                ],
+              ),
+              buildDecorationImageWidget(),
+            ],
+          ),
+        ],
+      ),
+    );
+  }
 
+  static Container buildResumeGameButton(Data myProvider) {
     return Container(
-      margin: EdgeInsets.all(Parameters.blockMargin),
-      padding: EdgeInsets.all(Parameters.blockPadding),
+      margin: EdgeInsets.all(blockMargin),
+      padding: EdgeInsets.all(blockPadding),
       child: Table(
         defaultColumnWidth: IntrinsicColumnWidth(),
         children: [
           TableRow(
             children: [
-              decorationImage,
               Column(
                 children: [
                   TextButton(
-                    child: Container(
-                      child: Image(
-                        image: AssetImage('assets/icons/button_start.png'),
-                        fit: BoxFit.fill,
-                      ),
-                    ),
-                    onPressed: () => GameUtils.startGame(myProvider),
+                    child: buildImageContainerWidget('button_delete_saved_game'),
+                    onPressed: () => GameUtils.deleteSavedGame(myProvider),
                   ),
                 ],
               ),
-              decorationImage,
+              Column(
+                children: [
+                  TextButton(
+                    child: buildImageContainerWidget('button_resume_game'),
+                    onPressed: () => GameUtils.resumeSavedGame(myProvider),
+                  ),
+                ],
+              ),
+              buildDecorationImageWidget(),
             ],
           ),
         ],
@@ -112,26 +163,21 @@ class Parameters {
     String currentValue = myProvider.getParameterValue(parameterCode).toString();
 
     bool isActive = (parameterValue == currentValue);
-    String imageAsset = 'assets/icons/' + parameterCode + '_' + parameterValue + '.png';
+    String imageAsset = parameterCode + '_' + parameterValue;
 
     return TextButton(
       child: Container(
-        margin: EdgeInsets.all(Parameters.buttonMargin),
-        padding: EdgeInsets.all(Parameters.buttonPadding),
+        margin: EdgeInsets.all(buttonMargin),
+        padding: EdgeInsets.all(buttonPadding),
         decoration: BoxDecoration(
-          color: Parameters.buttonBackgroundColor,
-          borderRadius: BorderRadius.circular(Parameters.buttonBorderRadius),
+          color: buttonBackgroundColor,
+          borderRadius: BorderRadius.circular(buttonBorderRadius),
           border: Border.all(
-            color: isActive
-                ? Parameters.buttonBorderColorActive
-                : Parameters.buttonBorderColorInactive,
-            width: Parameters.buttonBorderWidth,
+            color: isActive ? buttonBorderColorActive : buttonBorderColorInactive,
+            width: buttonBorderWidth,
           ),
         ),
-        child: Image(
-          image: AssetImage(imageAsset),
-          fit: BoxFit.fill,
-        ),
+        child: buildImageWidget(imageAsset),
       ),
       onPressed: () => myProvider.setParameterValue(parameterCode, parameterValue),
     );
diff --git a/lib/provider/data.dart b/lib/provider/data.dart
index 7f6fe7c..c2b80e5 100644
--- a/lib/provider/data.dart
+++ b/lib/provider/data.dart
@@ -1,3 +1,5 @@
+import 'dart:convert';
+
 import 'package:flutter/foundation.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 
@@ -42,6 +44,7 @@ class Data extends ChangeNotifier {
   int? _currentCellValue;
   bool _showConflicts = false;
   int _givenTipsCount = 0;
+  String _currentState = '';
 
   void updateParameterLevel(String parameterLevel) {
     _parameterLevel = parameterLevel;
@@ -109,6 +112,69 @@ class Data extends ChangeNotifier {
     setParameterValue('skin', prefs.getString('skin') ?? _parameterSkinDefault);
   }
 
+  String get currentState => _currentState;
+
+  String computeCurrentGameState() {
+    String cellsValues = '';
+    String stringValues = '0123456789ABCDEFG';
+    for (var rowIndex = 0; rowIndex < _cells.length; rowIndex++) {
+      for (var colIndex = 0; colIndex < _cells[rowIndex].length; colIndex++) {
+        cellsValues += stringValues[_cells[rowIndex][colIndex].value];
+        cellsValues += _cells[rowIndex][colIndex].isFixed ? 'x' : ' ';
+      }
+    }
+
+    var currentState = {
+      'level': _parameterLevel,
+      'size': _parameterSize,
+      'skin': _parameterSkin,
+      'tipsCount': _givenTipsCount,
+      'showConflicts': _showConflicts,
+      'boardValues': cellsValues,
+      'shuffledCellValues': _shuffledCellValues,
+    };
+
+    return json.encode(currentState);
+  }
+
+  void saveCurrentGameState() async {
+    if (_gameIsRunning) {
+      _currentState = computeCurrentGameState();
+
+      final prefs = await SharedPreferences.getInstance();
+      prefs.setString('savedState', _currentState);
+    } else {
+      resetCurrentSavedState();
+    }
+  }
+
+  void resetCurrentSavedState() async {
+    _currentState = '';
+
+    final prefs = await SharedPreferences.getInstance();
+    prefs.setString('savedState', _currentState);
+    notifyListeners();
+  }
+
+  void loadCurrentSavedState() async {
+    final prefs = await SharedPreferences.getInstance();
+    _currentState = prefs.getString('savedState') ?? '';
+  }
+
+  bool hasCurrentSavedState() {
+    return (_currentState != '');
+  }
+
+  Map<String, dynamic> getCurrentSavedState() {
+    if (_currentState != '') {
+      Map<String, dynamic> savedState = json.decode(_currentState);
+      if (savedState.isNotEmpty) {
+        return savedState;
+      }
+    }
+    return {};
+  }
+
   bool get gameIsRunning => _gameIsRunning;
   void updateGameIsRunning(bool gameIsRunning) {
     _gameIsRunning = gameIsRunning;
@@ -143,6 +209,10 @@ class Data extends ChangeNotifier {
     _shuffledCellValues = values;
   }
 
+  void setShuffleCellValues(List values) {
+    _shuffledCellValues = values;
+  }
+
   int getTranslatedValueForDisplay(int originalValue) {
     return _shuffledCellValues[originalValue - 1];
   }
@@ -168,14 +238,19 @@ class Data extends ChangeNotifier {
   int get givenTipsCount => _givenTipsCount;
   increaseGivenTipsCount() {
     _givenTipsCount = _givenTipsCount + 1;
+    saveCurrentGameState();
     notifyListeners();
   }
 
-  resetGivenTipsCount() {
-    _givenTipsCount = 0;
+  setGivenTipsCount(int value) {
+    _givenTipsCount = value;
     notifyListeners();
   }
 
+  resetGivenTipsCount() {
+    setGivenTipsCount(0);
+  }
+
   selectCell(int? col, int? row) {
     _currentCellCol = col;
     _currentCellRow = row;
@@ -192,8 +267,10 @@ class Data extends ChangeNotifier {
     if ((col != null) && (row != null)) {
       if (!_cells[row][col].isFixed) {
         _cells[row][col].value = value;
+
+        saveCurrentGameState();
+        notifyListeners();
       }
-      notifyListeners();
     }
   }
 
@@ -205,6 +282,7 @@ class Data extends ChangeNotifier {
 
   void toggleShowConflicts() {
     updateShowConflicts(!showConflicts);
+    saveCurrentGameState();
   }
 
   bool get animationInProgress => _animationInProgress;
diff --git a/lib/screens/home.dart b/lib/screens/home.dart
index f33c6e6..dba9586 100644
--- a/lib/screens/home.dart
+++ b/lib/screens/home.dart
@@ -22,6 +22,7 @@ class _HomeState extends State<Home> {
 
     Data myProvider = Provider.of<Data>(context, listen: false);
     myProvider.initParametersValues();
+    myProvider.loadCurrentSavedState();
   }
 
   List getImagesAssets(Data myProvider) {
@@ -81,7 +82,7 @@ class _HomeState extends State<Home> {
             ),
           ),
           onPressed: () => toast('Long press to quit game...'),
-          onLongPress: () => GameUtils.resetGame(myProvider),
+          onLongPress: () => GameUtils.quitGame(myProvider),
         ),
         Spacer(flex: 6),
         TextButton(
diff --git a/lib/utils/board_utils.dart b/lib/utils/board_utils.dart
index 9efe0a9..867301b 100644
--- a/lib/utils/board_utils.dart
+++ b/lib/utils/board_utils.dart
@@ -58,6 +58,30 @@ class BoardUtils {
     return cells;
   }
 
+  static List createBoardFromSavedState(Data myProvider, String savedBoard) {
+    List cells = [];
+    int boardSize = int.parse(pow((savedBoard.length / 2), 1 / 2).toStringAsFixed(0));
+
+    String stringValues = '0123456789ABCDEFG';
+
+    int index = 0;
+    for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+      List row = [];
+      for (var colIndex = 0; colIndex < boardSize; colIndex++) {
+        String stringValue = savedBoard[index++];
+        int value = stringValues.indexOf(stringValue);
+
+        String isFixedString = savedBoard[index++];
+        bool isFixed = (isFixedString != ' ');
+
+        row.add(Cell(value, isFixed));
+      }
+      cells.add(row);
+    }
+
+    return cells;
+  }
+
   static List copyBoard(List cells) {
     List copiedGrid = [];
     for (var rowIndex = 0; rowIndex < cells.length; rowIndex++) {
diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart
index a187647..77ba0da 100644
--- a/lib/utils/game_utils.dart
+++ b/lib/utils/game_utils.dart
@@ -3,11 +3,14 @@ import '../utils/board_animate.dart';
 import '../utils/board_utils.dart';
 
 class GameUtils {
-  static Future<void> resetGame(Data myProvider) async {
+  static Future<void> quitGame(Data myProvider) async {
     myProvider.updateGameIsRunning(false);
+    if (BoardUtils.checkBoardIsSolved(myProvider)) {
+      myProvider.resetCurrentSavedState();
+    }
   }
 
-  static Future<void> startGame(Data myProvider) async {
+  static Future<void> startNewGame(Data myProvider) async {
     myProvider.updateParameterSize(myProvider.parameterSize);
     myProvider.updateGameIsRunning(true);
     myProvider.resetGivenTipsCount();
@@ -18,6 +21,39 @@ class GameUtils {
     BoardAnimate.startAnimation(myProvider, 'start');
   }
 
+  static void deleteSavedGame(Data myProvider) {
+    myProvider.resetCurrentSavedState();
+  }
+
+  static void resumeSavedGame(Data myProvider) {
+    Map<String, dynamic> savedState = myProvider.getCurrentSavedState();
+    if (savedState.isNotEmpty) {
+      try {
+        myProvider.setParameterValue('level', savedState['level']);
+        myProvider.setParameterValue('size', savedState['size']);
+        myProvider.setParameterValue('skin', savedState['skin']);
+
+        myProvider.setGivenTipsCount(savedState['tipsCount']);
+        myProvider.updateShowConflicts(savedState['showConflicts']);
+
+        myProvider.setShuffleCellValues(savedState['shuffledCellValues']);
+
+        myProvider.updateCells(
+            BoardUtils.createBoardFromSavedState(myProvider, savedState['boardValues']));
+        myProvider.updateGameIsRunning(true);
+      } catch (e) {
+        print('Failed to resume game. Will start new one instead.');
+        myProvider.resetCurrentSavedState();
+        myProvider.initParametersValues();
+        startNewGame(myProvider);
+      }
+    } else {
+      myProvider.resetCurrentSavedState();
+      myProvider.initParametersValues();
+      startNewGame(myProvider);
+    }
+  }
+
   static void showTip(Data myProvider) {
     if (myProvider.currentCellCol == null || myProvider.currentCellRow == null) {
       // no selected cell -> pick one
@@ -91,6 +127,7 @@ class GameUtils {
         allowedValuesCount == 1 ? eligibleValue : 0);
     myProvider.selectCell(null, null);
     if (BoardUtils.checkBoardIsSolved(myProvider)) {
+      myProvider.resetCurrentSavedState();
       BoardAnimate.startAnimation(myProvider, 'win');
     }
   }
-- 
GitLab