import java.util.*; public class MakkahCity { private static final ArrayList listOfCampaigns = new ArrayList<>(); private static final ArrayList listOfVehicles = new ArrayList<>(); private static final Route[] stdRoutes = new Route[6]; private static final Street[] stdStreet = new Street[9]; private static final PDate timeManager = new PDate( new GregorianCalendar(2020, Calendar.JANUARY, 1, 4, 0, 0), new GregorianCalendar(2020, Calendar.JANUARY, 1, 17, 0, 0) ); public static void main(String[] args) { //Gen Camp generateCamps(District.ALAZIZIYA, (int)getRandom(1200, 1400)); generateCamps(District.ALMANSOOR, (int)getRandom(1600, 1800)); generateCamps(District.ALHIJRA, (int)getRandom(1400, 1600)); fillBusesToList(); //Make Streets makeStreets(); addCivilVehicleNoise(); //Make Routes makeRoutes(); //Set Routes for Campaigns setRoutesForCampaigns(); //TODO: use Queues or Wating area for each street? while(!timeManager.isEnded()) { //Start of Every hour if (timeManager.getCurrentCalendar().get(Calendar.MINUTE) == 0){ if (isAllArrived()) { System.out.println("\nAll campaigns have arrived before " + timeManager.getCurrentTime()); break; } } //Start of Every half-hour if (timeManager.getCurrentCalendar().get(Calendar.MINUTE) % 30 == 0){ } //Start of every 10min if (timeManager.getCurrentCalendar().get(Calendar.MINUTE) % 10 == 0){ addCivilVehicleNoise(); System.out.println("\n\n" + getStreetsReport()); printFinalRep(); } if (timeManager.getCurrentCalendar().get(Calendar.MINUTE) == getRandom(0,59) && timeManager.getCurrentCalendar().get(Calendar.SECOND) == getRandom(0,59)){ } for (Vehicle vehicle : listOfVehicles) { Route route = vehicle.getRoute(); double currentLocation = vehicle.getCurrentLocation(); if (vehicle.getCurrentStreet() == null && route.getStreets()[0].capcityPoint(0,1000) < 1) { vehicle.setCurrentStreet(route.getStreets()[0]); } if (vehicle.getCurrentStreet() != null && vehicle.getCurrentStreet().capcityPoint(currentLocation, currentLocation+1000) < 1 ) { //TODO: Possible bug. Checks 1Km ahead. Street may not be that long(checks as ok). if (currentLocation >= vehicle.getCurrentStreet().getLength()) { //Move to next street vehicle.moveToNextStreet(); } if (!vehicle.isArrivedToDest()) { double factor = 1-(vehicle.getCurrentStreet().capcityPoint(vehicle.getCurrentLocation(), vehicle.getCurrentLocation()+1000,vehicle)) ; if (vehicle instanceof Bus) vehicle.move(Bus.MAX_FORWARD * factor ); else if (vehicle instanceof Sedan) vehicle.move(Sedan.MAX_FORWARD * factor ); else if (vehicle instanceof SUV) vehicle.move(SUV.MAX_FORWARD * factor ); else if (vehicle instanceof Truck) vehicle.move(Bus.MAX_FORWARD * factor ); } } } // Vehicle v = listOfVehicles.get(150); // if (v.getCurrentStreet() != null) { // System.out.printf("St: %s distance: %f total: %f %s\n", // v.getCurrentStreet().getName(), // v.getCurrentLocation(), // v.getTotalDistanceTraveled(), // timeManager.getCurrentTime()); //} //noise based on time of day (From PDate) /* Output: Street stats Campaigns avg (at end) */ timeManager.step(Calendar.MINUTE, 1); } //TODO: print final report } private static void setRoutesForCampaigns() { for (Campaign camp : listOfCampaigns){ camp.setDestToHousingRoute(getShortestRoute(camp)); } } private static double getRandom(double min, double max) { return (Math.random() * (max - min) + min); } private static void generateCamps(District area, int count) { for (int i = 0; i < count; i++){ Campaign camp = new Campaign(area, (int)getRandom(10, 15)); listOfCampaigns.add(camp); } } private static void makeStreets(){ stdStreet[StreetNames.KA_STREET.ordinal()] = new Street(4700,3, StreetNames.KA_STREET); stdStreet[StreetNames.FOURTH_HIGHWAY.ordinal()] = new Street(9700,4, StreetNames.FOURTH_HIGHWAY); stdStreet[StreetNames.THIRD_HIGHWAY.ordinal()] = new Street(8200,3, StreetNames.THIRD_HIGHWAY); stdStreet[StreetNames.STREET1.ordinal()] = new Street(7800,3, StreetNames.STREET1); stdStreet[StreetNames.STREET2.ordinal()] = new Street(2400,3,StreetNames.STREET2); stdStreet[StreetNames.STREET3.ordinal()] = new Street(4800,2, StreetNames.STREET3); stdStreet[StreetNames.STREET4.ordinal()] = new Street(3800,3,StreetNames.STREET4); stdStreet[StreetNames.STREET5.ordinal()] = new Street(3200,2, StreetNames.STREET5); stdStreet[StreetNames.IBRAHIM_ALKHALIL.ordinal()] = new Street(4500,3, StreetNames.IBRAHIM_ALKHALIL); } private static void makeRoutes() { stdRoutes[RouteName.mashierToAlHijra1.ordinal()] = new Route( new Street[]{ stdStreet[StreetNames.STREET1.ordinal()], stdStreet[StreetNames.STREET2.ordinal()], stdStreet[StreetNames.THIRD_HIGHWAY.ordinal()]}, District.ALHIJRA, Mashier.ARAFAT); stdRoutes[RouteName.mashierToAlHijra2.ordinal()] = new Route(new Street[]{ stdStreet[StreetNames.STREET1.ordinal()], stdStreet[StreetNames.FOURTH_HIGHWAY.ordinal()], stdStreet[StreetNames.STREET4.ordinal()] },District.ALHIJRA, Mashier.ARAFAT); stdRoutes[RouteName.mashierToAlMansoor1.ordinal()] = new Route( new Street[]{ stdStreet[StreetNames.STREET1.ordinal()], stdStreet[StreetNames.STREET2.ordinal()], stdStreet[StreetNames.KA_STREET.ordinal()], stdStreet[StreetNames.STREET3.ordinal()] },District.ALMANSOOR, Mashier.ARAFAT); stdRoutes[RouteName.mashierToAlMansoor2.ordinal()] = new Route( new Street[]{ stdStreet[StreetNames.STREET1.ordinal()], stdStreet[StreetNames.STREET2.ordinal()], stdStreet[StreetNames.THIRD_HIGHWAY.ordinal()], stdStreet[StreetNames.STREET5.ordinal()]//TODO: [8]is actually half of ibrahim khalil. },District.ALMANSOOR, Mashier.ARAFAT); //Optimal for Almansoor stdRoutes[RouteName.mashierToAlMansoor3.ordinal()] = new Route( new Street[]{ stdStreet[StreetNames.STREET1.ordinal()], stdStreet[StreetNames.FOURTH_HIGHWAY.ordinal()], stdStreet[StreetNames.IBRAHIM_ALKHALIL.ordinal()] },District.ALMANSOOR, Mashier.ARAFAT); stdRoutes[RouteName.mashierToAlAzizi1.ordinal()] = new Route( new Street[]{ stdStreet[StreetNames.STREET1.ordinal()], stdStreet[StreetNames.STREET2.ordinal()], stdStreet[StreetNames.KA_STREET.ordinal()] },District.ALAZIZIYA, Mashier.ARAFAT); } private static void fillBusesToList() { for (Campaign camp : listOfCampaigns) { listOfVehicles.addAll(camp.getVehicles()); } } private static void addCivilVehicleNoise() { for (Street street: stdStreet) { int numOfSedan = (int)getRandom(40,50); int numOfSUV = (int)getRandom(20,30); int numOfTruck = (int)getRandom(10,12); if (street.getName() == StreetNames.FOURTH_HIGHWAY) numOfSedan = (int) (numOfSedan * 0.5); if (street.getName() == StreetNames.STREET3) numOfSedan = (int) (numOfSedan * 1.5); if (street.getName() == StreetNames.STREET5) numOfSedan = (int) (numOfSedan * 1.5); for (int x = 0; x < numOfSedan; x++) { Sedan car = new Sedan(getRandom(4, 5)); double pointOfEntry = getRandom(0, street.getLength()); if (street.capcityPoint(pointOfEntry, pointOfEntry+1500) < 1){ listOfVehicles.add(car); car.setCurrentLocation(pointOfEntry); car.setRoute(new Route(street)); car.setCurrentStreet(street); } } if (street.getName() == StreetNames.FOURTH_HIGHWAY) numOfTruck = (int) (numOfTruck * 0.5); if (street.getName() == StreetNames.STREET3) numOfTruck = (int) (numOfTruck * 1.5); if (street.getName() == StreetNames.STREET5) numOfSedan = (int) (numOfSedan * 1.5); for (int x = 0; x < numOfTruck; x++) { Truck car = new Truck(getRandom(4, 5)); double pointOfEntry = getRandom(0, street.getLength()); if (street.capcityPoint(pointOfEntry, pointOfEntry+1500) < 1){ listOfVehicles.add(car); car.setCurrentLocation(pointOfEntry); car.setRoute(new Route(street)); car.setCurrentStreet(street); } } if (street.getName() == StreetNames.FOURTH_HIGHWAY) numOfSUV = (int) (numOfSUV * 0.5); if (street.getName() == StreetNames.STREET3) numOfSUV = (int) (numOfSUV * 1.5); if (street.getName() == StreetNames.STREET5) numOfSedan = (int) (numOfSedan * 1.5); for (int x = 0; x < numOfSUV; x++) { SUV car = new SUV(getRandom(4, 5)); double pointOfEntry = getRandom(0, street.getLength()); if (street.capcityPoint(pointOfEntry, pointOfEntry+1500) < 1){ listOfVehicles.add(car); car.setCurrentLocation(pointOfEntry); car.setRoute(new Route(street)); car.setCurrentStreet(street); } } } } /** * Generates 'noise' cars to be used in streets * @param numberOfCars * @return Array of 70% Sedans and 30% SUVs */ private static CivilVehicle[] generateCivilVehicles(int numberOfCars) { CivilVehicle[] cars = new CivilVehicle[numberOfCars]; int sedans = (int)(numberOfCars*0.7); int SUVs = numberOfCars - sedans; for (int i = 0; i < sedans; i++) { cars[i] = new Sedan(getRandom(25,32)/10); } for (int i = 0; i < SUVs; i++) { try { cars[sedans+i] = new SUV(getRandom(35,45)/10); } catch (IndexOutOfBoundsException ex) { break; } } return cars; } public static PDate getTimeManager() { return timeManager; } /** * Find shortest path without respect to traffic * @param campaign * @return */ private static Route getShortestRoute(Campaign campaign) { Route[] routes = getRoutesToDistrict(campaign.getHotelDistrict()); Route route = null; double min = Double.MAX_VALUE; for (Route r : routes) { if (r.getTotalLength() < min) { min = r.getTotalLength(); route = r; } } return route; } /** * Find routes that connect to a certain district. * @param district * @return Array of routes that connect to 'district' */ private static Route[] getRoutesToDistrict(District district) { ArrayList routes = new ArrayList<>(); for (Route route : stdRoutes) { if (route.getHotelArea() == district) { routes.add(route); } } Route[] routesArray = new Route[routes.size()]; return routes.toArray(routesArray); } private static void printReport() { for(Street street : stdStreet) { System.out.printf("StreetName: %s NumberOfVheciles : %d Capcity: %f\n", street.getName().name(),street.getVehicles().size(), street.capcity()); int qurter = (int) street.getLength()/4; double capcity = 0; for(int i = 0; i < 4; i++) { capcity = street.capcityPoint(i * qurter, qurter * (i+1)); System.out.printf("qurter%d: %.2f ", (i+1) , capcity ); } System.out.println("\n"); } } private static String getStreetsReport() { String headerFormat = "******Streets report*****\n" + "Time: %s\n" + "Street name |remaining capacity| cars\n"; String report = ""; report = report + String.format(headerFormat, timeManager.getCurrentTime()); String entryFormat = "%-16s | %%%-15s | %d\n"; for (Street street : stdStreet) { int cap = street.getPercentRemainingCapacity(); report = report + String.format(entryFormat, street.getName().name(), cap, street.getVehicles().size()); } return report; } private static void printFinalRep() { int numberOfBusses = 0; int numberOfArrivedBuses = getNumberOfArrivedBusses(); //Redundant loops slow down execution. find better sol. for (Campaign campaign : listOfCampaigns) { numberOfBusses += campaign.getNumberOfBusses(); } System.out.printf("Buses: %d Buses done: %d\n", numberOfBusses, numberOfArrivedBuses); } private static int getNumberOfArrivedBusses() { int num = 0; for (Campaign campaign : listOfCampaigns) { for (Vehicle vehicle : campaign.getVehicles()){ if (vehicle instanceof Bus && vehicle.isArrivedToDest()) num++; } } return num; } private static boolean isAllArrived() { for (Campaign campaign : listOfCampaigns) if (!campaign.isDone()) return false; return true; } }