Merge pull request 'Chore: Java 21.' (#9) from feature/java21 into master
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build is passing
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	continuous-integration/drone/push Build is passing
				
			Reviewed-on: #9
This commit is contained in:
		
						commit
						e3bc8d8452
					
				
					 34 changed files with 279 additions and 290 deletions
				
			
		|  | @ -3,7 +3,7 @@ type: docker | ||||||
| name: default | name: default | ||||||
| steps: | steps: | ||||||
|   - name: build |   - name: build | ||||||
|     image: maven:3.8-openjdk-18-slim |     image: maven:3.9-eclipse-temurin-21 | ||||||
|     commands: |     commands: | ||||||
|       - mvn clean install -DskipTests=true -Dmaven.javadoc.skip=true -B -V |       - mvn clean install -DskipTests=true -Dmaven.javadoc.skip=true -B -V | ||||||
|     when: |     when: | ||||||
|  | @ -13,7 +13,7 @@ steps: | ||||||
|           - refs/head/feature/** |           - refs/head/feature/** | ||||||
|           - refs/tags/** |           - refs/tags/** | ||||||
|   - name: test |   - name: test | ||||||
|     image: maven:3.8-openjdk-18-slim |     image: maven:3.9-eclipse-temurin-21 | ||||||
|     commands: |     commands: | ||||||
|       - mvn test -B |       - mvn test -B | ||||||
|     when: |     when: | ||||||
|  | @ -22,7 +22,7 @@ steps: | ||||||
|           - master |           - master | ||||||
|           - feature/* |           - feature/* | ||||||
|   - name: deploy |   - name: deploy | ||||||
|     image: maven:3.8-openjdk-18-slim |     image: maven:3.9-eclipse-temurin-21 | ||||||
|     environment: |     environment: | ||||||
|       REPO_TOKEN: |       REPO_TOKEN: | ||||||
|         from_secret: repo-token |         from_secret: repo-token | ||||||
|  |  | ||||||
							
								
								
									
										13
									
								
								pom.xml
									
										
									
									
									
								
							
							
						
						
									
										13
									
								
								pom.xml
									
										
									
									
									
								
							|  | @ -46,7 +46,6 @@ | ||||||
|         <tag>HEAD</tag> |         <tag>HEAD</tag> | ||||||
|     </scm> |     </scm> | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
|     <distributionManagement> |     <distributionManagement> | ||||||
|         <snapshotRepository> |         <snapshotRepository> | ||||||
|             <id>ossrh</id> |             <id>ossrh</id> | ||||||
|  | @ -56,16 +55,22 @@ | ||||||
|     </distributionManagement> |     </distributionManagement> | ||||||
| 
 | 
 | ||||||
|     <properties> |     <properties> | ||||||
|         <jackson.version>2.15.0</jackson.version> |         <assertj.version>3.25.3</assertj.version> | ||||||
|  |         <jackson.version>2.17.1</jackson.version> | ||||||
|         <jsonschema2pojo-maven-plugin.version>1.2.1</jsonschema2pojo-maven-plugin.version> |         <jsonschema2pojo-maven-plugin.version>1.2.1</jsonschema2pojo-maven-plugin.version> | ||||||
|  |         <logback.version>1.5.6</logback.version> | ||||||
|  |         <lombok.version>1.18.32</lombok.version> | ||||||
|  |         <maven.compiler.release>21</maven.compiler.release> | ||||||
|         <maven-site-plugin.version>4.0.0-M8</maven-site-plugin.version> |         <maven-site-plugin.version>4.0.0-M8</maven-site-plugin.version> | ||||||
|         <pdfbox.version>2.0.28</pdfbox.version> |         <pdfbox.version>3.0.2</pdfbox.version> | ||||||
|  |         <slf4j.version>2.0.12</slf4j.version> | ||||||
|     </properties> |     </properties> | ||||||
| 
 | 
 | ||||||
|     <dependencies> |     <dependencies> | ||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>org.projectlombok</groupId> |             <groupId>org.projectlombok</groupId> | ||||||
|             <artifactId>lombok</artifactId> |             <artifactId>lombok</artifactId> | ||||||
|  |             <version>${lombok.version}</version> | ||||||
|         </dependency> |         </dependency> | ||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>org.jetbrains</groupId> |             <groupId>org.jetbrains</groupId> | ||||||
|  | @ -107,7 +112,7 @@ | ||||||
|         <dependency> |         <dependency> | ||||||
|             <groupId>org.assertj</groupId> |             <groupId>org.assertj</groupId> | ||||||
|             <artifactId>assertj-core</artifactId> |             <artifactId>assertj-core</artifactId> | ||||||
|             <version>3.24.2</version> |             <version>${assertj.version}</version> | ||||||
|             <scope>test</scope> |             <scope>test</scope> | ||||||
|         </dependency> |         </dependency> | ||||||
|     </dependencies> |     </dependencies> | ||||||
|  |  | ||||||
|  | @ -9,17 +9,18 @@ import ch.fritteli.maze.generator.renderer.jsonfile.JsonFileRenderer; | ||||||
| import ch.fritteli.maze.generator.renderer.pdffile.PDFFileRenderer; | import ch.fritteli.maze.generator.renderer.pdffile.PDFFileRenderer; | ||||||
| import ch.fritteli.maze.generator.renderer.text.TextRenderer; | import ch.fritteli.maze.generator.renderer.text.TextRenderer; | ||||||
| import ch.fritteli.maze.generator.renderer.textfile.TextFileRenderer; | import ch.fritteli.maze.generator.renderer.textfile.TextFileRenderer; | ||||||
| import java.nio.file.Path; |  | ||||||
| import java.nio.file.Paths; |  | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.experimental.UtilityClass; | import lombok.experimental.UtilityClass; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
|  | 
 | ||||||
|  | import java.nio.file.Path; | ||||||
|  | import java.nio.file.Paths; | ||||||
| 
 | 
 | ||||||
| @Slf4j | @Slf4j | ||||||
| @UtilityClass | @UtilityClass | ||||||
| public class Main { | public class Main { | ||||||
| 
 | 
 | ||||||
|     public static void main(@NonNull final String[] args) { |     public static void main(@NotNull final String[] args) { | ||||||
|         final int width = 20; |         final int width = 20; | ||||||
|         final int height = 30; |         final int height = 30; | ||||||
|         final Maze maze = new Maze(width, height/*, 0*/); |         final Maze maze = new Maze(width, height/*, 0*/); | ||||||
|  | @ -58,7 +59,7 @@ public class Main { | ||||||
|         log.info("PDF rendering to file:\n{}", pdfFileRenderer.render(maze)); |         log.info("PDF rendering to file:\n{}", pdfFileRenderer.render(maze)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private static String getBaseFilename(@NonNull final Maze maze) { |     private static String getBaseFilename(@NotNull final Maze maze) { | ||||||
|         return "maze-" + maze.getWidth() + "x" + maze.getHeight() + "-" + maze.getRandomSeed(); |         return "maze-" + maze.getWidth() + "x" + maze.getHeight() + "-" + maze.getRandomSeed(); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -5,21 +5,22 @@ import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Position; | import ch.fritteli.maze.generator.model.Position; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import io.vavr.control.Option; | import io.vavr.control.Option; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
|  | 
 | ||||||
| import java.util.Deque; | import java.util.Deque; | ||||||
| import java.util.LinkedList; | import java.util.LinkedList; | ||||||
| import java.util.Random; | import java.util.Random; | ||||||
| import lombok.NonNull; |  | ||||||
| 
 | 
 | ||||||
| public class RandomDepthFirst { | public class RandomDepthFirst { | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     private final Maze maze; |     private final Maze maze; | ||||||
|     @NonNull |     @NotNull | ||||||
|     private final Random random; |     private final Random random; | ||||||
|     @NonNull |     @NotNull | ||||||
|     private final Deque<Position> positions = new LinkedList<>(); |     private final Deque<Position> positions = new LinkedList<>(); | ||||||
| 
 | 
 | ||||||
|     public RandomDepthFirst(@NonNull final Maze maze) { |     public RandomDepthFirst(@NotNull final Maze maze) { | ||||||
|         this.maze = maze; |         this.maze = maze; | ||||||
|         this.random = new Random(maze.getRandomSeed()); |         this.random = new Random(maze.getRandomSeed()); | ||||||
|     } |     } | ||||||
|  | @ -34,16 +35,16 @@ public class RandomDepthFirst { | ||||||
|         final Position end = this.maze.getEnd(); |         final Position end = this.maze.getEnd(); | ||||||
|         final Tile endTile = this.maze.getEndTile(); |         final Tile endTile = this.maze.getEndTile(); | ||||||
| 
 | 
 | ||||||
|         if (end.getY() == 0) { |         if (end.y() == 0) { | ||||||
|             endTile.enableDiggingToOrFrom(Direction.TOP); |             endTile.enableDiggingToOrFrom(Direction.TOP); | ||||||
|             endTile.digFrom(Direction.TOP); |             endTile.digFrom(Direction.TOP); | ||||||
|         } else if (end.getX() == 0) { |         } else if (end.x() == 0) { | ||||||
|             endTile.enableDiggingToOrFrom(Direction.LEFT); |             endTile.enableDiggingToOrFrom(Direction.LEFT); | ||||||
|             endTile.digFrom(Direction.LEFT); |             endTile.digFrom(Direction.LEFT); | ||||||
|         } else if (end.getY() == this.maze.getHeight() - 1) { |         } else if (end.y() == this.maze.getHeight() - 1) { | ||||||
|             endTile.enableDiggingToOrFrom(Direction.BOTTOM); |             endTile.enableDiggingToOrFrom(Direction.BOTTOM); | ||||||
|             endTile.digFrom(Direction.BOTTOM); |             endTile.digFrom(Direction.BOTTOM); | ||||||
|         } else if (end.getX() == this.maze.getWidth() - 1) { |         } else if (end.x() == this.maze.getWidth() - 1) { | ||||||
|             endTile.enableDiggingToOrFrom(Direction.RIGHT); |             endTile.enableDiggingToOrFrom(Direction.RIGHT); | ||||||
|             endTile.digFrom(Direction.RIGHT); |             endTile.digFrom(Direction.RIGHT); | ||||||
|         } |         } | ||||||
|  | @ -86,16 +87,16 @@ public class RandomDepthFirst { | ||||||
|         final Position start = this.maze.getStart(); |         final Position start = this.maze.getStart(); | ||||||
|         final Tile startTile = this.maze.getStartTile(); |         final Tile startTile = this.maze.getStartTile(); | ||||||
| 
 | 
 | ||||||
|         if (start.getY() == 0) { |         if (start.y() == 0) { | ||||||
|             startTile.enableDiggingToOrFrom(Direction.TOP); |             startTile.enableDiggingToOrFrom(Direction.TOP); | ||||||
|             startTile.digTo(Direction.TOP); |             startTile.digTo(Direction.TOP); | ||||||
|         } else if (start.getX() == 0) { |         } else if (start.x() == 0) { | ||||||
|             startTile.enableDiggingToOrFrom(Direction.LEFT); |             startTile.enableDiggingToOrFrom(Direction.LEFT); | ||||||
|             startTile.digTo(Direction.LEFT); |             startTile.digTo(Direction.LEFT); | ||||||
|         } else if (start.getY() == this.maze.getHeight() - 1) { |         } else if (start.y() == this.maze.getHeight() - 1) { | ||||||
|             startTile.enableDiggingToOrFrom(Direction.BOTTOM); |             startTile.enableDiggingToOrFrom(Direction.BOTTOM); | ||||||
|             startTile.digTo(Direction.BOTTOM); |             startTile.digTo(Direction.BOTTOM); | ||||||
|         } else if (start.getX() == this.maze.getWidth() - 1) { |         } else if (start.x() == this.maze.getWidth() - 1) { | ||||||
|             startTile.enableDiggingToOrFrom(Direction.RIGHT); |             startTile.enableDiggingToOrFrom(Direction.RIGHT); | ||||||
|             startTile.digTo(Direction.RIGHT); |             startTile.digTo(Direction.RIGHT); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -7,17 +7,11 @@ public enum Direction { | ||||||
|     LEFT; |     LEFT; | ||||||
| 
 | 
 | ||||||
|     public Direction invert() { |     public Direction invert() { | ||||||
|         switch (this) { |         return switch (this) { | ||||||
|             case TOP: |             case TOP -> BOTTOM; | ||||||
|                 return BOTTOM; |             case RIGHT -> LEFT; | ||||||
|             case RIGHT: |             case BOTTOM -> TOP; | ||||||
|                 return LEFT; |             case LEFT -> RIGHT; | ||||||
|             case BOTTOM: |         }; | ||||||
|                 return TOP; |  | ||||||
|             case LEFT: |  | ||||||
|                 return RIGHT; |  | ||||||
|             default: |  | ||||||
|                 throw new IllegalStateException("Programming error: Not all enum values covered in enum Direction#invert()!"); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -3,8 +3,8 @@ package ch.fritteli.maze.generator.model; | ||||||
| import io.vavr.control.Option; | import io.vavr.control.Option; | ||||||
| import lombok.EqualsAndHashCode; | import lombok.EqualsAndHashCode; | ||||||
| import lombok.Getter; | import lombok.Getter; | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.ToString; | import lombok.ToString; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| @EqualsAndHashCode | @EqualsAndHashCode | ||||||
| @ToString | @ToString | ||||||
|  | @ -26,7 +26,7 @@ public class Maze { | ||||||
|         this(width, height, System.nanoTime()); |         this(width, height, System.nanoTime()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public Maze(final int width, final int height, @NonNull final Position start, @NonNull final Position end) { |     public Maze(final int width, final int height, @NotNull final Position start, @NotNull final Position end) { | ||||||
|         this(width, height, System.nanoTime(), start, end); |         this(width, height, System.nanoTime(), start, end); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -34,17 +34,17 @@ public class Maze { | ||||||
|         this(width, height, randomSeed, new Position(0, 0), new Position(width - 1, height - 1)); |         this(width, height, randomSeed, new Position(0, 0), new Position(width - 1, height - 1)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public Maze(final int width, final int height, final long randomSeed, @NonNull final Position start, @NonNull final Position end) { |     public Maze(final int width, final int height, final long randomSeed, @NotNull final Position start, @NotNull final Position end) { | ||||||
|         if (width <= 1 || height <= 1) { |         if (width <= 1 || height <= 1) { | ||||||
|             throw new IllegalArgumentException("width and height must be >1"); |             throw new IllegalArgumentException("width and height must be >1"); | ||||||
|         } |         } | ||||||
|         if (start.equals(end)) { |         if (start.equals(end)) { | ||||||
|             throw new IllegalArgumentException("'start' must not be equal to 'end'"); |             throw new IllegalArgumentException("'start' must not be equal to 'end'"); | ||||||
|         } |         } | ||||||
|         if (start.getX() != 0 && start.getX() != width - 1 && start.getY() != 0 && start.getY() != height - 1) { |         if (start.x() != 0 && start.x() != width - 1 && start.y() != 0 && start.y() != height - 1) { | ||||||
|             throw new IllegalArgumentException("'start' must be at the edge of the maze"); |             throw new IllegalArgumentException("'start' must be at the edge of the maze"); | ||||||
|         } |         } | ||||||
|         if (end.getX() != 0 && end.getX() != width - 1 && end.getY() != 0 && end.getY() != height - 1) { |         if (end.x() != 0 && end.x() != width - 1 && end.y() != 0 && end.y() != height - 1) { | ||||||
|             throw new IllegalArgumentException("'end' must be at the edge of the maze"); |             throw new IllegalArgumentException("'end' must be at the edge of the maze"); | ||||||
|         } |         } | ||||||
|         this.width = width; |         this.width = width; | ||||||
|  | @ -59,7 +59,7 @@ public class Maze { | ||||||
|     /** |     /** | ||||||
|      * INTERNAL API. Exists only for deserialization. Not to be called from user code. |      * INTERNAL API. Exists only for deserialization. Not to be called from user code. | ||||||
|      */ |      */ | ||||||
|     private Maze(@NonNull final Tile[][] field, final int width, final int height, final long randomSeed) { |     private Maze(@NotNull final Tile[][] field, final int width, final int height, final long randomSeed) { | ||||||
|         this.field = field; |         this.field = field; | ||||||
|         this.width = width; |         this.width = width; | ||||||
|         this.height = height; |         this.height = height; | ||||||
|  | @ -71,7 +71,7 @@ public class Maze { | ||||||
|     /** |     /** | ||||||
|      * INTERNAL API. Exists only for deserialization. Not to be called from user code. |      * INTERNAL API. Exists only for deserialization. Not to be called from user code. | ||||||
|      */ |      */ | ||||||
|     private Maze(@NonNull final Tile[][] field, final int width, final int height, @NonNull final Position start, @NonNull final Position end, final long randomSeed) { |     private Maze(@NotNull final Tile[][] field, final int width, final int height, @NotNull final Position start, @NotNull final Position end, final long randomSeed) { | ||||||
|         this.field = field; |         this.field = field; | ||||||
|         this.width = width; |         this.width = width; | ||||||
|         this.height = height; |         this.height = height; | ||||||
|  | @ -80,12 +80,12 @@ public class Maze { | ||||||
|         this.end = end; |         this.end = end; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public Option<Tile> getTileAt(@NonNull final Position position) { |     public Option<Tile> getTileAt(@NotNull final Position position) { | ||||||
|         return this.getTileAt(position.getX(), position.getY()); |         return this.getTileAt(position.x(), position.y()); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public Option<Tile> getTileAt(final int x, final int y) { |     public Option<Tile> getTileAt(final int x, final int y) { | ||||||
|         if (x < 0 || y < 0 || x >= this.width || y >= this.height) { |         if (x < 0 || y < 0 || x >= this.width || y >= this.height) { | ||||||
|             return Option.none(); |             return Option.none(); | ||||||
|  | @ -93,12 +93,12 @@ public class Maze { | ||||||
|         return Option.of(this.field[x][y]); |         return Option.of(this.field[x][y]); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public Tile getStartTile() { |     public Tile getStartTile() { | ||||||
|         return this.getTileAt(this.start).get(); |         return this.getTileAt(this.start).get(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public Tile getEndTile() { |     public Tile getEndTile() { | ||||||
|         return this.getTileAt(this.end).get(); |         return this.getTileAt(this.end).get(); | ||||||
|     } |     } | ||||||
|  | @ -114,7 +114,7 @@ public class Maze { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void hardenWalls(@NonNull final Tile tile, final int x, final int y) { |     private void hardenWalls(@NotNull final Tile tile, final int x, final int y) { | ||||||
|         if (x == 0) { |         if (x == 0) { | ||||||
|             tile.preventDiggingToOrFrom(Direction.LEFT); |             tile.preventDiggingToOrFrom(Direction.LEFT); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -1,27 +1,16 @@ | ||||||
| package ch.fritteli.maze.generator.model; | package ch.fritteli.maze.generator.model; | ||||||
| 
 | 
 | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.Value; |  | ||||||
| import lombok.With; | import lombok.With; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| @Value |  | ||||||
| @With | @With | ||||||
| public class Position { | public record Position(int x, int y) { | ||||||
|     int x; |     public Position move(@NotNull final Direction direction) { | ||||||
|     int y; |         return switch (direction) { | ||||||
| 
 |             case BOTTOM -> this.withY(this.y + 1); | ||||||
|     public Position move(@NonNull final Direction direction) { |             case LEFT -> this.withX(this.x - 1); | ||||||
|         switch (direction) { |             case RIGHT -> this.withX(this.x + 1); | ||||||
|             case BOTTOM: |             case TOP -> this.withY(this.y - 1); | ||||||
|                 return this.withY(this.y + 1); |         }; | ||||||
|             case LEFT: |  | ||||||
|                 return this.withX(this.x - 1); |  | ||||||
|             case RIGHT: |  | ||||||
|                 return this.withX(this.x + 1); |  | ||||||
|             case TOP: |  | ||||||
|                 return this.withY(this.y - 1); |  | ||||||
|             default: |  | ||||||
|                 throw new IllegalStateException("Programming error: Not all Direction enum values covered in Position#move(Direction)!"); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -5,9 +5,9 @@ import io.vavr.control.Option; | ||||||
| import lombok.AccessLevel; | import lombok.AccessLevel; | ||||||
| import lombok.EqualsAndHashCode; | import lombok.EqualsAndHashCode; | ||||||
| import lombok.Getter; | import lombok.Getter; | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.ToString; | import lombok.ToString; | ||||||
| import lombok.experimental.FieldDefaults; | import lombok.experimental.FieldDefaults; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import java.util.EnumSet; | import java.util.EnumSet; | ||||||
| import java.util.Random; | import java.util.Random; | ||||||
|  | @ -32,7 +32,7 @@ public class Tile { | ||||||
|      * @param walls |      * @param walls | ||||||
|      * @param solution |      * @param solution | ||||||
|      */ |      */ | ||||||
|     private Tile(@NonNull final EnumSet<Direction> walls, final boolean solution) { |     private Tile(@NotNull final EnumSet<Direction> walls, final boolean solution) { | ||||||
|         for (final Direction direction : walls) { |         for (final Direction direction : walls) { | ||||||
|             this.walls.set(direction); |             this.walls.set(direction); | ||||||
|             this.walls.harden(direction); |             this.walls.harden(direction); | ||||||
|  | @ -41,15 +41,15 @@ public class Tile { | ||||||
|         this.solution = solution; |         this.solution = solution; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void preventDiggingToOrFrom(@NonNull final Direction direction) { |     public void preventDiggingToOrFrom(@NotNull final Direction direction) { | ||||||
|         this.walls.harden(direction); |         this.walls.harden(direction); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void enableDiggingToOrFrom(@NonNull final Direction direction) { |     public void enableDiggingToOrFrom(@NotNull final Direction direction) { | ||||||
|         this.walls.unharden(direction); |         this.walls.unharden(direction); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public boolean digFrom(@NonNull final Direction direction) { |     public boolean digFrom(@NotNull final Direction direction) { | ||||||
|         if (this.visited) { |         if (this.visited) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|  | @ -57,15 +57,15 @@ public class Tile { | ||||||
|         return this.walls.clear(direction); |         return this.walls.clear(direction); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public boolean digTo(@NonNull final Direction direction) { |     public boolean digTo(@NotNull final Direction direction) { | ||||||
|         return this.walls.clear(direction); |         return this.walls.clear(direction); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void undigTo(@NonNull final Direction direction) { |     public void undigTo(@NotNull final Direction direction) { | ||||||
|         this.walls.set(direction); |         this.walls.set(direction); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public Option<Direction> getRandomAvailableDirection(@NonNull final Random random) { |     public Option<Direction> getRandomAvailableDirection(@NotNull final Random random) { | ||||||
|         final Stream<Direction> availableDirections = this.walls.getUnhardenedSet(); |         final Stream<Direction> availableDirections = this.walls.getUnhardenedSet(); | ||||||
|         if (availableDirections.isEmpty()) { |         if (availableDirections.isEmpty()) { | ||||||
|             return Option.none(); |             return Option.none(); | ||||||
|  | @ -74,7 +74,7 @@ public class Tile { | ||||||
|         return Option.of(availableDirections.get(index)); |         return Option.of(availableDirections.get(index)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public boolean hasWallAt(@NonNull final Direction direction) { |     public boolean hasWallAt(@NotNull final Direction direction) { | ||||||
|         return this.walls.isSet(direction); |         return this.walls.isSet(direction); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -2,8 +2,8 @@ package ch.fritteli.maze.generator.model; | ||||||
| 
 | 
 | ||||||
| import io.vavr.collection.Stream; | import io.vavr.collection.Stream; | ||||||
| import lombok.EqualsAndHashCode; | import lombok.EqualsAndHashCode; | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.ToString; | import lombok.ToString; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import java.util.EnumSet; | import java.util.EnumSet; | ||||||
| import java.util.HashSet; | import java.util.HashSet; | ||||||
|  | @ -17,7 +17,7 @@ public class Walls { | ||||||
|     private final SortedSet<Direction> directions = new TreeSet<>(); |     private final SortedSet<Direction> directions = new TreeSet<>(); | ||||||
|     private final Set<Direction> hardened = new HashSet<>(); |     private final Set<Direction> hardened = new HashSet<>(); | ||||||
| 
 | 
 | ||||||
|     public void set(@NonNull final Direction direction) { |     public void set(@NotNull final Direction direction) { | ||||||
|         this.directions.add(direction); |         this.directions.add(direction); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -25,14 +25,14 @@ public class Walls { | ||||||
|         this.directions.addAll(EnumSet.allOf(Direction.class)); |         this.directions.addAll(EnumSet.allOf(Direction.class)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public boolean clear(@NonNull final Direction direction) { |     public boolean clear(@NotNull final Direction direction) { | ||||||
|         if (this.hardened.contains(direction)) { |         if (this.hardened.contains(direction)) { | ||||||
|             return false; |             return false; | ||||||
|         } |         } | ||||||
|         return this.directions.remove(direction); |         return this.directions.remove(direction); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public boolean isSet(@NonNull final Direction direction) { |     public boolean isSet(@NotNull final Direction direction) { | ||||||
|         return this.directions.contains(direction); |         return this.directions.contains(direction); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -41,14 +41,14 @@ public class Walls { | ||||||
|                 .removeAll(this.hardened); |                 .removeAll(this.hardened); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void harden(@NonNull final Direction direction) { |     public void harden(@NotNull final Direction direction) { | ||||||
|         if (!this.directions.contains(direction)) { |         if (!this.directions.contains(direction)) { | ||||||
|             throw new IllegalStateException("Trying to harden cleared Direction: " + direction); |             throw new IllegalStateException("Trying to harden cleared Direction: " + direction); | ||||||
|         } |         } | ||||||
|         this.hardened.add(direction); |         this.hardened.add(direction); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public void unharden(@NonNull final Direction direction) { |     public void unharden(@NotNull final Direction direction) { | ||||||
|         this.hardened.remove(direction); |         this.hardened.remove(direction); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,9 +1,9 @@ | ||||||
| package ch.fritteli.maze.generator.renderer; | package ch.fritteli.maze.generator.renderer; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import lombok.NonNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| public interface Renderer<T> { | public interface Renderer<T> { | ||||||
|     @NonNull |     @NotNull | ||||||
|     T render(@NonNull final Maze maze); |     T render(@NotNull final Maze maze); | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -6,8 +6,8 @@ import ch.fritteli.maze.generator.model.Tile; | ||||||
| import io.vavr.collection.HashSet; | import io.vavr.collection.HashSet; | ||||||
| import io.vavr.collection.Set; | import io.vavr.collection.Set; | ||||||
| import lombok.AccessLevel; | import lombok.AccessLevel; | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| @RequiredArgsConstructor(access = AccessLevel.PACKAGE) | @RequiredArgsConstructor(access = AccessLevel.PACKAGE) | ||||||
| class Generator { | class Generator { | ||||||
|  | @ -31,7 +31,7 @@ class Generator { | ||||||
|         return sb.toString(); |         return sb.toString(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private Set<String> getClasses(@NonNull final Tile tile) { |     private Set<String> getClasses(@NotNull final Tile tile) { | ||||||
|         Set<String> result = HashSet.empty(); |         Set<String> result = HashSet.empty(); | ||||||
|         if (tile.hasWallAt(Direction.TOP)) { |         if (tile.hasWallAt(Direction.TOP)) { | ||||||
|             result = result.add("top"); |             result = result.add("top"); | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ package ch.fritteli.maze.generator.renderer.html; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.renderer.Renderer; | import ch.fritteli.maze.generator.renderer.Renderer; | ||||||
| import lombok.NonNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| public class HTMLRenderer implements Renderer<String> { | public class HTMLRenderer implements Renderer<String> { | ||||||
| 
 | 
 | ||||||
|  | @ -112,14 +112,14 @@ public class HTMLRenderer implements Renderer<String> { | ||||||
|     private HTMLRenderer() { |     private HTMLRenderer() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public static HTMLRenderer newInstance() { |     public static HTMLRenderer newInstance() { | ||||||
|         return new HTMLRenderer(); |         return new HTMLRenderer(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public String render(@NonNull final Maze maze) { |     public String render(@NotNull final Maze maze) { | ||||||
|         if (maze.getWidth() == 0 || maze.getHeight() == 0) { |         if (maze.getWidth() == 0 || maze.getHeight() == 0) { | ||||||
|             return this.getPreamble(maze) + POSTAMBLE; |             return this.getPreamble(maze) + POSTAMBLE; | ||||||
|         } |         } | ||||||
|  | @ -134,7 +134,7 @@ public class HTMLRenderer implements Renderer<String> { | ||||||
|         return sb.toString(); |         return sb.toString(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private String getPreamble(@NonNull final Maze maze) { |     private String getPreamble(@NotNull final Maze maze) { | ||||||
|         return "<!DOCTYPE html><html lang=\"en\">" + |         return "<!DOCTYPE html><html lang=\"en\">" + | ||||||
|                 "<head>" + |                 "<head>" + | ||||||
|                 "<title>Maze " + maze.getWidth() + "x" + maze.getHeight() + ", ID " + maze.getRandomSeed() + "</title>" + |                 "<title>Maze " + maze.getWidth() + "x" + maze.getHeight() + ", ID " + maze.getRandomSeed() + "</title>" + | ||||||
|  |  | ||||||
|  | @ -5,8 +5,8 @@ import ch.fritteli.maze.generator.renderer.Renderer; | ||||||
| import ch.fritteli.maze.generator.renderer.html.HTMLRenderer; | import ch.fritteli.maze.generator.renderer.html.HTMLRenderer; | ||||||
| import io.vavr.control.Option; | import io.vavr.control.Option; | ||||||
| import io.vavr.control.Try; | import io.vavr.control.Try; | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
|  | @ -17,9 +17,9 @@ import java.util.NoSuchElementException; | ||||||
| 
 | 
 | ||||||
| @Slf4j | @Slf4j | ||||||
| public class HTMLFileRenderer implements Renderer<Path> { | public class HTMLFileRenderer implements Renderer<Path> { | ||||||
|     @NonNull |     @NotNull | ||||||
|     private static final HTMLRenderer HTML_RENDERER = HTMLRenderer.newInstance(); |     private static final HTMLRenderer HTML_RENDERER = HTMLRenderer.newInstance(); | ||||||
|     @NonNull |     @NotNull | ||||||
|     private Option<Path> targetFile; |     private Option<Path> targetFile; | ||||||
| 
 | 
 | ||||||
|     private HTMLFileRenderer() { |     private HTMLFileRenderer() { | ||||||
|  | @ -29,7 +29,7 @@ public class HTMLFileRenderer implements Renderer<Path> { | ||||||
|                 .toOption(); |                 .toOption(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public static HTMLFileRenderer newInstance() { |     public static HTMLFileRenderer newInstance() { | ||||||
|         return new HTMLFileRenderer(); |         return new HTMLFileRenderer(); | ||||||
|     } |     } | ||||||
|  | @ -40,15 +40,15 @@ public class HTMLFileRenderer implements Renderer<Path> { | ||||||
|                 .exists(File::canWrite); |                 .exists(File::canWrite); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public HTMLFileRenderer setTargetFile(@NonNull final Path targetFile) { |     public HTMLFileRenderer setTargetFile(@NotNull final Path targetFile) { | ||||||
|         this.targetFile = Option.of(targetFile); |         this.targetFile = Option.of(targetFile); | ||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public Path render(@NonNull final Maze maze) { |     public Path render(@NotNull final Maze maze) { | ||||||
|         if (!this.isTargetFileDefinedAndWritable()) { |         if (!this.isTargetFileDefinedAndWritable()) { | ||||||
|             try { |             try { | ||||||
|                 Files.createFile(this.targetFile.get()); |                 Files.createFile(this.targetFile.get()); | ||||||
|  |  | ||||||
|  | @ -7,8 +7,8 @@ import ch.fritteli.maze.generator.model.Direction; | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import lombok.AccessLevel; | import lombok.AccessLevel; | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
|  | @ -16,10 +16,10 @@ import java.util.List; | ||||||
| @RequiredArgsConstructor(access = AccessLevel.PACKAGE) | @RequiredArgsConstructor(access = AccessLevel.PACKAGE) | ||||||
| class Generator { | class Generator { | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     private final Maze maze; |     private final Maze maze; | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     JsonMaze generate() { |     JsonMaze generate() { | ||||||
|         final JsonMaze result = new JsonMaze(); |         final JsonMaze result = new JsonMaze(); | ||||||
|         result.setId(String.valueOf(this.maze.getRandomSeed())); |         result.setId(String.valueOf(this.maze.getRandomSeed())); | ||||||
|  | @ -30,7 +30,7 @@ class Generator { | ||||||
|             final ArrayList<JsonCell> row = new ArrayList<>(); |             final ArrayList<JsonCell> row = new ArrayList<>(); | ||||||
|             for (int x = 0; x < this.maze.getWidth(); x++) { |             for (int x = 0; x < this.maze.getWidth(); x++) { | ||||||
|                 // x and y are not effectively final and can therefore not be accessed from within the lambda. Hence, create the string beforehand. |                 // x and y are not effectively final and can therefore not be accessed from within the lambda. Hence, create the string beforehand. | ||||||
|                 final String exceptionString = "Failed to obtain tile at %dx%d, although maze has dimensoins %dx%d" |                 final String exceptionString = "Failed to obtain tile at %dx%d, although maze has dimensions %dx%d" | ||||||
|                         .formatted(x, y, this.maze.getWidth(), this.maze.getHeight()); |                         .formatted(x, y, this.maze.getWidth(), this.maze.getHeight()); | ||||||
|                 final Tile tile = this.maze.getTileAt(x, y) |                 final Tile tile = this.maze.getTileAt(x, y) | ||||||
|                         .getOrElseThrow(() -> new IllegalStateException(exceptionString)); |                         .getOrElseThrow(() -> new IllegalStateException(exceptionString)); | ||||||
|  | @ -46,12 +46,12 @@ class Generator { | ||||||
|         } |         } | ||||||
|         result.setGrid(rows); |         result.setGrid(rows); | ||||||
|         final JsonCoordinates start = new JsonCoordinates(); |         final JsonCoordinates start = new JsonCoordinates(); | ||||||
|         start.setX(this.maze.getStart().getX()); |         start.setX(this.maze.getStart().x()); | ||||||
|         start.setY(this.maze.getStart().getY()); |         start.setY(this.maze.getStart().y()); | ||||||
|         result.setStart(start); |         result.setStart(start); | ||||||
|         final JsonCoordinates end = new JsonCoordinates(); |         final JsonCoordinates end = new JsonCoordinates(); | ||||||
|         end.setX(this.maze.getEnd().getX()); |         end.setX(this.maze.getEnd().x()); | ||||||
|         end.setY(this.maze.getEnd().getY()); |         end.setY(this.maze.getEnd().y()); | ||||||
|         result.setEnd(end); |         result.setEnd(end); | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -7,14 +7,14 @@ import ch.fritteli.maze.generator.renderer.Renderer; | ||||||
| import com.fasterxml.jackson.core.JsonProcessingException; | import com.fasterxml.jackson.core.JsonProcessingException; | ||||||
| import com.fasterxml.jackson.databind.ObjectMapper; | import com.fasterxml.jackson.databind.ObjectMapper; | ||||||
| import com.fasterxml.jackson.databind.SerializationFeature; | import com.fasterxml.jackson.databind.SerializationFeature; | ||||||
| import lombok.NonNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import java.util.ArrayList; | import java.util.ArrayList; | ||||||
| import java.util.List; | import java.util.List; | ||||||
| 
 | 
 | ||||||
| public class JsonRenderer implements Renderer<String> { | public class JsonRenderer implements Renderer<String> { | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     private final ObjectMapper objectMapper; |     private final ObjectMapper objectMapper; | ||||||
| 
 | 
 | ||||||
|     private JsonRenderer() { |     private JsonRenderer() { | ||||||
|  | @ -22,12 +22,12 @@ public class JsonRenderer implements Renderer<String> { | ||||||
|                 .enable(SerializationFeature.INDENT_OUTPUT); |                 .enable(SerializationFeature.INDENT_OUTPUT); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public static JsonRenderer newInstance() { |     public static JsonRenderer newInstance() { | ||||||
|         return new JsonRenderer(); |         return new JsonRenderer(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     private static JsonMaze createSingleCellMaze() { |     private static JsonMaze createSingleCellMaze() { | ||||||
|         // This is the only cell. |         // This is the only cell. | ||||||
|         final JsonCell cell = new JsonCell(); |         final JsonCell cell = new JsonCell(); | ||||||
|  | @ -37,7 +37,7 @@ public class JsonRenderer implements Renderer<String> { | ||||||
|         // Wrap that in a nested list. |         // Wrap that in a nested list. | ||||||
|         final List<List<JsonCell>> rows = new ArrayList<>(); |         final List<List<JsonCell>> rows = new ArrayList<>(); | ||||||
|         rows.add(new ArrayList<>()); |         rows.add(new ArrayList<>()); | ||||||
|         rows.get(0).add(cell); |         rows.getFirst().add(cell); | ||||||
|         // Wrap it all in an instance of JsonMaze. |         // Wrap it all in an instance of JsonMaze. | ||||||
|         final JsonMaze jsonMaze = new JsonMaze(); |         final JsonMaze jsonMaze = new JsonMaze(); | ||||||
|         jsonMaze.setId("0"); |         jsonMaze.setId("0"); | ||||||
|  | @ -45,8 +45,8 @@ public class JsonRenderer implements Renderer<String> { | ||||||
|         return jsonMaze; |         return jsonMaze; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     private String toString(@NonNull final JsonMaze jsonMaze) { |     private String toString(@NotNull final JsonMaze jsonMaze) { | ||||||
|         try { |         try { | ||||||
|             return this.objectMapper.writeValueAsString(jsonMaze); |             return this.objectMapper.writeValueAsString(jsonMaze); | ||||||
|         } catch (final JsonProcessingException e) { |         } catch (final JsonProcessingException e) { | ||||||
|  | @ -54,9 +54,9 @@ public class JsonRenderer implements Renderer<String> { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public String render(@NonNull final Maze maze) { |     public String render(@NotNull final Maze maze) { | ||||||
|         final JsonMaze jsonMaze; |         final JsonMaze jsonMaze; | ||||||
|         if (maze.getWidth() == 0 || maze.getHeight() == 0) { |         if (maze.getWidth() == 0 || maze.getHeight() == 0) { | ||||||
|             jsonMaze = createSingleCellMaze(); |             jsonMaze = createSingleCellMaze(); | ||||||
|  |  | ||||||
|  | @ -5,21 +5,22 @@ import ch.fritteli.maze.generator.renderer.Renderer; | ||||||
| import ch.fritteli.maze.generator.renderer.json.JsonRenderer; | import ch.fritteli.maze.generator.renderer.json.JsonRenderer; | ||||||
| import io.vavr.control.Option; | import io.vavr.control.Option; | ||||||
| import io.vavr.control.Try; | import io.vavr.control.Try; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
|  | 
 | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.nio.charset.StandardCharsets; | import java.nio.charset.StandardCharsets; | ||||||
| import java.nio.file.Files; | import java.nio.file.Files; | ||||||
| import java.nio.file.Path; | import java.nio.file.Path; | ||||||
| import java.util.NoSuchElementException; | import java.util.NoSuchElementException; | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.extern.slf4j.Slf4j; |  | ||||||
| 
 | 
 | ||||||
| @Slf4j | @Slf4j | ||||||
| public class JsonFileRenderer implements Renderer<Path> { | public class JsonFileRenderer implements Renderer<Path> { | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     private static final JsonRenderer JSON_RENDERER = JsonRenderer.newInstance(); |     private static final JsonRenderer JSON_RENDERER = JsonRenderer.newInstance(); | ||||||
|     @NonNull |     @NotNull | ||||||
|     private Option<Path> targetFile; |     private Option<Path> targetFile; | ||||||
| 
 | 
 | ||||||
|     private JsonFileRenderer() { |     private JsonFileRenderer() { | ||||||
|  | @ -29,7 +30,7 @@ public class JsonFileRenderer implements Renderer<Path> { | ||||||
|                 .toOption(); |                 .toOption(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public static JsonFileRenderer newInstance() { |     public static JsonFileRenderer newInstance() { | ||||||
|         return new JsonFileRenderer(); |         return new JsonFileRenderer(); | ||||||
|     } |     } | ||||||
|  | @ -40,15 +41,15 @@ public class JsonFileRenderer implements Renderer<Path> { | ||||||
|                 .exists(File::canWrite); |                 .exists(File::canWrite); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public JsonFileRenderer setTargetFile(@NonNull final Path targetFile) { |     public JsonFileRenderer setTargetFile(@NotNull final Path targetFile) { | ||||||
|         this.targetFile = Option.of(targetFile); |         this.targetFile = Option.of(targetFile); | ||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public Path render(@NonNull final Maze maze) { |     public Path render(@NotNull final Maze maze) { | ||||||
|         if (!this.isTargetFileDefinedAndWritable()) { |         if (!this.isTargetFileDefinedAndWritable()) { | ||||||
|             try { |             try { | ||||||
|                 Files.createFile(this.targetFile.get()); |                 Files.createFile(this.targetFile.get()); | ||||||
|  |  | ||||||
|  | @ -5,11 +5,6 @@ import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Position; | import ch.fritteli.maze.generator.model.Position; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import io.vavr.control.Option; | import io.vavr.control.Option; | ||||||
| import java.awt.BasicStroke; |  | ||||||
| import java.awt.Color; |  | ||||||
| import java.io.ByteArrayOutputStream; |  | ||||||
| import java.io.IOException; |  | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
| import lombok.Value; | import lombok.Value; | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
|  | @ -18,16 +13,21 @@ import org.apache.pdfbox.pdmodel.PDDocumentInformation; | ||||||
| import org.apache.pdfbox.pdmodel.PDPage; | import org.apache.pdfbox.pdmodel.PDPage; | ||||||
| import org.apache.pdfbox.pdmodel.PDPageContentStream; | import org.apache.pdfbox.pdmodel.PDPageContentStream; | ||||||
| import org.apache.pdfbox.pdmodel.common.PDRectangle; | import org.apache.pdfbox.pdmodel.common.PDRectangle; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| import org.jetbrains.annotations.Nullable; | import org.jetbrains.annotations.Nullable; | ||||||
| 
 | 
 | ||||||
|  | import java.awt.*; | ||||||
|  | import java.io.ByteArrayOutputStream; | ||||||
|  | import java.io.IOException; | ||||||
|  | 
 | ||||||
| @RequiredArgsConstructor | @RequiredArgsConstructor | ||||||
| @Slf4j | @Slf4j | ||||||
| class Generator { | class Generator { | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     private final Maze maze; |     private final Maze maze; | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public ByteArrayOutputStream generate() { |     public ByteArrayOutputStream generate() { | ||||||
|         final float pageWidth = this.maze.getWidth() * PDFRenderer.SCALE + 2 * PDFRenderer.MARGIN; |         final float pageWidth = this.maze.getWidth() * PDFRenderer.SCALE + 2 * PDFRenderer.MARGIN; | ||||||
|         final float pageHeight = this.maze.getHeight() * PDFRenderer.SCALE + 2 * PDFRenderer.MARGIN; |         final float pageHeight = this.maze.getHeight() * PDFRenderer.SCALE + 2 * PDFRenderer.MARGIN; | ||||||
|  | @ -41,7 +41,7 @@ class Generator { | ||||||
|         pdDocument.addPage(puzzlePage); |         pdDocument.addPage(puzzlePage); | ||||||
|         pdDocument.addPage(solutionPage); |         pdDocument.addPage(solutionPage); | ||||||
|         try (final PDPageContentStream puzzlePageContentStream = new PDPageContentStream(pdDocument, puzzlePage); |         try (final PDPageContentStream puzzlePageContentStream = new PDPageContentStream(pdDocument, puzzlePage); | ||||||
|                 final PDPageContentStream solutionPageContentStream = new PDPageContentStream(pdDocument, solutionPage)) { |              final PDPageContentStream solutionPageContentStream = new PDPageContentStream(pdDocument, solutionPage)) { | ||||||
|             setUpPageContentStream(puzzlePageContentStream); |             setUpPageContentStream(puzzlePageContentStream); | ||||||
|             setUpPageContentStream(solutionPageContentStream); |             setUpPageContentStream(solutionPageContentStream); | ||||||
|             this.drawHorizontalLines(puzzlePageContentStream, solutionPageContentStream); |             this.drawHorizontalLines(puzzlePageContentStream, solutionPageContentStream); | ||||||
|  | @ -60,7 +60,7 @@ class Generator { | ||||||
|         return output; |         return output; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void setUpPageContentStream(@NonNull final PDPageContentStream pageContentStream) throws IOException { |     private void setUpPageContentStream(@NotNull final PDPageContentStream pageContentStream) throws IOException { | ||||||
|         pageContentStream.setLineCapStyle(BasicStroke.CAP_ROUND); |         pageContentStream.setLineCapStyle(BasicStroke.CAP_ROUND); | ||||||
|         pageContentStream.setLineJoinStyle(BasicStroke.JOIN_ROUND); |         pageContentStream.setLineJoinStyle(BasicStroke.JOIN_ROUND); | ||||||
|         pageContentStream.setLineWidth(1.0f); |         pageContentStream.setLineWidth(1.0f); | ||||||
|  | @ -68,7 +68,7 @@ class Generator { | ||||||
|         pageContentStream.setNonStrokingColor(Color.BLACK); |         pageContentStream.setNonStrokingColor(Color.BLACK); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void drawHorizontalLines(@NonNull final PDPageContentStream... contentStreams) throws IOException { |     private void drawHorizontalLines(@NotNull final PDPageContentStream... contentStreams) throws IOException { | ||||||
|         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. |         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. | ||||||
|         Coordinate coordinate = new Coordinate(0f, 0f); |         Coordinate coordinate = new Coordinate(0f, 0f); | ||||||
|         // Draw the TOP borders of all tiles. |         // Draw the TOP borders of all tiles. | ||||||
|  | @ -136,7 +136,7 @@ class Generator { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void drawVerticalLines(@NonNull final PDPageContentStream... contentStreams) throws IOException { |     private void drawVerticalLines(@NotNull final PDPageContentStream... contentStreams) throws IOException { | ||||||
|         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. |         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. | ||||||
|         Coordinate coordinate = new Coordinate(0f, 0f); |         Coordinate coordinate = new Coordinate(0f, 0f); | ||||||
|         // Draw the LEFT borders of all tiles. |         // Draw the LEFT borders of all tiles. | ||||||
|  | @ -204,27 +204,27 @@ class Generator { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private void drawSolution(@NonNull final PDPageContentStream pageContentStream) throws IOException { |     private void drawSolution(@NotNull final PDPageContentStream pageContentStream) throws IOException { | ||||||
|         // Draw the solution in red |         // Draw the solution in red | ||||||
|         pageContentStream.setStrokingColor(Color.RED); |         pageContentStream.setStrokingColor(Color.RED); | ||||||
|         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. |         // PDF has the origin in the lower left corner. We want it in the upper left corner, hence some magic is required. | ||||||
|         final Position end = this.maze.getEnd(); |         final Position end = this.maze.getEnd(); | ||||||
|         Position currentPosition = this.maze.getStart(); |         Position currentPosition = this.maze.getStart(); | ||||||
|         Position previousPosition = null; |         Position previousPosition = null; | ||||||
|         SolutionCoordinate coordinate = new SolutionCoordinate(currentPosition.getX(), currentPosition.getY()); |         SolutionCoordinate coordinate = new SolutionCoordinate(currentPosition.x(), currentPosition.y()); | ||||||
|         pageContentStream.moveTo(coordinate.getX(), coordinate.getY()); |         pageContentStream.moveTo(coordinate.getX(), coordinate.getY()); | ||||||
|         do { |         do { | ||||||
|             Position newCurrent = this.findNextSolutionPosition(previousPosition, currentPosition); |             Position newCurrent = this.findNextSolutionPosition(previousPosition, currentPosition); | ||||||
|             previousPosition = currentPosition; |             previousPosition = currentPosition; | ||||||
|             currentPosition = newCurrent; |             currentPosition = newCurrent; | ||||||
|             coordinate = new SolutionCoordinate(currentPosition.getX(), currentPosition.getY()); |             coordinate = new SolutionCoordinate(currentPosition.x(), currentPosition.y()); | ||||||
|             pageContentStream.lineTo(coordinate.getX(), coordinate.getY()); |             pageContentStream.lineTo(coordinate.getX(), coordinate.getY()); | ||||||
|         } while (!currentPosition.equals(end)); |         } while (!currentPosition.equals(end)); | ||||||
|         pageContentStream.stroke(); |         pageContentStream.stroke(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     private Position findNextSolutionPosition(@Nullable final Position previousPosition, @NonNull final Position currentPosition) { |     private Position findNextSolutionPosition(@Nullable final Position previousPosition, @NotNull final Position currentPosition) { | ||||||
|         final Tile currentTile = this.maze.getTileAt(currentPosition).get(); |         final Tile currentTile = this.maze.getTileAt(currentPosition).get(); | ||||||
|         for (final Direction direction : Direction.values()) { |         for (final Direction direction : Direction.values()) { | ||||||
|             if (!currentTile.hasWallAt(direction)) { |             if (!currentTile.hasWallAt(direction)) { | ||||||
|  |  | ||||||
|  | @ -2,9 +2,9 @@ package ch.fritteli.maze.generator.renderer.pdf; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.renderer.Renderer; | import ch.fritteli.maze.generator.renderer.Renderer; | ||||||
| import java.io.ByteArrayOutputStream; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import lombok.NonNull; | import java.io.ByteArrayOutputStream; | ||||||
| 
 | 
 | ||||||
| public class PDFRenderer implements Renderer<ByteArrayOutputStream> { | public class PDFRenderer implements Renderer<ByteArrayOutputStream> { | ||||||
|     static final float MARGIN = 10; |     static final float MARGIN = 10; | ||||||
|  | @ -13,14 +13,14 @@ public class PDFRenderer implements Renderer<ByteArrayOutputStream> { | ||||||
|     private PDFRenderer() { |     private PDFRenderer() { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public static PDFRenderer newInstance() { |     public static PDFRenderer newInstance() { | ||||||
|         return new PDFRenderer(); |         return new PDFRenderer(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public ByteArrayOutputStream render(@NonNull final Maze maze) { |     public ByteArrayOutputStream render(@NotNull final Maze maze) { | ||||||
|         final Generator generator = new Generator(maze); |         final Generator generator = new Generator(maze); | ||||||
|         return generator.generate(); |         return generator.generate(); | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  | @ -5,21 +5,22 @@ import ch.fritteli.maze.generator.renderer.Renderer; | ||||||
| import ch.fritteli.maze.generator.renderer.pdf.PDFRenderer; | import ch.fritteli.maze.generator.renderer.pdf.PDFRenderer; | ||||||
| import io.vavr.control.Option; | import io.vavr.control.Option; | ||||||
| import io.vavr.control.Try; | import io.vavr.control.Try; | ||||||
|  | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
|  | 
 | ||||||
| import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.nio.file.Files; | import java.nio.file.Files; | ||||||
| import java.nio.file.Path; | import java.nio.file.Path; | ||||||
| import java.util.NoSuchElementException; | import java.util.NoSuchElementException; | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.extern.slf4j.Slf4j; |  | ||||||
| 
 | 
 | ||||||
| @Slf4j | @Slf4j | ||||||
| public class PDFFileRenderer implements Renderer<Path> { | public class PDFFileRenderer implements Renderer<Path> { | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     private static final PDFRenderer PDF_RENDERER = PDFRenderer.newInstance(); |     private static final PDFRenderer PDF_RENDERER = PDFRenderer.newInstance(); | ||||||
|     @NonNull |     @NotNull | ||||||
|     private Option<Path> targetFile; |     private Option<Path> targetFile; | ||||||
| 
 | 
 | ||||||
|     private PDFFileRenderer() { |     private PDFFileRenderer() { | ||||||
|  | @ -29,7 +30,7 @@ public class PDFFileRenderer implements Renderer<Path> { | ||||||
|                 .toOption(); |                 .toOption(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public static PDFFileRenderer newInstance() { |     public static PDFFileRenderer newInstance() { | ||||||
|         return new PDFFileRenderer(); |         return new PDFFileRenderer(); | ||||||
|     } |     } | ||||||
|  | @ -40,15 +41,15 @@ public class PDFFileRenderer implements Renderer<Path> { | ||||||
|                 .exists(File::canWrite); |                 .exists(File::canWrite); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public PDFFileRenderer setTargetFile(@NonNull final Path targetFile) { |     public PDFFileRenderer setTargetFile(@NotNull final Path targetFile) { | ||||||
|         this.targetFile = Option.of(targetFile); |         this.targetFile = Option.of(targetFile); | ||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public Path render(@NonNull final Maze maze) { |     public Path render(@NotNull final Maze maze) { | ||||||
|         if (!this.isTargetFileDefinedAndWritable()) { |         if (!this.isTargetFileDefinedAndWritable()) { | ||||||
|             try { |             try { | ||||||
|                 Files.createFile(this.targetFile.get()); |                 Files.createFile(this.targetFile.get()); | ||||||
|  |  | ||||||
|  | @ -5,12 +5,12 @@ import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import io.vavr.control.Option; | import io.vavr.control.Option; | ||||||
| import lombok.AccessLevel; | import lombok.AccessLevel; | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.RequiredArgsConstructor; | import lombok.RequiredArgsConstructor; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| @RequiredArgsConstructor(access = AccessLevel.PACKAGE) | @RequiredArgsConstructor(access = AccessLevel.PACKAGE) | ||||||
| class Generator { | class Generator { | ||||||
|     @NonNull |     @NotNull | ||||||
|     private final Maze maze; |     private final Maze maze; | ||||||
|     private final boolean renderSolution; |     private final boolean renderSolution; | ||||||
|     private int x = 0; |     private int x = 0; | ||||||
|  | @ -34,21 +34,12 @@ class Generator { | ||||||
|         final Option<Tile> rightTile = this.maze.getTileAt(this.x + 1, this.y); |         final Option<Tile> rightTile = this.maze.getTileAt(this.x + 1, this.y); | ||||||
|         final Option<Tile> bottomTile = this.maze.getTileAt(this.x, this.y + 1); |         final Option<Tile> bottomTile = this.maze.getTileAt(this.x, this.y + 1); | ||||||
|         final Option<Tile> leftTile = this.maze.getTileAt(this.x - 1, this.y); |         final Option<Tile> leftTile = this.maze.getTileAt(this.x - 1, this.y); | ||||||
|         final String s; |         final String s = switch (this.line) { | ||||||
|         switch (this.line) { |             case 0 -> this.renderTopLine(currentTile, leftTile, topTile); | ||||||
|             case 0: |             case 1 -> this.renderCenterLine(currentTile, topTile, rightTile, bottomTile, leftTile); | ||||||
|                 s = this.renderTopLine(currentTile, leftTile, topTile); |             case 2 -> this.renderBottomLine(currentTile, leftTile); | ||||||
|                 break; |             default -> ""; | ||||||
|             case 1: |         }; | ||||||
|                 s = this.renderCenterLine(currentTile, topTile, rightTile, bottomTile, leftTile); |  | ||||||
|                 break; |  | ||||||
|             case 2: |  | ||||||
|                 s = this.renderBottomLine(currentTile, leftTile); |  | ||||||
|                 break; |  | ||||||
|             default: |  | ||||||
|                 s = ""; |  | ||||||
|                 break; |  | ||||||
|         } |  | ||||||
|         this.prepareNextStep(); |         this.prepareNextStep(); | ||||||
|         return s; |         return s; | ||||||
|     } |     } | ||||||
|  | @ -76,7 +67,7 @@ class Generator { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private String renderTopLine(@NonNull final Tile currentTile, @NonNull final Option<Tile> leftTile, @NonNull final Option<Tile> topTile) { |     private String renderTopLine(@NotNull final Tile currentTile, @NotNull final Option<Tile> leftTile, @NotNull final Option<Tile> topTile) { | ||||||
|         final CharDefinition charDef1 = new CharDefinition(); |         final CharDefinition charDef1 = new CharDefinition(); | ||||||
|         final CharDefinition charDef2 = new CharDefinition(); |         final CharDefinition charDef2 = new CharDefinition(); | ||||||
|         final CharDefinition charDef3 = new CharDefinition(); |         final CharDefinition charDef3 = new CharDefinition(); | ||||||
|  | @ -112,11 +103,11 @@ class Generator { | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private String renderCenterLine(@NonNull final Tile currentTile, |     private String renderCenterLine(@NotNull final Tile currentTile, | ||||||
|                                     @NonNull final Option<Tile> topTile, |                                     @NotNull final Option<Tile> topTile, | ||||||
|                                     @NonNull final Option<Tile> rightTile, |                                     @NotNull final Option<Tile> rightTile, | ||||||
|                                     @NonNull final Option<Tile> bottomTile, |                                     @NotNull final Option<Tile> bottomTile, | ||||||
|                                     @NonNull final Option<Tile> leftTile) { |                                     @NotNull final Option<Tile> leftTile) { | ||||||
|         final CharDefinition charDef1 = new CharDefinition(); |         final CharDefinition charDef1 = new CharDefinition(); | ||||||
|         final CharDefinition charDef2 = new CharDefinition(); |         final CharDefinition charDef2 = new CharDefinition(); | ||||||
|         final CharDefinition charDef3 = new CharDefinition(); |         final CharDefinition charDef3 = new CharDefinition(); | ||||||
|  | @ -160,7 +151,7 @@ class Generator { | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private String renderBottomLine(@NonNull final Tile currentTile, @NonNull final Option<Tile> leftTile) { |     private String renderBottomLine(@NotNull final Tile currentTile, @NotNull final Option<Tile> leftTile) { | ||||||
|         String result; |         String result; | ||||||
|         final CharDefinition charDef1 = new CharDefinition(); |         final CharDefinition charDef1 = new CharDefinition(); | ||||||
|         final CharDefinition charDef2 = new CharDefinition(); |         final CharDefinition charDef2 = new CharDefinition(); | ||||||
|  | @ -193,15 +184,15 @@ class Generator { | ||||||
|         return result; |         return result; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean hasWallAt(@NonNull final Option<Tile> tile, @NonNull final Direction direction) { |     private boolean hasWallAt(@NotNull final Option<Tile> tile, @NotNull final Direction direction) { | ||||||
|         return tile.map(t -> t.hasWallAt(direction)).getOrElse(false); |         return tile.map(t -> t.hasWallAt(direction)).getOrElse(false); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean isSolution(@NonNull final Tile tile) { |     private boolean isSolution(@NotNull final Tile tile) { | ||||||
|         return this.renderSolution && tile != null && tile.isSolution(); |         return this.renderSolution && tile.isSolution(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean isSolution(@NonNull final Option<Tile> tile) { |     private boolean isSolution(@NotNull final Option<Tile> tile) { | ||||||
|         return this.renderSolution && tile.map(Tile::isSolution).getOrElse(false); |         return this.renderSolution && tile.map(Tile::isSolution).getOrElse(false); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -2,7 +2,7 @@ package ch.fritteli.maze.generator.renderer.text; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.renderer.Renderer; | import ch.fritteli.maze.generator.renderer.Renderer; | ||||||
| import lombok.NonNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| public class TextRenderer implements Renderer<String> { | public class TextRenderer implements Renderer<String> { | ||||||
|     private boolean renderSolution; |     private boolean renderSolution; | ||||||
|  | @ -11,20 +11,20 @@ public class TextRenderer implements Renderer<String> { | ||||||
|         this.renderSolution = false; |         this.renderSolution = false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public static TextRenderer newInstance() { |     public static TextRenderer newInstance() { | ||||||
|         return new TextRenderer(); |         return new TextRenderer(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public TextRenderer setRenderSolution(final boolean renderSolution) { |     public TextRenderer setRenderSolution(final boolean renderSolution) { | ||||||
|         this.renderSolution = renderSolution; |         this.renderSolution = renderSolution; | ||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public String render(@NonNull final Maze maze) { |     public String render(@NotNull final Maze maze) { | ||||||
|         if (maze.getWidth() == 0 || maze.getHeight() == 0) { |         if (maze.getWidth() == 0 || maze.getHeight() == 0) { | ||||||
|             return ""; |             return ""; | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -6,23 +6,22 @@ import ch.fritteli.maze.generator.renderer.text.TextRenderer; | ||||||
| import io.vavr.collection.List; | import io.vavr.collection.List; | ||||||
| import io.vavr.control.Option; | import io.vavr.control.Option; | ||||||
| import io.vavr.control.Try; | import io.vavr.control.Try; | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.extern.slf4j.Slf4j; | import lombok.extern.slf4j.Slf4j; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import java.io.File; | import java.io.File; | ||||||
| import java.io.IOException; | import java.io.IOException; | ||||||
| import java.nio.charset.StandardCharsets; |  | ||||||
| import java.nio.file.Files; | import java.nio.file.Files; | ||||||
| import java.nio.file.Path; | import java.nio.file.Path; | ||||||
| import java.util.NoSuchElementException; | import java.util.NoSuchElementException; | ||||||
| 
 | 
 | ||||||
| @Slf4j | @Slf4j | ||||||
| public class TextFileRenderer implements Renderer<List<Path>> { | public class TextFileRenderer implements Renderer<List<Path>> { | ||||||
|     @NonNull |     @NotNull | ||||||
|     private static final TextRenderer TEXT_RENDERER = TextRenderer.newInstance(); |     private static final TextRenderer TEXT_RENDERER = TextRenderer.newInstance(); | ||||||
|     @NonNull |     @NotNull | ||||||
|     private Option<Path> targetMazeFile; |     private Option<Path> targetMazeFile; | ||||||
|     @NonNull |     @NotNull | ||||||
|     private Option<Path> targetSolutionFile; |     private Option<Path> targetSolutionFile; | ||||||
| 
 | 
 | ||||||
|     private TextFileRenderer() { |     private TextFileRenderer() { | ||||||
|  | @ -42,7 +41,7 @@ public class TextFileRenderer implements Renderer<List<Path>> { | ||||||
|                 .toOption(); |                 .toOption(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public static TextFileRenderer newInstance() { |     public static TextFileRenderer newInstance() { | ||||||
|         return new TextFileRenderer(); |         return new TextFileRenderer(); | ||||||
|     } |     } | ||||||
|  | @ -59,21 +58,21 @@ public class TextFileRenderer implements Renderer<List<Path>> { | ||||||
|                 .exists(File::canWrite); |                 .exists(File::canWrite); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public TextFileRenderer setTargetMazeFile(@NonNull final Path targetMazeFile) { |     public TextFileRenderer setTargetMazeFile(@NotNull final Path targetMazeFile) { | ||||||
|         this.targetMazeFile = Option.of(targetMazeFile); |         this.targetMazeFile = Option.of(targetMazeFile); | ||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public TextFileRenderer setTargetSolutionFile(@NonNull final Path targetSolutionFile) { |     public TextFileRenderer setTargetSolutionFile(@NotNull final Path targetSolutionFile) { | ||||||
|         this.targetSolutionFile = Option.of(targetSolutionFile); |         this.targetSolutionFile = Option.of(targetSolutionFile); | ||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public List<Path> render(@NonNull final Maze maze) { |     public List<Path> render(@NotNull final Maze maze) { | ||||||
|         if (!this.isTargetMazeFileDefinedAndWritable()) { |         if (!this.isTargetMazeFileDefinedAndWritable()) { | ||||||
|             try { |             try { | ||||||
|                 Files.createFile(this.targetMazeFile.get()); |                 Files.createFile(this.targetMazeFile.get()); | ||||||
|  | @ -98,12 +97,12 @@ public class TextFileRenderer implements Renderer<List<Path>> { | ||||||
|         final Path targetMazeFile = this.targetMazeFile.get(); |         final Path targetMazeFile = this.targetMazeFile.get(); | ||||||
|         final Path targetSolutionFile = this.targetSolutionFile.get(); |         final Path targetSolutionFile = this.targetSolutionFile.get(); | ||||||
|         try { |         try { | ||||||
|             Files.write(targetMazeFile, text.getBytes(StandardCharsets.UTF_8)); |             Files.writeString(targetMazeFile, text); | ||||||
|         } catch (IOException e) { |         } catch (IOException e) { | ||||||
|             log.error("Failed writing to file " + targetMazeFile.normalize(), e); |             log.error("Failed writing to file " + targetMazeFile.normalize(), e); | ||||||
|         } |         } | ||||||
|         try { |         try { | ||||||
|             Files.write(targetSolutionFile, solution.getBytes(StandardCharsets.UTF_8)); |             Files.writeString(targetSolutionFile, solution); | ||||||
|         } catch (IOException e) { |         } catch (IOException e) { | ||||||
|             log.error("Failed writing to file " + targetSolutionFile.normalize()); |             log.error("Failed writing to file " + targetSolutionFile.normalize()); | ||||||
|         } |         } | ||||||
|  |  | ||||||
|  | @ -1,18 +1,19 @@ | ||||||
| package ch.fritteli.maze.generator.serialization; | package ch.fritteli.maze.generator.serialization; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
|  | 
 | ||||||
| import java.io.ByteArrayInputStream; | import java.io.ByteArrayInputStream; | ||||||
| import lombok.NonNull; |  | ||||||
| 
 | 
 | ||||||
| public abstract class AbstractMazeInputStream extends ByteArrayInputStream { | public abstract class AbstractMazeInputStream extends ByteArrayInputStream { | ||||||
| 
 | 
 | ||||||
|     public AbstractMazeInputStream(@NonNull final byte[] buf) { |     public AbstractMazeInputStream(@NotNull final byte[] buf) { | ||||||
|         super(buf); |         super(buf); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public abstract void checkHeader(); |     public abstract void checkHeader(); | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     public abstract Maze readMazeData(); |     public abstract Maze readMazeData(); | ||||||
| 
 | 
 | ||||||
|     public byte readByte() { |     public byte readByte() { | ||||||
|  |  | ||||||
|  | @ -1,14 +1,15 @@ | ||||||
| package ch.fritteli.maze.generator.serialization; | package ch.fritteli.maze.generator.serialization; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
|  | 
 | ||||||
| import java.io.ByteArrayOutputStream; | import java.io.ByteArrayOutputStream; | ||||||
| import lombok.NonNull; |  | ||||||
| 
 | 
 | ||||||
| public abstract class AbstractMazeOutputStream extends ByteArrayOutputStream { | public abstract class AbstractMazeOutputStream extends ByteArrayOutputStream { | ||||||
| 
 | 
 | ||||||
|     public abstract void writeHeader(); |     public abstract void writeHeader(); | ||||||
| 
 | 
 | ||||||
|     public abstract void writeMazeData(@NonNull final Maze maze); |     public abstract void writeMazeData(@NotNull final Maze maze); | ||||||
| 
 | 
 | ||||||
|     public void writeByte(final byte value) { |     public void writeByte(final byte value) { | ||||||
|         this.write(value); |         this.write(value); | ||||||
|  |  | ||||||
|  | @ -3,11 +3,11 @@ package ch.fritteli.maze.generator.serialization.v1; | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream; | import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream; | ||||||
| import lombok.NonNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| public class MazeInputStreamV1 extends AbstractMazeInputStream { | public class MazeInputStreamV1 extends AbstractMazeInputStream { | ||||||
| 
 | 
 | ||||||
|     public MazeInputStreamV1(@NonNull final byte[] buf) { |     public MazeInputStreamV1(@NotNull final byte[] buf) { | ||||||
|         super(buf); |         super(buf); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -27,7 +27,7 @@ public class MazeInputStreamV1 extends AbstractMazeInputStream { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public Maze readMazeData() { |     public Maze readMazeData() { | ||||||
|         final long randomSeed = this.readLong(); |         final long randomSeed = this.readLong(); | ||||||
|  |  | ||||||
|  | @ -3,7 +3,7 @@ package ch.fritteli.maze.generator.serialization.v1; | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream; | import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream; | ||||||
| import lombok.NonNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| public class MazeOutputStreamV1 extends AbstractMazeOutputStream { | public class MazeOutputStreamV1 extends AbstractMazeOutputStream { | ||||||
| 
 | 
 | ||||||
|  | @ -15,7 +15,7 @@ public class MazeOutputStreamV1 extends AbstractMazeOutputStream { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void writeMazeData(@NonNull final Maze maze) { |     public void writeMazeData(@NotNull final Maze maze) { | ||||||
|         final long randomSeed = maze.getRandomSeed(); |         final long randomSeed = maze.getRandomSeed(); | ||||||
|         final int width = maze.getWidth(); |         final int width = maze.getWidth(); | ||||||
|         final int height = maze.getHeight(); |         final int height = maze.getHeight(); | ||||||
|  |  | ||||||
|  | @ -3,8 +3,8 @@ package ch.fritteli.maze.generator.serialization.v1; | ||||||
| import ch.fritteli.maze.generator.model.Direction; | import ch.fritteli.maze.generator.model.Direction; | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.experimental.UtilityClass; | import lombok.experimental.UtilityClass; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import java.lang.reflect.Constructor; | import java.lang.reflect.Constructor; | ||||||
| import java.lang.reflect.InvocationTargetException; | import java.lang.reflect.InvocationTargetException; | ||||||
|  | @ -62,8 +62,8 @@ public class SerializerDeserializerV1 { | ||||||
|      * @param maze The {@link Maze} to be serialized. |      * @param maze The {@link Maze} to be serialized. | ||||||
|      * @return The resulting byte array. |      * @return The resulting byte array. | ||||||
|      */ |      */ | ||||||
|     @NonNull |     @NotNull | ||||||
|     public byte[] serialize(@NonNull final Maze maze) { |     public byte[] serialize(@NotNull final Maze maze) { | ||||||
|         final MazeOutputStreamV1 stream = new MazeOutputStreamV1(); |         final MazeOutputStreamV1 stream = new MazeOutputStreamV1(); | ||||||
|         stream.writeHeader(); |         stream.writeHeader(); | ||||||
|         stream.writeMazeData(maze); |         stream.writeMazeData(maze); | ||||||
|  | @ -76,38 +76,38 @@ public class SerializerDeserializerV1 { | ||||||
|      * @param bytes The byte array to be deserialized. |      * @param bytes The byte array to be deserialized. | ||||||
|      * @return An instance of {@link Maze}. |      * @return An instance of {@link Maze}. | ||||||
|      */ |      */ | ||||||
|     @NonNull |     @NotNull | ||||||
|     public Maze deserialize(@NonNull final byte[] bytes) { |     public Maze deserialize(@NotNull final byte[] bytes) { | ||||||
|         final MazeInputStreamV1 stream = new MazeInputStreamV1(bytes); |         final MazeInputStreamV1 stream = new MazeInputStreamV1(bytes); | ||||||
|         stream.checkHeader(); |         stream.checkHeader(); | ||||||
|         return stream.readMazeData(); |         return stream.readMazeData(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     Maze createMaze(@NonNull final Tile[][] field, final int width, final int height, final long randomSeed) { |     Maze createMaze(@NotNull final Tile[][] field, final int width, final int height, final long randomSeed) { | ||||||
|         try { |         try { | ||||||
|             final Constructor<Maze> constructor = Maze.class.getDeclaredConstructor(Tile[][].class, Integer.TYPE, Integer.TYPE, Long.TYPE); |             final Constructor<Maze> constructor = Maze.class.getDeclaredConstructor(Tile[][].class, Integer.TYPE, Integer.TYPE, Long.TYPE); | ||||||
|             constructor.setAccessible(true); |             constructor.setAccessible(true); | ||||||
|             return constructor.newInstance(field, width, height, randomSeed); |             return constructor.newInstance(field, width, height, randomSeed); | ||||||
|         } catch (@NonNull final NoSuchMethodException | IllegalAccessException | InstantiationException | |         } catch (@NotNull final NoSuchMethodException | IllegalAccessException | InstantiationException | | ||||||
|                                 InvocationTargetException e) { |                                 InvocationTargetException e) { | ||||||
|             throw new RuntimeException("Can not deserialize Maze from maze data.", e); |             throw new RuntimeException("Can not deserialize Maze from maze data.", e); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     private Tile createTile(@NonNull final EnumSet<Direction> walls, boolean solution) { |     private Tile createTile(@NotNull final EnumSet<Direction> walls, boolean solution) { | ||||||
|         try { |         try { | ||||||
|             final Constructor<Tile> constructor = Tile.class.getDeclaredConstructor(EnumSet.class, Boolean.TYPE); |             final Constructor<Tile> constructor = Tile.class.getDeclaredConstructor(EnumSet.class, Boolean.TYPE); | ||||||
|             constructor.setAccessible(true); |             constructor.setAccessible(true); | ||||||
|             return constructor.newInstance(walls, solution); |             return constructor.newInstance(walls, solution); | ||||||
|         } catch (@NonNull final NoSuchMethodException | InstantiationException | IllegalAccessException | |         } catch (@NotNull final NoSuchMethodException | InstantiationException | IllegalAccessException | | ||||||
|                                 InvocationTargetException e) { |                                 InvocationTargetException e) { | ||||||
|             throw new RuntimeException("Can not deserialize Tile from maze data.", e); |             throw new RuntimeException("Can not deserialize Tile from maze data.", e); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     byte getBitmaskForTile(@NonNull final Tile tile) { |     byte getBitmaskForTile(@NotNull final Tile tile) { | ||||||
|         byte bitmask = 0; |         byte bitmask = 0; | ||||||
|         if (tile.hasWallAt(Direction.TOP)) { |         if (tile.hasWallAt(Direction.TOP)) { | ||||||
|             bitmask |= TOP_BIT; |             bitmask |= TOP_BIT; | ||||||
|  | @ -127,7 +127,7 @@ public class SerializerDeserializerV1 { | ||||||
|         return bitmask; |         return bitmask; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     Tile getTileForBitmask(final byte bitmask) { |     Tile getTileForBitmask(final byte bitmask) { | ||||||
|         final EnumSet<Direction> walls = EnumSet.noneOf(Direction.class); |         final EnumSet<Direction> walls = EnumSet.noneOf(Direction.class); | ||||||
|         if ((bitmask & TOP_BIT) == TOP_BIT) { |         if ((bitmask & TOP_BIT) == TOP_BIT) { | ||||||
|  |  | ||||||
|  | @ -4,11 +4,11 @@ import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Position; | import ch.fritteli.maze.generator.model.Position; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream; | import ch.fritteli.maze.generator.serialization.AbstractMazeInputStream; | ||||||
| import lombok.NonNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| public class MazeInputStreamV2 extends AbstractMazeInputStream { | public class MazeInputStreamV2 extends AbstractMazeInputStream { | ||||||
| 
 | 
 | ||||||
|     public MazeInputStreamV2(@NonNull final byte[] buf) { |     public MazeInputStreamV2(@NotNull final byte[] buf) { | ||||||
|         super(buf); |         super(buf); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -31,7 +31,7 @@ public class MazeInputStreamV2 extends AbstractMazeInputStream { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     @Override |     @Override | ||||||
|     public Maze readMazeData() { |     public Maze readMazeData() { | ||||||
|         // 03..06  width (int) |         // 03..06  width (int) | ||||||
|  |  | ||||||
|  | @ -4,7 +4,7 @@ import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Position; | import ch.fritteli.maze.generator.model.Position; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream; | import ch.fritteli.maze.generator.serialization.AbstractMazeOutputStream; | ||||||
| import lombok.NonNull; | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| public class MazeOutputStreamV2 extends AbstractMazeOutputStream { | public class MazeOutputStreamV2 extends AbstractMazeOutputStream { | ||||||
| 
 | 
 | ||||||
|  | @ -19,7 +19,7 @@ public class MazeOutputStreamV2 extends AbstractMazeOutputStream { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Override |     @Override | ||||||
|     public void writeMazeData(@NonNull final Maze maze) { |     public void writeMazeData(@NotNull final Maze maze) { | ||||||
|         // 03..06  width (int) |         // 03..06  width (int) | ||||||
|         // 07..10  height (int) |         // 07..10  height (int) | ||||||
|         // 11..14  start-x (int) |         // 11..14  start-x (int) | ||||||
|  | @ -35,10 +35,10 @@ public class MazeOutputStreamV2 extends AbstractMazeOutputStream { | ||||||
|         final Position end = maze.getEnd(); |         final Position end = maze.getEnd(); | ||||||
|         this.writeInt(width); |         this.writeInt(width); | ||||||
|         this.writeInt(height); |         this.writeInt(height); | ||||||
|         this.writeInt(start.getX()); |         this.writeInt(start.x()); | ||||||
|         this.writeInt(start.getY()); |         this.writeInt(start.y()); | ||||||
|         this.writeInt(end.getX()); |         this.writeInt(end.x()); | ||||||
|         this.writeInt(end.getY()); |         this.writeInt(end.y()); | ||||||
|         this.writeLong(randomSeed); |         this.writeLong(randomSeed); | ||||||
| 
 | 
 | ||||||
|         for (int y = 0; y < height; y++) { |         for (int y = 0; y < height; y++) { | ||||||
|  |  | ||||||
|  | @ -4,8 +4,8 @@ import ch.fritteli.maze.generator.model.Direction; | ||||||
| import ch.fritteli.maze.generator.model.Maze; | import ch.fritteli.maze.generator.model.Maze; | ||||||
| import ch.fritteli.maze.generator.model.Position; | import ch.fritteli.maze.generator.model.Position; | ||||||
| import ch.fritteli.maze.generator.model.Tile; | import ch.fritteli.maze.generator.model.Tile; | ||||||
| import lombok.NonNull; |  | ||||||
| import lombok.experimental.UtilityClass; | import lombok.experimental.UtilityClass; | ||||||
|  | import org.jetbrains.annotations.NotNull; | ||||||
| 
 | 
 | ||||||
| import java.lang.reflect.Constructor; | import java.lang.reflect.Constructor; | ||||||
| import java.lang.reflect.InvocationTargetException; | import java.lang.reflect.InvocationTargetException; | ||||||
|  | @ -67,8 +67,8 @@ public class SerializerDeserializerV2 { | ||||||
|      * @param maze The {@link Maze} to be serialized. |      * @param maze The {@link Maze} to be serialized. | ||||||
|      * @return The resulting byte array. |      * @return The resulting byte array. | ||||||
|      */ |      */ | ||||||
|     @NonNull |     @NotNull | ||||||
|     public byte[] serialize(@NonNull final Maze maze) { |     public byte[] serialize(@NotNull final Maze maze) { | ||||||
|         final MazeOutputStreamV2 stream = new MazeOutputStreamV2(); |         final MazeOutputStreamV2 stream = new MazeOutputStreamV2(); | ||||||
|         stream.writeHeader(); |         stream.writeHeader(); | ||||||
|         stream.writeMazeData(maze); |         stream.writeMazeData(maze); | ||||||
|  | @ -81,38 +81,38 @@ public class SerializerDeserializerV2 { | ||||||
|      * @param bytes The byte array to be deserialized. |      * @param bytes The byte array to be deserialized. | ||||||
|      * @return An instance of {@link Maze}. |      * @return An instance of {@link Maze}. | ||||||
|      */ |      */ | ||||||
|     @NonNull |     @NotNull | ||||||
|     public Maze deserialize(@NonNull final byte[] bytes) { |     public Maze deserialize(@NotNull final byte[] bytes) { | ||||||
|         final MazeInputStreamV2 stream = new MazeInputStreamV2(bytes); |         final MazeInputStreamV2 stream = new MazeInputStreamV2(bytes); | ||||||
|         stream.checkHeader(); |         stream.checkHeader(); | ||||||
|         return stream.readMazeData(); |         return stream.readMazeData(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     Maze createMaze(@NonNull final Tile[][] field, final int width, final int height, @NonNull final Position start, @NonNull final Position end, final long randomSeed) { |     Maze createMaze(@NotNull final Tile[][] field, final int width, final int height, @NotNull final Position start, @NotNull final Position end, final long randomSeed) { | ||||||
|         try { |         try { | ||||||
|             final Constructor<Maze> constructor = Maze.class.getDeclaredConstructor(Tile[][].class, Integer.TYPE, Integer.TYPE, Position.class, Position.class, Long.TYPE); |             final Constructor<Maze> constructor = Maze.class.getDeclaredConstructor(Tile[][].class, Integer.TYPE, Integer.TYPE, Position.class, Position.class, Long.TYPE); | ||||||
|             constructor.setAccessible(true); |             constructor.setAccessible(true); | ||||||
|             return constructor.newInstance(field, width, height, start, end, randomSeed); |             return constructor.newInstance(field, width, height, start, end, randomSeed); | ||||||
|         } catch (@NonNull final NoSuchMethodException | IllegalAccessException | InstantiationException | |         } catch (@NotNull final NoSuchMethodException | IllegalAccessException | InstantiationException | | ||||||
|                                 InvocationTargetException e) { |                                 InvocationTargetException e) { | ||||||
|             throw new RuntimeException("Can not deserialize Maze from maze data.", e); |             throw new RuntimeException("Can not deserialize Maze from maze data.", e); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     private Tile createTile(@NonNull final EnumSet<Direction> walls, boolean solution) { |     private Tile createTile(@NotNull final EnumSet<Direction> walls, boolean solution) { | ||||||
|         try { |         try { | ||||||
|             final Constructor<Tile> constructor = Tile.class.getDeclaredConstructor(EnumSet.class, Boolean.TYPE); |             final Constructor<Tile> constructor = Tile.class.getDeclaredConstructor(EnumSet.class, Boolean.TYPE); | ||||||
|             constructor.setAccessible(true); |             constructor.setAccessible(true); | ||||||
|             return constructor.newInstance(walls, solution); |             return constructor.newInstance(walls, solution); | ||||||
|         } catch (@NonNull final NoSuchMethodException | InstantiationException | IllegalAccessException | |         } catch (@NotNull final NoSuchMethodException | InstantiationException | IllegalAccessException | | ||||||
|                                 InvocationTargetException e) { |                                 InvocationTargetException e) { | ||||||
|             throw new RuntimeException("Can not deserialize Tile from maze data.", e); |             throw new RuntimeException("Can not deserialize Tile from maze data.", e); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     byte getBitmaskForTile(@NonNull final Tile tile) { |     byte getBitmaskForTile(@NotNull final Tile tile) { | ||||||
|         byte bitmask = 0; |         byte bitmask = 0; | ||||||
|         if (tile.hasWallAt(Direction.TOP)) { |         if (tile.hasWallAt(Direction.TOP)) { | ||||||
|             bitmask |= TOP_BIT; |             bitmask |= TOP_BIT; | ||||||
|  | @ -132,7 +132,7 @@ public class SerializerDeserializerV2 { | ||||||
|         return bitmask; |         return bitmask; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NotNull | ||||||
|     Tile getTileForBitmask(final byte bitmask) { |     Tile getTileForBitmask(final byte bitmask) { | ||||||
|         final EnumSet<Direction> walls = EnumSet.noneOf(Direction.class); |         final EnumSet<Direction> walls = EnumSet.noneOf(Direction.class); | ||||||
|         if ((bitmask & TOP_BIT) == TOP_BIT) { |         if ((bitmask & TOP_BIT) == TOP_BIT) { | ||||||
|  |  | ||||||
|  | @ -1,13 +1,12 @@ | ||||||
| package ch.fritteli.maze.generator.model; | package ch.fritteli.maze.generator.model; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.maze.generator.model.Direction; |  | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| 
 | 
 | ||||||
| import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||||
| 
 | 
 | ||||||
| class DirectionTest { | class DirectionTest { | ||||||
|     @Test |     @Test | ||||||
|     void invert() { |     void shouldInvertTheDirection() { | ||||||
|         assertThat(Direction.TOP.invert()).isEqualTo(Direction.BOTTOM); |         assertThat(Direction.TOP.invert()).isEqualTo(Direction.BOTTOM); | ||||||
|         assertThat(Direction.RIGHT.invert()).isEqualTo(Direction.LEFT); |         assertThat(Direction.RIGHT.invert()).isEqualTo(Direction.LEFT); | ||||||
|         assertThat(Direction.BOTTOM.invert()).isEqualTo(Direction.TOP); |         assertThat(Direction.BOTTOM.invert()).isEqualTo(Direction.TOP); | ||||||
|  |  | ||||||
|  | @ -7,14 +7,24 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; | ||||||
| 
 | 
 | ||||||
| class MazeTest { | class MazeTest { | ||||||
|     @Test |     @Test | ||||||
|     void testConstruct() { |     void shouldNotAccept0AsWidthOrHeight() { | ||||||
|         // act / assert on simple cases |         // act / assert | ||||||
|         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> new Maze(0, 0)) |         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> new Maze(0, 0)) | ||||||
|                 .withMessage("width and height must be >1"); |                 .withMessage("width and height must be >1"); | ||||||
|         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> new Maze(0, 0, 0)) |         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> new Maze(0, 0, 0)) | ||||||
|                 .withMessage("width and height must be >1"); |                 .withMessage("width and height must be >1"); | ||||||
|  |         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> new Maze(0, 5)) | ||||||
|  |                 .withMessage("width and height must be >1"); | ||||||
|  |         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> new Maze(0, 5, 0)) | ||||||
|  |                 .withMessage("width and height must be >1"); | ||||||
|  |         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> new Maze(5, 0)) | ||||||
|  |                 .withMessage("width and height must be >1"); | ||||||
|  |         assertThatExceptionOfType(IllegalArgumentException.class).isThrownBy(() -> new Maze(5, 0, 0)) | ||||||
|  |                 .withMessage("width and height must be >1"); | ||||||
|  |     } | ||||||
| 
 | 
 | ||||||
|         // now for the real work: |     @Test | ||||||
|  |     void testConstruct() { | ||||||
|         // arrange |         // arrange | ||||||
|         final Maze sut = new Maze(2, 3, 5); |         final Maze sut = new Maze(2, 3, 5); | ||||||
| 
 | 
 | ||||||
|  | @ -23,7 +33,9 @@ class MazeTest { | ||||||
|                 .returns(2, Maze::getWidth) |                 .returns(2, Maze::getWidth) | ||||||
|                 .returns(3, Maze::getHeight) |                 .returns(3, Maze::getHeight) | ||||||
|                 .returns(5L, Maze::getRandomSeed) |                 .returns(5L, Maze::getRandomSeed) | ||||||
|                 .returns(new Position(0, 0), Maze::getStart) |                 .satisfies( | ||||||
|                 .returns(new Position(1, 2), Maze::getEnd); |                         maze -> assertThat(maze.getStart()).isEqualTo(new Position(0, 0)), | ||||||
|  |                         maze -> assertThat(maze.getEnd()).isEqualTo(new Position(1, 2)) | ||||||
|  |                 ); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,14 +1,12 @@ | ||||||
| package ch.fritteli.maze.generator.model; | package ch.fritteli.maze.generator.model; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.maze.generator.model.Direction; |  | ||||||
| import ch.fritteli.maze.generator.model.Position; |  | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| 
 | 
 | ||||||
| import static org.assertj.core.api.Assertions.assertThat; | import static org.assertj.core.api.Assertions.assertThat; | ||||||
| 
 | 
 | ||||||
| class PositionTest { | class PositionTest { | ||||||
|     @Test |     @Test | ||||||
|     void move() { |     void shouldMoveToCorrectNeighborPosition() { | ||||||
|         // arrange |         // arrange | ||||||
|         final Position sut = new Position(0, 0); |         final Position sut = new Position(0, 0); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,7 +1,5 @@ | ||||||
| package ch.fritteli.maze.generator.model; | package ch.fritteli.maze.generator.model; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.maze.generator.model.Direction; |  | ||||||
| import ch.fritteli.maze.generator.model.Tile; |  | ||||||
| import io.vavr.control.Option; | import io.vavr.control.Option; | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| 
 | 
 | ||||||
|  | @ -11,21 +9,20 @@ import static org.assertj.core.api.Assertions.assertThat; | ||||||
| 
 | 
 | ||||||
| class TileTest { | class TileTest { | ||||||
|     @Test |     @Test | ||||||
|     void testConstruct() { |     void shouldConstructATileWithDefaultValues() { | ||||||
|         // arrange / act |         // arrange / act | ||||||
|         final Tile sut = new Tile(); |         final Tile sut = new Tile(); | ||||||
| 
 | 
 | ||||||
|         //assert |         //assert | ||||||
|         assertThat(sut) |         assertThat(sut.hasWallAt(Direction.TOP)).isTrue(); | ||||||
|                 .returns(true, v -> v.hasWallAt(Direction.TOP)) |         assertThat(sut.hasWallAt(Direction.RIGHT)).isTrue(); | ||||||
|                 .returns(true, v -> v.hasWallAt(Direction.RIGHT)) |         assertThat(sut.hasWallAt(Direction.BOTTOM)).isTrue(); | ||||||
|                 .returns(true, v -> v.hasWallAt(Direction.BOTTOM)) |         assertThat(sut.hasWallAt(Direction.LEFT)).isTrue(); | ||||||
|                 .returns(true, v -> v.hasWallAt(Direction.LEFT)) |         assertThat(sut.isSolution()).isFalse(); | ||||||
|                 .returns(false, Tile::isSolution); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
|     void testDigFrom() { |     void tileCanBeDugIntoOnlyOnce() { | ||||||
|         // arrange |         // arrange | ||||||
|         final Tile sut = new Tile(); |         final Tile sut = new Tile(); | ||||||
| 
 | 
 | ||||||
|  | @ -45,29 +42,27 @@ class TileTest { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
|     void testDigTo() { |     void canDigToDirectionOnlyOnce() { | ||||||
|         // arrange |         // arrange | ||||||
|         final Tile sut = new Tile(); |         final Tile sut = new Tile(); | ||||||
| 
 | 
 | ||||||
|         // act / assert |         // act / assert | ||||||
|         assertThat(sut) |         assertThat(sut.digTo(Direction.TOP)).isTrue(); | ||||||
|                 .returns(true, v -> v.digTo(Direction.TOP)) |         assertThat(sut.digTo(Direction.RIGHT)).isTrue(); | ||||||
|                 .returns(true, v -> v.digTo(Direction.RIGHT)) |         assertThat(sut.digTo(Direction.BOTTOM)).isTrue(); | ||||||
|                 .returns(true, v -> v.digTo(Direction.BOTTOM)) |         assertThat(sut.digTo(Direction.LEFT)).isTrue(); | ||||||
|                 .returns(true, v -> v.digTo(Direction.LEFT)) |         // digging a second time does not succeed | ||||||
|                 // digging a second time does not succeed |         assertThat(sut.digTo(Direction.LEFT)).isFalse(); | ||||||
|                 .returns(false, v -> v.digTo(Direction.LEFT)); |  | ||||||
| 
 | 
 | ||||||
|         // assert |         // assert | ||||||
|         assertThat(sut) |         assertThat(sut.hasWallAt(Direction.TOP)).isFalse(); | ||||||
|                 .returns(false, v -> v.hasWallAt(Direction.TOP)) |         assertThat(sut.hasWallAt(Direction.RIGHT)).isFalse(); | ||||||
|                 .returns(false, v -> v.hasWallAt(Direction.RIGHT)) |         assertThat(sut.hasWallAt(Direction.BOTTOM)).isFalse(); | ||||||
|                 .returns(false, v -> v.hasWallAt(Direction.BOTTOM)) |         assertThat(sut.hasWallAt(Direction.LEFT)).isFalse(); | ||||||
|                 .returns(false, v -> v.hasWallAt(Direction.LEFT)); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
|     void testPreventDiggingToOrFrom() { |     void canNotDigToOrFromDirectionWhenPrevented() { | ||||||
|         // arrange |         // arrange | ||||||
|         final Tile sut = new Tile(); |         final Tile sut = new Tile(); | ||||||
| 
 | 
 | ||||||
|  | @ -75,10 +70,11 @@ class TileTest { | ||||||
|         sut.preventDiggingToOrFrom(Direction.LEFT); |         sut.preventDiggingToOrFrom(Direction.LEFT); | ||||||
| 
 | 
 | ||||||
|         // assert |         // assert | ||||||
|         assertThat(sut) |         assertThat(sut.digTo(Direction.LEFT)).isFalse(); | ||||||
|                 .returns(false, v -> v.digTo(Direction.LEFT)) |         assertThat(sut.digFrom(Direction.LEFT)).isFalse(); | ||||||
|                 .returns(false, v -> v.digFrom(Direction.LEFT)) |         assertThat(sut.hasWallAt(Direction.LEFT)).isTrue(); | ||||||
|                 .returns(true, v -> v.hasWallAt(Direction.LEFT)); |         // Digging in another direction is still permitted | ||||||
|  |         assertThat(sut.digTo(Direction.RIGHT)).isTrue(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @Test |     @Test | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue