From 86188915ece177303978e61fc8cd68db2415d786 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr>
Date: Thu, 11 Jan 2024 23:20:28 +0100
Subject: [PATCH] Clean/improve code

---
 android/gradle.properties                     |   4 +-
 .../metadata/android/en-US/changelogs/58.txt  |   1 +
 .../metadata/android/fr-FR/changelogs/58.txt  |   1 +
 lib/main.dart                                 |  29 +-
 lib/provider/data.dart                        |  30 +-
 lib/screens/game.dart                         | 182 +++++++++++
 lib/screens/game_pick_image.dart              | 257 +++------------
 lib/screens/game_pick_word.dart               | 293 ++++--------------
 lib/screens/home.dart                         |  28 +-
 lib/utils/random_pick_words.dart              |   8 +-
 pubspec.lock                                  |  66 +---
 pubspec.yaml                                  |   3 +-
 12 files changed, 323 insertions(+), 579 deletions(-)
 create mode 100644 fastlane/metadata/android/en-US/changelogs/58.txt
 create mode 100644 fastlane/metadata/android/fr-FR/changelogs/58.txt
 create mode 100644 lib/screens/game.dart

diff --git a/android/gradle.properties b/android/gradle.properties
index ef113c5..b1ac45a 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.33
-app.versionCode=57
+app.versionName=0.1.34
+app.versionCode=58
diff --git a/fastlane/metadata/android/en-US/changelogs/58.txt b/fastlane/metadata/android/en-US/changelogs/58.txt
new file mode 100644
index 0000000..3eec54c
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/58.txt
@@ -0,0 +1 @@
+Improve / clean code.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/58.txt b/fastlane/metadata/android/fr-FR/changelogs/58.txt
new file mode 100644
index 0000000..2ea6899
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/58.txt
@@ -0,0 +1 @@
+AmΓ©liorations / nettoyage de code.
diff --git a/lib/main.dart b/lib/main.dart
index 8f745e2..a8b8d26 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -1,11 +1,11 @@
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
 import 'package:flutter/services.dart';
+import 'package:provider/provider.dart';
 
