Skip to content
Snippets Groups Projects
Select Git revision
  • dfb5090f2e31e4e33b9032ed9666bcb693afea27
  • master default protected
2 results

Block.cpython-36.pyc

Blame
  • Robot.java 7.29 KiB
    package automail;
    
    import exceptions.ExcessiveDeliveryException;
    import exceptions.ItemTooHeavyException;
    import simulation.Building;
    import simulation.Clock;
    import simulation.IMailDelivery;
    
    /**
     * The robot delivers mail!
     */
    public class Robot {
    	
        static public final int INDIVIDUAL_MAX_WEIGHT = 2000;
    
        /*Number of activity units associated with each activity*/
        static private final double MOVEMENT_ACTIVITY_UNITS = 5;
        static private final double LOOKUP_ACTIVITY_UNITS = 0.1;
        
        IMailDelivery delivery;
        protected final String id;
        /** Possible states the robot can be in */
        public enum RobotState { DELIVERING, WAITING, RETURNING }
        public RobotState current_state;
        private int current_floor;
        private int destination_floor;
        private MailPool mailPool;
        private boolean receivedDispatch;
        
        private MailItem deliveryItem = null;
        private MailItem tube = null;
        
        private int deliveryCounter;
        
    
        /**
         * Initiates the robot's location at the start to be at the mailroom
         * also set it to be waiting for mail.
         * @param behaviour governs selection of mail items for delivery and behaviour on priority arrivals
         * @param delivery governs the final delivery
         * @param mailPool is the source of mail items
         */
        public Robot(IMailDelivery delivery, MailPool mailPool, int number){
        	this.id = "R" + number;
            // current_state = RobotState.WAITING;
        	current_state = RobotState.RETURNING;
            current_floor = Building.MAILROOM_LOCATION;
            this.delivery = delivery;
            this.mailPool = mailPool;
            this.receivedDispatch = false;
            this.deliveryCounter = 0;
            
            
        }
        
        /**
         * This is called when a robot is assigned the mail items and ready to dispatch for the delivery 
         */
        public void dispatch() {
        	receivedDispatch = true;
        }
    
        /**
         * This is called on every time step
         * @throws ExcessiveDeliveryException if robot delivers more than the capacity of the tube without refilling
         */
        public void operate() throws ExcessiveDeliveryException {   
        	switch(current_state) {
        		/** This state is triggered when the robot is returning to the mailroom after a delivery */
        		case RETURNING:
        			/** If its current position is at the mailroom, then the robot should change state */
                    if(current_floor == Building.MAILROOM_LOCATION){
                    	if (tube != null) {
                    		mailPool.addToPool(tube);
                            System.out.printf("T: %3d > old addToPool [%s]%n", Clock.Time(), tube.toString());
                            tube = null;
                    	}
            			/** Tell the sorter the robot is ready */
            			mailPool.registerWaiting(this);
                    	changeState(RobotState.WAITING);
                    } else {
                    	/** If the robot is not at the mailroom floor yet, then move towards it! */
                        moveTowards(Building.MAILROOM_LOCATION);
                    	break;
                    }
        		case WAITING:
                    /** If the StorageTube is ready and the Robot is waiting in the mailroom then start the delivery */
                    if(!isEmpty() && receivedDispatch){
                    	receivedDispatch = false;
                    	deliveryCounter = 0; // reset delivery counter
                    	setDestination();
                    	changeState(RobotState.DELIVERING);
                    }
                    break;
        		case DELIVERING:
        			if(current_floor == destination_floor){ // If already here drop off either way
        				
        				/*add activity units for the delivery*/
        				deliveryItem.addActivityUnits(LOOKUP_ACTIVITY_UNITS);
        				
        				/* set item service fee */
        				deliveryItem.setServiceFee(delivery.getServiceFee(current_floor));
        				
        				// TODO - deliveryItem calls charge calculator
        				// TODO - deliveryItem increment stats in charge calculator deliveryItem.updateStats()
        				
                        /** Delivery complete, report this to the simulator! */
                        delivery.deliver(deliveryItem);
                        deliveryItem = null;
                        deliveryCounter++;
                        if(deliveryCounter > 2){  // Implies a simulation bug
                        	throw new ExcessiveDeliveryException();
                        }
                        /** Check if want to return, i.e. if there is no item in the tube*/
                        if(tube == null){
                        	changeState(RobotState.RETURNING);
                        }
                        else{
                            /** If there is another item, set the robot's route to the location to deliver the item */
                            deliveryItem = tube;
                            tube = null;
                            setDestination();
                            changeState(RobotState.DELIVERING);
                        }
        			} else {
    	        		/** The robot is not at the destination yet, move towards it! */
    	                moveTowards(destination_floor);
    	                
    	                /*Increment activity units for items being carried*/
                        if (deliveryItem != null) {
                        	deliveryItem.addActivityUnits(MOVEMENT_ACTIVITY_UNITS);
                        }
                        if (tube != null) {
                        	tube.addActivityUnits(MOVEMENT_ACTIVITY_UNITS);
                        }
        			}
                    break;
        	}
        }
    
        /**
         * Sets the route for the robot
         */
        private void setDestination() {
            /** Set the destination floor */
            destination_floor = deliveryItem.getDestFloor();
        }
    
        /**
         * Generic function that moves the robot towards the destination
         * @param destination the floor towards which the robot is moving
         */
        private void moveTowards(int destination) {
            if(current_floor < destination){
                current_floor++;
            } else {
                current_floor--;
            }
        }
        
        private String getIdTube() {
        	return String.format("%s(%1d)", this.id, (tube == null ? 0 : 1));
        }
        
        /**
         * Prints out the change in state
         * @param nextState the state to which the robot is transitioning
         */
        private void changeState(RobotState nextState){
        	assert(!(deliveryItem == null && tube != null));
        	if (current_state != nextState) {
                System.out.printf("T: %3d > %7s changed from %s to %s%n", Clock.Time(), getIdTube(), current_state, nextState);
        	}
        	current_state = nextState;
        	if(nextState == RobotState.DELIVERING){
                System.out.printf("T: %3d > %7s-> [%s]%n", Clock.Time(), getIdTube(), deliveryItem.toString());
        	}
        }
    
    	public MailItem getTube() {
    		return tube;
    	}
    
    	public boolean isEmpty() {
    		return (deliveryItem == null && tube == null);
    	}
    
    	public void addToHand(MailItem mailItem) throws ItemTooHeavyException {
    		assert(deliveryItem == null);
    		deliveryItem = mailItem;
    		if (deliveryItem.weight > INDIVIDUAL_MAX_WEIGHT) throw new ItemTooHeavyException();
    	}
    
    	public void addToTube(MailItem mailItem) throws ItemTooHeavyException {
    		assert(tube == null);
    		tube = mailItem;
    		if (tube.weight > INDIVIDUAL_MAX_WEIGHT) throw new ItemTooHeavyException();
    	}
    
    }