Update Passengers

PHOTO EMBED

Sat Dec 11 2021 14:11:17 GMT+0000 (Coordinated Universal Time)

Saved by @vincentleoooo #javascript

function updatePassenger(index) {
  index = Number(index);
  let passenger = objects.passengers[index];
  let row = Number(passenger.row);
  let col = Number(passenger.col);
  let state = passenger.state;
  let queueState = passenger.queueState;
  let chosenQueue = Number(passenger.chosenQueue);

  let hasArrived =
    Math.abs(Number(passenger.targetRow) - row) +
      Math.abs(Number(passenger.targetCol) - col) ==
    0;

  switch (state) {
    case "immigration":
      if (queueState == "immigrationQueue" && hasArrived) {
        if (
          col == Number(objects[queueState][chosenQueue].col) + 50 &&
          objects.immigration[chosenQueue].state == "IDLE"
        ) {
          passenger.queueState = "none";
          passenger.targetRow =
            Number(objects.immigration[chosenQueue].row) + 3;
          passenger.targetCol =
            Number(objects.immigration[chosenQueue].col) - 1;
          let newStack =
            Number(objects.immigrationQueue[chosenQueue].stack) - 1;
          objects.immigrationQueue[chosenQueue].stack = newStack;
          objects.immigration[chosenQueue].state = "BUSY";
        } else if (col < Number(objects[queueState][chosenQueue].col) + 50) {
          let filledCol = objects.passengers.filter(function (i) {
            return i.col == col + 1 && i.row == row;
          });

          if (filledCol.length == 0) {
            passenger.targetCol = col + 1;
          }
        }
      } else if (queueState == "none" && hasArrived) {
        if (Math.random() < probImmigration) {
          // TODO Create function callable by the different states.
          // ? Could probably do a recursive function for this.
          objects.immigration[chosenQueue].state = "IDLE";
          let station = Number(passenger.station);
          station += 1;
          let newState = getKeyByValue(positions, station);
          if (newState == undefined) {
            newState = getKeyByValue(positions, station + 1);
            station += 1;
            if (newState == undefined) {
              newState = getKeyByValue(positions, station + 1);
              station += 1;
            } // Final state if nothing else will be "out".
          }

          if (newState == "exiting") {
            passenger.state = "exiting";
            passenger.targetCol = width;
            passenger.targetRow = height / 2;
          } else {
            passenger.state = newState;
            queueState = newState + "Queue";
            passenger.queueState = queueState;

            function chosenQueueRectifier(chosenQueue) {
              //* Recursive function when having mismatched station lengths.
              if (chosenQueue >= objects[queueState].length) {
                chosenQueue -= 1;
                return chosenQueueRectifier(chosenQueue);
              } else {
                return chosenQueue;
              }
            }

            chosenQueue = chosenQueueRectifier(chosenQueue);

            for (let i in objects[queueState]) {
              if (i !== chosenQueue) {
                if (
                  Number(objects[queueState][i].stack) <
                  Number(objects[queueState][chosenQueue].stack)
                ) {
                  chosenQueue = Number(i);
                }
              }
            }

            if (Math.random() < randomChosenQueue) {
              chosenQueue = Math.floor(
                Math.random() * objects[queueState].length
              );
            }

            let stackOverflow = 0;

            if (Number(objects[queueState][chosenQueue].stack) > 50) {
              stackOverflow =
                Number(objects[queueState][chosenQueue].stack) - 50;
            }

            passenger.targetRow =
              Number(objects[queueState][chosenQueue].row) + 3;
            passenger.targetCol =
              Number(objects[queueState][chosenQueue].col) - stackOverflow;
            passenger.station = station;
            passenger.chosenQueue = chosenQueue;
            let newStack = Number(objects[queueState][chosenQueue].stack) + 1;
            objects[queueState][chosenQueue].stack = newStack;
          }
        }
      }
      break;
    case "testing":
      if (queueState == "testingQueue" && hasArrived) {
        if (
          col == Number(objects[queueState][chosenQueue].col) + 50 &&
          objects.testing[chosenQueue].state == "IDLE"
        ) {
          passenger.queueState = "testBox";
          passenger.targetRow = Number(objects.testing[chosenQueue].row) + 3;
          passenger.targetCol = Number(objects.testing[chosenQueue].col) - 1;
          let newStack = Number(objects.testingQueue[chosenQueue].stack) - 1;
          objects.testingQueue[chosenQueue].stack = newStack;
          objects.testing[chosenQueue].state = "BUSY";
        } else if (col < Number(objects[queueState][chosenQueue].col) + 50) {
          let filledCol = objects.passengers.filter(function (i) {
            return i.col == col + 1 && i.row == row;
          });

          if (filledCol.length == 0) {
            passenger.targetCol = col + 1;
          }
        }
      } else if (queueState == "testBox" && hasArrived) {
        if (Math.random() < probTesting) {
          passenger.queueState = "enteringTestBox";
          passenger.targetCol = Number(objects.testingBox[0].col) - 1;
          objects.testing[chosenQueue].state = "IDLE";
        }
      } else if (queueState == "enteringTestBox" && hasArrived) {
        let boxWidth = Number(objects.testingBox[0].width);
        let boxHeight = Number(objects.testingBox[0].height);
        let boxRow = Number(objects.testingBox[0].row);
        let boxCol = Number(objects.testingBox[0].col);
        let newCol;
        let newRow;

        let overlapping = true;
        while (overlapping) {
          let count = 1;
          let randRow = Math.floor(Math.random() * boxHeight);
          let randCol = Math.floor(Math.random() * boxWidth);
          newRow = boxRow + randRow;
          newCol = boxCol + randCol;

          let overlappedList = objects.passengers.filter(function (d) {
            return d.targetRow == newRow && d.targetCol == newCol;
          });

          if (overlappedList.length == 0) {
            overlapping = false;
          }

          // ! DEFINE BEHAVIOUR WHEN BOX IS FULL (UNLIKELY, BUT STILL).
          // * FOR NOW, IF BOX IS FULL, ALLOW OVERLAP.
          if (count > boxWidth * boxHeight) {
            overlapping = false;
          }
        }

        passenger.targetCol = newCol;
        passenger.targetRow = newRow;
        passenger.queueState = "waiting";
      } else if (queueState == "waiting" && hasArrived) {
        passenger.timeWaited = Number(passenger.timeWaited) + 1;
        if (passenger.timeWaited >= testingTime && passenger.covid) {
          passenger.state = "covid";
          passenger.targetRow = 0;
        } else if (passenger.timeWaited >= testingTime) {
          let station = Number(passenger.station);
          station += 1;
          let newState = getKeyByValue(positions, station);
          if (newState == undefined) {
            newState = getKeyByValue(positions, station + 1);
            station += 1;
            if (newState == undefined) {
              newState = getKeyByValue(positions, station + 1);
              station += 1;
            } // Final state if nothing else will be "out".
          }

          if (newState == "exiting") {
            passenger.state = "exiting";
            passenger.targetCol = width;
            passenger.targetRow = height / 2;
          } else {
            passenger.state = newState;
            queueState = newState + "Queue";
            passenger.queueState = queueState;

            function chosenQueueRectifier(chosenQueue) {
              //* Recursive function when having mismatched station lengths.
              if (chosenQueue >= objects[queueState].length) {
                chosenQueue -= 1;
                return chosenQueueRectifier(chosenQueue);
              } else {
                return chosenQueue;
              }
            }

            chosenQueue = chosenQueueRectifier(chosenQueue);

            for (let i in objects[queueState]) {
              if (i !== chosenQueue) {
                if (
                  Number(objects[queueState][i].stack) <
                  Number(objects[queueState][chosenQueue].stack)
                ) {
                  chosenQueue = Number(i);
                }
              }
            }

            if (Math.random() < randomChosenQueue) {
              chosenQueue = Math.floor(
                Math.random() * objects[queueState].length
              );
            }

            let stackOverflow = 0;

            if (Number(objects[queueState][chosenQueue].stack) > 50) {
              stackOverflow =
                Number(objects[queueState][chosenQueue].stack) - 50;
            }

            passenger.targetRow =
              Number(objects[queueState][chosenQueue].row) + 3;
            passenger.targetCol =
              Number(objects[queueState][chosenQueue].col) - stackOverflow;
            passenger.station = station;
            passenger.chosenQueue = chosenQueue;
            let newStack = Number(objects[queueState][chosenQueue].stack) + 1;
            objects[queueState][chosenQueue].stack = newStack;
          }
        }
      }
      break;
    case "baggage":
      if (queueState == "baggageQueue" && hasArrived) {
        if (col == Number(objects[queueState][chosenQueue].col) + 50) {
          let newStack = Number(objects.baggageQueue[chosenQueue].stack) - 1;
          objects.baggageQueue[chosenQueue].stack = newStack;
          passenger.queueState = "gettingBaggage";
          passenger.targetCol = Number(objects.baggage[0].col) - 1;
          // objects.testing[chosenQueue].state = "BUSY";
        } else if (col < Number(objects[queueState][chosenQueue].col) + 50) {
          let filledCol = objects.passengers.filter(function (i) {
            return i.col == col + 1 && i.row == row;
          });

          if (filledCol.length == 0) {
            passenger.targetCol = col + 1;
          }
        }
      } else if (queueState == "gettingBaggage" && hasArrived) {
        let boxWidth = Number(objects.baggage[0].width);
        let boxHeight = Number(objects.baggage[0].height);
        let boxRow = Number(objects.baggage[0].row);
        let boxCol = Number(objects.baggage[0].col);
        let newCol;
        let newRow;

        let overlapping = true;
        while (overlapping) {
          let count = 1;
          let randRow = Math.floor(Math.random() * boxHeight);
          let randCol = Math.floor(Math.random() * boxWidth);
          newRow = boxRow + randRow;
          newCol = boxCol + randCol;

          let overlappedList = objects.passengers.filter(function (d) {
            return d.targetRow == newRow && d.targetCol == newCol;
          });

          if (overlappedList.length == 0) {
            overlapping = false;
          }

          // ! DEFINE BEHAVIOUR WHEN BOX IS FULL (UNLIKELY, BUT STILL).
          // * FOR NOW, IF BOX IS FULL, ALLOW OVERLAP.
          if (count > boxWidth * boxHeight) {
            overlapping = false;
          }
        }

        passenger.targetCol = newCol;
        passenger.targetRow = newRow;
        passenger.queueState = "reachedBaggage";
      } else if (queueState == "reachedBaggage" && hasArrived) {
        if (Math.random() < probFindBaggage) {
          let station = Number(passenger.station);
          station += 1;
          let newState = getKeyByValue(positions, station);
          if (newState == undefined) {
            newState = getKeyByValue(positions, station + 1);
            station += 1;
            if (newState == undefined) {
              newState = getKeyByValue(positions, station + 1);
              station += 1;
            } // Final state if nothing else will be "out".
          }

          if (newState == "exiting") {
            passenger.state = "exiting";
            passenger.targetCol = width;
            passenger.targetRow = height / 2;
          } else {
            passenger.state = newState;
            queueState = newState + "Queue";
            passenger.queueState = queueState;

            function chosenQueueRectifier(chosenQueue) {
              //* Recursive function when having mismatched station lengths.
              if (chosenQueue >= objects[queueState].length) {
                chosenQueue -= 1;
                return chosenQueueRectifier(chosenQueue);
              } else {
                return chosenQueue;
              }
            }

            chosenQueue = chosenQueueRectifier(chosenQueue);

            for (let i in objects[queueState]) {
              if (i !== chosenQueue) {
                if (
                  Number(objects[queueState][i].stack) <
                  Number(objects[queueState][chosenQueue].stack)
                ) {
                  chosenQueue = Number(i);
                }
              }
            }

            if (Math.random() < randomChosenQueue) {
              chosenQueue = Math.floor(
                Math.random() * objects[queueState].length
              );
            }

            let stackOverflow = 0;

            if (Number(objects[queueState][chosenQueue].stack) > 50) {
              stackOverflow =
                Number(objects[queueState][chosenQueue].stack) - 50;
            }

            passenger.targetRow =
              Number(objects[queueState][chosenQueue].row) + 3;
            passenger.targetCol =
              Number(objects[queueState][chosenQueue].col) - stackOverflow;
            passenger.station = station;
            passenger.chosenQueue = chosenQueue;
            let newStack = Number(objects[queueState][chosenQueue].stack) + 1;
            objects[queueState][chosenQueue].stack = newStack;
          }
        } else {
          passenger.queueState = "gettingBaggage";
          hasArrived = true;
        }
      }
      break;
    case "exiting":
      if (hasArrived) {
        passenger.state = "out";
        exitedPassengers += 1;
        document.getElementById("numExited").innerHTML =
          "Number of exited passengers: " + exitedPassengers + ".";
        listTimeToClear.push(Number(passenger.timeTaken));
        newAvg =
          listTimeToClear.reduce((a, b) => a + b) / listTimeToClear.length;
        listMeanTimeToClear.push(newAvg);
        let overallAvg;
        if (listSimulationMeanRunTime.length > 0) {
          overallAvg =
            listSimulationMeanRunTime[listSimulationMeanRunTime.length - 1];
          var overallStdDev = Math.sqrt(
            listSimulationRunTime
              .map((x) => Math.pow(x - overallAvg, 2))
              .reduce((a, b) => a + b) / listSimulationRunTime.length
          );
        } else {
          overallAvg = 0;
          var overallStdDev = 0;
        }
        document.getElementById("aveAll").innerHTML =
          "Average time taken by a passenger: " +
          newAvg.toFixed(2) +
          ". Average time taken for " +
          passengerCount +
          " passenger(s): " +
          overallAvg.toFixed(2) +
          " over " +
          simulationsRan +
          " simulation(s) with a standard deviation of " +
          overallStdDev.toFixed(2) +
          ".";
        if (isRunning == true) {
          Plotly.extendTraces("tester", { y: [[getData1()]] }, [0]);
          cnt++;
          if (cnt > limit) {
            Plotly.relayout("tester", {
              xaxis: {
                range: [cnt - limit, cnt],
              },
            });
          }
        }
      }
      break;
    case "covid":
      if (hasArrived) {
        passenger.state = "exiting";
      }
  }

  passenger.timeTaken = Number(passenger.timeTaken) + 1;

  let targetRow = Number(passenger.targetRow);
  let targetCol = Number(passenger.targetCol);
  // compute the distance to the target destination
  let rowsToGo = targetRow - row;
  let colsToGo = targetCol - col;
  // set the speed
  let cellsPerStep = 1;
  // compute the cell to move to
  let newRow =
    row + Math.min(Math.abs(rowsToGo), cellsPerStep) * Math.sign(rowsToGo);
  let newCol =
    col + Math.min(Math.abs(colsToGo), cellsPerStep) * Math.sign(colsToGo);
  // update the location of the passenger
  passenger.row = newRow;
  passenger.col = newCol;
}
content_copyCOPY