Add interactiveness to HTML outputs.
This commit is contained in:
parent
57c7359693
commit
dd498e15cd
1 changed files with 107 additions and 5 deletions
|
@ -5,7 +5,109 @@ import ch.fritteli.labyrinth.generator.renderer.Renderer;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
|
|
||||||
public class HTMLRenderer implements Renderer<String> {
|
public class HTMLRenderer implements Renderer<String> {
|
||||||
private static final String POSTAMBLE = "</body></html>";
|
|
||||||
|
private static final String POSTAMBLE = "<script>"
|
||||||
|
+ "let userPath = [];"
|
||||||
|
+ "const DIR_UNDEF = -1;"
|
||||||
|
+ "const DIR_SAME = 0;"
|
||||||
|
+ "const DIR_UP = 1;"
|
||||||
|
+ "const DIR_RIGHT = 2;"
|
||||||
|
+ "const DIR_DOWN = 3;"
|
||||||
|
+ "const DIR_LEFT = 4;"
|
||||||
|
+ "function getCoords(cell) {"
|
||||||
|
+ " return {"
|
||||||
|
+ " x: cell.cellIndex,"
|
||||||
|
+ " y: cell.parentElement.rowIndex"
|
||||||
|
+ " };"
|
||||||
|
+ "}"
|
||||||
|
+ "function distance(prev, next) {"
|
||||||
|
+ " return Math.abs(prev.x - next.x) + Math.abs(prev.y - next.y);"
|
||||||
|
+ "}"
|
||||||
|
+ "function direction(prev, next) {"
|
||||||
|
+ " const dist = distance(prev, next);"
|
||||||
|
+ " if (dist === 0) {"
|
||||||
|
+ " return DIR_SAME;"
|
||||||
|
+ " }"
|
||||||
|
+ " if (dist !== 1) {"
|
||||||
|
+ " return DIR_UNDEF;"
|
||||||
|
+ " }"
|
||||||
|
+ " if (next.x === prev.x) {"
|
||||||
|
+ " if (next.y === prev.y + 1) {"
|
||||||
|
+ " return DIR_DOWN;"
|
||||||
|
+ " }"
|
||||||
|
+ " return DIR_UP;"
|
||||||
|
+ " }"
|
||||||
|
+ " if (next.x === prev.x + 1) {"
|
||||||
|
+ " return DIR_RIGHT;"
|
||||||
|
+ " }"
|
||||||
|
+ " return DIR_LEFT;"
|
||||||
|
+ "}"
|
||||||
|
+ "(function () {"
|
||||||
|
+ " const labyrinthTable = document.getElementById(\"labyrinth\");"
|
||||||
|
+ " const labyrinthCells = labyrinthTable.getElementsByTagName(\"td\");"
|
||||||
|
+ " const start = {x: 0, y: 0};"
|
||||||
|
+ " const end = {"
|
||||||
|
+ " x: labyrinthTable.getElementsByTagName(\"tr\")[0].getElementsByTagName(\"td\").length - 1,"
|
||||||
|
+ " y: labyrinthTable.getElementsByTagName(\"tr\").length - 1"
|
||||||
|
+ " };"
|
||||||
|
+ " for (let i = 0; i < labyrinthCells.length; i++) {"
|
||||||
|
+ " let cell = labyrinthCells.item(i);"
|
||||||
|
+ " cell.onclick = (event) => {"
|
||||||
|
+ " let target = event.target;"
|
||||||
|
+ " const coords = getCoords(target);"
|
||||||
|
+ " if (coords.x === end.x && coords.y === end.y) {"
|
||||||
|
+ " alert(\"HOORAY! You did it! Congratulations!\")"
|
||||||
|
+ " }"
|
||||||
|
+ " if (userPath.length === 0) {"
|
||||||
|
+ " if (coords.x === start.x && coords.y === start.y) {"
|
||||||
|
+ " userPath.push(coords);"
|
||||||
|
+ " target.classList.toggle(\"user\");"
|
||||||
|
+ " }"
|
||||||
|
+ " } else {"
|
||||||
|
+ " const dir = direction(userPath[userPath.length - 1], coords);"
|
||||||
|
+ " switch (dir) {"
|
||||||
|
+ " case DIR_UNDEF:"
|
||||||
|
+ " return;"
|
||||||
|
+ " case DIR_SAME:"
|
||||||
|
+ " userPath.pop();"
|
||||||
|
+ " target.classList.toggle(\"user\");"
|
||||||
|
+ " return;"
|
||||||
|
+ " default:"
|
||||||
|
+ " if (userPath.find(value => value.x === coords.x && value.y === coords.y)) {"
|
||||||
|
+ " return;"
|
||||||
|
+ " } else {"
|
||||||
|
+ " switch (dir) {"
|
||||||
|
+ " case DIR_UP:"
|
||||||
|
+ " if (target.classList.contains(\"bottom\")) {"
|
||||||
|
+ " return;"
|
||||||
|
+ " }"
|
||||||
|
+ " break;"
|
||||||
|
+ " case DIR_RIGHT:"
|
||||||
|
+ " if (target.classList.contains(\"left\")) {"
|
||||||
|
+ " return;"
|
||||||
|
+ " }"
|
||||||
|
+ " break;"
|
||||||
|
+ " case DIR_DOWN:"
|
||||||
|
+ " if (target.classList.contains(\"top\")) {"
|
||||||
|
+ " return;"
|
||||||
|
+ " }"
|
||||||
|
+ " break;"
|
||||||
|
+ " case DIR_LEFT:"
|
||||||
|
+ " if (target.classList.contains(\"right\")) {"
|
||||||
|
+ " return;"
|
||||||
|
+ " }"
|
||||||
|
+ " break;"
|
||||||
|
+ " }"
|
||||||
|
+ " userPath.push(coords);"
|
||||||
|
+ " target.classList.toggle(\"user\");"
|
||||||
|
+ " return;"
|
||||||
|
+ " }"
|
||||||
|
+ " }"
|
||||||
|
+ " }"
|
||||||
|
+ " };"
|
||||||
|
+ " }"
|
||||||
|
+ "})();"
|
||||||
|
+ "</script></body></html>";
|
||||||
|
|
||||||
private HTMLRenderer() {
|
private HTMLRenderer() {
|
||||||
}
|
}
|
||||||
|
@ -23,7 +125,7 @@ public class HTMLRenderer implements Renderer<String> {
|
||||||
}
|
}
|
||||||
final Generator generator = new Generator(labyrinth);
|
final Generator generator = new Generator(labyrinth);
|
||||||
final StringBuilder sb = new StringBuilder(this.getPreamble(labyrinth));
|
final StringBuilder sb = new StringBuilder(this.getPreamble(labyrinth));
|
||||||
sb.append("<table>");
|
sb.append("<table id=\"labyrinth\">");
|
||||||
while (generator.hasNext()) {
|
while (generator.hasNext()) {
|
||||||
sb.append(generator.next());
|
sb.append(generator.next());
|
||||||
}
|
}
|
||||||
|
@ -39,11 +141,12 @@ public class HTMLRenderer implements Renderer<String> {
|
||||||
"<meta charset=\"utf-8\">" +
|
"<meta charset=\"utf-8\">" +
|
||||||
"<style>" +
|
"<style>" +
|
||||||
"table{border-collapse:collapse;}" +
|
"table{border-collapse:collapse;}" +
|
||||||
"td{border:0 solid black;height:1em;width:1em;}" +
|
"td{border:0 solid black;height:1em;width:1em;cursor:pointer;}" +
|
||||||
"td.top{border-top-width:1px;}" +
|
"td.top{border-top-width:1px;}" +
|
||||||
"td.right{border-right-width:1px;}" +
|
"td.right{border-right-width:1px;}" +
|
||||||
"td.bottom{border-bottom-width:1px;}" +
|
"td.bottom{border-bottom-width:1px;}" +
|
||||||
"td.left{border-left-width:1px;}" +
|
"td.left{border-left-width:1px;}" +
|
||||||
|
"td.user{background:hotpink;}" +
|
||||||
"</style>" +
|
"</style>" +
|
||||||
"<script>" +
|
"<script>" +
|
||||||
"let solution = false;" +
|
"let solution = false;" +
|
||||||
|
@ -59,7 +162,6 @@ public class HTMLRenderer implements Renderer<String> {
|
||||||
"</script>" +
|
"</script>" +
|
||||||
"</head>" +
|
"</head>" +
|
||||||
"<body>" +
|
"<body>" +
|
||||||
"<input type=\"checkbox\" onclick=\"toggleSolution()\">show solution</input>";
|
"<input id=\"solutionbox\" type=\"checkbox\" onclick=\"toggleSolution()\"/><label for=\"solutionbox\">show solution</label>";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue