diff --git a/.gitignore b/.gitignore
index 96d545b0d571e47eb28482b8851d26045aeec5f5..236e42707f5e11d1ec7e92a727ac0df4abc646bc 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/logs/
 /target/
 /bin/
 .settings/
@@ -5,4 +6,4 @@
 .classpath
 .idea/
 *.mv.db
-*.trace.db
\ No newline at end of file
+*.trace.db
diff --git a/pom.xml b/pom.xml
index 3b70e3bf97e5e7b41a783fe9f0c3e2d8ea4e5566..618b538f7cc0ee9222e349fcb9d9c71e781a54c0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,6 +13,22 @@
 		<maven.compiler.target>21</maven.compiler.target>
 	</properties>
 	<dependencies>
+		<!--
+		https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-core -->
+		<dependency>
+			<groupId>org.apache.logging.log4j</groupId>
+			<artifactId>log4j-core</artifactId>
+			<version>2.24.3</version>
+		</dependency>
+
+		<!--
+		https://mvnrepository.com/artifact/org.apache.logging.log4j/log4j-api -->
+		<dependency>
+			<groupId>org.apache.logging.log4j</groupId>
+			<artifactId>log4j-api</artifactId>
+			<version>2.24.3</version>
+		</dependency>
+
 		<dependency>
 			<groupId>com.h2database</groupId>
 			<artifactId>h2</artifactId>
