Make TextRenderer and HTMLRenderer thread-safe (or so I think ...)
This commit is contained in:
		
							parent
							
								
									8774324b65
								
							
						
					
					
						commit
						cf96949f8e
					
				
					 5 changed files with 292 additions and 294 deletions
				
			
		|  | @ -9,6 +9,8 @@ import java.nio.file.Path; | ||||||
| import java.nio.file.StandardOpenOption; | import java.nio.file.StandardOpenOption; | ||||||
| 
 | 
 | ||||||
| public class HTMLFileRenderer implements Renderer<Path> { | public class HTMLFileRenderer implements Renderer<Path> { | ||||||
|  |     @NonNull | ||||||
|  |     private static final HTMLRenderer HTML_RENDERER = HTMLRenderer.newInstance(); | ||||||
|     @Setter |     @Setter | ||||||
|     private Path targetFile; |     private Path targetFile; | ||||||
| 
 | 
 | ||||||
|  | @ -35,7 +37,7 @@ public class HTMLFileRenderer implements Renderer<Path> { | ||||||
|         if (!this.isTargetFileDefinedAndWritable()) { |         if (!this.isTargetFileDefinedAndWritable()) { | ||||||
|             throw new IllegalArgumentException("Cannot write to target file. See previous log messages for details."); |             throw new IllegalArgumentException("Cannot write to target file. See previous log messages for details."); | ||||||
|         } |         } | ||||||
|         final String html = HTMLRenderer.newInstance().render(labyrinth); |         final String html = HTML_RENDERER.render(labyrinth); | ||||||
|         try { |         try { | ||||||
|             Files.writeString(this.targetFile, html, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE); |             Files.writeString(this.targetFile, html, StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.WRITE); | ||||||
|         } catch (IOException e) { |         } catch (IOException e) { | ||||||
|  |  | ||||||
|  | @ -3,6 +3,7 @@ package ch.fritteli.labyrinth; | ||||||
| import io.vavr.collection.HashSet; | import io.vavr.collection.HashSet; | ||||||
| import io.vavr.collection.Set; | import io.vavr.collection.Set; | ||||||
| import lombok.NonNull; | import lombok.NonNull; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
| 
 | 
 | ||||||
| public class HTMLRenderer implements Renderer<String> { | public class HTMLRenderer implements Renderer<String> { | ||||||
|     private static final String PREAMBLE = "<!DOCTYPE html><html lang=\"en\">" + |     private static final String PREAMBLE = "<!DOCTYPE html><html lang=\"en\">" + | ||||||
|  | @ -33,11 +34,6 @@ public class HTMLRenderer implements Renderer<String> { | ||||||
|             "<body>" + |             "<body>" + | ||||||
|             "<input type=\"checkbox\" onclick=\"toggleSolution()\">show solution</input>"; |             "<input type=\"checkbox\" onclick=\"toggleSolution()\">show solution</input>"; | ||||||
|     private static final String POSTAMBLE = "</body></html>"; |     private static final String POSTAMBLE = "</body></html>"; | ||||||
|     private Labyrinth labyrinth; |  | ||||||
|     private int width; |  | ||||||
|     private int height; |  | ||||||
|     // row counter |  | ||||||
|     private int y = 0; |  | ||||||
| 
 | 
 | ||||||
|     private HTMLRenderer() { |     private HTMLRenderer() { | ||||||
|     } |     } | ||||||
|  | @ -49,56 +45,60 @@ public class HTMLRenderer implements Renderer<String> { | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NonNull | ||||||
|     public String render(@NonNull final Labyrinth labyrinth) { |     public String render(@NonNull final Labyrinth labyrinth) { | ||||||
|         this.labyrinth = labyrinth; |         if (labyrinth.getWidth() == 0 || labyrinth.getHeight() == 0) { | ||||||
|         this.width = labyrinth.getWidth(); |  | ||||||
|         this.height = labyrinth.getHeight(); |  | ||||||
|         if (this.width == 0 || this.height == 0) { |  | ||||||
|             return PREAMBLE + POSTAMBLE; |             return PREAMBLE + POSTAMBLE; | ||||||
|         } |         } | ||||||
|  |         final Generator generator = new Generator(labyrinth); | ||||||
|         final StringBuilder sb = new StringBuilder(PREAMBLE); |         final StringBuilder sb = new StringBuilder(PREAMBLE); | ||||||
|         sb.append("<table>"); |         sb.append("<table>"); | ||||||
|         while (this.hasNext()) { |         while (generator.hasNext()) { | ||||||
|             sb.append(this.next()); |             sb.append(generator.next()); | ||||||
|         } |         } | ||||||
|         sb.append("</table>"); |         sb.append("</table>"); | ||||||
|         sb.append(POSTAMBLE); |         sb.append(POSTAMBLE); | ||||||
|         return sb.toString(); |         return sb.toString(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean hasNext() { |     @RequiredArgsConstructor | ||||||
|         return this.y < this.height; |     private static class Generator { | ||||||
|     } |         private final Labyrinth labyrinth; | ||||||
|  |         private int y = 0; | ||||||
| 
 | 
 | ||||||
|     private String next() { |         private boolean hasNext() { | ||||||
|         StringBuilder sb = new StringBuilder("<tr>"); |             return this.y < this.labyrinth.getHeight(); | ||||||
|         for (int x = 0; x < this.width; x++) { |  | ||||||
|             final Tile currentTile = this.labyrinth.getTileAt(x, this.y); |  | ||||||
|             sb.append("<td class=\""); |  | ||||||
|             sb.append(this.getClasses(currentTile).mkString(" ")); |  | ||||||
|             sb.append("\"> </td>"); |  | ||||||
|         } |         } | ||||||
|         sb.append("</tr>"); |  | ||||||
|         this.y++; |  | ||||||
|         return sb.toString(); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private Set<String> getClasses(@NonNull final Tile tile) { |         private String next() { | ||||||
|         Set<String> result = HashSet.empty(); |             StringBuilder sb = new StringBuilder("<tr>"); | ||||||
|         if (tile.hasWallAt(Direction.TOP)) { |             for (int x = 0; x < this.labyrinth.getWidth(); x++) { | ||||||
|             result = result.add("top"); |                 final Tile currentTile = this.labyrinth.getTileAt(x, this.y); | ||||||
|  |                 sb.append("<td class=\""); | ||||||
|  |                 sb.append(this.getClasses(currentTile).mkString(" ")); | ||||||
|  |                 sb.append("\"> </td>"); | ||||||
|  |             } | ||||||
|  |             sb.append("</tr>"); | ||||||
|  |             this.y++; | ||||||
|  |             return sb.toString(); | ||||||
|         } |         } | ||||||
|         if (tile.hasWallAt(Direction.RIGHT)) { | 
 | ||||||
|             result = result.add("right"); |         private Set<String> getClasses(@NonNull final Tile tile) { | ||||||
|  |             Set<String> result = HashSet.empty(); | ||||||
|  |             if (tile.hasWallAt(Direction.TOP)) { | ||||||
|  |                 result = result.add("top"); | ||||||
|  |             } | ||||||
|  |             if (tile.hasWallAt(Direction.RIGHT)) { | ||||||
|  |                 result = result.add("right"); | ||||||
|  |             } | ||||||
|  |             if (tile.hasWallAt(Direction.BOTTOM)) { | ||||||
|  |                 result = result.add("bottom"); | ||||||
|  |             } | ||||||
|  |             if (tile.hasWallAt(Direction.LEFT)) { | ||||||
|  |                 result = result.add("left"); | ||||||
|  |             } | ||||||
|  |             if (tile.isSolution()) { | ||||||
|  |                 result = result.add("solution"); | ||||||
|  |             } | ||||||
|  |             return result; | ||||||
|         } |         } | ||||||
|         if (tile.hasWallAt(Direction.BOTTOM)) { |  | ||||||
|             result = result.add("bottom"); |  | ||||||
|         } |  | ||||||
|         if (tile.hasWallAt(Direction.LEFT)) { |  | ||||||
|             result = result.add("left"); |  | ||||||
|         } |  | ||||||
|         if (tile.isSolution()) { |  | ||||||
|             result = result.add("solution"); |  | ||||||
|         } |  | ||||||
|         return result; |  | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -9,7 +9,7 @@ public class Main { | ||||||
|         final Labyrinth labyrinth = new Labyrinth(width, height); |         final Labyrinth labyrinth = new Labyrinth(width, height); | ||||||
|         final TextRenderer textRenderer = TextRenderer.newInstance(); |         final TextRenderer textRenderer = TextRenderer.newInstance(); | ||||||
|         System.out.println(textRenderer.render(labyrinth)); |         System.out.println(textRenderer.render(labyrinth)); | ||||||
|         System.out.println(textRenderer.setRenderingSolution(true).render(labyrinth)); |         System.out.println(textRenderer.setRenderSolution(true).render(labyrinth)); | ||||||
|         final HTMLRenderer htmlRenderer = HTMLRenderer.newInstance(); |         final HTMLRenderer htmlRenderer = HTMLRenderer.newInstance(); | ||||||
|         System.out.println(htmlRenderer.render(labyrinth)); |         System.out.println(htmlRenderer.render(labyrinth)); | ||||||
|         System.out.println(HTMLFileRenderer.newInstance().render(labyrinth)); |         System.out.println(HTMLFileRenderer.newInstance().render(labyrinth)); | ||||||
|  |  | ||||||
|  | @ -4,20 +4,12 @@ import lombok.AccessLevel; | ||||||
| import lombok.AllArgsConstructor; | import lombok.AllArgsConstructor; | ||||||
| import lombok.NoArgsConstructor; | import lombok.NoArgsConstructor; | ||||||
| import lombok.NonNull; | import lombok.NonNull; | ||||||
|  | import lombok.RequiredArgsConstructor; | ||||||
| import lombok.experimental.FieldDefaults; | import lombok.experimental.FieldDefaults; | ||||||
| import org.jetbrains.annotations.Nullable; | import org.jetbrains.annotations.Nullable; | ||||||
| 
 | 
 | ||||||
| public class TextRenderer implements Renderer<String> { | public class TextRenderer implements Renderer<String> { | ||||||
|     private Labyrinth labyrinth; |  | ||||||
|     private int width; |  | ||||||
|     private int height; |  | ||||||
|     private boolean renderSolution; |     private boolean renderSolution; | ||||||
|     // column counter |  | ||||||
|     private int x; |  | ||||||
|     // row counter |  | ||||||
|     private int y; |  | ||||||
|     // line counter (top-, center- or bottom line of a row) |  | ||||||
|     private int line; |  | ||||||
| 
 | 
 | ||||||
|     private TextRenderer() { |     private TextRenderer() { | ||||||
|         this.renderSolution = false; |         this.renderSolution = false; | ||||||
|  | @ -29,295 +21,299 @@ public class TextRenderer implements Renderer<String> { | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NonNull | ||||||
|     public TextRenderer setRenderingSolution(final boolean renderSolution) { |     public TextRenderer setRenderSolution(final boolean renderSolution) { | ||||||
|         this.renderSolution = renderSolution; |         this.renderSolution = renderSolution; | ||||||
|         return this; |         return this; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     @NonNull |     @NonNull | ||||||
|     public String render(@NonNull final Labyrinth labyrinth) { |     public String render(@NonNull final Labyrinth labyrinth) { | ||||||
|         this.labyrinth = labyrinth; |         if (labyrinth.getWidth() == 0 || labyrinth.getHeight() == 0) { | ||||||
|         this.width = labyrinth.getWidth(); |  | ||||||
|         this.height = labyrinth.getHeight(); |  | ||||||
|         if (this.width == 0 || this.height == 0) { |  | ||||||
|             return ""; |             return ""; | ||||||
|         } |         } | ||||||
|         this.x = 0; |         final Generator generator = new Generator(labyrinth, this.renderSolution); | ||||||
|         this.y = 0; |  | ||||||
|         this.line = 0; |  | ||||||
|         final StringBuilder sb = new StringBuilder(); |         final StringBuilder sb = new StringBuilder(); | ||||||
|         while (this.hasNext()) { |         while (generator.hasNext()) { | ||||||
|             sb.append(this.next()); |             sb.append(generator.next()); | ||||||
|         } |         } | ||||||
|         return sb.toString(); |         return sb.toString(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private boolean hasNext() { |     @RequiredArgsConstructor(access = AccessLevel.PRIVATE) | ||||||
|         return this.y < this.height; |     static class Generator { | ||||||
|     } |         @NonNull | ||||||
|  |         private final Labyrinth labyrinth; | ||||||
|  |         private final boolean renderSolution; | ||||||
|  |         private int x = 0; | ||||||
|  |         private int y = 0; | ||||||
|  |         private int line = 0; | ||||||
| 
 | 
 | ||||||
|     private String next() { |         private boolean hasNext() { | ||||||
|         final Tile currentTile = this.labyrinth.getTileAt(this.x, this.y); |             return this.y < this.labyrinth.getHeight(); | ||||||
|         final Tile leftTile = this.getTileOrNull(this.x - 1, this.y); |  | ||||||
|         final Tile topTile = this.getTileOrNull(this.x, this.y - 1); |  | ||||||
|         final String s; |  | ||||||
|         switch (this.line) { |  | ||||||
|             case 0: |  | ||||||
|                 s = this.renderTopLine(currentTile, leftTile, topTile); |  | ||||||
|                 break; |  | ||||||
|             case 1: |  | ||||||
|                 s = this.renderCenterLine(currentTile); |  | ||||||
|                 break; |  | ||||||
|             case 2: |  | ||||||
|                 s = this.renderBottomLine(currentTile, leftTile); |  | ||||||
|                 break; |  | ||||||
|             default: |  | ||||||
|                 s = ""; |  | ||||||
|                 break; |  | ||||||
|         } |         } | ||||||
|         this.prepareNextStep(); |  | ||||||
|         return s; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private void prepareNextStep() { |         private String next() { | ||||||
|         // do some magic ... |             final Tile currentTile = this.labyrinth.getTileAt(this.x, this.y); | ||||||
|         this.x++; |             final Tile leftTile = this.getTileOrNull(this.x - 1, this.y); | ||||||
|         if (this.x == this.width) { |             final Tile topTile = this.getTileOrNull(this.x, this.y - 1); | ||||||
|             // Reached the end of the row? |             final String s; | ||||||
|             // On to the next line then! |             switch (this.line) { | ||||||
|             this.x = 0; |                 case 0: | ||||||
|             this.line++; |                     s = this.renderTopLine(currentTile, leftTile, topTile); | ||||||
|  |                     break; | ||||||
|  |                 case 1: | ||||||
|  |                     s = this.renderCenterLine(currentTile); | ||||||
|  |                     break; | ||||||
|  |                 case 2: | ||||||
|  |                     s = this.renderBottomLine(currentTile, leftTile); | ||||||
|  |                     break; | ||||||
|  |                 default: | ||||||
|  |                     s = ""; | ||||||
|  |                     break; | ||||||
|  |             } | ||||||
|  |             this.prepareNextStep(); | ||||||
|  |             return s; | ||||||
|         } |         } | ||||||
|         if (this.line == 2 && this.y < this.height - 1) { |  | ||||||
|             // Finished rendering the center line, and more rows available? |  | ||||||
|             // On to the next row then! |  | ||||||
|             this.line = 0; |  | ||||||
|             this.y++; |  | ||||||
|         } |  | ||||||
|         if (this.line == 3) { |  | ||||||
|             // Finished rendering the bottom line (of the last row)? |  | ||||||
|             // Increment row counter one more time => this is the exit condition. |  | ||||||
|             this.line = 0; |  | ||||||
|             this.y++; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private Tile getTileOrNull(final int x, final int y) { |         private void prepareNextStep() { | ||||||
|         if (x < 0 || y < 0 || x >= this.width || y >= this.height) { |             // do some magic ... | ||||||
|             return null; |             this.x++; | ||||||
|  |             if (this.x == this.labyrinth.getWidth()) { | ||||||
|  |                 // Reached the end of the row? | ||||||
|  |                 // On to the next line then! | ||||||
|  |                 this.x = 0; | ||||||
|  |                 this.line++; | ||||||
|  |             } | ||||||
|  |             if (this.line == 2 && this.y < this.labyrinth.getHeight() - 1) { | ||||||
|  |                 // Finished rendering the center line, and more rows available? | ||||||
|  |                 // On to the next row then! | ||||||
|  |                 this.line = 0; | ||||||
|  |                 this.y++; | ||||||
|  |             } | ||||||
|  |             if (this.line == 3) { | ||||||
|  |                 // Finished rendering the bottom line (of the last row)? | ||||||
|  |                 // Increment row counter one more time => this is the exit condition. | ||||||
|  |                 this.line = 0; | ||||||
|  |                 this.y++; | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|         return this.labyrinth.getTileAt(x, y); |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private String renderTopLine(@NonNull final Tile currentTile, @Nullable final Tile leftTile, @Nullable final Tile topTile) { |         private Tile getTileOrNull(final int x, final int y) { | ||||||
|         final CharDefinition charDef1 = new CharDefinition(); |             if (x < 0 || y < 0 || x >= this.labyrinth.getWidth() || y >= this.labyrinth.getHeight()) { | ||||||
|         final CharDefinition charDef2 = new CharDefinition(); |                 return null; | ||||||
|         final CharDefinition charDef3 = new CharDefinition(); |             } | ||||||
|         String result; |             return this.labyrinth.getTileAt(x, y); | ||||||
|         if (currentTile.hasWallAt(Direction.LEFT)) { |  | ||||||
|             charDef1.down(); |  | ||||||
|         } |         } | ||||||
|         if (currentTile.hasWallAt(Direction.TOP)) { | 
 | ||||||
|             charDef1.right(); |         private String renderTopLine(@NonNull final Tile currentTile, @Nullable final Tile leftTile, @Nullable final Tile topTile) { | ||||||
|             charDef2.horizontal(); |             final CharDefinition charDef1 = new CharDefinition(); | ||||||
|             charDef3.left(); |             final CharDefinition charDef2 = new CharDefinition(); | ||||||
|  |             final CharDefinition charDef3 = new CharDefinition(); | ||||||
|  |             String result; | ||||||
|  |             if (currentTile.hasWallAt(Direction.LEFT)) { | ||||||
|  |                 charDef1.down(); | ||||||
|  |             } | ||||||
|  |             if (currentTile.hasWallAt(Direction.TOP)) { | ||||||
|  |                 charDef1.right(); | ||||||
|  |                 charDef2.horizontal(); | ||||||
|  |                 charDef3.left(); | ||||||
|  |             } | ||||||
|  |             if (currentTile.hasWallAt(Direction.RIGHT)) { | ||||||
|  |                 charDef3.down(); | ||||||
|  |             } | ||||||
|  |             if (leftTile != null && leftTile.hasWallAt(Direction.TOP)) { | ||||||
|  |                 charDef1.left(); | ||||||
|  |             } | ||||||
|  |             if (topTile != null) { | ||||||
|  |                 if (topTile.hasWallAt(Direction.LEFT)) { | ||||||
|  |                     charDef1.up(); | ||||||
|  |                 } | ||||||
|  |                 if (topTile.hasWallAt(Direction.RIGHT)) { | ||||||
|  |                     charDef3.up(); | ||||||
|  |                 } | ||||||
|  |             } | ||||||
|  |             result = charDef1.toString() + charDef2; | ||||||
|  |             if (this.x == this.labyrinth.getWidth() - 1) { | ||||||
|  |                 result += charDef3 + "\n"; | ||||||
|  |             } | ||||||
|  |             return result; | ||||||
|         } |         } | ||||||
|         if (currentTile.hasWallAt(Direction.RIGHT)) { | 
 | ||||||
|             charDef3.down(); |         private String renderCenterLine(@NonNull final Tile currentTile) { | ||||||
|  |             final CharDefinition charDef1 = new CharDefinition(); | ||||||
|  |             final CharDefinition charDef2 = new CharDefinition(); | ||||||
|  |             String result; | ||||||
|  |             if (currentTile.hasWallAt(Direction.LEFT)) { | ||||||
|  |                 charDef1.vertical(); | ||||||
|  |             } | ||||||
|  |             if (currentTile.hasWallAt(Direction.RIGHT)) { | ||||||
|  |                 charDef2.vertical(); | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             result = charDef1 + (currentTile.isSolution() && this.renderSolution ? "x" : " "); | ||||||
|  | 
 | ||||||
|  |             if (this.x == this.labyrinth.getWidth() - 1) { | ||||||
|  |                 result += charDef2 + "\n"; | ||||||
|  |             } | ||||||
|  | 
 | ||||||
|  |             return result; | ||||||
|         } |         } | ||||||
|         if (leftTile != null && leftTile.hasWallAt(Direction.TOP)) { | 
 | ||||||
|             charDef1.left(); |         private String renderBottomLine(@NonNull final Tile currentTile, @Nullable final Tile leftTile) { | ||||||
|         } |             String result; | ||||||
|         if (topTile != null) { |             final CharDefinition charDef1 = new CharDefinition(); | ||||||
|             if (topTile.hasWallAt(Direction.LEFT)) { |             final CharDefinition charDef2 = new CharDefinition(); | ||||||
|  |             final CharDefinition charDef3 = new CharDefinition(); | ||||||
|  | 
 | ||||||
|  |             if (currentTile.hasWallAt(Direction.LEFT)) { | ||||||
|                 charDef1.up(); |                 charDef1.up(); | ||||||
|             } |             } | ||||||
|             if (topTile.hasWallAt(Direction.RIGHT)) { |             if (currentTile.hasWallAt(Direction.BOTTOM)) { | ||||||
|  |                 charDef1.right(); | ||||||
|  |                 charDef2.horizontal(); | ||||||
|  |                 charDef3.left(); | ||||||
|  |             } | ||||||
|  |             if (currentTile.hasWallAt(Direction.RIGHT)) { | ||||||
|                 charDef3.up(); |                 charDef3.up(); | ||||||
|             } |             } | ||||||
|         } |             if (leftTile != null && leftTile.hasWallAt(Direction.BOTTOM)) { | ||||||
|         result = charDef1.toString() + charDef2; |                 charDef1.left(); | ||||||
|         if (this.x == this.width - 1) { |             } | ||||||
|             result += charDef3 + "\n"; |  | ||||||
|         } |  | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     private String renderCenterLine(@NonNull final Tile currentTile) { |             result = charDef1.toString() + charDef2; | ||||||
|         final CharDefinition charDef1 = new CharDefinition(); | 
 | ||||||
|         final CharDefinition charDef2 = new CharDefinition(); |             if (this.x == this.labyrinth.getWidth() - 1) { | ||||||
|         String result; |                 result += charDef3; | ||||||
|         if (currentTile.hasWallAt(Direction.LEFT)) { |             } | ||||||
|             charDef1.vertical(); |             return result; | ||||||
|         } |  | ||||||
|         if (currentTile.hasWallAt(Direction.RIGHT)) { |  | ||||||
|             charDef2.vertical(); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         result = charDef1 + (currentTile.isSolution() && this.renderSolution ? "x" : " "); |         @FieldDefaults(level = AccessLevel.PRIVATE) | ||||||
|  |         @NoArgsConstructor | ||||||
|  |         @AllArgsConstructor | ||||||
|  |         static class CharDefinition { | ||||||
|  |             // ─ | ||||||
|  |             static final String HORIZONTAL = "\u2500"; | ||||||
|  |             // │ | ||||||
|  |             static final String VERTICAL = "\u2502"; | ||||||
|  |             // ╴ | ||||||
|  |             static final String LEFT = "\u2574"; | ||||||
|  |             // ╵ | ||||||
|  |             static final String UP = "\u2575"; | ||||||
|  |             // ╶ | ||||||
|  |             static final String RIGHT = "\u2576"; | ||||||
|  |             // ╷ | ||||||
|  |             static final String DOWN = "\u2577"; | ||||||
|  |             // ┌ | ||||||
|  |             static final String DOWN_RIGHT = "\u250c"; | ||||||
|  |             // ┐ | ||||||
|  |             static final String DOWN_LEFT = "\u2510"; | ||||||
|  |             // └ | ||||||
|  |             static final String UP_RIGHT = "\u2514"; | ||||||
|  |             // ┘ | ||||||
|  |             static final String UP_LEFT = "\u2518"; | ||||||
|  |             // ├ | ||||||
|  |             static final String VERTICAL_RIGHT = "\u251c"; | ||||||
|  |             // ┤ | ||||||
|  |             static final String VERTICAL_LEFT = "\u2524"; | ||||||
|  |             // ┬ | ||||||
|  |             static final String HORIZONTAL_DOWN = "\u252c"; | ||||||
|  |             // ┴ | ||||||
|  |             static final String HORIZONTAL_UP = "\u2534"; | ||||||
|  |             // ┼ | ||||||
|  |             static final String CROSS = "\u253c"; | ||||||
|  |             boolean up = false; | ||||||
|  |             boolean down = false; | ||||||
|  |             boolean left = false; | ||||||
|  |             boolean right = false; | ||||||
| 
 | 
 | ||||||
|         if (this.x == this.width - 1) { |             CharDefinition up() { | ||||||
|             result += charDef2 + "\n"; |                 this.up = true; | ||||||
|         } |                 return this; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|         return result; |             CharDefinition down() { | ||||||
|     } |                 this.down = true; | ||||||
|  |                 return this; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|     private String renderBottomLine(@NonNull final Tile currentTile, @Nullable final Tile leftTile) { |             CharDefinition vertical() { | ||||||
|         String result; |                 return this.up().down(); | ||||||
|         final CharDefinition charDef1 = new CharDefinition(); |             } | ||||||
|         final CharDefinition charDef2 = new CharDefinition(); |  | ||||||
|         final CharDefinition charDef3 = new CharDefinition(); |  | ||||||
| 
 | 
 | ||||||
|         if (currentTile.hasWallAt(Direction.LEFT)) { |             CharDefinition left() { | ||||||
|             charDef1.up(); |                 this.left = true; | ||||||
|         } |                 return this; | ||||||
|         if (currentTile.hasWallAt(Direction.BOTTOM)) { |             } | ||||||
|             charDef1.right(); |  | ||||||
|             charDef2.horizontal(); |  | ||||||
|             charDef3.left(); |  | ||||||
|         } |  | ||||||
|         if (currentTile.hasWallAt(Direction.RIGHT)) { |  | ||||||
|             charDef3.up(); |  | ||||||
|         } |  | ||||||
|         if (leftTile != null && leftTile.hasWallAt(Direction.BOTTOM)) { |  | ||||||
|             charDef1.left(); |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         result = charDef1.toString() + charDef2; |             CharDefinition right() { | ||||||
|  |                 this.right = true; | ||||||
|  |                 return this; | ||||||
|  |             } | ||||||
| 
 | 
 | ||||||
|         if (this.x == this.width - 1) { |             CharDefinition horizontal() { | ||||||
|             result += charDef3; |                 return this.left().right(); | ||||||
|         } |             } | ||||||
|         return result; |  | ||||||
|     } |  | ||||||
| 
 | 
 | ||||||
|     @FieldDefaults(level = AccessLevel.PRIVATE) |             public String toString() { | ||||||
|     @NoArgsConstructor |                 if (this.up) { | ||||||
|     @AllArgsConstructor |                     if (this.down) { | ||||||
|     static class CharDefinition { |                         if (this.left) { | ||||||
|         // ─ |                             if (this.right) { | ||||||
|         static final String HORIZONTAL = "\u2500"; |                                 return CROSS; | ||||||
|         // │ |                             } else { | ||||||
|         static final String VERTICAL = "\u2502"; |                                 return VERTICAL_LEFT; | ||||||
|         // ╴ |                             } | ||||||
|         static final String LEFT = "\u2574"; |  | ||||||
|         // ╵ |  | ||||||
|         static final String UP = "\u2575"; |  | ||||||
|         // ╶ |  | ||||||
|         static final String RIGHT = "\u2576"; |  | ||||||
|         // ╷ |  | ||||||
|         static final String DOWN = "\u2577"; |  | ||||||
|         // ┌ |  | ||||||
|         static final String DOWN_RIGHT = "\u250c"; |  | ||||||
|         // ┐ |  | ||||||
|         static final String DOWN_LEFT = "\u2510"; |  | ||||||
|         // └ |  | ||||||
|         static final String UP_RIGHT = "\u2514"; |  | ||||||
|         // ┘ |  | ||||||
|         static final String UP_LEFT = "\u2518"; |  | ||||||
|         // ├ |  | ||||||
|         static final String VERTICAL_RIGHT = "\u251c"; |  | ||||||
|         // ┤ |  | ||||||
|         static final String VERTICAL_LEFT = "\u2524"; |  | ||||||
|         // ┬ |  | ||||||
|         static final String HORIZONTAL_DOWN = "\u252c"; |  | ||||||
|         // ┴ |  | ||||||
|         static final String HORIZONTAL_UP = "\u2534"; |  | ||||||
|         // ┼ |  | ||||||
|         static final String CROSS = "\u253c"; |  | ||||||
|         boolean up = false; |  | ||||||
|         boolean down = false; |  | ||||||
|         boolean left = false; |  | ||||||
|         boolean right = false; |  | ||||||
| 
 |  | ||||||
|         CharDefinition up() { |  | ||||||
|             this.up = true; |  | ||||||
|             return this; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         CharDefinition down() { |  | ||||||
|             this.down = true; |  | ||||||
|             return this; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         CharDefinition vertical() { |  | ||||||
|             return this.up().down(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         CharDefinition left() { |  | ||||||
|             this.left = true; |  | ||||||
|             return this; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         CharDefinition right() { |  | ||||||
|             this.right = true; |  | ||||||
|             return this; |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
| 
 |  | ||||||
|         CharDefinition horizontal() { |  | ||||||
|             return this.left().right(); |  | ||||||
|         } |  | ||||||
| 
 |  | ||||||
|         public String toString() { |  | ||||||
|             if (this.up) { |  | ||||||
|                 if (this.down) { |  | ||||||
|                     if (this.left) { |  | ||||||
|                         if (this.right) { |  | ||||||
|                             return CROSS; |  | ||||||
|                         } else { |                         } else { | ||||||
|                             return VERTICAL_LEFT; |                             if (this.right) { | ||||||
|  |                                 return VERTICAL_RIGHT; | ||||||
|  |                             } else { | ||||||
|  |                                 return VERTICAL; | ||||||
|  |                             } | ||||||
|                         } |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         if (this.right) { |                         if (this.left) { | ||||||
|                             return VERTICAL_RIGHT; |                             if (this.right) { | ||||||
|  |                                 return HORIZONTAL_UP; | ||||||
|  |                             } else { | ||||||
|  |                                 return UP_LEFT; | ||||||
|  |                             } | ||||||
|                         } else { |                         } else { | ||||||
|                             return VERTICAL; |                             if (this.right) { | ||||||
|  |                                 return UP_RIGHT; | ||||||
|  |                             } else { | ||||||
|  |                                 return UP; | ||||||
|  |                             } | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } else { |                 } else { | ||||||
|                     if (this.left) { |                     if (this.down) { | ||||||
|                         if (this.right) { |                         if (this.left) { | ||||||
|                             return HORIZONTAL_UP; |                             if (this.right) { | ||||||
|  |                                 return HORIZONTAL_DOWN; | ||||||
|  |                             } else { | ||||||
|  |                                 return DOWN_LEFT; | ||||||
|  |                             } | ||||||
|                         } else { |                         } else { | ||||||
|                             return UP_LEFT; |                             if (this.right) { | ||||||
|  |                                 return DOWN_RIGHT; | ||||||
|  |                             } else { | ||||||
|  |                                 return DOWN; | ||||||
|  |                             } | ||||||
|                         } |                         } | ||||||
|                     } else { |                     } else { | ||||||
|                         if (this.right) { |                         if (this.left) { | ||||||
|                             return UP_RIGHT; |                             if (this.right) { | ||||||
|  |                                 return HORIZONTAL; | ||||||
|  |                             } else { | ||||||
|  |                                 return LEFT; | ||||||
|  |                             } | ||||||
|                         } else { |                         } else { | ||||||
|                             return UP; |                             if (this.right) { | ||||||
|                         } |                                 return RIGHT; | ||||||
|                     } |                             } else { | ||||||
|                 } |                                 return " "; | ||||||
|             } else { |                             } | ||||||
|                 if (this.down) { |  | ||||||
|                     if (this.left) { |  | ||||||
|                         if (this.right) { |  | ||||||
|                             return HORIZONTAL_DOWN; |  | ||||||
|                         } else { |  | ||||||
|                             return DOWN_LEFT; |  | ||||||
|                         } |  | ||||||
|                     } else { |  | ||||||
|                         if (this.right) { |  | ||||||
|                             return DOWN_RIGHT; |  | ||||||
|                         } else { |  | ||||||
|                             return DOWN; |  | ||||||
|                         } |  | ||||||
|                     } |  | ||||||
|                 } else { |  | ||||||
|                     if (this.left) { |  | ||||||
|                         if (this.right) { |  | ||||||
|                             return HORIZONTAL; |  | ||||||
|                         } else { |  | ||||||
|                             return LEFT; |  | ||||||
|                         } |  | ||||||
|                     } else { |  | ||||||
|                         if (this.right) { |  | ||||||
|                             return RIGHT; |  | ||||||
|                         } else { |  | ||||||
|                             return " "; |  | ||||||
|                         } |                         } | ||||||
|                     } |                     } | ||||||
|                 } |                 } | ||||||
|  |  | ||||||
|  | @ -1,6 +1,6 @@ | ||||||
| package ch.fritteli.labyrinth; | package ch.fritteli.labyrinth; | ||||||
| 
 | 
 | ||||||
| import ch.fritteli.labyrinth.TextRenderer.CharDefinition; | import ch.fritteli.labyrinth.TextRenderer.Generator.CharDefinition; | ||||||
| import org.junit.jupiter.api.Nested; | import org.junit.jupiter.api.Nested; | ||||||
| import org.junit.jupiter.api.Test; | import org.junit.jupiter.api.Test; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue