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.8 KiB

working (level2 solution)

Level 2 solution also works here with the same limitatitons.

{   
    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
        }
}