Skip to content

Up to challenge 7 this works fine

frevds edited this page Jan 23, 2015 · 2 revisions
{   
    init: function(elevators, floors)  // hook up events
    {
        // these are the global wish lists that idle elevators choose from (key are floor numbers, values are number of people): 
        var wishListUp = {}, wishListDown = {}; 

        for (var i = 0, l = elevators.length; i < l; i++)
        {
            var elevator = elevators[i];
            // API: goToFloor(n) [enqueues], stop() [clears queue], currentFloor(), 
            //      goingUpIndicator([set]), goingDownIndicator([set]), loadFactor() [0..1], 
            //      destinationQueue[], checkDestinationQueue() [after manual update]

            elevator.on("idle", function()  // elevator destination queue finished
            {
                processWishList();
            }); 

            elevator.on("floor_button_pressed", function(floorNum)  // passenger indicates where to go
            {
                if (this.destinationQueue.filter(function (d) { return d == floorNum; }).length == 0)  // if not already enqueued
                    this.goToFloor(floorNum);  // enqueue
                // note: passengers coming first need to be delivered first (or at least at all)
                //       however, the elevator will check by passing, whether one destination
                //       can be approached before the others since it comes on the way. 
            }); 

            elevator.on("passing_floor", function(floorNum, direction/*"up"/"down"*/)  // if not in destination queue
            {
                updateIndicators(this);  // indicate next destination from here
                // we stop here if the queue contains this destination, 
                // or if a passenger on the global wish list want to go in our direction. 
                // we can only hope that people check where the elevator is going. 
                if (this.destinationQueue.filter(function(d) { return d == floorNum; }).length > 0)
                {
                    this.destinationQueue = this.destinationQueue.filter(function(d) { return d != floorNum; });  // remove from later
                    this.destinationQueue.unshift(floorNum);  // add as immediate next destination
                    this.checkDestinationQueue();  // announce modification
                }
                else if (this.loadFactor() < 1.0)  // if there is some space left
                {
                    switch (getDirection(this))
                    {
                        case 1:  // going up
                            if (wishListUp[floorNum])  // are people waiting to go up from here?
                            {
                                //if ((1.0 - this.loadFactor()) * 10.0 - wishListUp[floorNum] > 0)  // assume capacity for 10 people with regular weight
                                //    delete wishListUp[floorNum];  // mark as visited
                                this.destinationQueue.unshift(floorNum);  // add as immediate next destination
                                this.checkDestinationQueue();  // announce modification
                            }
                            break;
                        case -1: // going down
                            if (wishListDown[floorNum])  // are people waiting to go down from here?
                            {
                                //if ((1.0 - this.loadFactor()) * 10.0 - wishListDown[floorNum] > 0)  // assume capacity for 10 people with regular weight
                                //    delete wishListDown[floorNum];  // mark as visited
                                this.destinationQueue.unshift(floorNum);  // add as immediate next destination
                                this.checkDestinationQueue();  // announce modification
                            }
                            break;
                        case 0:  // final destination
                        default: 
                            break; 
                    }
                }
            }); 

            elevator.on("stopped_at_floor", function(floorNum)  // one destination reached
            {
                processWishList(); 
                updateIndicators(this);  // next direction
            });
        }

        for (var i = 0, l = floors.length; i < l; i++)
        {
            var floor = floors[i];
            // API: floorNum()

            floor.on("up_button_pressed", function()  // somebody wants to go up from a certain floor
            {
                // elevators are choosing their next best destination, 
                // we just enqueue this into the global wish list queue: 
                var f = this.floorNum(); 
                if (wishListUp[f])
                    wishListUp[f]++; 
                else
                    wishListUp[f] = 1;
                processWishList(); 
            }); 

            floor.on("down_button_pressed", function()  // somebody wants to go down from a certain floor
            {
                // elevators are choosing their next best destination, 
                // we just enqueue this into the global wish list queue: 
                var f = this.floorNum();
                if (wishListDown[f])
                    wishListDown[f]++;
                else
                    wishListDown[f] = 1;
                processWishList();
            });
        }


        function processWishList()  // give idle elevators a new destination
        {
            for (var i = 0, l = elevators.length; i < l; i++)  // idle
            {
                var elevator = elevators[i]; 
                if (elevator.destinationQueue.length == 0)
                {
                    var next = chooseFloor(elevator.currentFloor(), true);  // find closest wish
                    if (elevator.currentFloor() != next)
                        elevator.goToFloor(next); 
                }
            }
        }

        function getDirection(elevator)
        {
            if (elevator.destinationQueue.length == 0)
                return 0;  // nowhere
            else if (elevator.currentFloor() < elevator.destinationQueue[0])
                return 1;  // up
            else
                return -1;  // down
        }

        function chooseFloor(currentFloor, dequeue)
        {
            // choose next destination from the global wish lists for up and down, 
            // depending on a) closest distance and b) number of waiting passengers: 
            var wishList = {};  // joined up and down lists with passenger counts
            var floors = [];  // array of distinct floor numbers
            for (var i in wishListUp)
            {
                wishList[i] = wishListUp[i]; 
                floors.push(i); 
            }
            for (var i in wishListDown)
                if (wishList[i])
                    wishList[i] += wishListDown[i];
                else
                {
                    wishList[i] = wishListDown[i];
                    floors.push(i); 
                }
            floors.sort(function(a, b)
                { 
                    var res = Math.abs(currentFloor - a) - Math.abs(currentFloor - b);  // by closeness asc
                    if (res == 0)
                        res = wishList[b] - wishList[a];  // by passengers waiting desc
                    return res; 
                }); 
            if (floors.length == 0)
                return 0;  // nothing to do, go back to base
            var next = floors[0];
            if (dequeue)
            {
                if (wishListUp[next])
                    delete wishListUp[next]; 
                if (wishListDown[next])
                    delete wishListDown[next];
            }
            return next; 
        }

        function updateIndicators(elevator)
        {
return;  // there seems to be a bug if announcing, people do not react ..
            switch (getDirection(elevator))
            {
                case 1:  // up
                    if (!elevator.goingUpIndicator())
                        elevator.goingUpIndicator(true);
                    if (elevator.goingDownIndicator())
                        elevator.goingDownIndicator(false);
                    break; 

                case -1:  // down
                    if (elevator.goingUpIndicator())
                        elevator.goingUpIndicator(false);
                    if (!elevator.goingDownIndicator())
                        elevator.goingDownIndicator(true);
                    break; 

                case 0:  // nowhere
                default: 
                    if (elevator.goingUpIndicator())
                        elevator.goingUpIndicator(false);
                    if (elevator.goingDownIndicator())
                        elevator.goingDownIndicator(false);
                    break; 
            }
        }
    },

    update: function(time, elevators, floors)  // loop during operation, called each frame
    {
    }, 

    vendor: 'frevd'
}
Clone this wiki locally