From bf8bd0496ea2b5188b9baff06cdaa7496047ae97 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Beno=C3=AEt=20Harrault?= <benoit@harrault.fr>
Date: Mon, 2 Sep 2024 11:26:46 +0200
Subject: [PATCH] Improve UI, add custom graphics

---
 android/gradle.properties                     |   4 +-
 assets/skins/default_house.png                | Bin 2357 -> 0 bytes
 .../metadata/android/en-US/changelogs/7.txt   |   1 +
 .../metadata/android/fr-FR/changelogs/7.txt   |   1 +
 lib/main.dart                                 |   1 -
 lib/models/data/category.dart                 |  24 --
 lib/models/data/letter.dart                   |  21 --
 lib/ui/layouts/game_layout.dart               |   2 +-
 lib/ui/widgets/game/game_board.dart           | 108 +++++-
 lib/ui/widgets/game/game_house.dart           |  20 +-
 lib/ui/widgets/game/game_player.dart          |  20 +-
 lib/ui/widgets/game/game_score.dart           |  18 +-
 lib/ui/widgets/game/game_seeds.dart           |  89 +++++
 pubspec.yaml                                  |   2 +-
 resources/seeds_layout.svg                    | 335 ++++++++++++++++++
 resources/ui/skins/default/house.svg          |   2 -
 16 files changed, 539 insertions(+), 109 deletions(-)
 delete mode 100644 assets/skins/default_house.png
 create mode 100644 fastlane/metadata/android/en-US/changelogs/7.txt
 create mode 100644 fastlane/metadata/android/fr-FR/changelogs/7.txt
 delete mode 100644 lib/models/data/category.dart
 delete mode 100644 lib/models/data/letter.dart
 create mode 100644 lib/ui/widgets/game/game_seeds.dart
 create mode 100644 resources/seeds_layout.svg
 delete mode 100644 resources/ui/skins/default/house.svg

diff --git a/android/gradle.properties b/android/gradle.properties
index 135006f..85b94f8 100644
--- a/android/gradle.properties
+++ b/android/gradle.properties
@@ -1,5 +1,5 @@
 org.gradle.jvmargs=-Xmx1536M
 android.useAndroidX=true
 android.enableJetifier=true
-app.versionName=0.0.6
-app.versionCode=6
+app.versionName=0.0.7
+app.versionCode=7
diff --git a/assets/skins/default_house.png b/assets/skins/default_house.png
deleted file mode 100644
index c99a90a4839788959792c2524e482cf83c149ecb..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 2357
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

diff --git a/fastlane/metadata/android/en-US/changelogs/7.txt b/fastlane/metadata/android/en-US/changelogs/7.txt
new file mode 100644
index 0000000..64a1a22
--- /dev/null
+++ b/fastlane/metadata/android/en-US/changelogs/7.txt
@@ -0,0 +1 @@
+Improve UI.
diff --git a/fastlane/metadata/android/fr-FR/changelogs/7.txt b/fastlane/metadata/android/fr-FR/changelogs/7.txt
new file mode 100644
index 0000000..fe0f6b2
--- /dev/null
+++ b/fastlane/metadata/android/fr-FR/changelogs/7.txt
@@ -0,0 +1 @@
+Améliorations graphiques.
diff --git a/lib/main.dart b/lib/main.dart
index a9ae7b7..621b307 100644
--- a/lib/main.dart
+++ b/lib/main.dart
@@ -98,7 +98,6 @@ class MyApp extends StatelessWidget {
     }
 
     final List<String> skinImages = [
-      'house',
       'seed',
     ];
 
