layout | title |
---|---|
page |
Developer Guide |
- Table of Contents {:toc}
Refer to the guide Setting up and getting started.
The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.
💡 Tip: The .puml
files used to create diagrams in this document can be found in the diagrams folder. Refer to the PlantUML Tutorial at se-edu/guides 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 methods where necessary.
Commons
represents a collection of classes used by multiple other components.
The rest of the App consists of four components.
UI
: The UI of the App.Logic
: The command executor.Model
: Holds the data of the App in memory.Storage
: Reads data from, and writes data to, the hard disk.
Each of the four components,
- defines its API in an
interface
with the same name as the Component. - exposes its functionality using a concrete
{Component Name}Manager
class (which implements the corresponding APIinterface
mentioned in the previous point.
For example, the Logic
component (see the class diagram given below) defines its API in the Logic.java
interface and exposes its functionality using the LogicManager.java
class which implements the Logic
interface.
How the architecture components interact with each other
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.
API :
Ui.java
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
Logic
component. - Listens for changes to
Model
data so that the UI can be updated with the modified data.
API :
Logic.java
Logic
uses theAddressBookParser
class to parse the user command.- This results in a
Command
object 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
CommandResult
object which is passed back to theUi
. - In addition, the
CommandResult
object can also instruct theUi
to 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.
API : Model.java
The Model
,
- stores a
UserPref
object that represents the user’s preferences. - stores the address book 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.
![BetterModelClassDiagram](images/BetterModelClassDiagram.png)
API : Storage.java
The Storage
component,
- can save
UserPref
objects in json format and read it back. - can save the address book data in json format and read it back.
Classes used by multiple components are in the seedu.addressbook.commons
package.
This section describes some noteworthy details on how certain features are implemented.
The Resident family of features consist of the following features: Add Resident, Edit Resident, List Resident, Find Resident and Delete Resident.
The Resident class consists of 5 fields, each of which contain their own methods to verify their respective input. This allows for a low degree of coupling, and individual fields can change their input verification rules without affecting the other classes. Similarly, the Resident class can expand to contain more fields without affecting existing fields too.
Examples of verification functions in each of the fields include Resident#isValidName()
etc.
The Resident
objects are stored in a UniqueResidentList
which is held by AddressBook
.
This section will detail the implementation of the Add Resident feature via the radd
command,
The AddResidentCommand is triggered through the use of radd
followed by valid parameters such as name, phone, etc.
The entire command string must then be parsed to extract the parameters that were inserted, and if they are all valid, a Resident object is constructed and added to the model and saved to the backing store. Upon successful insertion, a feedback message is displayed to the user.
This process is summarised in the diagram below
The diagram below details how the user's command to add a resident propagates through the system to eventually add a resident.
The Room family of features consist of the following features: Add Room, Edit Room, List Rooms, Find Room and Delete Room.
The Room class consists of 4 fields, each of which contain their own methods to verify their respective input. This allows for a low degree of coupling, and individual fields can change their input verification rules without affecting the other classes. Similarly, the Room class can expand to contain more fields without affecting existing fields too.
Examples of verification functions in each of the fields include RoomNumber#isValidRoomNumber()
, RoomType#isValidRoomType()
, etc.
The Room
objects are stored in a UniqueRoomList
which is held by AddressBook
.
- Alternative 1 (current choice): Abstract fields of Room out as separate classes
- Pros:
- Each field can take care of its own validation
- Updating a field does not update the Room class itself
- Cons:
- More classes to manage and individually track
- Might be unintuitive to initially understand
- Pros:
- Alternative 2: Leave fields of Room as member variables of the Room class
- Pros:
- Everything is self-contained within the Room class, single source of "truth"
- Cons
- Field verification becomes a responsibility of the Room class which is not desirable (Violation of SRP)
- Changes to individual fields would impact the Room class which may unintentionally break other things
- Less object oriented approach which goes against the principles of how this project was set up
- Pros:
This section will detail the implementation of the Add Room feature via the oadd
command,
The AddRoomCommand is triggered through the use of oadd
followed by valid parameters such as room number, type, etc. The entire command string must then be parsed to extract the parameters that were inserted, and if they are all valid, a Room object is constructed and added to the model and saved to the backing store. Upon successful insertion, a feedback message is displayed to the user.
This process is summarised in the diagram below
The AddRoomCommand
inherits from the Command
object and overrides the execute()
method. It checks if the model already has the room being inserted, and if it does not, it will insert the room.
The inheritance from Command
allows Logic
to deal with and manipulate polymorphic Command
objects without dealing with the specific implemetations of each Command
object.
The diagram below details how the user's command to add a room propagates through the system to eventually add a room.
The allocation feature is facilitated by ResidentRoom
which is a pair value of
valid [Resident, Room]
that represents an existing resident allocated to a room.
It should be able to support the following operations:
ResidentRoom#getName()
- Returns the resident allocated for a given ResidentRoom.ResidentRoom#getRoomNumber()
- Returns the room assignment for a given ResidentRoom.
A ResidentRoomList
is a supplementary class that tracks all the ResidentRoom
assignments. It should support
the following operations.
ResidentRoomList#add()
- Adds aResidentRoom
new allocation.ResidentRoomList#remove()
- Removes an existingResidentRoom
allocation.ResidentRoomList#contains()
- Checks if an allocation exists given the resident and room.
There are two Resident-Room user allocation and deallocation commands, alloc
and dealloc
respectively.
The alloc
command will do the following:
Example: alloc ri/1 oi/2
-
Check that the 1st resident exists.
-
Check that the 2nd room exists exists.
-
Check that the 1st resident has not already been allocated to the 2nd room.
-
Check that no other room is allocated to the 2nd resident.
-
Check that room the 2nd room is not occupied by any resident.
If all the above is true,
-
Set the
ROOM
of the resident to be the room number of the room. -
Set the
OCCUPATION_STATUS
of the room toY
.
The dealloc
command will do the following:
Example: dealloc 1
-
Check that the first resident exists.
-
Check that the first resident has been allocated to a room.
If all the above is true,
-
Set the
ROOM
of the resident to beRoom unallocated
. -
Set the
OCCUPATION_STATUS
of the room toN
.
- Alternative 1 (current choice): Resident-Room solely keeps track of resident and room allocation
performed through
alloc
anddealloc
commands. Any allocated resident and occupied rooms cannot be edited.- Pros:
- Simpler to implement.
- Better testability for synchronicity between fields.
- Cons:
- Less user control.
- Pros:
- Alternative 2: Resident-Room allocation is modelled as a Parent-Child where the parent is the
Room
and the child is theResident
.- Pros:
- Simpler to implement.
- Cons:
- Lack of 2-way updates. Room number of the
Resident
cannot be updated and viewed. The problem is reversed if the parent-child roles are swapped where the occupancy ofRoom
cannot be updated and viewed.
- Lack of 2-way updates. Room number of the
- Pros:
- Alternative 3: Resident-Room interface as a lookup.
Room
andResident
would look up theresidentRoom
class every time to get itsOCCUPANCY STATUS
andROOM NUMBER
.- Pros:
- User has more control and flexibility.
- Cons:
- Creates cascading effect with a lot of dependencies between regular commands
such as
redit
,rdel
,oedit
,odel
.
- Creates cascading effect with a lot of dependencies between regular commands
such as
- Pros:
The Issue family of features consist of the following features: Add Issue, Edit Issue, List Issue, Find Issue, Delete Issue and Close Issue.
The Issue class consists of 5 fields, each of which contain their own methods to verify their respective input. This allows for a low degree of coupling, and individual fields can change their input verification rules without affecting the other classes. Similarly, the Issue class can expand to contain more fields without affecting existing fields too.
Examples of verification functions in each of the fields include Category#isValidCategory()
, Status#isValidStatus()
, etc.
The Issue
objects are stored in an IssueList
which is held by AddressBook
.
This section will detail the implementation of the Add Issue feature via the iadd
command.
The AddIssueCommand is triggered through the use of iadd
followed by valid parameters such as room number, description, etc. The entire command string must then be parsed to extract the parameters that were inserted, and if they are all valid, an Issue object is constructed and added to the model and saved to the backing store. Upon successful insertion, a feedback message is displayed to the user.
This process is summarised in the diagram below
The AddIssueCommand
inherits from the Command
object and overrides the execute()
method.
The inheritance from Command
allows Logic
to deal with and manipulate polymorphic Command
objects without dealing with the specific implemetations of each Command
object.
The diagram below details how the user's command to add an issue propagates through the system to eventually add an issue.
The Alias
feature allows users to define a shortcut for a longer command that is often used. The longer command can then be executed by entering the alias instead of the full or partial command.
User-defined Alias
is stored in AliasMapping
within UserPrefs
. AliasMapping
internally uses HashMap<String, Alias>
to store the mapping between the name of an Alias
object and itself. With AliasMapping
included in UserPrefs
, UserPrefs
supports the following methods:
-
UserPrefs#getAliasMapping()
— Returns the currentAliasMapping
. -
UserPrefs#setAliasMapping(AliasMapping aliasMappings)
— Sets the current mapping to the specified mapping. -
UserPrefs#addAlias(Alias alias)
— Adds a user-definedAlias
to the current mapping. -
UserPrefs#getAlias(String aliasName)
— Returns anAlias
based on alias name. -
UserPrefs#containsAlias(String aliasName)
— Checks if the current mapping contains anAlias
based on alias name. -
UserPrefs#isReservedKeyword(String aliasName)
— Checks if the alias name is a reserved keyword. This prevents users from using existing commands as alias name. -
UserPrefs#isRecursiveKeyword(String commandWord)
— Checks if the command word is a recursive keyword. This prevents users from chaining aliases.
User can create a new Alias
via the AliasCommand
. The sequence diagram below describes how an Alias
is created.
When a user executes a new command, AddressBookParser
will follow these steps:
- If the input begins with an existing command word, parse it as one of those pre-defined command.
- If all parameters are valid, return the corresponding
Command
object. - Else show error to the user.
- If all parameters are valid, return the corresponding
- Else if the input begins with a mapped
Alias
, replace the alias with the mappedCommand
.- Parse the mapped
Command
as per normal.
- Parse the mapped
- Else show error to the user.
The following diagram illustrates the flow:
The command history feature has a few sub-features:
- View history command: the user can list the command history.
- Navigate history: the user can navigate their command history like in a terminal program.
- Save/load history: command history persists across SunRez runs.
This section starts with an overview of the command history model then looks at each sub-feature in turn.
SunRez command history is represented by a CommandHistory
, stored in the ModelManager
. A CommandHistory
is
composed of zero or more CommandHistoryEntry
objects, each representing a previously entered command. New entries
can be appended to CommandHistory
. CommandHistory
implements the ReadOnlyCommandHistory
interface,
which provides a non-editable view of the implementing CommandHistory
; this readonly view is used by other components
that do not need to append to the command history. For example, the view history command reads it to display it - or a
filtered portion of it - to the user.
The following class diagram shows an overview of the command history subsystem and its relation to other components.
Logic#execute()
triggers the update. Only after a command parses and executes successfully will that command's text
be appended to the command history via Model#appendCommandHistoryEntry()
. If either parsing or execution fails,
then CommandHistory
will be unchanged. The following sequence diagram shows this process pictorially using the
example command help
.
SunRez allows the user to list the full command history, or a portion of it, through the command history [COUNT]
where
[COUNT]
is an optional integer that the user can specify to limit the number of most-recent entries to be listed.
If [COUNT]
is omitted, then the full command history is displayed.
Viewing command history is implemented through ViewHistoryCommand
and supported by ReadOnlyCommandHistory
.
ViewHistoryCommand#execute()
accesses command history through the view of a ReadOnlyCommandHistory
, reads the
entries it needs to display, formats the entries into a message, then finally returns the message wrapped in
a CommandResult
, to be displayed to the user. The following sequence diagram illustrates the main interactions
between ViewHistoryCommand
and the Model component. It uses the example command of history 5
.
The user navigates their command history via the UP and DOWN arrow keys. The UP and DOWN arrow keys respectively select the previous and next commands in history, if any.
The UP and DOWN key press events are first handled by CommandBox
in the UI component. CommandBox
delegates the
logic of navigation and keeping track of state (which command we are selecting) to a CommandHistorySelector
.
The CommandHistorySelector
is called via #selectNext()
and #selectPrevious()
which are expected
to respectively return the next and previous commands in history since they were last called. Upon receiving the
relevant commands from CommandHistorySelector
, CommandBox
will populate its text box with that command's text.
The following sequence diagram shows the aforementioned relationships.
CommandHistorySelector#selectLast()
can also be called to reset the selection to the most recent command in history.
This is useful, for example, when a user has navigated to the middle of their command history then executes a new
command. At this point, we want navigation to start from the most recent command again - not where the user was
before he/she executed a command.
Currently, SunRez uses a SuppliedCommandHistorySelector
as its CommandHistorySelector
. This implementation uses
a Supplier<ReadOnlyCommandHistory>
to view SunRez command history whenever it is called to select a new entry.
SunRez automatically saves command history after each command execution, and loads command history (if any) upon app
start-up. The command history is saved in a plain-text file at [JAR_file_location]/data/commandhistory.txt
.
Saving and loading is supported by CommandHistoryStorage
, an interface that exposes read and write methods. SunRez
currently uses an implementation of this interface called PlainTextCommandHistoryStorage
, which serializes each
command history entry as a single line of plain text in the command history file. The class structure is shown
in the class diagram in the Command History Overview subsection above.
Command history is saved immediately after it is updated. Since command history is only updated after a successful
command execution, this implies that only successful commands are saved. In order to save command history,
CommandHistoryStorage
creates a serialized string from a ReadOnlyCommandHistory
view of the command history, then
writes it to disk using FileUtil#writeToFile()
as a helper. The following activity diagram shows a simplified flow
of the storage process from command execution to writing the command history to file.
-
Alternative 1 (current choice): Only record valid commands (commands which parse and execute successfully).
- Pros:
- Less cluttered command history.
- A User can still easily correct typos in a failed command because SunRez does not consume the input if it fails to execute.
- Cons:
- Behaves less like a regular shell program, so the user might be expecting different behavior.
- Pros:
-
Alternative 2: Record all command text that the user tries to execute.
- Pros:
- Behaves more like a regular shell program.
- Cons:
- More cluttered command history.
- Arguably does not help the user correct typos in failed commands (see Alternative 1: Pros).
- Pros:
-
Alternative 1 (current choice): No, abstract it out to an interface
CommandHistorySelector
with a backing implementation.- Pros:
- Follows SRP because
CommandBox
is part of the UI component, but history selection is logic. If selection logic is left inCommandBox
, then it now has two reasons (UI and logic) to change. - Easier to unit test because logic is separated from UI.
- Follows SRP because
- Cons:
- More complex to implement: one additional interface and class.
- Pros:
-
Alternative 2: Yes, keep the selection logic in
CommandBox
.- Pros:
- Simpler to implement: no additional classes or interfaces; and the selection logic is quite straightforward, so the bloat may be acceptable in the short term.
- Arguably, selection only affects the
CommandBox
so the added complexity may not be worth it.
- Cons:
- Harder to unit test because selection logic is bundled with UI.
- Pollutes a UI component with details of logic. If we wish to change the selection logic in future but not
the UI,
CommandBox
will still need to change.
- Pros:
The proposed undo/redo mechanism is facilitated by VersionedAddressBook
. It extends AddressBook
with an undo/redo history, stored internally as an addressBookStateList
and currentStatePointer
. Additionally, it implements the following operations:
VersionedAddressBook#commit()
— Saves the current address book state in its history.VersionedAddressBook#undo()
— Restores the previous address book state from its history.VersionedAddressBook#redo()
— Restores a previously undone address book state from its history.
These operations are exposed in the Model
interface as Model#commitAddressBook()
, Model#undoAddressBook()
and Model#redoAddressBook()
respectively.
Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
Step 1. The user launches the application for the first time. The VersionedAddressBook
will be initialized with the initial address book state, and the currentStatePointer
pointing to that single address book state.
Step 2. The user executes delete 5
command to delete the 5th person in the address book. The delete
command calls Model#commitAddressBook()
, causing the modified state of the address book after the delete 5
command executes to be saved in the addressBookStateList
, and the currentStatePointer
is shifted to the newly inserted address book state.
Step 3. The user executes add n/David …
to add a new person. The add
command also calls Model#commitAddressBook()
, causing another modified address book state to be saved into the addressBookStateList
.
Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the undo
command. The undo
command will call Model#undoAddressBook()
, which will shift the currentStatePointer
once to the left, pointing it to the previous address book state, and restores the address book to that state.
The following sequence diagram shows how the undo operation works:
The redo
command does the opposite — it calls Model#redoAddressBook()
, which shifts the currentStatePointer
once to the right, pointing to the previously undone state, and restores the address book to that state.
Step 5. The user then decides to execute the command list
. Commands that do not modify the address book, such as list
, will usually not call Model#commitAddressBook()
, Model#undoAddressBook()
or Model#redoAddressBook()
. Thus, the addressBookStateList
remains unchanged.
Step 6. The user executes clear
, which calls Model#commitAddressBook()
. Since the currentStatePointer
is not pointing at the end of the addressBookStateList
, all address book states after the currentStatePointer
will be purged. Reason: It no longer makes sense to redo the add n/David …
command. This is the behavior that most modern desktop applications follow.
The following activity diagram summarizes what happens when a user executes a new command:
-
Alternative 1 (current choice): Saves the entire address book.
- Pros: Easy to implement.
- Cons: May have performance issues in terms of memory usage.
-
Alternative 2: Individual command knows how to undo/redo by itself.
- Pros: Will use less memory (e.g. for
delete
, just save the person being deleted). - Cons: We must ensure that the implementation of each individual command are correct.
- Pros: Will use less memory (e.g. for
{more aspects and alternatives to be added}
{Explain here how the data archiving feature will be implemented}
Target user profile:
Nina works as a housing service management officer for a Residential College* (in NUS). She is the sole manager of the office. She:
- has to manage a large number of residents and rooms (> 600)
- needs to efficiently assign rooms to residents
- handles room allocation exercise every semester
- needs to track room issues reported by students during the semester
- needs to update the issue lifecycle (reported => maintenance ongoing => fixed/closed)
- prefers typing over interacting via GUI
Value proposition: manage residents, rooms, and allocations faster than a typical GUI 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 if I forget how to use the app |
* * * |
confused user | have a help command | learn how to use the application |
* * * |
user | add a new person | |
* * * |
user | add issues | |
* * * |
user | see a list of pending tasks sorted by deadline | prioritise which to do |
* * * |
user | search for tasks | |
* * * |
user | close issues | focus on open issues |
* * * |
user | update issues | |
* * * |
user | remove issues | |
* * * |
user | add residents | |
* * * |
user | search for residents | |
* * * |
user | update resident details | ensure their information is up to date |
* * * |
user | remove residents | |
* * * |
user | add new rooms | |
* * * |
user | see a list of rooms with their statuses | know which rooms are available |
* * * |
user | search for rooms | |
* * * |
user | update room details | |
* * * |
user | remove rooms | |
* * |
user | see both available rooms and unassigned residents side by side | easily match residents to rooms |
* * |
careless user | undo previous commands | easily fix any errors I might make |
* * |
careless user | redo previous commands | easily fix an erroneous undo |
* * * |
user | allocate a resident to a room | |
* * * |
user | deallocate a resident from a room | |
* * |
power user | access my command history | efficiently repeat similar commands |
* * |
power user | access command history from previous sessions | easily reuse commands from previous sessions |
* * |
power user | create aliases for longer commands | avoid typing the same command multiple times |
* * |
power user | delete aliases that are no longer needed | avoid triggering the wrong command |
(For all use cases below, the System is the SunRez
and the Actor is the user
, unless specified otherwise. All Use Cases are prefixed with UC
followed by a 3 digit code)
MSS
- User requests to add a specific resident to the list.
- SunRez adds the resident and saves the changes.
Use case ends.
Extensions
- 1a. The resident's details are incorrectly formatted (e.g. phone number/email/year format does not conform, OR room number is invalid).
-
1a1. SunRez displays an error stating which field is incorrectly formatted and requests the user to try again after fixing the stated error.
Use case ends.
-
- 1b. The resident's phone number or email are in use by an existing resident.
-
1b1. SunRez displays an error stating which field is already in use and requests the user to try again after fixing the stated error.
Use case ends.
-
- 2a. SunRez encounters an error while saving the content.
-
2a1. SunRez shows an error message and requests the user to try their command again.
Use case ends.
-
MSS
- User requests to list residents.
- SunRez shows a list of residents.
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
MSS
- User searches for a resident by keywords.
- SunRez shows a list of residents whose name contain any of the keywords.
Use case ends.
Extensions
- 2a. There are no residents matching the keywords.
-
2a1. An empty list is displayed.
Use case ends.
-
MSS
- User requests to list residents.
- SunRez shows a list of residents.
- User requests to edit a specific resident based on the index from the list displayed in step 2.
- SunRez edits the residents and saves the changes.
Use case ends.
Extensions
-
2a. The list of residents is empty.
Use case ends.
-
3a. The resident's details are invalid (e.g phone number/email/dob format does not conform, OR room number is invalid).
-
3a1. SunRez shows an error message stating which field is incorrectly formatted and requests the user to try again.
Use case resumes at step 2.
-
MSS
- User requests to list residents.
- SunRez shows a list of residents.
- User requests to delete a specific resident based on the index from the list displayed in step 2.
- SunRez deletes the specified resident and saves the changes.
Use case ends.
Extensions
-
2a. The list of residents is empty.
Use case ends.
-
3a. The specified resident does not exist.
-
3a1. SunRez shows an error message.
Use case resumes at step 2.
-
MSS
- User requests to add a specific room to the list.
- SunRez adds the room and saves the changes.
Use case ends.
Extensions
- 1a. The room's details are invalid (e.g room number format is not valid).
-
1a1. SunRez shows an error stating which field is incorrectly formatted and requests the user to try again after fixing the stated error.
Use case ends.
-
Similar to UC-002 List all residents, just replace residents with rooms.
Similar to UC-003 Find residents, just replace resident with room.
MSS
- User requests to list rooms.
- SunRez shows a list of rooms.
- User requests to edit a specific room based on the index from the list displayed in step 2.
- SunRez edits the room and saves the changes.
Use case ends.
Extensions
-
2a. The list of rooms is empty.
Use case ends.
-
3a. The room's details are invalid (e.g. room number format is not valid).
-
3a1. SunRez shows an error message stating which field is incorrectly formatted and requests the user to try again.
Use case resumes at step 2.
-
Similar to UC-005 Delete a resident, just replace resident with room.
MSS
- User requests to add a specific open issue to the list.
- SunRez adds the issue and saves the changes.
Use case ends.
Extensions
- 1a. The issue's details are invalid (e.g. invalid room number).
-
1a1. SunRez shows an error stating which field is incorrectly formatted and requests the user to try again after fixing the stated error.
Use case ends.
-
Similar to UC-002 List all residents, just replace residents with issues.
Similar to UC-003 Find residents, just replace residents with issues.
MSS
- User requests to list issues.
- SunRez shows a list of issues.
- User requests to edit a specific issue based on the index from the list displayed in step 2.
- SunRez edits the issue and saves the changes.
Use case ends.
Extensions
-
2a. The list of issue is empty.
Use case ends.
-
3a. The issue's details are invalid (e.g invalid room number).
-
3a1. SunRez shows an error message stating which field is incorrectly formatted and requests the user to try again.
Use case resumes at step 2.
-
MSS
- User requests to list issues.
- SunRez shows a list of issues.
- User requests to mark a specific issue as closed based on the index from the list displayed in step 2.
- SunRez marks the issue as closed and saves the changes.
Use case ends.
Extensions
-
2a. The list is empty.
Use case ends.
-
3a. The given index is invalid.
-
3a1. SunRez shows an error message.
Use case resumes at step 2.
-
Similar to UC-005 Delete a resident, just replace resident with issue.
MSS
- User requests to undo previous command.
- Previous command is undone and SunRez's state is reverted to before that command.
Use case ends.
Extensions
- 1a. There are no previous commands that change state.
-
1a1 SunRez shows an error message.
Use case ends.
-
MSS
- User requests to redo previously undone command.
- Previous undone command is redone and SunRez's state is updated accordingly.
Use case ends.
Extensions
- 1a. There are no previously undone commands.
-
1a1 SunRez shows an error message.
Use case ends.
-
MSS
- User requests to list unassigned residents and unallocated rooms.
- SunRez displays unassigned residents and unallocated rooms side-by-side.
- User requests to allocate a room to a resident.
- SunRez allocates the room and saves the changes.
Extensions
-
2a. There are no unassigned residents or unassigned.
Use case ends.
-
3a. The given index is invalid.
-
3a1. SunRez shows an error message.
Use case resumes at step 2.
-
MSS
- User requests to list room allocations.
- SunRez displays rooms, each with its corresponding allocated resident.
- User requests to deallocate a room based on the index from the list displayed in step 2.
- SunRez deallocates the room and saves the changes.
Extensions
-
2a. There are no unassigned residents or unassigned.
Use case ends.
-
3a. The given index is invalid.
-
3a1. SunRez shows an error message.
Use case resumes at step 2.
-
MSS
- User requests to view command history.
- SunRez displays command history, in reverse order of entry.
- User selects a previously entered command.
- SunRez fills the command field with the selected command.
- User modifies and/or executes the command.
Use case ends.
Extensions
-
1a. There is no command history.
Use case ends.
MSS
- User requests to assign an alias name for a command.
- SunRez validates the alias name and command.
- SunRez saves the alias mapping to the user’s preferences.
Use case ends.
Extensions
-
2a. Alias name is invalid.
-
2a1. SunRez shows an error message.
Use case ends.
-
-
3a. An alias with the same name exists.
-
3a1. SunRez overwrites the existing alias.
Use case ends.
-
MSS
- User requests to delete an alias.
- SunRez validates the alias name.
- SunRez removes the alias and updates the alias mapping in the user’s preferences.
Use case ends.
Extensions
- 2a. Alias is not found in the current alias mapping.
-
2a1. SunRez shows an error message.
Use case ends.
-
- Should work on any mainstream OS as long as it has Java
11
or above installed. - Should be able to hold up to 1000 records (residents, rooms and issues) 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.
- A user should be able to learn the basic commands within half an hour of initial usage.
- Should work without the internet.
- Should be a highly portable to enable transfer between different computers with different OS.
- Executable program should occupy less than 20MB on the computer.
- Should not require an installer.
- The data should not be stored in a Database Management System (DBMS).
- Should not depend on any remote server.
{More to be added}
- Mainstream OS: Windows, Linux, Unix, OS-X
- Residential College (RC): A university residence for students that offers a 2-year program at NUS
- NUS: The National University of Singapore
- Resident: A university student staying in the Residential College
- Issue: A maintenance problem that concerns the condition of a room
Given below are instructions to test the app manually.
-
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.
-
-
{ more test cases … }
-
Dealing with missing/corrupted data files
- {explain how to simulate a missing/corrupted file, and the expected behavior}
-
{ more test cases … }