From 47597143fbca583d16a530a7c645343a2a75bb60 Mon Sep 17 00:00:00 2001 From: Shautvast Date: Sat, 9 Nov 2024 22:40:02 +0100 Subject: [PATCH] improvements --- .../algorithm/OptimalPathFinder.java | 1 - src/main/resources/static/css/style.css | 22 ++- src/main/resources/static/index.html | 5 +- src/main/resources/static/js/console.js | 166 +++++++++++------- src/main/resources/static/js/grid.js | 55 +++--- src/main/resources/static/js/parser.js | 0 .../assessment/algorithm/PathFinderTest.java | 2 +- 7 files changed, 147 insertions(+), 104 deletions(-) delete mode 100644 src/main/resources/static/js/parser.js diff --git a/src/main/java/assessment/algorithm/OptimalPathFinder.java b/src/main/java/assessment/algorithm/OptimalPathFinder.java index 4b9e822..1e6d102 100644 --- a/src/main/java/assessment/algorithm/OptimalPathFinder.java +++ b/src/main/java/assessment/algorithm/OptimalPathFinder.java @@ -99,7 +99,6 @@ public class OptimalPathFinder { paths.add(newPath); takenPaths.add(newPath); pointsAdded = true; -// System.out.println("add " + newPath); } } } diff --git a/src/main/resources/static/css/style.css b/src/main/resources/static/css/style.css index afa713f..061824d 100644 --- a/src/main/resources/static/css/style.css +++ b/src/main/resources/static/css/style.css @@ -1,5 +1,6 @@ -body{ - background-color: green; +body { + background-color: black; + overflow: hidden; } canvas { @@ -12,16 +13,25 @@ canvas { padding: 5px; color: greenyellow; background: black; - position: absolute; + position: fixed; right: 10px; bottom: 0; width: 20%; - height: 10em; + height: 12em; border: 2px solid darkgray; border-radius: 10px; z-index: 10; } +#slider { + position: absolute; + left: calc(50% - 1.5em); + top: -.2em; + color: lightgray; + cursor: row-resize; + user-select: none; +} + #prompt { position: absolute; bottom: 0; @@ -40,9 +50,9 @@ canvas { #command_history { font-size: 12px; color: greenyellow; - position: absolute; + position: fixed; bottom: 1.5em; - max-height: 20em; + max-height: 11em; width: 100%; overflow-y: visible; overflow-x: hidden; diff --git a/src/main/resources/static/index.html b/src/main/resources/static/index.html index 0167365..da0fa58 100644 --- a/src/main/resources/static/index.html +++ b/src/main/resources/static/index.html @@ -5,9 +5,10 @@ - +
+
@@ -18,7 +19,5 @@ - - \ No newline at end of file diff --git a/src/main/resources/static/js/console.js b/src/main/resources/static/js/console.js index 304fa16..edafa8a 100644 --- a/src/main/resources/static/js/console.js +++ b/src/main/resources/static/js/console.js @@ -3,14 +3,86 @@ const command_history_element = document.getElementById('command_history'); let command_history = ['']; let command_history_index = 0; let token_index = 0; -const bindings = {}; -const state = {}; +const bindings = { + "N": { + is_binding: true, + name: "N", + }, + "t": { + is_binding: true, + name: "t", + }, + "T": { + is_binding: true, + name: "T", + }, + "x": { + is_binding: true, + name: "x", + }, + "y": { + is_binding: true, + name: "y", + }, + "color": { + is_binding: true, + name: "color", + } + +}; +const state = { + "N": 100, + "t": 50, + "T": 1000, + "x": 50, + "y": 50, + color: "red", +}; +// const slider = document.getElementById('slider'); +const console_element = document.getElementById('console'); +let slider_start_Y, slider_start_height; +clear(); + +const fly = function () { + let N = state['N']; + let t = state['t']; + let T = state['T']; + let x = state['x']; + let y = state['y']; + + fetch(`/api/path/${N}/${t}/${T}/${x}/${y}`, { + method: 'GET' + }).then((response) => { + if (response.ok) { + return response.json(); + } else { + throw new Error('Server response wasn\'t OK'); + } + }).then(path => { + const canvasElement = document.getElementById("gridCanvas"); + const canvas = canvasElement.getContext('2d'); + const factor = 1000 / N; + canvas.beginPath(); + canvas.moveTo(7 + path.points[0].x * factor, 2 + path.points[0].y * factor); + for (let i = 1; i < path.points.length; i++) { + canvas.lineTo(8 + path.points[i].x * factor, 5 + path.points[i].y * factor); + } + canvas.strokeStyle = state['color']; + canvas.stroke(); + command_history_element.innerText += `${path.value}\n`; + }).catch((err) => { + console.log('Fetching failed', err); + }); +} + const keywords = { 'true': true, 'false': false, 'pi': Math.PI, 'PI': Math.PI, - 'e': Math.E + 'e': Math.E, + 'fly': fly, + 'clear': clear, } let tokens; @@ -25,12 +97,6 @@ const adjust_input_element_height = function () { } } -// command_input_element.onkeypress = function handle_key_input(event) { -// if (event.key === 'Enter') { -// event.preventDefault(); -// } -// } - command_input_element.onkeyup = function handle_key_input(event) { adjust_input_element_height(); if (event.key === 'c' && event.ctrlKey) { @@ -63,7 +129,7 @@ const handle_enter = function () { adjust_input_element_height(); if (command.length > 0) { - command_history_element.innerText += command + "\n"; + command_history_element.innerText += `>${command}\n`; command_input_element.value = ''; command_history_index = command_history.length; @@ -72,23 +138,14 @@ const handle_enter = function () { let value = evaluate(statement); if (value !== undefined) { - let binding; - if (value.is_binding) { // if it's declaration work with the initializer - binding = value.name; // but we also need the name of the bound variable - value = state[value.name]; // lookup the value for the binding + if (typeof value === 'function') { + value.apply(); + } else { + if (value.is_binding) { + value = state[value.name]; + } + command_history_element.innerText += value.toString() + "\n"; } - - // if (value.is_visual) { - // - // } else { - // if (binding && bindings[binding].previous && bindings[binding].previous.is_visual) { - // label(bindings[binding].previous, '@' + bindings[binding].previous.id); - // } - // } - // if (value.description) { - // value = value.description; - // } - command_history_element.innerText += value.toString() + "\n"; command_history.push(command); command_history_element.scrollTo(0, command_history_element.scrollHeight); } @@ -138,6 +195,8 @@ const evaluate = function (expr) { return logical_and(evaluate(expr.left), evaluate(expr.right)); case token_types.OR: return logical_or(evaluate(expr.left), evaluate(expr.right)); + case token_types.CIRCUMFLEX: + return power(evaluate(expr.left), evaluate(expr.right)); } throw {message: 'illegal binary operator'}; } @@ -211,7 +270,7 @@ function add_sub() { } function mult_div() { - let expr = unary(); + let expr = pow(); while (match([token_types.AND, token_types.SLASH, token_types.STAR, token_types.DOT])) { let operator = previous_token(); @@ -222,6 +281,17 @@ function mult_div() { return expr; } +function pow() { + let expr = unary(); + + if (match([token_types.CIRCUMFLEX])) { + let operator = previous_token(); + let right = unary(); + expr = {type: 'binary', left: expr, operator: operator, right: right}; + } + return expr; +} + function unary() { if (match([token_types.NOT, token_types.MINUS])) { let operator = previous_token(); @@ -376,6 +446,8 @@ const scan = function (command) { return token_types.STAR; case '/': return token_types.SLASH; + case '^': + return token_types.CIRCUMFLEX; case '>': if (expect('=')) { return token_types.GREATER_OR_EQUAL; @@ -460,13 +532,6 @@ const scan = function (command) { return is_digit(char) || char === '.'; // no scientific notation for now } - function parse_reference() { - while (current_char() === '@' || is_digit(current_char())) { - advance(); - } - return command.substring(word_start_index, current_index); - } - function parse_number() { while (is_part_of_number(current_char())) { advance(); @@ -516,6 +581,7 @@ const token_types = { PLUS: {type: 'plus'}, STAR: {type: 'star'}, SLASH: {type: 'slash'}, + CIRCUMFLEX: {type: 'circonflex'}, EQUALS: {type: 'equals'}, EQUALS_EQUALS: {type: 'equals_equals'}, NOT_EQUALS: {type: 'not_equals'}, @@ -563,34 +629,6 @@ const logical_or = function (left, right) { return left || right; } -const create_2d_id_matrix = function () { - return { - data: [[1, 0], [0, 1]], - id: index_sequence++, - is_visual: true, - is_vector: false, // for type comparison - is_matrix: true, - type: 'matrix', // for showing type to user - is_new: true, // to determine view action - visible: true, - toString: function () { - return `matrix@${this.id}`; - }, - hide: function () { - return hide(this); - }, - label: function (text) { - return label(this, text); - }, - show: function () { - return show(this); - }, - equals: function (other) { - return (this.id === other.id || (this.type === other.type && this.data === other.data)); // TODO - }, - row: function (index) { - return this.data[index]; - } - } - +const power = function (left, right) { + return Math.pow(left, right); } \ No newline at end of file diff --git a/src/main/resources/static/js/grid.js b/src/main/resources/static/js/grid.js index 1664a4c..0826bce 100644 --- a/src/main/resources/static/js/grid.js +++ b/src/main/resources/static/js/grid.js @@ -1,32 +1,29 @@ -let canvas = document.getElementById('myCanvas'); -let ctx; -if (canvas.getContext) { - ctx = canvas.getContext('2d'); +let canvasElement = document.getElementById('gridCanvas'); +let canvas = canvasElement.getContext('2d'); - // draw here - ctx.fillStyle = 'green'; - ctx.fillRect(0, 0, 500, 500); -} else { - console.log("Canvas not supported"); -} +function clear() { + canvas.fillStyle = 'black'; + canvas.fillRect(0, 0, 1000, 1000); -fetch('/api/grid/100', { - method: 'GET' // or 'POST' -}).then((response) => { - if (response.ok) { - return response.json(); // Here we're using JSON but you can use other formats such as blob, text etc. - } else { - throw new Error('Server response wasn\'t OK'); - } -}).then((grid) => { - const cell_factor = 500 / grid.size; - ctx.font = `5px Arial`; - ctx.fillStyle = "grey" - for (let r = 0; r < grid.size; r++) { - for (let c = 0; c < grid.size; c++) { - ctx.fillText("" + grid.grid[r][c], 5 + c * cell_factor, r * cell_factor); + fetch('/api/grid/100', { + method: 'GET' + }).then((response) => { + if (response.ok) { + return response.json(); + } else { + throw new Error('Server response wasn\'t OK'); } - } -}).catch((err) => { - console.log('Fetching failed', err); -}); \ No newline at end of file + }).then((grid) => { + const cell_factor = 1000 / grid.size; + canvas.font = `8px Arial`; + canvas.strokeStyle = "green" + canvas.strokeWidth = 1; + for (let r = 0; r < grid.size; r++) { + for (let c = 0; c < grid.size; c++) { + canvas.strokeText("" + grid.grid[r][c], 5 + c * cell_factor, 8 + r * cell_factor); + } + } + }).catch((err) => { + console.log('Fetching failed', err); + }); +} \ No newline at end of file diff --git a/src/main/resources/static/js/parser.js b/src/main/resources/static/js/parser.js deleted file mode 100644 index e69de29..0000000 diff --git a/src/test/java/assessment/algorithm/PathFinderTest.java b/src/test/java/assessment/algorithm/PathFinderTest.java index 81c7216..a6c9b35 100644 --- a/src/test/java/assessment/algorithm/PathFinderTest.java +++ b/src/test/java/assessment/algorithm/PathFinderTest.java @@ -14,7 +14,7 @@ public class PathFinderTest { @Test public void testBestPath100() { Grid grid = Grid.fromFile("grids/100.txt"); - Path path = new OptimalPathFinder().findOptimalPath(grid, 100, 8, 10000, 50, 50); + Path path = new OptimalPathFinder().findOptimalPath(grid, 100, 10, 100, 50, 50); System.out.println(path); }