diff --git a/lib/models/data/category.dart b/lib/models/data/category.dart
deleted file mode 100644
index fcfc583..0000000
--- a/lib/models/data/category.dart
+++ /dev/null
@@ -1,24 +0,0 @@
-class Category {
-  final String key;
-  final String text;
-  final String emoji;
-
-  const Category({
-    required this.key,
-    required this.text,
-    required this.emoji,
-  });
-
-  @override
-  String toString() {
-    return '$Category(${toJson()})';
-  }
-
-  Map<String, dynamic> toJson() {
-    return {
-      'key': key,
-      'text': text,
-      'emoji': emoji,
-    };
-  }
-}
diff --git a/lib/models/data/letter.dart b/lib/models/data/letter.dart
deleted file mode 100644
index 7827fe5..0000000
--- a/lib/models/data/letter.dart
+++ /dev/null
@@ -1,21 +0,0 @@
-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/ui/layouts/game_layout.dart b/lib/ui/layouts/game_layout.dart
index 2c89418..127b309 100644
--- a/lib/ui/layouts/game_layout.dart
+++ b/lib/ui/layouts/game_layout.dart
@@ -25,7 +25,7 @@ class GameLayout extends StatelessWidget {
               const SizedBox(height: 8),
               const GameBoardWidget(),
               const SizedBox(height: 8),
-              const Expanded(child: SizedBox.shrink()),
+              //   const Expanded(child: SizedBox.shrink()),
               currentGame.isFinished ? const GameEndWidget() : const SizedBox.shrink(),
             ],
           ),
diff --git a/lib/ui/widgets/game/game_board.dart b/lib/ui/widgets/game/game_board.dart
index 69c2ac1..578fc06 100644
--- a/lib/ui/widgets/game/game_board.dart
+++ b/lib/ui/widgets/game/game_board.dart
@@ -18,19 +18,31 @@ class GameBoardWidget extends StatelessWidget {
           final Game currentGame = gameState.currentGame;
           final Color borderColor = Theme.of(context).colorScheme.onSurface;
 
+          var screenSize = MediaQuery.of(context).size;
+
+          const totalMargins = 9 * 4;
+          final availableHeight = screenSize.height - totalMargins;
+
+          final double houseHeight = availableHeight / 10;
+          final double houseWidth = houseHeight;
+
           return Row(
             mainAxisAlignment: MainAxisAlignment.spaceBetween,
             crossAxisAlignment: CrossAxisAlignment.center,
             children: [
               currentGame.isFinished
                   ? const SizedBox.shrink()
-                  : const GamePlayerWidget(playerIndex: 0),
+                  : SizedBox(
+                      width: houseWidth,
+                      height: houseHeight,
+                      child: const GamePlayerWidget(playerIndex: 0),
+                    ),
               Container(
                 margin: const EdgeInsets.all(2),
                 padding: const EdgeInsets.all(2),
                 decoration: BoxDecoration(
                   color: borderColor,
-                  borderRadius: BorderRadius.circular(2),
+                  borderRadius: BorderRadius.circular(40),
                   border: Border.all(
                     color: borderColor,
                     width: 6,
@@ -40,43 +52,103 @@ class GameBoardWidget extends StatelessWidget {
                   mainAxisAlignment: MainAxisAlignment.spaceBetween,
                   crossAxisAlignment: CrossAxisAlignment.center,
                   children: [
-                    const GameScoreWidget(playerIndex: 0),
+                    SizedBox(
+                      width: 2 * houseWidth,
+                      height: houseHeight,
+                      child: const GameScoreWidget(playerIndex: 1),
+                    ),
                     Table(
                       defaultColumnWidth: const IntrinsicColumnWidth(),
-                      children: const [
+                      children: [
                         TableRow(children: [
-                          GameHouseWidget(cellIndex: 0),
-                          GameHouseWidget(cellIndex: 11),
+                          SizedBox(
+                            width: houseWidth,
+                            height: houseHeight,
+                            child: const GameHouseWidget(cellIndex: 0),
+                          ),
+                          SizedBox(
+                            width: houseWidth,
+                            height: houseHeight,
+                            child: const GameHouseWidget(cellIndex: 11),
+                          ),
                         ]),
                         TableRow(children: [
-                          GameHouseWidget(cellIndex: 1),
-                          GameHouseWidget(cellIndex: 10),
+                          SizedBox(
+                            width: houseWidth,
+                            height: houseHeight,
+                            child: const GameHouseWidget(cellIndex: 1),
+                          ),
+                          SizedBox(
+                            width: houseWidth,
+                            height: houseHeight,
+                            child: const GameHouseWidget(cellIndex: 10),
+                          ),
                         ]),
                         TableRow(children: [
-                          GameHouseWidget(cellIndex: 2),
-                          GameHouseWidget(cellIndex: 9),
+                          SizedBox(
+                            width: houseWidth,
+                            height: houseHeight,
+                            child: const GameHouseWidget(cellIndex: 2),
+                          ),
+                          SizedBox(
+                            width: houseWidth,
+                            height: houseHeight,
+                            child: const GameHouseWidget(cellIndex: 9),
+                          ),
                         ]),
                         TableRow(children: [
-                          GameHouseWidget(cellIndex: 3),
-                          GameHouseWidget(cellIndex: 8),
+                          SizedBox(
+                            width: houseWidth,
+                            height: houseHeight,
+                            child: const GameHouseWidget(cellIndex: 3),
+                          ),
+                          SizedBox(
+                            width: houseWidth,
+                            height: houseHeight,
+                            child: const GameHouseWidget(cellIndex: 8),
+                          ),
                         ]),
                         TableRow(children: [
-                          GameHouseWidget(cellIndex: 4),
-                          GameHouseWidget(cellIndex: 7),
+                          SizedBox(
+                            width: houseWidth,
+                            height: houseHeight,
+                            child: const GameHouseWidget(cellIndex: 4),
+                          ),
+                          SizedBox(
+                            width: houseWidth,
+                            height: houseHeight,
+                            child: const GameHouseWidget(cellIndex: 7),
+                          ),
                         ]),
                         TableRow(children: [
-                          GameHouseWidget(cellIndex: 5),
-                          GameHouseWidget(cellIndex: 6),
+                          SizedBox(
+                            width: houseWidth,
+                            height: houseHeight,
+                            child: const GameHouseWidget(cellIndex: 5),
+                          ),
+                          SizedBox(
+                            width: houseWidth,
+                            height: houseHeight,
+                            child: const GameHouseWidget(cellIndex: 6),
+                          ),
                         ]),
                       ],
                     ),
-                    const GameScoreWidget(playerIndex: 1)
+                    SizedBox(
+                      width: 2 * houseWidth,
+                      height: houseHeight,
+                      child: const GameScoreWidget(playerIndex: 0),
+                    ),
                   ],
                 ),
               ),
               currentGame.isFinished
                   ? const SizedBox.shrink()
-                  : const GamePlayerWidget(playerIndex: 1),
+                  : SizedBox(
+                      width: houseWidth,
+                      height: houseHeight,
+                      child: const GamePlayerWidget(playerIndex: 1),
+                    ),
             ],
           );
         },
diff --git a/lib/ui/widgets/game/game_house.dart b/lib/ui/widgets/game/game_house.dart
index d26961e..d0ae200 100644
--- a/lib/ui/widgets/game/game_house.dart
+++ b/lib/ui/widgets/game/game_house.dart
@@ -3,6 +3,8 @@ import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:awale/cubit/game_cubit.dart';
 import 'package:awale/models/game/game.dart';
+import 'package:awale/ui/widgets/game/game_seeds.dart';
+import 'package:awale/utils/color_extensions.dart';
 
 class GameHouseWidget extends StatelessWidget {
   const GameHouseWidget({
@@ -37,22 +39,14 @@ class GameHouseWidget extends StatelessWidget {
               padding: const EdgeInsets.all(2),
               decoration: BoxDecoration(
                 color: baseColor,
-                borderRadius: BorderRadius.circular(2),
+                borderRadius: BorderRadius.circular(100),
                 border: Border.all(
-                  color: baseColor,
-                  width: 2,
-                ),
-              ),
-              width: 50,
-              child: Text(
-                seedsCount == 0 ? '' : seedsCount.toString(),
-                textAlign: TextAlign.center,
-                style: TextStyle(
-                  fontSize: 30,
-                  fontWeight: FontWeight.bold,
-                  color: Theme.of(context).colorScheme.primary,
+                  color: baseColor.darken(),
+                  width: 4,
                 ),
               ),
+              width: 60,
+              child: GameSeedsWidget(seedsCount: seedsCount),
             ),
           ),
         );
diff --git a/lib/ui/widgets/game/game_player.dart b/lib/ui/widgets/game/game_player.dart
index 67eb225..84fed3c 100644
--- a/lib/ui/widgets/game/game_player.dart
+++ b/lib/ui/widgets/game/game_player.dart
@@ -1,8 +1,10 @@
+import 'package:awale/utils/color_extensions.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:awale/cubit/game_cubit.dart';
 import 'package:awale/models/game/game.dart';
+import 'package:awale/ui/widgets/game/game_seeds.dart';
 
 class GamePlayerWidget extends StatelessWidget {
   const GamePlayerWidget({
@@ -29,23 +31,13 @@ class GamePlayerWidget extends StatelessWidget {
           padding: const EdgeInsets.all(2),
           decoration: BoxDecoration(
             color: baseColor,
-            borderRadius: BorderRadius.circular(2),
+            borderRadius: BorderRadius.circular(6),
             border: Border.all(
-              color: baseColor,
-              width: 2,
-            ),
-          ),
-          width: 100,
-          height: 100,
-          child: Text(
-            seedsCount == 0 ? '' : seedsCount.toString(),
-            textAlign: TextAlign.center,
-            style: TextStyle(
-              fontSize: 50,
-              fontWeight: FontWeight.bold,
-              color: Theme.of(context).colorScheme.primary,
+              color: baseColor.darken(),
+              width: 6,
             ),
           ),
+          child: GameSeedsWidget(seedsCount: seedsCount),
         );
       },
     );
diff --git a/lib/ui/widgets/game/game_score.dart b/lib/ui/widgets/game/game_score.dart
index 89834f2..9bea3b2 100644
--- a/lib/ui/widgets/game/game_score.dart
+++ b/lib/ui/widgets/game/game_score.dart
@@ -1,8 +1,10 @@
+import 'package:awale/utils/color_extensions.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 
 import 'package:awale/cubit/game_cubit.dart';
 import 'package:awale/models/game/game.dart';
+import 'package:awale/ui/widgets/game/game_seeds.dart';
 
 class GameScoreWidget extends StatelessWidget {
   const GameScoreWidget({
@@ -28,22 +30,14 @@ class GameScoreWidget extends StatelessWidget {
           padding: const EdgeInsets.all(2),
           decoration: BoxDecoration(
             color: baseColor,
-            borderRadius: BorderRadius.circular(2),
+            borderRadius: BorderRadius.circular(100),
             border: Border.all(
-              color: baseColor,
-              width: 2,
+              color: baseColor.darken(),
+              width: 4,
             ),
           ),
           width: 100,
-          child: Text(
-            currentGame.scores[playerIndex].toString(),
-            textAlign: TextAlign.center,
-            style: TextStyle(
-              fontSize: 50,
-              fontWeight: FontWeight.bold,
-              color: Theme.of(context).colorScheme.primary,
-            ),
-          ),
+          child: GameSeedsWidget(seedsCount: currentGame.scores[playerIndex]),
         );
       },
     );
diff --git a/lib/ui/widgets/game/game_seeds.dart b/lib/ui/widgets/game/game_seeds.dart
new file mode 100644
index 0000000..8a05066
--- /dev/null
+++ b/lib/ui/widgets/game/game_seeds.dart
@@ -0,0 +1,89 @@
+import 'dart:math';
+
+import 'package:flutter/material.dart';
+import 'package:flutter_bloc/flutter_bloc.dart';
+
+import 'package:awale/cubit/game_cubit.dart';
+import 'package:awale/models/game/game.dart';
+
+class GameSeedsWidget extends StatelessWidget {
+  const GameSeedsWidget({
+    super.key,
+    required this.seedsCount,
+  });
+
+  final int seedsCount;
+
+  @override
+  Widget build(BuildContext context) {
+    return BlocBuilder<GameCubit, GameState>(
+      builder: (BuildContext context, GameState gameState) {
+        final Game currentGame = gameState.currentGame;
+        final String skin = currentGame.globalSettings.skin;
+
+        const ratioScale = 0.2;
+        const ratioTranslate = 0.65;
+
+        const List<List<double>> layout = [
+          [0, 0], // 1
+          [10, -17], // 2
+          [20, 0], // 3
+          [10, 17], // 4
+          [-10, 17], // 5
+          [-20, 0], // 6
+          [-10, -17], // 7
+          [0, -34], // 8
+          [21, -34], // 9
+          [30, -16], // 10
+          [40, 0], // 11
+          [30, -18], // 12
+          [20, 35], // 13
+          [0, 35], // 14
+          [-20, 35], // 15
+          [-30, 18], // 16
+          [-38, 0], // 17
+          [-30, -16], // 18
+          [-20, -34], // 19
+        ];
+
+        double minX = 0;
+        double maxX = 0;
+        double minY = 0;
+        double maxY = 0;
+
+        for (int i = 0; i < seedsCount; i++) {
+          final List<double> seedLocation = layout[i];
+
+          maxX = max(maxX, seedLocation[0]);
+          minX = min(minX, seedLocation[0]);
+          maxY = max(maxY, seedLocation[1]);
+          minY = min(minY, seedLocation[1]);
+        }
+
+        final double deltaX = minX + (maxX - minX) / 2;
+        final double deltaY = minY + (maxY - minY) / 2;
+
+        List<Widget> seeds = [];
+        for (int i = 0; i < seedsCount; i++) {
+          final List<double> seedLocation = layout[i];
+          seeds.add(
+            Transform.translate(
+              offset: Offset(
+                ratioTranslate * (seedLocation[0] - deltaX),
+                ratioTranslate * (seedLocation[1] - deltaY),
+              ),
+              child: Transform.scale(
+                scale: ratioScale,
+                child: Image.asset('assets/skins/${skin}_seed.png'),
+              ),
+            ),
+          );
+        }
+
+        return Stack(
+          children: seeds,
+        );
+      },
+    );
+  }
+}
diff --git a/pubspec.yaml b/pubspec.yaml
index 8d28b01..b13223f 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -3,7 +3,7 @@ description: Awale game
 
 publish_to: "none"
 
-version: 0.0.6+6
+version: 0.0.7+7
 
 environment:
   sdk: "^3.0.0"
diff --git a/resources/seeds_layout.svg b/resources/seeds_layout.svg
new file mode 100644
index 0000000..221b8f1
--- /dev/null
+++ b/resources/seeds_layout.svg
@@ -0,0 +1,335 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+   enable-background="new 0 0 100 100"
+   version="1.1"
+   viewBox="0 0 102 102"
+   xml:space="preserve"
+   id="svg1"
+   sodipodi:docname="seeds_layout.svg"
+   inkscape:version="1.3.2 (1:1.3.2+202311252150+091e20ef0f)"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns="http://www.w3.org/2000/svg"
+   xmlns:svg="http://www.w3.org/2000/svg"><defs
+     id="defs1" /><sodipodi:namedview
+     id="namedview1"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1.0"
+     inkscape:showpageshadow="2"
+     inkscape:pageopacity="0.0"
+     inkscape:pagecheckerboard="0"
+     inkscape:deskcolor="#d1d1d1"
+     inkscape:zoom="4.1078432"
+     inkscape:cx="18.622912"
+     inkscape:cy="18.988067"
+     inkscape:window-width="1199"
+     inkscape:window-height="838"
+     inkscape:window-x="3531"
+     inkscape:window-y="68"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg1" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="path1"
+     cx="0.24011007"
+     cy="-0.2564899"
+     r="9.4961176"
+     transform="rotate(128.31689)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle12"
+     cx="-39.179901"
+     cy="-8.8366365"
+     r="9.4961176"
+     transform="rotate(-72.165849)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle13"
+     cx="-20.544954"
+     cy="27.919674"
+     r="9.4961176"
+     transform="rotate(-35.338291)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle14"
+     cx="19.937935"
+     cy="34.132896"
+     r="9.4961176"
+     transform="rotate(1.4893076)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle15"
+     cx="33.807491"
+     cy="-4.5862694"
+     r="9.4961176"
+     transform="rotate(38.316887)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle16"
+     cx="10.259504"
+     cy="-38.344585"
+     r="9.4961176"
+     transform="rotate(75.144506)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle17"
+     cx="-26.963198"
+     cy="-21.682329"
+     r="9.4961176"
+     transform="rotate(111.97209)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle18"
+     cx="-35.107906"
+     cy="18.365372"
+     r="9.4961176"
+     transform="rotate(148.79967)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle19"
+     cx="2.7728879"
+     cy="33.62381"
+     r="9.4961176"
+     transform="rotate(-174.37276)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle20"
+     cx="36.981033"
+     cy="11.651199"
+     r="9.4961176"
+     transform="rotate(-137.54517)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle21"
+     cx="21.71364"
+     cy="-26.034775"
+     r="9.4961176"
+     transform="rotate(-100.71757)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle22"
+     cx="-18.037323"
+     cy="-35.501793"
+     r="9.4961176"
+     transform="rotate(-63.890011)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle23"
+     cx="-34.741604"
+     cy="1.8949511"
+     r="9.4961176"
+     transform="rotate(-27.062431)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle24"
+     cx="-7.0690489"
+     cy="18.942566"
+     r="9.4961176"
+     transform="rotate(9.7651874)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle25"
+     cx="19.332306"
+     cy="4.9920368"
+     r="9.4961176"
+     transform="rotate(46.592737)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle26"
+     cx="2.5728326"
+     cy="-19.762348"
+     r="9.4961176"
+     transform="rotate(83.420366)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle27"
+     cx="-19.671154"
+     cy="-0.43411279"
+     r="9.4961176"
+     transform="rotate(120.24798)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle28"
+     cx="2.4148488"
+     cy="19.107695"
+     r="9.4961176"
+     transform="rotate(157.07556)" /><circle
+     style="fill:#43834c;stroke:#152818;stroke-width:0.897713;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none;stroke-opacity:1"
+     id="circle29"
+     cx="19.188715"
+     cy="-5.1802483"
+     r="9.4961176"
+     transform="rotate(-166.09691)" /><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="-5.5879693"
+     y="-0.105837"
+     id="text1"><tspan
+       sodipodi:role="line"
+       id="tspan1"
+       x="-5.5879693"
+       y="-0.105837"
+       style="stroke-width:0.196623">1</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="13.903109"
+     y="-0.31237617"
+     id="text2"><tspan
+       sodipodi:role="line"
+       id="tspan2"
+       x="13.903109"
+       y="-0.31237617"
+       style="stroke-width:0.196623">3</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="4.2930083"
+     y="18.846392"
+     id="text3"><tspan
+       sodipodi:role="line"
+       id="tspan3"
+       x="4.2930083"
+       y="18.846392"
+       style="stroke-width:0.196623">4</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="-14.656782"
+     y="18.846392"
+     id="text4"><tspan
+       sodipodi:role="line"
+       id="tspan4"
+       x="-14.656782"
+       y="18.846392"
+       style="stroke-width:0.196623">5</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="-23.915712"
+     y="-0.93393528"
+     id="text5"><tspan
+       sodipodi:role="line"
+       id="tspan5"
+       x="-23.915712"
+       y="-0.93393528"
+       style="stroke-width:0.196623">6</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="-13.795031"
+     y="-15.558908"
+     id="text6"><tspan
+       sodipodi:role="line"
+       id="tspan6"
+       x="-13.795031"
+       y="-15.558908"
+       style="stroke-width:0.196623">7</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="8.4240704"
+     y="-14.865454"
+     id="text7"><tspan
+       sodipodi:role="line"
+       id="tspan7"
+       x="8.4240704"
+       y="-14.865454"
+       style="stroke-width:0.196623">2</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="26.778719"
+     y="-16.190016"
+     id="text8"><tspan
+       sodipodi:role="line"
+       id="tspan8"
+       x="26.778719"
+       y="-16.190016"
+       style="stroke-width:0.196623">10</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="33.585457"
+     y="-0.28264824"
+     id="text9"><tspan
+       sodipodi:role="line"
+       id="tspan9"
+       x="33.585457"
+       y="-0.28264824"
+       style="stroke-width:0.196623">11</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="22.871408"
+     y="17.452448"
+     id="text10"><tspan
+       sodipodi:role="line"
+       id="tspan10"
+       x="22.871408"
+       y="17.452448"
+       style="stroke-width:0.196623">12</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="14.791765"
+     y="31.922098"
+     id="text11"><tspan
+       sodipodi:role="line"
+       id="tspan11"
+       x="14.791765"
+       y="31.922098"
+       style="stroke-width:0.196623">13</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="-5.4304147"
+     y="33.756279"
+     id="text12"><tspan
+       sodipodi:role="line"
+       id="tspan12"
+       x="-5.4304147"
+       y="33.756279"
+       style="stroke-width:0.196623">14</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="-25.521875"
+     y="33.744972"
+     id="text13"><tspan
+       sodipodi:role="line"
+       id="tspan13"
+       x="-25.521875"
+       y="33.744972"
+       style="stroke-width:0.196623">15</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="-35.382278"
+     y="17.175936"
+     id="text14"><tspan
+       sodipodi:role="line"
+       id="tspan14"
+       x="-35.382278"
+       y="17.175936"
+       style="stroke-width:0.196623">16</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="-42.581348"
+     y="1.4445361"
+     id="text15"><tspan
+       sodipodi:role="line"
+       id="tspan15"
+       x="-42.581348"
+       y="1.4445361"
+       style="stroke-width:0.196623">17</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="-32.45631"
+     y="-16.667093"
+     id="text16"><tspan
+       sodipodi:role="line"
+       id="tspan16"
+       x="-32.45631"
+       y="-16.667093"
+       style="stroke-width:0.196623">18</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="-22.339037"
+     y="-30.433443"
+     id="text17"><tspan
+       sodipodi:role="line"
+       id="tspan17"
+       x="-22.339037"
+       y="-30.433443"
+       style="stroke-width:0.196623">19</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="-2.6990914"
+     y="-31.878004"
+     id="text18"><tspan
+       sodipodi:role="line"
+       id="tspan18"
+       x="-2.6990914"
+       y="-31.878004"
+       style="stroke-width:0.196623">8</tspan></text><text
+     xml:space="preserve"
+     style="font-style:normal;font-weight:normal;font-size:7.86491px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;word-spacing:0px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.196623"
+     x="16.496477"
+     y="-31.550072"
+     id="text19"><tspan
+       sodipodi:role="line"
+       id="tspan19"
+       x="16.496477"
+       y="-31.550072"
+       style="stroke-width:0.196623">9</tspan></text></svg>
diff --git a/resources/ui/skins/default/house.svg b/resources/ui/skins/default/house.svg
deleted file mode 100644
index f5b9722..0000000
--- a/resources/ui/skins/default/house.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<svg enable-background="new 0 0 100 100" version="1.1" viewBox="0 0 100 100" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"><rect width="100" height="100" ry="2" fill="none"/><rect x="2.6304" y="2.6304" width="94.739" height="94.739" ry="20.054" fill="#c6bd7b" stroke="#505050" stroke-linecap="round" stroke-linejoin="round" stroke-width="2.4632"/></svg>
-- 
GitLab