From cc298e0b75868f91c9fde9c9e2de0265ec1f78c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr>
Date: Mon, 6 May 2024 01:13:33 +0200
Subject: [PATCH] Improve game architecture/conception

---
 android/app/build.gradle                      |   2 +-
 android/gradle.properties                     |   4 +-
 assets/files/categories-fr.json               |  67 ------
 assets/icons/button_back.png                  | Bin 0 -> 3771 bytes
 assets/icons/button_start.png                 | Bin 0 -> 3999 bytes
 assets/icons/placeholder.png                  | Bin 0 -> 170 bytes
 .../metadata/android/en-US/changelogs/37.txt  |   1 +
 .../metadata/android/fr-FR/changelogs/37.txt  |   1 +
 icons/build_game_icons.sh                     |  78 ++++++
 icons/build_icons.sh                          |  48 ----
 icons/button_back.svg                         |   2 +
 icons/button_start.svg                        |   2 +
 icons/placeholder.svg                         |   2 +
 lib/config/default_game_settings.dart         |  51 ++++
 lib/config/default_global_settings.dart       |  10 +
 lib/config/default_settings.dart              |  12 -
 lib/config/menu.dart                          |  63 ++---
 lib/cubit/game_cubit.dart                     | 131 +++++++++-
 lib/cubit/game_state.dart                     |   6 +-
 .../{bottom_nav_cubit.dart => nav_cubit.dart} |  22 +-
 lib/cubit/settings_cubit.dart                 |  47 ----
 lib/cubit/settings_game_cubit.dart            |  70 ++++++
 lib/cubit/settings_game_state.dart            |  19 ++
 lib/cubit/settings_global_cubit.dart          |  44 ++++
 lib/cubit/settings_global_state.dart          |  19 ++
 lib/cubit/settings_state.dart                 |  19 --
 lib/data/fetch_data_helper.dart               |  66 +++++
 lib/data/game_data.dart                       |  66 +++++
 lib/main.dart                                 |  56 +++--
 lib/models/data/category.dart                 |  21 ++
 lib/models/data/game_item.dart                |  24 ++
 lib/models/data/letter.dart                   |  21 ++
 lib/models/game.dart                          | 100 ++++++++
 lib/models/game/game.dart                     |  38 ---
 lib/models/settings_game.dart                 |  53 +++++
 lib/models/settings_global.dart               |  23 ++
 lib/provider/data.dart                        |  76 ------
 lib/ui/painters/parameter_painter.dart        | 225 ++++++++++++++++++
 lib/ui/screens/game_page.dart                 |  34 ---
 .../{about_page.dart => page_about.dart}      |   7 +-
 lib/ui/screens/page_game.dart                 |  18 ++
 ...{settings_page.dart => page_settings.dart} |   9 +-
 lib/ui/skeleton.dart                          |  45 ++--
 lib/ui/widgets/app_bar.dart                   |  20 --
 lib/ui/widgets/bottom_nav_bar.dart            |  40 ----
 lib/ui/widgets/button_game_start_new.dart     |  34 +++
 lib/ui/widgets/game/game.dart                 |  37 +++
 lib/ui/widgets/game/game_countdown.dart       |  82 +++++++
 .../widgets/game/game_position_indicator.dart |  50 ++++
 lib/ui/widgets/game/widget_category.dart      |  52 ++++
 lib/ui/widgets/game/widget_letter.dart        |  51 ++++
 lib/ui/widgets/global_app_bar.dart            |  84 +++++++
 .../app_header.dart}                          |   5 +-
 lib/ui/widgets/helpers/app_title.dart         |  17 ++
 .../widgets/helpers/outlined_text_widget.dart |  51 ++++
 lib/ui/widgets/mini_game.dart                 | 107 ---------
 lib/ui/widgets/parameters.dart                | 115 +++++++++
 lib/ui/widgets/picked_category.dart           |  55 -----
 lib/ui/widgets/picked_letter.dart             | 101 --------
 lib/ui/widgets/previous_letter.dart           |  52 ----
 lib/ui/widgets/settings/settings_form.dart    |  63 +++++
 lib/ui/widgets/settings/theme_card.dart       |  47 ++++
 lib/ui/widgets/settings_form.dart             | 108 ---------
 lib/ui/widgets/theme_card.dart                |  45 ----
 lib/utils/game_utils.dart                     |  37 ---
 lib/utils/random_pick_category.dart           |  30 ---
 lib/utils/random_pick_letter.dart             |  20 --
 pubspec.lock                                  |  86 +++----
 pubspec.yaml                                  |  17 +-
 69 files changed, 1874 insertions(+), 1134 deletions(-)
 delete mode 100644 assets/files/categories-fr.json
 create mode 100644 assets/icons/button_back.png
 create mode 100644 assets/icons/button_start.png
 create mode 100644 assets/icons/placeholder.png
 create mode 100644 fastlane/metadata/android/en-US/changelogs/37.txt
 create mode 100644 fastlane/metadata/android/fr-FR/changelogs/37.txt
 create mode 100755 icons/build_game_icons.sh
 delete mode 100755 icons/build_icons.sh
 create mode 100644 icons/button_back.svg
 create mode 100644 icons/button_start.svg
 create mode 100644 icons/placeholder.svg
 create mode 100644 lib/config/default_game_settings.dart
 create mode 100644 lib/config/default_global_settings.dart
 delete mode 100644 lib/config/default_settings.dart
 rename lib/cubit/{bottom_nav_cubit.dart => nav_cubit.dart} (51%)
 delete mode 100644 lib/cubit/settings_cubit.dart
 create mode 100644 lib/cubit/settings_game_cubit.dart
 create mode 100644 lib/cubit/settings_game_state.dart
 create mode 100644 lib/cubit/settings_global_cubit.dart
 create mode 100644 lib/cubit/settings_global_state.dart
 delete mode 100644 lib/cubit/settings_state.dart
 create mode 100644 lib/data/fetch_data_helper.dart
 create mode 100644 lib/data/game_data.dart
 create mode 100644 lib/models/data/category.dart
 create mode 100644 lib/models/data/game_item.dart
 create mode 100644 lib/models/data/letter.dart
 create mode 100644 lib/models/game.dart
 delete mode 100644 lib/models/game/game.dart
 create mode 100644 lib/models/settings_game.dart
 create mode 100644 lib/models/settings_global.dart
 delete mode 100644 lib/provider/data.dart
 create mode 100644 lib/ui/painters/parameter_painter.dart
 delete mode 100644 lib/ui/screens/game_page.dart
 rename lib/ui/screens/{about_page.dart => page_about.dart} (86%)
 create mode 100644 lib/ui/screens/page_game.dart
 rename lib/ui/screens/{settings_page.dart => page_settings.dart} (64%)
 delete mode 100644 lib/ui/widgets/app_bar.dart
 delete mode 100644 lib/ui/widgets/bottom_nav_bar.dart
 create mode 100644 lib/ui/widgets/button_game_start_new.dart
 create mode 100644 lib/ui/widgets/game/game.dart
 create mode 100644 lib/ui/widgets/game/game_countdown.dart
 create mode 100644 lib/ui/widgets/game/game_position_indicator.dart
 create mode 100644 lib/ui/widgets/game/widget_category.dart
 create mode 100644 lib/ui/widgets/game/widget_letter.dart
 create mode 100644 lib/ui/widgets/global_app_bar.dart
 rename lib/ui/widgets/{header_app.dart => helpers/app_header.dart} (77%)
 create mode 100644 lib/ui/widgets/helpers/app_title.dart
 create mode 100644 lib/ui/widgets/helpers/outlined_text_widget.dart
 delete mode 100644 lib/ui/widgets/mini_game.dart
 create mode 100644 lib/ui/widgets/parameters.dart
 delete mode 100644 lib/ui/widgets/picked_category.dart
 delete mode 100644 lib/ui/widgets/picked_letter.dart
 delete mode 100644 lib/ui/widgets/previous_letter.dart
 create mode 100644 lib/ui/widgets/settings/settings_form.dart
 create mode 100644 lib/ui/widgets/settings/theme_card.dart
 delete mode 100644 lib/ui/widgets/settings_form.dart
 delete mode 100644 lib/ui/widgets/theme_card.dart
 delete mode 100644 lib/utils/game_utils.dart
 delete mode 100644 lib/utils/random_pick_category.dart
 delete mode 100644 lib/utils/random_pick_letter.dart

