An implementation of the coding exercise provided by LittlePay
- File is of fixed length; ie. no transient updates
- File is consistent and can be read into memory
- File is in order of ascending date and time; ie. no sort is required prior to processing
- Given the TapType is provided in the data passed to the script, another process must control the state of a PAN; ie. external software processing the card uses expiry times to denote a default tap off
- Services do not break down; ie. journeys are not interruped and a passenger always has the option to tap off and can therefore fairly be charged a full fare
- The file is an autonomous set of data; ie. there is no expected pre-status of a PAN and there are no PANs tap states to be created for another, or subsequent, file to process
- The data being read in does not require validation; if there were to be validation, then it would be added to the CSVReader and ignore any lines with failed data parsing.
The java source files are contained within the main directory and the JUnit test files are located in a test
subdirectory. A separate bin
subdirectory is utilised for storing all the generated class files.
The script and tests can be compiled with:
javac -classpath .:bin:junit-platform-console-standalone-1.9.3.jar -sourcepath test -d bin *.java test/*Test.java
From the main directory, the tests can be executed with the following command:
java -jar junit-platform-console-standalone-1.9.3.jar --class-path bin --scan-class-path
As well as a set of automated unit tests, a set of test files have been created to allow the script to be run with disparate sets of data containing expected fail points. These have been stored in the test_csv_files
subdirectory.
The script to process the fares is run from the command line using the following:
java -cp bin LittlePay <taps CSV input filename> [separator] [trips CSV output filename]
This is a path and filename to the CSV file to be processed; as described in the documentation, this is expected as a well-formed file; therefore there is no data validation on the fields read in.
This is an optional field to specify a particular separator; the default is a comma.
An optional filename for the output CSV file within an existing path. The default is trips.csv
.
Any fatal errors from the script will exit with an error message and a related status code.
Runtime, non-fatal, errors will be output to stderr
during processing.
The script will calculate the appropriate fares between stops; the following conditions are also processed:
This can only occur if, as stated in the assumptions, an external process is determining a time-out or expiry of the tap status. Therefore, the previous tap on is charged at full fare.
This entails an issue in the status handling of the external software providing the data, so an error will be raised.
As this is an autonomous process, the remaining PANs that are currently tapped on will be charged a full fare.
The FareProcessor has been developed for an efficient lookup, entailing an expanded initial data configuration. This is to facilitate longer single setup but a quicker iterative fare lookup; as the data is determined to be well-formed in the source file, there is no additional validation on an invalid stop id being passed in.
The fare processor is external to the bus stop processing to allow different fare processors to be utilised; is not particularly necessary for the example but allows for more flexibility.
In a more expandable design, the data would not be stored internally but in a separate data source.
The exercise states that the tap on and off is at the bus stop but the data contains a bus id, which does not really correlate as the tap on and off would have to be on the bus itself to provide that data.