improvements

This commit is contained in:
Shautvast 2024-11-09 22:40:02 +01:00
parent 5b1584e300
commit 47597143fb
7 changed files with 147 additions and 104 deletions

View file

@ -99,7 +99,6 @@ public class OptimalPathFinder {
paths.add(newPath); paths.add(newPath);
takenPaths.add(newPath); takenPaths.add(newPath);
pointsAdded = true; pointsAdded = true;
// System.out.println("add " + newPath);
} }
} }
} }

View file

@ -1,5 +1,6 @@
body{ body {
background-color: green; background-color: black;
overflow: hidden;
} }
canvas { canvas {
@ -12,16 +13,25 @@ canvas {
padding: 5px; padding: 5px;
color: greenyellow; color: greenyellow;
background: black; background: black;
position: absolute; position: fixed;
right: 10px; right: 10px;
bottom: 0; bottom: 0;
width: 20%; width: 20%;
height: 10em; height: 12em;
border: 2px solid darkgray; border: 2px solid darkgray;
border-radius: 10px; border-radius: 10px;
z-index: 10; z-index: 10;
} }
#slider {
position: absolute;
left: calc(50% - 1.5em);
top: -.2em;
color: lightgray;
cursor: row-resize;
user-select: none;
}
#prompt { #prompt {
position: absolute; position: absolute;
bottom: 0; bottom: 0;
@ -40,9 +50,9 @@ canvas {
#command_history { #command_history {
font-size: 12px; font-size: 12px;
color: greenyellow; color: greenyellow;
position: absolute; position: fixed;
bottom: 1.5em; bottom: 1.5em;
max-height: 20em; max-height: 11em;
width: 100%; width: 100%;
overflow-y: visible; overflow-y: visible;
overflow-x: hidden; overflow-x: hidden;

View file

@ -5,9 +5,10 @@
<link rel="stylesheet" href="css/style.css"> <link rel="stylesheet" href="css/style.css">
</head> </head>
<body> <body>
<canvas id="myCanvas" width="500px" height="500px"></canvas> <canvas id="gridCanvas" width="1000px" height="1000px"></canvas>
<div id="console"> <div id="console">
<!-- <div id="slider">⩵</div>-->
<div id="command_history"> <div id="command_history">
<div id="bottom"></div> <div id="bottom"></div>
</div> </div>
@ -18,7 +19,5 @@
<script src="js/grid.js"></script> <script src="js/grid.js"></script>
<script src="js/console.js"></script> <script src="js/console.js"></script>
<script src="js/scanner.js"></script>
<script src="js/parser.js"></script>
</body> </body>

View file

@ -3,14 +3,86 @@ const command_history_element = document.getElementById('command_history');
let command_history = ['']; let command_history = [''];
let command_history_index = 0; let command_history_index = 0;
let token_index = 0; let token_index = 0;
const bindings = {}; const bindings = {
const state = {}; "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 = { const keywords = {
'true': true, 'true': true,
'false': false, 'false': false,
'pi': Math.PI, 'pi': Math.PI,
'PI': Math.PI, 'PI': Math.PI,
'e': Math.E 'e': Math.E,
'fly': fly,
'clear': clear,
} }
let tokens; 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) { command_input_element.onkeyup = function handle_key_input(event) {
adjust_input_element_height(); adjust_input_element_height();
if (event.key === 'c' && event.ctrlKey) { if (event.key === 'c' && event.ctrlKey) {
@ -63,7 +129,7 @@ const handle_enter = function () {
adjust_input_element_height(); adjust_input_element_height();
if (command.length > 0) { if (command.length > 0) {
command_history_element.innerText += command + "\n"; command_history_element.innerText += `>${command}\n`;
command_input_element.value = ''; command_input_element.value = '';
command_history_index = command_history.length; command_history_index = command_history.length;
@ -72,23 +138,14 @@ const handle_enter = function () {
let value = evaluate(statement); let value = evaluate(statement);
if (value !== undefined) { if (value !== undefined) {
let binding; if (typeof value === 'function') {
if (value.is_binding) { // if it's declaration work with the initializer value.apply();
binding = value.name; // but we also need the name of the bound variable } else {
value = state[value.name]; // lookup the value for the binding 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.push(command);
command_history_element.scrollTo(0, command_history_element.scrollHeight); 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)); return logical_and(evaluate(expr.left), evaluate(expr.right));
case token_types.OR: case token_types.OR:
return logical_or(evaluate(expr.left), evaluate(expr.right)); 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'}; throw {message: 'illegal binary operator'};
} }
@ -211,7 +270,7 @@ function add_sub() {
} }
function mult_div() { function mult_div() {
let expr = unary(); let expr = pow();
while (match([token_types.AND, token_types.SLASH, token_types.STAR, token_types.DOT])) { while (match([token_types.AND, token_types.SLASH, token_types.STAR, token_types.DOT])) {
let operator = previous_token(); let operator = previous_token();
@ -222,6 +281,17 @@ function mult_div() {
return expr; 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() { function unary() {
if (match([token_types.NOT, token_types.MINUS])) { if (match([token_types.NOT, token_types.MINUS])) {
let operator = previous_token(); let operator = previous_token();
@ -376,6 +446,8 @@ const scan = function (command) {
return token_types.STAR; return token_types.STAR;
case '/': case '/':
return token_types.SLASH; return token_types.SLASH;
case '^':
return token_types.CIRCUMFLEX;
case '>': case '>':
if (expect('=')) { if (expect('=')) {
return token_types.GREATER_OR_EQUAL; return token_types.GREATER_OR_EQUAL;
@ -460,13 +532,6 @@ const scan = function (command) {
return is_digit(char) || char === '.'; // no scientific notation for now 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() { function parse_number() {
while (is_part_of_number(current_char())) { while (is_part_of_number(current_char())) {
advance(); advance();
@ -516,6 +581,7 @@ const token_types = {
PLUS: {type: 'plus'}, PLUS: {type: 'plus'},
STAR: {type: 'star'}, STAR: {type: 'star'},
SLASH: {type: 'slash'}, SLASH: {type: 'slash'},
CIRCUMFLEX: {type: 'circonflex'},
EQUALS: {type: 'equals'}, EQUALS: {type: 'equals'},
EQUALS_EQUALS: {type: 'equals_equals'}, EQUALS_EQUALS: {type: 'equals_equals'},
NOT_EQUALS: {type: 'not_equals'}, NOT_EQUALS: {type: 'not_equals'},
@ -563,34 +629,6 @@ const logical_or = function (left, right) {
return left || right; return left || right;
} }
const create_2d_id_matrix = function () { const power = function (left, right) {
return { return Math.pow(left, right);
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];
}
}
} }

View file

@ -1,32 +1,29 @@
let canvas = document.getElementById('myCanvas'); let canvasElement = document.getElementById('gridCanvas');
let ctx; let canvas = canvasElement.getContext('2d');
if (canvas.getContext) {
ctx = canvas.getContext('2d');
// draw here function clear() {
ctx.fillStyle = 'green'; canvas.fillStyle = 'black';
ctx.fillRect(0, 0, 500, 500); canvas.fillRect(0, 0, 1000, 1000);
} else {
console.log("Canvas not supported");
}
fetch('/api/grid/100', { fetch('/api/grid/100', {
method: 'GET' // or 'POST' method: 'GET'
}).then((response) => { }).then((response) => {
if (response.ok) { if (response.ok) {
return response.json(); // Here we're using JSON but you can use other formats such as blob, text etc. return response.json();
} else { } else {
throw new Error('Server response wasn\'t OK'); 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);
} }
} }).then((grid) => {
}).catch((err) => { const cell_factor = 1000 / grid.size;
console.log('Fetching failed', err); 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);
});
}

View file

@ -14,7 +14,7 @@ public class PathFinderTest {
@Test @Test
public void testBestPath100() { public void testBestPath100() {
Grid grid = Grid.fromFile("grids/100.txt"); 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); System.out.println(path);
} }