mapToJson
This commit is contained in:
parent
b97c4ba4b1
commit
0258fbb525
17
.vscode/launch.json
vendored
Normal file
17
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
|
||||
|
||||
{
|
||||
"type": "pwa-chrome",
|
||||
"request": "launch",
|
||||
"name": "Launch Chrome against localhost",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
}
|
||||
]
|
||||
}
|
13
src/modules/agent.js
Normal file
13
src/modules/agent.js
Normal file
@ -0,0 +1,13 @@
|
||||
class Agent extends AgentController {
|
||||
constructor(canvas) {
|
||||
super(canvas);
|
||||
|
||||
let { x, y } = Grid.instance.randomPlace();
|
||||
this.moveTo(x, y);
|
||||
|
||||
this.onDestinationReached(() => {
|
||||
let { x, y } = Grid.instance.randomPlace();
|
||||
this.moveTo(x, y);
|
||||
})
|
||||
}
|
||||
}
|
146
src/modules/agentController.js
Normal file
146
src/modules/agentController.js
Normal file
@ -0,0 +1,146 @@
|
||||
class AgentController {
|
||||
constructor(canvas) {
|
||||
this.ctx = canvas.getContext('2d');
|
||||
this.events = {
|
||||
'ON_DESTINATION_REACHED': [],
|
||||
};
|
||||
|
||||
this.setCanvasSize(canvas);
|
||||
|
||||
this.position = { x: 6, y: 0 };
|
||||
|
||||
this.update();
|
||||
}
|
||||
|
||||
setCanvasSize (canvas) {
|
||||
canvas.width = 2000;
|
||||
canvas.height = 900;
|
||||
}
|
||||
|
||||
update() {
|
||||
this.clearCanvas();
|
||||
if (this.currentPath) {
|
||||
this.drawPath(this.currentPath);
|
||||
this.updateAgentPosition();
|
||||
}
|
||||
this.drawAgent();
|
||||
|
||||
requestAnimationFrame(this.update.bind(this));
|
||||
}
|
||||
|
||||
updateAgentPosition() {
|
||||
const speed = 30;
|
||||
if (!this.currentPathIndex) {
|
||||
this.currentPathIndex = 0;
|
||||
}
|
||||
|
||||
let nearestPoint = this.currentPath[this.currentPathIndex];
|
||||
|
||||
if (nearestPoint) {
|
||||
this.position = {
|
||||
x: this.position.x + (Math.sign(nearestPoint.x - this.position.x)/speed),
|
||||
y: this.position.y + (Math.sign(nearestPoint.y - this.position.y)/speed)
|
||||
}
|
||||
if (Math.abs(nearestPoint.x - this.position.x) < 0.001 && Math.abs(nearestPoint.y - this.position.y) < 0.001) {
|
||||
nearestPoint = this.currentPath[++this.currentPathIndex];
|
||||
if (!nearestPoint) {
|
||||
this.position = {
|
||||
x: Math.round(this.position.x),
|
||||
y: Math.round(this.position.y)
|
||||
}
|
||||
this.currentPath = [];
|
||||
this.currentPathIndex = 0;
|
||||
this.events.ON_DESTINATION_REACHED.forEach(func => func());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
moveTo(x, y) {
|
||||
this.currentPath = this.findPathTo(x, y, this.position.x, this.position.y);
|
||||
}
|
||||
|
||||
drawPath(path) {
|
||||
for(let i = 0; i < path.length - 1; i++) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.strokeWidth = 5;
|
||||
this.ctx.strokeStyle = 'red';
|
||||
this.ctx.moveTo(path[i].x * 100 + 50, path[i].y * 100 + 50);
|
||||
this.ctx.lineTo(path[i + 1].x * 100 + 50, path[i + 1].y * 100 + 50);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
drawAgent() {
|
||||
const {x, y} = this.position;
|
||||
const offset = 5;
|
||||
this.ctx.clearRect((x * 100) + (offset), (y * 100) + (offset), 100 - (offset * 2), 100 - (offset * 2));
|
||||
this.roundRect((x * 100) + (offset), (y * 100) + (offset), 100 - (offset * 2), 100 - (offset * 2));
|
||||
}
|
||||
|
||||
findPathTo(dx, dy, sx, sy) {
|
||||
const grid = JSON.parse(JSON.stringify(Grid.instance.grid));
|
||||
const queue = [];
|
||||
const lastPoint = [];
|
||||
|
||||
if (grid[dx][dy] === GRID_FIELD_TYPE.SHELF) {
|
||||
if(grid[dx][dy + 1] === GRID_FIELD_TYPE.PATH) {
|
||||
lastPoint.push({ x: dx, y: dy, options: { isShelf: true } });
|
||||
dy++;
|
||||
} else if(grid[dx][dy - 1] === GRID_FIELD_TYPE.PATH) {
|
||||
lastPoint.push({ x: dx, y: dy, options: { isShelf: true } });
|
||||
dy--;
|
||||
}
|
||||
}
|
||||
|
||||
queue.push({ x: sx, y: sy, path: [] });
|
||||
|
||||
while(queue.length) {
|
||||
const { x, y, path } = queue.shift();
|
||||
path.push({ x, y });
|
||||
|
||||
if (x === dx && y === dy) {
|
||||
return [...path, ...lastPoint];
|
||||
}
|
||||
if (grid[x][y - 1] === GRID_FIELD_TYPE.PATH) {
|
||||
queue.push({ x, y: y - 1, path: [...path] });
|
||||
}
|
||||
if (grid[x][y + 1] === GRID_FIELD_TYPE.PATH) {
|
||||
queue.push({ x, y: y + 1, path: [...path] });
|
||||
}
|
||||
if (grid[x - 1] && grid[x - 1][y] === GRID_FIELD_TYPE.PATH) {
|
||||
queue.push({ x: x - 1, y, path: [...path] });
|
||||
}
|
||||
if (grid[x + 1] && grid[x + 1][y] === GRID_FIELD_TYPE.PATH) {
|
||||
queue.push({ x: x + 1, y, path: [...path] });
|
||||
}
|
||||
|
||||
grid[x][y] = -1;
|
||||
}
|
||||
}
|
||||
|
||||
onDestinationReached(func) {
|
||||
this.events.ON_DESTINATION_REACHED.push(func);
|
||||
}
|
||||
|
||||
clearCanvas() {
|
||||
this.ctx.clearRect(0, 0, 2000, 900);
|
||||
}
|
||||
|
||||
roundRect(x, y, w, h, r = 20) {
|
||||
this.ctx.lineWidth = 5;
|
||||
this.ctx.strokeStyle = 'red';
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x + r, y);
|
||||
this.ctx.lineTo(x + w - r, y);
|
||||
this.ctx.quadraticCurveTo(x + w, y, x + w, y + r);
|
||||
this.ctx.lineTo(x + w, y + h - r);
|
||||
this.ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
|
||||
this.ctx.lineTo(x + r, y + h);
|
||||
this.ctx.quadraticCurveTo(x, y + h, x, y + h - r);
|
||||
this.ctx.lineTo(x, y + r);
|
||||
this.ctx.quadraticCurveTo(x, y, x + r, y);
|
||||
this.ctx.closePath();
|
||||
this.ctx.stroke();
|
||||
}
|
||||
}
|
45
src/modules/floor.js
Normal file
45
src/modules/floor.js
Normal file
@ -0,0 +1,45 @@
|
||||
class Floor {
|
||||
constructor(canvas) {
|
||||
this.ctx = canvas.getContext('2d');
|
||||
this.setCanvasSize(canvas);
|
||||
this.drawFloor();
|
||||
}
|
||||
|
||||
setCanvasSize (canvas) {
|
||||
canvas.width = 2000;
|
||||
canvas.height = 900;
|
||||
}
|
||||
|
||||
drawFloor() {
|
||||
let tileWidth = 50;
|
||||
let tileHeight = 50;
|
||||
|
||||
for (let x = 0; x < 2000; x += tileWidth) {
|
||||
for (let y = 0; y < 900; y += tileHeight) {
|
||||
this.tile(x, y, tileWidth, tileHeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tile(x, y, w, h) {
|
||||
this.ctx.strokeStyle = '#202020';
|
||||
this.ctx.strokeRect(x, y, w, h);
|
||||
this.roundRect(x, y, w, h);
|
||||
}
|
||||
|
||||
roundRect( x, y, w, h, r = 20) {
|
||||
this.ctx.strokeStyle = '#202020';
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x + r, y);
|
||||
this.ctx.lineTo(x + w - r, y);
|
||||
this.ctx.quadraticCurveTo(x + w, y, x + w, y + r);
|
||||
this.ctx.lineTo(x + w, y + h - r);
|
||||
this.ctx.quadraticCurveTo(x + w, y + h, x + w - r, y + h);
|
||||
this.ctx.lineTo(x + r, y + h);
|
||||
this.ctx.quadraticCurveTo(x, y + h, x, y + h - r);
|
||||
this.ctx.lineTo(x, y + r);
|
||||
this.ctx.quadraticCurveTo(x, y, x + r, y);
|
||||
this.ctx.closePath();
|
||||
this.ctx.stroke();
|
||||
}
|
||||
}
|
171
src/modules/grid.js
Normal file
171
src/modules/grid.js
Normal file
@ -0,0 +1,171 @@
|
||||
const GRID_FIELD_TYPE = Object.freeze({
|
||||
PATH: 0,
|
||||
SHELF: 1,
|
||||
STORAGE: 2
|
||||
});
|
||||
|
||||
class Grid {
|
||||
static instance;
|
||||
|
||||
constructor(canvas) {
|
||||
this.grid = [[]];
|
||||
this.ctx;
|
||||
|
||||
this.ctx = canvas.getContext('2d');
|
||||
|
||||
this.setCanvasSize(canvas);
|
||||
this.processGrid();
|
||||
this.drawShelfs();
|
||||
this.drawStorages();
|
||||
|
||||
Grid.instance = this;
|
||||
}
|
||||
|
||||
getGrid () {
|
||||
return this.grid;
|
||||
}
|
||||
|
||||
setCanvasSize (canvas) {
|
||||
canvas.width = 2000;
|
||||
canvas.height = 900;
|
||||
}
|
||||
|
||||
processGrid () {
|
||||
const fact = (a, value = GRID_FIELD_TYPE.SHELF) => Array(a).fill(value, 0, a);
|
||||
const cartesian = (arr1, arr2) => arr1.map(a => (a && arr2) || fact(arr2.length, 0));
|
||||
|
||||
this.grid = cartesian(
|
||||
[...fact(6), GRID_FIELD_TYPE.PATH, ...fact(6), GRID_FIELD_TYPE.PATH, ...fact(6)],
|
||||
[...fact(1), GRID_FIELD_TYPE.PATH, ...fact(2), GRID_FIELD_TYPE.PATH, ...fact(2), GRID_FIELD_TYPE.PATH]
|
||||
);
|
||||
|
||||
const lastLine = [...fact(6), GRID_FIELD_TYPE.PATH, ...fact(6, GRID_FIELD_TYPE.STORAGE), GRID_FIELD_TYPE.PATH, ...fact(6)];
|
||||
for (let i = 0; i < 20; i++) {
|
||||
this.grid[i] = [...this.grid[i], lastLine[i]];
|
||||
}
|
||||
}
|
||||
|
||||
drawShelfs () {
|
||||
for (let [x, line] of this.grid.entries()) {
|
||||
for (let [y, type] of line.entries()) {
|
||||
if (type === GRID_FIELD_TYPE.SHELF) {
|
||||
this.shelf(x * 100, y * 100, 100, 100);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
randomPlace() {
|
||||
const x = Math.floor(Math.random() * this.grid.length);
|
||||
const y = Math.floor(Math.random() * this.grid[0].length);
|
||||
const rand = this.grid[x][y];
|
||||
if (rand === GRID_FIELD_TYPE.SHELF || rand === GRID_FIELD_TYPE.PATH) {
|
||||
return { x, y };
|
||||
}
|
||||
return this.randomPlace();
|
||||
}
|
||||
|
||||
drawStorages () {
|
||||
let isFirstOfType = true;
|
||||
let isLastOfType = false;
|
||||
|
||||
let firstX;
|
||||
for (let [x, line] of this.grid.entries()) {
|
||||
for (let [y, type] of line.entries()) {
|
||||
if (type === GRID_FIELD_TYPE.STORAGE) {
|
||||
if (this.grid[x + 1] && this.grid[x + 1][y] !== GRID_FIELD_TYPE.STORAGE) {
|
||||
isLastOfType = true;
|
||||
}
|
||||
|
||||
if (isFirstOfType) {
|
||||
isFirstOfType = false;
|
||||
firstX = x;
|
||||
this.storage(x * 100, y * 100, 100, 100, true, false, true, true);
|
||||
} else if (isLastOfType) {
|
||||
isLastOfType = false;
|
||||
isFirstOfType = true;
|
||||
this.storage(x * 100, y * 100, 100, 100, true, true, true, false);
|
||||
this.storeLabel(firstX * 100, y * 100, (x - firstX + 1) * 100, 100);
|
||||
} else {
|
||||
this.storage(x * 100, y * 100, 100, 100, true, false, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
storeLabel(x, y, w, h) {
|
||||
let fontSize = 40;
|
||||
this.ctx.font = `${fontSize}px Montserrat`;
|
||||
this.ctx.textAlign = "center";
|
||||
this.ctx.fillStyle = 'yellow';
|
||||
this.ctx.fillText("STORE", x + (w/2), y + (h/2) + 15);
|
||||
}
|
||||
|
||||
shelf (x, y, w, h) {
|
||||
this.ctx.strokeStyle = '#ffffff';
|
||||
this.ctx.lineWidth = 5;
|
||||
this.ctx.strokeRect(x, y, w, h);
|
||||
this.drawFixIfOnEdge(x, y, w, h);
|
||||
}
|
||||
|
||||
storage (x, y, w, h, hasTop, hasRight, hasBottom, hasLeft) {
|
||||
this.ctx.strokeStyle = '#ffff00';
|
||||
this.ctx.lineWidth = 5;
|
||||
if (hasTop) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x, y);
|
||||
this.ctx.lineTo(x + w, y);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
if (hasRight) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x + w, y);
|
||||
this.ctx.lineTo(x + w, y + h);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
if (hasBottom) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x, y + h);
|
||||
this.ctx.lineTo(x + w, y + h);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
if (hasLeft) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x, y);
|
||||
this.ctx.lineTo(x, y + h);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
this.drawFixIfOnEdge(x, y, w, h);
|
||||
}
|
||||
|
||||
drawFixIfOnEdge(x, y, w, h) {
|
||||
const offsetFix = 2;
|
||||
|
||||
if (x === 0) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x + offsetFix, y);
|
||||
this.ctx.lineTo(x + offsetFix, y + h);
|
||||
this.ctx.stroke();
|
||||
} else if (x + w === 2000) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x + w - offsetFix, y);
|
||||
this.ctx.lineTo(x + w - offsetFix, y + h);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
|
||||
if (y === 0) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x, y + offsetFix);
|
||||
this.ctx.lineTo(x + w, y + offsetFix);
|
||||
this.ctx.stroke();
|
||||
} else if (y + h === 900) {
|
||||
this.ctx.beginPath();
|
||||
this.ctx.moveTo(x, y + h - offsetFix);
|
||||
this.ctx.lineTo(x + w, y + h - offsetFix);
|
||||
this.ctx.stroke();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
7
src/modules/log.js
Normal file
7
src/modules/log.js
Normal file
@ -0,0 +1,7 @@
|
||||
class log {
|
||||
|
||||
}
|
||||
|
||||
function add (str) {
|
||||
return str;
|
||||
}
|
94
src/modules/products.js
Normal file
94
src/modules/products.js
Normal file
@ -0,0 +1,94 @@
|
||||
class Products {
|
||||
|
||||
constructor(canvas){
|
||||
|
||||
this.gridProducts = [
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i'],
|
||||
['a','b', 'c', 'd', 'e', 'f', 'g', 'h', 'i']
|
||||
];
|
||||
this.ctx = canvas.getContext('2d');
|
||||
this.setCanvasSize(canvas);
|
||||
this.update();
|
||||
|
||||
}
|
||||
|
||||
setCanvasSize (canvas) {
|
||||
canvas.width = 2000;
|
||||
canvas.height = 900;
|
||||
}
|
||||
|
||||
update(){
|
||||
this.clearCanvas();
|
||||
this.drawProducts();
|
||||
}
|
||||
|
||||
|
||||
|
||||
drawProducts () {
|
||||
for (let [x, line] of Grid.instance.grid.entries()) {
|
||||
for (let [y, type] of line.entries()) {
|
||||
if (type === GRID_FIELD_TYPE.SHELF) {
|
||||
let v =this.value(x * 100, y * 100);
|
||||
this.product(x * 100, y * 100, v, x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
value (x,y){
|
||||
let fontSize = 20;
|
||||
this.ctx.font = `${fontSize}px Montserrat`;
|
||||
this.ctx.textAlign = "left";
|
||||
this.ctx.fillStyle = 'white';
|
||||
let number = Math.floor(Math.random() * (50 - 0 + 1)) + 0;
|
||||
this.ctx.fillText(number, x+10, y+90);
|
||||
return number;
|
||||
}
|
||||
|
||||
product(x, y, v, productsKey, productsValue){
|
||||
let fontSize = 40;
|
||||
this.ctx.font = `${fontSize}px Montserrat`;
|
||||
this.ctx.textAlign = "center";
|
||||
if (v <= 10){
|
||||
this.ctx.fillStyle = '#ff0000';
|
||||
}
|
||||
else if(v <= 25){
|
||||
this.ctx.fillStyle = '#ffe700';
|
||||
}
|
||||
else {
|
||||
this.ctx.fillStyle = '#74ee15';
|
||||
}
|
||||
let productsColumn = this.gridProducts[productsKey];
|
||||
let prdct = productsColumn[productsValue];
|
||||
this.ctx.fillText(prdct, x+50, y+60);
|
||||
}
|
||||
|
||||
|
||||
changeValue(xFirst, yFirst, xSecond, ySecond){
|
||||
|
||||
}
|
||||
|
||||
clearCanvas() {
|
||||
this.ctx.clearRect(0, 0, 2000, 900);
|
||||
}
|
||||
|
||||
}
|
@ -5,7 +5,7 @@
|
||||
* @param {...any[]} rows
|
||||
* @returns
|
||||
*/
|
||||
function fromTable(header, ...rows) {
|
||||
function fromTable(header, ...rows) {
|
||||
function tupleToRecord(names, array) {
|
||||
return names.reduce((p, v, i) => ({ ...p, [v]: array[i] }), {})
|
||||
}
|
||||
@ -64,6 +64,12 @@ function randomFromSet(set) {
|
||||
unreachable();
|
||||
}
|
||||
|
||||
function mapToJson(map) {
|
||||
return JSON.stringify([...map]);
|
||||
}
|
||||
function jsonToMap(jsonStr) {
|
||||
return new Map(JSON.parse(jsonStr));
|
||||
}
|
||||
|
||||
function nice(v) { return `${(v * 100).toFixed(1)}%` }
|
||||
|
||||
@ -75,7 +81,9 @@ async function requestJSONCached(url, params = {}) {
|
||||
const response = await fetch(url, params);
|
||||
const json = await response.json();
|
||||
requestJSONCached.cache.set(key, json);
|
||||
const cache = mapToJson(requestJSONCached.cache);
|
||||
localStorage.setItem("cache", cache);
|
||||
return json;
|
||||
}
|
||||
|
||||
requestJSONCached.cache = new Map();
|
||||
requestJSONCached.cache = jsonToMap(localStorage.getItem("cache"));
|
||||
|
Loading…
Reference in New Issue
Block a user