570 lines
14 KiB
JavaScript
570 lines
14 KiB
JavaScript
//Klasy
|
|
class Agent{
|
|
constructor(positionX, positionY, turn){
|
|
this.positionX = positionX;
|
|
this.positionY = positionY;
|
|
this.turn = turn;
|
|
}
|
|
|
|
getParams(){
|
|
let params = {};
|
|
|
|
positionX = this.positionX;
|
|
positionY = this.positionY;
|
|
turn = this.turn;
|
|
|
|
params = {positionX, positionY, turn};
|
|
|
|
return params;
|
|
}
|
|
|
|
turnLeft(){
|
|
if(this.turn == 'Up'){
|
|
this.turn = 'Left';
|
|
}
|
|
else if(this.turn == 'Down'){
|
|
this.turn = 'Right';
|
|
}
|
|
else if(this.turn == 'Left'){
|
|
this.turn = 'Down';
|
|
}
|
|
else if(this.turn == 'Right'){
|
|
this.turn = 'Up'
|
|
}
|
|
}
|
|
|
|
turnRight(){
|
|
if(this.turn == 'Up'){
|
|
this.turn = 'Right';
|
|
}
|
|
else if(this.turn == 'Down'){
|
|
this.turn = 'Left';
|
|
}
|
|
else if(this.turn == 'Left'){
|
|
this.turn = 'Up';
|
|
}
|
|
else if(this.turn == 'Right'){
|
|
this.turn = 'Down'
|
|
}
|
|
}
|
|
|
|
showAgent(){
|
|
if(this.turn === "Up"){
|
|
document.getElementById(this.positionX + "-" + this.positionY).style.backgroundImage = "url('img/Up.png')";
|
|
}
|
|
else if(this.turn === "Down"){
|
|
document.getElementById(this.positionX + "-" + this.positionY).style.backgroundImage = "url('img/Down.png')";
|
|
}
|
|
else if(this.turn === "Right"){
|
|
document.getElementById(this.positionX + "-" + this.positionY).style.backgroundImage = "url('img/Right.png')";
|
|
}
|
|
else if(this.turn === "Left"){
|
|
document.getElementById(this.positionX + "-" + this.positionY).style.backgroundImage = "url('img/Left.png')";
|
|
}
|
|
|
|
}
|
|
|
|
hideAgent(){
|
|
document.getElementById(this.positionX + "-" + this.positionY).style.backgroundImage = "";
|
|
}
|
|
|
|
goForward(){
|
|
this.hideAgent()
|
|
if(this.turn == 'Up'){
|
|
this.positionY += 1;
|
|
}
|
|
else if(this.turn == 'Down'){
|
|
this.positionY -= 1;
|
|
}
|
|
else if(this.turn == 'Left'){
|
|
this.positionX -= 1;
|
|
}
|
|
else if(this.turn == 'Right'){
|
|
this.positionX += 1;
|
|
}
|
|
this.showAgent()
|
|
}
|
|
|
|
goToField(field){
|
|
if(field.yField > this.positionY){
|
|
//pole jest nad agentem
|
|
|
|
}
|
|
if(field.yField < this.positionY){
|
|
//pole jest pod agentem
|
|
|
|
}
|
|
if(field.xField > this.positionX){
|
|
//pole jest na prawo
|
|
|
|
}
|
|
if(field.xField < this.positionX){
|
|
//pole jest na lewo
|
|
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
class Field{
|
|
constructor(x, y, isShelf, isOccupiedByAgent, costOfTravel){
|
|
this.xField = x;
|
|
this.yField = y;
|
|
this.isShelf = isShelf;
|
|
this.isOccupiedByAgent = isOccupiedByAgent;
|
|
this.costOfTravel = costOfTravel;
|
|
this.neighbors = [];
|
|
this.g = 0;
|
|
this.h = 0;
|
|
this.f = 0;
|
|
this.previous = undefined;
|
|
}
|
|
|
|
getParams(){
|
|
let params = {};
|
|
|
|
xField = this.xField;
|
|
yField = this.yField;
|
|
isShelf = this.isShelf;
|
|
isOccupiedByAgent = this.isOccupiedByAgent;
|
|
costOfTravel = this.costOfTravel;
|
|
params = {xField, yField, isShelf, isOccupiedByAgent, costOfTravel}
|
|
|
|
return params;
|
|
}
|
|
|
|
setIsShelf(isShelf){
|
|
this.isShelf = isShelf;
|
|
}
|
|
|
|
getIsShelf(){
|
|
return this.isShelf;
|
|
}
|
|
|
|
setIsOccupiedByAgent(isOccupiedByAgent){
|
|
this.isOccupiedByAgent = isOccupiedByAgent;
|
|
}
|
|
|
|
setCostOfTravel(costOfTravel){
|
|
this.costOfTravel = costOfTravel;
|
|
}
|
|
|
|
setNeighbors(field){
|
|
if(field.isShelf == false){
|
|
this.neighbors.push(field)
|
|
}
|
|
}
|
|
}
|
|
|
|
class Shelf{
|
|
constructor(accessY, accessX, havePlace, box1, box2, box3){
|
|
this.accessX = accessX;
|
|
this.accessY = accessY;
|
|
this.havePlace = true;
|
|
this.box1 = box1;
|
|
this.box2 = box2;
|
|
this.box3 = box3;
|
|
}
|
|
|
|
getParams(){
|
|
let params = {};
|
|
|
|
xField = this.xField;
|
|
yField = this.yField;
|
|
havePlace = this.havePlace;
|
|
box1 = this.box1;
|
|
box2 = this.box2;
|
|
box3 = this.box3;
|
|
params = {xField, yField, havePlace, box1, box2, box3}
|
|
|
|
return params;
|
|
}
|
|
|
|
setbox1(box1){
|
|
this.box1 = box1;
|
|
}
|
|
|
|
setbox2(box1){
|
|
this.box2 = box2;
|
|
}
|
|
|
|
setbox3(box1){
|
|
this.box3 = box3;
|
|
}
|
|
|
|
setHavePlace(havePlace){
|
|
this.havePlace = havePlace;
|
|
}
|
|
}
|
|
|
|
class Candy{
|
|
constructor(type, taste, mark, id){
|
|
this.type = type;
|
|
this.taste = taste;
|
|
this.mark = mark;
|
|
this.id = id;
|
|
}
|
|
|
|
getId(){
|
|
return this.id;
|
|
}
|
|
|
|
}
|
|
|
|
//funkcje
|
|
|
|
function createBoard(rangeX, rangeY){
|
|
const board = [];
|
|
|
|
for(let y = 0; y < rangeY; y++){
|
|
const row = [];
|
|
for(let x = 0; x < rangeX; x++){
|
|
let field = new Field(x, y, false, false, 1);
|
|
row.push(field)
|
|
}
|
|
board.push(row)
|
|
}
|
|
return board
|
|
}
|
|
|
|
function createShelfOnBoard(board){
|
|
//pierwszy poziom
|
|
board[2][2].setIsShelf(true);
|
|
board[3][2].setIsShelf(true);
|
|
|
|
board[2][4].setIsShelf(true);
|
|
board[3][4].setIsShelf(true);
|
|
|
|
board[2][6].setIsShelf(true);
|
|
board[3][6].setIsShelf(true);
|
|
|
|
board[2][8].setIsShelf(true);
|
|
board[3][8].setIsShelf(true);
|
|
|
|
//drugi poziom
|
|
board[5][2].setIsShelf(true);
|
|
board[5][3].setIsShelf(true);
|
|
|
|
board[5][7].setIsShelf(true);
|
|
board[5][8].setIsShelf(true);
|
|
|
|
//trzeci poziom
|
|
board[7][2].setIsShelf(true);
|
|
board[8][2].setIsShelf(true);
|
|
|
|
board[7][4].setIsShelf(true);
|
|
board[8][4].setIsShelf(true);
|
|
|
|
board[7][6].setIsShelf(true);
|
|
board[8][6].setIsShelf(true);
|
|
|
|
board[7][8].setIsShelf(true);
|
|
board[8][8].setIsShelf(true);
|
|
return board
|
|
}
|
|
|
|
function createCostofField(board, rangeX, rangeY){
|
|
let cost;
|
|
let number;
|
|
for(let y = 0; y < rangeY; y++){
|
|
for(let x = 0; x < rangeX; x++){
|
|
number = 0;
|
|
if(y<9 && board[y+1][x].getIsShelf()){
|
|
number = number + 1;
|
|
}
|
|
if(y>0 && board[y-1][x].getIsShelf()){
|
|
number = number + 1;
|
|
}
|
|
if(x<9 && board[y][x+1].getIsShelf()){
|
|
number = number + 1;
|
|
}
|
|
if(x>0 && board[y][x-1].getIsShelf()){
|
|
number = number + 1;
|
|
}
|
|
cost = number*2;
|
|
if(cost==0){
|
|
cost = 1;
|
|
}
|
|
board[y][x].setCostOfTravel(cost);
|
|
}
|
|
}
|
|
return board;
|
|
}
|
|
|
|
function createShelf(){
|
|
const listOfShelf = [];
|
|
|
|
//pierwszy poziom
|
|
let shelf = new Shelf(2, 1, true, 211, 212, 0);
|
|
listOfShelf.push(shelf)
|
|
shelf = new Shelf(3, 1, true, 311, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
|
|
shelf = new Shelf(4, 4, false, 441, 442, 443);
|
|
listOfShelf.push(shelf)
|
|
shelf = new Shelf(1, 4, true, 0, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
|
|
shelf = new Shelf(4, 6, true, 461, 462, 0);
|
|
listOfShelf.push(shelf)
|
|
shelf = new Shelf(1, 6, true, 161, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
|
|
shelf = new Shelf(3, 9, true, 391, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
shelf = new Shelf(2, 9, true, 291, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
|
|
//drugi poziom
|
|
shelf = new Shelf(5, 1, true, 511, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
shelf = new Shelf(5, 4, true, 541, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
|
|
shelf = new Shelf(5, 6, true, 561, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
shelf = new Shelf(5, 9, true, 591, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
|
|
//trzeci poziom
|
|
shelf = new Shelf(7, 1, true, 711, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
shelf = new Shelf(8, 1, true, 811, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
|
|
shelf = new Shelf(6, 4, true, 641, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
shelf = new Shelf(9, 4, true, 941, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
|
|
shelf = new Shelf(6, 6, true, 661, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
shelf = new Shelf(9, 6, true, 961, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
|
|
shelf = new Shelf(7, 9, true, 791, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
shelf = new Shelf(8, 9, true, 891, 0, 0);
|
|
listOfShelf.push(shelf)
|
|
|
|
|
|
return listOfShelf;
|
|
}
|
|
|
|
function showBoard(board){
|
|
for(let y = board.length - 1; y >= 0 ; y--){
|
|
document.getElementById("board").innerHTML += "<div class='row' id='row-" + y + "'> </div>";
|
|
|
|
for(let x = 0; x < board[y].length; x++){
|
|
if(board[y][x].getIsShelf())
|
|
document.getElementById("row-" + y).innerHTML += "<div class='regal2' id=" + x + "-" + y + "> </div>"
|
|
else
|
|
document.getElementById("row-" + y).innerHTML += "<div class='field' id=" + x + "-" + y + ">"+ board[y][x].costOfTravel + "</div>"
|
|
}
|
|
}
|
|
}
|
|
|
|
function getDistance(field, goalField){
|
|
// var a = field.xField - goalField.xField;
|
|
// var b = field.yField - goalField.yField;
|
|
// var c = Math.sqrt(a*a + b*b);
|
|
var d = Math.abs(field.xField - goalField.xField) + Math.abs(field.yField - goalField.yField)
|
|
return d
|
|
}
|
|
|
|
function addNeighbors(board){
|
|
for(var y = 0; y < 10; y++){
|
|
for(var x = 0; x < 10; x++){
|
|
var leftNeigbor, rightNeighbor, topNeighbor, bottomNeighbor;
|
|
if(x > 0){
|
|
leftNeigbor = board[y][x - 1];
|
|
board[y][x].setNeighbors(leftNeigbor);
|
|
}
|
|
if(x < board[y].length - 1){
|
|
rightNeighbor = board[y][x + 1];
|
|
board[y][x].setNeighbors(rightNeighbor);
|
|
}
|
|
if(y > 0){
|
|
bottomNeighbor = board[y - 1][x];
|
|
board[y][x].setNeighbors(bottomNeighbor);
|
|
}
|
|
if(y < board.length - 1){
|
|
topNeighbor = board[y + 1][x];
|
|
board[y][x].setNeighbors(topNeighbor);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// function colorGreen(field){
|
|
// document.getElementById(field.xField + "-" + field.yField).style.backgroundColor = "green";
|
|
// }
|
|
|
|
// function colorRed(field){
|
|
// document.getElementById(field.xField + "-" + field.yField).style.backgroundColor = "red";
|
|
// }
|
|
|
|
// function colorYellow(field){
|
|
// document.getElementById(field.xField + "-" + field.yField).style.backgroundColor = "yellow";
|
|
// }
|
|
|
|
const colorFactory = color => (field, animationFrame) => {
|
|
const delay = animationFrame * 50
|
|
console.log(delay)
|
|
setTimeout(() => {
|
|
document.getElementById(field.xField + "-" + field.yField).style.backgroundColor = color;
|
|
}, delay);
|
|
return ++animationFrame
|
|
}
|
|
|
|
const colorYellow = colorFactory('yellow')
|
|
const colorGreen = colorFactory('green')
|
|
const colorRed = colorFactory('red')
|
|
|
|
// function addNeighborsToOpenSet(set, neigbors){
|
|
// for(x = 0; x < neigbors.length; x++){
|
|
// set.push(neigbors[x]);
|
|
// colorGreen(neigbors[x]);
|
|
// }
|
|
// }
|
|
|
|
function addToClosedSet(set, field){
|
|
set.push(field);
|
|
colorRed(field);
|
|
}
|
|
|
|
|
|
function addToOpenSet(set, field){
|
|
set.push(field);
|
|
colorGreen(field);
|
|
}
|
|
|
|
function calculateFScore(field, goalField){
|
|
let fscore, distanceToGoal, costOfTravel;
|
|
distanceToGoal = getDistance(field, goalField);
|
|
costOfTravel = field.costOfTravel;
|
|
fscore = costOfTravel + distanceToGoal;
|
|
return fscore;
|
|
}
|
|
|
|
function findLowestFScore(openSet, goalField){
|
|
let bestField = openSet[0];
|
|
for(var x = 1; x < openSet.length; x++){
|
|
if(calculateFScore(openSet[x], goalField) < calculateFScore(bestField, goalField)){
|
|
bestField = openSet[x];
|
|
}
|
|
}
|
|
return bestField;
|
|
}
|
|
|
|
function removeFromSet(openSet, promisingField){
|
|
for(var x = openSet.length - 1; x >= 0; x--){
|
|
if(openSet[x] == promisingField){
|
|
openSet.splice(x,1);
|
|
}
|
|
}
|
|
}
|
|
|
|
function aStar(startField, goalField){
|
|
let closedSet = [];
|
|
let openSet = [];
|
|
var path;
|
|
let animationFrame = 0
|
|
|
|
// addToOpenSet(openSet, startField)
|
|
openSet.push(startField);
|
|
colorGreen(startField, animationFrame);
|
|
|
|
while(openSet.length > 0){
|
|
|
|
// let current = findLowestFScore(openSet, goalField);
|
|
let winner = 0;
|
|
for(let i = 0; i < openSet.length; i++){
|
|
if (openSet[i].f < openSet[winner].f){
|
|
winner = i
|
|
}
|
|
}
|
|
|
|
let current = openSet[winner];
|
|
|
|
if(current === goalField){
|
|
path = []
|
|
var temp = current;
|
|
path.push(temp);
|
|
while(temp.previous){
|
|
path.push(temp.previous);
|
|
temp = temp.previous
|
|
}
|
|
console.log("A* COMPLETED");
|
|
|
|
for(var i = 0; i < path.length; i++){
|
|
animationFrame = colorYellow(path[i], animationFrame);
|
|
}
|
|
return path;
|
|
}
|
|
|
|
removeFromSet(openSet, current);
|
|
// addToClosedSet(closedSet, current);
|
|
closedSet.push(current);
|
|
animationFrame = colorRed(current, animationFrame);
|
|
|
|
var neighbors = current.neighbors;
|
|
|
|
for(var i = 0; i < neighbors.length; i++){
|
|
var neighbor = neighbors[i];
|
|
|
|
if(!closedSet.includes(neighbor)){
|
|
var tempG = current.g + neighbor.costOfTravel;
|
|
|
|
if(openSet.includes(neighbor)){
|
|
if(tempG < neighbor.g){
|
|
neighbor.g = tempG;
|
|
}
|
|
} else {
|
|
neighbor.g = tempG;
|
|
// addToOpenSet(openSet, neighbor);
|
|
openSet.push(neighbor);
|
|
animationFrame = colorGreen(neighbor,animationFrame);
|
|
}
|
|
neighbor.h = getDistance(neighbor, goalField);
|
|
neighbor.f = neighbor.g + neighbor.h;
|
|
|
|
neighbor.previous = current;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
function executePath(agent, path){
|
|
|
|
}
|
|
|
|
|
|
let board = createBoard(10,10);
|
|
board = createShelfOnBoard(board);
|
|
board = createCostofField(board, 10, 10);
|
|
let candy = new Candy('zelek', 'truskawkowy', 'Jumbo', 541);
|
|
let shelfs = createShelf();
|
|
let agent = new Agent(0,0, 'Right');
|
|
|
|
addNeighbors(board);
|
|
|
|
function delayedFunction(func, index, time) {
|
|
setTimeout(() => func(), time * index);
|
|
}
|
|
|
|
function start(){
|
|
showBoard(board);
|
|
|
|
// for (let i = 0; i<9; i++) {
|
|
// delayedStep(agent, i);
|
|
// }
|
|
const path = aStar(board[0][0], board[9][9]);
|
|
// agent.showAgent();
|
|
console.log(path.reverse())
|
|
}
|
|
|
|
|
|
|