diff --git a/src/main/java/lab/Config.java b/src/main/java/lab/Config.java
index f1aa8b7ed2cddc6e289c700673f4e05e005a8d25..0a18ac14467a53af169efc0f07de81e85605ae6d 100644
--- a/src/main/java/lab/Config.java
+++ b/src/main/java/lab/Config.java
@@ -7,19 +7,33 @@ public class Config {
 
 	private static Config instance;
 
-	private ScoreStorageInterface scoreStorageInterface = new DbConnector();
-	private double monsterMinXPopsition = 0.5;
-	private double monsterMinSpeed = 50;
-	private double monsterMaxSpeed = 150;
-	private double obstacleWidth = 30;
-	private double obstacleHeight = 20;
-	private double playerStartSpeed= 50;
-	private int monsterMultiplier= 1;
-	
+	private ScoreStorageInterface scoreStorageInterface;
+	private double monsterMinXPopsition;
+	private double monsterMinSpeed;
+	private double monsterMaxSpeed;
+	private double obstacleWidth;
+	private double obstacleHeight;
+	private double playerStartSpeed;
+	private int monsterMultiplier;
+
 	public static void configure(Config setting) {
 		instance = setting;
 	}
 
+	private Config(ScoreStorageInterface scoreStorageInterface, double monsterMinXPopsition, double monsterMinSpeed,
+			double monsterMaxSpeed, double obstacleWidth, double obstacleHeight, double playerStartSpeed,
+			int monsterMultiplier) {
+		super();
+		this.scoreStorageInterface = scoreStorageInterface;
+		this.monsterMinXPopsition = monsterMinXPopsition;
+		this.monsterMinSpeed = monsterMinSpeed;
+		this.monsterMaxSpeed = monsterMaxSpeed;
+		this.obstacleWidth = obstacleWidth;
+		this.obstacleHeight = obstacleHeight;
+		this.playerStartSpeed = playerStartSpeed;
+		this.monsterMultiplier = monsterMultiplier;
+	}
+
 	public static Config getInstance() {
 		return instance;
 	}
@@ -55,6 +69,71 @@ public class Config {
 	public int getMonsterMultiplier() {
 		return monsterMultiplier;
 	}
-	
+
+	public static Builder builder() {
+		return new Builder();
+	}
+
+	public static Config getInstanceForHardcoreGame() {
+		return builder().monsterMinSpeed(150).monsterMaxSpeed(500).monsterMultiplier(5).monsterMinXPopsition(0.2)
+				.build();
+	}
+
+	public static class Builder {
+		private ScoreStorageInterface scoreStorageInterface = new DbConnector();
+		private double monsterMinXPopsition = 0.5;
+		private double monsterMinSpeed = 50;
+		private double monsterMaxSpeed = 150;
+		private double obstacleWidth = 30;
+		private double obstacleHeight = 20;
+		private double playerStartSpeed = 50;
+		private int monsterMultiplier = 1;
+
+		public Builder scoreStorageInterface(ScoreStorageInterface scoreStorageInterface) {
+			this.scoreStorageInterface = scoreStorageInterface;
+			return this;
+		}
+
+		public Builder monsterMinXPopsition(double monsterMinXPopsition) {
+			this.monsterMinXPopsition = monsterMinXPopsition;
+			return this;
+		}
+
+		public Builder monsterMinSpeed(double monsterMinSpeed) {
+			this.monsterMinSpeed = monsterMinSpeed;
+			return this;
+		}
+
+		public Builder monsterMaxSpeed(double monsterMaxSpeed) {
+			this.monsterMaxSpeed = monsterMaxSpeed;
+			return this;
+		}
+
+		public Builder obstacleWidth(double obstacleWidth) {
+			this.obstacleWidth = obstacleWidth;
+			return this;
+		}
+
+		public Builder obstacleHeight(double obstacleHeight) {
+			this.obstacleHeight = obstacleHeight;
+			return this;
+		}
+
+		public Builder playerStartSpeed(double playerStartSpeed) {
+			this.playerStartSpeed = playerStartSpeed;
+			return this;
+		}
+
+		public Builder monsterMultiplier(int monsterMultiplier) {
+			this.monsterMultiplier = monsterMultiplier;
+			return this;
+		}
+
+		public Config build() {
+			return new Config(scoreStorageInterface, monsterMinXPopsition, monsterMinSpeed, monsterMaxSpeed,
+					obstacleWidth, obstacleHeight, playerStartSpeed, monsterMultiplier);
+		}
+
+	}
 
 }
diff --git a/src/main/java/lab/data/Score.java b/src/main/java/lab/data/Score.java
index 01dc746bf946fa4492b77a46a8f80fb85d50d655..a9993a9c51be53b7870842a1757836b776292340 100644
--- a/src/main/java/lab/data/Score.java
+++ b/src/main/java/lab/data/Score.java
@@ -1,5 +1,6 @@
 package lab.data;
 
+import java.util.Objects;
 import java.util.Random;
 
 public class Score {
@@ -30,6 +31,23 @@ public class Score {
 		this.points = points;
 	}
 
+	@Override
+	public int hashCode() {
+		return Objects.hash(name, points);
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj)
+			return true;
+		if (obj == null)
+			return false;
+		if (getClass() != obj.getClass())
+			return false;
+		Score other = (Score) obj;
+		return Objects.equals(name, other.name) && points == other.points;
+	}
+
 	@Override
 	public String toString() {
 		return "Score [name=" + name + ", points=" + points + "]";
diff --git a/src/main/java/lab/game/Monster.java b/src/main/java/lab/game/Monster.java
index 0bca7df5dc2ea193fbd2e4ce6c286dd4371745d2..a256acc1d481bf7b8b1a0deec7ce8cbeabf9888b 100644
--- a/src/main/java/lab/game/Monster.java
+++ b/src/main/java/lab/game/Monster.java
@@ -4,6 +4,9 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Random;
 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
 import javafx.geometry.Dimension2D;
 import javafx.geometry.Point2D;
 import javafx.geometry.Rectangle2D;
@@ -13,6 +16,8 @@ import lab.Config;
 
 public class Monster extends WorldEntity implements Collisionable {
 
+	private static Logger log = LogManager.getLogger(Monster.class);
+
 	private static final Random RANDOM = new Random();
 
 	private Image image;
@@ -41,6 +46,7 @@ public class Monster extends WorldEntity implements Collisionable {
 
 	public void changeDirection() {
 		speed = speed.multiply(-1);
+		log.debug("Monster chaned direction.");
 	}
 
 	public void simulate(double delay) {
@@ -49,7 +55,7 @@ public class Monster extends WorldEntity implements Collisionable {
 		if (position.getY() + image.getHeight() < 0) {
 			position = new Point2D(position.getX(), level.getHeight());
 		}
-	}
+		log.trace("Monster position: {}", position);	}
 
 	@Override
 	public Rectangle2D getBoundingBox() {
@@ -63,6 +69,7 @@ public class Monster extends WorldEntity implements Collisionable {
 
 	@Override
 	public void hitBy(Collisionable another) {
+		log.trace("Moster hitted by {}.", another);
 		if (another instanceof Player) {
 			level.remove(this);
 			level.add(new Obstacle(level, getPosition(), new Dimension2D(Config.getInstance().getObstacleWidth(),
diff --git a/src/main/java/lab/gui/App.java b/src/main/java/lab/gui/App.java
index 62f014e6c0caa6ca94e616d6d5238085a0873ccc..270f55187013d85a9bbc7812f2325845be0d59d0 100644
--- a/src/main/java/lab/gui/App.java
+++ b/src/main/java/lab/gui/App.java
@@ -3,6 +3,9 @@ package lab.gui;
 import java.io.IOException;
 import java.net.URL;
 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
 import javafx.application.Application;
 import javafx.fxml.FXMLLoader;
 import javafx.scene.Parent;
@@ -19,12 +22,14 @@ import lab.Config;
  */
 public class App extends Application {
 
+	private static Logger log = LogManager.getLogger(App.class);
 	private GameController gameController;
 	
 	private Stage primaryStage;
 	
 	public static void main(String[] args) {
-		Config.configure(new Config());
+		log.info("Application lauched");
+		Config.configure(Config.getInstanceForHardcoreGame());
 		launch(args);
 	}
 
@@ -38,7 +43,7 @@ public class App extends Application {
 			// Exit program when main window is closed
 			primaryStage.setOnCloseRequest(this::exitProgram);
 		} catch (Exception e) {
-			e.printStackTrace();
+			log.error("Error during game play.", e);
 		}
 	}
 
@@ -71,9 +76,11 @@ public class App extends Application {
 			gameController.stop();
 		}
 		super.stop();
+		log.info("Gamne stoped");
 	}
 
 	private void exitProgram(WindowEvent evt) {
+		log.info("Exiting game");
 		System.exit(0);
 	}
 }
\ No newline at end of file
diff --git a/src/main/java/lab/gui/GameController.java b/src/main/java/lab/gui/GameController.java
index 13c98d55bbb33eb2c0316019e9a31c3d13586bf7..fde1322c0cfd3c1d7bd889c85c76d04402e38cae 100644
--- a/src/main/java/lab/gui/GameController.java
+++ b/src/main/java/lab/gui/GameController.java
@@ -1,5 +1,8 @@
 package lab.gui;
 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
 import javafx.animation.AnimationTimer;
 import javafx.beans.value.ObservableValue;
 import javafx.event.ActionEvent;
@@ -15,6 +18,8 @@ import lab.game.MujListener;
 
 public class GameController {
 
+	private static Logger log = LogManager.getLogger(GameController.class);
+
 	private AnimationTimer timer;
 	private Level level;
 
@@ -60,6 +65,7 @@ public class GameController {
 					level.getPlayer().setSpeed(newValue.doubleValue());
 				});
 
+		log.info("Screeen initialized.");
 	}
 
 	public void startGame(String name, int numberOfMonsters) {
diff --git a/src/main/java/lab/gui/MainScreenController.java b/src/main/java/lab/gui/MainScreenController.java
index f362c767533632f781c88477023fc1a136980cb1..45c849ad3e39027f6a0aa7f591c3f895b0077185 100644
--- a/src/main/java/lab/gui/MainScreenController.java
+++ b/src/main/java/lab/gui/MainScreenController.java
@@ -3,6 +3,9 @@ package lab.gui;
 import java.io.IOException;
 import java.util.List;
 
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
 import javafx.event.ActionEvent;
 import javafx.fxml.FXML;
 import javafx.scene.control.Button;
@@ -21,6 +24,8 @@ import lab.game.Difficult;
  */
 public class MainScreenController {
 
+	private static Logger log = LogManager.getLogger(MainScreenController.class);
+
     @FXML
     private Button btnGenerateScore;
 
@@ -100,6 +105,7 @@ public class MainScreenController {
 		pointsColumn.setCellValueFactory(new PropertyValueFactory<>("points"));
 		
 		initDB();
+		log.info("Screeen initialized.");
 	}
 	
 	private void initDB() {
diff --git a/src/main/java/module-info.java b/src/main/java/module-info.java
index 732cf186a66ae4af97c710524d7fa139e8247470..75517d2cb9c0ac2380899c7faf60e5c6d1fa0c85 100644
--- a/src/main/java/module-info.java
+++ b/src/main/java/module-info.java
@@ -3,6 +3,7 @@ module cz.vsb.fei.java2.lab03_module {
 	requires javafx.fxml;
 	requires javafx.base;
 	requires java.sql;
+	requires org.apache.logging.log4j;
 
 	opens lab.gui to javafx.fxml;
 	opens lab.data to javafx.base;
diff --git a/src/main/resources/log4j2.xml b/src/main/resources/log4j2.xml
new file mode 100644
index 0000000000000000000000000000000000000000..da032d36b62811a46f0edf9bd0e5d3aa4cb66e58
--- /dev/null
+++ b/src/main/resources/log4j2.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Configuration xmlns="https://logging.apache.org/xml/ns"
+	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="
+                   https://logging.apache.org/xml/ns
+                   https://logging.apache.org/xml/ns/log4j-config-2.xsd">
+	<Appenders>
+		<Console name="Console">
+			<PatternLayout
+				pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
+		</Console>
+		<RollingFile name="File" fileName="logs/app.log"
+			filePattern="logs/app.%d{yyyy-MM-dd}.%i.log.gz">
+			<PatternLayout
+				pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
+			<DefaultRolloverStrategy max="5">
+				<Delete basePath="logs">
+					<IfAccumulatedFileSize  exceeds="2.2M" />
+				</Delete>
+			</DefaultRolloverStrategy>
+			<Policies>
+				<OnStartupTriggeringPolicy />
+				<SizeBasedTriggeringPolicy size="10M" />
+				<TimeBasedTriggeringPolicy interval="1" />
+			</Policies>
+		</RollingFile>
+	</Appenders>
+	<Loggers>
+		<Root level="INFO">
+			<AppenderRef ref="Console" level="INFO"/>
+			<AppenderRef ref="File" />
+		</Root>
+		<Logger name="lab.game" level="TRACE">
+		</Logger>
+	</Loggers>
+</Configuration>