Elevator Saga - Browser game with js-like programming tasks https://play.elevatorsaga.com
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

6.9 KiB

v0.2 working

It’s not really optimal, as elevator builds it’s destination queue in plain format without thinking about it’s current movement direction.

{   
    init: function(elevators, floors) {
        const DIR_UP = 2;
        const DIR_DOWN = 1;
        const DIR_STOP = 0;

        const MAX_FLOOR = floors.length - 1;    

        var elev_state = [];

        console.clear();

        // Initialize elevator states
        if (elev_state == []) {
            for (var i = 0; i < elevators.length; i++) {
                elev_state.push(DIR_STOP);
            }
        }

        // HELPER functions
        // Command elevator to move to floor
        sendElevator = function(floor, dir) {
            // debug
            for (var i = 0; i < elevators.length; i++) {
                var elevator = elevators[i];

                //console.log("Elevator " + elev + " pressed floors:");
                //console.log(elevator.getPressedFloors());
            }

            // At first trying to find closest empty elevator and send it
            if (!getFreeElevator(floor)) {
                // We didn't found free elevator
                var less_loaded = getLessLoaded()[0];
                if (!less_loaded.destinationQueue.includes(floor)) {
                    less_loaded.destinationQueue.push(floor);
                    //less_loaded.destinationQueue = superSort(less_loaded);
                    less_loaded.checkDestinationQueue();
                    // debug
                    console.log("Added floor " + floor + " to less loaded elevator");
                    console.log("Elevator queue: ");
                    console.log(less_loaded.destinationQueue);
                }
            }
        }

        // Get distance of elevator from floor
        getDistance = function(elevator, floor) {
            return Math.abs(elevator.currentFloor() - floor);
        }

        // Found free elevator closer to required floor and send it there
        getFreeElevator = function(floorRequired = 0) {
            // closest empty elevator
            var best = null;
            // get zero-loaded elevators
            var zero = [];
            for (var elev = 0; elev < elevators.length; elev++) {
                var elevator = elevators[elev];
                if (elevator.loadFactor() == 0) {
                    zero.push(elevator);
                }
            }
            // Found closer elevator from those who had 0 load
            for (var elev = 0; elev < zero.length; elev++) {
                var elevator = zero[elev];

                if (best == null) {
                    best = elevator;
                }
                if (getDistance(elevator, floorRequired) < getDistance(best, floorRequired)) {
                    best = elevator;
                }
            }
            if (best != null) {
                // debug 
                console.log("Empty elevator moving to floor " + floorRequired);

                // If we found one command to move to requested floor
                best.goToFloor(floorRequired);
                return true;
            }
            return false;
        }

        // Super sort
        superSort = function(elevator) {
            var queue = elevator.destinationQueue;
            var currentFloor = elevator.currentFloor;
            queue.sort();

            for (var i = 0; i < queue.length; i++) {
                if (queue[i] > currentFloor) {
                    var idx = i;
                    break;
                }
            }
            var modQueue = queue.slice(idx);
            modQueue = modQueue.concat(queue.slice(0, idx));
            return modQueue;
        } 

        // Get less loaded elevator
        getLessLoaded = function() {
            return elevators.sort( (a,b) => (a.destinationQueue.length - b.destinationQueue.length) );
        }

        // ELEVATOR events
        for (var elev = 0; elev < elevators.length; elev++) {
            var elevator = elevators[elev];

            // Elevator is not doing anything
            elevator.on("idle", function() {
                // When idle move to 0 floor
                // elevator.goToFloor(0);
            });

            // Passenger requested floor
            elevator.on("floor_button_pressed", function(floor) {
                // debug
                //console.log("Elevator " + elev + " pressed floors:");
                //console.log(elevator.getPressedFloors());

                //elevator.goToFloor(floor);
                if (!elevator.destinationQueue.includes(floor)) {
                    elevator.destinationQueue.push(floor);
                    elevator.checkDestinationQueue();
                }
            });

            // Stopped on a particulat floor
            elevator.on("stopped_at_floor", function(floorNum) {
                // debug
                // console.log("Elevator " + elev + " pressed floors:");
                // console.log(elevator.getPressedFloors());
                console.log("Elevator stopped at floor: " + floorNum);

                elev_state[elev] = DIR_STOP;

                // Change direction arrows lights
                var state_up, state_down = false;
                switch (floorNum) {
                    case 0: 
                        state_up = true;
                        state_down = false;
                        break;
                    case MAX_FLOOR: 
                        state_up = false;
                        state_down = true;
                        break;
                    default: 
                        state_up = true;
                        state_down = true;
                        break;
                }
                elevator.goingUpIndicator(state_up);
                elevator.goingDownIndicator(state_down);
            });

            // Passing floor
            elevator.on("passing_floor", function(floor, dir) {
                switch (dir) {
                    case "up": elev_state[elev] = DIR_UP;
                        break;
                    case "down": elev_state[elev] = DIR_DOWN;
                        break;
                }

            });
        }

        // FLOOR events
        for (var fl = 0; fl < floors.length; fl++) {
            var floor = floors[fl];

            // DOWN button pressed on a floor
            floor.on("down_button_pressed", function() {
                // debug
                console.log("Button DOWN pressed on a floor " + this.floorNum());

                sendElevator(this.floorNum(), DIR_DOWN);
            });

            // UP button pressed on a floor
            floor.on("up_button_pressed", function() {
                // debug
                console.log("Button UP pressed on a floor " + this.floorNum());

                sendElevator(this.floorNum(), DIR_UP);
            });
        }
    },
        update: function(dt, elevators, floors) {
            // We normally don't need to do anything here
        }
}