Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package sg.edu.nus.cs2020.ps3;
- import java.util.ArrayList;
- import java.util.Collections;
- import java.util.List;
- /* Assumptions:
- * Let the class implementing the IRUNwaySearch be RunwayNode
- * keySuccessor and keyPredecessor returns -1 when the data cannot be found, instead of having errors
- * dataSearch, dataSuccessor, dataPredecessor returns null when the data cannot be found, instead of having errors
- * Standard errors are handled at a higher level, functions returning int with errors returns -1,
- * functions returning Objects with errors returns null
- */
- public class Scheduler implements IRunwayScheduler {
- //The root node of of the tree, initialized as null
- private RunwayNode node;
- //Helper to ensure that the input of time is non-negative
- private boolean isValidTiming(int time) {
- if (time < 0) {
- System.out.println("Invalid Timing: Input time cannot be negative");
- return false;
- }
- if (time > 10080) {
- System.out.println("Invalid Timing: Input time is beyond the current week");
- return false;
- }
- return true;
- }
- /* Helper function to check if a timing is safe
- * by checking if the successor of time - 3 is within 3 min of input time
- */
- private boolean isSafeTiming(int time) {
- //If time entered is -ve, stop
- if (!isValidTiming(time))
- return false;
- //If there are no scheduled planes
- if (node == null)
- return true;
- //If the successor of the virtual node at time-3 clashes...
- int clash = node.keySuccessor(time - 3);
- //If there is no successor at all, then definitely safe
- if (clash == -1)
- return true;
- //Check if the successor clashes with the suggested time
- return (Math.abs(clash - time) < 3) ?
- false : true;
- }
- @Override
- public boolean requestTimeSlot(int time, String pilot) {
- //If invalid input, reject
- if (!isValidTiming(time))
- return false;
- //If there are no scheduled planes
- if (node == null) {
- node = new RunwayNode(time, pilot, null);
- return true;
- }
- //If the timing is not safe, reject
- if (!isSafeTiming(time))
- return false;
- //Else, insert the node and return true
- node.insert(time, pilot);
- return true;
- }
- /* There are 4 conditions for getNextFreeSlot
- * -> The suggested timing is clear, return the suggested timing
- * -> The suggested timing is a right border case
- * -> There is a free timing between both the prev and the next that is not before the suggested timing
- * -> Have to look for a timing after the next plane lands
- */
- @Override
- public int getNextFreeSlot(int time) {
- //If the input data is invalid, reject and return sentinel value
- if (!isValidTiming(time))
- return -1;
- //If the timing is safe, or there are no scheduled planes, definitely free
- if (node == null || isSafeTiming(time))
- return time;
- int next = node.keySuccessor(time);
- int prev = node.keyPredecessor(time);
- //Right Border case
- if (next == -1)
- if (node.search(time)) //The right edge is at time, so return time+3
- return time + 3;
- else //The right edge is at prev, so return prev.time+3
- return prev + 3;
- if (node.search(time) || //there is a plane scheduled exactly on the suggested time
- prev == -1 || //left border case
- next- time < 3 || //there is not enough between the suggested time and the next plane's landing time
- next - prev < 6) { //no space to fit between both the prev and next time
- int current = next;
- next = node.keySuccessor(current);
- //Find a case where there is a 6 or more minute gap between 2 nodes, or the right border case is reached
- //Which means continue until right is not null, and the gap between next and current is less than 6
- while (next != -1 && next - current < 6) {
- current = next;
- next = node.keySuccessor(current);
- }
- //return closest time after current
- return current + 3;
- }
- //Can fit between both, and suggested time was too close to prev, so return closest possible time after prev
- return prev + 3;
- }
- @Override
- public int getNextPlane(int time) {
- //If the input data is invalid, return sentinel
- if (!isValidTiming(time))
- return -1;
- //If there are no scheduled planes, return sentinel
- if (node == null) {
- System.out.println("There are no scheduled planes");
- return -1;
- }
- int next = node.keySuccessor(time);
- //If there is no next plane, notify and return sentinel value
- if (next == -1)
- System.out.println("There are no records beyond " + time);
- return next;
- }
- @Override
- public String getPilot(int time) {
- //Reject invalid input and return sentinel value
- if (!isValidTiming(time))
- return null;
- //If there are no scheduled planes, return sentinel
- if (node == null) {
- System.out.println("There are no scheduled planes");
- return null;
- }
- //Find the Plane using the key
- String search = node.dataSearch(time);
- //If no plane is scheduled for the time, return sentinel value
- if (search == null)
- System.out.println("Unable to find a plane scheduled for " + time);
- //Finally, return the pilot
- return search;
- }
- @Override
- public List<String> getPilots() {
- List<String> ans = new ArrayList<String>();
- //If there are no scheduled planes, so return an empty arraylist
- if (node == null) {
- System.out.println("There are no scheduled planes");
- return ans;
- }
- //Since time starts from 0, this gets the first entry (based on key)
- int plane = node.keySuccessor(-1);
- //Keep track of the pilots to prevent duplicate entries
- int pilotCount = 0;
- //Keep finding the successor until null
- while (plane != -1) {
- boolean repeat = false;
- String pilotName = node.dataSearch(plane);
- //Check if the new pilot is already in the list
- for (int i=0;i<pilotCount;i++)
- if (ans.get(i) == pilotName) {
- repeat = true;
- //Escape as a repeat has been found
- break;
- }
- //Add the new pilot to the list if it's not a duplicate
- if (repeat == false) {
- ans.add(pilotName);
- pilotCount++;
- }
- plane = node.keySuccessor(plane);
- }
- //The question asks for the list to be alphabetically sorted
- Collections.sort(ans);
- return ans;
- }
- @Override
- public List<Integer> getPilotSchedule(String pilot) {
- List<Integer> ans = new ArrayList<Integer>();
- //If there are no scheduled planes, so return an empty arraylist
- if (node == null) {
- System.out.println("There are no scheduled planes");
- return ans;
- }
- //Since time starts from 0, this gets the first entry (based on key)
- int plane = node.keySuccessor(-1);
- //Keep finding the successor until null
- while (plane != -1) {
- //If the data is from that pilot, add it to the list
- if (node.dataSearch(plane) == pilot)
- ans.add(plane);
- plane = node.keySuccessor(plane);
- }
- if (ans.isEmpty())
- System.out.println("Unable to find any planes piloted by " + pilot);
- return ans;
- }
- public static void main(String[] args) {
- //Sample given in question
- Scheduler schedule = new Scheduler();
- boolean answer = schedule.requestTimeSlot(300, "Seth"); // Request slot 300
- System.out.println("Answer: " + (answer? "Success!" : "Failure!")); // Success!
- answer = schedule.requestTimeSlot(400, "Steven"); // Request slot 400
- System.out.println("Answer: " + (answer? "Success!" : "Failure!")); // Success!
- answer = schedule.requestTimeSlot(302, "Steven"); // Request slot 302
- System.out.println("Answer: " + (answer? "Success!" : "Failure!")); // Failure!
- answer = schedule.requestTimeSlot(398, "Seth"); // Request slot 398
- System.out.println("Answer: " + (answer? "Success!" : "Failure!")); // Failure!
- int nextFree = schedule.getNextFreeSlot(398); // When can I land?
- System.out.println("Next free slot: " + nextFree); // I can land at 403
- answer = schedule.requestTimeSlot(nextFree, "Seth"); // Request next free slot
- System.out.println("Answer: " + (answer? "Success!" : "Failure!")); // Success!
- int nextPlane = schedule.getNextPlane(350); // When is the next plane landing?
- System.out.println("Next plane: " + nextPlane); // At time=400
- String pilot = schedule.getPilot(nextPlane); // Who is landing then?
- System.out.println("Next pilot: " + pilot); // Steven is landing at 400
- List<String> pilots = schedule.getPilots(); // List all the pilots
- for (int i=0;i<pilots.size();i++)
- System.out.println("Pilot " + pilots.get(i));
- // Outputs Seth and Steven (in sorted order, alphabetically)
- List<Integer> landingTimes = schedule.getPilotSchedule("Seth"); // When is Seth landing?
- for (int i=0;i<landingTimes.size();i++)
- System.out.println("Time: " + landingTimes.get(i));
- // Outputs that Seth is landing at slot 300 and 403.
- //Displays the tree that stores the thing, for fun, only works for my RunwayNode
- System.out.println("\n----- Tree -----");
- schedule.node.displayTree();
- /* ----- Tree -----
- 300-Seth
- Empty 400-Steven
- Empty Empty Empty 403-Seth */
- //My test cases
- Scheduler test = new Scheduler();
- //Invalid input / Empty node tests
- System.out.println("\n\n\n");
- System.out.println("1a: test.getNextFreeSlot(-1): " + test.getNextFreeSlot(-1)); //Error message and -1
- System.out.println("1b: test.getNextPlane(-1): " + test.getNextPlane(-1)); //Error message and -1
- System.out.println("1c: test.getPilot(-1): " + test.getPilot(-1)); //Error message and null
- System.out.println("1d: test.requestTimeSlot(-1, <me>): " + test.requestTimeSlot(-1, "me")); //Error message and false
- System.out.println("\n\n");
- System.out.println("2a: test.getPilots(): " + test.getPilots()); //Empty nodes message and blank array of int
- System.out.println("2b: test.getNextFreeSlot(5): " + test.getNextFreeSlot(5)); //Returns 5
- System.out.println("2c: test.getNextPlane(0): " + test.getNextPlane(0)); //Empty nodes message and -1
- System.out.println("2d: test.getPilot(5): " + test.getPilot(5)); //Empty nodes message and null
- System.out.println("2e: test.getPilotSchedule(<>): " + test.getPilotSchedule("")); //Empty nodes message and blank array of string
- System.out.println("2f: test.getPilotSchedule(<me>): " + test.getPilotSchedule("me")); //Empty nodes message and blank array of string
- System.out.println("\n\n");
- //RequestTimeSlot tests
- //Add first node and check tree
- System.out.println("3a: test.requestTimeSlot(50, <me>): " + test.requestTimeSlot(50, "me")); //True
- test.node.displayTree();
- System.out.println();
- //Clash testing and add more nodes
- for (int i = 47; i <= 53; i++)
- System.out.println("3b: test.requestTimeSlot(" + i + ", <test>): " + test.requestTimeSlot(i, "test"));
- //True for 47 and 53 only
- //Adding to tree for next test:
- System.out.println("Adding time <41>: " + test.requestTimeSlot(41, "left"));
- System.out.println("Adding time <59>: " + test.requestTimeSlot(59, "right"));
- test.node.displayTree();
- System.out.println();
- //Current list: 41, 47, 50, 53, 59
- //getNextFreeSlot Testing
- //Right border cases
- System.out.println("4a: test.getNextFreeSlot(60): " + test.getNextFreeSlot(60)); //62
- System.out.println("4a: test.getNextFreeSlot(59): " + test.getNextFreeSlot(59)); //62
- //Can fit exactly case
- System.out.println("4a: test.getNextFreeSlot(56): " + test.getNextFreeSlot(56)); //56
- //Too close to left, but can fit if pushed right a bit
- System.out.println("4a: test.getNextFreeSlot(42): " + test.getNextFreeSlot(42)); //44
- //Totally no space, search for next space
- System.out.println("4a: test.getNextFreeSlot(49): " + test.getNextFreeSlot(49)); //56
- System.out.println("4a: test.getNextFreeSlot(50): " + test.getNextFreeSlot(50)); //56
- System.out.println("4a: test.getNextFreeSlot(40): " + test.getNextFreeSlot(40)); //44
- //Pilots are left, me, right and test respectively, in alphabetic order
- System.out.println(test.getPilots());
- //Test getNextPlane and getPilot together
- System.out.println(test.getPilot(test.getNextPlane(40))); //left
- //Test getPilotSchedule
- System.out.println(test.getPilotSchedule("test")); //47 and 53
- System.out.println(test.getPilotSchedule("fake")); //unable to find notification and empty arraylist
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement