diff --git a/pom.xml b/pom.xml
index e924ec8..2ba1c8a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -19,7 +19,7 @@
17
24.0.1
5.9.2
- 0.0.7
+ 0.0.8
1.4.6
1.18.26
2.0.7
diff --git a/src/main/java/ch/fritteli/labyrinth/server/LabyrinthServer.java b/src/main/java/ch/fritteli/labyrinth/server/LabyrinthServer.java
index 16e0aae..4c7da3e 100644
--- a/src/main/java/ch/fritteli/labyrinth/server/LabyrinthServer.java
+++ b/src/main/java/ch/fritteli/labyrinth/server/LabyrinthServer.java
@@ -1,7 +1,8 @@
package ch.fritteli.labyrinth.server;
import ch.fritteli.labyrinth.server.handler.CreateHandler;
-import ch.fritteli.labyrinth.server.handler.RenderHandler;
+import ch.fritteli.labyrinth.server.handler.RenderV1Handler;
+import ch.fritteli.labyrinth.server.handler.RenderV2Handler;
import io.undertow.Undertow;
import io.undertow.server.RoutingHandler;
import io.vavr.control.Try;
@@ -21,7 +22,8 @@ public class LabyrinthServer {
log.info("Starting Server at http://{}:{}/", hostAddress, port);
final RoutingHandler routingHandler = new RoutingHandler()
.get(CreateHandler.PATH_TEMPLATE, new CreateHandler())
- .post(RenderHandler.PATH_TEMPLATE, new RenderHandler());
+ .post(RenderV1Handler.PATH_TEMPLATE, new RenderV1Handler())
+ .post(RenderV2Handler.PATH_TEMPLATE, new RenderV2Handler());
this.undertow = Undertow.builder()
.addHttpListener(port, hostAddress)
diff --git a/src/main/java/ch/fritteli/labyrinth/server/OutputType.java b/src/main/java/ch/fritteli/labyrinth/server/OutputType.java
index 77fd88b..767d4da 100644
--- a/src/main/java/ch/fritteli/labyrinth/server/OutputType.java
+++ b/src/main/java/ch/fritteli/labyrinth/server/OutputType.java
@@ -5,7 +5,8 @@ import ch.fritteli.labyrinth.generator.renderer.html.HTMLRenderer;
import ch.fritteli.labyrinth.generator.renderer.json.JsonRenderer;
import ch.fritteli.labyrinth.generator.renderer.pdf.PDFRenderer;
import ch.fritteli.labyrinth.generator.renderer.text.TextRenderer;
-import ch.fritteli.labyrinth.generator.serialization.SerializerDeserializer;
+import ch.fritteli.labyrinth.generator.serialization.v1.SerializerDeserializerV1;
+import ch.fritteli.labyrinth.generator.serialization.v2.SerializerDeserializerV2;
import io.vavr.collection.List;
import io.vavr.collection.Stream;
import io.vavr.control.Option;
@@ -55,10 +56,16 @@ public enum OutputType {
"pdffile"),
BINARY("application/octet-stream",
"laby",
- SerializerDeserializer::serialize,
+ SerializerDeserializerV1::serialize,
true,
"b",
- "binary");
+ "binary"),
+ BINARY_V2("application/octet-stream",
+ "lab2",
+ SerializerDeserializerV2::serialize,
+ true,
+ "v",
+ "binaryv2");
@Getter
@NonNull
private final String contentType;
diff --git a/src/main/java/ch/fritteli/labyrinth/server/handler/ParametersToLabyrinthExtractor.java b/src/main/java/ch/fritteli/labyrinth/server/handler/ParametersToLabyrinthExtractor.java
index a1cf854..1000677 100644
--- a/src/main/java/ch/fritteli/labyrinth/server/handler/ParametersToLabyrinthExtractor.java
+++ b/src/main/java/ch/fritteli/labyrinth/server/handler/ParametersToLabyrinthExtractor.java
@@ -1,6 +1,8 @@
package ch.fritteli.labyrinth.server.handler;
+import ch.fritteli.labyrinth.generator.Generator;
import ch.fritteli.labyrinth.generator.model.Labyrinth;
+import ch.fritteli.labyrinth.generator.model.Position;
import ch.fritteli.labyrinth.server.OutputType;
import io.vavr.Tuple;
import io.vavr.Tuple2;
@@ -25,6 +27,8 @@ class ParametersToLabyrinthExtractor {
final Option width = getParameterValue(RequestParameter.WIDTH);
final Option height = getParameterValue(RequestParameter.HEIGHT);
final Option id = getParameterValue(RequestParameter.ID);
+ final Option start = getParameterValue(RequestParameter.START);
+ final Option end = getParameterValue(RequestParameter.END);
if (output.isEmpty()) {
return Try.failure(new IllegalArgumentException("Path parameter %s is required and must be one of: %s".formatted(
@@ -45,7 +49,16 @@ class ParametersToLabyrinthExtractor {
)));
}
- return Try.of(() -> Tuple.of(output.get(), new Labyrinth(width.get(), height.get(), id.getOrElse(() -> new Random().nextLong()))));
+ return Try.of(() -> {
+ final Labyrinth labyrinth;
+ if (start.isDefined() && end.isDefined()) {
+ labyrinth = new Labyrinth(width.get(), height.get(), id.getOrElse(() -> new Random().nextLong()), start.get(), end.get());
+ } else {
+ labyrinth = new Labyrinth(width.get(), height.get(), id.getOrElse(() -> new Random().nextLong()));
+ }
+ new Generator(labyrinth).run();
+ return Tuple.of(output.get(), labyrinth);
+ });
}
@NonNull
diff --git a/src/main/java/ch/fritteli/labyrinth/server/handler/RenderHandler.java b/src/main/java/ch/fritteli/labyrinth/server/handler/RenderV1Handler.java
similarity index 90%
rename from src/main/java/ch/fritteli/labyrinth/server/handler/RenderHandler.java
rename to src/main/java/ch/fritteli/labyrinth/server/handler/RenderV1Handler.java
index 52a61d5..a02810b 100644
--- a/src/main/java/ch/fritteli/labyrinth/server/handler/RenderHandler.java
+++ b/src/main/java/ch/fritteli/labyrinth/server/handler/RenderV1Handler.java
@@ -1,7 +1,7 @@
package ch.fritteli.labyrinth.server.handler;
import ch.fritteli.labyrinth.generator.model.Labyrinth;
-import ch.fritteli.labyrinth.generator.serialization.SerializerDeserializer;
+import ch.fritteli.labyrinth.generator.serialization.v1.SerializerDeserializerV1;
import ch.fritteli.labyrinth.server.OutputType;
import io.undertow.server.HttpServerExchange;
import io.undertow.util.HeaderValues;
@@ -12,9 +12,9 @@ import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
@Slf4j
-public class RenderHandler extends AbstractHttpHandler {
+public class RenderV1Handler extends AbstractHttpHandler {
- public static final String PATH_TEMPLATE = "/render/{output}";
+ public static final String PATH_TEMPLATE = "/render/v1/{output}";
@Override
public void handle(final HttpServerExchange exchange) {
@@ -28,7 +28,7 @@ public class RenderHandler extends AbstractHttpHandler {
final OutputType output = this.getOutputType(httpServerExchange);
final byte[] render;
try {
- final Labyrinth labyrinth = SerializerDeserializer.deserialize(bytes);
+ final Labyrinth labyrinth = SerializerDeserializerV1.deserialize(bytes);
render = output.render(labyrinth);
} catch (final Exception e) {
log.error("Error rendering binary labyrinth data", e);
diff --git a/src/main/java/ch/fritteli/labyrinth/server/handler/RenderV2Handler.java b/src/main/java/ch/fritteli/labyrinth/server/handler/RenderV2Handler.java
new file mode 100644
index 0000000..80d0549
--- /dev/null
+++ b/src/main/java/ch/fritteli/labyrinth/server/handler/RenderV2Handler.java
@@ -0,0 +1,60 @@
+package ch.fritteli.labyrinth.server.handler;
+
+import ch.fritteli.labyrinth.generator.model.Labyrinth;
+import ch.fritteli.labyrinth.generator.serialization.v2.SerializerDeserializerV2;
+import ch.fritteli.labyrinth.server.OutputType;
+import io.undertow.server.HttpServerExchange;
+import io.undertow.util.HeaderValues;
+import io.undertow.util.Headers;
+import io.undertow.util.StatusCodes;
+import java.nio.ByteBuffer;
+import lombok.NonNull;
+import lombok.extern.slf4j.Slf4j;
+
+@Slf4j
+public class RenderV2Handler extends AbstractHttpHandler {
+
+ public static final String PATH_TEMPLATE = "/render/v2/{output}";
+
+ @Override
+ public void handle(final HttpServerExchange exchange) {
+ log.debug("Handling render request");
+
+ if (exchange.isInIoThread()) {
+ exchange.dispatch(this);
+ return;
+ }
+ exchange.getRequestReceiver().receiveFullBytes((httpServerExchange, bytes) -> {
+ final OutputType output = this.getOutputType(httpServerExchange);
+ final byte[] render;
+ try {
+ final Labyrinth labyrinth = SerializerDeserializerV2.deserialize(bytes);
+ render = output.render(labyrinth);
+ } catch (final Exception e) {
+ log.error("Error rendering binary labyrinth data", e);
+ httpServerExchange.setStatusCode(StatusCodes.INTERNAL_SERVER_ERROR)
+ .getResponseSender()
+ .send("Error rendering labyrinth: %s".formatted(e.getMessage()));
+ return;
+ }
+ httpServerExchange
+ .setStatusCode(StatusCodes.OK)
+ .getResponseHeaders()
+ .put(Headers.CONTENT_TYPE, output.getContentType());
+ httpServerExchange.getResponseSender()
+ .send(ByteBuffer.wrap(render));
+ });
+ }
+
+ @NonNull
+ private OutputType getOutputType(@NonNull final HttpServerExchange httpServerExchange) {
+ return RequestParameter.OUTPUT.getParameterValue(httpServerExchange.getQueryParameters())
+ .getOrElse(() -> {
+ final HeaderValues accept = httpServerExchange.getRequestHeaders().get(Headers.ACCEPT);
+ if (accept.contains(OutputType.HTML.getContentType())) {
+ return OutputType.HTML;
+ }
+ return OutputType.TEXT_PLAIN;
+ });
+ }
+}
diff --git a/src/main/java/ch/fritteli/labyrinth/server/handler/RequestParameter.java b/src/main/java/ch/fritteli/labyrinth/server/handler/RequestParameter.java
index 314ee22..dc1c59b 100644
--- a/src/main/java/ch/fritteli/labyrinth/server/handler/RequestParameter.java
+++ b/src/main/java/ch/fritteli/labyrinth/server/handler/RequestParameter.java
@@ -1,5 +1,6 @@
package ch.fritteli.labyrinth.server.handler;
+import ch.fritteli.labyrinth.generator.model.Position;
import ch.fritteli.labyrinth.server.OutputType;
import io.vavr.Tuple2;
import io.vavr.collection.HashMap;
@@ -26,7 +27,23 @@ enum RequestParameter {
.toOption()
.onEmpty(() -> log.debug("Unparseable value for parameter 'id': '{}'", p)), "i", "id"),
OUTPUT(p -> OutputType.ofString(p)
- .onEmpty(() -> log.debug("Unparseable value for parameter 'output': '{}'", p)), "o", "output");
+ .onEmpty(() -> log.debug("Unparseable value for parameter 'output': '{}'", p)), "o", "output"),
+ START(p -> Try.of(() -> {
+ final String[] parts = p.split(",");
+ final int x = Integer.parseInt(parts[0]);
+ final int y = Integer.parseInt(parts[1]);
+ return new Position(x, y);
+ })
+ .toOption()
+ .onEmpty(() -> log.debug("Unparseable value for parameter 'start': '{}'", p)), "s", "start"),
+ END(p -> Try.of(() -> {
+ final String[] parts = p.split(",");
+ final int x = Integer.parseInt(parts[0]);
+ final int y = Integer.parseInt(parts[1]);
+ return new Position(x, y);
+ })
+ .toOption()
+ .onEmpty(() -> log.debug("Unparseable value for parameter 'end': '{}'", p)), "e", "end");
@NonNull
private final Function> extractor;
@Getter