-import 'provider/data.dart';
-import 'screens/home.dart';
-import 'screens/game_pick_word.dart';
-import 'screens/game_pick_image.dart';
+import 'package:wordguessing/provider/data.dart';
+import 'package:wordguessing/screens/game_pick_image.dart';
+import 'package:wordguessing/screens/game_pick_word.dart';
+import 'package:wordguessing/screens/home.dart';
 
 void main() {
   WidgetsFlutterBinding.ensureInitialized();
@@ -28,24 +28,15 @@ class MyApp extends StatelessWidget {
           onGenerateRoute: (settings) {
             switch (settings.name) {
               case '/game-pick-word':
-                {
-                  return MaterialPageRoute(
-                    builder: (context) => GamePickWordPage(),
-                  );
-                }
+                return MaterialPageRoute(builder: (context) => GamePickWordPage());
 
               case '/game-pick-image':
-                {
-                  return MaterialPageRoute(
-                    builder: (context) => GamePickImagePage(),
-                  );
-                }
+                return MaterialPageRoute(
+                  builder: (context) => GamePickImagePage(),
+                );
 
               default:
-                {
-                  print("Unknown menu entry");
-                }
-                break;
+                print("Unknown menu entry");
             }
 
             return null;
diff --git a/lib/provider/data.dart b/lib/provider/data.dart
index 729b8c8..c5559fd 100644
--- a/lib/provider/data.dart
+++ b/lib/provider/data.dart
@@ -1,4 +1,5 @@
 import 'package:flutter/foundation.dart';
+
 import 'package:wordguessing/models/word.dart';
 
 class Data extends ChangeNotifier {
@@ -19,14 +20,14 @@ class Data extends ChangeNotifier {
 
   String get lang => _lang;
 
-  set updateLang(String value) {
+  void updateLang(String value) {
     _lang = value;
     notifyListeners();
   }
 
   Word? get word => _word;
 
-  set updateWord(Word? newWord) {
+  void updateWord(Word? newWord) {
     _word = newWord;
     if ((newWord != null) && (newWord.key != '')) {
       _recentWordsKeys.insert(0, newWord.key);
@@ -39,47 +40,48 @@ class Data extends ChangeNotifier {
     return _recentWordsKeys.contains(word);
   }
 
-  List get otherWords => _otherWords;
+  List<Word> get otherWords => _otherWords;
 
-  set updateOtherWords(List<Word> words) {
+  void updateOtherWords(List<Word> words) {
     _otherWords = words;
     notifyListeners();
   }
 
   List<Word> get images => _images;
 
-  set updateImages(List<Word> images) {
+  void updateImages(List<Word> images) {
     _images = images;
     notifyListeners();
   }
 
   void resetGame() {
-    _word = null;
-    _otherWords = [];
-    _images = [];
-    _questionsCount = 0;
-    _goodAnswers = 0;
-    _wrongAnswers = 0;
+    updateLang('');
+    updateQuestionsCount(0);
+    updateGoodAnswers(0);
+    updateWrongAnswers(0);
+    updateWord(null);
+    updateOtherWords([]);
+    updateImages([]);
     notifyListeners();
   }
 
   int get questionsCount => _questionsCount;
 
-  set updateQuestionsCount(int value) {
+  void updateQuestionsCount(int value) {
     _questionsCount = value;
     notifyListeners();
   }
 
   int get goodAnswers => _goodAnswers;
 
-  set updateGoodAnswers(int value) {
+  void updateGoodAnswers(int value) {
     _goodAnswers = value;
     notifyListeners();
   }
 
   int get wrongAnswers => _wrongAnswers;
 
-  set updateWrongAnswers(int value) {
+  void updateWrongAnswers(int value) {
     _wrongAnswers = value;
     notifyListeners();
   }
diff --git a/lib/screens/game.dart b/lib/screens/game.dart
new file mode 100644
index 0000000..a887af7
--- /dev/null
+++ b/lib/screens/game.dart
@@ -0,0 +1,182 @@
+import 'package:flutter/material.dart';
+import 'package:provider/provider.dart';
+
+import 'package:wordguessing/provider/data.dart';
+
+class Game extends StatelessWidget {
+  final int countWords = 4;
+
+  Future<void> startGame(Data myProvider, String lang) async {
+    myProvider.resetGame();
+    myProvider.updateLang(lang);
+    await nextWord(myProvider);
+  }
+
+  Future<void> nextWord(Data myProvider) async {
+    await pickData(myProvider);
+    myProvider.updateQuestionsCount(myProvider.questionsCount + 1);
+  }
+
+  Future<void> pickData(Data myProvider) async {}
+
+  Future<void> checkWord(Data myProvider, word) async {
+    if (myProvider.word?.key == word.key) {
+      myProvider.updateGoodAnswers(myProvider.goodAnswers + 1);
+      nextWord(myProvider);
+    } else {
+      myProvider.updateWrongAnswers(myProvider.wrongAnswers + 1);
+    }
+  }
+
+  Widget buildScoreItemContainer(String text, Color blockColor) {
+    // Darken block color to get border color
+    const double amount = 0.2;
+    final hsl = HSLColor.fromColor(blockColor);
+    final hslDark = hsl.withLightness((hsl.lightness - amount).clamp(0.0, 1.0));
+    final Color borderColor = hslDark.toColor();
+
+    return Container(
+      margin: const EdgeInsets.symmetric(horizontal: 15),
+      padding: const EdgeInsets.all(5),
+      decoration: BoxDecoration(
+        color: blockColor,
+        borderRadius: BorderRadius.circular(4),
+        border: Border.all(
+          color: borderColor,
+          width: 4,
+        ),
+      ),
+      child: Text(
+        text,
+        style: TextStyle(
+          fontSize: 25,
+          fontWeight: FontWeight.w600,
+          color: Colors.black,
+        ),
+      ),
+    );
+  }
+
+  String getGoodAnswersString(Data myProvider) {
+    final int count = myProvider.questionsCount - 1;
+    return 'πŸ‘ ' + myProvider.goodAnswers.toString() + '/' + count.toString();
+  }
+
+  String getWrongAnswersString(Data myProvider) {
+    final int count = myProvider.questionsCount - 1;
+    return '🚩 ' + myProvider.wrongAnswers.toString() + '/' + count.toString();
+  }
+
+  Widget buildScoreContainer(Data myProvider) {
+    return Container(
+      padding: const EdgeInsets.all(5),
+      child: Row(
+        mainAxisSize: MainAxisSize.min,
+        mainAxisAlignment: MainAxisAlignment.center,
+        children: [
+          buildScoreItemContainer(
+            getGoodAnswersString(myProvider),
+            Colors.green,
+          ),
+          const SizedBox(width: 20),
+          buildScoreItemContainer(
+            getWrongAnswersString(myProvider),
+            Colors.orange,
+          ),
+        ],
+      ),
+    );
+  }
+
+  Widget buildStartGameBlock(Data myProvider) {
+    return Column(
+      mainAxisSize: MainAxisSize.min,
+      mainAxisAlignment: MainAxisAlignment.center,
+      children: [
+        Container(
+          child: ElevatedButton(
+            style: ElevatedButton.styleFrom(
+              foregroundColor: Colors.teal,
+              backgroundColor: Colors.teal,
+              padding: const EdgeInsets.all(35),
+            ),
+            child: const Text(
+              "πŸ‡«πŸ‡·",
+              style: TextStyle(
+                fontSize: 60,
+                color: Colors.black,
+              ),
+            ),
+            onPressed: () => startGame(myProvider, 'fr'),
+          ),
+        ),
+        const SizedBox(height: 15),
+        Container(
+          child: ElevatedButton(
+            style: ElevatedButton.styleFrom(
+              foregroundColor: Colors.teal,
+              backgroundColor: Colors.teal,
+              padding: const EdgeInsets.all(35),
+            ),
+            child: const Text(
+              "πŸ‡¬πŸ‡§",
+              style: TextStyle(
+                fontSize: 60,
+                color: Colors.black,
+              ),
+            ),
+            onPressed: () => startGame(myProvider, 'en'),
+          ),
+        )
+      ],
+    );
+  }
+
+  List<Widget> buildPageContent(Data myProvider) {
+    return <Widget>[];
+  }
+
+  Widget buildPage(BuildContext context) {
+    final Data myProvider = Provider.of<Data>(context);
+
+    final Scaffold pageContent = Scaffold(
+      appBar: AppBar(
+        elevation: 0,
+        actions: <Widget>[
+          IconButton(
+            icon: const Icon(Icons.loop),
+            onPressed: () => myProvider.resetGame(),
+          ),
+        ],
+      ),
+      backgroundColor: Colors.blue,
+      body: Center(
+        child: Column(
+          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          mainAxisSize: MainAxisSize.max,
+          children: buildPageContent(myProvider),
+        ),
+      ),
+    );
+
+    return SizedBox.expand(
+      child: Container(
+        child: FittedBox(
+          fit: BoxFit.contain,
+          alignment: Alignment.center,
+          child: SizedBox(
+            height: (MediaQuery.of(context).size.height),
+            width: (MediaQuery.of(context).size.width),
+            child: pageContent,
+          ),
+        ),
+      ),
+    );
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return buildPage(context);
+  }
+}
diff --git a/lib/screens/game_pick_image.dart b/lib/screens/game_pick_image.dart
index 857fcff..7f5929e 100644
--- a/lib/screens/game_pick_image.dart
+++ b/lib/screens/game_pick_image.dart
@@ -1,137 +1,40 @@
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
+
 import 'package:wordguessing/models/word.dart';
+import 'package:wordguessing/provider/data.dart';
+import 'package:wordguessing/screens/game.dart';
 import 'package:wordguessing/utils/random_pick_words.dart';
 
-import '../provider/data.dart';
-
-class GamePickImagePage extends StatelessWidget {
-  final int _countWords = 4;
-
-  Future<void> startGame(Data myProvider, String lang) async {
-    await resetGame(myProvider);
-    myProvider.updateLang = lang;
-    await nextWord(myProvider);
-  }
-
-  Future<void> resetGame(Data myProvider) async {
-    myProvider.updateLang = '';
-    myProvider.updateQuestionsCount = 0;
-    myProvider.updateGoodAnswers = 0;
-    myProvider.updateWrongAnswers = 0;
-    myProvider.updateWord = null;
-    myProvider.updateImages = [];
-  }
-
-  Future<void> nextWord(Data myProvider) async {
-    await pickData(myProvider);
-    myProvider.updateQuestionsCount = myProvider.questionsCount + 1;
-  }
-
+class GamePickImagePage extends Game {
   Future<void> pickData(Data myProvider) async {
-    List<Word> words = [];
-    RandomPickWords randomPickWords;
-    Word? word;
+    final RandomPickWords randomPickWords = RandomPickWords();
+    Word word;
 
     int attempts = 0;
     do {
-      randomPickWords = RandomPickWords();
-      await randomPickWords.init(myProvider.lang, _countWords);
+      await randomPickWords.init(myProvider.lang, countWords);
 
-      words = randomPickWords.words;
+      final List<Word> words = randomPickWords.words;
 
-      if (words.length > 0) {
-        word = words.take(1).toList()[0];
+      word = words.take(1).toList()[0];
 
-        if ((words.length == _countWords) && !myProvider.isRecentlyPicked(word.key)) {
-          myProvider.updateWord = word;
+      if ((words.length == countWords) && !myProvider.isRecentlyPicked(word.key)) {
+        myProvider.updateWord(word);
 
-          List<Word> images = [];
-          words.forEach((element) {
-            images.add(element);
-          });
+        final List<Word> images = [];
+        words.forEach((element) {
+          images.add(element);
+        });
 
-          myProvider.updateImages = images;
-        }
+        myProvider.updateImages(images);
       }
 
       attempts++;
     } while (myProvider.word != word && attempts < 10);
   }
 
-  Future<void> checkWord(Data myProvider, word) async {
-    if (myProvider.word?.key == word.key) {
-      myProvider.updateGoodAnswers = myProvider.goodAnswers + 1;
-      nextWord(myProvider);
-    } else {
-      myProvider.updateWrongAnswers = myProvider.wrongAnswers + 1;
-    }
-  }
-
-  Container _buildScoreItemContainer(String text, Color blockColor) {
-    Color backgroundColor = blockColor;
-
-    // Darken block color to get border color
-    double amount = 0.2;
-    final hsl = HSLColor.fromColor(blockColor);
-    final hslDark = hsl.withLightness((hsl.lightness - amount).clamp(0.0, 1.0));
-    Color borderColor = hslDark.toColor();
-
-    return Container(
-      margin: EdgeInsets.symmetric(horizontal: 15),
-      padding: EdgeInsets.all(5),
-      decoration: BoxDecoration(
-        color: backgroundColor,
-        borderRadius: BorderRadius.circular(4),
-        border: Border.all(
-          color: borderColor,
-          width: 4,
-        ),
-      ),
-      child: Text(
-        text,
-        style: TextStyle(
-          fontSize: 25,
-          fontWeight: FontWeight.w600,
-          color: Colors.black,
-        ),
-      ),
-    );
-  }
-
-  String getGoodAnswersString(Data myProvider) {
-    int count = myProvider.questionsCount - 1;
-    return 'πŸ‘ ' + myProvider.goodAnswers.toString() + '/' + count.toString();
-  }
-
-  String getWrongAnswersString(Data myProvider) {
-    int count = myProvider.questionsCount - 1;
-    return '🚩 ' + myProvider.wrongAnswers.toString() + '/' + count.toString();
-  }
-
-  Container _buildScoreContainer(Data myProvider) {
-    return Container(
-      padding: EdgeInsets.all(5),
-      child: Row(
-        mainAxisSize: MainAxisSize.min,
-        mainAxisAlignment: MainAxisAlignment.center,
-        children: [
-          _buildScoreItemContainer(
-            getGoodAnswersString(myProvider),
-            Colors.green,
-          ),
-          SizedBox(width: 20),
-          _buildScoreItemContainer(
-            getWrongAnswersString(myProvider),
-            Colors.orange,
-          ),
-        ],
-      ),
-    );
-  }
-
-  Container _buildImageContainer(Data myProvider, Word word) {
-    double imageSize = 130;
+  Widget buildImageContainer(Data myProvider, Word word) {
+    const double imageSize = 130;
 
     String imageAsset = 'assets/placeholder.png';
     if ((word.images.length != 0)) {
@@ -148,7 +51,7 @@ class GamePickImagePage extends StatelessWidget {
               width: 8,
             ),
           ),
-          margin: EdgeInsets.all(2),
+          margin: const EdgeInsets.all(2),
           child: Image(
             image: AssetImage(imageAsset),
             width: imageSize,
@@ -163,11 +66,11 @@ class GamePickImagePage extends StatelessWidget {
     );
   }
 
-  Column _buildImageItemsBlock(Data myProvider) {
-    List<Word> images = myProvider.images;
+  Widget buildImageItemsBlock(Data myProvider) {
+    final List<Word> images = myProvider.images;
 
-    if (images.length != _countWords) {
-      return Column();
+    if (images.length != countWords) {
+      return const SizedBox.shrink();
     }
 
     images.sort((a, b) => a.key.compareTo(b.key));
@@ -180,24 +83,24 @@ class GamePickImagePage extends StatelessWidget {
           mainAxisSize: MainAxisSize.min,
           mainAxisAlignment: MainAxisAlignment.center,
           children: [
-            _buildImageContainer(myProvider, images[0]),
-            _buildImageContainer(myProvider, images[1]),
+            buildImageContainer(myProvider, images[0]),
+            buildImageContainer(myProvider, images[1]),
           ],
         ),
         Row(
           mainAxisSize: MainAxisSize.min,
           mainAxisAlignment: MainAxisAlignment.center,
           children: [
-            _buildImageContainer(myProvider, images[2]),
-            _buildImageContainer(myProvider, images[3]),
+            buildImageContainer(myProvider, images[2]),
+            buildImageContainer(myProvider, images[3]),
           ],
         )
       ],
     );
   }
 
-  Widget _buildTextItemBlock(Data myProvider) {
-    Word? word = myProvider.word;
+  Widget buildTextItemBlock(Data myProvider) {
+    final Word? word = myProvider.word;
 
     if (word == null) {
       return const SizedBox.shrink();
@@ -213,7 +116,7 @@ class GamePickImagePage extends StatelessWidget {
         ),
       ),
       child: Padding(
-        padding: EdgeInsets.all(12),
+        padding: const EdgeInsets.all(12),
         child: Text(
           word.text,
           style: TextStyle(
@@ -226,95 +129,15 @@ class GamePickImagePage extends StatelessWidget {
     );
   }
 
-  Column _buildStartGameBlock(Data myProvider) {
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: [
-        Container(
-          child: ElevatedButton(
-            style: ElevatedButton.styleFrom(
-              foregroundColor: Colors.teal,
-              backgroundColor: Colors.teal,
-              padding: EdgeInsets.all(35),
-            ),
-            child: Text(
-              "πŸ‡«πŸ‡·",
-              style: TextStyle(
-                fontSize: 60,
-                color: Colors.black,
-              ),
-            ),
-            onPressed: () => startGame(myProvider, 'fr'),
-          ),
-        ),
-        SizedBox(height: 15),
-        Container(
-          child: ElevatedButton(
-            style: ElevatedButton.styleFrom(
-              foregroundColor: Colors.teal,
-              backgroundColor: Colors.teal,
-              padding: EdgeInsets.all(35),
-            ),
-            child: Text(
-              "πŸ‡¬πŸ‡§",
-              style: TextStyle(
-                fontSize: 60,
-                color: Colors.black,
-              ),
-            ),
-            onPressed: () => startGame(myProvider, 'en'),
-          ),
-        )
-      ],
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    Data myProvider = Provider.of<Data>(context);
-
-    Scaffold pageContent = Scaffold(
-      appBar: AppBar(
-        elevation: 0,
-        actions: <Widget>[
-          IconButton(
-            icon: const Icon(Icons.loop),
-            onPressed: () => resetGame(myProvider),
-          ),
-        ],
-      ),
-      backgroundColor: Colors.blue,
-      body: Center(
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          mainAxisSize: MainAxisSize.max,
-          children: <Widget>[
-            _buildTextItemBlock(myProvider),
-            SizedBox(height: 2),
-            ((myProvider.word == null) || (myProvider.word?.key == ''))
-                ? _buildStartGameBlock(myProvider)
-                : _buildScoreContainer(myProvider),
-            SizedBox(height: 2),
-            _buildImageItemsBlock(myProvider),
-          ],
-        ),
-      ),
-    );
-
-    return SizedBox.expand(
-      child: Container(
-        child: FittedBox(
-          fit: BoxFit.contain,
-          alignment: Alignment.center,
-          child: SizedBox(
-            height: (MediaQuery.of(context).size.height),
-            width: (MediaQuery.of(context).size.width),
-            child: pageContent,
-          ),
-        ),
-      ),
-    );
+  List<Widget> buildPageContent(Data myProvider) {
+    return <Widget>[
+      buildTextItemBlock(myProvider),
+      const SizedBox(height: 2),
+      ((myProvider.word == null) || (myProvider.word?.key == ''))
+          ? buildStartGameBlock(myProvider)
+          : buildScoreContainer(myProvider),
+      const SizedBox(height: 2),
+      buildImageItemsBlock(myProvider),
+    ];
   }
 }
diff --git a/lib/screens/game_pick_word.dart b/lib/screens/game_pick_word.dart
index 9ab6216..66403f1 100644
--- a/lib/screens/game_pick_word.dart
+++ b/lib/screens/game_pick_word.dart
@@ -1,135 +1,35 @@
 import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
+
 import 'package:wordguessing/models/word.dart';
+import 'package:wordguessing/provider/data.dart';
+import 'package:wordguessing/screens/game.dart';
 import 'package:wordguessing/utils/random_pick_words.dart';
 
-import '../provider/data.dart';
-
-class GamePickWordPage extends StatelessWidget {
-  final int _countWords = 4;
-  final int _countImages = 4;
-
-  Future<void> startGame(Data myProvider, String lang) async {
-    await resetGame(myProvider);
-    myProvider.updateLang = lang;
-    await nextWord(myProvider);
-  }
-
-  Future<void> resetGame(Data myProvider) async {
-    myProvider.updateLang = '';
-    myProvider.updateQuestionsCount = 0;
-    myProvider.updateGoodAnswers = 0;
-    myProvider.updateWrongAnswers = 0;
-    myProvider.updateWord = null;
-    myProvider.updateImages = [];
-  }
-
-  Future<void> nextWord(Data myProvider) async {
-    await pickData(myProvider);
-    myProvider.updateQuestionsCount = myProvider.questionsCount + 1;
-  }
-
+class GamePickWordPage extends Game {
   Future<void> pickData(Data myProvider) async {
-    List<Word> words = [];
-    List<Word> images = [];
-    RandomPickWords randomPickWords;
+    final RandomPickWords randomPickWords = RandomPickWords();
     Word word;
 
     int attempts = 0;
     do {
-      randomPickWords = RandomPickWords();
-      await randomPickWords.init(myProvider.lang, _countWords);
+      await randomPickWords.init(myProvider.lang, countWords);
 
-      words = randomPickWords.words;
+      final List<Word> words = randomPickWords.words;
 
       word = words.take(1).toList()[0];
-      images = [word];
 
-      attempts++;
-
-      if ((words.length >= _countWords) &&
-          // (images.length >= _countImages) &&
-          !myProvider.isRecentlyPicked(word.key)) {
-        myProvider.updateWord = word;
-        myProvider.updateOtherWords = words.skip(1).toList();
-        myProvider.updateImages = images;
+      if ((words.length >= countWords) && !myProvider.isRecentlyPicked(word.key)) {
+        myProvider.updateWord(word);
+        myProvider.updateOtherWords(words.skip(1).toList());
+        myProvider.updateImages([word]);
       }
-    } while (myProvider.word != word && attempts < 10);
-  }
-
-  Future<void> checkWord(Data myProvider, word) async {
-    if (myProvider.word?.key == word.key) {
-      myProvider.updateGoodAnswers = myProvider.goodAnswers + 1;
-      nextWord(myProvider);
-    } else {
-      myProvider.updateWrongAnswers = myProvider.wrongAnswers + 1;
-    }
-  }
-
-  Container _buildScoreItemContainer(String text, Color blockColor) {
-    Color backgroundColor = blockColor;
 
-    // Darken block color to get border color
-    double amount = 0.2;
-    final hsl = HSLColor.fromColor(blockColor);
-    final hslDark = hsl.withLightness((hsl.lightness - amount).clamp(0.0, 1.0));
-    Color borderColor = hslDark.toColor();
-
-    return Container(
-      margin: EdgeInsets.symmetric(horizontal: 15),
-      padding: EdgeInsets.all(5),
-      decoration: BoxDecoration(
-        color: backgroundColor,
-        borderRadius: BorderRadius.circular(4),
-        border: Border.all(
-          color: borderColor,
-          width: 4,
-        ),
-      ),
-      child: Text(
-        text,
-        style: TextStyle(
-          fontSize: 25,
-          fontWeight: FontWeight.w600,
-          color: Colors.black,
-        ),
-      ),
-    );
-  }
-
-  String getGoodAnswersString(Data myProvider) {
-    int count = myProvider.questionsCount - 1;
-    return 'πŸ‘ ' + myProvider.goodAnswers.toString() + '/' + count.toString();
-  }
-
-  String getWrongAnswersString(Data myProvider) {
-    int count = myProvider.questionsCount - 1;
-    return '🚩 ' + myProvider.wrongAnswers.toString() + '/' + count.toString();
-  }
-
-  Container _buildScoreContainer(Data myProvider) {
-    return Container(
-      padding: EdgeInsets.all(5),
-      child: Row(
-        mainAxisSize: MainAxisSize.min,
-        mainAxisAlignment: MainAxisAlignment.center,
-        children: [
-          _buildScoreItemContainer(
-            getGoodAnswersString(myProvider),
-            Colors.green,
-          ),
-          SizedBox(width: 20),
-          _buildScoreItemContainer(
-            getWrongAnswersString(myProvider),
-            Colors.orange,
-          ),
-        ],
-      ),
-    );
+      attempts++;
+    } while (myProvider.word != word && attempts < 10);
   }
 
-  Container _buildImageContainer(String image) {
-    double imageSize = 130;
+  Widget buildImageContainer(String image) {
+    const double imageSize = 130;
 
     String imageAsset = 'assets/placeholder.png';
     if (image != '') {
@@ -137,7 +37,7 @@ class GamePickWordPage extends StatelessWidget {
     }
 
     return Container(
-      margin: EdgeInsets.all(2),
+      margin: const EdgeInsets.all(2),
       decoration: BoxDecoration(
         borderRadius: BorderRadius.circular(8),
         border: Border.all(
@@ -146,18 +46,15 @@ class GamePickWordPage extends StatelessWidget {
         ),
       ),
       child: Image(
-          image: AssetImage(imageAsset),
-          width: imageSize,
-          height: imageSize,
-          fit: BoxFit.fill),
+        image: AssetImage(imageAsset),
+        width: imageSize,
+        height: imageSize,
+        fit: BoxFit.fill,
+      ),
     );
   }
 
-  Column _buildImageItemsBlock(Word? currentWord) {
-    if ((currentWord?.images.length ?? 0) < _countImages) {
-      return Column();
-    }
-
+  Widget buildImageItemsBlock(Word? currentWord) {
     return Column(
       mainAxisSize: MainAxisSize.min,
       mainAxisAlignment: MainAxisAlignment.center,
@@ -166,25 +63,25 @@ class GamePickWordPage extends StatelessWidget {
           mainAxisSize: MainAxisSize.min,
           mainAxisAlignment: MainAxisAlignment.center,
           children: [
-            _buildImageContainer(currentWord?.images[0] ?? ''),
-            _buildImageContainer(currentWord?.images[1] ?? ''),
+            buildImageContainer(currentWord?.images[0] ?? ''),
+            buildImageContainer(currentWord?.images[1] ?? ''),
           ],
         ),
         Row(
           mainAxisSize: MainAxisSize.min,
           mainAxisAlignment: MainAxisAlignment.center,
           children: [
-            _buildImageContainer(currentWord?.images[2] ?? ''),
-            _buildImageContainer(currentWord?.images[3] ?? ''),
+            buildImageContainer(currentWord?.images[2] ?? ''),
+            buildImageContainer(currentWord?.images[3] ?? ''),
           ],
         )
       ],
     );
   }
 
-  Container _buildTextContainer(Data myProvider, Word word) {
+  Widget buildTextContainer(Data myProvider, Word word) {
     return Container(
-      margin: EdgeInsets.all(2),
+      margin: const EdgeInsets.all(2),
       decoration: BoxDecoration(
         color: Colors.blue[800],
         borderRadius: BorderRadius.circular(6),
@@ -195,7 +92,7 @@ class GamePickWordPage extends StatelessWidget {
       ),
       child: TextButton(
         style: TextButton.styleFrom(
-          padding: EdgeInsets.all(15),
+          padding: const EdgeInsets.all(15),
         ),
         child: Text(
           word.text,
@@ -212,19 +109,19 @@ class GamePickWordPage extends StatelessWidget {
     );
   }
 
-  Column _buildTextItemsBlock(Data myProvider) {
+  Widget buildTextItemsBlock(Data myProvider) {
     Word? word = myProvider.word;
-    List otherWords = myProvider.otherWords;
+    List<Word> otherWords = myProvider.otherWords;
 
-    if ((word == null) || (otherWords.length != (_countWords - 1))) {
+    if ((word == null) || (otherWords.length != (countWords - 1))) {
       return Column();
     }
 
-    List words = [
+    List<Word> words = [
       word,
-      otherWords.length > 0 ? otherWords[0] : null,
-      otherWords.length > 1 ? otherWords[1] : null,
-      otherWords.length > 2 ? otherWords[2] : null,
+      otherWords[0],
+      otherWords[1],
+      otherWords[2],
     ];
 
     words.sort((a, b) => a.key.compareTo(b.key));
@@ -237,116 +134,36 @@ class GamePickWordPage extends StatelessWidget {
           mainAxisSize: MainAxisSize.min,
           mainAxisAlignment: MainAxisAlignment.center,
           children: [
-            _buildTextContainer(myProvider, words[0]),
-            SizedBox(width: 10),
-            _buildTextContainer(myProvider, words[1]),
+            buildTextContainer(myProvider, words[0]),
+            const SizedBox(width: 10),
+            buildTextContainer(myProvider, words[1]),
           ],
         ),
-        SizedBox(height: 5),
+        const SizedBox(height: 5),
         Row(
           mainAxisSize: MainAxisSize.min,
           mainAxisAlignment: MainAxisAlignment.center,
           children: [
-            _buildTextContainer(myProvider, words[2]),
-            SizedBox(width: 10),
-            _buildTextContainer(myProvider, words[3]),
+            buildTextContainer(myProvider, words[2]),
+            const SizedBox(width: 10),
+            buildTextContainer(myProvider, words[3]),
           ],
         )
       ],
     );
   }
 
-  Column _buildStartGameBlock(Data myProvider) {
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: [
-        Container(
-          child: ElevatedButton(
-            style: ElevatedButton.styleFrom(
-              foregroundColor: Colors.teal,
-              backgroundColor: Colors.teal,
-              padding: EdgeInsets.all(35),
-            ),
-            child: Text(
-              "πŸ‡«πŸ‡·",
-              style: TextStyle(
-                fontSize: 60,
-                color: Colors.black,
-              ),
-            ),
-            onPressed: () => startGame(myProvider, 'fr'),
-          ),
-        ),
-        SizedBox(height: 15),
-        Container(
-          child: ElevatedButton(
-            style: ElevatedButton.styleFrom(
-              foregroundColor: Colors.teal,
-              backgroundColor: Colors.teal,
-              padding: EdgeInsets.all(35),
-            ),
-            child: Text(
-              "πŸ‡¬πŸ‡§",
-              style: TextStyle(
-                fontSize: 60,
-                color: Colors.black,
-              ),
-            ),
-            onPressed: () => startGame(myProvider, 'en'),
-          ),
-        )
-      ],
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    Data myProvider = Provider.of<Data>(context);
-
-    Scaffold pageContent = Scaffold(
-      appBar: AppBar(
-        elevation: 0,
-        actions: <Widget>[
-          IconButton(
-            icon: const Icon(Icons.loop),
-            onPressed: () => resetGame(myProvider),
-          ),
-        ],
-      ),
-      backgroundColor: Colors.blue,
-      body: Center(
-        child: Column(
-          mainAxisAlignment: MainAxisAlignment.spaceEvenly,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          mainAxisSize: MainAxisSize.max,
-          children: <Widget>[
-            (myProvider.images.length != 0)
-                ? _buildImageItemsBlock(myProvider.images[0])
-                : SizedBox.shrink(),
-            SizedBox(height: 2),
-            ((myProvider.word == null) || (myProvider.word?.key == ''))
-                ? _buildStartGameBlock(myProvider)
-                : _buildScoreContainer(myProvider),
-            SizedBox(height: 2),
-            _buildTextItemsBlock(myProvider),
-          ],
-        ),
-      ),
-    );
-
-    return SizedBox.expand(
-      child: Container(
-        child: FittedBox(
-          fit: BoxFit.contain,
-          alignment: Alignment.center,
-          child: SizedBox(
-            height: (MediaQuery.of(context).size.height),
-            width: (MediaQuery.of(context).size.width),
-            child: pageContent,
-          ),
-        ),
-      ),
-    );
+  List<Widget> buildPageContent(Data myProvider) {
+    return <Widget>[
+      (myProvider.images.length != 0)
+          ? buildImageItemsBlock(myProvider.images[0])
+          : const SizedBox.shrink(),
+      const SizedBox(height: 2),
+      ((myProvider.word == null) || (myProvider.word?.key == ''))
+          ? buildStartGameBlock(myProvider)
+          : buildScoreContainer(myProvider),
+      const SizedBox(height: 2),
+      buildTextItemsBlock(myProvider),
+    ];
   }
 }
diff --git a/lib/screens/home.dart b/lib/screens/home.dart
index ca9fc55..8b664e9 100644
--- a/lib/screens/home.dart
+++ b/lib/screens/home.dart
@@ -1,32 +1,22 @@
 import 'package:flutter/material.dart';
 import 'package:provider/provider.dart';
 
-import '../provider/data.dart';
+import 'package:wordguessing/provider/data.dart';
 
 class Home extends StatelessWidget {
   static const String id = 'home';
 
-  Future<void> resetGame(Data myProvider) async {
-    myProvider.updateLang = '';
-    myProvider.updateQuestionsCount = 0;
-    myProvider.updateGoodAnswers = 0;
-    myProvider.updateWrongAnswers = 0;
-    myProvider.updateWord = null;
-    myProvider.updateOtherWords = [];
-    myProvider.updateImages = [];
-  }
-
   @override
   Widget build(BuildContext context) {
-    Data myProvider = Provider.of<Data>(context);
+    final Data myProvider = Provider.of<Data>(context);
 
-    Container _buildMenuItemContainer(String code, Color color) {
-      double imageSize = 150;
+    Container buildMenuItemContainer(String code, Color color) {
+      const double imageSize = 150;
 
-      String imageAsset = 'assets/menu/' + code + '.png';
+      final String imageAsset = 'assets/menu/' + code + '.png';
 
       return Container(
-        margin: EdgeInsets.all(2),
+        margin: const EdgeInsets.all(2),
         decoration: BoxDecoration(
           borderRadius: BorderRadius.circular(8),
           border: Border.all(
@@ -42,7 +32,7 @@ class Home extends StatelessWidget {
             fit: BoxFit.fill,
           ),
           onTap: () {
-            resetGame(myProvider);
+            myProvider.resetGame();
             Navigator.pushNamed(
               context,
               '/' + code,
@@ -60,8 +50,8 @@ class Home extends StatelessWidget {
           crossAxisAlignment: CrossAxisAlignment.center,
           mainAxisSize: MainAxisSize.max,
           children: <Widget>[
-            _buildMenuItemContainer('game-pick-word', Colors.pink),
-            _buildMenuItemContainer('game-pick-image', Colors.yellow),
+            buildMenuItemContainer('game-pick-word', Colors.pink),
+            buildMenuItemContainer('game-pick-image', Colors.yellow),
           ],
         ),
       ),
diff --git a/lib/utils/random_pick_words.dart b/lib/utils/random_pick_words.dart
index e35cd9a..e0fe729 100644
--- a/lib/utils/random_pick_words.dart
+++ b/lib/utils/random_pick_words.dart
@@ -1,6 +1,8 @@
 import 'dart:async';
 import 'dart:convert';
+
 import 'package:flutter/services.dart';
+
 import 'package:wordguessing/models/word.dart';
 
 class RandomPickWords {
@@ -16,12 +18,12 @@ class RandomPickWords {
     List<Word> wordList = [];
 
     try {
-      String jsonString = await rootBundle.loadString('assets/words.json');
+      final String jsonString = await rootBundle.loadString('assets/words.json');
       final jsonResponse = await json.decode(jsonString);
-      Map<String, dynamic> wordsMap = jsonResponse['words'] as Map<String, dynamic>;
+      final Map<String, dynamic> wordsMap = jsonResponse['words'] as Map<String, dynamic>;
 
       wordsMap.forEach((key, data) {
-        List<String> images = [];
+        final List<String> images = [];
         (data['images'] as List<dynamic>).forEach((image) {
           images.add(image as String);
         });
diff --git a/pubspec.lock b/pubspec.lock
index 3ffe094..aa6ea1d 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -1,14 +1,6 @@
 # Generated by pub
 # See https://dart.dev/tools/pub/glossary#lockfile
 packages:
-  async:
-    dependency: transitive
-    description:
-      name: async
-      sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
-      url: "https://pub.dev"
-    source: hosted
-    version: "2.11.0"
   characters:
     dependency: transitive
     description:
@@ -30,22 +22,6 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.0"
-  http:
-    dependency: "direct main"
-    description:
-      name: http
-      sha256: d4872660c46d929f6b8a9ef4e7a7eff7e49bbf0c4ec3f385ee32df5119175139
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.1.2"
-  http_parser:
-    dependency: transitive
-    description:
-      name: http_parser
-      sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
-      url: "https://pub.dev"
-    source: hosted
-    version: "4.0.2"
   material_color_utilities:
     dependency: transitive
     description:
@@ -70,14 +46,6 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.0.0"
-  path:
-    dependency: transitive
-    description:
-      name: path
-      sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.9.0"
   provider:
     dependency: "direct main"
     description:
@@ -91,38 +59,6 @@ packages:
     description: flutter
     source: sdk
     version: "0.0.99"
-  source_span:
-    dependency: transitive
-    description:
-      name: source_span
-      sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.10.0"
-  string_scanner:
-    dependency: transitive
-    description:
-      name: string_scanner
-      sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.2.0"
-  term_glyph:
-    dependency: transitive
-    description:
-      name: term_glyph
-      sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.2.1"
-  typed_data:
-    dependency: transitive
-    description:
-      name: typed_data
-      sha256: facc8d6582f16042dd49f2463ff1bd6e2c9ef9f3d5da3d9b087e244a7b564b3c
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.3.2"
   vector_math:
     dependency: transitive
     description:
@@ -140,5 +76,5 @@ packages:
     source: hosted
     version: "0.3.0"
 sdks:
-  dart: ">=3.2.0 <4.0.0"
+  dart: ">=3.2.0-194.0.dev <4.0.0"
   flutter: ">=1.16.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 88e9290..a33fb28 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,7 +1,7 @@
 name: wordguessing
 description: A wordguessing game application.
 publish_to: 'none'
-version: 0.1.33+57
+version: 0.1.34+58
 
 environment:
   sdk: '^3.0.0'
@@ -9,7 +9,6 @@ environment:
 dependencies:
   flutter:
     sdk: flutter
-  http: ^1.1.0
   provider: ^6.0.5
 
 flutter:
-- 
GitLab