Skip to content

Instantly share code, notes, and snippets.

@gkucmierz
Created July 16, 2026 21:25
Show Gist options
  • Select an option

  • Save gkucmierz/6dd74f710187868c7b676e3c69f29d01 to your computer and use it in GitHub Desktop.

Select an option

Save gkucmierz/6dd74f710187868c7b676e3c69f29d01 to your computer and use it in GitHub Desktop.
Run this code instantly in your browser: https://instacode.app/gist/6dd74f710187868c7b676e3c69f29d01
{
init: function(elevators, floors) {
// Wykrywamy wyzwania oparte na limicie ruchów (Challenge #6 i #7)
this.clearConditionIsMoves = ["#challenge=6", "#challenge=7"].includes(location.hash);
// Zakres pięter
const minFloorNum = Math.min.apply(null, floors.map(floor => floor.floorNum()));
const maxFloorNum = Math.max.apply(null, floors.map(floor => floor.floorNum()));
// Stan przycisków na piętrach (up/down)
const floorButton = {};
floors.forEach(floor => floorButton[floor.floorNum()] = {up: false, down: false});
// Pobranie pięter, na których wciśnięto przyciski wezwania windy
this.getPushedFloorButtons = () => {
const pushedFloorButtons = [];
for (let floorNum = minFloorNum; floorNum <= maxFloorNum; floorNum++) {
if (floorButton[floorNum].up) {
pushedFloorButtons.push({ floorNum: floorNum, indicator: "up" });
}
if (floorButton[floorNum].down) {
pushedFloorButtons.push({ floorNum: floorNum, indicator: "down" });
}
}
return pushedFloorButtons;
}
// Informacje o tym, dokąd jadą inne windy
this.getOtherElevatorGoFloors = (targetElevator) => {
return elevators
.filter(elevator => elevator != targetElevator)
.map((otherElevator) => {
const otherElevatorGoFloor = {
elevatorNumber: otherElevator.number,
floorNum: otherElevator.destinationQueue[0],
up: otherElevator.goingUpIndicator(),
down: otherElevator.goingDownIndicator()
};
if (otherElevator.destinationQueue.length == 1) {
if (floorButton[otherElevatorGoFloor.floorNum].up
&& !floorButton[otherElevatorGoFloor.floorNum].down) {
otherElevatorGoFloor.up = true;
otherElevatorGoFloor.down = false;
} else if (!floorButton[otherElevatorGoFloor.floorNum].up
&& floorButton[otherElevatorGoFloor.floorNum].down) {
otherElevatorGoFloor.up = false;
otherElevatorGoFloor.down = true;
}
}
return otherElevatorGoFloor;
});
}
// Skierowanie windy do najbliższego wolnego wezwania z piętra
this.goToPressedFloor = (elevator, currentFloorNum) => {
elevator.destinationQueue = [];
elevator.checkDestinationQueue();
const otherElevatorGoFloors = this.getOtherElevatorGoFloors(elevator);
// Filtrujemy zgłoszenia, ignorując te, do których jedzie już inna winda
// (chyba że nasza winda jest o co najmniej 2 piętra bliżej niż tamta)
const gotoChoices = this.getPushedFloorButtons().filter((pushedFloorButton) => {
return !otherElevatorGoFloors.some((otherElevatorGoFloor) => {
const distanceByTargetElevator = Math.abs(pushedFloorButton.floorNum - currentFloorNum)
const distanceByOtherElevator = Math.abs(pushedFloorButton.floorNum - otherElevatorGoFloor.floorNum)
return pushedFloorButton.floorNum == otherElevatorGoFloor.floorNum
&& distanceByOtherElevator < (distanceByTargetElevator + 2)
&& ((pushedFloorButton.indicator == "up" && otherElevatorGoFloor.up)
|| (pushedFloorButton.indicator == "down" && otherElevatorGoFloor.down));
})
});
if (gotoChoices.length == 0) {
return;
}
// Wybieramy najbliższe wezwanie
const nearGotoChoice = gotoChoices.sort((gotoChoice1, gotoChoice2) => {
const diff = Math.abs(gotoChoice1.floorNum - currentFloorNum)
- Math.abs(gotoChoice2.floorNum - currentFloorNum);
if (diff != 0) return diff;
return gotoChoice2.floorNum - gotoChoice1.floorNum;
})[0];
let gotoFloor = nearGotoChoice;
if (nearGotoChoice.floorNum <= currentFloorNum
&& nearGotoChoice.indicator == "up" && elevator.goingUpIndicator()) {
gotoFloor = gotoChoices.find(gotoChoice => {
return gotoChoice.indicator == "up" && gotoChoice.floorNum == (nearGotoChoice.floorNum - 1);
}) || gotoFloor;
} else if (nearGotoChoice.floorNum > currentFloorNum
&& nearGotoChoice.indicator == "down" && elevator.goingDownIndicator()) {
gotoFloor = gotoChoices.find(gotoChoice => {
return gotoChoice.indicator == "down" && gotoChoice.floorNum == (nearGotoChoice.floorNum + 1);
}) || gotoFloor;
}
if (gotoFloor.indicator == "up") {
elevator.goingUpIndicator(true);
elevator.goingDownIndicator(false);
} else {
elevator.goingUpIndicator(false);
elevator.goingDownIndicator(true);
}
elevator.goToFloor(gotoFloor.floorNum);
}
// Znajdowanie wolnej i pustej windy w pobliżu zgłoszenia
this.pickupStoppedNearElevator = (floorNum) => {
return elevators
.filter((elevator) => {
return elevator.destinationQueue.length == 0 && elevator.loadFactor() == 0;
})
.sort((elevator1, elevator2) => {
return Math.abs(elevator1.currentFloor() - floorNum)
- Math.abs(elevator2.currentFloor() - floorNum);
})[0];
}
// Sortowanie i optymalizacja kolejki celów wewnątrz windy (algorytm SCAN)
this.resetDestination = (elevator) => {
const currentFloorNum = elevator.currentFloor();
// Dzielimy piętra na te powyżej i poniżej nas, sortując od najbliższych
const uppers = elevator.getPressedFloors()
.filter(num => num >= currentFloorNum)
.sort((num1, num2) => num1 - num2);
const lowers = elevator.getPressedFloors()
.filter(num => num < currentFloorNum)
.sort((num1, num2) => num1 - num2)
.reverse();
// Ustawienie kierunku
if (elevator.goingUpIndicator() && uppers.length == 0) {
elevator.goingUpIndicator(false);
elevator.goingDownIndicator(true);
} else if (elevator.goingDownIndicator() && lowers.length == 0) {
elevator.goingUpIndicator(true);
elevator.goingDownIndicator(false);
}
if (elevator.goingUpIndicator()) {
elevator.destinationQueue = uppers.concat(lowers);
} else {
elevator.destinationQueue = lowers.concat(uppers);
}
elevator.checkDestinationQueue();
}
// --- Rejestracja zdarzeń na piętrach ---
floors.forEach((floor) => {
const floorNum = floor.floorNum();
floor.on("up_button_pressed", () => {
floorButton[floorNum].up = true;
const stoppedElevator = this.pickupStoppedNearElevator(floorNum);
if (stoppedElevator) {
stoppedElevator.goingUpIndicator(true);
stoppedElevator.goingDownIndicator(false);
stoppedElevator.goToFloor(floorNum);
}
});
floor.on("down_button_pressed", () => {
floorButton[floorNum].down = true;
const stoppedElevator = this.pickupStoppedNearElevator(floorNum);
if (stoppedElevator) {
stoppedElevator.goingUpIndicator(false);
stoppedElevator.goingDownIndicator(true);
stoppedElevator.goToFloor(floorNum);
}
});
});
// --- Rejestracja zdarzeń na windach ---
elevators.forEach((elevator) => {
elevator.number = elevators.indexOf(elevator);
elevator.isCrowded = () => {
return elevator.loadFactor() >= 0.5;
}
elevator.on("stopped_at_floor", (floorNum) => {
if (elevator.destinationQueue.length == 0) {
if (floorButton[floorNum].up && !floorButton[floorNum].down) {
elevator.goingUpIndicator(true);
elevator.goingDownIndicator(false);
} else if (!floorButton[floorNum].up && floorButton[floorNum].down) {
elevator.goingUpIndicator(false);
elevator.goingDownIndicator(true);
}
}
if (elevator.goingUpIndicator()) {
floorButton[floorNum].up = false;
}
if (elevator.goingDownIndicator()) {
floorButton[floorNum].down = false;
}
if (this.clearConditionIsMoves && !elevator.isCrowded()) {
// W wyzwaniu na ruchy: czekaj na ludzi przed ruszeniem
elevator.stop();
elevator.goingUpIndicator(true);
elevator.goingDownIndicator(true);
}
});
elevator.on("passing_floor", (floorNum, direction) => {
if (elevator.loadFactor() == 0) {
this.goToPressedFloor(elevator, floorNum);
return;
}
// Sprawdzamy czy zatrzymać się "po drodze"
const otherElevatorGoFloors = this.getOtherElevatorGoFloors(elevator);
const isOtherElevetorStop = otherElevatorGoFloors.some((elevatorGoFloor) => {
return elevatorGoFloor.floorNum == floorNum
&& ((direction == "up" && elevatorGoFloor.up)
|| (direction == "down" && elevatorGoFloor.down));
});
// Zatrzymujemy się, jeśli ktoś chce jechać w naszą stronę, winda nie jest pełna
// i inna winda już tam nie jedzie
if (floorButton[floorNum][direction] && !elevator.isCrowded() && !isOtherElevetorStop) {
elevator.goToFloor(floorNum, true);
}
});
elevator.on("idle", () => {
if (this.clearConditionIsMoves && !elevator.isCrowded()) {
return;
}
this.goToPressedFloor(elevator, elevator.currentFloor());
});
elevator.on("floor_button_pressed", (floorNum) => {
if (this.clearConditionIsMoves && !elevator.isCrowded()) {
return;
}
this.resetDestination(elevator);
});
});
},
update: function(dt, elevators, floors) {
if (this.clearConditionIsMoves) {
// Regularne wybudzanie pełnych wind w wyzwaniach na ruchy
elevators
.filter(elevator => elevator.isCrowded())
.forEach(elevator => this.resetDestination(elevator));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment