From d237d98b173a276fdd6707b3ff6bdd609921fcd4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr>
Date: Mon, 19 Feb 2024 14:38:09 +0100
Subject: [PATCH] Use flutter linter, apply lints, update dependencies

---
 analysis_options.yaml                         |   1 +
 android/app/build.gradle                      |   2 +-
 android/gradle.properties                     |   4 +-
 .../metadata/android/en-US/changelogs/62.txt  |   1 +
 .../metadata/android/fr-FR/changelogs/62.txt  |   1 +
 lib/entities/cell.dart                        |  80 +++--
 lib/layout/board.dart                         |  21 +-
 lib/layout/game.dart                          |  82 +++--
 lib/layout/parameters.dart                    |  98 +++---
 lib/main.dart                                 |  13 +-
 lib/provider/data.dart                        |  74 ++---
 lib/screens/home.dart                         | 167 +++++-----
 lib/utils/board_animate.dart                  |  52 +--
 lib/utils/board_utils.dart                    | 313 +++++++++---------
 lib/utils/game_utils.dart                     |  59 ++--
 lib/utils/random_pick_grid.dart               |   4 +-
 pubspec.lock                                  |  96 +++---
 pubspec.yaml                                  |   5 +-
 18 files changed, 564 insertions(+), 509 deletions(-)
 create mode 100644 analysis_options.yaml
 create mode 100644 fastlane/metadata/android/en-US/changelogs/62.txt
 create mode 100644 fastlane/metadata/android/fr-FR/changelogs/62.txt