diff --git a/android/app/build.gradle b/android/app/build.gradle
index c5483a3..5919a87 100644
--- a/android/app/build.gradle
+++ b/android/app/build.gradle
@@ -37,7 +37,7 @@ if (keystorePropertiesFile.exists()) {
 }
 
 android {
-    compileSdkVersion 33
+    compileSdkVersion 34
     namespace "org.benoitharrault.petitbac"
 
     defaultConfig {
diff --git a/android/gradle.properties b/android/gradle.properties
index b33cdc8..000015d 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=1.2.30
-app.versionCode=36
+app.versionName=1.2.31
+app.versionCode=37
diff --git a/assets/files/categories-fr.json b/assets/files/categories-fr.json
deleted file mode 100644
index 4205a8c..0000000
--- a/assets/files/categories-fr.json
+++ /dev/null
@@ -1,67 +0,0 @@
-{
-  "categories": [
-    "Pays",
-    "Prénom fille",
-    "Prénom garçon",
-    "Animal",
-    "Métier",
-    "Villes",
-    "Dessin animé",
-    "Film",
-    "Auteur de littérature",
-    "Acteur ou actrice",
-    "Chanteur ou chanteuse",
-    "Chose ou objet",
-    "Fruit ou légume",
-    "Couleur",
-    "Marque",
-    "Moyen de transport",
-    "Outil",
-    "Capitale",
-    "Instrument de musique",
-    "Boisson",
-    "Fleur",
-    "Plat",
-    "Personnage historique",
-    "Vêtement",
-
-    "Minéral ou pierre précieuse",
-    "Étoile, planète ou constellation",
-    "Fleuve, cours d'eau ou océan",
-    "Partie du corps humain",
-    "Oiseau",
-    "Poisson",
-    "Qualité ou défaut",
-    "Arbre",
-    "Bande dessinée",
-    "Département français",
-    "Insecte",
-    "Dessert",
-    "Mammifère",
-    "Épice",
-    "Héros de mythologie",
-    "Héros fictif",
-    "Fromage",
-    "Jeu",
-    "Élément de véhicules",
-    "Site internet",
-
-    "Mot de plus de 8 lettres",
-    "Cadeau de Noël",
-    "Mot en anglais",
-    "Mot en espagnol",
-    "Métier dont rêvent les enfants",
-    "Chose qui se trouve dans une voiture",
-    "Chose qui se trouve dans un camping",
-    "Chose qui se trouve dans un cartable",
-    "Chose qui se trouve dans une maison",
-    "Chose qui se trouve dans une forêt",
-    "Chose qui se trouve dans la mer",
-    "Ville française",
-
-    "Qui sent mauvais",
-    "Qui fait plaisir",
-    "Mauvais pour la santé",
-    "Mauvais pour l'environement"
-  ]
-}
diff --git a/assets/icons/button_back.png b/assets/icons/button_back.png
new file mode 100644
index 0000000000000000000000000000000000000000..cc48ffb1dbb653d9a996f139dfbe02969724bfa5
GIT binary patch
literal 3771
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

literal 0
HcmV?d00001

diff --git a/assets/icons/button_start.png b/assets/icons/button_start.png
new file mode 100644
index 0000000000000000000000000000000000000000..6845e2f5c21598ab61f1684d2075aeec0334bf23
GIT binary patch
literal 3999
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

literal 0
HcmV?d00001

diff --git a/assets/icons/placeholder.png b/assets/icons/placeholder.png
new file mode 100644
index 0000000000000000000000000000000000000000..814df31be6ddc4275ebe4490c79365578dbef1f0
GIT binary patch
literal 170
zcmeAS@N?(olHy`uVBq!ia0y~yU^oE6jLZxS3>iZITo@P_I14-?iy0WCPk}I_+{y{!
z3=9mCC9V-A!TD(=<%vb94CUqJdYO6I#mR{Use1WE>9gP2NHH)lFbDXAxc>kDfB6yV
z6ATOtj3q&S!3+-1Zlp0VFi3m4IEF|_zCCEj$iTpGNa6SLI9~n)1_lO(0v(|P42<pU
Q7vF(+p00i_>zopr0K3yKtN;K2

literal 0
HcmV?d00001

diff --git a/fastlane/metadata/android/en-US/changelogs/37.txt b/fastlane/metadata/android/en-US/changelogs/37.txt
new file mode 100644
index 0000000..9dc5d66
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/37.txt
@@ -0,0 +1 @@
+Improve game architecture.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/37.txt b/fastlane/metadata/android/fr-FR/changelogs/37.txt
new file mode 100644
index 0000000..33a094d
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/37.txt
@@ -0,0 +1 @@
+Amélioration globale de la conception du jeu.
diff --git a/icons/build_game_icons.sh b/icons/build_game_icons.sh
new file mode 100755
index 0000000..7368dc4
--- /dev/null
+++ b/icons/build_game_icons.sh
@@ -0,0 +1,78 @@
+#! /bin/bash
+
+# Check dependencies
+command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; }
+command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not installed. Aborting."; exit 1; }
+command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
+
+CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
+BASE_DIR="$(dirname "${CURRENT_DIR}")"
+ASSETS_DIR="${BASE_DIR}/assets"
+
+OPTIPNG_OPTIONS="-preserve -quiet -o7"
+ICON_SIZE=192
+
+#######################################################
+
+# Game images
+AVAILABLE_GAME_IMAGES="
+  button_back
+  button_start
+  placeholder
+"
+
+#######################################################
+
+# optimize svg
+function optimize_svg() {
+  SOURCE="$1"
+
+  cp ${SOURCE} ${SOURCE}.tmp
+  scour \
+      --remove-descriptive-elements \
+      --enable-id-stripping \
+      --enable-viewboxing \
+      --enable-comment-stripping \
+      --nindent=4 \
+      --quiet \
+      -i ${SOURCE}.tmp \
+      -o ${SOURCE}
+  rm ${SOURCE}.tmp
+}
+
+# build icons
+function build_icon() {
+  SOURCE="$1"
+  TARGET="$2"
+
+  echo "Building ${TARGET}"
+
+  if [ ! -f "${SOURCE}" ]; then
+    echo "Missing file: ${SOURCE}"
+    exit 1
+  fi
+
+  optimize_svg "${SOURCE}"
+
+  inkscape \
+      --export-width=${ICON_SIZE} \
+      --export-height=${ICON_SIZE} \
+      --export-filename=${TARGET} \
+      ${SOURCE}
+
+  optipng ${OPTIPNG_OPTIONS} ${TARGET}
+}
+
+#######################################################
+
+# Create output folders
+mkdir -p ${ASSETS_DIR}/icons
+
+# Delete existing generated images
+find ${ASSETS_DIR}/icons -type f -name "*.png" -delete
+
+# build game images
+for GAME_IMAGE in ${AVAILABLE_GAME_IMAGES}
+do
+  build_icon ${CURRENT_DIR}/${GAME_IMAGE}.svg ${ASSETS_DIR}/icons/${GAME_IMAGE}.png
+done
diff --git a/icons/build_icons.sh b/icons/build_icons.sh
deleted file mode 100755
index fefc393..0000000
--- a/icons/build_icons.sh
+++ /dev/null
@@ -1,48 +0,0 @@
-#! /bin/bash
-
-# Check dependencies
-command -v inkscape >/dev/null 2>&1 || { echo >&2 "I require inkscape but it's not installed. Aborting."; exit 1; }
-command -v scour >/dev/null 2>&1 || { echo >&2 "I require scour but it's not installed. Aborting."; exit 1; }
-command -v optipng >/dev/null 2>&1 || { echo >&2 "I require optipng but it's not installed. Aborting."; exit 1; }
-command -v convert >/dev/null 2>&1 || { echo >&2 "I require convert (imagemagick) but it's not installed. Aborting."; exit 1; }
-
-CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null 2>&1 && pwd)"
-BASE_DIR="$(dirname "${CURRENT_DIR}")"
-
-SOURCE="${CURRENT_DIR}/icon.svg"
-OPTIPNG_OPTIONS="-preserve -quiet -o7"
-
-# optimize svg
-cp ${SOURCE} ${SOURCE}.tmp
-scour \
-    --remove-descriptive-elements \
-    --enable-id-stripping \
-    --enable-viewboxing \
-    --enable-comment-stripping \
-    --nindent=4 \
-    -i ${SOURCE}.tmp \
-    -o ${SOURCE}
-rm ${SOURCE}.tmp
-
-# build icons
-function build_icon() {
-  ICON_SIZE="$1"
-  TARGET="$2"
-
-  TARGET_PNG="${TARGET}.png"
-
-  inkscape \
-      --export-width=${ICON_SIZE} \
-      --export-height=${ICON_SIZE} \
-      --export-filename=${TARGET_PNG} \
-      ${SOURCE}
-
-  optipng ${OPTIPNG_OPTIONS} ${TARGET_PNG}
-}
-
-
-build_icon  72 ${BASE_DIR}/android/app/src/main/res/mipmap-hdpi/ic_launcher
-build_icon  48 ${BASE_DIR}/android/app/src/main/res/mipmap-mdpi/ic_launcher
-build_icon  96 ${BASE_DIR}/android/app/src/main/res/mipmap-xhdpi/ic_launcher
-build_icon 144 ${BASE_DIR}/android/app/src/main/res/mipmap-xxhdpi/ic_launcher
-build_icon 192 ${BASE_DIR}/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher
diff --git a/icons/button_back.svg b/icons/button_back.svg
new file mode 100644
index 0000000..2622a57
--- /dev/null
+++ b/icons/button_back.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#e41578" stroke="#fff" stroke-width=".238"/><path d="m59.387 71.362c1.1248 1.1302 4.0012 1.1302 4.0012 0v-45.921c0-1.1316-2.8832-1.1316-4.0121 0l-37.693 20.918c-1.1289 1.1248-1.1479 2.9551-0.02171 4.084z" fill="#fefeff" stroke="#930e4e" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m57.857 68.048c0.96243 0.96706 3.4236 0.96706 3.4236 0v-39.292c0-0.96825-2.467-0.96825-3.4329 0l-32.252 17.898c-0.96594 0.96243-0.9822 2.5285-0.01858 3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg>
diff --git a/icons/button_start.svg b/icons/button_start.svg
new file mode 100644
index 0000000..e9d49d2
--- /dev/null
+++ b/icons/button_start.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 93.665 93.676" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect x=".44662" y=".89101" width="92.772" height="91.894" ry="11.689" fill="#49a1ee" stroke="#fff" stroke-width=".238"/><path d="m34.852 25.44c-1.1248-1.1302-4.0012-1.1302-4.0012 0v45.921c0 1.1316 2.8832 1.1316 4.0121 0l37.693-20.918c1.1289-1.1248 1.1479-2.9551 0.02171-4.084z" fill="#fefeff" stroke="#105ca1" stroke-linecap="round" stroke-linejoin="round" stroke-width="8.257"/><path d="m36.382 28.754c-0.96243-0.96706-3.4236-0.96706-3.4236 0v39.292c0 0.96825 2.467 0.96825 3.4329 0l32.252-17.898c0.96594-0.96243 0.9822-2.5285 0.01858-3.4945z" fill="#fefeff" stroke="#feffff" stroke-linecap="round" stroke-linejoin="round" stroke-width="4.314"/></svg>
diff --git a/icons/placeholder.svg b/icons/placeholder.svg
new file mode 100644
index 0000000..23ace81
--- /dev/null
+++ b/icons/placeholder.svg
@@ -0,0 +1,2 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 102 102" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"/>
diff --git a/lib/config/default_game_settings.dart b/lib/config/default_game_settings.dart
new file mode 100644
index 0000000..a1556ef
--- /dev/null
+++ b/lib/config/default_game_settings.dart
@@ -0,0 +1,51 @@
+import 'package:petitbac/utils/tools.dart';
+
+class DefaultGameSettings {
+  // available game parameters codes
+  static const String parameterCodeItemsCount = 'itemsCount';
+  static const String parameterCodeTimerValue = 'timerValue';
+  static const List<String> availableParameters = [
+    parameterCodeItemsCount,
+    parameterCodeTimerValue,
+  ];
+
+  // items count: available values
+  static const int itemsCountValueNoLimit = 0;
+  static const int itemsCountValueShort = 5;
+  static const int itemsCountValueMedium = 10;
+  static const int itemsCountValueLong = 20;
+  static const List<int> allowedItemsCountValues = [
+    itemsCountValueNoLimit,
+    itemsCountValueShort,
+    itemsCountValueMedium,
+    itemsCountValueLong,
+  ];
+  // items count: default value
+  static const int defaultItemsCountValue = itemsCountValueMedium;
+
+  // timer value: available values
+  static const int timerValueNoTimer = 0;
+  static const int timerValueLow = 10;
+  static const int timerValueMedium = 30;
+  static const int timerValueHigh = 60;
+  static const List<int> allowedTimerValues = [
+    timerValueNoTimer,
+    timerValueLow,
+    timerValueMedium,
+    timerValueHigh,
+  ];
+  // timer value: default value
+  static const int defaultTimerValue = timerValueMedium;
+
+  static List<int> getAvailableValues(String parameterCode) {
+    switch (parameterCode) {
+      case 'itemsCount':
+        return DefaultGameSettings.allowedItemsCountValues;
+      case 'timerValue':
+        return DefaultGameSettings.allowedTimerValues;
+    }
+
+    printlog('Did not find any available value for game parameter "$parameterCode".');
+    return [];
+  }
+}
diff --git a/lib/config/default_global_settings.dart b/lib/config/default_global_settings.dart
new file mode 100644
index 0000000..363c2a1
--- /dev/null
+++ b/lib/config/default_global_settings.dart
@@ -0,0 +1,10 @@
+import 'package:petitbac/utils/tools.dart';
+
+class DefaultGlobalSettings {
+  static const List<String> availableParameters = [];
+
+  static List<int> getAvailableValues(String parameterCode) {
+    printlog('Did not find any available value for global parameter "$parameterCode".');
+    return [];
+  }
+}
diff --git a/lib/config/default_settings.dart b/lib/config/default_settings.dart
deleted file mode 100644
index fa69149..0000000
--- a/lib/config/default_settings.dart
+++ /dev/null
@@ -1,12 +0,0 @@
-class DefaultSettings {
-  static const List<int> allowedTimerValues = [
-    5,
-    10,
-    20,
-    30,
-    60,
-    90,
-  ];
-
-  static const int defaultTimerValue = 10;
-}
diff --git a/lib/config/menu.dart b/lib/config/menu.dart
index 4ba90b2..d875b6b 100644
--- a/lib/config/menu.dart
+++ b/lib/config/menu.dart
@@ -1,10 +1,9 @@
-import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:unicons/unicons.dart';
 
-import 'package:petitbac/ui/screens/about_page.dart';
-import 'package:petitbac/ui/screens/game_page.dart';
-import 'package:petitbac/ui/screens/settings_page.dart';
+import 'package:petitbac/ui/screens/page_about.dart';
+import 'package:petitbac/ui/screens/page_game.dart';
+import 'package:petitbac/ui/screens/page_settings.dart';
 
 class MenuItem {
   final String code;
@@ -19,35 +18,39 @@ class MenuItem {
 }
 
 class Menu {
-  static List<MenuItem> items = [
-    const MenuItem(
-      code: 'bottom_nav_home',
-      icon: Icon(UniconsLine.home),
-      page: GamePage(),
-    ),
-    const MenuItem(
-      code: 'bottom_nav_settings',
-      icon: Icon(UniconsLine.setting),
-      page: SettingsPage(),
-    ),
-    const MenuItem(
-      code: 'bottom_nav_about',
-      icon: Icon(UniconsLine.info_circle),
-      page: AboutPage(),
-    ),
-  ];
+  static const indexGame = 0;
+  static const menuItemGame = MenuItem(
+    code: 'bottom_nav_game',
+    icon: Icon(UniconsLine.home),
+    page: PageGame(),
+  );
 
-  static Widget getPageWidget(int pageIndex) {
-    return Menu.items.elementAt(pageIndex).page;
+  static const indexSettings = 1;
+  static const menuItemSettings = MenuItem(
+    code: 'bottom_nav_settings',
+    icon: Icon(UniconsLine.setting),
+    page: PageSettings(),
+  );
+
+  static const indexAbout = 2;
+  static const menuItemAbout = MenuItem(
+    code: 'bottom_nav_about',
+    icon: Icon(UniconsLine.info_circle),
+    page: PageAbout(),
+  );
+
+  static Map<int, MenuItem> items = {
+    indexGame: menuItemGame,
+    indexSettings: menuItemSettings,
+    indexAbout: menuItemAbout,
+  };
+
+  static bool isIndexAllowed(int pageIndex) {
+    return items.keys.contains(pageIndex);
   }
 
-  static List<BottomNavigationBarItem> getMenuItems() {
-    return Menu.items
-        .map((MenuItem item) => BottomNavigationBarItem(
-              icon: item.icon,
-              label: tr(item.code),
-            ))
-        .toList();
+  static Widget getPageWidget(int pageIndex) {
+    return items[pageIndex]?.page ?? menuItemGame.page;
   }
 
   static int itemsCount = Menu.items.length;
diff --git a/lib/cubit/game_cubit.dart b/lib/cubit/game_cubit.dart
index bfe94d2..d310d36 100644
--- a/lib/cubit/game_cubit.dart
+++ b/lib/cubit/game_cubit.dart
@@ -1,35 +1,148 @@
+import 'dart:async';
+import 'dart:math';
+
 import 'package:equatable/equatable.dart';
 import 'package:flutter/material.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
 
-import 'package:petitbac/models/game/game.dart';
+import 'package:petitbac/data/fetch_data_helper.dart';
+import 'package:petitbac/models/data/game_item.dart';
+import 'package:petitbac/models/game.dart';
+import 'package:petitbac/models/settings_game.dart';
+import 'package:petitbac/models/settings_global.dart';
 
 part 'game_state.dart';
 
 class GameCubit extends HydratedCubit<GameState> {
-  GameCubit() : super(const GameState());
+  GameCubit()
+      : super(GameState(
+          currentGame: Game.createNull(),
+        ));
+
+  void updateState(Game game) {
+    emit(GameState(
+      currentGame: game,
+    ));
+  }
+
+  void refresh() {
+    final Game game = Game(
+      gameSettings: state.currentGame.gameSettings,
+      globalSettings: state.currentGame.globalSettings,
+      items: state.currentGame.items,
+      isRunning: state.currentGame.isRunning,
+      isFinished: state.currentGame.isFinished,
+      countdown: state.currentGame.countdown,
+      position: state.currentGame.position,
+    );
+    // game.dump();
 
-  void getData(GameState gameState) {
-    emit(gameState);
+    updateState(game);
   }
 
-  void updateGameState(Game gameData) {
-    emit(GameState(game: gameData));
+  void startNewGame({
+    required GameSettings gameSettings,
+    required GlobalSettings globalSettings,
+  }) {
+    Game newGame = Game.createNew(
+      gameSettings: gameSettings,
+      globalSettings: globalSettings,
+    );
+
+    newGame.dump();
+
+    updateState(newGame);
+    startTimer();
+  }
+
+  void quitGame() {
+    state.currentGame.isRunning = false;
+    refresh();
+  }
+
+  void next() {
+    if (state.currentGame.position < (state.currentGame.gameSettings.itemsCount - 1)) {
+      state.currentGame.position++;
+      startTimer();
+    } else {
+      state.currentGame.isFinished = true;
+    }
+    refresh();
+  }
+
+  void startTimer() {
+    int timerValue = state.currentGame.gameSettings.timerValue;
+
+    if (timerValue != 0) {
+      state.currentGame.countdown = timerValue;
+
+      const Duration interval = Duration(seconds: 1);
+      Timer.periodic(
+        interval,
+        (Timer timer) {
+          if (state.currentGame.countdown != 0) {
+            state.currentGame.countdown = max(state.currentGame.countdown - 1, 0);
+            refresh();
+          }
+
+          if (state.currentGame.countdown == 0) {
+            timer.cancel();
+            if (state.currentGame.position ==
+                (state.currentGame.gameSettings.itemsCount - 1)) {
+              state.currentGame.isFinished = true;
+            }
+          }
+
+          refresh();
+        },
+      );
+    } else {
+      if (state.currentGame.position == (state.currentGame.gameSettings.itemsCount - 1)) {
+        state.currentGame.isFinished = true;
+      }
+    }
+
+    refresh();
+  }
+
+  void pickNewItem() {
+    state.currentGame.items[state.currentGame.position] = FetchDataHelper().getRandomItem();
+    refresh();
+  }
+
+  void pickNewCategory() {
+    GameItem newItem = GameItem(
+      letter: state.currentGame.letter,
+      category: FetchDataHelper().getRandomItem().category,
+    );
+
+    state.currentGame.items[state.currentGame.position] = newItem;
+    refresh();
+  }
+
+  void pickNewLetter() {
+    GameItem newItem = GameItem(
+      letter: FetchDataHelper().getRandomItem().letter,
+      category: state.currentGame.category,
+    );
+
+    state.currentGame.items[state.currentGame.position] = newItem;
+    refresh();
   }
 
   @override
   GameState? fromJson(Map<String, dynamic> json) {
-    Game game = json['game'] as Game;
+    Game currentGame = json['currentGame'] as Game;
 
     return GameState(
-      game: game,
+      currentGame: currentGame,
     );
   }
 
   @override
   Map<String, dynamic>? toJson(GameState state) {
     return <String, dynamic>{
-      'game': state.game?.toJson(),
+      'currentGame': state.currentGame.toJson(),
     };
   }
 }
diff --git a/lib/cubit/game_state.dart b/lib/cubit/game_state.dart
index 3e4d0d0..8581d72 100644
--- a/lib/cubit/game_state.dart
+++ b/lib/cubit/game_state.dart
@@ -3,13 +3,13 @@ part of 'game_cubit.dart';
 @immutable
 class GameState extends Equatable {
   const GameState({
-    this.game,
+    required this.currentGame,
   });
 
-  final Game? game;
+  final Game currentGame;
 
   @override
   List<Object?> get props => <Object?>[
-        game,
+        currentGame,
       ];
 }
diff --git a/lib/cubit/bottom_nav_cubit.dart b/lib/cubit/nav_cubit.dart
similarity index 51%
rename from lib/cubit/bottom_nav_cubit.dart
rename to lib/cubit/nav_cubit.dart
index ac26ae9..c01599b 100644
--- a/lib/cubit/bottom_nav_cubit.dart
+++ b/lib/cubit/nav_cubit.dart
@@ -2,26 +2,32 @@ import 'package:hydrated_bloc/hydrated_bloc.dart';
 
 import 'package:petitbac/config/menu.dart';
 
-class BottomNavCubit extends HydratedCubit<int> {
-  BottomNavCubit() : super(0);
+class NavCubit extends HydratedCubit<int> {
+  NavCubit() : super(0);
 
   void updateIndex(int index) {
-    if (isIndexAllowed(index)) {
+    if (Menu.isIndexAllowed(index)) {
       emit(index);
     } else {
-      goToHomePage();
+      goToGamePage();
     }
   }
 
-  bool isIndexAllowed(int index) {
-    return (index >= 0) && (index < Menu.itemsCount);
+  void goToGamePage() {
+    emit(Menu.indexGame);
   }
 
-  void goToHomePage() => emit(0);
+  void goToSettingsPage() {
+    emit(Menu.indexSettings);
+  }
+
+  void goToAboutPage() {
+    emit(Menu.indexAbout);
+  }
 
   @override
   int fromJson(Map<String, dynamic> json) {
-    return 0;
+    return Menu.indexGame;
   }
 
   @override
diff --git a/lib/cubit/settings_cubit.dart b/lib/cubit/settings_cubit.dart
deleted file mode 100644
index d105a3f..0000000
--- a/lib/cubit/settings_cubit.dart
+++ /dev/null
@@ -1,47 +0,0 @@
-import 'package:equatable/equatable.dart';
-import 'package:flutter/material.dart';
-import 'package:hydrated_bloc/hydrated_bloc.dart';
-
-import 'package:petitbac/config/default_settings.dart';
-
-part 'settings_state.dart';
-
-class SettingsCubit extends HydratedCubit<SettingsState> {
-  SettingsCubit() : super(const SettingsState());
-
-  Object getSetting(String key, [String? defaultValue]) {
-    if (state.values.keys.contains(key)) {
-      return state.values[key] ?? defaultValue ?? '';
-    }
-
-    return defaultValue ?? '';
-  }
-
-  int getTimerValue() {
-    return state.timerValue ?? DefaultSettings.defaultTimerValue;
-  }
-
-  void setValues({
-    int? timerValue,
-  }) {
-    emit(SettingsState(
-      timerValue: timerValue ?? state.timerValue,
-    ));
-  }
-
-  @override
-  SettingsState? fromJson(Map<String, dynamic> json) {
-    int timerValue = json['timerValue'] as int;
-
-    return SettingsState(
-      timerValue: timerValue,
-    );
-  }
-
-  @override
-  Map<String, dynamic>? toJson(SettingsState state) {
-    return <String, dynamic>{
-      'timerValue': state.timerValue ?? DefaultSettings.defaultTimerValue,
-    };
-  }
-}
diff --git a/lib/cubit/settings_game_cubit.dart b/lib/cubit/settings_game_cubit.dart
new file mode 100644
index 0000000..b31cae3
--- /dev/null
+++ b/lib/cubit/settings_game_cubit.dart
@@ -0,0 +1,70 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:petitbac/models/settings_game.dart';
+import 'package:petitbac/utils/tools.dart';
+
+part 'settings_game_state.dart';
+
+class GameSettingsCubit extends HydratedCubit<GameSettingsState> {
+  GameSettingsCubit() : super(GameSettingsState(settings: GameSettings.createDefault()));
+
+  void setValues({
+    int? itemsCount,
+    int? timerValue,
+  }) {
+    emit(
+      GameSettingsState(
+        settings: GameSettings(
+          itemsCount: itemsCount ?? state.settings.itemsCount,
+          timerValue: timerValue ?? state.settings.timerValue,
+        ),
+      ),
+    );
+  }
+
+  int getParameterValue(String code) {
+    switch (code) {
+      case 'itemsCount':
+        return GameSettings.getItemsCountValueFromUnsafe(state.settings.itemsCount);
+      case 'timerValue':
+        return GameSettings.getTimerValueFromUnsafe(state.settings.timerValue);
+    }
+    return 0;
+  }
+
+  void setParameterValue(String code, int value) {
+    printlog('GameSettingsCubit.setParameterValue');
+    printlog('code: $code / value: $value');
+
+    int itemsCount = code == 'itemsCount' ? value : getParameterValue('itemsCount');
+    int timerValue = code == 'timerValue' ? value : getParameterValue('timerValue');
+
+    setValues(
+      itemsCount: itemsCount,
+      timerValue: timerValue,
+    );
+  }
+
+  @override
+  GameSettingsState? fromJson(Map<String, dynamic> json) {
+    int itemsCount = json['itemsCount'] as int;
+    int timerValue = json['timerValue'] as int;
+
+    return GameSettingsState(
+      settings: GameSettings(
+        itemsCount: itemsCount,
+        timerValue: timerValue,
+      ),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GameSettingsState state) {
+    return <String, dynamic>{
+      'itemsCount': state.settings.itemsCount,
+      'timerValue': state.settings.timerValue,
+    };
+  }
+}
diff --git a/lib/cubit/settings_game_state.dart b/lib/cubit/settings_game_state.dart
new file mode 100644
index 0000000..b773dc6
--- /dev/null
+++ b/lib/cubit/settings_game_state.dart
@@ -0,0 +1,19 @@
+part of 'settings_game_cubit.dart';
+
+@immutable
+class GameSettingsState extends Equatable {
+  const GameSettingsState({
+    required this.settings,
+  });
+
+  final GameSettings settings;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        settings,
+      ];
+
+  Map<String, dynamic> get values => <String, dynamic>{
+        'settings': settings,
+      };
+}
diff --git a/lib/cubit/settings_global_cubit.dart b/lib/cubit/settings_global_cubit.dart
new file mode 100644
index 0000000..43f64fe
--- /dev/null
+++ b/lib/cubit/settings_global_cubit.dart
@@ -0,0 +1,44 @@
+import 'package:equatable/equatable.dart';
+import 'package:flutter/material.dart';
+import 'package:hydrated_bloc/hydrated_bloc.dart';
+
+import 'package:petitbac/models/settings_global.dart';
+import 'package:petitbac/utils/tools.dart';
+
+part 'settings_global_state.dart';
+
+class GlobalSettingsCubit extends HydratedCubit<GlobalSettingsState> {
+  GlobalSettingsCubit() : super(GlobalSettingsState(settings: GlobalSettings.createDefault()));
+
+  void setValues() {
+    emit(
+      GlobalSettingsState(
+        settings: GlobalSettings(),
+      ),
+    );
+  }
+
+  int getParameterValue(String code) {
+    switch (code) {}
+    return 0;
+  }
+
+  void setParameterValue(String code, int value) {
+    printlog('GlobalSettingsCubit.setParameterValue');
+    printlog('code: $code / value: $value');
+
+    setValues();
+  }
+
+  @override
+  GlobalSettingsState? fromJson(Map<String, dynamic> json) {
+    return GlobalSettingsState(
+      settings: GlobalSettings(),
+    );
+  }
+
+  @override
+  Map<String, dynamic>? toJson(GlobalSettingsState state) {
+    return <String, dynamic>{};
+  }
+}
diff --git a/lib/cubit/settings_global_state.dart b/lib/cubit/settings_global_state.dart
new file mode 100644
index 0000000..4e4fbdf
--- /dev/null
+++ b/lib/cubit/settings_global_state.dart
@@ -0,0 +1,19 @@
+part of 'settings_global_cubit.dart';
+
+@immutable
+class GlobalSettingsState extends Equatable {
+  const GlobalSettingsState({
+    required this.settings,
+  });
+
+  final GlobalSettings settings;
+
+  @override
+  List<dynamic> get props => <dynamic>[
+        settings,
+      ];
+
+  Map<String, dynamic> get values => <String, dynamic>{
+        'settings': settings,
+      };
+}
diff --git a/lib/cubit/settings_state.dart b/lib/cubit/settings_state.dart
deleted file mode 100644
index 6048256..0000000
--- a/lib/cubit/settings_state.dart
+++ /dev/null
@@ -1,19 +0,0 @@
-part of 'settings_cubit.dart';
-
-@immutable
-class SettingsState extends Equatable {
-  const SettingsState({
-    this.timerValue,
-  });
-
-  final int? timerValue;
-
-  @override
-  List<dynamic> get props => <dynamic>[
-        timerValue,
-      ];
-
-  Map<String, dynamic> get values => <String, dynamic>{
-        'timerValue': timerValue,
-      };
-}
diff --git a/lib/data/fetch_data_helper.dart b/lib/data/fetch_data_helper.dart
new file mode 100644
index 0000000..66931e9
--- /dev/null
+++ b/lib/data/fetch_data_helper.dart
@@ -0,0 +1,66 @@
+import 'dart:math';
+
+import 'package:petitbac/data/game_data.dart';
+import 'package:petitbac/models/data/category.dart';
+import 'package:petitbac/models/data/game_item.dart';
+import 'package:petitbac/models/data/letter.dart';
+import 'package:petitbac/utils/tools.dart';
+
+class FetchDataHelper {
+  FetchDataHelper();
+
+  final List<Category> _categories = [];
+  List<Category> get categories => _categories;
+
+  final List<Letter> _letters = [];
+  List<Letter> get letters => _letters;
+
+  void init() {
+    try {
+      final List<dynamic> rawCategories = GameData.data['categories'] as List<dynamic>;
+      for (var rawElement in rawCategories) {
+        final categoryCode = rawElement.toString();
+        _categories.add(Category(
+          key: categoryCode,
+          text: categoryCode,
+        ));
+      }
+    } catch (e) {
+      printlog("$e");
+    }
+
+    const String chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+    for (var char in chars.split('')) {
+      _letters.add(Letter(key: char, text: char));
+    }
+  }
+
+  List<GameItem> getRandomItems(int count) {
+    if (_categories.isEmpty || _letters.isEmpty) {
+      init();
+    }
+
+    // will pick at least one item
+    int realCount = max(count, 1);
+
+    List<Category> categories = _categories;
+    categories.shuffle();
+
+    List<Letter> letters = _letters;
+    letters.shuffle();
+
+    List<GameItem> items = [];
+    for (var i = 0; i < realCount; i++) {
+      items.add(GameItem(
+        letter: letters.elementAt(i),
+        category: categories.elementAt(i),
+      ));
+    }
+
+    return items;
+  }
+
+  GameItem getRandomItem() {
+    return getRandomItems(1).first;
+  }
+}
diff --git a/lib/data/game_data.dart b/lib/data/game_data.dart
new file mode 100644
index 0000000..563adb1
--- /dev/null
+++ b/lib/data/game_data.dart
@@ -0,0 +1,66 @@
+class GameData {
+  static const Map<String, dynamic> data = {
+    "categories": [
+      "Pays",
+      "Prénom fille",
+      "Prénom garçon",
+      "Animal",
+      "Métier",
+      "Villes",
+      "Dessin animé",
+      "Film",
+      "Auteur de littérature",
+      "Acteur ou actrice",
+      "Chanteur ou chanteuse",
+      "Chose ou objet",
+      "Fruit ou légume",
+      "Couleur",
+      "Marque",
+      "Moyen de transport",
+      "Outil",
+      "Capitale",
+      "Instrument de musique",
+      "Boisson",
+      "Fleur",
+      "Plat",
+      "Personnage historique",
+      "Vêtement",
+      "Minéral ou pierre précieuse",
+      "Étoile, planète ou constellation",
+      "Fleuve, cours d'eau ou océan",
+      "Partie du corps humain",
+      "Oiseau",
+      "Poisson",
+      "Qualité ou défaut",
+      "Arbre",
+      "Bande dessinée",
+      "Département français",
+      "Insecte",
+      "Dessert",
+      "Mammifère",
+      "Épice",
+      "Héros de mythologie",
+      "Héros fictif",
+      "Fromage",
+      "Jeu",
+      "Élément de véhicules",
+      "Site internet",
+      "Mot de plus de 8 lettres",
+      "Cadeau de Noël",
+      "Mot en anglais",
+      "Mot en espagnol",
+      "Métier dont rêvent les enfants",
+      "Chose qui se trouve dans une voiture",
+      "Chose qui se trouve dans un camping",
+      "Chose qui se trouve dans un cartable",
+      "Chose qui se trouve dans une maison",
+      "Chose qui se trouve dans une forêt",
+      "Chose qui se trouve dans la mer",
+      "Ville française",
+      "Qui sent mauvais",
+      "Qui fait plaisir",
+      "Mauvais pour la santé",
+      "Mauvais pour l'environement",
+    ]
+  };
+}
diff --git a/lib/main.dart b/lib/main.dart
index 462abf0..4c088e7 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -6,18 +6,17 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:hive/hive.dart';
 import 'package:hydrated_bloc/hydrated_bloc.dart';
 import 'package:path_provider/path_provider.dart';
-import 'package:petitbac/cubit/theme_cubit.dart';
-import 'package:provider/provider.dart';
 
 import 'package:petitbac/config/theme.dart';
-import 'package:petitbac/cubit/bottom_nav_cubit.dart';
 import 'package:petitbac/cubit/game_cubit.dart';
-import 'package:petitbac/cubit/settings_cubit.dart';
-import 'package:petitbac/provider/data.dart';
+import 'package:petitbac/cubit/nav_cubit.dart';
+import 'package:petitbac/cubit/settings_game_cubit.dart';
+import 'package:petitbac/cubit/settings_global_cubit.dart';
+import 'package:petitbac/cubit/theme_cubit.dart';
 import 'package:petitbac/ui/skeleton.dart';
 
 void main() async {
-  /// Initialize packages
+  // Initialize packages
   WidgetsFlutterBinding.ensureInitialized();
   await EasyLocalization.ensureInitialized();
   final Directory tmpDir = await getTemporaryDirectory();
@@ -47,32 +46,31 @@ class MyApp extends StatelessWidget {
   Widget build(BuildContext context) {
     return MultiBlocProvider(
       providers: [
-        BlocProvider<BottomNavCubit>(create: (context) => BottomNavCubit()),
-        BlocProvider<GameCubit>(create: (context) => GameCubit()),
-        BlocProvider<SettingsCubit>(create: (context) => SettingsCubit()),
+        BlocProvider<NavCubit>(create: (context) => NavCubit()),
         BlocProvider<ThemeCubit>(create: (context) => ThemeCubit()),
+        BlocProvider<GameCubit>(create: (context) => GameCubit()),
+        BlocProvider<GlobalSettingsCubit>(create: (context) => GlobalSettingsCubit()),
+        BlocProvider<GameSettingsCubit>(create: (context) => GameSettingsCubit()),
       ],
       child: BlocBuilder<ThemeCubit, ThemeModeState>(
-          builder: (BuildContext context, ThemeModeState state) {
-        return ChangeNotifierProvider(
-          create: (BuildContext context) => Data(),
-          child: Consumer<Data>(
-            builder: (context, data, child) {
-              return MaterialApp(
-                title: 'Petit Bac',
-                theme: lightTheme,
-                darkTheme: darkTheme,
-                themeMode: state.themeMode,
-                home: const SkeletonScreen(),
-                localizationsDelegates: context.localizationDelegates,
-                supportedLocales: context.supportedLocales,
-                locale: context.locale,
-                debugShowCheckedModeBanner: false,
-              );
-            },
-          ),
-        );
-      }),
+        builder: (BuildContext context, ThemeModeState state) {
+          return MaterialApp(
+            title: 'Petit Bac',
+            home: const SkeletonScreen(),
+
+            // Theme stuff
+            theme: lightTheme,
+            darkTheme: darkTheme,
+            themeMode: state.themeMode,
+
+            // Localization stuff
+            localizationsDelegates: context.localizationDelegates,
+            supportedLocales: context.supportedLocales,
+            locale: context.locale,
+            debugShowCheckedModeBanner: false,
+          );
+        },
+      ),
     );
   }
 }
diff --git a/lib/models/data/category.dart b/lib/models/data/category.dart
new file mode 100644
index 0000000..ffe80be
--- /dev/null
+++ b/lib/models/data/category.dart
@@ -0,0 +1,21 @@
+class Category {
+  final String key;
+  final String text;
+
+  const Category({
+    required this.key,
+    required this.text,
+  });
+
+  @override
+  String toString() {
+    return '$Category(${toJson()})';
+  }
+
+  Map<String, dynamic> toJson() {
+    return {
+      'key': key,
+      'text': text,
+    };
+  }
+}
diff --git a/lib/models/data/game_item.dart b/lib/models/data/game_item.dart
new file mode 100644
index 0000000..fb0aa31
--- /dev/null
+++ b/lib/models/data/game_item.dart
@@ -0,0 +1,24 @@
+import 'package:petitbac/models/data/category.dart';
+import 'package:petitbac/models/data/letter.dart';
+
+class GameItem {
+  final Letter letter;
+  final Category category;
+
+  GameItem({
+    required this.letter,
+    required this.category,
+  });
+
+  @override
+  String toString() {
+    return '$GameItem(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'letter': letter.toJson(),
+      'category': category.toJson(),
+    };
+  }
+}
diff --git a/lib/models/data/letter.dart b/lib/models/data/letter.dart
new file mode 100644
index 0000000..7827fe5
--- /dev/null
+++ b/lib/models/data/letter.dart
@@ -0,0 +1,21 @@
+class Letter {
+  final String key;
+  final String text;
+
+  const Letter({
+    required this.key,
+    required this.text,
+  });
+
+  @override
+  String toString() {
+    return '$Letter(${toJson()})';
+  }
+
+  Map<String, dynamic> toJson() {
+    return {
+      'key': key,
+      'text': text,
+    };
+  }
+}
diff --git a/lib/models/game.dart b/lib/models/game.dart
new file mode 100644
index 0000000..9cdb175
--- /dev/null
+++ b/lib/models/game.dart
@@ -0,0 +1,100 @@
+import 'package:petitbac/data/fetch_data_helper.dart';
+import 'package:petitbac/models/data/category.dart';
+import 'package:petitbac/models/data/game_item.dart';
+import 'package:petitbac/models/data/letter.dart';
+import 'package:petitbac/models/settings_game.dart';
+import 'package:petitbac/models/settings_global.dart';
+import 'package:petitbac/utils/tools.dart';
+
+class Game {
+  final List<GameItem> items;
+  final GameSettings gameSettings;
+  final GlobalSettings globalSettings;
+  int countdown = 0;
+  int position = 0;
+  bool isRunning = false;
+  bool isFinished = false;
+
+  Game({
+    required this.items,
+    required this.gameSettings,
+    required this.globalSettings,
+    required this.countdown,
+    required this.position,
+    this.isRunning = false,
+    this.isFinished = false,
+  });
+
+  factory Game.createNull() {
+    return Game(
+      items: [],
+      gameSettings: GameSettings.createDefault(),
+      globalSettings: GlobalSettings.createDefault(),
+      countdown: 0,
+      position: 0,
+    );
+  }
+
+  factory Game.createNew({
+    GameSettings? gameSettings,
+    GlobalSettings? globalSettings,
+  }) {
+    GameSettings newGameSettings = gameSettings ?? GameSettings.createDefault();
+    GlobalSettings newGlobalSettings = globalSettings ?? GlobalSettings.createDefault();
+
+    List<GameItem> items = FetchDataHelper().getRandomItems(newGameSettings.itemsCount);
+
+    return Game(
+      items: items,
+      gameSettings: newGameSettings,
+      globalSettings: newGlobalSettings,
+      countdown: 0,
+      position: 0,
+      isRunning: true,
+      isFinished: false,
+    );
+  }
+
+  void stop() {
+    isRunning = false;
+  }
+
+  GameItem get item => items[position];
+  Category get category => item.category;
+  Letter get letter => item.letter;
+
+  void dump() {
+    printlog('');
+    printlog('## Current game dump:');
+    printlog('');
+    gameSettings.dump();
+    globalSettings.dump();
+    printlog('');
+    printlog('items:');
+    printlog(items.toString());
+    printlog('');
+    printlog('Game: ');
+    printlog('  isRunning: $isRunning');
+    printlog('  isFinished: $isFinished');
+    printlog('  position: $position');
+    printlog('  countdown: $countdown');
+    printlog('');
+  }
+
+  @override
+  String toString() {
+    return '$Game(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'items': items,
+      'gameSettings': gameSettings,
+      'globalSettings': globalSettings,
+      'countdown': countdown,
+      'position': position,
+      'isRunning': isRunning,
+      'isFinished': isFinished,
+    };
+  }
+}
diff --git a/lib/models/game/game.dart b/lib/models/game/game.dart
deleted file mode 100644
index ebe3d57..0000000
--- a/lib/models/game/game.dart
+++ /dev/null
@@ -1,38 +0,0 @@
-import 'package:petitbac/utils/tools.dart';
-
-class Game {
-  bool isRunning = false;
-
-  Game({
-    this.isRunning = false,
-  });
-
-  factory Game.createNull() {
-    return Game();
-  }
-
-  factory Game.createNew() {
-    return Game(
-      isRunning: true,
-    );
-  }
-
-  void stop() {
-    isRunning = false;
-  }
-
-  @override
-  String toString() {
-    return 'Game(${toJson()})';
-  }
-
-  Map<String, dynamic>? toJson() {
-    return <String, dynamic>{
-      'isRunning': isRunning,
-    };
-  }
-
-  void dump() {
-    printlog(toString());
-  }
-}
diff --git a/lib/models/settings_game.dart b/lib/models/settings_game.dart
new file mode 100644
index 0000000..5262546
--- /dev/null
+++ b/lib/models/settings_game.dart
@@ -0,0 +1,53 @@
+import 'package:petitbac/config/default_game_settings.dart';
+import 'package:petitbac/utils/tools.dart';
+
+class GameSettings {
+  final int itemsCount;
+  final int timerValue;
+
+  GameSettings({
+    required this.itemsCount,
+    required this.timerValue,
+  });
+
+  static int getItemsCountValueFromUnsafe(int itemsCount) {
+    if (DefaultGameSettings.allowedItemsCountValues.contains(itemsCount)) {
+      return itemsCount;
+    }
+
+    return DefaultGameSettings.defaultItemsCountValue;
+  }
+
+  static int getTimerValueFromUnsafe(int timerValue) {
+    if (DefaultGameSettings.allowedTimerValues.contains(timerValue)) {
+      return timerValue;
+    }
+
+    return DefaultGameSettings.defaultTimerValue;
+  }
+
+  factory GameSettings.createDefault() {
+    return GameSettings(
+      itemsCount: DefaultGameSettings.defaultItemsCountValue,
+      timerValue: DefaultGameSettings.defaultTimerValue,
+    );
+  }
+
+  void dump() {
+    printlog('Game settings: ');
+    printlog('  itemsCount: $itemsCount');
+    printlog('  timerValue: $timerValue');
+  }
+
+  @override
+  String toString() {
+    return '$GameSettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{
+      'itemsCount': itemsCount,
+      'timerValue': timerValue,
+    };
+  }
+}
diff --git a/lib/models/settings_global.dart b/lib/models/settings_global.dart
new file mode 100644
index 0000000..2448620
--- /dev/null
+++ b/lib/models/settings_global.dart
@@ -0,0 +1,23 @@
+import 'package:petitbac/utils/tools.dart';
+
+class GlobalSettings {
+  GlobalSettings();
+
+  factory GlobalSettings.createDefault() {
+    return GlobalSettings();
+  }
+
+  void dump() {
+    printlog('Global settings: ');
+    printlog('  (none)');
+  }
+
+  @override
+  String toString() {
+    return '$GlobalSettings(${toJson()})';
+  }
+
+  Map<String, dynamic>? toJson() {
+    return <String, dynamic>{};
+  }
+}
diff --git a/lib/provider/data.dart b/lib/provider/data.dart
deleted file mode 100644
index ebbe397..0000000
--- a/lib/provider/data.dart
+++ /dev/null
@@ -1,76 +0,0 @@
-import 'package:flutter/foundation.dart';
-
-class Data extends ChangeNotifier {
-  bool _searchingCategory = false;
-  bool _searchingLetter = false;
-
-  String _category = '';
-  String _letter = '';
-
-  int _countdown = -1;
-
-  final int _recentCategoriesCount = 15;
-  final int _recentLettersCount = 10;
-  List<String> _recentCategories = [];
-  List<String> _recentLetters = [];
-
-  bool get searchingCategory => _searchingCategory;
-  void setSearchingCategory(bool value) {
-    _searchingCategory = value;
-    notifyListeners();
-  }
-
-  bool get searchingLetter => _searchingLetter;
-  void setSearchingLetter(bool value) {
-    _searchingLetter = value;
-    notifyListeners();
-  }
-
-  String get category => _category;
-  void updateCategory(String value) {
-    _category = value;
-    if (value != '') {
-      _recentCategories.insert(0, value);
-      _recentCategories = _recentCategories.take(_recentCategoriesCount).toList();
-    }
-    notifyListeners();
-  }
-
-  String get letter => _letter;
-  void updateLetter(String value) {
-    _letter = value;
-    if (value != '') {
-      _recentLetters.insert(0, value);
-      _recentLetters = _recentLetters.take(_recentLettersCount).toList();
-    }
-    notifyListeners();
-  }
-
-  String recentlyPickedLetter(int count) {
-    if (_recentLetters.length > count) {
-      return _recentLetters[count];
-    }
-    return '';
-  }
-
-  bool isCategoryRecentlyPicked(String category) {
-    return _recentCategories.contains(category);
-  }
-
-  bool isLetterRecentlyPicked(String letter) {
-    return _recentLetters.contains(letter);
-  }
-
-  int get countdown => _countdown;
-  void updateCountdown(int value) {
-    _countdown = value;
-    notifyListeners();
-  }
-
-  void resetGame() {
-    _category = '';
-    _letter = '';
-    _countdown = 0;
-    notifyListeners();
-  }
-}
diff --git a/lib/ui/painters/parameter_painter.dart b/lib/ui/painters/parameter_painter.dart
new file mode 100644
index 0000000..2509c75
--- /dev/null
+++ b/lib/ui/painters/parameter_painter.dart
@@ -0,0 +1,225 @@
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+
+import 'package:petitbac/config/default_game_settings.dart';
+import 'package:petitbac/models/settings_game.dart';
+import 'package:petitbac/models/settings_global.dart';
+import 'package:petitbac/utils/tools.dart';
+
+class ParameterPainter extends CustomPainter {
+  const ParameterPainter({
+    required this.code,
+    required this.value,
+    required this.isSelected,
+    required this.gameSettings,
+    required this.globalSettings,
+  });
+
+  final String code;
+  final int value;
+  final bool isSelected;
+  final GameSettings gameSettings;
+  final GlobalSettings globalSettings;
+
+  @override
+  void paint(Canvas canvas, Size size) {
+    // force square
+    final double canvasSize = min(size.width, size.height);
+
+    const Color borderColorEnabled = Colors.blue;
+    const Color borderColorDisabled = Colors.white;
+
+    // "enabled/disabled" border
+    final paint = Paint();
+    paint.style = PaintingStyle.stroke;
+    paint.color = isSelected ? borderColorEnabled : borderColorDisabled;
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 10;
+    canvas.drawRect(
+        Rect.fromPoints(const Offset(0, 0), Offset(canvasSize, canvasSize)), paint);
+
+    // content
+    switch (code) {
+      case DefaultGameSettings.parameterCodeItemsCount:
+        paintItemsCountParameterItem(value, canvas, canvasSize);
+        break;
+      case DefaultGameSettings.parameterCodeTimerValue:
+        paintTimerParameterItem(value, canvas, canvasSize);
+        break;
+      default:
+        printlog('Unknown parameter: $code/$value');
+        paintUnknownParameterItem(value, canvas, canvasSize);
+    }
+  }
+
+  @override
+  bool shouldRepaint(CustomPainter oldDelegate) {
+    return false;
+  }
+
+  // "unknown" parameter -> simple block with text
+  void paintUnknownParameterItem(
+    final int value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3;
+
+    paint.color = Colors.grey;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    final textSpan = TextSpan(
+      text: '?\n$value',
+      style: const TextStyle(
+        color: Colors.black,
+        fontSize: 18,
+        fontWeight: FontWeight.bold,
+      ),
+    );
+    final textPainter = TextPainter(
+      text: textSpan,
+      textDirection: TextDirection.ltr,
+      textAlign: TextAlign.center,
+    );
+    textPainter.layout();
+    textPainter.paint(
+      canvas,
+      Offset(
+        (size - textPainter.width) * 0.5,
+        (size - textPainter.height) * 0.5,
+      ),
+    );
+  }
+
+  void paintItemsCountParameterItem(
+    final int value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    const itemCountEmoji = '💬\n';
+
+    Color backgroundColor = Colors.grey;
+    String text = '';
+
+    switch (value) {
+      case DefaultGameSettings.itemsCountValueNoLimit:
+        backgroundColor = Colors.grey;
+        text = '⭐';
+        break;
+      case DefaultGameSettings.itemsCountValueShort:
+        backgroundColor = Colors.green;
+        text = itemCountEmoji + DefaultGameSettings.itemsCountValueShort.toString();
+        break;
+      case DefaultGameSettings.itemsCountValueMedium:
+        backgroundColor = Colors.orange;
+        text = itemCountEmoji + DefaultGameSettings.itemsCountValueMedium.toString();
+        break;
+      case DefaultGameSettings.itemsCountValueLong:
+        backgroundColor = Colors.red;
+        text = itemCountEmoji + DefaultGameSettings.itemsCountValueLong.toString();
+        break;
+      default:
+        printlog('Wrong value for itemsCount parameter value: $value');
+    }
+
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3 / 100 * size;
+
+    // Colored background
+    paint.color = backgroundColor;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    // centered text value
+    final textSpan = TextSpan(
+      text: text,
+      style: TextStyle(
+        color: Colors.black,
+        fontSize: size / 2.6,
+        fontWeight: FontWeight.bold,
+      ),
+    );
+    final textPainter = TextPainter(
+      text: textSpan,
+      textDirection: TextDirection.ltr,
+      textAlign: TextAlign.center,
+    );
+    textPainter.layout();
+    textPainter.paint(
+      canvas,
+      Offset(
+        (size - textPainter.width) * 0.5,
+        (size - textPainter.height) * 0.5,
+      ),
+    );
+  }
+
+  void paintTimerParameterItem(
+    final int value,
+    final Canvas canvas,
+    final double size,
+  ) {
+    const timerEmoji = '⏲️\n';
+
+    Color backgroundColor = Colors.grey;
+    String text = '';
+
+    switch (value) {
+      case DefaultGameSettings.timerValueNoTimer:
+        backgroundColor = Colors.grey;
+        text = '⭐';
+        break;
+      case DefaultGameSettings.timerValueLow:
+        backgroundColor = Colors.green;
+        text = '$timerEmoji${DefaultGameSettings.timerValueLow}"';
+        break;
+      case DefaultGameSettings.timerValueMedium:
+        backgroundColor = Colors.orange;
+        text = '$timerEmoji${DefaultGameSettings.timerValueMedium}"';
+        break;
+      case DefaultGameSettings.timerValueHigh:
+        backgroundColor = Colors.red;
+        text = '$timerEmoji${DefaultGameSettings.timerValueHigh}"';
+        break;
+      default:
+        printlog('Wrong value for itemsCount parameter value: $value');
+    }
+
+    final paint = Paint();
+    paint.strokeJoin = StrokeJoin.round;
+    paint.strokeWidth = 3 / 100 * size;
+
+    // Colored background
+    paint.color = backgroundColor;
+    paint.style = PaintingStyle.fill;
+    canvas.drawRect(Rect.fromPoints(const Offset(0, 0), Offset(size, size)), paint);
+
+    // centered text value
+    final textSpan = TextSpan(
+      text: text,
+      style: TextStyle(
+        color: Colors.black,
+        fontSize: size / 2.6,
+        fontWeight: FontWeight.bold,
+      ),
+    );
+    final textPainter = TextPainter(
+      text: textSpan,
+      textDirection: TextDirection.ltr,
+      textAlign: TextAlign.center,
+    );
+    textPainter.layout();
+    textPainter.paint(
+      canvas,
+      Offset(
+        (size - textPainter.width) * 0.5,
+        (size - textPainter.height) * 0.5,
+      ),
+    );
+  }
+}
diff --git a/lib/ui/screens/game_page.dart b/lib/ui/screens/game_page.dart
deleted file mode 100644
index 125ea95..0000000
--- a/lib/ui/screens/game_page.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:petitbac/ui/widgets/mini_game.dart';
-import 'package:petitbac/ui/widgets/picked_category.dart';
-import 'package:petitbac/ui/widgets/picked_letter.dart';
-
-class GamePage extends StatelessWidget {
-  const GamePage({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    const double borderWidth = 8;
-
-    return const Column(
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: <Widget>[
-        PickedLetter(
-          backgroundColor: Colors.orange,
-          borderWidth: borderWidth,
-        ),
-        SizedBox(height: 5),
-        MiniGame(
-          backgroundColor: Colors.blue,
-          borderWidth: borderWidth,
-        ),
-        SizedBox(height: 5),
-        PickedCategory(
-          backgroundColor: Colors.green,
-          borderWidth: borderWidth,
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/screens/about_page.dart b/lib/ui/screens/page_about.dart
similarity index 86%
rename from lib/ui/screens/about_page.dart
rename to lib/ui/screens/page_about.dart
index dd5c176..1720556 100644
--- a/lib/ui/screens/about_page.dart
+++ b/lib/ui/screens/page_about.dart
@@ -2,10 +2,10 @@ import 'package:easy_localization/easy_localization.dart';
 import 'package:flutter/material.dart';
 import 'package:package_info_plus/package_info_plus.dart';
 
-import 'package:petitbac/ui/widgets/header_app.dart';
+import 'package:petitbac/ui/widgets/helpers/app_header.dart';
 
-class AboutPage extends StatelessWidget {
-  const AboutPage({super.key});
+class PageAbout extends StatelessWidget {
+  const PageAbout({super.key});
 
   @override
   Widget build(BuildContext context) {
@@ -14,7 +14,6 @@ class AboutPage extends StatelessWidget {
       crossAxisAlignment: CrossAxisAlignment.start,
       mainAxisSize: MainAxisSize.max,
       children: <Widget>[
-        const SizedBox(height: 8),
         const AppHeader(text: 'about_title'),
         const Text('about_content').tr(),
         FutureBuilder<PackageInfo>(
diff --git a/lib/ui/screens/page_game.dart b/lib/ui/screens/page_game.dart
new file mode 100644
index 0000000..933478a
--- /dev/null
+++ b/lib/ui/screens/page_game.dart
@@ -0,0 +1,18 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:petitbac/cubit/game_cubit.dart';
+import 'package:petitbac/ui/widgets/game/game.dart';
+import 'package:petitbac/ui/widgets/parameters.dart';
+
+class PageGame extends StatelessWidget {
+  const PageGame({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+        builder: (BuildContext context, GameState gameState) {
+      return gameState.currentGame.isRunning ? const GameWidget() : const Parameters();
+    });
+  }
+}
diff --git a/lib/ui/screens/settings_page.dart b/lib/ui/screens/page_settings.dart
similarity index 64%
rename from lib/ui/screens/settings_page.dart
rename to lib/ui/screens/page_settings.dart
index 216fad9..d8690b9 100644
--- a/lib/ui/screens/settings_page.dart
+++ b/lib/ui/screens/page_settings.dart
@@ -1,10 +1,10 @@
 import 'package:flutter/material.dart';
 
-import 'package:petitbac/ui/widgets/header_app.dart';
-import 'package:petitbac/ui/widgets/settings_form.dart';
+import 'package:petitbac/ui/widgets/helpers/app_header.dart';
+import 'package:petitbac/ui/widgets/settings/settings_form.dart';
 
-class SettingsPage extends StatelessWidget {
-  const SettingsPage({super.key});
+class PageSettings extends StatelessWidget {
+  const PageSettings({super.key});
 
   @override
   Widget build(BuildContext context) {
@@ -13,7 +13,6 @@ class SettingsPage extends StatelessWidget {
       crossAxisAlignment: CrossAxisAlignment.start,
       mainAxisSize: MainAxisSize.max,
       children: <Widget>[
-        SizedBox(height: 8),
         AppHeader(text: 'settings_title'),
         SizedBox(height: 8),
         SettingsForm(),
diff --git a/lib/ui/skeleton.dart b/lib/ui/skeleton.dart
index f5fc21f..789d18b 100644
--- a/lib/ui/skeleton.dart
+++ b/lib/ui/skeleton.dart
@@ -1,43 +1,32 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_swipe/flutter_swipe.dart';
 
 import 'package:petitbac/config/menu.dart';
-import 'package:petitbac/cubit/bottom_nav_cubit.dart';
-import 'package:petitbac/ui/widgets/app_bar.dart';
-import 'package:petitbac/ui/widgets/bottom_nav_bar.dart';
+import 'package:petitbac/cubit/nav_cubit.dart';
+import 'package:petitbac/ui/widgets/global_app_bar.dart';
 
-class SkeletonScreen extends StatefulWidget {
+class SkeletonScreen extends StatelessWidget {
   const SkeletonScreen({super.key});
 
-  @override
-  State<SkeletonScreen> createState() => _SkeletonScreenState();
-}
-
-class _SkeletonScreenState extends State<SkeletonScreen> {
   @override
   Widget build(BuildContext context) {
     return Scaffold(
+      appBar: const GlobalAppBar(),
       extendBodyBehindAppBar: false,
-      appBar: const StandardAppBar(),
-      body: Swiper(
-        itemCount: Menu.itemsCount,
-        itemBuilder: (BuildContext context, int index) {
-          return Menu.getPageWidget(index);
-        },
-        pagination: SwiperPagination(
-          margin: const EdgeInsets.all(0),
-          builder: SwiperCustomPagination(
-            builder: (BuildContext context, SwiperPluginConfig config) {
-              return BottomNavBar(swipeController: config.controller);
-            },
-          ),
+      body: Material(
+        color: Theme.of(context).colorScheme.background,
+        child: BlocBuilder<NavCubit, int>(
+          builder: (BuildContext context, int pageIndex) {
+            return Padding(
+              padding: const EdgeInsets.only(
+                top: 8,
+                left: 2,
+                right: 2,
+              ),
+              child: Menu.getPageWidget(pageIndex),
+            );
+          },
         ),
-        onIndexChanged: (newPageIndex) {
-          BlocProvider.of<BottomNavCubit>(context).updateIndex(newPageIndex);
-        },
-        outer: true,
-        loop: false,
       ),
       backgroundColor: Theme.of(context).colorScheme.background,
     );
diff --git a/lib/ui/widgets/app_bar.dart b/lib/ui/widgets/app_bar.dart
deleted file mode 100644
index 2e76fc6..0000000
--- a/lib/ui/widgets/app_bar.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:petitbac/ui/widgets/header_app.dart';
-
-class StandardAppBar extends StatelessWidget implements PreferredSizeWidget {
-  const StandardAppBar({super.key});
-
-  @override
-  Widget build(BuildContext context) {
-    return AppBar(
-      title: const AppHeader(text: 'app_name'),
-      actions: const [
-        //
-      ],
-    );
-  }
-
-  @override
-  Size get preferredSize => const Size.fromHeight(50);
-}
diff --git a/lib/ui/widgets/bottom_nav_bar.dart b/lib/ui/widgets/bottom_nav_bar.dart
deleted file mode 100644
index d9f18ee..0000000
--- a/lib/ui/widgets/bottom_nav_bar.dart
+++ /dev/null
@@ -1,40 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:flutter_swipe/flutter_swipe.dart';
-
-import 'package:petitbac/config/menu.dart';
-import 'package:petitbac/cubit/bottom_nav_cubit.dart';
-
-class BottomNavBar extends StatelessWidget {
-  const BottomNavBar({super.key, required this.swipeController});
-
-  final SwiperController swipeController;
-
-  @override
-  Widget build(BuildContext context) {
-    return Card(
-      margin: const EdgeInsets.all(0),
-      elevation: 4,
-      shadowColor: Theme.of(context).colorScheme.shadow,
-      color: Theme.of(context).colorScheme.surfaceVariant,
-      shape: const ContinuousRectangleBorder(),
-      child: BlocBuilder<BottomNavCubit, int>(
-        builder: (BuildContext context, int state) {
-          return BottomNavigationBar(
-            currentIndex: state,
-            onTap: (int index) {
-              context.read<BottomNavCubit>().updateIndex(index);
-              swipeController.move(index);
-            },
-            type: BottomNavigationBarType.fixed,
-            elevation: 0,
-            backgroundColor: Colors.transparent,
-            selectedItemColor: Theme.of(context).colorScheme.primary,
-            unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color,
-            items: Menu.getMenuItems(),
-          );
-        },
-      ),
-    );
-  }
-}
diff --git a/lib/ui/widgets/button_game_start_new.dart b/lib/ui/widgets/button_game_start_new.dart
new file mode 100644
index 0000000..2b0ca95
--- /dev/null
+++ b/lib/ui/widgets/button_game_start_new.dart
@@ -0,0 +1,34 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:petitbac/cubit/game_cubit.dart';
+import 'package:petitbac/cubit/settings_game_cubit.dart';
+import 'package:petitbac/cubit/settings_global_cubit.dart';
+
+class StartNewGameButton extends StatelessWidget {
+  const StartNewGameButton({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameSettingsCubit, GameSettingsState>(
+      builder: (BuildContext context, GameSettingsState gameSettingsState) {
+        return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
+          builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
+            final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+
+            return TextButton(
+              child: const Image(
+                image: AssetImage('assets/icons/button_start.png'),
+                fit: BoxFit.fill,
+              ),
+              onPressed: () => gameCubit.startNewGame(
+                gameSettings: gameSettingsState.settings,
+                globalSettings: globalSettingsState.settings,
+              ),
+            );
+          },
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/game.dart b/lib/ui/widgets/game/game.dart
new file mode 100644
index 0000000..b7384eb
--- /dev/null
+++ b/lib/ui/widgets/game/game.dart
@@ -0,0 +1,37 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:petitbac/cubit/game_cubit.dart';
+import 'package:petitbac/models/game.dart';
+import 'package:petitbac/ui/widgets/game/game_countdown.dart';
+import 'package:petitbac/ui/widgets/game/game_position_indicator.dart';
+import 'package:petitbac/ui/widgets/game/widget_category.dart';
+import 'package:petitbac/ui/widgets/game/widget_letter.dart';
+
+class GameWidget extends StatelessWidget {
+  const GameWidget({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        return Center(
+          child: Column(
+            mainAxisAlignment: MainAxisAlignment.start,
+            crossAxisAlignment: CrossAxisAlignment.center,
+            children: [
+              currentGame.gameSettings.itemsCount != 0
+                  ? const GamePositionIndicator()
+                  : const SizedBox.shrink(),
+              const WidgetLetter(),
+              const GameButtonNextWithCountdown(),
+              const WidgetCategory(),
+            ],
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/game_countdown.dart b/lib/ui/widgets/game/game_countdown.dart
new file mode 100644
index 0000000..508f35f
--- /dev/null
+++ b/lib/ui/widgets/game/game_countdown.dart
@@ -0,0 +1,82 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:petitbac/cubit/game_cubit.dart';
+import 'package:petitbac/cubit/settings_game_cubit.dart';
+import 'package:petitbac/models/game.dart';
+import 'package:petitbac/utils/color_extensions.dart';
+
+class GameButtonNextWithCountdown extends StatelessWidget {
+  const GameButtonNextWithCountdown({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        const Color backgroundColor = Colors.blue;
+        const double borderWidth = 8.0;
+        final Color borderColor = backgroundColor.darken();
+
+        const Color textColor = Colors.black;
+
+        return BlocBuilder<GameSettingsCubit, GameSettingsState>(
+          builder: (context, settingsSate) {
+            return Column(
+              mainAxisSize: MainAxisSize.min,
+              mainAxisAlignment: MainAxisAlignment.center,
+              children: [
+                const SizedBox(height: 5),
+                Container(
+                  margin: const EdgeInsets.all(borderWidth),
+                  padding: const EdgeInsets.all(borderWidth),
+                  decoration: BoxDecoration(
+                    color: backgroundColor,
+                    borderRadius: BorderRadius.circular(borderWidth),
+                    border: Border.all(
+                      color: borderColor,
+                      width: borderWidth,
+                    ),
+                  ),
+                  child: TextButton(
+                    onPressed: () {
+                      final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+
+                      if (currentGame.isFinished) {
+                        gameCubit.quitGame();
+                      } else {
+                        if (currentGame.gameSettings.itemsCount == 0) {
+                          gameCubit.pickNewItem();
+                          gameCubit.startTimer();
+                        } else {
+                          if (currentGame.countdown == 0) {
+                            gameCubit.next();
+                          }
+                        }
+                      }
+                    },
+                    child: Text(
+                      currentGame.isFinished
+                          ? '🎆'
+                          : ((currentGame.countdown == 0)
+                              ? '🎲'
+                              : currentGame.countdown.toString()),
+                      textAlign: TextAlign.center,
+                      style: const TextStyle(
+                        fontSize: 50,
+                        fontWeight: FontWeight.w600,
+                        color: textColor,
+                      ),
+                    ),
+                  ),
+                ),
+                const SizedBox(height: 5),
+              ],
+            );
+          },
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/game_position_indicator.dart b/lib/ui/widgets/game/game_position_indicator.dart
new file mode 100644
index 0000000..84b3af5
--- /dev/null
+++ b/lib/ui/widgets/game/game_position_indicator.dart
@@ -0,0 +1,50 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:petitbac/cubit/game_cubit.dart';
+import 'package:petitbac/models/game.dart';
+import 'package:petitbac/ui/widgets/helpers/outlined_text_widget.dart';
+import 'package:petitbac/utils/color_extensions.dart';
+
+class GamePositionIndicator extends StatelessWidget {
+  const GamePositionIndicator({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final int currentPosition = currentGame.position + 1;
+        final int maxPosition = currentGame.gameSettings.itemsCount;
+
+        // Normalized [0..1] value
+        final double barValue = currentPosition / maxPosition;
+
+        const barHeight = 30.0;
+        const Color baseColor = Colors.grey;
+        const Color textColor = Color.fromARGB(255, 238, 238, 238);
+        const Color outlineColor = Color.fromARGB(255, 200, 200, 200);
+
+        return Stack(
+          alignment: Alignment.center,
+          children: [
+            LinearProgressIndicator(
+              value: barValue,
+              color: baseColor,
+              backgroundColor: baseColor.darken(),
+              minHeight: barHeight,
+              borderRadius: const BorderRadius.all(Radius.circular(15)),
+            ),
+            OutlinedText(
+              text: '$currentPosition/$maxPosition',
+              fontSize: barHeight * 0.7,
+              textColor: textColor,
+              outlineColor: outlineColor,
+            ),
+          ],
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/widget_category.dart b/lib/ui/widgets/game/widget_category.dart
new file mode 100644
index 0000000..a54a2c1
--- /dev/null
+++ b/lib/ui/widgets/game/widget_category.dart
@@ -0,0 +1,52 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:petitbac/cubit/game_cubit.dart';
+import 'package:petitbac/models/game.dart';
+import 'package:petitbac/utils/color_extensions.dart';
+
+class WidgetCategory extends StatelessWidget {
+  const WidgetCategory({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    const Color backgroundColor = Colors.green;
+    const double borderWidth = 8.0;
+
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final Color borderColor = backgroundColor.darken();
+
+        return Container(
+          margin: const EdgeInsets.all(borderWidth),
+          padding: const EdgeInsets.all(borderWidth),
+          decoration: BoxDecoration(
+            color: backgroundColor,
+            borderRadius: BorderRadius.circular(borderWidth),
+            border: Border.all(
+              color: borderColor,
+              width: borderWidth,
+            ),
+          ),
+          child: TextButton(
+            onPressed: () {
+              final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+              gameCubit.pickNewCategory();
+            },
+            child: Text(
+              currentGame.category.text,
+              textAlign: TextAlign.center,
+              style: const TextStyle(
+                fontSize: 30,
+                fontWeight: FontWeight.w600,
+                color: Colors.black,
+              ),
+            ),
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/game/widget_letter.dart b/lib/ui/widgets/game/widget_letter.dart
new file mode 100644
index 0000000..9b7832d
--- /dev/null
+++ b/lib/ui/widgets/game/widget_letter.dart
@@ -0,0 +1,51 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:petitbac/cubit/game_cubit.dart';
+import 'package:petitbac/models/game.dart';
+import 'package:petitbac/utils/color_extensions.dart';
+
+class WidgetLetter extends StatelessWidget {
+  const WidgetLetter({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    const Color backgroundColor = Colors.orange;
+    const double borderWidth = 8.0;
+
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+
+        final Color borderColor = backgroundColor.darken();
+
+        return Container(
+          margin: const EdgeInsets.all(borderWidth),
+          padding: const EdgeInsets.all(borderWidth),
+          decoration: BoxDecoration(
+            color: backgroundColor,
+            borderRadius: BorderRadius.circular(borderWidth),
+            border: Border.all(
+              color: borderColor,
+              width: borderWidth,
+            ),
+          ),
+          child: TextButton(
+            onPressed: () {
+              final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+              gameCubit.pickNewLetter();
+            },
+            child: Text(
+              currentGame.letter.text,
+              style: const TextStyle(
+                fontSize: 40,
+                fontWeight: FontWeight.w600,
+                color: Colors.black,
+              ),
+            ),
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/global_app_bar.dart b/lib/ui/widgets/global_app_bar.dart
new file mode 100644
index 0000000..512717a
--- /dev/null
+++ b/lib/ui/widgets/global_app_bar.dart
@@ -0,0 +1,84 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:petitbac/config/menu.dart';
+import 'package:petitbac/cubit/game_cubit.dart';
+import 'package:petitbac/cubit/nav_cubit.dart';
+import 'package:petitbac/models/game.dart';
+import 'package:petitbac/ui/widgets/helpers/app_title.dart';
+
+class GlobalAppBar extends StatelessWidget implements PreferredSizeWidget {
+  const GlobalAppBar({super.key});
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        return BlocBuilder<NavCubit, int>(
+          builder: (BuildContext context, int pageIndex) {
+            final Game currentGame = gameState.currentGame;
+
+            final List<Widget> menuActions = [];
+
+            if (currentGame.isRunning) {
+              menuActions.add(TextButton(
+                child: const Image(
+                  image: AssetImage('assets/icons/button_back.png'),
+                  fit: BoxFit.fill,
+                ),
+                onPressed: () {},
+                onLongPress: () {
+                  final GameCubit gameCubit = BlocProvider.of<GameCubit>(context);
+                  gameCubit.quitGame();
+                },
+              ));
+            } else {
+              if (pageIndex == Menu.indexGame) {
+                // go to Settings page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToSettingsPage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemSettings.icon,
+                ));
+
+                // go to About page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToAboutPage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemAbout.icon,
+                ));
+              } else {
+                // back to Home page
+                menuActions.add(ElevatedButton(
+                  onPressed: () {
+                    context.read<NavCubit>().goToGamePage();
+                  },
+                  style: ElevatedButton.styleFrom(
+                    shape: const CircleBorder(),
+                  ),
+                  child: Menu.menuItemGame.icon,
+                ));
+              }
+            }
+
+            return AppBar(
+              title: const AppTitle(text: 'app_name'),
+              actions: menuActions,
+            );
+          },
+        );
+      },
+    );
+  }
+
+  @override
+  Size get preferredSize => const Size.fromHeight(50);
+}
diff --git a/lib/ui/widgets/header_app.dart b/lib/ui/widgets/helpers/app_header.dart
similarity index 77%
rename from lib/ui/widgets/header_app.dart
rename to lib/ui/widgets/helpers/app_header.dart
index bf54b77..b5c5be0 100644
--- a/lib/ui/widgets/header_app.dart
+++ b/lib/ui/widgets/helpers/app_header.dart
@@ -8,15 +8,16 @@ class AppHeader extends StatelessWidget {
 
   @override
   Widget build(BuildContext context) {
-    return Row(
+    return Column(
       mainAxisAlignment: MainAxisAlignment.start,
       crossAxisAlignment: CrossAxisAlignment.start,
       children: [
         Text(
           tr(text),
           textAlign: TextAlign.start,
-          style: Theme.of(context).textTheme.headlineMedium!.apply(fontWeightDelta: 2),
+          style: Theme.of(context).textTheme.headlineSmall!.apply(fontWeightDelta: 2),
         ),
+        const SizedBox(height: 8),
       ],
     );
   }
diff --git a/lib/ui/widgets/helpers/app_title.dart b/lib/ui/widgets/helpers/app_title.dart
new file mode 100644
index 0000000..7cbbb20
--- /dev/null
+++ b/lib/ui/widgets/helpers/app_title.dart
@@ -0,0 +1,17 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+
+class AppTitle extends StatelessWidget {
+  const AppTitle({super.key, required this.text});
+
+  final String text;
+
+  @override
+  Widget build(BuildContext context) {
+    return Text(
+      tr(text),
+      textAlign: TextAlign.start,
+      style: Theme.of(context).textTheme.headlineLarge!.apply(fontWeightDelta: 2),
+    );
+  }
+}
diff --git a/lib/ui/widgets/helpers/outlined_text_widget.dart b/lib/ui/widgets/helpers/outlined_text_widget.dart
new file mode 100644
index 0000000..c495cdb
--- /dev/null
+++ b/lib/ui/widgets/helpers/outlined_text_widget.dart
@@ -0,0 +1,51 @@
+import 'package:flutter/material.dart';
+
+import 'package:petitbac/utils/color_extensions.dart';
+
+class OutlinedText extends StatelessWidget {
+  const OutlinedText({
+    super.key,
+    required this.text,
+    required this.fontSize,
+    required this.textColor,
+    this.outlineColor,
+  });
+
+  final String text;
+  final double fontSize;
+  final Color textColor;
+  final Color? outlineColor;
+
+  @override
+  Widget build(BuildContext context) {
+    final double delta = fontSize / 30;
+
+    return Text(
+      text,
+      style: TextStyle(
+        inherit: true,
+        fontSize: fontSize,
+        fontWeight: FontWeight.w600,
+        color: textColor,
+        shadows: [
+          Shadow(
+            offset: Offset(-delta, -delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(delta, -delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(delta, delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+          Shadow(
+            offset: Offset(-delta, delta),
+            color: outlineColor ?? textColor.darken(),
+          ),
+        ],
+      ),
+    );
+  }
+}
diff --git a/lib/ui/widgets/mini_game.dart b/lib/ui/widgets/mini_game.dart
deleted file mode 100644
index 3734c5f..0000000
--- a/lib/ui/widgets/mini_game.dart
+++ /dev/null
@@ -1,107 +0,0 @@
-import 'dart:async';
-
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-import 'package:petitbac/config/default_settings.dart';
-import 'package:petitbac/cubit/settings_cubit.dart';
-import 'package:provider/provider.dart';
-
-import 'package:petitbac/utils/color_extensions.dart';
-import 'package:petitbac/utils/game_utils.dart';
-import 'package:petitbac/provider/data.dart';
-
-class MiniGame extends StatelessWidget {
-  const MiniGame({
-    super.key,
-    required this.backgroundColor,
-    required this.borderWidth,
-  });
-
-  final Color backgroundColor;
-  final double borderWidth;
-
-  static Timer? _timer;
-  static int _countdownStart = 0;
-
-  void dispose() {
-    _timer?.cancel();
-  }
-
-  Future<void> startTimer(Data myProvider, int timerDuration) async {
-    const oneSec = Duration(seconds: 1);
-    if (_timer != null) {
-      dispose();
-    }
-    _countdownStart = timerDuration;
-    myProvider.updateCountdown(_countdownStart);
-    _timer = Timer.periodic(
-      oneSec,
-      (Timer timer) {
-        if (_countdownStart < 0) {
-          timer.cancel();
-        } else {
-          _countdownStart--;
-          myProvider.updateCountdown(_countdownStart);
-        }
-      },
-    );
-  }
-
-  Future<void> startMiniGame(Data myProvider, int timerDuration) async {
-    if (myProvider.countdown <= 0) {
-      GameUtils.pickCategory(myProvider);
-      GameUtils.pickLetter(myProvider);
-      startTimer(myProvider, timerDuration);
-    }
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final Data myProvider = Provider.of<Data>(context);
-
-    final Color borderColor = backgroundColor.darken();
-
-    Color countDownColor = Colors.black;
-    if (myProvider.countdown == 0) {
-      countDownColor = Colors.red;
-    }
-
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: [
-        Container(
-          margin: EdgeInsets.all(borderWidth),
-          padding: EdgeInsets.all(borderWidth),
-          decoration: BoxDecoration(
-            color: backgroundColor,
-            borderRadius: BorderRadius.circular(borderWidth),
-            border: Border.all(
-              color: borderColor,
-              width: borderWidth,
-            ),
-          ),
-          child: BlocBuilder<SettingsCubit, SettingsState>(
-            builder: (context, settingsSate) {
-              return TextButton(
-                onPressed: (myProvider.countdown >= 0)
-                    ? null
-                    : () => startMiniGame(myProvider,
-                        settingsSate.timerValue ?? DefaultSettings.defaultTimerValue),
-                child: Text(
-                  (myProvider.countdown >= 0) ? myProvider.countdown.toString() : '🎲',
-                  textAlign: TextAlign.center,
-                  style: TextStyle(
-                    fontSize: 50,
-                    fontWeight: FontWeight.w600,
-                    color: countDownColor,
-                  ),
-                ),
-              );
-            },
-          ),
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/widgets/parameters.dart b/lib/ui/widgets/parameters.dart
new file mode 100644
index 0000000..c13ccba
--- /dev/null
+++ b/lib/ui/widgets/parameters.dart
@@ -0,0 +1,115 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:petitbac/config/default_game_settings.dart';
+import 'package:petitbac/config/default_global_settings.dart';
+import 'package:petitbac/cubit/settings_game_cubit.dart';
+import 'package:petitbac/cubit/settings_global_cubit.dart';
+import 'package:petitbac/ui/painters/parameter_painter.dart';
+import 'package:petitbac/ui/widgets/button_game_start_new.dart';
+
+class Parameters extends StatelessWidget {
+  const Parameters({super.key});
+
+  final double separatorHeight = 8.0;
+
+  @override
+  Widget build(BuildContext context) {
+    final List<Widget> lines = [];
+
+    // Game settings
+    for (String code in DefaultGameSettings.availableParameters) {
+      lines.add(Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: buildParametersLine(
+          code: code,
+          isGlobal: false,
+        ),
+      ));
+
+      lines.add(SizedBox(height: separatorHeight));
+    }
+
+    lines.add(SizedBox(height: separatorHeight));
+    lines.add(const Expanded(child: StartNewGameButton()));
+    lines.add(SizedBox(height: separatorHeight));
+
+    // Global settings
+    for (String code in DefaultGlobalSettings.availableParameters) {
+      lines.add(Row(
+        mainAxisAlignment: MainAxisAlignment.spaceBetween,
+        children: buildParametersLine(
+          code: code,
+          isGlobal: true,
+        ),
+      ));
+
+      lines.add(SizedBox(height: separatorHeight));
+    }
+
+    return Column(
+      children: lines,
+    );
+  }
+
+  List<Widget> buildParametersLine({
+    required String code,
+    required bool isGlobal,
+  }) {
+    final List<Widget> parameterButtons = [];
+
+    final List<int> availableValues = isGlobal
+        ? DefaultGlobalSettings.getAvailableValues(code)
+        : DefaultGameSettings.getAvailableValues(code);
+
+    if (availableValues.length <= 1) {
+      return [];
+    }
+
+    for (int value in availableValues) {
+      final Widget parameterButton = BlocBuilder<GameSettingsCubit, GameSettingsState>(
+        builder: (BuildContext context, GameSettingsState gameSettingsState) {
+          return BlocBuilder<GlobalSettingsCubit, GlobalSettingsState>(
+            builder: (BuildContext context, GlobalSettingsState globalSettingsState) {
+              final GameSettingsCubit gameSettingsCubit =
+                  BlocProvider.of<GameSettingsCubit>(context);
+              final GlobalSettingsCubit globalSettingsCubit =
+                  BlocProvider.of<GlobalSettingsCubit>(context);
+
+              final int currentValue = isGlobal
+                  ? globalSettingsCubit.getParameterValue(code)
+                  : gameSettingsCubit.getParameterValue(code);
+
+              final bool isActive = (value == currentValue);
+
+              final double displayWidth = MediaQuery.of(context).size.width;
+              final double itemWidth = displayWidth / availableValues.length - 26;
+
+              return TextButton(
+                child: CustomPaint(
+                  size: Size(itemWidth, itemWidth),
+                  willChange: false,
+                  painter: ParameterPainter(
+                    code: code,
+                    value: value,
+                    isSelected: isActive,
+                    gameSettings: gameSettingsState.settings,
+                    globalSettings: globalSettingsState.settings,
+                  ),
+                  isComplex: true,
+                ),
+                onPressed: () => isGlobal
+                    ? globalSettingsCubit.setParameterValue(code, value)
+                    : gameSettingsCubit.setParameterValue(code, value),
+              );
+            },
+          );
+        },
+      );
+
+      parameterButtons.add(parameterButton);
+    }
+
+    return parameterButtons;
+  }
+}
diff --git a/lib/ui/widgets/picked_category.dart b/lib/ui/widgets/picked_category.dart
deleted file mode 100644
index de5781b..0000000
--- a/lib/ui/widgets/picked_category.dart
+++ /dev/null
@@ -1,55 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-import 'package:petitbac/utils/color_extensions.dart';
-import 'package:petitbac/utils/game_utils.dart';
-import 'package:petitbac/provider/data.dart';
-
-class PickedCategory extends StatelessWidget {
-  const PickedCategory({
-    super.key,
-    required this.backgroundColor,
-    required this.borderWidth,
-  });
-
-  final Color backgroundColor;
-  final double borderWidth;
-
-  @override
-  Widget build(BuildContext context) {
-    final Data myProvider = Provider.of<Data>(context);
-
-    final Color borderColor = backgroundColor.darken();
-
-    return Column(
-      mainAxisSize: MainAxisSize.min,
-      mainAxisAlignment: MainAxisAlignment.center,
-      children: [
-        Container(
-          margin: EdgeInsets.all(borderWidth),
-          padding: EdgeInsets.all(borderWidth),
-          decoration: BoxDecoration(
-            color: backgroundColor,
-            borderRadius: BorderRadius.circular(borderWidth),
-            border: Border.all(
-              color: borderColor,
-              width: borderWidth,
-            ),
-          ),
-          child: TextButton(
-            onPressed: () => GameUtils.pickCategory(myProvider),
-            child: Text(
-              myProvider.category == '' ? "🔀" : myProvider.category,
-              textAlign: TextAlign.center,
-              style: const TextStyle(
-                fontSize: 30,
-                fontWeight: FontWeight.w600,
-                color: Colors.black,
-              ),
-            ),
-          ),
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/widgets/picked_letter.dart b/lib/ui/widgets/picked_letter.dart
deleted file mode 100644
index 0c0e009..0000000
--- a/lib/ui/widgets/picked_letter.dart
+++ /dev/null
@@ -1,101 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-
-import 'package:petitbac/ui/widgets/previous_letter.dart';
-import 'package:petitbac/utils/color_extensions.dart';
-import 'package:petitbac/utils/game_utils.dart';
-import 'package:petitbac/provider/data.dart';
-
-class PickedLetter extends StatelessWidget {
-  const PickedLetter({
-    super.key,
-    required this.backgroundColor,
-    required this.borderWidth,
-  });
-
-  final Color backgroundColor;
-  final double borderWidth;
-
-  Container mainLetterButtonContainer(
-    Data myProvider,
-    Color backgroundColor,
-    double borderWidth,
-  ) {
-    final Color borderColor = backgroundColor.darken();
-
-    return Container(
-      margin: EdgeInsets.all(borderWidth),
-      padding: EdgeInsets.all(borderWidth),
-      decoration: BoxDecoration(
-        color: backgroundColor,
-        borderRadius: BorderRadius.circular(borderWidth),
-        border: Border.all(
-          color: borderColor,
-          width: borderWidth,
-        ),
-      ),
-      child: TextButton(
-        onPressed: () => GameUtils.pickLetter(myProvider),
-        child: Text(
-          myProvider.letter == '' ? "🔀" : myProvider.letter,
-          style: const TextStyle(
-            fontSize: 40,
-            fontWeight: FontWeight.w600,
-            color: Colors.black,
-          ),
-        ),
-      ),
-    );
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    final Data myProvider = Provider.of<Data>(context);
-
-    const int previousLettersCountToShow = 3;
-
-    final List<Widget> cells = [];
-
-    // Add previous letters blocks
-    for (var i = 0; i < previousLettersCountToShow; i++) {
-      final int position = previousLettersCountToShow - i;
-      cells.add(TableCell(
-        verticalAlignment: TableCellVerticalAlignment.middle,
-        child: PreviousLetter(
-          letter: myProvider.recentlyPickedLetter(position),
-          position: position,
-          displayed: true,
-        ),
-      ));
-    }
-
-    // Add current letter block
-    cells.add(TableCell(
-      verticalAlignment: TableCellVerticalAlignment.middle,
-      child: mainLetterButtonContainer(myProvider, backgroundColor, borderWidth),
-    ));
-
-    // Pad with empty blocks to keep symetrical layout
-    for (var i = 0; i < previousLettersCountToShow; i++) {
-      cells.add(TableCell(
-        verticalAlignment: TableCellVerticalAlignment.middle,
-        child: PreviousLetter(
-          letter: myProvider.recentlyPickedLetter(i + 1),
-          position: i + 1,
-          displayed: false,
-        ),
-      ));
-    }
-
-    return Container(
-      margin: const EdgeInsets.all(2),
-      padding: const EdgeInsets.all(2),
-      child: Table(
-        defaultColumnWidth: const IntrinsicColumnWidth(),
-        children: [
-          TableRow(children: cells),
-        ],
-      ),
-    );
-  }
-}
diff --git a/lib/ui/widgets/previous_letter.dart b/lib/ui/widgets/previous_letter.dart
deleted file mode 100644
index 558f27c..0000000
--- a/lib/ui/widgets/previous_letter.dart
+++ /dev/null
@@ -1,52 +0,0 @@
-import 'package:flutter/material.dart';
-
-import 'package:petitbac/utils/color_extensions.dart';
-
-class PreviousLetter extends StatelessWidget {
-  const PreviousLetter({
-    super.key,
-    required this.letter,
-    required this.position,
-    required this.displayed,
-  });
-
-  final String letter;
-  final int position;
-  final bool displayed;
-
-  @override
-  Widget build(BuildContext context) {
-    const double spacingWidth = 2;
-    const double borderWidth = 3;
-    Color backgroundColor = Colors.grey;
-    Color borderColor = backgroundColor.darken();
-    Color fontColor = Colors.black;
-
-    if (letter == '' || displayed == false) {
-      backgroundColor = Theme.of(context).colorScheme.background;
-      borderColor = Theme.of(context).colorScheme.background;
-      fontColor = Theme.of(context).colorScheme.background;
-    }
-
-    return Container(
-      margin: const EdgeInsets.all(spacingWidth),
-      padding: const EdgeInsets.all(spacingWidth),
-      decoration: BoxDecoration(
-        color: backgroundColor,
-        borderRadius: BorderRadius.circular(borderWidth),
-        border: Border.all(
-          color: borderColor,
-          width: borderWidth,
-        ),
-      ),
-      child: Text(
-        ' $letter ',
-        style: TextStyle(
-          fontSize: 35.0 - (7 * position),
-          fontWeight: FontWeight.w600,
-          color: fontColor,
-        ),
-      ),
-    );
-  }
-}
diff --git a/lib/ui/widgets/settings/settings_form.dart b/lib/ui/widgets/settings/settings_form.dart
new file mode 100644
index 0000000..eef343a
--- /dev/null
+++ b/lib/ui/widgets/settings/settings_form.dart
@@ -0,0 +1,63 @@
+import 'package:easy_localization/easy_localization.dart';
+import 'package:flutter/material.dart';
+import 'package:unicons/unicons.dart';
+
+import 'package:petitbac/ui/widgets/settings/theme_card.dart';
+
+class SettingsForm extends StatefulWidget {
+  const SettingsForm({super.key});
+
+  @override
+  State<SettingsForm> createState() => _SettingsFormState();
+}
+
+class _SettingsFormState extends State<SettingsForm> {
+  @override
+  void dispose() {
+    super.dispose();
+  }
+
+  @override
+  void didChangeDependencies() {
+    super.didChangeDependencies();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    return Column(
+      mainAxisAlignment: MainAxisAlignment.start,
+      crossAxisAlignment: CrossAxisAlignment.start,
+      mainAxisSize: MainAxisSize.max,
+      children: <Widget>[
+        // Light/dark theme
+        Row(
+          mainAxisAlignment: MainAxisAlignment.spaceBetween,
+          crossAxisAlignment: CrossAxisAlignment.center,
+          children: <Widget>[
+            const Text('settings_label_theme').tr(),
+            const Row(
+              mainAxisAlignment: MainAxisAlignment.end,
+              crossAxisAlignment: CrossAxisAlignment.center,
+              children: [
+                ThemeCard(
+                  mode: ThemeMode.system,
+                  icon: UniconsLine.cog,
+                ),
+                ThemeCard(
+                  mode: ThemeMode.light,
+                  icon: UniconsLine.sun,
+                ),
+                ThemeCard(
+                  mode: ThemeMode.dark,
+                  icon: UniconsLine.moon,
+                )
+              ],
+            ),
+          ],
+        ),
+
+        const SizedBox(height: 16),
+      ],
+    );
+  }
+}
diff --git a/lib/ui/widgets/settings/theme_card.dart b/lib/ui/widgets/settings/theme_card.dart
new file mode 100644
index 0000000..4fe730a
--- /dev/null
+++ b/lib/ui/widgets/settings/theme_card.dart
@@ -0,0 +1,47 @@
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:petitbac/cubit/theme_cubit.dart';
+
+class ThemeCard extends StatelessWidget {
+  const ThemeCard({
+    super.key,
+    required this.mode,
+    required this.icon,
+  });
+
+  final IconData icon;
+  final ThemeMode mode;
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<ThemeCubit, ThemeModeState>(
+      builder: (BuildContext context, ThemeModeState state) {
+        return Card(
+          elevation: 2,
+          shadowColor: Theme.of(context).colorScheme.shadow,
+          color: state.themeMode == mode
+              ? Theme.of(context).colorScheme.primary
+              : Theme.of(context).colorScheme.surface,
+          shape: const RoundedRectangleBorder(
+            borderRadius: BorderRadius.all(Radius.circular(12)),
+          ),
+          margin: const EdgeInsets.all(5),
+          child: InkWell(
+            onTap: () => BlocProvider.of<ThemeCubit>(context).getTheme(
+              ThemeModeState(themeMode: mode),
+            ),
+            borderRadius: const BorderRadius.all(Radius.circular(12)),
+            child: Icon(
+              icon,
+              size: 32,
+              color: state.themeMode != mode
+                  ? Theme.of(context).colorScheme.primary
+                  : Colors.white,
+            ),
+          ),
+        );
+      },
+    );
+  }
+}
diff --git a/lib/ui/widgets/settings_form.dart b/lib/ui/widgets/settings_form.dart
deleted file mode 100644
index 6251f79..0000000
--- a/lib/ui/widgets/settings_form.dart
+++ /dev/null
@@ -1,108 +0,0 @@
-import 'package:easy_localization/easy_localization.dart';
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:petitbac/config/default_settings.dart';
-import 'package:petitbac/cubit/settings_cubit.dart';
-import 'package:petitbac/ui/widgets/theme_card.dart';
-import 'package:unicons/unicons.dart';
-
-class SettingsForm extends StatefulWidget {
-  const SettingsForm({super.key});
-
-  @override
-  State<SettingsForm> createState() => _SettingsFormState();
-}
-
-class _SettingsFormState extends State<SettingsForm> {
-  int timerValue = DefaultSettings.defaultTimerValue;
-
-  List<bool> _selectedTimerValue = [];
-
-  @override
-  void dispose() {
-    super.dispose();
-  }
-
-  @override
-  void didChangeDependencies() {
-    SettingsCubit settings = BlocProvider.of<SettingsCubit>(context);
-
-    timerValue = settings.getTimerValue();
-
-    _selectedTimerValue =
-        DefaultSettings.allowedTimerValues.map((e) => (e == timerValue)).toList();
-
-    super.didChangeDependencies();
-  }
-
-  @override
-  Widget build(BuildContext context) {
-    void saveSettings() {
-      BlocProvider.of<SettingsCubit>(context).setValues(
-        timerValue: timerValue,
-      );
-    }
-
-    return Column(
-      mainAxisAlignment: MainAxisAlignment.start,
-      crossAxisAlignment: CrossAxisAlignment.start,
-      mainAxisSize: MainAxisSize.max,
-      children: <Widget>[
-        // Light/dark theme
-        Row(
-          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: <Widget>[
-            const Text('settings_label_theme').tr(),
-            const Row(
-              mainAxisAlignment: MainAxisAlignment.end,
-              crossAxisAlignment: CrossAxisAlignment.center,
-              children: [
-                ThemeCard(
-                  mode: ThemeMode.system,
-                  icon: UniconsLine.cog,
-                ),
-                ThemeCard(
-                  mode: ThemeMode.light,
-                  icon: UniconsLine.sun,
-                ),
-                ThemeCard(
-                  mode: ThemeMode.dark,
-                  icon: UniconsLine.moon,
-                )
-              ],
-            ),
-          ],
-        ),
-
-        const SizedBox(height: 16),
-
-        // Timer value
-        Row(
-          mainAxisAlignment: MainAxisAlignment.spaceBetween,
-          crossAxisAlignment: CrossAxisAlignment.center,
-          children: [
-            const Text('settings_label_timer_value').tr(),
-            ToggleButtons(
-              onPressed: (int index) {
-                setState(() {
-                  timerValue = DefaultSettings.allowedTimerValues[index];
-                  for (int i = 0; i < _selectedTimerValue.length; i++) {
-                    _selectedTimerValue[i] = i == index;
-                  }
-                });
-                saveSettings();
-              },
-              borderRadius: const BorderRadius.all(Radius.circular(8)),
-              constraints: const BoxConstraints(minHeight: 30.0, minWidth: 30.0),
-              isSelected: _selectedTimerValue,
-              children:
-                  DefaultSettings.allowedTimerValues.map((e) => Text(e.toString())).toList(),
-            ),
-          ],
-        ),
-      ],
-    );
-  }
-}
diff --git a/lib/ui/widgets/theme_card.dart b/lib/ui/widgets/theme_card.dart
deleted file mode 100644
index dd99708..0000000
--- a/lib/ui/widgets/theme_card.dart
+++ /dev/null
@@ -1,45 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:flutter_bloc/flutter_bloc.dart';
-
-import 'package:petitbac/cubit/theme_cubit.dart';
-
-class ThemeCard extends StatelessWidget {
-  const ThemeCard({
-    super.key,
-    required this.mode,
-    required this.icon,
-  });
-
-  final IconData icon;
-  final ThemeMode mode;
-
-  @override
-  Widget build(BuildContext context) {
-    return BlocBuilder<ThemeCubit, ThemeModeState>(
-        builder: (BuildContext context, ThemeModeState state) {
-      return Card(
-        elevation: 2,
-        shadowColor: Theme.of(context).colorScheme.shadow,
-        color: state.themeMode == mode
-            ? Theme.of(context).colorScheme.primary
-            : Theme.of(context).colorScheme.surface,
-        shape: const RoundedRectangleBorder(
-          borderRadius: BorderRadius.all(Radius.circular(12)),
-        ),
-        margin: const EdgeInsets.all(5),
-        child: InkWell(
-          onTap: () => BlocProvider.of<ThemeCubit>(context).getTheme(
-            ThemeModeState(themeMode: mode),
-          ),
-          borderRadius: const BorderRadius.all(Radius.circular(12)),
-          child: Icon(
-            icon,
-            size: 32,
-            color:
-                state.themeMode != mode ? Theme.of(context).colorScheme.primary : Colors.white,
-          ),
-        ),
-      );
-    });
-  }
-}
diff --git a/lib/utils/game_utils.dart b/lib/utils/game_utils.dart
deleted file mode 100644
index e206a93..0000000
--- a/lib/utils/game_utils.dart
+++ /dev/null
@@ -1,37 +0,0 @@
-import 'package:petitbac/provider/data.dart';
-import 'package:petitbac/utils/random_pick_category.dart';
-import 'package:petitbac/utils/random_pick_letter.dart';
-
-class GameUtils {
-  static Future<void> pickLetter(Data myProvider) async {
-    myProvider.setSearchingLetter(true);
-    RandomPickLetter randomPickLetter;
-    int attempts = 0;
-    do {
-      randomPickLetter = RandomPickLetter();
-      await randomPickLetter.init();
-      if (!myProvider.isLetterRecentlyPicked(randomPickLetter.letter)) {
-        myProvider.updateLetter(randomPickLetter.letter);
-        myProvider.setSearchingLetter(false);
-        break;
-      }
-      attempts++;
-    } while (attempts < 10);
-  }
-
-  static Future<void> pickCategory(Data myProvider) async {
-    myProvider.setSearchingCategory(true);
-    RandomPickCategory randomPickCategory;
-    int attempts = 0;
-    do {
-      randomPickCategory = RandomPickCategory();
-      await randomPickCategory.init();
-      if (!myProvider.isCategoryRecentlyPicked(randomPickCategory.category)) {
-        myProvider.updateCategory(randomPickCategory.category);
-        myProvider.setSearchingCategory(false);
-        break;
-      }
-      attempts++;
-    } while (attempts < 10);
-  }
-}
diff --git a/lib/utils/random_pick_category.dart b/lib/utils/random_pick_category.dart
deleted file mode 100644
index 0132446..0000000
--- a/lib/utils/random_pick_category.dart
+++ /dev/null
@@ -1,30 +0,0 @@
-import 'dart:async';
-import 'dart:convert';
-import 'dart:math' show Random;
-
-import 'package:flutter/services.dart';
-
-class RandomPickCategory {
-  RandomPickCategory();
-
-  String? _category;
-  final random = Random();
-
-  init() async {
-    await categoryFromLocalFile();
-  }
-
-  Future<void> categoryFromLocalFile() async {
-    String jsonString;
-    try {
-      jsonString = await rootBundle.loadString('assets/files/categories-fr.json');
-      final jsonResponse = await json.decode(jsonString);
-      var categoryList = jsonResponse[jsonResponse.keys.toList().join()];
-      _category = categoryList[random.nextInt(categoryList.length)];
-    } catch (e) {
-      _category = 'UNEXPECTED ERROR';
-    }
-  }
-
-  String get category => (_category != null) ? _category.toString() : '';
-}
diff --git a/lib/utils/random_pick_letter.dart b/lib/utils/random_pick_letter.dart
deleted file mode 100644
index 32caf82..0000000
--- a/lib/utils/random_pick_letter.dart
+++ /dev/null
@@ -1,20 +0,0 @@
-import 'dart:async';
-import 'dart:math' show Random;
-
-class RandomPickLetter {
-  RandomPickLetter();
-
-  String? _letter;
-  final random = Random();
-  final String _chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
-
-  init() async {
-    await letterFromLocalFile();
-  }
-
-  Future<void> letterFromLocalFile() async {
-    _letter = _chars[random.nextInt(_chars.length)];
-  }
-
-  String get letter => (_letter != null) ? _letter.toString() : '';
-}
diff --git a/pubspec.lock b/pubspec.lock
index 53bc85d..b5a356d 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,10 +5,10 @@ packages:
     dependency: transitive
     description:
       name: args
-      sha256: eef6c46b622e0494a36c5a12d10d77fb4e855501a91c1b9ef9339326e58f0596
+      sha256: "7cf60b9f0cc88203c5a190b4cd62a99feea42759a7fa695010eb5de1c0b2252a"
       url: "https://pub.dev"
     source: hosted
-    version: "2.4.2"
+    version: "2.5.0"
   async:
     dependency: transitive
     description:
@@ -21,10 +21,10 @@ packages:
     dependency: transitive
     description:
       name: bloc
-      sha256: f53a110e3b48dcd78136c10daa5d51512443cea5e1348c9d80a320095fa2db9e
+      sha256: "106842ad6569f0b60297619e9e0b1885c2fb9bf84812935490e6c5275777804e"
       url: "https://pub.dev"
     source: hosted
-    version: "8.1.3"
+    version: "8.1.4"
   characters:
     dependency: transitive
     description:
@@ -61,10 +61,10 @@ packages:
     dependency: "direct main"
     description:
       name: easy_localization
-      sha256: c145aeb6584aedc7c862ab8c737c3277788f47488bfdf9bae0fe112bd0a4789c
+      sha256: "432698c31a488dd64c56d4759f20d04844baba5e9e4f2cb1abb9676257918b17"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.5"
+    version: "3.0.6"
   easy_logger:
     dependency: transitive
     description:
@@ -106,31 +106,23 @@ packages:
     dependency: "direct main"
     description:
       name: flutter_bloc
-      sha256: "87325da1ac757fcc4813e6b34ed5dd61169973871fdf181d6c2109dd6935ece1"
+      sha256: f0ecf6e6eb955193ca60af2d5ca39565a86b8a142452c5b24d96fb477428f4d2
       url: "https://pub.dev"
     source: hosted
-    version: "8.1.4"
+    version: "8.1.5"
   flutter_lints:
     dependency: "direct dev"
     description:
       name: flutter_lints
-      sha256: e2a421b7e59244faef694ba7b30562e489c2b489866e505074eb005cd7060db7
+      sha256: "9e8c3858111da373efc5aa341de011d9bd23e2c5c5e0c62bccf32438e192d7b1"
       url: "https://pub.dev"
     source: hosted
-    version: "3.0.1"
+    version: "3.0.2"
   flutter_localizations:
     dependency: transitive
     description: flutter
     source: sdk
     version: "0.0.0"
-  flutter_swipe:
-    dependency: "direct main"
-    description:
-      name: flutter_swipe
-      sha256: dc6541bac3a0545ce15a3fa15913f6250532062960bf6b0ad4562d02f14a8545
-      url: "https://pub.dev"
-    source: hosted
-    version: "1.0.1"
   flutter_web_plugins:
     dependency: transitive
     description: flutter
@@ -148,10 +140,10 @@ packages:
     dependency: transitive
     description:
       name: http
-      sha256: a2bbf9d017fcced29139daa8ed2bba4ece450ab222871df93ca9eec6f80c34ba
+      sha256: "761a297c042deedc1ffbb156d6e2af13886bb305c2a343a4d972504cd67dd938"
       url: "https://pub.dev"
     source: hosted
-    version: "1.2.0"
+    version: "1.2.1"
   http_parser:
     dependency: transitive
     description:
@@ -164,10 +156,10 @@ packages:
     dependency: "direct main"
     description:
       name: hydrated_bloc
-      sha256: "00a2099680162e74b5a836b8a7f446e478520a9cae9f6032e028ad8129f4432d"
+      sha256: af35b357739fe41728df10bec03aad422cdc725a1e702e03af9d2a41ea05160c
       url: "https://pub.dev"
     source: hosted
-    version: "9.1.4"
+    version: "9.1.5"
   intl:
     dependency: transitive
     description:
@@ -212,20 +204,20 @@ packages:
     dependency: "direct main"
     description:
       name: package_info_plus
-      sha256: "88bc797f44a94814f2213db1c9bd5badebafdfb8290ca9f78d4b9ee2a3db4d79"
+      sha256: b93d8b4d624b4ea19b0a5a208b2d6eff06004bc3ce74c06040b120eeadd00ce0
       url: "https://pub.dev"
     source: hosted
-    version: "5.0.1"
+    version: "8.0.0"
   package_info_plus_platform_interface:
     dependency: transitive
     description:
       name: package_info_plus_platform_interface
-      sha256: "9bc8ba46813a4cc42c66ab781470711781940780fd8beddd0c3da62506d3a6c6"
+      sha256: f49918f3433a3146047372f9d4f1f847511f2acd5cd030e1f44fe5a50036b70e
       url: "https://pub.dev"
     source: hosted
-    version: "2.0.1"
+    version: "3.0.0"
   path:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: path
       sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af"
@@ -236,26 +228,26 @@ packages:
     dependency: "direct main"
     description:
       name: path_provider
-      sha256: b27217933eeeba8ff24845c34003b003b2b22151de3c908d0e679e8fe1aa078b
+      sha256: c9e7d3a4cd1410877472158bee69963a4579f78b68c65a2b7d40d1a7a88bb161
       url: "https://pub.dev"
     source: hosted
-    version: "2.1.2"
+    version: "2.1.3"
   path_provider_android:
     dependency: transitive
     description:
       name: path_provider_android
-      sha256: "477184d672607c0a3bf68fbbf601805f92ef79c82b64b4d6eb318cbca4c48668"
+      sha256: a248d8146ee5983446bf03ed5ea8f6533129a12b11f12057ad1b4a67a2b3b41d
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.2.4"
   path_provider_foundation:
     dependency: transitive
     description:
       name: path_provider_foundation
-      sha256: "5a7999be66e000916500be4f15a3633ebceb8302719b47b9cc49ce924125350f"
+      sha256: f234384a3fdd67f989b4d54a5d73ca2a6c422fa55ae694381ae0f4375cd1ea16
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.2"
+    version: "2.4.0"
   path_provider_linux:
     dependency: transitive
     description:
@@ -297,7 +289,7 @@ packages:
     source: hosted
     version: "2.1.8"
   provider:
-    dependency: "direct main"
+    dependency: transitive
     description:
       name: provider
       sha256: c8a055ee5ce3fd98d6fc872478b03823ffdb448699c6ebdbbc71d59b596fd48c
@@ -308,26 +300,26 @@ packages:
     dependency: transitive
     description:
       name: shared_preferences
-      sha256: "81429e4481e1ccfb51ede496e916348668fd0921627779233bd24cc3ff6abd02"
+      sha256: d3bbe5553a986e83980916ded2f0b435ef2e1893dfaa29d5a7a790d0eca12180
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.2.3"
   shared_preferences_android:
     dependency: transitive
     description:
       name: shared_preferences_android
-      sha256: "8568a389334b6e83415b6aae55378e158fbc2314e074983362d20c562780fb06"
+      sha256: "1ee8bf911094a1b592de7ab29add6f826a7331fb854273d55918693d5364a1f2"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.1"
+    version: "2.2.2"
   shared_preferences_foundation:
     dependency: transitive
     description:
       name: shared_preferences_foundation
-      sha256: "7708d83064f38060c7b39db12aefe449cb8cdc031d6062280087bc4cdb988f5c"
+      sha256: "0a8a893bf4fd1152f93fec03a415d11c27c74454d96e2318a7ac38dd18683ab7"
       url: "https://pub.dev"
     source: hosted
-    version: "2.3.5"
+    version: "2.4.0"
   shared_preferences_linux:
     dependency: transitive
     description:
@@ -348,10 +340,10 @@ packages:
     dependency: transitive
     description:
       name: shared_preferences_web
-      sha256: "7b15ffb9387ea3e237bb7a66b8a23d2147663d391cafc5c8f37b2e7b4bde5d21"
+      sha256: "9aee1089b36bd2aafe06582b7d7817fd317ef05fc30e6ba14bff247d0933042a"
       url: "https://pub.dev"
     source: hosted
-    version: "2.2.2"
+    version: "2.3.0"
   shared_preferences_windows:
     dependency: transitive
     description:
@@ -425,18 +417,18 @@ packages:
     dependency: transitive
     description:
       name: web
-      sha256: "4188706108906f002b3a293509234588823c8c979dc83304e229ff400c996b05"
+      sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27"
       url: "https://pub.dev"
     source: hosted
-    version: "0.4.2"
+    version: "0.5.1"
   win32:
     dependency: transitive
     description:
       name: win32
-      sha256: "8cb58b45c47dcb42ab3651533626161d6b67a2921917d8d429791f76972b3480"
+      sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb"
       url: "https://pub.dev"
     source: hosted
-    version: "5.3.0"
+    version: "5.5.0"
   xdg_directories:
     dependency: transitive
     description:
@@ -447,4 +439,4 @@ packages:
     version: "1.0.4"
 sdks:
   dart: ">=3.3.0 <4.0.0"
-  flutter: ">=3.16.0"
+  flutter: ">=3.19.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 45c8369..e7d76b4 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,11 +1,12 @@
 name: petitbac
 description: A PetitBac game application.
 
-publish_to: 'none'
-version: 1.2.30+36
+publish_to: "none"
+
+version: 1.2.31+37
 
 environment:
-  sdk: '^3.0.0'
+  sdk: "^3.0.0"
 
 dependencies:
   flutter:
@@ -14,22 +15,19 @@ dependencies:
   easy_localization: ^3.0.1
   equatable: ^2.0.5
   flutter_bloc: ^8.1.1
-  flutter_swipe: ^1.0.1
   hive: ^2.2.3
   hydrated_bloc: ^9.0.0
-  package_info_plus: ^5.0.1
-  path: ^1.9.0
+  package_info_plus: ^8.0.0
   path_provider: ^2.0.11
-  provider: ^6.0.5
   unicons: ^2.1.1
 
 dev_dependencies:
   flutter_lints: ^3.0.1
 
 flutter:
-  uses-material-design: false
+  uses-material-design: true
   assets:
-    - assets/files/
+    - assets/icons/
     - assets/translations/
 
   fonts:
@@ -43,4 +41,3 @@ flutter:
           weight: 400
         - asset: assets/fonts/Nunito-Light.ttf
           weight: 300
-
-- 
GitLab