diff --git a/ChargeCalculator.java b/ChargeCalculator.java
new file mode 100644
index 0000000000000000000000000000000000000000..80e22faf48a8057320ef4d1626ec5c3107ce53f1
--- /dev/null
+++ b/ChargeCalculator.java
@@ -0,0 +1,46 @@
+package automail;
+
+import java.util.Map;
+
+public class ChargeCalculator {
+	private static Map<Integer, Double> lastServiceFee;
+	private double markup;
+	private double unitPrice;
+	
+	public ChargeCalculator(int numFloors, double markup, double unitPrice) {
+		this.markup = markup;
+		this.unitPrice = unitPrice;
+		
+		// initialise service fees to 0 for all floors
+		for(int i = 1; i < numFloors + 1; i++) {
+			lastServiceFee.put(i, 0.0);
+		}
+	}
+	
+	/**
+	 * Calculates the activity cost for the parameter item
+	 * Activity cost = activity units * unit price
+	 * May be altered to factor in weight or delays in the future
+	 * @param item the mail item whos activity cost is calculated
+	 * */
+	private double calculateActivityCost(MailItem item) {
+		return item.getActivityUnits() * unitPrice;
+	}
+	
+	/**
+	 * Returns the expected cost for an item using the last calculated service fee
+	 * @param item The item whos expected cost is calculated
+	 * */
+	public double calculateExpectedCost(MailItem item) {
+		double cost = calculateActivityCost(item) + lastServiceFee.get(item.getDestFloor());
+		
+		return cost * (1 + markup);
+	}
+	
+	/**
+	 * TODO
+	 * */
+	public double calculateCost(MailItem item) {
+		return 0.0;
+	}
+}
diff --git a/src/automail/MailItem.java b/MailItem.java
similarity index 61%
rename from src/automail/MailItem.java
rename to MailItem.java
index 23430f39202ca4d8d6fcb217a8b8853bece46c95..6d0022999db751a900b978eddf127c705ec438c8 100644
--- a/src/automail/MailItem.java
+++ b/MailItem.java
@@ -25,11 +25,17 @@ public class MailItem {
     
     /** The service fee looked up at time of delivery*/
     private double service_fee;
+    private Boolean lookupSuccessful;
+    
     /** The portion of cost associated with activity units*/
     private double activity_cost;
     /** The total charge for delivering the item*/
     private double charge;
     
+    // TODO - review
+    private MailPool mailPool;
+    // private static ChargeCalculator chargeCalculator = new ChargeCalculator();
+    
 
     /**
      * Constructor for a MailItem
@@ -37,7 +43,9 @@ public class MailItem {
      * @param arrival_time the time that the mail arrived
      * @param weight the weight of this mail item
      */
-    public MailItem(int dest_floor, int arrival_time, int weight){
+    
+    // TODO - review this
+    public MailItem(int dest_floor, int arrival_time, int weight, MailPool mailPool){
         this.destination_floor = dest_floor;
         this.id = String.valueOf(hashCode());
         this.arrival_time = arrival_time;
@@ -46,13 +54,40 @@ public class MailItem {
         /*Initialise activity units and costs to zero*/
         this.activity_units = 0;
         this.service_fee = 0;
+        this.lookupSuccessful = false;
         this.activity_cost = 0;
         this.charge = 0;
+        
+        this.mailPool = mailPool;
+    }
+    
+    // TODO - configure charge calculator
+    public static void setUnitPrice() {
+    	return;
     }
 
+    /**
+     * Return a string representation of MailItem. Print charge information if charge threshold is set, otherwise preserve
+     * original output.
+     * */
     @Override
     public String toString(){
-        return String.format("Mail Item:: ID: %6s | Arrival: %4d | Destination: %2d | Weight: %4d", id, arrival_time, destination_floor, weight);
+    	double charge_threshold = mailPool.getChargeThreshold();
+    	if (charge_threshold == 0) {
+    		return String.format("Mail Item:: ID: %6s | Arrival: %4d | Destination: %2d | Weight: %4d", id, arrival_time, 
+    				destination_floor, weight);
+    	}
+    	return String.format("Mail Item:: ID: %6s | Arrival: %4d | Destination: %2d | Weight: %4d | Charge: %.2f | Cost: %.2f | Fee: %.2f | Activity: %.2f", 
+      		   id, arrival_time, destination_floor, weight, charge, getCost(), service_fee, activity_cost);
+    }
+    
+    /**
+     * Modified version of the toString() method that includes information related to the charge
+     * THIS METHOD SHOULD NOT BE CALLED IN THE FINAL VERSION
+     */
+    public String toStringWithCharge(){
+        return String.format("Mail Item:: ID: %6s | Arrival: %4d | Destination: %2d | Weight: %4d | Charge: %.2f | Cost: %.2f | Fee: %.2f | Activity: %.2f", 
+      		   id, arrival_time, destination_floor, weight, charge, getCost(), service_fee, activity_cost);
     }
 
     /**
@@ -107,14 +142,15 @@ public class MailItem {
 	   return service_fee + activity_cost;
    }
    
-   /**
-    * Modified version of the toString() method that includes information related to the charge
-    */
-   public String toStringWithCharge(){
-       return String.format("Mail Item:: ID: %6s | Arrival: %4d | Destination: %2d | Weight: %4d | Charge: %.2f | Cost: %.2f | Fee: %.2f | Activity: %.2f", 
-    		   id, arrival_time, destination_floor, weight, charge, getCost(), service_fee, activity_cost);
+   // TODO - validate fee and update success
+   public void setServiceFee(double fee) {
+	   this.service_fee = fee;
    }
    
+   // TODO - update statistics
+   public void updateStats() {
+	   
+   }
    
 	static private int count = 0;
 	static private Map<Integer, Integer> hashMap = new TreeMap<Integer, Integer>();
diff --git a/src/automail/Robot.java b/Robot.java
similarity index 93%
rename from src/automail/Robot.java
rename to Robot.java
index 7de2c1cd12185484a2939f632315221855fa2a5a..15839d67102019bbfcfadaee721cfc9033734185 100644
--- a/src/automail/Robot.java
+++ b/Robot.java
@@ -49,6 +49,8 @@ public class Robot {
         this.mailPool = mailPool;
         this.receivedDispatch = false;
         this.deliveryCounter = 0;
+        
+        
     }
     
     /**
@@ -96,6 +98,12 @@ public class Robot {
     				/*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;
diff --git a/src/simulation/Simulation.java b/Simulation.java
similarity index 85%
rename from src/simulation/Simulation.java
rename to Simulation.java
index 06eab853ed1e577ef6bb758517564022967e6fce..2bedb2580117c487409b186a9d16c3bf2dfff56d 100644
--- a/src/simulation/Simulation.java
+++ b/Simulation.java
@@ -73,10 +73,13 @@ public class Simulation {
          * This code section is for running a simulation
          */
         /* Instantiate MailPool and Automail */
-     	MailPool mailPool = new MailPool(NUM_ROBOTS);
+     	MailPool mailPool = new MailPool(NUM_ROBOTS, CHARGE_THRESHOLD);
         Automail automail = new Automail(mailPool, new ReportDelivery(), NUM_ROBOTS);
         MailGenerator mailGenerator = new MailGenerator(MAIL_TO_CREATE, MAIL_MAX_WEIGHT, mailPool, seedMap);
         
+        // TODO - something
+        MailItem.setUnitPrice();
+        
         /** Generate all the mails */
         mailGenerator.generateAllMail();
         while(MAIL_DELIVERED.size() != mailGenerator.MAIL_TO_CREATE) {
@@ -101,6 +104,7 @@ public class Simulation {
     static private Properties setUpProperties() throws IOException {
     	Properties automailProperties = new Properties();
 		// Default properties
+    	// TODO - add unit price
     	automailProperties.setProperty("Robots", "Standard");
     	automailProperties.setProperty("Floors", "10");
     	automailProperties.setProperty("Mail_to_Create", "80");
@@ -140,6 +144,7 @@ public class Simulation {
 		// Charge Display
 		CHARGE_DISPLAY = Boolean.parseBoolean(automailProperties.getProperty("ChargeDisplay"));
 		System.out.println("#Charge Display: " + CHARGE_DISPLAY);
+		// TODO - add unit price
 		
 		return automailProperties;
     }
@@ -149,6 +154,10 @@ public class Simulation {
     	/** Confirm the delivery and calculate the total score */
     	public void deliver(MailItem deliveryItem){
     		if(!MAIL_DELIVERED.contains(deliveryItem)){
+    			
+    			// mail item calls charge calculator deliveryItem.getCost()
+    			// getCost () {  mailPool.
+    			
     			MAIL_DELIVERED.add(deliveryItem);
                 System.out.printf("T: %3d > Delivered(%4d) [%s]%n", Clock.Time(), MAIL_DELIVERED.size(), deliveryItem.toString());
                 
@@ -170,6 +179,13 @@ public class Simulation {
     			}
     		}
     	}
+    	
+    	// TODO - review this
+    	public double getServiceFee(int floor) {
+    		double fee = wModem.forwardCallToAPI_LookupPrice(floor);
+    		
+    		return fee;
+    	}
 
     }
     
@@ -185,5 +201,20 @@ public class Simulation {
         System.out.println("T: "+Clock.Time()+" | Simulation complete!");
         System.out.println("Final Delivery time: "+Clock.Time());
         System.out.printf("Delay: %.2f%n", total_delay);
+        // Print statistics if chargeDisplay is toggled on
+        if (CHARGE_DISPLAY) {
+        	printStatistics();
+        }
+    }
+    
+    /**
+     * Print statistics - to be called at the end of the mail run if chargeDisplay is toggled on.
+     */
+    public static void printStatistics() {
+    	System.out.println("Number of items delivered: ");
+    	System.out.println("Total billable activity: ");
+    	System.out.println("Total activity cost: ");
+    	System.out.println("Total service cost: ");
+    	System.out.println("Number of lookups: XXX [XXX failed, XXX successful]" );
     }
 }
diff --git a/src/automail/Automail.java b/src/automail/Automail.java
deleted file mode 100644
index 196cb3533e2f04eb628a76be70f272d80520c64b..0000000000000000000000000000000000000000
--- a/src/automail/Automail.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package automail;
-
-import simulation.IMailDelivery;
-
-public class Automail {
-	      
-    public Robot[] robots;
-    public MailPool mailPool;
-    
-    public Automail(MailPool mailPool, IMailDelivery delivery, int numRobots) { 
-    	/** Initialize the MailPool */
-    	
-    	this.mailPool = mailPool;
-    	
-    	/** Initialize robots */
-    	robots = new Robot[numRobots];
-    	for (int i = 0; i < numRobots; i++) robots[i] = new Robot(delivery, mailPool, i);
-    }
-    
-}
diff --git a/src/automail/MailPool.java b/src/automail/MailPool.java
deleted file mode 100644
index 009147cf86df4a832eca3d7ea412dbd93928030e..0000000000000000000000000000000000000000
--- a/src/automail/MailPool.java
+++ /dev/null
@@ -1,100 +0,0 @@
-package automail;
-
-import java.util.LinkedList;
-import java.util.Comparator;
-import java.util.ListIterator;
-
-import exceptions.ItemTooHeavyException;
-
-/**
- * addToPool is called when there are mail items newly arrived at the building to add to the MailPool or
- * if a robot returns with some undelivered items - these are added back to the MailPool.
- * The data structure and algorithms used in the MailPool is your choice.
- * 
- */
-public class MailPool {
-
-	private class Item {
-		int destination;
-		MailItem mailItem;
-		// Use stable sort to keep arrival time relative positions
-		
-		public Item(MailItem mailItem) {
-			destination = mailItem.getDestFloor();
-			this.mailItem = mailItem;
-		}
-	}
-	
-	public class ItemComparator implements Comparator<Item> {
-		@Override
-		public int compare(Item i1, Item i2) {
-			int order = 0;
-			if (i1.destination < i2.destination) {
-				order = 1;
-			} else if (i1.destination > i2.destination) {
-				order = -1;
-			}
-			return order;
-		}
-	}
-	
-	private LinkedList<Item> pool;
-	private LinkedList<Robot> robots;
-
-	public MailPool(int nrobots){ //does it need a number of robots??????
-		// Start empty
-		pool = new LinkedList<Item>();
-		robots = new LinkedList<Robot>();
-	}
-
-	/**
-     * Adds an item to the mail pool
-     * @param mailItem the mail item being added.
-     */
-	public void addToPool(MailItem mailItem) {
-		Item item = new Item(mailItem);
-		pool.add(item);
-		pool.sort(new ItemComparator());
-	}
-	
-	
-	
-	/**
-     * load up any waiting robots with mailItems, if any.
-     */
-	public void loadItemsToRobot() throws ItemTooHeavyException {
-		//List available robots
-		ListIterator<Robot> i = robots.listIterator();
-		while (i.hasNext()) loadItem(i);
-	}
-	
-	//load items to the robot
-	private void loadItem(ListIterator<Robot> i) throws ItemTooHeavyException {
-		Robot robot = i.next();
-		assert(robot.isEmpty());
-		// System.out.printf("P: %3d%n", pool.size());
-		ListIterator<Item> j = pool.listIterator();
-		if (pool.size() > 0) {
-			try {
-			robot.addToHand(j.next().mailItem); // hand first as we want higher priority delivered first
-			j.remove();
-			if (pool.size() > 0) {
-				robot.addToTube(j.next().mailItem);
-				j.remove();
-			}
-			robot.dispatch(); // send the robot off if it has any items to deliver
-			i.remove();       // remove from mailPool queue
-			} catch (Exception e) { 
-	            throw e; 
-	        } 
-		}
-	}
-
-	/**
-     * @param robot refers to a robot which has arrived back ready for more mailItems to deliver
-     */	
-	public void registerWaiting(Robot robot) { // assumes won't be there already
-		robots.add(robot);
-	}
-
-}
diff --git a/src/exceptions/ExcessiveDeliveryException.java b/src/exceptions/ExcessiveDeliveryException.java
deleted file mode 100644
index db1962e00da4c1b99bc241109346ede6e90bf950..0000000000000000000000000000000000000000
--- a/src/exceptions/ExcessiveDeliveryException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package exceptions;
-
-/**
- * An exception thrown when the robot tries to deliver more items than its tube capacity without refilling.
- */
-public class ExcessiveDeliveryException extends Throwable {
-	public ExcessiveDeliveryException(){
-		super("Attempting to deliver more than 4 items in a single trip!!");
-	}
-}
diff --git a/src/exceptions/ItemTooHeavyException.java b/src/exceptions/ItemTooHeavyException.java
deleted file mode 100644
index 7084c003d059b1b0d96e067dfd9d99584c986180..0000000000000000000000000000000000000000
--- a/src/exceptions/ItemTooHeavyException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package exceptions;
-
-/**
- * This exception is thrown when a robot takes a MailItem from its StorageTube which is too heavy for that robot
- */
-public class ItemTooHeavyException extends Exception {
-    public ItemTooHeavyException(){
-        super("Item too heavy! Dropped by robot.");
-    }
-}
diff --git a/src/exceptions/MailAlreadyDeliveredException.java b/src/exceptions/MailAlreadyDeliveredException.java
deleted file mode 100644
index db8b3ec7757883690f3625cfeffa52abdb2b0ac9..0000000000000000000000000000000000000000
--- a/src/exceptions/MailAlreadyDeliveredException.java
+++ /dev/null
@@ -1,10 +0,0 @@
-package exceptions;
-
-/**
- * An exception thrown when a mail that is already delivered attempts to be delivered again.
- */
-public class MailAlreadyDeliveredException extends Throwable    {
-    public MailAlreadyDeliveredException(){
-        super("This mail has already been delivered!");
-    }
-}
diff --git a/src/simulation/Building.java b/src/simulation/Building.java
deleted file mode 100644
index 8ca4c2052f77523dbac69389a46243a5f6058ccd..0000000000000000000000000000000000000000
--- a/src/simulation/Building.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package simulation;
-
-public class Building {
-	
-	
-    /** The number of floors in the building **/
-    public static int FLOORS;
-    
-    /** Represents the ground floor location */
-    public static final int LOWEST_FLOOR = 1;
-    
-    /** Represents the mailroom location */
-    public static final int MAILROOM_LOCATION = 1;
-
-}
diff --git a/src/simulation/Clock.java b/src/simulation/Clock.java
deleted file mode 100644
index 667fe343255fe488e10a62585b06f76edcbd8907..0000000000000000000000000000000000000000
--- a/src/simulation/Clock.java
+++ /dev/null
@@ -1,18 +0,0 @@
-package simulation;
-
-public class Clock {
-	
-	/** Represents the current time **/
-    private static int Time = 0;
-    
-    /** The threshold for the latest time for mail to arrive **/
-    public static int MAIL_RECEVING_LENGTH;
-
-    public static int Time() {
-    	return Time;
-    }
-    
-    public static void Tick() {
-    	Time++;
-    }
-}
diff --git a/src/simulation/IMailDelivery.java b/src/simulation/IMailDelivery.java
deleted file mode 100644
index fdcdff78fe87b35794052210295d1bc57e6e2022..0000000000000000000000000000000000000000
--- a/src/simulation/IMailDelivery.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package simulation;
-
-import automail.MailItem;
-
-/**
- * a MailDelivery is used by the Robot to deliver mail once it has arrived at the correct location
- */
-public interface IMailDelivery {
-
-	/**
-     * Delivers an item at its floor
-     * @param mailItem the mail item being delivered.
-     */
-	void deliver(MailItem mailItem);
-    
-}
\ No newline at end of file
diff --git a/src/simulation/MailGenerator.java b/src/simulation/MailGenerator.java
deleted file mode 100644
index 14e3404ea9803204f713d43ec46feb107a02c128..0000000000000000000000000000000000000000
--- a/src/simulation/MailGenerator.java
+++ /dev/null
@@ -1,135 +0,0 @@
-package simulation;
-
-import java.util.*;
-
-import automail.MailItem;
-import automail.MailPool;
-
-/**
- * This class generates the mail
- */
-public class MailGenerator {
-
-    public final int MAIL_TO_CREATE;
-    public final int MAIL_MAX_WEIGHT;
-    
-    private int mailCreated;
-
-    private final Random random;
-    /** This seed is used to make the behaviour deterministic */
-    
-    private boolean complete;
-    private MailPool mailPool;
-
-    private Map<Integer,ArrayList<MailItem>> allMail;
-
-    /**
-     * Constructor for mail generation
-     * @param mailToCreate roughly how many mail items to create
-     * @param mailMaxWeight limits the maximum weight of the mail
-     * @param mailPool where mail items go on arrival
-     * @param seed random seed for generating mail
-     */
-    public MailGenerator(int mailToCreate, int mailMaxWeight, MailPool mailPool, HashMap<Boolean,Integer> seed){
-        if(seed.containsKey(true)){
-        	this.random = new Random((long) seed.get(true));
-        }
-        else{
-        	this.random = new Random();	
-        }
-        // Vary arriving mail by +/-20%
-        MAIL_TO_CREATE = mailToCreate*4/5 + random.nextInt(mailToCreate*2/5);
-        MAIL_MAX_WEIGHT = mailMaxWeight;
-        // System.out.println("Num Mail Items: "+MAIL_TO_CREATE);
-        mailCreated = 0;
-        complete = false;
-        allMail = new HashMap<Integer,ArrayList<MailItem>>();
-        this.mailPool = mailPool;
-    }
-
-    /**
-     * @return a new mail item that needs to be delivered
-     */
-    private MailItem generateMail(){
-    	MailItem newMailItem;
-        int destinationFloor = generateDestinationFloor();
-        int arrivalTime = generateArrivalTime();
-        int weight = generateWeight();
-        
-        newMailItem = new MailItem(destinationFloor,arrivalTime,weight);
-        return newMailItem;
-    }
-
-    /**
-     * @return a destination floor between the ranges of GROUND_FLOOR to FLOOR
-     */
-    private int generateDestinationFloor(){
-        return Building.LOWEST_FLOOR + random.nextInt(Building.FLOORS);
-    }
-
-    /**
-     * @return a random weight
-     */
-    private int generateWeight(){
-    	final double mean = 200.0; // grams for normal item
-    	final double stddev = 1000.0; // grams
-    	double base = random.nextGaussian();
-    	if (base < 0) base = -base;
-    	int weight = (int) (mean + base * stddev);
-        return weight > MAIL_MAX_WEIGHT ? MAIL_MAX_WEIGHT : weight;
-    }
-    
-    /**
-     * @return a random arrival time before the last delivery time
-     */
-    private int generateArrivalTime(){
-        return 1 + random.nextInt(Clock.MAIL_RECEVING_LENGTH);
-    }
-
-    /**
-     * This class initializes all mails and sets their corresponding values,
-     * All generated mails will be saved in allMail
-     */
-    public void generateAllMail(){
-        while(!complete){
-            MailItem newMail =  generateMail();
-            int timeToDeliver = newMail.getArrivalTime();
-            /** Check if key exists for this time **/
-            if(allMail.containsKey(timeToDeliver)){
-                /** Add to existing array */
-                allMail.get(timeToDeliver).add(newMail);
-            }
-            else{
-                /** If the key doesn't exist then set a new key along with the array of MailItems to add during
-                 * that time step.
-                 */
-                ArrayList<MailItem> newMailList = new ArrayList<MailItem>();
-                newMailList.add(newMail);
-                allMail.put(timeToDeliver,newMailList);
-            }
-            /** Mark the mail as created */
-            mailCreated++;
-
-            /** Once we have satisfied the amount of mail to create, we're done!*/
-            if(mailCreated == MAIL_TO_CREATE){
-                complete = true;
-            }
-        }
-
-    }
-    
-    /**
-     * Given the clock time, put the generated mails into the mailPool.
-     * So that the robot will can pick up the mails from the pool.
-     */
-    public void addToMailPool(){
-    	// Check if there are any mail to create
-        if(this.allMail.containsKey(Clock.Time())){
-            for(MailItem mailItem : allMail.get(Clock.Time())){
-                System.out.printf("T: %3d > new addToPool [%s]%n", Clock.Time(), mailItem.toString());
-                mailPool.addToPool(mailItem);
-            }
-        }
-    }
-    
-}