By: Team CS2103-T11-1 Since: October 2019 Licence: MIT
Refer to the guide here.
The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
|
💡
|
The .puml files used to create diagrams in this document can be found in the diagrams folder.
Refer to the Using PlantUML guide to learn how to create and edit diagrams.
|
Main has two classes called Main and MainApp. It is responsible for,
-
At app launch: Initializes the components in the correct sequence, and connects them up with each other.
-
At shut down: Shuts down the components and invokes cleanup method where necessary.
Commons represents a collection of classes used by multiple other components.
The following class plays an important role at the architecture level:
-
LogsCenter: Used by many classes to write log messages to the App’s log file.
The rest of the App consists of four components.
Each of the four components
-
Defines its API in an
interfacewith the same name as the Component. -
Exposes its functionality using a
{Component Name}Managerclass.
For example, the Logic component (see the class diagram given below) defines it’s API in the Logic.java interface and exposes its functionality using the LogicManager.java class.
The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1.
The sections below give more details of each component.
The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, PersonListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class.
The UI component uses JavaFx UI framework. The layout of these UI parts are defined in matching .fxml files that are in the src/main/resources/view folder. For example, the layout of the MainWindow is specified in MainWindow.fxml.
The UI component,
-
Executes user commands using the
Logiccomponent. -
Listens for changes to
Modeldata so that the UI can be updated with the modified data.
-
Logicuses theIncidentManagerParserclass to parse the user command. -
This results in a
Commandobject which is executed by theLogicManager. -
The command execution can affect the
Model(e.g. adding a person). -
The result of the command execution is encapsulated as a
CommandResultobject which is passed back to theUi. -
In addition, the
CommandResultobject can also instruct theUito perform certain actions, such as displaying help to the user.
Given below is the Sequence Diagram for interactions within the Logic component for the execute("delete 1") API call.
|
ℹ️
|
The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
|
The Model:
-
Stores a
UserPrefobject that represents the user’s preferences. -
Stores the Incident Manager data.
-
Exposes an unmodifiable
ObservableList<Person>that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. -
Does not depend on any of the other three components.
The Person:
-
Represents a user account on the incident manager.
-
Contains the account
Username,Password,Name,Phone,Email
The Incident:
-
Represents an incident report in the incident manager.
-
Contains the attributes
CallerNumber,Description,IncidentDateTimeand IncidentId`. -
Also contains a
Personobject representing the 'Operator' who filed the incident, aDistrictwhich represents the location of the incident, and aVehiclerepresenting the vehicle dispatched to investigate this incident. -
Has three states encapsulated by a
Statusenum -INCOMPLETE_DRAFT(report not completely filled and not submitted),COMPLETE_DRAFT(report completely filled but not submitted), andSUBMITTED_REPORT(report completely filled and submitted).
The Storage component:
-
Can save
UserPrefobjects in json format and read it back. -
Can save the Incident Manager data in json format and read it back.
This section describes some noteworthy details on how certain features are implemented.
The access control feature is centered around three core concepts:
-
Command Restrictions: Restriction of access to commands until after identity is verified
-
Identity Verification: Verification of identity via unique credentials and a confidential key
-
Account Management Restrictions: Access level restrictions for commands affecting other accounts
Prior to login, the user is only granted access to the Login, Register, Help, and Exit commands. This is achieved via a guard statement in the IncidentManagerParser checking whether the user is logged in or the command created is an approved command that doesn’t require login.
|
ℹ️
|
The guard statement throws a command exception and informs the user of the available commands prior to login. |
Activity Diagram for illustration:
Users are required to login via the Login command with a Username and Password. See user guide for more details on the command syntax for Login. Users are also allowed to Logout and thus end their Session.
|
ℹ️
|
Session details are displayed on the status bar in the GUI to reflect whether a user is logged in, and the username as well as time logged in if a user is logged in. |
Class Diagram for illustration:
Uniqueness of a username is ensured by preventing duplicates during the account creation [RegisterCommand] and account update [UpdateCommand] processes. The respective commands will check the list of accounts in the model and throw an exception if a duplicate is found.
To prevent abuse (e.g. adding a dummy account and editing/deleting other accounts), all new accounts are differentiated from Admin accounts. This restriction based on access level is implemented via account Tags:
-
Only a
Personwith an adminTagcan access account management features. Such a person will henceforth be referred to as an Admin. -
Users who are not admins are not allowed to add tags (via both
RegisterCommandandUpdateCommand). -
Only Admins are allowed to edit or add tags (via both
RegisterCommandandUpdateCommand).
|
ℹ️
|
Non-admins can still edit their own account details via the UpdateCommand. Refer to user guide for more info.
|
Additional access restrictions:
-
Only admins can update an account that is not their own.
-
Only admins can access the delete command.
-
Admins cannot delete their own account.
-
Admins cannot 'downgrade' themselves by removing their own admin tag.
The checks described above all function in the command execution stage. The RegisterCommand, UpdateCommand, and DeleteCommand retrieves the logged in Person from the Model via utilisation of the Session.
Simplified Sequence Diagram for illustration:
|
ℹ️
|
The lifeline for DeleteCommand should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of the diagram. |
-
Current Choice: Guard statement in IncidentManagerParser prior to Command Creation.
-
Pros: Early catching of restriction, command doesn’t get instantiated unnecessarily. Better user experience as error message is displayed early.
-
Cons: Need to expose model to parser as session is managed by model, increasing coupling.
-
-
Alternative: Guard statement in LogicManager prior to Command Execution.
-
Pros: Model does not need to be exposed to parser as it is already managed by command execution, decreasing coupling.
-
Cons: Command still gets instantiated, memory allocated to command creation. Decreases user experience as user still has to type a proper command before the access error is thrown.
-
-
Current Choice: Unique username and password.
-
Pros: Easy to implement.
-
Cons: Sufficiently advanced users can access the data file directly to retrieve user passwords.
-
-
Alternative: Physical security USB dongle.
-
Pros: Secure individually identifiable token.
-
Cons: Prone to loss and potential duplication. Hard to implement.
-
-
Current Choice: Utilisation of Account Tags
-
Pros: Easy to implement.
-
Cons: Easy to exploit, requires additional restrictions (e.g. users cannot add tags unless they are an admin).
-
-
Alternative: Addition of an Admin account attribute.
-
Pros: Distinct object class, improves cohesiveness.
-
Cons: Hard to implement.
-
The account management feature functions as a suite of commands available to the user. The commands available as part of this suite:
-
Register Command - Creates a new user account.
-
Update Command - Edits a user account. Not including an index updates your own account.
-
Delete Command - Deletes a a user account. Not allowed to delete your own account.
-
List Persons Command - Lists all user accounts or those whose tags match the user input.
-
Find Persons Command - Searches for user accounts based on matching name or username keywords.
-
Swap Command - Swaps GUI interface between account management and incident management.
|
ℹ️
|
Users are restricted from accessing commands affecting objects not on display. They need to invoke Swap to access the different command suites.
|
Only Admin accounts can access the full suite of account management features. See access control feature for more information. Non-Admins only have access to Register, List, Find, and Swap commands, as well as Update for their own account.
In the code base, Persons represent user accounts. See person model for more information.
-
Current Choice: Utilising a swap command that transitions between two distinct interfaces.
-
Pros: Distinct difference in command suite utilisation (account vs incidents), giving users a much cleaner distinction of what’s being managed, improves user experience.
-
Cons: Hard to implement.
-
-
Alternative: Having account information display alongside incidents and vehicles in a separate pane.
-
Pros: Easy to implement.
-
Cons: User might be overloaded with information in one screen, and text might get truncated in lower resolutions, decreases user experience.
-
-
Current Choice: No index indicates own account update
-
Pros: Improves user experience, user does not need to look for their own index.
-
Cons: Susceptible to user error.
-
-
Alternative: Select index of own account for update
-
Pros: Easy to implement.
-
Cons: Decreases user experience, user will first need to find their own index.
-
-
Current Choice: Adding keywords after the list command performs a search
-
Pros: Does not require argument prefixes, improves user experience.
-
Cons: Decreases system cohesiveness as searching is performed in two separate commands.
-
-
Alternative: Utilising find command to search for tags
-
Pros: Centralise all account search operations in one command, improves system cohesiveness.
-
Cons: Requires the addition of argument prefixes, decreases user experience.
-
The incident draft creation mechanism is facilitated by the New Command. It creates a new draft incident report based on district of incident, optional automatic vehicle dispatchment. As of now, when there is no vehicle available in the district of incident, a new report cannot be generated.
If created successfully, the draft incident only has three fields filled: operator, district and vehicle dispatched.
There are two ways to use the New Command: 1. Auto dispatchment 2. Manual dispatchment, which requires user to provide a valid index that selects a vehicle
Vehicle will be automatically assigned to the incident draft if any is available in the district. If no vehicle is available, an exception will be thrown.
Below is a sequence diagram of a successful case:
User first obtains list of vehicles available in specified district with new dist/DISTRICT auto/n, which prompts user for index of vehicle to dispatch. Note that this list can only be obtained with the input new dist/DISTRICT auto/N, and not based on the list of vehicles currently displayed.
User then inputs the index of vehicle based on the list of available vehicle in given district to dispatch. If no index is provided, or the index is not valid, an exception will be thrown and user will be prompted to provide a valid index.
Below is an activity diagram illustrating the above:
For auto vehicle assignment:
-
Current Choice: Taking first vehicle on list of available vehicles in district.
-
Pros: Easy to implement
-
Cons: May not be the vehicle nearest to the incident site in real life, thus may not be optimal.
-
-
Alternative: Add details to location of vehicles to actually allocate the vehicle closest to the incident site.
-
Pros: Optimal efficiency in dispatching vehicles.
-
Cons: Difficult to implement; we do not have enough time.
-
Fro manual vehicle assignment:
-
Current Choice: Throw exception to prompt user to enter index of vehicle to dispatch.
-
Pros:
-
User need not key in the entire new command again, only need to add the relevant prefix and index.
-
Easy to implement.
-
-
Cons: May not seem logical to throw an exception for this.
-
-
Alternative: Show prompt message as a command result instead of exception message.
-
Pros: Logically seems to make more sense.
-
Cons: User has to retype the entire command, potentially a waste of time.
-
The incident filling and submission subroutines are facilitated by the fill and submit commands respectively.
In the IMS, each incident can have one of three statuses - INCOMPLETE_DRAFT, COMPLETE_DRAFT, and SUBMITTED REPORT.
These three statuses are maintained by an enum in Incident. Executing the fill command changes the status of
drafts (complete or incomplete) into COMPLETE_DRAFT while the submit command changes the status of only COMPLETE_DRAFTS to SUBMITTED_REPORT.
To prevent potential misuse, only the operator who has created the incident report is allowed access to execute the fill and submit commands on that report.
Each command works in two modes:
-
Without parameters: In this mode, the command -
fillorsubmit- lists the incidents that are ready for Filling (i.e. only all complete and incomplete drafts) or Submitting (i.e. only all complete drafts). -
With parameters: In this mode, the command -
fillorsubmit- actually fills (i.e. makes incident statusCOMPLETE_DRAFT) or submits (i.e. changes incident status fromCOMPLETE_DRAFTtoSUBMITTED_REPORT) the specified incident.
The implementation of these two modes is discussed below. As both fill and submit are rather similar in their implementation, a detailed discussion of only the fill command is given below.
This mode leverages the ability of the ListIncidentsCommand to list incidents by different predicates.
When the IncidentManagerParser parses a fill command without parameters, it returns a new ListIncidentsCommand
with predicate Incident::isDraft. This ListIncidentsCommand is then executed as per usual.
For the submit command, the predicate Incident::isCompleteDraft is used instead.
-
For the
fillcommand with parameters, theFillCommandParserwill be invoked to parse the fieldstargetIndex,callerNumber, anddescriptionand return aFillCommandcontaining these non-null fields. -
The
execute()method inFillCommandwill then retrieve the specified incident if there are drafts to be filled and if the index is valid. -
Two helper methods -
processReportFillingandfillReport- will complete the filling process.fillReportreturns a newIncidentwhich is a copy of the incident report to be filled, but with the specified caller and description details and aCOMPLETE_DRAFTstatus. -
The old incident report will be removed from the system and be replaced with the new updated incident report.
-
The new incident report is placed at the front of the incident list for easy access.
In this sequence diagram, the helper methods within FillCommand are omitted for clarity.
The SubmitCommand functions similarly, with one crucial difference. As no Incident fields are to be updated, the specified incident is simply retrieved, and its fields are copied into a new Incident object with a SUBMITTED_REPORT status.
-
Current choice: Use
ListIncidentscommand with appropriate predicate to fulfillfillandsubmitfunctionalities in no-parameter mode.-
Pros:
-
Intuitive and convenient to use. If user needs easy access to reports that can be filled or submitted, they do not need to remember a new command keyword.
-
Requires lesser code. Abstraction of the filtered listing subroutine reduces the amount of redundant code.
-
-
Con: 1. Might be potentially confusing to user as
FillCommandis performing a function of listing that is extraneous to the function of filling.
-
-
Alternative 1: Extend
FillCommandto create two child classesFillCommandNoParamsandFillCommandWithParams.-
Pros:
-
Better use of the OOP principle of inheritance.
-
Reduce coupling between
ListIncidentsCommandandFillCommand.
-
-
Cons:
-
Increases amount of code and hence marginally reduces app performance as one additional new class needs to be created.
-
Misleading use of abstraction as the
FillCommandNoParamsis technically not performing the function of filling but that of listing.
-
-
-
Alternative 2: Separate the 'listing' and the 'filling' aspect by using separate command words.
-
Pro: 1. Most appropriate use of abstraction and single responsibility principle, which are crucial OOP concepts.
-
Con: 1. User needs to either remember an additional command word or type a longer
list-icommand by specifying the filter predicate, which reduces user convenience.
-
-
Current choice: Both
callerNumberanddescriptionfields need to be specified when filling specified incident report. The other incident report fields are auto-filled and can only be changed by using theeditcommand once the incident report has been submitted.-
Pros:
-
Improved accountability. Prevents a user from changing the most important fields of the incident report, such as
incidentId,incidentDateTime, andvehicle, without first committing the report into the system. -
More convenient for the user as they only have to specify 2 report fields instead of 6 or 7.
-
-
Con: 1. User is unable to fill
callerNumberindependently ofdescriptionunless they first submit the incident report and then use theeditcommand.
-
-
Alternative 1: Combine
fillandsubmitfunctions i.e. filling a report completely will automatically submit it.-
Pros:
-
Easier to implement as Incident reports have two statuses - DRAFT or SUBMITTED - instead of three.
-
More convenient as this results in one less step in the user’s workflow and one less command word for the user to remember.
-
-
Con: 1. Less adaptable and modular. If new fields are added to the incident report, then the user might want to enter / replace those fields by executing repeated fill commands without committing the report into the system with incomplete / likely to change information.
-
-
Alternative 2: Allow
fillcommand to fill variable number of fields.-
Pro: 1. Satisfies the cons of the two approaches above as it is versatile enough to allow the user to independently fill different incident report fields as well as adaptable enough to accommodate extra fields.
-
Con: 1 . Harder to implement as we would need more elaborate methods to parse the variable arguments.
-
A user cannot independently fill the various incident report fields unless they first submit the incident report. This might be an acceptable issue it encourages users to completely fill a new incident report before submitting it, which reduces the likelihood of finding incomplete drafts in the system.
The incident search mechanism features a set of different types of searches that a user could utilise to list out all related incidents, inclusive of incomplete drafts, complete drafts and completed reports. Further documentation on the commands available in this set can be found in the User Guide. The types of searches are as listed:
-
Unfiltered - Displays all incidents in
Model
eg.list-i -
ID - Displays all incidents with exact matches in
IncidentId incidentIdinIncident incident, withinModel
eg.find-i id/0620150001 -
Description - Displays all incidents with keyword(s) contained within the
Description descriptioninIncident incident, withinModel+ eg.find-i desc/traffic -
Operator - Displays all incidents with keyword(s) contained within the name of the
Person operatorinIncident incident, withinModel
eg.find-i op/bill -
Operator - Displays all incidents with the name of the
Person operatorinIncident incidentmatching the logged-in user’s name exactly, withinModel
eg.find-i self
-
Each parameter in
find-isearch commands can be combined in any order and quantity, returning only results that abide by all filtering by each parameter used -
Search by keywords is case-insensitive
-
Each parameter in
find-iaccepts multiple keywords, and searches for matches containing any of these keywords
The incident search mechanism is facilitated by ModelManager, which implements abstract class Model. It contains a FilteredList<Incidents> filteredIncidents, which internally stores the list of displayed incidents in the GUI. Additionally, it implements the following key method:
* updateFilteredIncidentsList(Predicate<Incident> predicate) - Updates the stored filtered incidents list with the new predicate
There are two possible commands within this set of searches. Firstly, we will consider when the user calls the command list-i in the application.
The following sequence diagram shows how the list-i command works:
As indicated in the diagram, the LogicManager instantiates a ListIncidentsCommand upon running command execute(list-i). It then calls ListIncidentsCommand#execute(), which runs Model#updateFilteredIncidentList with the predicate PREDICATE_SHOW_ALL_INCIDENTS. This Predicate<Incident> always evaluates to true. This Predicate<Incident> is passed to FilteredList<Incident> filteredList, as a parameter to run the method setPredicate(). This updates the list of visible incidents. CommandResult commandResult is also returned to the LogicManager to log the success/failure of the method.
Next, we will look at an example in which the user calls search to look for incidents written by an operator whose name contains Alex.
The execution of this method is a little more complex.
The following sequence diagram shows how the search command identifies the keyword and flag, and returns related incidents:
The key difference is the utility of the SearchIncidentsCommandParser to parse the keyword after tag op\ in the command. It creates a NameKeywordsPredicate using the String "Alex", which is returned to be used in constructing a new instance of SearchIncidentsCommand, stored as a Predicate<Incident> predicate. From there, the process is similar, in that SearchIncidentsCommand#execute() is run, causing the Model to run Model#updateFilteredIncidentList(predicate) using the predicate stored in SearchIncidentsCommand. Upon updating the list similar to the incidents listing command above, SearchIncidentsCommand also calls Model#getFilteredIncidentList() to return ObservableList<Incident>. It obtains the size of this list, and returns it in CommandResult commandResult.
-
Current choice: Parse user input after flag (eg.
op\ordesc\)-
Pros: Easy to implement.
-
Cons: Have to parse keyword from command and flag, user has to follow style of flag for successful search.
-
-
Alternative: Prompt user for search input
-
Pros: Separates command from keyword for ease of reading and parsing.
-
Cons: Difficult to implement multi-command execution.
-
-
Current choice: Utilise separate command
incidents-
Pros: Intuitive to use.
-
Cons: Similar code under different command.
-
-
Alternative: Utilise
searchcommand (eg.search unfiltered)-
Pros: Less overlap in code.
-
Cons: Unintuitive to the user as no search is being made, even more keywords to remember.
-
-
Current choice:
SearchIncidentsCommandParserclass callsModelto create a new Predicate based on search string.-
Pros: Abstracts the creation and management of predicates to the
Model. -
Cons: Requires greater level of coupling between classes.
-
-
Alternative:
SearchIncidentsCommandorSearchIncidentsCommandParserdirectly create Predicate based on search string.-
Pros: Less dependencies within the parser class.
-
Cons: Breaks abstraction flow.
-
The incident edit mechanism is facilitated by EditCommand class. Validity of user input is checked when execute() is called and an exception is thrown if invalid.
The user can choose to put in any number of fields for editing. There are 2 ways to use the “edit-I” command: 1. ‘edit-I’ without any inputs will filter the incident list to display all incidents available for editing 2. ‘edit-I’ with fields identified for editing.
An exception will be thrown under these 2 conditions:
-
index.getZeroBased() >= listOfIncidents.size() -
!incidentToEdit.equals(editedIncident) && model.hasIncident(editedIncident)
Below is an activity diagram to illustrate the process that the user may go through
EditIncidentCommand` class makes use of EditIncident object to create a new
Incident object with the fields identified by user as well as the untouched
fields from the original incident. This new Incident will replace the original
Incident object in the incident list.
Below is a sequence diagram to illustrate how the command executes:
The command can only be used by admin accounts or accounts that created/filled/submitted the incident report. This is to prevent sabotage or accidental edits from operators who may not be familiar with the incident.
-
Current Choice: A new incident object with edited fields is created and used to replace the old incident object in the list.
-
Pros: This reduces direct changes to incident objects, hence
EditIncidentCommanddoes not have access toIncidentinternal structure. This helps reduce content coupling between the 2 classes and also makes the program easier to test. -
Cons: A new
Incidentobject is created every time user input is valid, hence may require more memory to run. It also requires the usage of the “EditIncident” class, increasing the complexity of the codebase.
-
-
Alternative: Direct edit of the attributes of incident to be modified
-
Pros: Easier to implement. Less objects created and less classes involved in the function.
-
Cons: High coupling since
EditIncidentCommandwill need to have access to internal details ofIncidentclass in order to directly modify the contents of the object. This will cause the system to be harder to test and maintain.
-
These are the commands available to the user related to vehicle management:
-
Changing the details of a vehicle:
edit-v -
Adding a new vehicle:
add-v -
Deleting a vehicle:
delete-v
|
ℹ️
|
Only vehicles with the status Avaliable are valid for editing or deleting. This is to prevent removing or changing the details of a vehicle that is currently being dispatched.
|
-
Only accounts with admin access are eligible to delete vehicles
Implementation of edit-v is similar to edit-i where EditVehicleCommand makes use of EditVehicle class to create a new Vehicle object with the modified fields and replaces the original object. Design considerations are also similar to that of edit-i.
Below is a sequence diagram to illustrate the process and classes involved in the edit-v command:
-
Current Choice: new Vehicle object is created in the parser and
AddVehicleCommandtakes aVehicleobject in the constructor.-
Pros: compliant with principle of data abstraction since
AddVehicleCommandonly receives a vehicle object that needs to be added and does not need to know how the object is created. -
Cons: Vehicle object needs to be created in the parser. Increases coupling of parser and vehicle model.
-
-
Alternative:
AddVehicleCommandtakes in the fields from parser and creates theVehicleobject in theexecute()method ofAddVehicleCommandclass-
Pros: Vehicle object does not need to be created in the parser.
-
Cons: Constructor for
AddVehicleCommandandVehiclewill be highly similar and almost overlap in functionality. The parameters for creating a vehicle will have to be passed twice.
-
Below is a sequence diagram to illustrate add-v:
-
Current Choice: Vehicle object is taken from the list in model and
DeleteVehicleCommandtakes in theVehicleobject to be deleted and identifies it from the list using the signatures of the object.-
Pros: Reduces coupling. By passing a vehicle object instead of the index will mean that
DeleteVehicleCommandneed not know the state of the filtered vehicle list. -
Cons: Requires the vehicle list in to be unique and the signatures of
Vehicleobjects need to be specific. Methods fromModelManagerneeds to be access from bothDeleteVehicleCommandParserandEditVehicleParser. Increases coupling.
-
-
Alternative:
DeleteVehicleCommandcan take in the index of the vehicle to be deleted and delete from the list by identifying the vehicle using the index.-
Pros: Easier implementation
-
Cons: DeleteVehicleCommand needs to know the state of the filtered list. Increases coupling.
-
Below is a sequence diagram to illustrate delete-v:
The vehicle search mechanism features a set of different types of searches that a user could utilise.The types of searches are as listed:
-
Unfiltered - Displays all vehicles in
Model.
e.g.list-v -
District - Displays all vehicles with
District districtin list of specified districts.
e.g.find-v dist/1 2 3 -
Vehicle Number - Displays all vehicles with
VehicleNumber vehicleNumberKeywordinVehicle vehicle. Need not be exact matches.
e.g.find-v vnum/2 -
Vehicle Type - Displays all vehicles with exact matches in
VehicleType vehicleTypeinVehicle vehicle.
e.g.find-v vtype/patrol car
Further documentation on the commands available in this set can be found in the User Guide.
-
Current choice: Parse user input after flag (eg.
dist/orvnum/)-
Pros:
-
Easy to implement.
-
Reduce number of steps of input, more efficient.
-
-
Cons:
-
Have to parse keyword from command and flag, user has to follow style of flag for successful search.
-
User might have to remember too many flags.
-
-
-
Alternative: Prompt user for search input
-
Pros:
-
Separates command from keyword for ease of reading and parsing.
-
User need not remember flags and will not confuse flags, just key in information as prompted.
-
-
Cons:
-
Difficult to implement multi-command execution.
-
Requires multiple steps of input, slower and less efficient.
-
-
-
Current choice: Utilise separate command
list-v-
Pros:
-
Intuitive to user, as it contains clear action word.
-
Consistent with other list commands.
-
-
Cons:
-
Some users might find it more intuitive to simply call
vehicles.
-
-
-
Alternative: Utilise separate command
vehicles-
Pros: Intuitive for some.
-
Cons: Appears separate from other list commands even though they are of the same nature and implemented similarly.
-
We are using java.util.logging package for logging. The LogsCenter class is used to manage the logging levels and logging destinations.
-
The logging level can be controlled using the
logLevelsetting in the configuration file (See Section 3.10, “Configuration”) -
The
Loggerfor a class can be obtained usingLogsCenter.getLogger(Class)which will log messages according to the specified logging level -
Currently log messages are output through:
Consoleand to a.logfile.
Logging Levels
-
SEVERE: Critical problem detected which may possibly cause the termination of the application -
WARNING: Can continue, but with caution -
INFO: Information showing the noteworthy actions by the App -
FINE: Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size
Refer to the guide here.
Refer to the guide here.
Refer to the guide here.
Target user profile: Emergency Services Call Operator
-
needs to quickly dispatch emergency vehicles
-
has a need to manage a significant number of incidents
-
prefer desktop apps over other types
-
can type fast, prefers typing over mouse input
-
is reasonably comfortable using CLI apps
Value proposition: manage incidents and vehicle dispatch faster than a typical mouse/GUI driven app
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
|
new user |
see usage instructions |
refer to instructions when I forget how to use the App |
|
operator |
log into the system with a password |
secure the system against unauthorised access |
|
operator |
log into the system with a unique identifier |
hold accountable others who use the system |
|
new user |
create an account |
log into the system to manage incidents |
|
operator |
open the app |
I can dispatch personnel and record an incident |
|
operator |
view available vehicles |
I can dispatch vehicles |
|
confused operator |
automatically prevent sending of non available vehicles |
I won’t be allowed to send occupied vehicles |
|
operator |
to select a vehicle |
it would be dispatched |
|
operator |
to contact the dispatched vehicle and confirm it has been selected |
it would be dispatched |
|
operator |
an ID to be generated for my summaries |
my reports can be tagged for easy search |
|
operator |
to have prompts for fields |
I know the information required |
|
careless operator |
edit the report |
I won’t have to retype everything |
|
operator on shift |
to save the case for future retrieval |
So that others can reference it locally |
|
operator handling many cases |
to quickly find relevant parties |
I can submit the incident log |
|
regular operator |
to view the phone number |
I can contact the caller whenever necessary |
|
regular operator |
to view the address |
I can dispatch personnel based on proximity to address |
|
operator who likes visual cues |
to view the vehicles on patrol on a map |
I have a visual on who to dispatch |
|
As an operator |
to view the available vehicles in descending order of proximity to site |
the vehicle can reach the incident site asap |
|
As an overwhelmed operator |
to filter the available vehicles |
I won’t get confused over which vehicle to send |
|
As a tired operator |
warning prompt when I select the least optimal available vehicle |
I minimise fatigue errors |
|
As a busy operator |
automatic spell and grammar check |
so that I can type fast without worry |
|
As an operator |
keyboard shortcuts |
I can type while I talk |
|
As an operator working under supervisors |
to alert the relevant parties |
So that they can act on it |
|
advanced operator |
to auto-transcribe the call |
I can store the call transcript for record-keeping purposes |
|
operator |
automatic triangulation of the call location |
I can dispatch a vehicle even if the caller does not know his/her address |
|
as an anxious operator |
nearby vehicles to be notified of the incident even though they’re not dispatched |
In case backup is needed |
|
As an operator that has to take many calls |
to select from drop down lists for certain fields |
so that I can fill in the summary report fast |
(For all use cases below, the System is the IMS and the Actor is the user, unless specified otherwise)
MSS
-
User inputs username and password
-
IMS checks username & password
-
IMS provides user with access
Use case ends.
Extensions
-
2a. The username is not found or password is incorrect.
-
2a1. IMS shows a generic error message to deter malicious intent. Use case ends.
-
MSS
-
User requests to create a new incident
-
User chooses auto vehicle dispatchment
-
IMS creates a new incident with autofill details
-
IMS prompts for completion of incident report
-
User fills in necessary details
-
User submits incident report
Use case ends.
Extensions
-
2a. User opts for manual assignment.
-
2a1. IMS displays list of all available vehicles.
-
2a2. User selects index of vehicle to dispatch.
Use case resumes at step 4.
-
-
6a. User opts to complete report later.
-
6a1. IMS stores incident as a draft.
Use case ends.
-
MSS
-
User searches for an incident
-
IMS retrieves the incident
-
User edits the incident details
-
IMS saves the edited incident report
Use case ends.
Extensions
-
2a. The incident is not found.
-
2a1. IMS shows an error message.
Use case ends.
-
-
Should work on any mainstream OS as long as it has Java
11or above installed. -
Should be able to hold up to 1000 incidents without a noticeable sluggishness in performance for typical usage.
-
A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.
-
Performance first for vehicle dispatch upon new incident creation.
-
Interface should prioritise user experience since operators function in a high stress environment.
Given below are instructions to test the app manually.
|
ℹ️
|
These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing. |
-
Initial launch
-
Download the jar file and copy into an empty folder
-
Double-click the jar file
Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
-
-
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
-
-
Deleting a person while all persons are listed
-
Prerequisites: List all persons using the
listcommand. Multiple persons in the list. -
Test case:
delete 1
Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated. -
Test case:
delete 0
Expected: No person is deleted. Error details shown in the status message. Status bar remains the same. -
Other incorrect delete commands to try:
delete,delete x(where x is larger than the list size) {give more}
Expected: Similar to previous.
-
-
Dealing with missing/corrupted data files
-
{explain how to simulate a missing/corrupted file and the expected behavior}
-
-
Attempting to execute
newwithout logging in.-
Prerequisites: User not logged in.
-
Test case:
new dist/1 auto/y
Expected: Message "Only Register, Login, Exit, and Help commands are available. Please login to access other commands. See help page for more information."
-
-
Executing
newwith valid inputs and successful auto vehicle dispatchment-
Prerequisites: User must be logged in, and there must be at least one available vehicle in the given district.
-
Test case:
new dist/1 auto/y
Expected: Message "New incident drafted!" with the newly drafted incident appears at the top of the incident pane. All vehicles in district 1 will be listed in the vehicle pane, and the vehicle dispatched will change it availability from "AVAILABLE" to "BUSY".
-
-
Executing
newwith no inputs for manual vehicle dispatchment-
Prerequisites: User must be logged in.
-
Test case:
new dist/1 auto/n
Expected: User prompted to fill in index of vehicle to dispatch with message "Please include the index of the vehicle you would like to assign, with the district prefix! eg new l/1 auto/n v/1 Note that the index must be a positive integer!"
-
-
Executing
newwith valid inputs for manual vehicle dispatchment-
Prerequisites: User must be logged in.
-
Test case:
new dist/1 auto/n v/1
Expected: Message "New incident drafted!" with the newly drafted incident appears at the top of the incident pane. All vehicles in district 1 will be listed in the vehicle pane, and the vehicle dispatched will change it availability from "AVAILABLE" to "BUSY".
-
-
Executing
newwith invalid inputs for manual vehicle dispatchment-
Prerequisites: User must be logged in.
-
Test case:
new dist/1 auto/n v/1.2
Expected: Message "The index must be a positive integer!"
-
-
Executing
newwith no vehicle available for dispatchment.-
Prerequisites: User must be logged in, and no vehicle is available in the district.
-
Test case:
new dist/28 auto/y
Expected: Message "No vehicle available in this district!", for both auto and manual dispatchment.
-
-
Attempting to execute
fillwithout logging in.-
Prerequisites: User not logged in.
-
Test case:
fill
Expected: Message "Only Register, Login, Exit, and Help commands are available. Please login to access other commands. See help page for more information." -
Test case:
fill 1 p/92034950 desc/There was an incident
Expected: Message "Only Register, Login, Exit, and Help commands are available. Please login to access other commands. See help page for more information."
-
-
Executing
fillin both no-parameter and parameter modes one after the other.-
Prerequisites: User must be logged in. There must be incomplete and/or complete draft incident reports in the system. Index, caller number, and description specified for
fillin parameter mode must all be valid. User must have created the incident report. -
Test case:
fill
Expected: All drafts are listed in the incident panel view, with incidents whose status was most recently changed being listed first. Message: "Listed all draft incident reports". -
Test case:
fill 1 p/95860594 desc/There was an incident
Expected: If selected draft was an incomplete draft, its status changes to 'Complete Draft' and the caller number and description fields are added according to the data specified. If selected draft was a complete draft, its status remains 'Complete Draft' and the caller number and description fields are overwritten with the data specified. The incident panel view lists all incidents in the system, with the just modified incident at the top of the list. Message: "Incident report filled: Incident #[ID]"
-
-
Executing
fillin parameter mode with valid parameters.-
Prerequisites: User must be logged in. There must be incomplete and/or complete draft incident reports in the system. Incident panel view must show all incidents (use
list-ito return to this view if needed). Index, caller number, and description specified forfillin parameter mode must all be valid. -
Test case:
fill 1 p/95860594 desc/There was an incident
Expected: If first incident in the list is a draft and the user has created the report, same expected behaviour as case 2 (iii) above. If user has not created the selected incident, the message "You do not have access to fill this draft as another operator has created it." is displayed. If selected incident has already been submitted and user has created the incident, the message "This report has already been submitted" is displayed.
-
-
Executing
fillin parameter mode with invalid parameters (including invalid - zero or out of bounds - index).-
Prerequisites: User must be logged in.
-
Test case:
fill 0 p/95860594 desc/There was an incidentorfill 1 c/95860594 desc/There was an incidentorfill 1 p/95860594 d/There was an incidentExpected: Message "Invalid command format!" is displayed along with command usage message.
-
-
Executing
fillwith no drafts present in the system.-
Prerequisites: User must be logged in. There must be no complete or incomplete drafts in the system.
-
Test case:
fillExpected: Message "No drafts present in the system" shown while the incident panel view remains unchanged. -
Test case:
fill 1 p/95860594 desc/There was an incidentExpected: Message "No drafts present in the system" shown while the incident panel view remains unchanged.
-
-
Attempting to execute
submitwithout logging in.-
Prerequisites: User not logged in.
-
Test case:
submit
Expected: Message "Only Register, Login, Exit, and Help commands are available. Please login to access other commands. See help page for more information." -
Test case:
submit 1
Expected: Message "Only Register, Login, Exit, and Help commands are available. Please login to access other commands. See help page for more information."
-
-
Executing
submitin both no-parameter and parameter modes one after the other.-
Prerequisites: User must be logged in. There must be complete draft incident reports in the system. Index specified for
submitin parameter mode must be valid. User must have created the incident report. -
Test case:
submit
Expected: All complete drafts are listed in the incident panel view, with incidents whose status was most recently changed being listed first. Message: "Listed all incident reports ready for submission". -
Test case:
submit 1
Expected: The status of the selected complete draft changes to 'Submitted'. The incident panel view lists all incidents in the system, with the just submitted incident at the top of the list. Message: "New incident report submitted: Incident #[ID]"
-
-
Executing
submitin parameter mode with valid index.-
Prerequisites: User must be logged in. There must be complete draft incident reports in the system. Incident panel view must show all incidents (use
list-ito return to this view if needed). Index specified forsubmitin parameter mode must be valid. -
Test case:
submit 1
Expected: If first incident in the list is a complete draft and the user has created the report, same expected behaviour as case 2 (iii) above. If user has not created the selected incident, the message "You do not have access to submit this report as another operator has created it." is displayed. If selected incident has already been submitted and user has created the incident, the message "This report has already been submitted" is displayed.
-
-
Executing
submitin parameter mode with invalid - zero or out of bounds - index.-
Prerequisites: User must be logged in.
-
Test case:
submit 0Expected: Message "Invalid command format!" is displayed along with command usage message.
-
-
Attempting to execute
edit-iwithout logging in-
Prerequisites: User not logged in.
-
Test case:
edit-i
Expected: Message "Only Register, Login, Exit and Help commands are availble. Please login to access other commands. See help page for more information."
-
-
Executing
edit-iwithout any keywords-
Test case:
edit-i
Expected: Message "Listed all submitted incident reports that can be edited."
-
-
Executing
edit-iwith some keywords when logged into admin account-
Test case:
edit-i 1 dist/21
Expected: Message "Edited Incident: Incident #[ID]"
-
-
Executing
edit-iwith all keywords when logged into admin account-
Test case:
edit-i 1 dist/22 p/91234567 desc/This is an incident description.
Expected: Message "Edited Incident: Incident #[ID]"
-
-
Executing
edit-ion incident not created by logged in non admin account. ..Test caseedit-i 1
Expected: Message "Only the admin and the operator who filled in this report can edit the report."
-
Attempting to execute
add-vwithout logging in.-
Prerequisites: User not logged in.
-
Test case:
add-v
Expected: Message "Only Register, Login, Exit, and Help commands are available. Please login to access other commands. See help page for more information."
-
-
Executing 'add-v' with all valid inputs
-
Test case :
add-v dist/2 vnum/SFD1356S vtype/Ambulance a/available
Expected: Message "New vehicle added: Ambulance Vehicle Number: SFD1356S District: 2 Availability: AVAILABLE"
-
-
Executing
add-vwith invalid vnum-
Test case:
add-v dist/2 vnum/1234 vtype/Patrol Car a/available
Expected: Message "Invalid vehicle number! All vehicle numbers must follow the format: ABC1234D"
-
-
Attempting to execute
find-vwithout logging in.-
Prerequisites: User not logged in.
-
Test case:
find-v dist/1
Expected: Message "Only Register, Login, Exit, and Help commands are available. Please login to access other commands. See help page for more information."
-
-
Executing
find-vwith a single district keyword.-
Prerequisites: User must be logged in, and there are vehicles in the district specified.
-
Test case:
find-v dist/1
Expected: Message "3 vehicles listed!", and vehicles in the given district will be listed in the vehicle pane.
-
-
Executing
find-vwith multiple district keywords.-
Prerequisites: User must be logged in, and there are vehicles in the districts specified.
-
Test case:
find-v dist/1 2 3
Expected: Message "10 vehicles listed!", and vehicles in the given districts will be listed in the vehicle pane.
-
-
Executing
find-vwith a single vehicle type keyword.-
Prerequisites: User must be logged in, the vehicle type must match exactly, and must be either "Ambulance" or "Patrol car", though case insensitive.
-
Test case:
find-v vtype/ambuLANce
Expected: Message "15 vehicles listed!", and vehicles ofAmbulancetype will be listed in the vehicle pane.
-
-
Executing
find-vwith a single character/ number of a vehicle number as keyword.-
Prerequisites: User must be logged in, and there must be at least one vehicle with vehicle number containing this keyword.
-
Test case:
find-v vnum/2
Expected: Message "27 vehicles listed!", and vehicles with vehicle numbers containing "2" will be listed in the vehicle pane.
-
-
Attempting to execute
list-vwithout logging in.-
Prerequisites: User not logged in.
-
Test case:
list-v
Expected: Message "Only Register, Login, Exit, and Help commands are available. Please login to access other commands. See help page for more information."
-
-
Executing
list-v.-
Prerequisites: User must be logged in.
-
Test case:
list-v
Expected: Message "Listed all vehicles", and all vehicles in database will be listed in the vehicle pane.
-
-
Attempting to execute
delete-vwithout logging in-
Prerequisites: User not logged in.
-
Test case:
delete-v
Expected: Message "Only Register, Login, Exit, and Help commands are available. Please login to access other commands. See help page for more information."
-
-
Executing
delete-vwith an admin account and dispatched vehicle-
Test case:
delete-v 1
Expected: Message "You cannot delete a vehicle that is currently dispatched."
-
-
Executing
delete-vwith an admin account and non dispatched vehicle-
Test case:
-
edit-v 1 available -
delete-v 1
Expected: Message "Deleted Vehicle Patrol Car Vehicle Number: SFD3204V District: 1 Availability: AVAILABLE"
-
-
-
Executing
delete-vwith a non admin account-
Test case:
delete-v 1
Expected: Message "You must be an admin to perform this operation. Please see help page for more info."
-
























