-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Nabil Belahouane
authored
Sep 23, 2019
1 parent
e7f93f4
commit 734adc9
Showing
58 changed files
with
810 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+6.36 KB
trafficmon/out/production/trafficmon/com/trafficmon/CongestionChargeSystem.class
Binary file not shown.
Binary file added
BIN
+1.11 KB
trafficmon/out/production/trafficmon/com/trafficmon/CustomerAccountsService.class
Binary file not shown.
Binary file added
BIN
+362 Bytes
trafficmon/out/production/trafficmon/com/trafficmon/CustomerAccountsServiceInterface.class
Binary file not shown.
Binary file added
BIN
+527 Bytes
trafficmon/out/production/trafficmon/com/trafficmon/EntryEvent.class
Binary file not shown.
Binary file added
BIN
+516 Bytes
trafficmon/out/production/trafficmon/com/trafficmon/ExitEvent.class
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+957 Bytes
trafficmon/out/production/trafficmon/com/trafficmon/OperationsService.class
Binary file not shown.
Binary file added
BIN
+294 Bytes
trafficmon/out/production/trafficmon/com/trafficmon/OperationsServiceInterface.class
Binary file not shown.
Binary file not shown.
Binary file added
BIN
+236 Bytes
trafficmon/out/production/trafficmon/com/trafficmon/VehicleInterface.class
Binary file not shown.
Binary file added
BIN
+883 Bytes
trafficmon/out/production/trafficmon/com/trafficmon/ZoneBoundaryCrossing.class
Binary file not shown.
Binary file added
BIN
+230 Bytes
trafficmon/out/production/trafficmon/com/trafficmon/ZoneBoundaryCrossingInterface.class
Binary file not shown.
Binary file added
BIN
+820 Bytes
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$1.class
Binary file not shown.
Binary file added
BIN
+1.62 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$10.class
Binary file not shown.
Binary file added
BIN
+1.61 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$11.class
Binary file not shown.
Binary file added
BIN
+1.62 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$12.class
Binary file not shown.
Binary file added
BIN
+1.62 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$13.class
Binary file not shown.
Binary file added
BIN
+1.63 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$14.class
Binary file not shown.
Binary file added
BIN
+1.62 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$15.class
Binary file not shown.
Binary file added
BIN
+1.63 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$16.class
Binary file not shown.
Binary file added
BIN
+1.63 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$17.class
Binary file not shown.
Binary file added
BIN
+1.62 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$18.class
Binary file not shown.
Binary file added
BIN
+1.62 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$19.class
Binary file not shown.
Binary file added
BIN
+1.41 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$2.class
Binary file not shown.
Binary file added
BIN
+1.62 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$20.class
Binary file not shown.
Binary file added
BIN
+1.63 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$21.class
Binary file not shown.
Binary file added
BIN
+1.63 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$22.class
Binary file not shown.
Binary file added
BIN
+1.4 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$3.class
Binary file not shown.
Binary file added
BIN
+1.42 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$4.class
Binary file not shown.
Binary file added
BIN
+1.6 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$5.class
Binary file not shown.
Binary file added
BIN
+1.6 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$6.class
Binary file not shown.
Binary file added
BIN
+1.6 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$7.class
Binary file not shown.
Binary file added
BIN
+1.61 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$8.class
Binary file not shown.
Binary file added
BIN
+1.61 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest$9.class
Binary file not shown.
Binary file added
BIN
+10.1 KB
trafficmon/out/test/trafficmon/com/trafficmon/CongestionChargeSystemTest.class
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
147 changes: 147 additions & 0 deletions
147
trafficmon/src/com/trafficmon/CongestionChargeSystem.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package com.trafficmon; | ||
|
||
import java.math.BigDecimal; | ||
import java.text.SimpleDateFormat; | ||
import java.util.*; | ||
|
||
public class CongestionChargeSystem { | ||
//Variables | ||
public static final long HOURS_TO_MILLI_SECONDS = 60*60*1000L; | ||
private Map<VehicleInterface, List<ZoneBoundaryCrossing>> crossingsByVehicle; | ||
private CustomerAccountsServiceInterface customerAccountService; | ||
private OperationsServiceInterface operationsService; | ||
//Variables* | ||
|
||
//Package Private Constructor for testing | ||
CongestionChargeSystem(Map<VehicleInterface, List<ZoneBoundaryCrossing>> crossingsByVehicle,CustomerAccountsServiceInterface customerAccountService,OperationsServiceInterface opsi){ | ||
this.crossingsByVehicle = crossingsByVehicle; | ||
this.customerAccountService = customerAccountService; | ||
this.operationsService = opsi; | ||
} | ||
|
||
public CongestionChargeSystem(){ | ||
this.operationsService = new OperationsService(); | ||
this.customerAccountService = new CustomerAccountsService(); | ||
this.crossingsByVehicle = new HashMap<VehicleInterface, List<ZoneBoundaryCrossing>>(); | ||
} | ||
|
||
public void vehicleEnteringZone(VehicleInterface vehicle) { | ||
if (!crossingsByVehicle.containsKey(vehicle)) { | ||
crossingsByVehicle.put(vehicle, new ArrayList<ZoneBoundaryCrossing>()); | ||
} | ||
crossingsByVehicle.get(vehicle).add(new EntryEvent(vehicle)); | ||
} | ||
|
||
public void vehicleLeavingZone(VehicleInterface vehicle) { | ||
//Make sure vehicle is registered | ||
if ((!crossingsByVehicle.containsKey(vehicle))||(crossingsByVehicle.get(vehicle).size()<=0)) { | ||
return; | ||
} | ||
crossingsByVehicle.get(vehicle).add(new ExitEvent(vehicle)); | ||
} | ||
|
||
public void calculateCharges() { | ||
//crossingsByVehicle.clear();//reset hashmap | ||
//For each vehicle make sure the crossing are not illegal and then calculate the charges and deduct from account | ||
for (Map.Entry<VehicleInterface, List<ZoneBoundaryCrossing>> vehicleCrossings : crossingsByVehicle.entrySet()) { | ||
VehicleInterface vehicle = vehicleCrossings.getKey(); | ||
List<ZoneBoundaryCrossing> crossings = vehicleCrossings.getValue(); | ||
if (!checkOrderingOf(crossings)) { | ||
operationsService.triggerInvestigationInto(vehicle); | ||
} else { | ||
|
||
BigDecimal charge = calculateChargeForTimeInZone(crossings); | ||
try { | ||
customerAccountService.deductChargeFrom(vehicle,charge); | ||
} catch (InsufficientCreditException | AccountNotRegisteredException ex) { | ||
operationsService.issuePenaltyNotice(vehicle, charge); | ||
} | ||
} | ||
} | ||
|
||
} | ||
|
||
private double timeFromEpochToHourOfDay(long millis){ | ||
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm"); | ||
Date resultantDate = new Date(millis); | ||
String[] timeOfDay = sdf.format(resultantDate).split(":"); | ||
return (Double.parseDouble(timeOfDay[0])+(Double.parseDouble(timeOfDay[1])/60.0)); | ||
|
||
} | ||
|
||
private BigDecimal calculateChargeForTimeInZone(List<ZoneBoundaryCrossing> crossings){ | ||
BigDecimal charge; | ||
ZoneBoundaryCrossing previousEvent = crossings.get(0);//stores the previous crossing | ||
ZoneBoundaryCrossing previousEntryEventCharged = crossings.get(0);//stores the last entry event in which you were charged | ||
long totalTimeInZone = 0; | ||
|
||
if (timeFromEpochToHourOfDay(previousEntryEventCharged.timestamp()) < 14.0){ | ||
charge= new BigDecimal(6.0);//before 2 pm | ||
}else{ | ||
charge= new BigDecimal(4.0);//2pm onwards will be 4 gbp | ||
} | ||
|
||
for (ZoneBoundaryCrossing crossing : crossings.subList(1, crossings.size())) { | ||
if (crossing instanceof ExitEvent) { | ||
totalTimeInZone += crossing.timestamp()-previousEvent.timestamp(); | ||
//For the case where you weren't charged when you entered but stayed past the 4 hour mark from the previous charge | ||
if ( (crossing.timestamp()-previousEntryEventCharged.timestamp()) > (4*HOURS_TO_MILLI_SECONDS) ){ | ||
long tmp_crossing_time = previousEntryEventCharged.timestamp()+(4*HOURS_TO_MILLI_SECONDS); | ||
if (timeFromEpochToHourOfDay(tmp_crossing_time) < 14.0){ | ||
charge = charge.add(new BigDecimal(6.0)); | ||
}else{ | ||
charge = charge.add(new BigDecimal(4.0)); | ||
} | ||
previousEntryEventCharged = new EntryEvent(crossing.getVehicle(),tmp_crossing_time);//create a phantom crossing(entry event) to make the system work | ||
} | ||
|
||
}else{ | ||
//Add Charges if previous charge was more than 4 hours ago | ||
if ( (crossing.timestamp()-previousEntryEventCharged.timestamp()) > (4*HOURS_TO_MILLI_SECONDS) ){ | ||
if (timeFromEpochToHourOfDay(crossing.timestamp()) < 14.0) { | ||
charge = charge.add(new BigDecimal(6.0)); | ||
} else{ | ||
charge = charge.add(new BigDecimal(4.0)); | ||
} | ||
previousEntryEventCharged = crossing; | ||
} | ||
} | ||
previousEvent = crossing; | ||
} | ||
|
||
//if total time spent in the zone greater than 4 hours return 12 gbp | ||
if (totalTimeInZone > (4* HOURS_TO_MILLI_SECONDS)){ | ||
return new BigDecimal(12); | ||
} | ||
|
||
return charge; | ||
} | ||
|
||
private boolean checkOrderingOf(List<ZoneBoundaryCrossing> crossings) { | ||
|
||
ZoneBoundaryCrossing previousEvent = crossings.get(0); | ||
//Even though the vehicleLeavingZone function does not allow for exit events to be registered as the first event, it is always a good idea to perform checks in multiple places | ||
if (previousEvent instanceof ExitEvent){ | ||
return false; | ||
} | ||
//Make sure a vehicle always leaves after entering (the list size is even and every Entry is followed by and Exit) | ||
if ((crossings.size() % 2) != 0){ | ||
return false; | ||
} | ||
for (ZoneBoundaryCrossing crossing : crossings.subList(1, crossings.size())) { | ||
if (crossing.timestamp() < previousEvent.timestamp()) { | ||
return false; | ||
} | ||
if (crossing instanceof EntryEvent && previousEvent instanceof EntryEvent) { | ||
return false; | ||
} | ||
if (crossing instanceof ExitEvent && previousEvent instanceof ExitEvent) { | ||
return false; | ||
} | ||
previousEvent = crossing; | ||
} | ||
|
||
return true; | ||
} | ||
|
||
} |
16 changes: 16 additions & 0 deletions
16
trafficmon/src/com/trafficmon/CustomerAccountsService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.trafficmon; | ||
|
||
import java.math.BigDecimal; | ||
|
||
/** | ||
* Created by Shoaib on 11/19/18. | ||
*/ | ||
|
||
public class CustomerAccountsService implements CustomerAccountsServiceInterface { | ||
private AccountsService registeredCustomerAccountsService = RegisteredCustomerAccountsService.getInstance(); | ||
|
||
@Override | ||
public void deductChargeFrom(VehicleInterface vehicle, BigDecimal charge) throws InsufficientCreditException,AccountNotRegisteredException { | ||
registeredCustomerAccountsService.accountFor((Vehicle) vehicle).deduct(charge); | ||
} | ||
} |
12 changes: 12 additions & 0 deletions
12
trafficmon/src/com/trafficmon/CustomerAccountsServiceInterface.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.trafficmon; | ||
|
||
import java.math.BigDecimal; | ||
|
||
/** | ||
* Created by Shoaib on 11/19/18. | ||
*/ | ||
|
||
public interface CustomerAccountsServiceInterface { | ||
|
||
void deductChargeFrom(VehicleInterface vehicle, BigDecimal charge) throws InsufficientCreditException,AccountNotRegisteredException ; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
package com.trafficmon; | ||
|
||
public class EntryEvent extends ZoneBoundaryCrossing{ | ||
public EntryEvent(VehicleInterface vehicleRegistration) { | ||
super(vehicleRegistration); | ||
} | ||
// Package-Private Method For Testing | ||
EntryEvent(VehicleInterface vehicleRegistration,long time) {super(vehicleRegistration, time);} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
package com.trafficmon; | ||
|
||
public class ExitEvent extends ZoneBoundaryCrossing { | ||
public ExitEvent(VehicleInterface vehicle) { | ||
super(vehicle); | ||
} | ||
// Package-Private Method For Testing | ||
ExitEvent(VehicleInterface vehicle, long time) { | ||
super(vehicle,time); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.trafficmon; | ||
|
||
/** | ||
* Created by Shoaib on 11/17/18. | ||
*/ | ||
|
||
public class Main { | ||
public static void main(String[] args) throws Exception { | ||
|
||
CongestionChargeSystem congestionChargeSystem = new CongestionChargeSystem(); | ||
congestionChargeSystem.vehicleEnteringZone(Vehicle.withRegistration("A123 XYZ")); | ||
//delaySeconds(15); | ||
congestionChargeSystem.vehicleEnteringZone(Vehicle.withRegistration("J091 4PY")); | ||
//delayMinutes(30); | ||
//congestionChargeSystem.vehicleLeavingZone(Vehicle.withRegistration("A123 XYZ")); | ||
//delayMinutes(10); | ||
congestionChargeSystem.vehicleLeavingZone(Vehicle.withRegistration("J091 4PY")); | ||
congestionChargeSystem.calculateCharges(); | ||
} | ||
private static void delayMinutes(int mins) throws InterruptedException { | ||
delaySeconds(mins * 60); | ||
} | ||
private static void delaySeconds(int secs) throws InterruptedException { | ||
Thread.sleep(secs * 1000); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
package com.trafficmon; | ||
|
||
import java.math.BigDecimal; | ||
|
||
public class OperationsService implements OperationsServiceInterface { | ||
private PenaltiesService OpTeam = OperationsTeam.getInstance(); | ||
|
||
@Override | ||
public void issuePenaltyNotice(VehicleInterface vehicle, BigDecimal charge) { | ||
OpTeam.issuePenaltyNotice((Vehicle) vehicle,charge); | ||
} | ||
|
||
@Override | ||
public void triggerInvestigationInto(VehicleInterface vehicle){ | ||
OpTeam.triggerInvestigationInto((Vehicle) vehicle); | ||
} | ||
|
||
|
||
} |
8 changes: 8 additions & 0 deletions
8
trafficmon/src/com/trafficmon/OperationsServiceInterface.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
package com.trafficmon; | ||
|
||
import java.math.BigDecimal; | ||
|
||
public interface OperationsServiceInterface { | ||
void issuePenaltyNotice(VehicleInterface vehicle, BigDecimal charge); | ||
void triggerInvestigationInto(VehicleInterface vehicle); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
package com.trafficmon; | ||
|
||
public class Vehicle implements VehicleInterface { | ||
|
||
private final String registration; | ||
|
||
private Vehicle(String registration) { | ||
this.registration = registration; | ||
} | ||
|
||
static Vehicle withRegistration(String registration) { | ||
return new Vehicle(registration); | ||
} | ||
|
||
@Override | ||
public String toString() { | ||
return "Vehicle [" + registration + "]"; | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) return true; | ||
if (o == null || getClass() != o.getClass()) return false; | ||
|
||
Vehicle vehicle = (Vehicle) o; | ||
|
||
return (registration != null) ? registration.equals(vehicle.registration) : vehicle.registration == null; | ||
|
||
/*if (registration != null){ | ||
return registration.equals(vehicle.registration); | ||
} | ||
return (vehicle.registration == null);*/ | ||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
return registration != null ? registration.hashCode() : 0; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.trafficmon; | ||
|
||
/** | ||
* Created by Shoaib on 11/17/18. | ||
*/ | ||
|
||
interface VehicleInterface { | ||
|
||
@Override | ||
String toString(); | ||
|
||
@Override | ||
boolean equals(Object o); | ||
|
||
@Override | ||
int hashCode(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.trafficmon; | ||
|
||
public abstract class ZoneBoundaryCrossing { | ||
|
||
private final VehicleInterface vehicle; | ||
private final long time; | ||
|
||
public ZoneBoundaryCrossing(VehicleInterface vehicle) { | ||
this.vehicle = vehicle; | ||
this.time = System.currentTimeMillis(); | ||
} | ||
//Package private constructor for testing purposes | ||
ZoneBoundaryCrossing(VehicleInterface vehicle, long time) { | ||
this.vehicle = vehicle; | ||
this.time = time; | ||
} | ||
|
||
public VehicleInterface getVehicle() { | ||
return vehicle; | ||
} | ||
|
||
public long timestamp() { | ||
return time; | ||
} | ||
} |
Oops, something went wrong.