Second test: sample task
NB! This task will probably take you more time than usually. During the test, there will a similar task, but a bit shorter. We strongly recommend you to solve this task in order to get invaluable experience and learn from own mistakes.
1. Task description
The task is to write a program for a company which repairs computers.
At the beginning of a day, the program is launched from the command line with one argument - a reference to the recourse with jobs to be done today (a job is a description of one computer to be repaired). The program reads in the jobs into an appropriate data structure and proceeds with a loop. On each iteration of the loop, the user is prompted for a task he wants to do next: to repair (P
), to register a new job (R
) or to finish a working day (F
).
2. An example of the program output
Line: Ordi@2017-04-21T14:00:23 Error explanation: The number of fields is incorrect! Do you want to repair (P), register a new job (R) or finish (F) ? P Computer info: Lenovo;urgentjob@2017-04-21T14:22:42 Enter the time in minutes spent on the repair: 142 Enter your name: Jan The job is completed. Invoice: 59.33€ Do you want to repair (P), register a new job (R) or finish (F) ? R Enter the job description: Dell;ordinaryjob;mnitor Invalid input! The value of the third field is not "monitor"! Enter the job description: Dell;ordinaryjob;monitor The job is registered! Do you want to repair (P), register a new job (R) or finish (F) ? P Computer info: ML;urgentjob;monitor@2017-04-21T14:08:09 Enter the time in minutes spent on the repair: 42 Enter your name: Peter The job is completed. Invoice: 36.45€ Do you want to repair (P), register a new job (R) or finish (F) ? P Computer info: Dell;ordinaryjob;monitor@2017-04-20T13:08:30.080 Enter the time in minutes spent on the repair: 75 Enter your name: Peter The job is completed. Invoice: 44.88€ Do you want to repair (P), register a new job (R) or finish (F) ? F Session summary: Earned sum of money: 140.66€ Repaired computers: Lenovo: 1pcs Dell: 1pcs ML: 1pcs There are 2 computer(s) in the queue left to be repaired next time.
3.Guidelines how to start solving the task
3.1 The main class
The main class should be named as ComputerRepair
and placed into the default package.
3.2 Classes Laptop
and Desktop
.
In order to create a list of job, create two classes into the default package: Laptop
and Desktop
. The Desktop
class should be a subclass of the Laptop
class. Do not duplicate the fields and methods of the superclass in the subclass. The instances of both classes should have the following methods to retrieve the data about a computer:
String getBrand()
boolean getIsUrgentJob()
java.time.LocalDateTime getRegistrationDateTime()
Also there should be a method called calculateInvoice
which takes in an argument for the base price (double
) and returns the sum to pay (the rules of the sum calculation are given further in the task - subtask 3.4).
NB! These methods should be accessible everywhere.
3.3 Job list management
Initial job list
A reference to the initial job list is given as a command line argument. The reference might be a file name or a webpage. You can assume if the first argument in the command line starts with http://
or https://
, then the reference is a webpage; otherwise, it is a file name. In both resources, the data is in the text format (the UTF-8 encoding).
Hint (check after you have tried to solve this subtask)
if (ref.startsWith("http://") || ref.startsWith("https://")) s = new URL(ref).openStream(); else s = new FileInputStream(ref); BufferedReader bf = new BufferedReader(new InputStreamReader(s, "UTF-8"));
Note: reading the text lines should be done in the main methods; a line processing should be done in a method called readComputer
(see the next section).
In both resource, the text consists of lines; each line contains information about one job. A job description has the following fields (separated by a column): computer's brand name, job type ("urgentjob" or "ordinaryjob"). If the computer is a desktop, the job type is followed by the keyword ;monitor
. After that there is a symbol @ followed by the registration date and time.
Example:
*Lenovo;ordinaryjob
*Ordi;urgentjob;monitor
During the data reading in from the file, an object of the corresponding class is created for each line and added to the collection of jobs (check a method readComputer
described in the next section). For all invalid lines, the program outputs a message with an explanation. If an exception occurs with reading the resource e.g. file is not found or reading from the web is failed (the exception is not connected to data processing), the exception has to be printed out and the program has finish its work.
Method ComputerRepair.readComputer
In the main class, there should be a method called readComputer
(the method might be static) which takes in a job description as a string argument and returns an object of the Laptop
or Desktop
type.
If a job description does not contain @ followed by the registration date and time, the object registration field should be assigned the time when the string has been taken to processing.
If the format of the string does not meet the requirements, the readComputer
method should throw an exception. Hence, create an exception class called FormatException
. The thrown out exception should contain a description of the exception. FormatException
should be thrown out in the following cases (you can assume that no other input exception occurs):
- the number of fields separated by columns is smaller that two or larger than three;
- the job type is neither "ordinaryjob" nor "urgentjob";
- there are three fields in the job description, but the value of the third field is not "monitor".
NB! The readComputer
method is a method of the main class; it should not be accessible from anywhere else.
Hint: LocalDateTime#parse
Hint: LocalDateTime#now
Hint (check after you have tried to solve this subtask)
private static Laptop readComputer(String line) { int at = line.lastIndexOf('@'); LocalDateTime regTime; if (at != -1) { regTime = LocalDateTime.parse(line.substring(at + 1)); line = line.substring(0, at); } else { regTime = LocalDateTime.now(); } String[] parts = line.split(";"); if (parts.length < 2 || parts.length > 3) // add an exception handler if (!parts[1].equals("ordinaryjob") && !parts[1].equals("urgentjob")) // add an exception handler if (parts.length == 3 && !parts[2].equals("monitor")) // add an exception handler boolean isUrgentjob = parts[1].equals("urgentjob"); if (parts.length == 3) return new Desktop(parts[0], isUrgentjob, regTime); return new Laptop(parts[0], isUrgentjob, regTime); }
Register new job
If the user wants to register a new job, he has to do it taking into account the format of the job description; however, the user do not have to enter the registration date, time and symbol @. Once a description of a new job is entered in the appropriate way, the program adds the job of the Laptop
or Desktop
type to the job collection. If the entered job description is invalid, the program prompts the user for the job description again until the user enters the job in the appropriate format. Each time the user enters an invalid job description, the program outputs the error description.
3.4 Computer repair
If the user wants to repair a computer, he is given one of the urgent jobs; if there are no urgent jobs, the master is given one of the ordinary jobs. The program shows the job description and holds on until the user enters the time spent on the computer repair (the whole minutes) and his name. After that the invoice has to be calculated, and the job is completed.
Calculate job invoice
The base price of a job is calculated as follows: the time spend on the computer repair times master's payment rate per hour. To get the total price of the repair, the base price is added the fixed sum of 2€ for a laptop or 3€ for a desktop. If the job is urgent, an additional fee of 10€ is added to the base price.
The masters' payment rates per hour are stored in a file called payment_rate.dat. This is a binary file created with the help of the java.io.DataOutputStream
class. On the first line of the file, there is the number of masters (int
) followed by the name of each master (String
) and his payment rate (double
). In other words, the structure of the .dat file looks like this:
- number of masters
- name of the first master
- payment rate of the first master
- ...
- name of the last master
- payment rate of the last master
3.5 Completed and not completed jobs
Before the program exits, the program saves the completed jobs into a file called completed.dat using the java.io.DataOutputStream
class. The file should have the following structure: the number of the completed jobs (int
) followed by the brand name of each repaired computer (String
), registration time (String
, use the toString
method of the LocalDateTime
class) and the sum to be paid (double
). NB! If there is a file with the same name, rewrite the content of the file.
The incompleted jobs have to be saved into a file called queue.txt using the UTF-8 encoding and the initial format.
Summary on jobs
The summary of the jobs has to be output at the end of the program execution session. The summary should contain information about the earned amount of money, the brand names of the repaired computers, the number of repaired computers of each brand, and the number of the jobs in the queue left for the next time.
Hint (check after you have tried to solve this subtask)
private static void showSummary(double sum, Map<Laptop, Double> completed, int incompleted){ System.out.println("Session summary:"); System.out.println("Earned sum of money: "+ Math.round(sum*100.0)/100.0 +"€"); System.out.println("Repaired computers: "); Map<String, Integer> differentComputers = new HashMap<String, Integer>(); for (Laptop computer : completed.keySet()){ String brandName = computer.getBrand(); if (differentComputers.containsKey(brandName)){ int numOfBrand = differentComputers.get(brandName)+1; differentComputers.put(brandName, numOfBrand); } else differentComputers.put(brandName, 1); } for (String brandName : differentComputers.keySet()) System.out.println(" "+ brandName +": "+differentComputers.get(brandName)+"pcs"); System.out.println("There are "+ incompleted +" computer(s) in the queue left to be repaired next time."); }
4. Data files
It is recommended to create your own data files. Think about the records which would test the program efficiently and help discover bugs in the program.
If it is too difficult to compose the files, use these: computers.zip.
To test data reading from a webpage, use : https://courses.cs.ut.ee/2018/oopn/spring/uploads/Main/computers.txt
Strong recommendations
- Reading the data with the aid of the
Scanner
class should be well-practised by now. Therefore, try to use other streams for reading from a file. - The code should be possibly easily readable!
- If possible, place subtasks into separate methods!
- If you notice that you copy-paste lines of code, try to place these lines of code into a separate method.
- Check if polymorphism, inheritance and data structure are used appropriately!
- All the fields have to be private and non-static!!
If the program cannot be compiled, 0 points will be awarded.