diff --git a/analysis_options.yaml b/analysis_options.yaml
new file mode 100644
index 0000000..f9b3034
--- /dev/null
+++ b/analysis_options.yaml
@@ -0,0 +1 @@
+include: package:flutter_lints/flutter.yaml
diff --git a/android/app/build.gradle b/android/app/build.gradle
index 6166fe3..e16818d 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -44,7 +44,7 @@ android {
 
     defaultConfig {
         applicationId "org.benoitharrault.sudoku"
-        minSdkVersion 16
+        minSdkVersion flutter.minSdkVersion
         targetSdkVersion 30
         versionCode appVersionCode.toInteger()
         versionName appVersionName
diff --git a/android/gradle.properties b/android/gradle.properties
index dd950cd..2a8865a 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.12
-app.versionCode=61
+app.versionName=0.1.13
+app.versionCode=62
diff --git a/fastlane/metadata/android/en-US/changelogs/62.txt b/fastlane/metadata/android/en-US/changelogs/62.txt
new file mode 100644
index 0000000..6ab1115
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/62.txt
@@ -0,0 +1 @@
+Add automatic flutter linter. Apply code lints. Update dependencies.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/62.txt b/fastlane/metadata/android/fr-FR/changelogs/62.txt
new file mode 100644
index 0000000..609f5cf
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/62.txt
@@ -0,0 +1 @@
+Ajout d'un correcteur automatique de code. Application des corrections. Mise à jour des dépendances.
diff --git a/lib/entities/cell.dart b/lib/entities/cell.dart
index a6a4786..bec985d 100644
--- a/lib/entities/cell.dart
+++ b/lib/entities/cell.dart
@@ -1,8 +1,8 @@
 import 'package:flutter/material.dart';
 
-import '../provider/data.dart';
-import '../utils/board_animate.dart';
-import '../utils/board_utils.dart';
+import 'package:sudoku/provider/data.dart';
+import 'package:sudoku/utils/board_animate.dart';
+import 'package:sudoku/utils/board_utils.dart';
 
 class Cell {
   int value;
@@ -20,18 +20,18 @@ class Cell {
   * Build widget for board cell, with interactions
   */
   Container widget(Data myProvider, int row, int col) {
-    String imageAsset = this.getImageAssetName(myProvider);
+    final String imageAsset = getImageAssetName(myProvider);
 
     return Container(
       decoration: BoxDecoration(
-        color: this.getBackgroundColor(myProvider),
-        border: this.getCellBorders(myProvider, row, col),
+        color: getBackgroundColor(myProvider),
+        border: getCellBorders(myProvider, row, col),
       ),
       child: GestureDetector(
         child: AnimatedSwitcher(
           duration: const Duration(milliseconds: 100),
           transitionBuilder: (Widget child, Animation<double> animation) {
-            return ScaleTransition(child: child, scale: animation);
+            return ScaleTransition(scale: animation, child: child);
           },
           child: Image(
             image: AssetImage(imageAsset),
@@ -54,22 +54,22 @@ class Cell {
   * Build widget for select/update value cell, with interactions
   */
   Container widgetUpdateValue(Data myProvider) {
-    if (this.value < 0) {
+    if (value < 0) {
       return Container();
     }
 
-    String imageAsset = this.getImageAssetName(myProvider);
+    final String imageAsset = getImageAssetName(myProvider);
     Color backgroundColor = Colors.grey.shade200;
 
     if (myProvider.showConflicts &&
         myProvider.currentCellCol != null &&
         myProvider.currentCellRow != null) {
-      List cells = myProvider.cells;
-      int blockSizeHorizontal = myProvider.blockSizeHorizontal;
-      int blockSizeVertical = myProvider.blockSizeVertical;
+      final List<List<Cell>> cells = myProvider.cells;
+      final int blockSizeHorizontal = myProvider.blockSizeHorizontal;
+      final int blockSizeVertical = myProvider.blockSizeVertical;
 
       if (!BoardUtils.isValueAllowed(cells, blockSizeHorizontal, blockSizeVertical,
-          myProvider.currentCellCol, myProvider.currentCellRow, this.value)) {
+          myProvider.currentCellCol, myProvider.currentCellRow, value)) {
         backgroundColor = Colors.pink.shade100;
       }
     }
@@ -87,7 +87,7 @@ class Cell {
           onTap: () {
             if (myProvider.currentCellCol != null && myProvider.currentCellRow != null) {
               myProvider.updateCellValue(
-                  myProvider.currentCellCol, myProvider.currentCellRow, this.value);
+                  myProvider.currentCellCol, myProvider.currentCellRow, value);
             }
             myProvider.selectCell(null, null);
             if (BoardUtils.checkBoardIsSolved(myProvider)) {
@@ -101,51 +101,49 @@ class Cell {
   * Compute image asset name, from skin and cell value/state
   */
   String getImageAssetName(Data myProvider) {
-    String imageAsset = 'assets/icons/cell_empty.png';
-    if (this.value > 0) {
-      int cellValue = myProvider.getTranslatedValueForDisplay(this.value);
-      imageAsset =
-          'assets/skins/' + myProvider.parameterSkin + '_' + cellValue.toString() + '.png';
+    if (value > 0) {
+      int cellValue = myProvider.getTranslatedValueForDisplay(value);
+      return 'assets/skins/${myProvider.parameterSkin}_$cellValue.png';
     }
 
-    return imageAsset;
+    return 'assets/icons/cell_empty.png';
   }
 
   // Compute cell background color, from cell state
   Color getBackgroundColor(Data myProvider) {
-    Color editableCellColor = Colors.grey.shade100;
-    Color editableCellColorConflict = Colors.pink.shade100;
-    Color fixedCellColor = Colors.grey.shade300;
-    Color fixedCellColorConflict = Colors.pink.shade200;
-    Color editableSelectedValueColor = Colors.green.shade100;
-    Color fixedSelectedValueColor = Colors.green.shade300;
-    Color editableAnimated = Colors.green.shade200;
-    Color fixedAnimated = Colors.green.shade300;
+    final Color editableCellColor = Colors.grey.shade100;
+    final Color editableCellColorConflict = Colors.pink.shade100;
+    final Color fixedCellColor = Colors.grey.shade300;
+    final Color fixedCellColorConflict = Colors.pink.shade200;
+    final Color editableSelectedValueColor = Colors.green.shade100;
+    final Color fixedSelectedValueColor = Colors.green.shade300;
+    final Color editableAnimated = Colors.green.shade200;
+    final Color fixedAnimated = Colors.green.shade300;
 
     Color backgroundColor = editableCellColor;
 
-    if (this.isFixed) {
+    if (isFixed) {
       backgroundColor = fixedCellColor;
     }
 
-    if (myProvider.showConflicts && (this.conflictsCount != 0)) {
-      if (this.isFixed) {
+    if (myProvider.showConflicts && (conflictsCount != 0)) {
+      if (isFixed) {
         backgroundColor = fixedCellColorConflict;
       } else {
         backgroundColor = editableCellColorConflict;
       }
     }
 
-    if (myProvider.showConflicts && (this.value == myProvider.currentCellValue)) {
-      if (this.isFixed) {
+    if (myProvider.showConflicts && (value == myProvider.currentCellValue)) {
+      if (isFixed) {
         backgroundColor = fixedSelectedValueColor;
       } else {
         backgroundColor = editableSelectedValueColor;
       }
     }
 
-    if (this.isAnimated) {
-      if (this.isFixed) {
+    if (isAnimated) {
+      if (isFixed) {
         backgroundColor = fixedAnimated;
       } else {
         backgroundColor = editableAnimated;
@@ -157,18 +155,18 @@ class Cell {
 
   // Compute cell borders, from board size and cell state
   Border getCellBorders(Data myProvider, int row, int col) {
-    int blockSizeHorizontal = myProvider.blockSizeHorizontal;
-    int blockSizeVertical = myProvider.blockSizeVertical;
+    final int blockSizeHorizontal = myProvider.blockSizeHorizontal;
+    final int blockSizeVertical = myProvider.blockSizeVertical;
 
-    Color cellBorderDarkColor = Colors.black;
-    Color cellBorderLightColor = Colors.grey;
-    Color cellBorderSelectedColor = Colors.red;
+    const Color cellBorderDarkColor = Colors.black;
+    const Color cellBorderLightColor = Colors.grey;
+    const Color cellBorderSelectedColor = Colors.red;
 
     Color cellBorderColor = cellBorderSelectedColor;
     double cellBorderWidth = 4;
 
     // Reduce cell border width on big boards
-    int boardSize = blockSizeVertical * blockSizeHorizontal;
+    final int boardSize = blockSizeVertical * blockSizeHorizontal;
     if (boardSize > 8) {
       cellBorderWidth = 2;
       if (boardSize > 10) {
diff --git a/lib/layout/board.dart b/lib/layout/board.dart
index 50fa7f8..9ad79f2 100644
--- a/lib/layout/board.dart
+++ b/lib/layout/board.dart
@@ -1,14 +1,15 @@
 import 'package:flutter/material.dart';
 
-import '../provider/data.dart';
+import 'package:sudoku/entities/cell.dart';
+import 'package:sudoku/provider/data.dart';
 
 class Board {
   static Container buildGameBoard(Data myProvider) {
-    Color borderColor = Colors.black;
+    const Color borderColor = Colors.black;
 
     return Container(
-      margin: EdgeInsets.all(2),
-      padding: EdgeInsets.all(2),
+      margin: const EdgeInsets.all(2),
+      padding: const EdgeInsets.all(2),
       decoration: BoxDecoration(
         color: borderColor,
         borderRadius: BorderRadius.circular(2),
@@ -25,14 +26,14 @@ class Board {
     );
   }
 
-  static Table buildGameTileset(Data myProvider) {
-    int boardSize = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
-    List cells = myProvider.cells;
+  static Widget buildGameTileset(Data myProvider) {
+    final int boardSize = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
+    final List<List<Cell>> cells = myProvider.cells;
 
-    return Table(defaultColumnWidth: IntrinsicColumnWidth(), children: [
-      for (var row = 0; row < boardSize; row++)
+    return Table(defaultColumnWidth: const IntrinsicColumnWidth(), children: [
+      for (int row = 0; row < boardSize; row++)
         TableRow(children: [
-          for (var col = 0; col < boardSize; col++)
+          for (int col = 0; col < boardSize; col++)
             Column(children: [cells[row][col].widget(myProvider, row, col)]),
         ]),
     ]);
diff --git a/lib/layout/game.dart b/lib/layout/game.dart
index 9417d48..a24deea 100644
--- a/lib/layout/game.dart
+++ b/lib/layout/game.dart
@@ -2,55 +2,53 @@ import 'dart:math';
 
 import 'package:flutter/material.dart';
 
-import '../entities/cell.dart';
-import '../layout/board.dart';
-import '../provider/data.dart';
-import '../utils/board_utils.dart';
-import '../utils/game_utils.dart';
+import 'package:sudoku/entities/cell.dart';
+import 'package:sudoku/layout/board.dart';
+import 'package:sudoku/provider/data.dart';
+import 'package:sudoku/utils/board_utils.dart';
+import 'package:sudoku/utils/game_utils.dart';
 
 class Game {
-  static Container buildGameWidget(Data myProvider) {
-    bool gameIsFinished = BoardUtils.checkBoardIsSolved(myProvider);
+  static Widget buildGameWidget(Data myProvider) {
+    final bool gameIsFinished = BoardUtils.checkBoardIsSolved(myProvider);
 
-    return Container(
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.start,
-        crossAxisAlignment: CrossAxisAlignment.center,
-        children: [
-          Board.buildGameBoard(myProvider),
-          SizedBox(height: 2),
-          gameIsFinished
-              ? Game.buildEndGameMessage(myProvider)
-              : Game.buildSelectCellValueBar(myProvider),
-        ],
-      ),
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.center,
+      children: [
+        Board.buildGameBoard(myProvider),
+        const SizedBox(height: 2),
+        gameIsFinished
+            ? Game.buildEndGameMessage(myProvider)
+            : Game.buildSelectCellValueBar(myProvider),
+      ],
     );
   }
 
   static Container buildSelectCellValueBar(Data myProvider) {
-    List cells = myProvider.cells;
+    final List<List<Cell>> cells = myProvider.cells;
 
-    bool isCellSelected =
+    final bool isCellSelected =
         (myProvider.currentCellCol != null && myProvider.currentCellRow != null);
-    bool isUpdatableCellSelected = isCellSelected
+    final bool isUpdatableCellSelected = isCellSelected
         ? !cells[myProvider.currentCellRow ?? 0][myProvider.currentCellCol ?? 0].isFixed
         : false;
-    int maxValue = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
+    final int maxValue = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
 
-    int maxItemsPerLine = 10;
-    int linesCount = (maxValue / maxItemsPerLine).floor() + 1;
-    int itemsCountPerLine = min(maxItemsPerLine, maxValue + 1);
+    const int maxItemsPerLine = 10;
+    final int linesCount = (maxValue / maxItemsPerLine).floor() + 1;
+    final int itemsCountPerLine = min(maxItemsPerLine, maxValue + 1);
 
     return Container(
-      margin: EdgeInsets.all(2),
-      padding: EdgeInsets.all(2),
+      margin: const EdgeInsets.all(2),
+      padding: const EdgeInsets.all(2),
       child: Table(
-        defaultColumnWidth: IntrinsicColumnWidth(),
+        defaultColumnWidth: const IntrinsicColumnWidth(),
         children: [
-          for (var lineIndex = 0; lineIndex < linesCount; lineIndex++)
+          for (int lineIndex = 0; lineIndex < linesCount; lineIndex++)
             TableRow(
               children: [
-                for (var value = lineIndex * itemsCountPerLine;
+                for (int value = lineIndex * itemsCountPerLine;
                     value < (lineIndex + 1) * itemsCountPerLine;
                     value++)
                   Column(
@@ -67,33 +65,31 @@ class Game {
     );
   }
 
-  static TextButton buildRestartGameButton(Data myProvider) {
+  static Widget buildRestartGameButton(Data myProvider) {
     return TextButton(
-      child: Container(
-        child: Image(
-          image: AssetImage('assets/icons/button_back.png'),
-          fit: BoxFit.fill,
-        ),
+      child: const Image(
+        image: AssetImage('assets/icons/button_back.png'),
+        fit: BoxFit.fill,
       ),
       onPressed: () => GameUtils.quitGame(myProvider),
     );
   }
 
   static Container buildEndGameMessage(Data myProvider) {
-    Image decorationImage = Image(
+    const Image decorationImage = Image(
       image: AssetImage('assets/icons/game_win.png'),
       fit: BoxFit.fill,
     );
 
     return Container(
-      margin: EdgeInsets.all(2),
-      padding: EdgeInsets.all(2),
+      margin: const EdgeInsets.all(2),
+      padding: const EdgeInsets.all(2),
       child: Table(
-        defaultColumnWidth: IntrinsicColumnWidth(),
+        defaultColumnWidth: const IntrinsicColumnWidth(),
         children: [
           TableRow(
             children: [
-              Column(
+              const Column(
                 children: [decorationImage],
               ),
               Column(
@@ -103,7 +99,7 @@ class Game {
                       : buildRestartGameButton(myProvider)
                 ],
               ),
-              Column(
+              const Column(
                 children: [decorationImage],
               ),
             ],
diff --git a/lib/layout/parameters.dart b/lib/layout/parameters.dart
index 163c3d2..7a3e5f1 100644
--- a/lib/layout/parameters.dart
+++ b/lib/layout/parameters.dart
@@ -1,27 +1,27 @@
 import 'package:flutter/material.dart';
 
-import '../provider/data.dart';
-import '../utils/game_utils.dart';
+import 'package:sudoku/provider/data.dart';
+import 'package:sudoku/utils/game_utils.dart';
 
 class Parameters {
-  static double separatorHeight = 2.0;
-  static double blockMargin = 3.0;
-  static double blockPadding = 2.0;
-  static Color buttonBackgroundColor = Colors.white;
-  static Color buttonBorderColorActive = Colors.blue;
-  static Color buttonBorderColorInactive = Colors.white;
-  static double buttonBorderWidth = 10.0;
-  static double buttonBorderRadius = 8.0;
-  static double buttonPadding = 0.0;
-  static double buttonMargin = 0.0;
-
-  static Container buildParametersSelector(Data myProvider) {
+  static const double separatorHeight = 2.0;
+  static const double blockMargin = 3.0;
+  static const double blockPadding = 2.0;
+  static const Color buttonBackgroundColor = Colors.white;
+  static const Color buttonBorderColorActive = Colors.blue;
+  static const Color buttonBorderColorInactive = Colors.white;
+  static const double buttonBorderWidth = 10.0;
+  static const double buttonBorderRadius = 8.0;
+  static const double buttonPadding = 0.0;
+  static const double buttonMargin = 0.0;
+
+  static Widget buildParametersSelector(Data myProvider) {
     List<Widget> lines = [];
 
-    List parameters = myProvider.availableParameters;
-    for (var index = 0; index < parameters.length; index++) {
+    List<String> parameters = myProvider.availableParameters;
+    for (int index = 0; index < parameters.length; index++) {
       lines.add(buildParameterSelector(myProvider, parameters[index]));
-      lines.add(SizedBox(height: separatorHeight));
+      lines.add(const SizedBox(height: separatorHeight));
     }
 
     myProvider.loadCurrentSavedState();
@@ -29,31 +29,29 @@ class Parameters {
         ? buildResumeGameButton(myProvider)
         : buildStartNewGameButton(myProvider);
 
-    return Container(
-      child: Column(
-        mainAxisAlignment: MainAxisAlignment.start,
-        crossAxisAlignment: CrossAxisAlignment.center,
-        children: [
-          SizedBox(height: separatorHeight),
-          Expanded(
-            child: Column(
-              mainAxisSize: MainAxisSize.min,
-              mainAxisAlignment: MainAxisAlignment.center,
-              children: lines,
-            ),
-          ),
-          SizedBox(height: separatorHeight),
-          Container(
-            child: buttonsBlock,
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.center,
+      children: [
+        const SizedBox(height: separatorHeight),
+        Expanded(
+          child: Column(
+            mainAxisSize: MainAxisSize.min,
+            mainAxisAlignment: MainAxisAlignment.center,
+            children: lines,
           ),
-        ],
-      ),
+        ),
+        const SizedBox(height: separatorHeight),
+        Container(
+          child: buttonsBlock,
+        ),
+      ],
     );
   }
 
   static Image buildImageWidget(String imageAssetCode) {
     return Image(
-      image: AssetImage('assets/icons/' + imageAssetCode + '.png'),
+      image: AssetImage('assets/icons/$imageAssetCode.png'),
       fit: BoxFit.fill,
     );
   }
@@ -69,7 +67,7 @@ class Parameters {
       children: [
         TextButton(
           child: buildImageContainerWidget('placeholder'),
-          onPressed: () => null,
+          onPressed: () {},
         ),
       ],
     );
@@ -77,10 +75,10 @@ class Parameters {
 
   static Container buildStartNewGameButton(Data myProvider) {
     return Container(
-      margin: EdgeInsets.all(blockMargin),
-      padding: EdgeInsets.all(blockPadding),
+      margin: const EdgeInsets.all(blockMargin),
+      padding: const EdgeInsets.all(blockPadding),
       child: Table(
-        defaultColumnWidth: IntrinsicColumnWidth(),
+        defaultColumnWidth: const IntrinsicColumnWidth(),
         children: [
           TableRow(
             children: [
@@ -103,10 +101,10 @@ class Parameters {
 
   static Container buildResumeGameButton(Data myProvider) {
     return Container(
-      margin: EdgeInsets.all(blockMargin),
-      padding: EdgeInsets.all(blockPadding),
+      margin: const EdgeInsets.all(blockMargin),
+      padding: const EdgeInsets.all(blockPadding),
       child: Table(
-        defaultColumnWidth: IntrinsicColumnWidth(),
+        defaultColumnWidth: const IntrinsicColumnWidth(),
         children: [
           TableRow(
             children: [
@@ -135,18 +133,18 @@ class Parameters {
   }
 
   static Widget buildParameterSelector(Data myProvider, String parameterCode) {
-    List availableValues = myProvider.getParameterAvailableValues(parameterCode);
+    List<String> availableValues = myProvider.getParameterAvailableValues(parameterCode);
 
     if (availableValues.length == 1) {
-      return SizedBox(height: 0.0);
+      return const SizedBox(height: 0.0);
     }
 
     return Table(
-      defaultColumnWidth: IntrinsicColumnWidth(),
+      defaultColumnWidth: const IntrinsicColumnWidth(),
       children: [
         TableRow(
           children: [
-            for (var index = 0; index < availableValues.length; index++)
+            for (int index = 0; index < availableValues.length; index++)
               Column(
                 children: [
                   _buildParameterButton(myProvider, parameterCode, availableValues[index])
@@ -163,12 +161,12 @@ class Parameters {
     String currentValue = myProvider.getParameterValue(parameterCode).toString();
 
     bool isActive = (parameterValue == currentValue);
-    String imageAsset = parameterCode + '_' + parameterValue;
+    String imageAsset = '${parameterCode}_$parameterValue';
 
     return TextButton(
       child: Container(
-        margin: EdgeInsets.all(buttonMargin),
-        padding: EdgeInsets.all(buttonPadding),
+        margin: const EdgeInsets.all(buttonMargin),
+        padding: const EdgeInsets.all(buttonPadding),
         decoration: BoxDecoration(
           color: buttonBackgroundColor,
           borderRadius: BorderRadius.circular(buttonBorderRadius),
diff --git a/lib/main.dart b/lib/main.dart
index 7f44866..2855178 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -3,16 +3,18 @@ import 'package:flutter/services.dart';
 import 'package:provider/provider.dart';
 import 'package:overlay_support/overlay_support.dart';
 
-import 'provider/data.dart';
-import 'screens/home.dart';
+import 'package:sudoku/provider/data.dart';
+import 'package:sudoku/screens/home.dart';
 
 void main() {
   WidgetsFlutterBinding.ensureInitialized();
   SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
-      .then((value) => runApp(MyApp()));
+      .then((value) => runApp(const MyApp()));
 }
 
 class MyApp extends StatelessWidget {
+  const MyApp({super.key});
+
   @override
   Widget build(BuildContext context) {
     return ChangeNotifierProvider(
@@ -22,12 +24,11 @@ class MyApp extends StatelessWidget {
           child: MaterialApp(
             debugShowCheckedModeBanner: false,
             theme: ThemeData(
-              primaryColor: Colors.blue,
               visualDensity: VisualDensity.adaptivePlatformDensity,
             ),
-            home: Home(),
+            home: const Home(),
             routes: {
-              Home.id: (context) => Home(),
+              Home.id: (context) => const Home(),
             },
           ),
         );
diff --git a/lib/provider/data.dart b/lib/provider/data.dart
index c2b80e5..7edff91 100644
--- a/lib/provider/data.dart
+++ b/lib/provider/data.dart
@@ -3,27 +3,29 @@ import 'dart:convert';
 import 'package:flutter/foundation.dart';
 import 'package:shared_preferences/shared_preferences.dart';
 
+import 'package:sudoku/entities/cell.dart';
+
 class Data extends ChangeNotifier {
   // Configuration available values
-  List _availableParameters = ['level', 'size', 'skin'];
+  final List<String> _availableParameters = ['level', 'size', 'skin'];
 
-  List _availableLevelValues = ['easy', 'medium', 'hard', 'nightmare'];
-  List _availableSizeValues = ['2x2', '3x2', '3x3', '4x4'];
-  List _availableSkinValues = ['default', 'food', 'nature', 'monsters'];
-  List _shufflableSkins = ['food', 'nature', 'monsters'];
+  final List<String> _availableLevelValues = ['easy', 'medium', 'hard', 'nightmare'];
+  final List<String> _availableSizeValues = ['2x2', '3x2', '3x3', '4x4'];
+  final List<String> _availableSkinValues = ['default', 'food', 'nature', 'monsters'];
+  final List<String> _shufflableSkins = ['food', 'nature', 'monsters'];
 
-  List get availableParameters => _availableParameters;
-  List get availableLevelValues => _availableLevelValues;
-  List get availableSizeValues => _availableSizeValues;
-  List get availableSkinValues => _availableSkinValues;
+  List<String> get availableParameters => _availableParameters;
+  List<String> get availableLevelValues => _availableLevelValues;
+  List<String> get availableSizeValues => _availableSizeValues;
+  List<String> get availableSkinValues => _availableSkinValues;
 
   // Application default configuration
   String _parameterLevel = '';
-  String _parameterLevelDefault = 'medium';
+  final String _parameterLevelDefault = 'medium';
   String _parameterSize = '';
-  String _parameterSizeDefault = '3x3';
+  final String _parameterSizeDefault = '3x3';
   String _parameterSkin = '';
-  String _parameterSkinDefault = 'default';
+  final String _parameterSkinDefault = 'default';
 
   // Application current configuration
   String get parameterLevel => _parameterLevel;
@@ -36,9 +38,9 @@ class Data extends ChangeNotifier {
   bool _animationInProgress = false;
   int _blockSizeVertical = 0;
   int _blockSizeHorizontal = 0;
-  List _cells = [];
-  List _cellsSolved = [];
-  List _shuffledCellValues = [];
+  List<List<Cell>> _cells = [];
+  List<List<Cell>> _cellsSolved = [];
+  List<int> _shuffledCellValues = [];
   int? _currentCellCol;
   int? _currentCellRow;
   int? _currentCellValue;
@@ -77,7 +79,7 @@ class Data extends ChangeNotifier {
     return '';
   }
 
-  List getParameterAvailableValues(String parameterCode) {
+  List<String> getParameterAvailableValues(String parameterCode) {
     switch (parameterCode) {
       case 'level':
         return _availableLevelValues;
@@ -116,15 +118,15 @@ class Data extends ChangeNotifier {
 
   String computeCurrentGameState() {
     String cellsValues = '';
-    String stringValues = '0123456789ABCDEFG';
-    for (var rowIndex = 0; rowIndex < _cells.length; rowIndex++) {
-      for (var colIndex = 0; colIndex < _cells[rowIndex].length; colIndex++) {
+    const String stringValues = '0123456789ABCDEFG';
+    for (int rowIndex = 0; rowIndex < _cells.length; rowIndex++) {
+      for (int colIndex = 0; colIndex < _cells[rowIndex].length; colIndex++) {
         cellsValues += stringValues[_cells[rowIndex][colIndex].value];
         cellsValues += _cells[rowIndex][colIndex].isFixed ? 'x' : ' ';
       }
     }
 
-    var currentState = {
+    return json.encode({
       'level': _parameterLevel,
       'size': _parameterSize,
       'skin': _parameterSkin,
@@ -132,9 +134,7 @@ class Data extends ChangeNotifier {
       'showConflicts': _showConflicts,
       'boardValues': cellsValues,
       'shuffledCellValues': _shuffledCellValues,
-    };
-
-    return json.encode(currentState);
+    });
   }
 
   void saveCurrentGameState() async {
@@ -186,30 +186,30 @@ class Data extends ChangeNotifier {
     _assetsPreloaded = assetsPreloaded;
   }
 
-  List get cells => _cells;
-  void updateCells(List cells) {
+  List<List<Cell>> get cells => _cells;
+  void updateCells(List<List<Cell>> cells) {
     _cells = cells;
     notifyListeners();
   }
 
-  List get cellsSolved => _cellsSolved;
-  void updateCellsSolved(List cells) {
+  List<List<Cell>> get cellsSolved => _cellsSolved;
+  void updateCellsSolved(List<List<Cell>> cells) {
     _cellsSolved = cells;
   }
 
   void shuffleCellValues() {
-    int maxCellValue = 16;
-    List values = new List<int>.generate(maxCellValue, (i) => i + 1);
+    const int maxCellValue = 16;
+    final List<int> values = List<int>.generate(maxCellValue, (i) => i + 1);
 
     if (_shufflableSkins.contains(_parameterSkin)) {
       values.shuffle();
-      print('Shuffled tiles values: ' + values.toString());
+      print('Shuffled tiles values: $values');
     }
 
     _shuffledCellValues = values;
   }
 
-  void setShuffleCellValues(List values) {
+  void setShuffleCellValues(List<int> values) {
     _shuffledCellValues = values;
   }
 
@@ -292,9 +292,9 @@ class Data extends ChangeNotifier {
   }
 
   void setAnimatedBackground(List animatedCellsPattern) {
-    int boardSideLength = _blockSizeHorizontal * _blockSizeVertical;
-    for (var row = 0; row < boardSideLength; row++) {
-      for (var col = 0; col < boardSideLength; col++) {
+    final int boardSideLength = _blockSizeHorizontal * _blockSizeVertical;
+    for (int row = 0; row < boardSideLength; row++) {
+      for (int col = 0; col < boardSideLength; col++) {
         _cells[row][col].isAnimated = animatedCellsPattern[row][col];
       }
     }
@@ -302,9 +302,9 @@ class Data extends ChangeNotifier {
   }
 
   void resetAnimatedBackground() {
-    int boardSideLength = _blockSizeHorizontal * _blockSizeVertical;
-    for (var row = 0; row < boardSideLength; row++) {
-      for (var col = 0; col < boardSideLength; col++) {
+    final int boardSideLength = _blockSizeHorizontal * _blockSizeVertical;
+    for (int row = 0; row < boardSideLength; row++) {
+      for (int col = 0; col < boardSideLength; col++) {
         _cells[row][col].isAnimated = false;
       }
     }
diff --git a/lib/screens/home.dart b/lib/screens/home.dart
index bbc480b..90b6ffb 100644
--- a/lib/screens/home.dart
+++ b/lib/screens/home.dart
@@ -3,19 +3,21 @@ import 'package:provider/provider.dart';
 import 'package:badges/badges.dart' as badges;
 import 'package:overlay_support/overlay_support.dart';
 
-import '../layout/game.dart';
-import '../layout/parameters.dart';
-import '../provider/data.dart';
-import '../utils/game_utils.dart';
+import 'package:sudoku/layout/game.dart';
+import 'package:sudoku/layout/parameters.dart';
+import 'package:sudoku/provider/data.dart';
+import 'package:sudoku/utils/game_utils.dart';
 
 class Home extends StatefulWidget {
   static const String id = 'home';
 
+  const Home({super.key});
+
   @override
-  _HomeState createState() => _HomeState();
+  HomeState createState() => HomeState();
 }
 
-class _HomeState extends State<Home> {
+class HomeState extends State<Home> {
   @override
   void initState() {
     super.initState();
@@ -25,10 +27,10 @@ class _HomeState extends State<Home> {
     myProvider.loadCurrentSavedState();
   }
 
-  List getImagesAssets(Data myProvider) {
-    List assets = [];
+  List<String> getImagesAssets(Data myProvider) {
+    final List<String> assets = [];
 
-    List gameImages = [
+    final List<String> gameImages = [
       'button_back',
       'button_help',
       'button_show_conflicts',
@@ -37,104 +39,113 @@ class _HomeState extends State<Home> {
       'placeholder',
       'cell_empty'
     ];
-    myProvider.availableLevelValues.forEach((level) => gameImages.add('level_' + level));
-    myProvider.availableSizeValues.forEach((size) => gameImages.add('size_' + size));
+    for (String level in myProvider.availableLevelValues) {
+      gameImages.add('level_$level');
+    }
+    for (String size in myProvider.availableSizeValues) {
+      gameImages.add('size_$size');
+    }
 
-    gameImages.forEach((image) => assets.add('assets/icons/' + image + '.png'));
+    for (String image in gameImages) {
+      assets.add('${'assets/icons/$image'}.png');
+    }
 
-    List skinImages = [];
+    List<String> skinImages = [];
     for (int value = 1; value <= 16; value++) {
       skinImages.add(value.toString());
     }
 
-    myProvider.availableSkinValues.forEach((skin) => skinImages
-        .forEach((image) => assets.add('assets/skins/' + skin + '_' + image + '.png')));
+    for (String skin in myProvider.availableSkinValues) {
+      for (String image in skinImages) {
+        assets.add('${'${'assets/skins/$skin'}_$image'}.png');
+      }
+    }
 
     return assets;
   }
 
   @override
   Widget build(BuildContext context) {
-    Data myProvider = Provider.of<Data>(context);
+    final Data myProvider = Provider.of<Data>(context);
 
     if (!myProvider.assetsPreloaded) {
-      List assets = getImagesAssets(myProvider);
-      assets.forEach((asset) => precacheImage(AssetImage(asset), context));
+      List<String> assets = getImagesAssets(myProvider);
+      for (String asset in assets) {
+        precacheImage(AssetImage(asset), context);
+      }
       myProvider.updateAssetsPreloaded(true);
     }
 
-    List<Widget> menuActions = [];
+    final List<Widget> menuActions = [];
 
     if (myProvider.gameIsRunning) {
-      menuActions = [
-        TextButton(
-          child: Container(
-            decoration: BoxDecoration(
-              borderRadius: BorderRadius.circular(4),
-              border: Border.all(
-                color: Colors.blue,
-                width: 4,
-              ),
-            ),
-            child: Image(
-              image: AssetImage('assets/icons/button_back.png'),
-              fit: BoxFit.fill,
+      menuActions.add(TextButton(
+        child: Container(
+          decoration: BoxDecoration(
+            borderRadius: BorderRadius.circular(4),
+            border: Border.all(
+              color: Colors.white,
+              width: 3,
             ),
           ),
-          onPressed: () => toast('Long press to quit game...'),
-          onLongPress: () => GameUtils.quitGame(myProvider),
+          child: const Image(
+            image: AssetImage('assets/icons/button_back.png'),
+            fit: BoxFit.fill,
+          ),
         ),
-        Spacer(flex: 6),
-        TextButton(
-          child: Container(
-            decoration: BoxDecoration(
-              borderRadius: BorderRadius.circular(4),
-              border: Border.all(
-                color: Colors.blue,
-                width: 4,
-              ),
-            ),
-            child: badges.Badge(
-              showBadge: myProvider.givenTipsCount == 0 ? false : true,
-              badgeStyle: badges.BadgeStyle(
-                badgeColor: myProvider.givenTipsCount < 10
-                    ? Colors.green
-                    : myProvider.givenTipsCount < 20
-                        ? Colors.orange
-                        : Colors.red,
-              ),
-              badgeContent: Text(
-                myProvider.givenTipsCount == 0 ? '' : myProvider.givenTipsCount.toString(),
-                style: TextStyle(color: Colors.white),
-              ),
-              child: Image(
-                image: AssetImage('assets/icons/button_help.png'),
-                fit: BoxFit.fill,
-              ),
+        onPressed: () => toast('Long press to quit game...'),
+        onLongPress: () => GameUtils.quitGame(myProvider),
+      ));
+      menuActions.add(const Spacer(flex: 6));
+      menuActions.add(TextButton(
+        child: Container(
+          decoration: BoxDecoration(
+            borderRadius: BorderRadius.circular(4),
+            border: Border.all(
+              color: Colors.white,
+              width: 3,
             ),
           ),
-          onPressed: () => GameUtils.showTip(myProvider),
-        ),
-        Spacer(),
-        TextButton(
-          child: Container(
-            decoration: BoxDecoration(
-              borderRadius: BorderRadius.circular(4),
-              border: Border.all(
-                color: myProvider.showConflicts ? Colors.white : Colors.blue,
-                width: 4,
-              ),
+          child: badges.Badge(
+            showBadge: myProvider.givenTipsCount == 0 ? false : true,
+            badgeStyle: badges.BadgeStyle(
+              badgeColor: myProvider.givenTipsCount < 10
+                  ? Colors.green
+                  : myProvider.givenTipsCount < 20
+                      ? Colors.orange
+                      : Colors.red,
             ),
-            child: Image(
-              image: AssetImage('assets/icons/button_show_conflicts.png'),
+            badgeContent: Text(
+              myProvider.givenTipsCount == 0 ? '' : myProvider.givenTipsCount.toString(),
+              style: const TextStyle(color: Colors.white),
+            ),
+            child: const Image(
+              image: AssetImage('assets/icons/button_help.png'),
               fit: BoxFit.fill,
             ),
           ),
-          onPressed: () {
-            myProvider.toggleShowConflicts();
-          },
         ),
-      ];
+        onPressed: () => GameUtils.showTip(myProvider),
+      ));
+      menuActions.add(const Spacer());
+      menuActions.add(TextButton(
+        child: Container(
+          decoration: BoxDecoration(
+            borderRadius: BorderRadius.circular(4),
+            border: Border.all(
+              color: myProvider.showConflicts ? Colors.blue : Colors.white,
+              width: 3,
+            ),
+          ),
+          child: const Image(
+            image: AssetImage('assets/icons/button_show_conflicts.png'),
+            fit: BoxFit.fill,
+          ),
+        ),
+        onPressed: () {
+          myProvider.toggleShowConflicts();
+        },
+      ));
     }
 
     return Scaffold(
diff --git a/lib/utils/board_animate.dart b/lib/utils/board_animate.dart
index ff8e1e6..e3f7a93 100644
--- a/lib/utils/board_animate.dart
+++ b/lib/utils/board_animate.dart
@@ -1,20 +1,20 @@
 import 'dart:async';
 
-import '../provider/data.dart';
+import 'package:sudoku/provider/data.dart';
 
 class BoardAnimate {
   // Start game animation: blinking tiles
-  static List createStartGameAnimationPatterns(Data myProvider) {
-    List<List> patterns = [];
+  static List<List<List<bool>>> createStartGameAnimationPatterns(Data myProvider) {
+    List<List<List<bool>>> patterns = [];
 
     int patternsCount = 3;
     int boardSideLength = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
 
-    for (var patternIndex = 0; patternIndex < patternsCount; patternIndex++) {
-      List<List> pattern = [];
-      for (var row = 0; row < boardSideLength; row++) {
+    for (int patternIndex = 0; patternIndex < patternsCount; patternIndex++) {
+      List<List<bool>> pattern = [];
+      for (int row = 0; row < boardSideLength; row++) {
         List<bool> patternRow = [];
-        for (var col = 0; col < boardSideLength; col++) {
+        for (int col = 0; col < boardSideLength; col++) {
           patternRow.add(((patternIndex + row + col) % 2 == 0));
         }
         pattern.add(patternRow);
@@ -26,17 +26,17 @@ class BoardAnimate {
   }
 
   // Win game animation: fill board with colored rows, from bottom to top
-  static List createWinGameAnimationPatterns(Data myProvider) {
-    List<List> patterns = [];
+  static List<List<List<bool>>> createWinGameAnimationPatterns(Data myProvider) {
+    List<List<List<bool>>> patterns = [];
 
     int boardSideLength = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
     int patternsCount = boardSideLength + 6;
 
-    for (var patternIndex = 0; patternIndex < patternsCount; patternIndex++) {
-      List<List> pattern = [];
-      for (var row = 0; row < boardSideLength; row++) {
+    for (int patternIndex = 0; patternIndex < patternsCount; patternIndex++) {
+      List<List<bool>> pattern = [];
+      for (int row = 0; row < boardSideLength; row++) {
         List<bool> patternRow = [];
-        for (var col = 0; col < boardSideLength; col++) {
+        for (int col = 0; col < boardSideLength; col++) {
           patternRow.add(row > (patternIndex - 4));
         }
         pattern.add(patternRow);
@@ -48,17 +48,17 @@ class BoardAnimate {
   }
 
   // Default multi-purpose animation: sliding stripes, from top left to right bottom
-  static List createDefaultAnimationPatterns(Data myProvider) {
-    List<List> patterns = [];
+  static List<List<List<bool>>> createDefaultAnimationPatterns(Data myProvider) {
+    List<List<List<bool>>> patterns = [];
 
     int boardSideLength = myProvider.blockSizeHorizontal * myProvider.blockSizeVertical;
     int patternsCount = boardSideLength;
 
-    for (var patternIndex = 0; patternIndex < patternsCount; patternIndex++) {
-      List<List> pattern = [];
-      for (var row = 0; row < boardSideLength; row++) {
+    for (int patternIndex = 0; patternIndex < patternsCount; patternIndex++) {
+      List<List<bool>> pattern = [];
+      for (int row = 0; row < boardSideLength; row++) {
         List<bool> patternRow = [];
-        for (var col = 0; col < boardSideLength; col++) {
+        for (int col = 0; col < boardSideLength; col++) {
           patternRow.add(((patternIndex + row + col) % 4 == 0));
         }
         pattern.add(patternRow);
@@ -70,7 +70,7 @@ class BoardAnimate {
   }
 
   static void startAnimation(Data myProvider, String animationType) {
-    List patterns = [];
+    List<List<List<bool>>> patterns = [];
 
     switch (animationType) {
       case 'start':
@@ -83,21 +83,21 @@ class BoardAnimate {
         patterns = createDefaultAnimationPatterns(myProvider);
     }
 
-    int _patternIndex = patterns.length;
+    int patternIndex = patterns.length;
 
     myProvider.updateAnimationInProgress(true);
 
-    const interval = const Duration(milliseconds: 200);
-    new Timer.periodic(
+    const interval = Duration(milliseconds: 200);
+    Timer.periodic(
       interval,
       (Timer timer) {
-        if (_patternIndex == 0) {
+        if (patternIndex == 0) {
           timer.cancel();
           myProvider.resetAnimatedBackground();
           myProvider.updateAnimationInProgress(false);
         } else {
-          _patternIndex--;
-          myProvider.setAnimatedBackground(patterns[_patternIndex]);
+          patternIndex--;
+          myProvider.setAnimatedBackground(patterns[patternIndex]);
         }
       },
     );
diff --git a/lib/utils/board_utils.dart b/lib/utils/board_utils.dart
index 867301b..e1f5fdf 100644
--- a/lib/utils/board_utils.dart
+++ b/lib/utils/board_utils.dart
@@ -1,22 +1,22 @@
 import 'dart:math';
 
-import '../entities/cell.dart';
-import '../provider/data.dart';
-import '../utils/random_pick_grid.dart';
+import 'package:sudoku/entities/cell.dart';
+import 'package:sudoku/provider/data.dart';
+import 'package:sudoku/utils/random_pick_grid.dart';
 
 class BoardUtils {
-  static printGrid(List cells, List solvedCells) {
+  static printGrid(List<List<Cell>> cells, List<List<Cell>> solvedCells) {
     String stringValues = '0123456789ABCDEFG';
     print('');
     print('-------');
-    for (var rowIndex = 0; rowIndex < cells.length; rowIndex++) {
+    for (int rowIndex = 0; rowIndex < cells.length; rowIndex++) {
       String row = '';
       String rowSolved = '';
-      for (var colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
+      for (int colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
         row += stringValues[cells[rowIndex][colIndex].value];
         rowSolved += stringValues[solvedCells[rowIndex][colIndex].value];
       }
-      print(row + ' | ' + rowSolved);
+      print('$row | $rowSolved');
     }
     print('-------');
     print('');
@@ -31,11 +31,11 @@ class BoardUtils {
 
     grid = randomPickGrid.grid;
 
-    int blockSizeHorizontal = myProvider.blockSizeHorizontal;
-    int blockSizeVertical = myProvider.blockSizeVertical;
+    final int blockSizeHorizontal = myProvider.blockSizeHorizontal;
+    final int blockSizeVertical = myProvider.blockSizeVertical;
 
     if (grid.length == pow(blockSizeHorizontal * blockSizeVertical, 2)) {
-      print('Picked grid from template: ' + grid);
+      print('Picked grid from template: $grid');
       bool isSymetric = (blockSizeHorizontal == blockSizeVertical);
       myProvider.updateCells(BoardUtils.createBoardFromTemplate(grid, isSymetric));
       myProvider.updateCellsSolved(BoardUtils.getSolvedGrid(myProvider));
@@ -45,11 +45,11 @@ class BoardUtils {
     }
   }
 
-  static List createEmptyBoard(int boardSize) {
-    List cells = [];
-    for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-      List row = [];
-      for (var colIndex = 0; colIndex < boardSize; colIndex++) {
+  static List<List<Cell>> createEmptyBoard(final int boardSize) {
+    final List<List<Cell>> cells = [];
+    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+      final List<Cell> row = [];
+      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
         row.add(Cell(0, false));
       }
       cells.add(row);
@@ -58,21 +58,21 @@ 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));
+  static List<List<Cell>> createBoardFromSavedState(Data myProvider, String savedBoard) {
+    final List<List<Cell>> cells = [];
+    final int boardSize = int.parse(pow((savedBoard.length / 2), 1 / 2).toStringAsFixed(0));
 
-    String stringValues = '0123456789ABCDEFG';
+    const 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);
+    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+      final List<Cell> row = [];
+      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
+        final String stringValue = savedBoard[index++];
+        final int value = stringValues.indexOf(stringValue);
 
-        String isFixedString = savedBoard[index++];
-        bool isFixed = (isFixedString != ' ');
+        final String isFixedString = savedBoard[index++];
+        final bool isFixed = (isFixedString != ' ');
 
         row.add(Cell(value, isFixed));
       }
@@ -82,11 +82,11 @@ class BoardUtils {
     return cells;
   }
 
-  static List copyBoard(List cells) {
-    List copiedGrid = [];
-    for (var rowIndex = 0; rowIndex < cells.length; rowIndex++) {
-      List row = [];
-      for (var colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
+  static List<List<Cell>> copyBoard(List cells) {
+    final List<List<Cell>> copiedGrid = [];
+    for (int rowIndex = 0; rowIndex < cells.length; rowIndex++) {
+      final List<Cell> row = [];
+      for (int colIndex = 0; colIndex < cells[rowIndex].length; colIndex++) {
         row.add(Cell(cells[rowIndex][colIndex].value, false));
       }
       copiedGrid.add(row);
@@ -95,24 +95,24 @@ class BoardUtils {
     return copiedGrid;
   }
 
-  static List createBoardFromTemplate(String grid, bool isSymetric) {
-    List cells = [];
-    int boardSize = int.parse(pow(grid.length, 1 / 2).toStringAsFixed(0));
+  static List<List<Cell>> createBoardFromTemplate(String grid, bool isSymetric) {
+    List<List<Cell>> cells = [];
+    final int boardSize = int.parse(pow(grid.length, 1 / 2).toStringAsFixed(0));
 
-    String stringValues = '0123456789ABCDEFG';
+    const String stringValues = '0123456789ABCDEFG';
 
     int index = 0;
-    for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-      List row = [];
-      for (var colIndex = 0; colIndex < boardSize; colIndex++) {
-        String stringValue = grid[index++];
-        int value = stringValues.indexOf(stringValue);
+    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+      final List<Cell> row = [];
+      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
+        final String stringValue = grid[index++];
+        final int value = stringValues.indexOf(stringValue);
         row.add(Cell(value, (value != 0)));
       }
       cells.add(row);
     }
 
-    List<String> allowedFlip = ['none', 'horizontal', 'vertical'];
+    const List<String> allowedFlip = ['none', 'horizontal', 'vertical'];
     List<String> allowedRotate = ['none', 'left', 'right'];
 
     // Forbid rotation if blocks are not symetric
@@ -120,19 +120,19 @@ class BoardUtils {
       allowedRotate = ['none'];
     }
 
-    var rand = new Random();
-    String flip = allowedFlip[rand.nextInt(allowedFlip.length)];
-    String rotate = allowedRotate[rand.nextInt(allowedRotate.length)];
+    final Random rand = Random();
+    final String flip = allowedFlip[rand.nextInt(allowedFlip.length)];
+    final String rotate = allowedRotate[rand.nextInt(allowedRotate.length)];
 
-    print('flip board: ' + flip);
-    print('rotate board: ' + rotate);
+    print('flip board: $flip');
+    print('rotate board: $rotate');
 
     switch (flip) {
       case 'horizontal':
         {
-          List transformedBoard = createEmptyBoard(boardSize);
-          for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-            for (var colIndex = 0; colIndex < boardSize; colIndex++) {
+          final List<List<Cell>> transformedBoard = createEmptyBoard(boardSize);
+          for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+            for (int colIndex = 0; colIndex < boardSize; colIndex++) {
               transformedBoard[rowIndex][colIndex].value =
                   cells[boardSize - rowIndex - 1][colIndex].value;
             }
@@ -142,9 +142,9 @@ class BoardUtils {
         break;
       case 'vertical':
         {
-          List transformedBoard = createEmptyBoard(boardSize);
-          for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-            for (var colIndex = 0; colIndex < boardSize; colIndex++) {
+          final List<List<Cell>> transformedBoard = createEmptyBoard(boardSize);
+          for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+            for (int colIndex = 0; colIndex < boardSize; colIndex++) {
               transformedBoard[rowIndex][colIndex].value =
                   cells[rowIndex][boardSize - colIndex - 1].value;
             }
@@ -157,9 +157,9 @@ class BoardUtils {
     switch (rotate) {
       case 'left':
         {
-          List transformedBoard = createEmptyBoard(boardSize);
-          for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-            for (var colIndex = 0; colIndex < boardSize; colIndex++) {
+          final List<List<Cell>> transformedBoard = createEmptyBoard(boardSize);
+          for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+            for (int colIndex = 0; colIndex < boardSize; colIndex++) {
               transformedBoard[rowIndex][colIndex].value =
                   cells[colIndex][boardSize - rowIndex - 1].value;
             }
@@ -169,9 +169,9 @@ class BoardUtils {
         break;
       case 'right':
         {
-          List transformedBoard = createEmptyBoard(boardSize);
-          for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-            for (var colIndex = 0; colIndex < boardSize; colIndex++) {
+          final List<List<Cell>> transformedBoard = createEmptyBoard(boardSize);
+          for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+            for (int colIndex = 0; colIndex < boardSize; colIndex++) {
               transformedBoard[rowIndex][colIndex].value =
                   cells[boardSize - colIndex - 1][rowIndex].value;
             }
@@ -182,8 +182,8 @@ class BoardUtils {
     }
 
     // Fix cells fixed states
-    for (var rowIndex = 0; rowIndex < boardSize; rowIndex++) {
-      for (var colIndex = 0; colIndex < boardSize; colIndex++) {
+    for (int rowIndex = 0; rowIndex < boardSize; rowIndex++) {
+      for (int colIndex = 0; colIndex < boardSize; colIndex++) {
         cells[rowIndex][colIndex].isFixed =
             (cells[rowIndex][colIndex].value != 0) ? true : false;
       }
@@ -193,19 +193,19 @@ class BoardUtils {
   }
 
   static bool checkBoardIsSolved(Data myProvider) {
-    List cells = myProvider.cells;
+    final List<List<Cell>> cells = myProvider.cells;
 
-    int blockSizeHorizontal = myProvider.blockSizeHorizontal;
-    int blockSizeVertical = myProvider.blockSizeVertical;
+    final int blockSizeHorizontal = myProvider.blockSizeHorizontal;
+    final int blockSizeVertical = myProvider.blockSizeVertical;
 
-    int boardSize = blockSizeHorizontal * blockSizeVertical;
+    final int boardSize = blockSizeHorizontal * blockSizeVertical;
 
     // (re)compute conflicts
     BoardUtils.computeConflictsInBoard(myProvider);
 
     // check grid is fully completed and does not contain conflict
-    for (var row = 0; row < boardSize; row++) {
-      for (var col = 0; col < boardSize; col++) {
+    for (int row = 0; row < boardSize; row++) {
+      for (int col = 0; col < boardSize; col++) {
         if (cells[row][col].value == 0 || cells[row][col].conflictsCount != 0) {
           return false;
         }
@@ -217,18 +217,24 @@ class BoardUtils {
     return true;
   }
 
-  static bool isValueAllowed(List cells, int blockSizeHorizontal, int blockSizeVertical,
-      int? candidateCol, int? candidateRow, int candidateValue) {
+  static bool isValueAllowed(
+    List<List<Cell>> cells,
+    int blockSizeHorizontal,
+    int blockSizeVertical,
+    int? candidateCol,
+    int? candidateRow,
+    int candidateValue,
+  ) {
     if ((candidateCol == null) || (candidateRow == null) || (candidateValue == 0)) {
       return true;
     }
 
-    int boardSize = blockSizeHorizontal * blockSizeVertical;
+    final int boardSize = blockSizeHorizontal * blockSizeVertical;
 
     // check lines does not contains a value twice
-    for (var row = 0; row < boardSize; row++) {
-      List values = [];
-      for (var col = 0; col < boardSize; col++) {
+    for (int row = 0; row < boardSize; row++) {
+      final List<int> values = [];
+      for (int col = 0; col < boardSize; col++) {
         int value = cells[row][col].value;
         if (row == candidateRow && col == candidateCol) {
           value = candidateValue;
@@ -237,16 +243,16 @@ class BoardUtils {
           values.add(value);
         }
       }
-      List distinctValues = values.toSet().toList();
+      final List<int> distinctValues = values.toSet().toList();
       if (values.length != distinctValues.length) {
         return false;
       }
     }
 
     // check columns does not contains a value twice
-    for (var col = 0; col < boardSize; col++) {
-      List values = [];
-      for (var row = 0; row < boardSize; row++) {
+    for (int col = 0; col < boardSize; col++) {
+      final List<int> values = [];
+      for (int row = 0; row < boardSize; row++) {
         int value = cells[row][col].value;
         if (row == candidateRow && col == candidateCol) {
           value = candidateValue;
@@ -255,23 +261,23 @@ class BoardUtils {
           values.add(value);
         }
       }
-      List distinctValues = values.toSet().toList();
+      final List<int> distinctValues = values.toSet().toList();
       if (values.length != distinctValues.length) {
         return false;
       }
     }
 
     // check blocks does not contains a value twice
-    int horizontalBlocksCount = blockSizeVertical;
-    int verticalBlocksCount = blockSizeHorizontal;
-    for (var blockRow = 0; blockRow < verticalBlocksCount; blockRow++) {
-      for (var blockCol = 0; blockCol < horizontalBlocksCount; blockCol++) {
-        List values = [];
-
-        for (var rowInBlock = 0; rowInBlock < blockSizeVertical; rowInBlock++) {
-          for (var colInBlock = 0; colInBlock < blockSizeHorizontal; colInBlock++) {
-            int row = (blockRow * blockSizeVertical) + rowInBlock;
-            int col = (blockCol * blockSizeHorizontal) + colInBlock;
+    final int horizontalBlocksCount = blockSizeVertical;
+    final int verticalBlocksCount = blockSizeHorizontal;
+    for (int blockRow = 0; blockRow < verticalBlocksCount; blockRow++) {
+      for (int blockCol = 0; blockCol < horizontalBlocksCount; blockCol++) {
+        final List<int> values = [];
+
+        for (int rowInBlock = 0; rowInBlock < blockSizeVertical; rowInBlock++) {
+          for (int colInBlock = 0; colInBlock < blockSizeHorizontal; colInBlock++) {
+            final int row = (blockRow * blockSizeVertical) + rowInBlock;
+            final int col = (blockCol * blockSizeHorizontal) + colInBlock;
             int value = cells[row][col].value;
             if (row == candidateRow && col == candidateCol) {
               value = candidateValue;
@@ -282,7 +288,7 @@ class BoardUtils {
           }
         }
 
-        List distinctValues = values.toSet().toList();
+        final List<int> distinctValues = values.toSet().toList();
         if (values.length != distinctValues.length) {
           return false;
         }
@@ -293,67 +299,67 @@ class BoardUtils {
   }
 
   static void computeConflictsInBoard(Data myProvider) {
-    List cells = myProvider.cells;
+    final List<List<Cell>> cells = myProvider.cells;
 
-    int blockSizeHorizontal = myProvider.blockSizeHorizontal;
-    int blockSizeVertical = myProvider.blockSizeVertical;
+    final int blockSizeHorizontal = myProvider.blockSizeHorizontal;
+    final int blockSizeVertical = myProvider.blockSizeVertical;
 
-    int boardSize = blockSizeHorizontal * blockSizeVertical;
+    final int boardSize = blockSizeHorizontal * blockSizeVertical;
 
     // reset conflict states
-    for (var row = 0; row < boardSize; row++) {
-      for (var col = 0; col < boardSize; col++) {
+    for (int row = 0; row < boardSize; row++) {
+      for (int col = 0; col < boardSize; col++) {
         cells[row][col].conflictsCount = 0;
       }
     }
 
     // check lines does not contains a value twice
-    for (var row = 0; row < boardSize; row++) {
-      List values = [];
-      for (var col = 0; col < boardSize; col++) {
+    for (int row = 0; row < boardSize; row++) {
+      final List<int> values = [];
+      for (int col = 0; col < boardSize; col++) {
         int value = cells[row][col].value;
         if (value != 0) {
           values.add(value);
         }
       }
-      List distinctValues = values.toSet().toList();
+      final List<int> distinctValues = values.toSet().toList();
       if (values.length != distinctValues.length) {
-        print('line ' + row.toString() + ' contains duplicates');
+        print('line $row contains duplicates');
         // Add line to cells in conflict
-        for (var col = 0; col < boardSize; col++) {
+        for (int col = 0; col < boardSize; col++) {
           cells[row][col].conflictsCount++;
         }
       }
     }
 
     // check columns does not contains a value twice
-    for (var col = 0; col < boardSize; col++) {
-      List values = [];
-      for (var row = 0; row < boardSize; row++) {
+    for (int col = 0; col < boardSize; col++) {
+      final List<int> values = [];
+      for (int row = 0; row < boardSize; row++) {
         int value = cells[row][col].value;
         if (value != 0) {
           values.add(value);
         }
       }
-      List distinctValues = values.toSet().toList();
+      final List<int> distinctValues = values.toSet().toList();
       if (values.length != distinctValues.length) {
-        print('column ' + col.toString() + ' contains duplicates');
+        print('column $col contains duplicates');
         // Add column to cells in conflict
-        for (var row = 0; row < boardSize; row++) {
+        for (int row = 0; row < boardSize; row++) {
           cells[row][col].conflictsCount++;
         }
       }
     }
 
     // check blocks does not contains a value twice
-    int horizontalBlocksCount = blockSizeVertical;
-    int verticalBlocksCount = blockSizeHorizontal;
-    for (var blockRow = 0; blockRow < verticalBlocksCount; blockRow++) {
-      for (var blockCol = 0; blockCol < horizontalBlocksCount; blockCol++) {
-        List values = [];
-
-        for (var rowInBlock = 0; rowInBlock < blockSizeVertical; rowInBlock++) {
-          for (var colInBlock = 0; colInBlock < blockSizeHorizontal; colInBlock++) {
+    final int horizontalBlocksCount = blockSizeVertical;
+    final int verticalBlocksCount = blockSizeHorizontal;
+    for (int blockRow = 0; blockRow < verticalBlocksCount; blockRow++) {
+      for (int blockCol = 0; blockCol < horizontalBlocksCount; blockCol++) {
+        List<int> values = [];
+
+        for (int rowInBlock = 0; rowInBlock < blockSizeVertical; rowInBlock++) {
+          for (int colInBlock = 0; colInBlock < blockSizeHorizontal; colInBlock++) {
             int row = (blockRow * blockSizeVertical) + rowInBlock;
             int col = (blockCol * blockSizeHorizontal) + colInBlock;
             int value = cells[row][col].value;
@@ -363,16 +369,12 @@ class BoardUtils {
           }
         }
 
-        List distinctValues = values.toSet().toList();
+        List<int> distinctValues = values.toSet().toList();
         if (values.length != distinctValues.length) {
-          print('block [' +
-              blockCol.toString() +
-              ',' +
-              blockRow.toString() +
-              '] contains duplicates');
+          print('block [$blockCol,$blockRow] contains duplicates');
           // Add blocks to cells in conflict
-          for (var rowInBlock = 0; rowInBlock < blockSizeVertical; rowInBlock++) {
-            for (var colInBlock = 0; colInBlock < blockSizeHorizontal; colInBlock++) {
+          for (int rowInBlock = 0; rowInBlock < blockSizeVertical; rowInBlock++) {
+            for (int colInBlock = 0; colInBlock < blockSizeHorizontal; colInBlock++) {
               int row = (blockRow * blockSizeVertical) + rowInBlock;
               int col = (blockCol * blockSizeHorizontal) + colInBlock;
               cells[row][col].conflictsCount++;
@@ -383,13 +385,17 @@ class BoardUtils {
     }
   }
 
-  static List getCellsWithWrongValue(
-      List cells, List cellsSolved, int blockSizeHorizontal, int blockSizeVertical) {
-    List cellsWithWrongValue = [];
-    int boardSize = blockSizeHorizontal * blockSizeVertical;
-
-    for (var row = 0; row < boardSize; row++) {
-      for (var col = 0; col < boardSize; col++) {
+  static List<List<int>> getCellsWithWrongValue(
+    final List<List<Cell>> cells,
+    final List<List<Cell>> cellsSolved,
+    final int blockSizeHorizontal,
+    final int blockSizeVertical,
+  ) {
+    final List<List<int>> cellsWithWrongValue = [];
+    final int boardSize = blockSizeHorizontal * blockSizeVertical;
+
+    for (int row = 0; row < boardSize; row++) {
+      for (int col = 0; col < boardSize; col++) {
         if (cells[row][col].value != 0 &&
             cells[row][col].value != cellsSolved[row][col].value) {
           cellsWithWrongValue.add([col, row]);
@@ -400,12 +406,16 @@ class BoardUtils {
     return cellsWithWrongValue;
   }
 
-  static List getConflictingCells(List cells, int blockSizeHorizontal, int blockSizeVertical) {
-    List conflictingCells = [];
-    int boardSize = blockSizeHorizontal * blockSizeVertical;
+  static List<List<int>> getConflictingCells(
+    final List<List<Cell>> cells,
+    final int blockSizeHorizontal,
+    final int blockSizeVertical,
+  ) {
+    final List<List<int>> conflictingCells = [];
+    final int boardSize = blockSizeHorizontal * blockSizeVertical;
 
-    for (var row = 0; row < boardSize; row++) {
-      for (var col = 0; col < boardSize; col++) {
+    for (int row = 0; row < boardSize; row++) {
+      for (int col = 0; col < boardSize; col++) {
         if (!cells[row][col].isFixed && cells[row][col].value != 0) {
           if (cells[row][col].conflictsCount != 0 &&
               !BoardUtils.isValueAllowed(cells, blockSizeHorizontal, blockSizeVertical, col,
@@ -419,17 +429,20 @@ class BoardUtils {
     return conflictingCells;
   }
 
-  static List getCellsWithUniqueAvailableValue(
-      List cells, int blockSizeHorizontal, int blockSizeVertical) {
-    List candidateCells = [];
-    int boardSize = blockSizeHorizontal * blockSizeVertical;
+  static List<List<int>> getCellsWithUniqueAvailableValue(
+    List<List<Cell>> cells,
+    final int blockSizeHorizontal,
+    final int blockSizeVertical,
+  ) {
+    final List<List<int>> candidateCells = [];
+    final int boardSize = blockSizeHorizontal * blockSizeVertical;
 
-    for (var row = 0; row < boardSize; row++) {
-      for (var col = 0; col < boardSize; col++) {
+    for (int row = 0; row < boardSize; row++) {
+      for (int col = 0; col < boardSize; col++) {
         if (cells[row][col].value == 0) {
           int allowedValuesCount = 0;
           int candidateValue = 0;
-          for (var value = 1; value <= boardSize; value++) {
+          for (int value = 1; value <= boardSize; value++) {
             if (BoardUtils.isValueAllowed(
                 cells, blockSizeHorizontal, blockSizeVertical, col, row, value)) {
               candidateValue = value;
@@ -446,18 +459,22 @@ class BoardUtils {
     return candidateCells;
   }
 
-  static List getSolvedGrid(Data myProvider) {
-    List cells = copyBoard(myProvider.cells);
-    int blockSizeHorizontal = myProvider.blockSizeHorizontal;
+  static List<List<Cell>> getSolvedGrid(Data myProvider) {
+    final List<List<Cell>> cells = copyBoard(myProvider.cells);
+    final int blockSizeHorizontal = myProvider.blockSizeHorizontal;
     int blockSizeVertical = myProvider.blockSizeVertical;
 
     do {
-      List cellsWithUniqueAvailableValue = BoardUtils.getCellsWithUniqueAvailableValue(
-          cells, blockSizeHorizontal, blockSizeVertical);
-      if (cellsWithUniqueAvailableValue.length == 0) {
+      List<List<int>> cellsWithUniqueAvailableValue =
+          BoardUtils.getCellsWithUniqueAvailableValue(
+        cells,
+        blockSizeHorizontal,
+        blockSizeVertical,
+      );
+      if (cellsWithUniqueAvailableValue.isEmpty) {
         break;
       }
-      for (var i = 0; i < cellsWithUniqueAvailableValue.length; i++) {
+      for (int i = 0; i < cellsWithUniqueAvailableValue.length; i++) {
         int col = cellsWithUniqueAvailableValue[i][0];
         int row = cellsWithUniqueAvailableValue[i][1];
         int value = cellsWithUniqueAvailableValue[i][2];
diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart
index 77ba0da..8ec4f38 100644
--- a/lib/utils/game_utils.dart
+++ b/lib/utils/game_utils.dart
@@ -1,6 +1,7 @@
-import '../provider/data.dart';
-import '../utils/board_animate.dart';
-import '../utils/board_utils.dart';
+import 'package:sudoku/entities/cell.dart';
+import 'package:sudoku/provider/data.dart';
+import 'package:sudoku/utils/board_animate.dart';
+import 'package:sudoku/utils/board_utils.dart';
 
 class GameUtils {
   static Future<void> quitGame(Data myProvider) async {
@@ -26,7 +27,7 @@ class GameUtils {
   }
 
   static void resumeSavedGame(Data myProvider) {
-    Map<String, dynamic> savedState = myProvider.getCurrentSavedState();
+    final Map<String, dynamic> savedState = myProvider.getCurrentSavedState();
     if (savedState.isNotEmpty) {
       try {
         myProvider.setParameterValue('level', savedState['level']);
@@ -66,56 +67,66 @@ class GameUtils {
   }
 
   static void helpSelectCell(Data myProvider) {
-    List cells = myProvider.cells;
-    int blockSizeHorizontal = myProvider.blockSizeHorizontal;
-    int blockSizeVertical = myProvider.blockSizeVertical;
+    final List<List<Cell>> cells = myProvider.cells;
+    final int blockSizeHorizontal = myProvider.blockSizeHorizontal;
+    final int blockSizeVertical = myProvider.blockSizeVertical;
 
     // pick one of wrong value cells, if found
-    List wrongValueCells = BoardUtils.getCellsWithWrongValue(
-        cells, myProvider.cellsSolved, blockSizeHorizontal, blockSizeVertical);
-    if (wrongValueCells.length != 0) {
+    final List<List<int>> wrongValueCells = BoardUtils.getCellsWithWrongValue(
+      cells,
+      myProvider.cellsSolved,
+      blockSizeHorizontal,
+      blockSizeVertical,
+    );
+    if (wrongValueCells.isNotEmpty) {
       GameUtils.pickRandomFromList(myProvider, wrongValueCells);
       return;
     }
 
     // pick one of conflicting cells, if found
-    List conflictingCells = BoardUtils.getCellsWithUniqueAvailableValue(
-        cells, blockSizeHorizontal, blockSizeVertical);
-    if (conflictingCells.length != 0) {
+    final List<List<int>> conflictingCells = BoardUtils.getCellsWithUniqueAvailableValue(
+      cells,
+      blockSizeHorizontal,
+      blockSizeVertical,
+    );
+    if (conflictingCells.isNotEmpty) {
       GameUtils.pickRandomFromList(myProvider, conflictingCells);
       return;
     }
 
     //  pick one form cells with unique non-conflicting candidate value
-    List candidateCells = BoardUtils.getCellsWithUniqueAvailableValue(
-        cells, blockSizeHorizontal, blockSizeVertical);
-    if (candidateCells.length != 0) {
+    final List<List<int>> candidateCells = BoardUtils.getCellsWithUniqueAvailableValue(
+      cells,
+      blockSizeHorizontal,
+      blockSizeVertical,
+    );
+    if (candidateCells.isNotEmpty) {
       GameUtils.pickRandomFromList(myProvider, candidateCells);
       return;
     }
   }
 
-  static void pickRandomFromList(Data myProvider, List cellsCoordinates) {
-    if (cellsCoordinates.length > 0) {
+  static void pickRandomFromList(Data myProvider, List<List<int>> cellsCoordinates) {
+    if (cellsCoordinates.isNotEmpty) {
       cellsCoordinates.shuffle();
-      List cell = cellsCoordinates[0];
+      List<int> cell = cellsCoordinates[0];
       myProvider.selectCell(cell[0], cell[1]);
     }
   }
 
   static void helpFillCell(Data myProvider) {
-    List cells = myProvider.cells;
-    int blockSizeHorizontal = myProvider.blockSizeHorizontal;
-    int blockSizeVertical = myProvider.blockSizeVertical;
+    final List<List<Cell>> cells = myProvider.cells;
+    final int blockSizeHorizontal = myProvider.blockSizeHorizontal;
+    final int blockSizeVertical = myProvider.blockSizeVertical;
 
-    int boardSize = blockSizeHorizontal * blockSizeVertical;
+    final int boardSize = blockSizeHorizontal * blockSizeVertical;
 
     // Will clean cell if no eligible value found
     int eligibleValue = 0;
 
     // ensure there is only one eligible value for this cell
     int allowedValuesCount = 0;
-    for (var value = 1; value <= boardSize; value++) {
+    for (int value = 1; value <= boardSize; value++) {
       if (BoardUtils.isValueAllowed(cells, blockSizeHorizontal, blockSizeVertical,
           myProvider.currentCellCol, myProvider.currentCellRow, value)) {
         allowedValuesCount++;
diff --git a/lib/utils/random_pick_grid.dart b/lib/utils/random_pick_grid.dart
index 67c55a2..903899f 100644
--- a/lib/utils/random_pick_grid.dart
+++ b/lib/utils/random_pick_grid.dart
@@ -23,8 +23,8 @@ class RandomPickGrid {
     }
 
     // Check we have enough grids
-    if (grids.length < 1) {
-      print('Not enough grids [' + size + ', ' + level + '] in templates.');
+    if (grids.isEmpty) {
+      print('Not enough grids [$size, $level] in templates.');
     }
 
     // Randomize grids list
diff --git a/pubspec.lock b/pubspec.lock
index 421b598..2abbf2c 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -29,52 +29,68 @@ packages:
     dependency: transitive
     description:
       name: collection
-      sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
+      sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a
       url: "https://pub.dev"
     source: hosted
-    version: "1.17.2"
+    version: "1.18.0"
   ffi:
     dependency: transitive
     description:
       name: ffi
-      sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878"
+      sha256: "493f37e7df1804778ff3a53bd691d8692ddf69702cf4c1c1096a2e41b4779e21"
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.0"
+    version: "2.1.2"
   file:
     dependency: transitive
     description:
       name: file
-      sha256: "1b92bec4fc2a72f59a8e15af5f52cd441e4a7860b49499d69dfa817af20e925d"
+      sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c"
       url: "https://pub.dev"
     source: hosted
-    version: "6.1.4"
+    version: "7.0.0"
   flutter:
     dependency: "direct main"
     description: flutter
     source: sdk
     version: "0.0.0"
+  flutter_lints:
+    dependency: "direct dev"
+    description:
+      name: flutter_lints
+      sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.1"
   flutter_web_plugins:
     dependency: transitive
     description: flutter
     source: sdk
     version: "0.0.0"
+  lints:
+    dependency: transitive
+    description:
+      name: lints
+      sha256: cbf8d4b858bb0134ef3ef87841abdf8d63bfc255c266b7bf6b39daa1085c4290
+      url: "https://pub.dev"
+    source: hosted
+    version: "3.0.0"
   material_color_utilities:
     dependency: transitive
     description:
       name: material_color_utilities
-      sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
+      sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a"
       url: "https://pub.dev"
     source: hosted
-    version: "0.5.0"
+    version: "0.8.0"
   meta:
     dependency: transitive
     description:
       name: meta
-      sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
+      sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04
       url: "https://pub.dev"
     source: hosted
-    version: "1.9.1"
+    version: "1.11.0"
   nested:
     dependency: transitive
     description:
@@ -95,10 +111,10 @@ packages:
     dependency: transitive
     description:
       name: path
-      sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
+      sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
       url: "https://pub.dev"
     source: hosted
-    version: "1.8.3"
+    version: "1.9.0"
   path_provider_linux:
     dependency: transitive
     description:
@@ -111,10 +127,10 @@ packages:
     dependency: transitive
     description:
       name: path_provider_platform_interface
-      sha256: "94b1e0dd80970c1ce43d5d4e050a9918fce4f4a775e6142424c30a29a363265c"
+      sha256: "88f5779f72ba699763fa3a3b06aa4bf6de76c8e5de842cf6f29e2e06476c2334"
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.1"
+    version: "2.1.2"
   path_provider_windows:
     dependency: transitive
     description:
@@ -127,34 +143,34 @@ packages:
     dependency: transitive
     description:
       name: platform
-      sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102
+      sha256: "12220bb4b65720483f8fa9450b4332347737cf8213dd2840d8b2c823e47243ec"
       url: "https://pub.dev"
     source: hosted
-    version: "3.1.2"
+    version: "3.1.4"
   plugin_platform_interface:
     dependency: transitive
     description:
       name: plugin_platform_interface
-      sha256: da3fdfeccc4d4ff2da8f8c556704c08f912542c5fb3cf2233ed75372384a034d
+      sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02"
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.6"
+    version: "2.1.8"
   provider:
     dependency: "direct main"
     description:
       name: provider
-      sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
+      sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096"
       url: "https://pub.dev"
     source: hosted
-    version: "6.0.5"
+    version: "6.1.1"
   shared_preferences:
     dependency: "direct main"
     description:
       name: shared_preferences
-      sha256: b7f41bad7e521d205998772545de63ff4e6c97714775902c199353f8bf1511ac
+      sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.1"
+    version: "2.2.2"
   shared_preferences_android:
     dependency: transitive
     description:
@@ -167,42 +183,42 @@ packages:
     dependency: transitive
     description:
       name: shared_preferences_foundation
-      sha256: "7bf53a9f2d007329ee6f3df7268fd498f8373602f943c975598bbb34649b62a7"
+      sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.4"
+    version: "2.3.5"
   shared_preferences_linux:
     dependency: transitive
     description:
       name: shared_preferences_linux
-      sha256: c2eb5bf57a2fe9ad6988121609e47d3e07bb3bdca5b6f8444e4cf302428a128a
+      sha256: "9f2cbcf46d4270ea8be39fa156d86379077c8a5228d9dfdb1164ae0bb93f1faa"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.1"
+    version: "2.3.2"
   shared_preferences_platform_interface:
     dependency: transitive
     description:
       name: shared_preferences_platform_interface
-      sha256: d4ec5fc9ebb2f2e056c617112aa75dcf92fc2e4faaf2ae999caa297473f75d8a
+      sha256: "22e2ecac9419b4246d7c22bfbbda589e3acf5c0351137d87dd2939d984d37c3b"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.1"
+    version: "2.3.2"
   shared_preferences_web:
     dependency: transitive
     description:
       name: shared_preferences_web
-      sha256: d762709c2bbe80626ecc819143013cc820fa49ca5e363620ee20a8b15a3e3daf
+      sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.1"
+    version: "2.3.0"
   shared_preferences_windows:
     dependency: transitive
     description:
       name: shared_preferences_windows
-      sha256: f763a101313bd3be87edffe0560037500967de9c394a714cd598d945517f694f
+      sha256: "841ad54f3c8381c480d0c9b508b89a34036f512482c407e6df7a9c4aa2ef8f59"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.1"
+    version: "2.3.2"
   sky_engine:
     dependency: transitive
     description: flutter
@@ -220,26 +236,26 @@ packages:
     dependency: transitive
     description:
       name: web
-      sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
+      sha256: "1d9158c616048c38f712a6646e317a3426da10e884447626167240d45209cbad"
       url: "https://pub.dev"
     source: hosted
-    version: "0.1.4-beta"
+    version: "0.5.0"
   win32:
     dependency: transitive
     description:
       name: win32
-      sha256: "350a11abd2d1d97e0cc7a28a81b781c08002aa2864d9e3f192ca0ffa18b06ed3"
+      sha256: "464f5674532865248444b4c3daca12bd9bf2d7c47f759ce2617986e7229494a8"
       url: "https://pub.dev"
     source: hosted
-    version: "5.0.9"
+    version: "5.2.0"
   xdg_directories:
     dependency: transitive
     description:
       name: xdg_directories
-      sha256: "589ada45ba9e39405c198fe34eb0f607cddb2108527e658136120892beac46d2"
+      sha256: faea9dee56b520b55a566385b84f2e8de55e7496104adada9962e0bd11bcff1d
       url: "https://pub.dev"
     source: hosted
-    version: "1.0.3"
+    version: "1.0.4"
 sdks:
-  dart: ">=3.1.0-185.0.dev <4.0.0"
-  flutter: ">=3.7.0"
+  dart: ">=3.3.0 <4.0.0"
+  flutter: ">=3.19.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 0a74705..2364986 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,7 +1,7 @@
 name: sudoku
 description: A sudoku game application.
 publish_to: 'none'
-version: 1.0.0+1
+version: 0.1.13+62
 
 environment:
   sdk: '^3.0.0'
@@ -14,6 +14,9 @@ dependencies:
   shared_preferences: ^2.2.1
   overlay_support: ^2.1.0
 
+dev_dependencies:
+  flutter_lints: ^3.0.1
+
 flutter:
   uses-material-design: true
   assets:
-- 
GitLab