Allow limiting max height and/or width when creating a maze.
This commit is contained in:
		
							parent
							
								
									f370037289
								
							
						
					
					
						commit
						87b16cb24a
					
				
					 4 changed files with 69 additions and 11 deletions
				
			
		|  | @ -22,7 +22,7 @@ public class MazeServer { | |||
|         final int port = config.port(); | ||||
|         log.info("Starting Server at http://{}:{}/", hostAddress, port); | ||||
|         final RoutingHandler routingHandler = new RoutingHandler() | ||||
|                 .get(CreateHandler.PATH_TEMPLATE, new CreateHandler()) | ||||
|                 .get(CreateHandler.PATH_TEMPLATE, new CreateHandler(config.maxMazeHeight(), config.maxMazeWidth())) | ||||
|                 .post(RenderV1Handler.PATH_TEMPLATE, new RenderV1Handler()) | ||||
|                 .post(RenderV2Handler.PATH_TEMPLATE, new RenderV2Handler()); | ||||
| 
 | ||||
|  | @ -47,7 +47,7 @@ public class MazeServer { | |||
|     private void start() { | ||||
|         Runtime.getRuntime().addShutdownHook(new Thread(this::stop, "listener-stopper")); | ||||
|         this.undertow.start(); | ||||
|         final InetSocketAddress address = (InetSocketAddress) this.undertow.getListenerInfo().get(0).getAddress(); | ||||
|         final InetSocketAddress address = (InetSocketAddress) this.undertow.getListenerInfo().getFirst().getAddress(); | ||||
|         final String hostAddress = address.getAddress().getHostAddress(); | ||||
|         final int port = address.getPort(); | ||||
| 
 | ||||
|  |  | |||
|  | @ -8,26 +8,41 @@ import org.jetbrains.annotations.Nullable; | |||
| import java.net.InetAddress; | ||||
| 
 | ||||
| @Slf4j | ||||
| public record ServerConfig(@NotNull InetAddress address, int port) { | ||||
| public record ServerConfig(@NotNull InetAddress address, | ||||
|                            int port, | ||||
|                            int maxMazeHeight, | ||||
|                            int maxMazeWidth) { | ||||
|     public static final String SYSPROP_HOST = "fritteli.maze.server.host"; | ||||
|     public static final String SYSPROP_PORT = "fritteli.maze.server.port"; | ||||
|     public static final String SYSPROP_MAX_MAZE_HEIGHT = "fritteli.maze.maxheight"; | ||||
|     public static final String SYSPROP_MAX_MAZE_WIDTH = "fritteli.maze.maxwidth"; | ||||
| 
 | ||||
|     public ServerConfig(@NotNull final InetAddress address, int port) { | ||||
|     public ServerConfig(@NotNull final InetAddress address, | ||||
|                         final int port, | ||||
|                         final int maxMazeHeight, | ||||
|                         final int maxMazeWidth) { | ||||
|         this.address = address; | ||||
|         this.port = validatePort(port); | ||||
|         this.maxMazeHeight = validateDimension(maxMazeHeight, "height"); | ||||
|         this.maxMazeWidth = validateDimension(maxMazeWidth, "width"); | ||||
|         log.debug("host={}, port={}", this.address, this.port); | ||||
|     } | ||||
| 
 | ||||
|     public ServerConfig(@Nullable final String address, final int port) throws ConfigurationException { | ||||
|         this(validateAddress(address), port); | ||||
|     public ServerConfig(@Nullable final String address, final int port, final int maxMazeHeight, final int maxMazeWidth) | ||||
|             throws ConfigurationException { | ||||
|         this(validateAddress(address), port, maxMazeHeight, maxMazeWidth); | ||||
|     } | ||||
| 
 | ||||
|     @NotNull | ||||
|     public static ServerConfig init() throws ConfigurationException { | ||||
|         final String host = System.getProperty(SYSPROP_HOST); | ||||
|         final String portString = System.getProperty(SYSPROP_PORT); | ||||
|         final String maxMazeHeightString = System.getProperty(SYSPROP_MAX_MAZE_HEIGHT); | ||||
|         final String maxMazeWidthString = System.getProperty(SYSPROP_MAX_MAZE_WIDTH); | ||||
|         final int port = validatePort(portString); | ||||
|         return new ServerConfig(host, port); | ||||
|         final int maxMazeHeight = validateDimension(maxMazeHeightString, "height", SYSPROP_MAX_MAZE_HEIGHT); | ||||
|         final int maxMazeWidth = validateDimension(maxMazeWidthString, "width", SYSPROP_MAX_MAZE_WIDTH); | ||||
|         return new ServerConfig(host, port, maxMazeHeight, maxMazeWidth); | ||||
|     } | ||||
| 
 | ||||
|     @NotNull | ||||
|  | @ -57,4 +72,26 @@ public record ServerConfig(@NotNull InetAddress address, int port) { | |||
|                         cause | ||||
|                 )); | ||||
|     } | ||||
| 
 | ||||
|     private static int validateDimension(final int dimension, @NotNull final String identifier) { | ||||
|         if (dimension < 0) { | ||||
|             throw new ConfigurationException("Maximum %s is negative : %s".formatted(dimension, identifier)); | ||||
|         } | ||||
|         return dimension; | ||||
|     } | ||||
| 
 | ||||
|     private static int validateDimension(@Nullable final String dimensionString, | ||||
|                                          @NotNull final String identifier, | ||||
|                                          @NotNull final String syspropName) { | ||||
|         if (dimensionString == null) { | ||||
|             log.info("No maximum {} configured; using default (unlimited).", identifier); | ||||
|             return 0; | ||||
|         } | ||||
|         return Try.of(() -> Integer.valueOf(dimensionString)) | ||||
|                 .getOrElseThrow(cause -> new ConfigurationException( | ||||
|                         "Failed to parse maximum %s specified in system property '%s': %s" | ||||
|                                 .formatted(identifier, syspropName, dimensionString), | ||||
|                         cause | ||||
|                 )); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -22,6 +22,13 @@ import java.util.Map; | |||
| public class CreateHandler extends AbstractHttpHandler { | ||||
| 
 | ||||
|     public static final String PATH_TEMPLATE = "/create/{output}"; | ||||
|     private final int maxHeight; | ||||
|     private final int maxWidth; | ||||
| 
 | ||||
|     public CreateHandler(final int maxHeight, final int maxWidth) { | ||||
|         this.maxHeight = maxHeight; | ||||
|         this.maxWidth = maxWidth; | ||||
|     } | ||||
| 
 | ||||
|     @Override | ||||
|     protected void handle(@NotNull final HttpServerExchange exchange) { | ||||
|  | @ -29,10 +36,11 @@ public class CreateHandler extends AbstractHttpHandler { | |||
|         log.debug("Handling create request"); | ||||
|         this.createMazeFromRequestParameters(exchange.getQueryParameters()) | ||||
|                 .onFailure(e -> { | ||||
|                     log.error("Error creating maze from request", e); | ||||
|                     if (e instanceof InvalidRequestParameterException) { | ||||
|                         log.debug("Error creating maze from request", e); | ||||
|                         exchange.setStatusCode(StatusCodes.BAD_REQUEST); | ||||
|                     } else { | ||||
|                         log.error("Error creating maze from request", e); | ||||
|                         exchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR); | ||||
|                     } | ||||
|                     exchange.getResponseSender() | ||||
|  | @ -75,6 +83,6 @@ public class CreateHandler extends AbstractHttpHandler { | |||
| 
 | ||||
|     @NotNull | ||||
|     private Try<ParametersToMazeExtractor.GeneratedMaze> createMazeFromRequestParameters(final Map<String, Deque<String>> queryParameters) { | ||||
|         return new ParametersToMazeExtractor(queryParameters).createMaze(); | ||||
|         return new ParametersToMazeExtractor(queryParameters, this.maxHeight, this.maxWidth).createMaze(); | ||||
|     } | ||||
| } | ||||
|  |  | |||
|  | @ -20,6 +20,8 @@ class ParametersToMazeExtractor { | |||
| 
 | ||||
|     @NotNull | ||||
|     private final Map<String, Deque<String>> queryParameters; | ||||
|     private final int maxHeight; | ||||
|     private final int maxWidth; | ||||
| 
 | ||||
|     @NotNull | ||||
|     Try<GeneratedMaze> createMaze() { | ||||
|  | @ -49,12 +51,23 @@ class ParametersToMazeExtractor { | |||
|             ))); | ||||
|         } | ||||
| 
 | ||||
|         final int desiredHeight = height.get(); | ||||
|         final int desiredWidth = width.get(); | ||||
| 
 | ||||
|         if (this.maxHeight != 0 && desiredHeight > this.maxHeight) { | ||||
|             return Try.failure(new InvalidRequestParameterException("Specified height (%s) is greater than allowed maximum of %s".formatted(desiredHeight, this.maxHeight))); | ||||
|         } | ||||
| 
 | ||||
|         if (this.maxWidth != 0 && desiredWidth > this.maxWidth) { | ||||
|             return Try.failure(new InvalidRequestParameterException("Specified width (%s) is greater than allowed maximum of %s".formatted(desiredWidth, this.maxWidth))); | ||||
|         } | ||||
| 
 | ||||
|         return Try.of(() -> { | ||||
|             final Maze maze; | ||||
|             if (start.isDefined() && end.isDefined()) { | ||||
|                 maze = new Maze(width.get(), height.get(), id.getOrElse(() -> new Random().nextLong()), start.get(), end.get()); | ||||
|                 maze = new Maze(desiredWidth, desiredHeight, id.getOrElse(() -> new Random().nextLong()), start.get(), end.get()); | ||||
|             } else { | ||||
|                 maze = new Maze(width.get(), height.get(), id.getOrElse(() -> new Random().nextLong())); | ||||
|                 maze = new Maze(desiredWidth, desiredHeight, id.getOrElse(() -> new Random().nextLong())); | ||||
|             } | ||||
|             new RandomDepthFirst(maze).run(); | ||||
|             return new GeneratedMaze(maze, output.get(), RandomDepthFirst.class.getSimpleName()); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue