Developer Guide
- Acknowledgements
- Setting up, getting started
- Design
- Implementation
- Documentation, logging, testing, configuration, dev-ops
- Appendix: Requirements
-
Appendix: Instructions for manual testing
- Launch and shutdown
- Clearing data:
clear - Adding a Student:
add - Adding a class:
addclass - Deleting a student:
delete - Deleting a tuition class:
deleteclass - Adding a Student to a Class:
addtoclass - Removing Student(s) from a class :
removefromclass - Editing a student:
edit - Editing a class:
editclass - Sorting classes and students:
sort - Locating a student by name:
findname - Locating a class by class timing:
findclass - Locating a class by name:
findclassname - Finding Student(s) by tag :
findtag - Changing tabs:
view - Selecting a class:
class - Listing all students:
list - Listing all classes:
listclass
- Appendix: Effort
Acknowledgements
- The
Timetablefeature was inspired by a similar feature in the past project of Pet Store Helper here. The implementation of the components of theTimetablefeature (TimetableTuitionClassSlot,TimetableDay,TimetableRegionandTimetableEmptySlot) has been adapted from them with maximum changes to fit our app. The implementation of how we built and designed (TimetablePanel.java) the entire Timetable Tab (layout, classes etc) is entirely new.
Setting up, getting started
Refer to the guide Setting up and getting started.
Design
.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.
Architecture

The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
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.
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.

Each of the four main components (also shown in the diagram above),
- defines its API in an
interfacewith the same name as the Component. - implements its functionality using a concrete
{Component Name}Managerclass (which follows the corresponding APIinterfacementioned in the previous point.
For example, the Logic component defines its API in the Logic.java interface and implements its functionality using the LogicManager.java class which follows the Logic interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component’s being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.

The sections below give more details of each component.
UI component
The API of this component is specified in Ui.java

The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, StatusBarFooter etc, and a TabPane consisting of StudentsUi, ClassesUi and TimetableUi. All these, including the MainWindow, inherit from the abstract UiPart class which captures the commonalities between classes that represent parts of the visible GUI.
The UI component uses the 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. - keeps a reference to the
Logiccomponent, because theUIrelies on theLogicto execute commands. - observes the
Commandabstract class in theLogiccomponent, because it needs to update when certain commands are run. - depends on some classes in the
Modelcomponent, as it displaysStudentandTuitionClassobjects residing in theModel.
Students UI

The StudentListPanel consists of StudentCards, which displays information about the Students. The StudentListPanel takes in an ObservableList<Student>, which builds a StudentCard for each student.
Timetable UI
Adapted from here. You can find more details in the acknowledgements section.

The TimetablePanel is made up of TimetableDay, TimetableHeader, TimetableTuitionClassSlot and TimetableEmptySlot.
They represent the day panel on the left, the header at the top with the label and timings, the slots representing the TuitionClasses and the empty slots between TuitionClasses respectively.
The TimetablePanel takes in an ObservableList<TuitionClass> to build the Timetable.
Classes UI

The ClassPanel consists of a TuitionClassPanel and a StudentClassPanel.
They represent the left and right panels of the GUI respectively.
TuitionClassPanel takes in both an ObservableList<TuitionClass> and an ObservableList<Student>, while
StudentClassPanel takes in only an ObservableList<Student>.
TuitionClassPanel requires an ObservableList<Student> for the purpose of filtering the Student List based on the selected TuitionClass.

TuitionClassPanel and StudentClassPanel both contain their respective Cards for each element in their respective ObservableList.
Note that StudentClassTabCard is different from the StudentCard in the studenttab package so we have less coupling and for future extensibility.
Logic component
API : Logic.java
Here’s a (partial) class diagram of the Logic component:

How the Logic component works:
- When
Logicis called upon to execute a command, it uses theTimesTableParserclass to parse the user command. - This results in a
Commandobject (more precisely, an object of one of its subclasses e.g.,AddCommand) which is executed by theLogicManager. TheCommandobject may call theCommandObserverto update theUIif necessary. - The command can communicate with the
Modelwhen it is executed (e.g. to add aStudent). - The result of the command execution is encapsulated as a
CommandResultobject which is returned back fromLogic.
The Sequence Diagram below illustrates the interactions within the Logic component for the execute("delete 1") API call.

DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Here are the other classes in Logic (omitted from the class diagram above) that are used for parsing a user command:

How the parsing works:
- When called upon to parse a user command, the
TimesTableParserclass creates anXYZCommandParser(XYZis a placeholder for the specific command name e.g.,AddCommandParser) which uses the other classes shown above to parse the user command and create aXYZCommandobject (e.g.,AddCommand) which theTimesTableParserreturns back as aCommandobject. - All
XYZCommandParserclasses (e.g.,AddCommandParser,DeleteCommandParser, …) inherit from theParserinterface so that they can be treated similarly where possible e.g, during testing.
Model component
API : Model.java

The Model component,
- stores the TimesTable data.
- All
Studentobjects which are contained inUniqueStudentList. - All
TuitionClassobjects which are contained inUniqueClassList.
- All
- stores the currently ‘selected’
Studentobjects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiableObservableList<Student>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. - Similarly, the currently ‘selected’
TuitionClassobjects are stored in a separated filtered list which is exposed to outsiders as an unmodifiableObservableList<TuitionClass>. - stores a
UserPrefobject that represents the user’s preferences. This is exposed to the outside as aReadOnlyUserPrefobjects. - does not depend on any of the other three components (as the
Modelrepresents data entities of the domain, they should make sense on their own without depending on other components).
The Student and NOK class (next-of-kin) extends the Person class. The Student class’s structure is as follows:

The structure of the TuitionClass class is as follows:

The
StudentNameList contains a List<Name>, and the diagram omits the relationship that Student and NOK are subclasses of the abstract class Person.
Storage component
API : Storage.java

The Storage component,
- can save both TimesTable data and user preference data in json format, and read them back into corresponding objects.
- inherits from both
TimesTableStorageandUserPrefStorage, which means it can be treated as either one (if only the functionality of only one is needed). - depends on some classes in the
Modelcomponent (because theStoragecomponent’s job is to save/retrieve objects that belong to theModel). -
JsonAdaptedStudentare saved in aList<JsonAdaptedStudent>andJsonAdaptedTuitionClassare saved in aList<JsonAdaptedTuitionClass>. -
JsonAdaptedTags are stored inJsonAdaptedStudentas aList<JsonAdaptedTag>.
Common classes
Classes used by multiple components are in the seedu.times.commons package.
Implementation
This section describes some noteworthy details on how certain features are implemented.
Classes Tab feature
The Classes Tab feature allows one to see the user’s classes and each class’ corresponding students.
Implementation

The class diagram for the Classes Tab feature as shown in the Classes Ui component is replicated here for convenience.
TuitionClassPanel and StudentClassPanel are both contained in their respective StackPane located below their respective Labels.

-
MainWindow#fillInnerParts()creates a newClassPanelusing theObservableList<Student>and theObservableList<TuitionClass>fromLogic. - A
StudentClassPaneland aTuitionClassPanelis created using theObservableList<Student>andObservableList<TuitionClass>. -
StudentClassPanelandTuitionClassPanelcreate their respective cells for eachStudent/TuitionClasspresent. -
TuitionClassPanel#setStudentClassList()is run by taking in theListView<Student>from theStudentClassPanel. This is to render the students in theStudentClassPanelin theTuitionClassPanelas well. - Afterwards, when a
TuitionClassCardis double clicked,TuitionClassCard#onMouseClick()bound to the fxml file is called, callingTuitionClassCard#selectTuitionClass(). - The
filteredmethod is then run on thestudentListto return anewStudentListwhich is filtered by all the students belonging to thetuitionClass. - The
tuitionClassListViewis set to thenewStudentListcreated and thus rendered.
Timetable Tab feature
The Timetable Tab feature is a feature which displays the user’s classes in a visual timetable format.
Implementation
The class diagram for Timetable as shown in the TimetableUI component is replicated here for convenience.

The image below shows the respective parts of the TimetablePanel:

- The green box represents the
TimetableDay, and there are 7TimetableDayparts to represent the 7 days of the week. - The yellow box represents the
TimetableHeader, with the box all the way at the left with the label “Time Slots” representing theTimetableHeaderLabel, and the others representing theTimetableHeaderTiming. There is always 1TimetableHeaderLabelbut can have manyTimetableHeaderTimingparts depending on the earliest start time and latest end time of the week. - The dark blue box represents the
TimetableEmptySlot. - The light blue box represents the
TimetableTuitionClassSlot.
The sequence diagrams below illustrate how the Timetable UI is built.

1.MainWindow#fillInnerParts() creates a new TimetablePanel using the ObservableList<TuitionClass> from Logic.
2.TimetablePanel#build() is called in the constructor of TimetablePanel to build the Timetable Ui.
3.TimetablePanel#build() starts building the Timetable Ui by first calling TimetablePanel#buildHeader() which takes in the ObservableList<TuitionClass>.

4.Based on the Timetable#buildHeader() reference frame above, it builds the TimetableHeaderLabel first, followed by the TimetableHeaderTimings, starting from the earliest start time of the ObservableList<TuitionClass> until the latest end time of the ObservableList<TuitionClass> in 30 minutes interval.

5.After TimetablePanel#buildHeader() is called, it would call TimetablePanel#buildDays(), which builds 7 TimetableDay objects to represent the 7 days of the week.

6.Finally, the TimetablePanel#buildClasses() is called, which takes in the same ObservableList<TuitionClass> as step 3. It iterates through the sorted ObservableList<TuitionClass>, building a TimetableTuitionClassSlot for each of the TuitionClass, and placing TimetableEmptySlots in between the TimetableTuitionClassSlots.
7.A listener is attached to the ObservableList<TuitionClass> which updates the Timetable UI whenever there are changes to the ObservableList<TuitionClass>,
such as when a new TuitionClass is added, or an existing TuitionClass is edited in the ObservableList<TuitionClass>.
Observer Pattern
The Observer Pattern is facilitated by the CommandObserver who represents the Observer. It observes the abstract Command class.
Implementation
The class diagram below shows how we implemented the structure of the Observer Pattern.

The MainWindow from UI component implements both the Ui and CommandObserver interface as it plays the role of the Ui as well as a CommandObserver. The MainWindow observes the Command class, who calls CommandObserver#updateView(), CommandObserver#updateClass() and CommandObserver#hideTuitionClassList() depending on what Command XYZCommand is.
For eg, the ViewComand calls CommandObserver#updateView() to set the displayed tab of the CommandObserver to the tab specified. Additionally, the AddToClassCommand calls both CommandObserver#updateClass() and CommandObserver#updateView() to update the class details and updates the view to the Classes tab when we execute the AddToClassCommand.
Design Considerations
- (Bad) After each command call, set a variable in the
CommandResultto be the value of the Tab to change to, or a boolean value to see if we need to update the class. TheMainWindowwould then check the variables inCommandResultinMainWindow#executeCommand(), and updates the tab or class accordingly.- This is a very bad and inefficient method as the
MainWindowwould have to constantly check theCommandResultafter everyCommand. - With the addition of new variables in
CommandResult, it has the potential to introduce more bugs and make the code more unreadable. Additionally, other classes may also be able to access these variables accidentally, as they have to bepublicin order forMainWindowto access them, leading to unwanted consequences.
- This is a very bad and inefficient method as the
- (Good) Follow the Observer Pattern taught in CS2103T, where we register the
MainWindowas aCommandObserverto observe the abstractCommandclass, and will only get updated when necessary.- This is a more efficient method as the
MainWindowdoes not have to always check theCommandResultafter each execution. - No new variables are needed to be introduced into the
CommandResult, keeping our code neater and less bug prone.
- This is a more efficient method as the
add and edit commands to include next-of-kin nok
Implementation
The solution that we came up with was very simple. we just had to split the string by /nok and put both of the split
portions into the parser. Modifying the existing parser was not needed at all. we learnt that oftentimes for a small feature, we don’t have
to go for the most extensible or “smart” solution, but the simplest to understand.
Design Considerations
Initially, it appeared challenging to us because the current Parser is only able to parse contents between tags, but not encompass other tags within recursively.
For example, add n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/Chemistry t/Sec 3 nok/ n/Jack Doe p/10987654 e/jackd@example.com a/311, Clementi Ave 2, #02-25 requires us to parse the tags before and after nok/ separately, which is a challenging problem to think about at first.
-
(Bad) We thought of a recursive implementation of the
Parser, callingparsemethods again on the two halves whenever we find an/noktag, but it proved to be too lofty and unneccesarily complicated. Moreover, using recursion in applications is not recommended due to the high potential of unseen bugs. -
(Bad) We thought of modifying the parser such that it always checks for the
/noktag (or any of the tags specified in the parameter) first, before parsing the other tags in the normal way. However, this was again too large scale for a single command with the same parameter.
Find commands
The find commands are a common group of commands that allows users to quickly find Student or TuitionClass. They are:
findnamefindtagfindclassfindclassname
Implementation of the command
The implementation of all search-related commands such as findtag, findname, findclass and findclassname uses a
common approach of setting a Predicate inside the corresponding FilteredList class. As mentioned above in Model
section, the filtered list either contains an ObservableList<Student> or ObservableList<TuitionClass> that is bound to the
UI such that UI is responsive to any changes in the list and these changes can be brought forward by setting a new
Predicate. One should also note that the default Predicate always returns a boolean true which means no Student
or TuitionClassis filtered out at the start.
The sequence diagram when a findtag command is executed is as follows:

The rest of the find command works the same way but note that for findclass and findclassname, they are calling the
setPredicate method of filteredTuitionClass instead.
Implementation of find predicates
Furthermore, to fully understand the find command, we also have to understand how Predicate works. The Predicates used
that filters out students or classes are typical java Predicate. For each searchable attribute, a new class must be
created that implements Predicate with the right generic type (i.e. predicate class for filtering Student must
implement Predicate<Student>, and predicate class for filtering TuitionClass must implement Predicate<TuitionClass>).
Each custom predicate class contains a List of search strings that would be used to match against the tested items
in the search.
View feature
The Students tab, Classes tab and Timetable tab, are parts of the UI Component.
Navigation between these tabs without the mouse is crucial for our application as the target audience are people who prefer keyboard to mouse or voice commands.
The view feature is facilitated by the ViewCommand, which extends the abstract Command class. The ViewCommand sets the displayed tab to be the tab specified by the user.
Implementation
The sequence diagram for the view command is shown below.

The ViewCommand calls the CommandObserver#updateView(TabName), which updates the view of the CommandObservers watching the Command abstract class to the TabName specified.
In this case, the only CommandObserver is the MainWindow, thus it updates the view of the MainWindow to display the TIMETABLE Tab at index 2.
TabName is an enumeration which represents the three tabs (Students, Classes, and Timetable), and their respective tab index (0 for Students, 1 for Classes and 2 for Timetable).
Sort feature
The sort feature allows sorting of the Students and TuitionClasses. It is able to sort it by Student name or ClassTiming, in ascending or descending order.
The sort feature is facilitated by the SortCommand, which extends the abstract Command class.
Implementation
The sequence diagram for the sort command is shown below.

The sort command sorts the ObservableList<Student> or the ObservableList<TuitionClass> in the Model component, whose results gets immediately reflected in their respective Students tab or Classes Tab.
After sorting, the Command sets the view to switch to their respective tabs, so that the user would be able to see the changes.
Adding a Student to a class
addtoclass command adds an existing Student into an existing TuitionClass.
Implementation of the parser
addtoclass command’s parser AddToClassCommandParser works by parsing indexes in the user input and
generating a List<Index> whereby the first index will be for the TuitionClass receiving the Students and the rest
of the index being the Students to be added into the TuitionClass. The only thing to note is that the parser
will only see zero and negative indices as invalid and not
out-of-range indices. This is because at the time of parsing, the model is not accessed to check if the indices are
out-of-range. The reason for this design is to reduce dependency and keep to the single responsibility principle. The
job of the parser should be separated from checking in with the model.
Implementation of the command
The addtoclass command follows an index based format and the TuitionClass contains the Index of the class to add
the new students to and a List of Index of students to be added. The command’s execution is composed of various
smaller steps. The steps are listed below:
- Check indices are not out-of-range
- Generate a list of
Names to be added to the class - Produce the new student
StudentNameListbased on the class’s existingStudentNameListand the list ofNames to be added - Creating the right
EditClassDescriptor - Updating the
Modelwith updatedTuitionClass
(Note that updating view action is omitted)
The following sequence diagram gives an overview of the execution:

The sequence diagram for the first reference frame from above:

The sequence diagram for the second reference frame from above:

Removing Student(s) from a Tuition Class
Allows the user to remove one or more Students from a selected TuitionClass.
Implementation
The removefromclass command follows a similar execution path as other commands. The user input is passed to
the LogicManager, which parses the input using the TimesTableParser and RemoveFromClassCommandParser.
A RemoveFromClassCommand is then created with the class and student indices involved in the command.
The command is then executed, interacting with the Model.
An overview of how the RemoveFromClassCommand is created is shown by this sequence diagram:

Challenges faced
The challenging aspect in removing students from a tuition class is in figuring out which students to remove.
The RemoveFromClassCommandParser parses the user input to obtain a list of indexes to be passed to the RemoveFromClassCommand.
As such, the RemoveFromClassCommand only has access to a list of indices. We can easily obtain the TuitionClass object by
simply using the class index with Model#getFilteredTuitionClassList().
On the other hand, the TuitionClass object only stores
the Name of each Student in the TuitionClass. This was done as we use immutable objects throughout TimesTable. As such, if the user
modifies any of the fields of a Student using the edit command, then we would have to reflect the change throughout all the tuition classes
of the student. By only storing the Name of the Student in the TuitionClass object, then we only have to update all the TuitionClass
objects if the user modifies the Name field of the Student.
However, this decision results in added complexity when removing students from tuition classes. This is due to the fact that the Names
stored in the TuitionClass object are in the order in which the students were added, but the order of the students as displayed in the
GUI is dependent on the sort and find commands used by the user. As such, the indices entered by the user do not correspond with the
actual Names stored in the TuitionClass object.
To solve this problem, we have to obtain the list of students in the order displayed by the GUI. To obtain this list,
we use the same method that the GUI uses to display the list in the first place. We use Model#getFilteredStudentList(),
then filter it to the students whose Names are in the TuitionClass that we are concerned with. From here, we can now use the
student indices entered by the user to obtain the Names of the corresponding Students in the filtered list. Then we can create
a new TuitionClass object with an updated list of Names and replace the old TuitionClass with this new one.
An overview of the process is shown below:

Deleting Tuition Class
Deletes a TuitionClass from the classes list in the Classes tab, to delete a tuition class, the deleteclass
command is used.
Implementation
- The
DeleteCommandParserparses the user input to obtain the index of the class to be deleted. - A
DeleteCommandis created with the index of the tuition class to be deleted. - The
DeleteCommand#execute()is run, the TimesTable is searched to find the tuition class to be deleted. - That tuition class is then deleted from the
Modeland theUniqueClassListby extension.
A diagram of the procedure is shown below:


Adding Tuition Class
Adds a new tuition class into the classes list in the Classes tab with all the relevant detail, to add a tuition
class, the addclass command is used.
Implementation
- The
AddClassCommandParserparses the user input to obtain 4 parameters:ClassName,ClassTiming,RateandLocation. - The parser checks if the user has inputted valid value for these 4 parameter.
- These 4 parameters and a new empty
StudentNameListare then used to create a newTuitionClassto be passed into a newAddClassCommand(TuitionClass)as an argument. - This command is then executed and the new
TuitionClassis added into theModeland into theUniqueClassList, where further checks are done to ensure that there is no overlapping timing between the newTuitionClassthat is to be added and other already existingTuitionClasses in the list, as TimesTable is made for a single user and thus designed to not allow overlappingTuitionClasses
The sequence diagram when a AddClass command is executed by the LogicManager is as follows:


The sequence diagram when a new TuitionClass is added to the Model is as follows

Challenges faced
The challenging aspect when adding a tuition class to the UniqueClassList was making sure that no overlapping
classes were added.
Initially, the equals() method of TuitionClass was used to compare TuitionClasses, and ClassTiming was the
only comparator in the equals() method, but this proved problematic later on due to comparing ClassTiming
using only the equals() method and comparing TuitionClasses using only ClassTiming. We realized that classes
would still be added even though they overlap as they were not strictly equals and this method of comparison was
very naive.
After some trial and error with quite a lot of developer’s testing, we created a isOverlapping() in TuitionClass
that checks for overlaps which checks for any overlap where either class will be within the timeframe of one another,
or where the start or end time of one class was within the timeframe of another. This made sure that we had a method
to check for any overlap between classes when adding new class to the UniqueClassList, ensuring that no new
classes would be added to the UniqueClassList when adding a tuition class to TimesTable. This check also served to
make sure that there would be no overlapping classes resulting from an editclass command.
Documentation, logging, testing, configuration, dev-ops
Appendix: Requirements
Product scope
Target user profile:
- Name: Kevin Bernard Long Zheng Wei
- Age: 28
- Gender: Male
- Marital status: Single
- Country: Singapore
- Habits: Sleeping, Netflix, Gym, Gaming
- Lifestyle: Code, eat, sleep, gives freelance tuition.
- prefer desktop apps over other types
- can type fast
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
- Interest: Loves coding and building apps during his free time with friends. Loves teaching people.
- Values: Work hard play hard.
- Salary: $12000/mth
- Job: Full time freelance A-levels Mathematics tuition teacher (Size of class: group and one-to-one)
- Has a need to manage a significant number of contacts
- Car: Owns 2 Teslas.
- Home Environment: Lives with parents, older brother and dog.
- Education: NIE graduate.
- Household Description: Sentosa Cove landed property with rich parents.
Value proposition:
A busy tutor who has a large number of students can find it extremely difficult to
- manage and organize student information
- schedule according to student class timing
This is where Timestable comes in. It improves two main areas:
- querying
- student information
- parent information
- class timing
- data manipulation
- add
- edit
- delete
By improving the data manipulation process, the tutor can organize student information more easily.
By improving the querying process, the tutor can make scheduling less painstaking and time-consuming.
User stories
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* |
Careless User | Be notified if there was a clash in timing | I can have peace of mind |
* |
User | View schedule for a specific day | Can prepare for lesson and won’t be absent |
* * |
User | Save class rates | Keep track of how much to charge each class |
* * |
User | Edit my student details | Keep track of changes of my students |
* * |
Organised user | Sort my students and classes | Arrange them the way I want to organise them |
* * * |
Forgetful user | Save their contacts | I can remember them |
* * * |
Organised User | View my class timings in a time table | Know how my weekly schedule looks like |
* * * |
User | Record parent contact of my students | Contact the student’s parent in case of emergencies |
* * * |
User | Delete my student’s contacts and information | I can declutter my contacts. |
* * * |
User | Record locations of classes | Knows where to go |
* * * |
User | Find a student or class with a specific name | Find details of a specific class or student quickly |
Use cases
(For all use cases below, the System is the TimesTable and the Actor is the user, unless specified otherwise)
Use case: Delete a student
MSS
- User requests to list students.
- TimesTable shows a list of students.
- User requests to delete a specific student in the list.
-
TimesTable deletes the student.
Use case ends.
Extensions
-
1a. The list is empty.
Use case ends.
-
3a. The given index is invalid.
-
3a1. TimesTable shows an error message.
Use case resumes at step 3.
-
-
3b. The given delete command has a typo.
-
3b1. TimesTable shows an error message.
Use case resumes at step 3.
-
Use case: Add a student
MSS
- User input details of new person to be added to TimesTable.
-
TimesTable adds new person with relevant details.
Use case ends.
Extension
-
1a. User keys in add command with invalid format(missing compulsory fields).
-
1a1. TimesTable shows an error message.
Use case resumes at step 1.
-
-
1b. User keys in add command with valid format but invalid String format for certain fields.
-
1b1. TimesTable shows an error message saying which field contains the invalid format.
Use case resumes at step 1.
-
Use case: Edit student details
MSS
- User edits details of existing student.
-
TimesTable updates the student with the added details.
Use case ends.
Extension
-
1a. User keys in field with invalid format.
-
1a1. TimesTable shows an error message.
Use case resumes at step 1.
-
Use case: Find student by name
MSS
- User input name of student that user wants to find.
-
TimesTable shows the student that has the same name.
Use case ends.
Extension
-
1a. No student name matches the name keyword inputted.
-
1a1. TimesTable shows no student listed.
Use case ends.
-
Use case: Find student by tag
MSS
- User input tag of student that user wants to find.
-
TimesTable shows the student that has the same tag.
Use case ends.
Extension
-
1a. No student tag matches the tag keyword inputted.
-
1a1. TimesTable shows no student listed.
Use case ends.
-
Use case: Add a tuition class
MSS
- User input details of new tuition class to be added to TimesTable.
-
TimesTable adds new tuition class with relevant details.
Use case ends.
Extension
-
1a. User keys in addclass command with invalid format(missing compulsory fields).
-
1a1. TimesTable shows an error message.
Use case resumes at step 1.
-
-
1b. User keys in addclass command with valid format but invalid String format for certain field.
-
1b1. TimesTable shows an error message saying which field contains the invalid format.
Use case resumes at step 1.
-
-
1c. User keys in addclass command with valid format, valid String format for all fields, but class timing overlaps with other classes already in TimesTable.
-
1c1. TimesTable shows an error message saying that this operation would cause a clash in class timing.
Use case resumes at step 1.
-
Use case: Delete a tuition class
MSS
- User requests to list classes.
- TimesTable shows a list of classes.
- User requests to delete a specific class in the list.
-
TimesTable deletes the class.
Use case ends.
Extensions
-
1a. The list is empty.
Use case ends.
-
3a. The given index is invalid.
-
3a1. TimesTable shows an error message.
Use case resumes at step 3.
-
-
3b. The given deleteclass command has a typo.
-
3b1. TimesTable shows an error message.
Use case resumes at step 3.
-
Use case: Add students to a tuition class
MSS
- User input index of class(in
classestab) to be added to and index of students(instudentstab) to be added. -
TimesTable adds students selected into class selected.
Use case ends.
Extension
-
1a. User keys in addtoclass command with invalid index(student or class or both).
-
1a1. TimesTable shows an error message citing which index is invalid.
Use case resumes at step 1.
-
-
1b. User attempts to add student to a class where the student is already in.
-
1b1. TimesTable shows an error message saying that student is already in the class.
Use case resumes at step 1.
-
Use case: Remove students from a tuition class
MSS
- User input index of class(in
classestab) to be added to and index of students(inclassestab) to be removed. -
TimesTable removes students from the class selected.
Use case ends.
Extension
-
1a. User keys in removefromclass command with invalid index(student or class or both).
-
1a1. TimesTable shows an error message citing which index is invalid.
Use case resumes at step 1.
-
Use case: Edit tuition class details
MSS
- User edits details of existing tuition class.
-
TimesTable updates the tuition class with the added details.
Use case ends.
Extension
-
1a. User keys in field with invalid format(wrong field name).
-
1a1. TimesTable shows an error message.
Use case resumes at step 1.
-
-
1b. User keys in invalid index.
-
1b1. TimesTable shows an error message.
Use case resumes at step 1.
-
-
1c. User keys in class timing that overlaps with other class’s class timing.
-
1c1. TimesTable shows an error message saying that this operation would cause a clash in class timing.
Use case resumes at step 1.
-
Use case: Find tuition class by class timing
MSS
- User input class timing of tuition class that user wants to find.
-
TimesTable shows the tuition classes that has similar class timing.
Use case ends.
Extension
-
1a. No tuition class timing matches the class timing keyword inputted.
-
1a1. TimesTable shows no tuition classes listed.
Use case ends.
-
Use case: Find tuition class by name
MSS
- User input name of tuition class that user wants to find.
-
TimesTable shows the tuition class that has similar name.
Use case ends.
Extension
-
1a. No tuition class name matches the name keyword inputted.
-
1a1. TimesTable shows no tuition class listed.
Use case ends.
-
Non-Functional Requirements
- Should work on any mainstream OS as long as it has Java
11or above installed. - Should be able to hold up to 1000 students 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.
- The data should be stored locally in a human editable text file
- Should not use a database management system to store data
- Should follow OOP paradigm primarily
- Should work without requiring an installer
- Should not depend on a remote server
- Project should simulate a brownfield project by evolving the code base with each iteration incrementally (breadth-first)
- Should be for a single user
- Third-party frameworks, libraries and services should be free, open-source, do not require any installation by the user, and do not violate other requirements.
- GUI should work well for
- Standard screen resolutions of 1920x1080 and higher
- Screen scales 100% and 125%
- GUI should be usable for
- Resolutions 1280x720 and higher
- Screen scales 150%
- Should package everything into a single JAR file
- Product should not exceed 100 MB and documents should not exceed 15 MB/file
- Developer Guide and User Guide should be PDF-friendly
Glossary
- Mainstream OS: Windows, Linux, Unix, OS-X
- Private contact detail: A contact detail that is not meant to be shared with others
Appendix: Instructions for manual testing
Given below are instructions to test the app manually.
Launch and shutdown
-
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.
-
Clearing data: clear
- Test case: Clear all
Students andTuitionClasses in TimesTable.- Prerequisite: TimesTable contains
Students andTuitionClasses. Steps to do this are below:- (You may skip this if you already have
Students) Add a student:add n/Amber p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/Chemistry t/Sec 3 nok/ n/Jack Doe p/10987654 e/jackd@example.com a/311, Clementi Ave 2, #02-25 - (You may skip this if you already have
TuitionClasses) Add a class:addclass cn/Sec 4 A Maths ct/MON 11:30-13:30 r/70 l/Nex Tuition Center
- (You may skip this if you already have
- Clear all data:
clear - Expected:
TimesTable has been cleared!and allStudents andTuitionClasses are removed from TimesTable.
- Prerequisite: TimesTable contains
- Test case: Clear empty TimesTable.
- Prerequisite: TimesTable does not contain
Students andTuitionClasses. Steps to do remove them are below:- (You may skip this if you do not have
Students) Delete a student:delete INDEXfor allStudents in TimesTable. - (You may skip this if you do not have
TuitionClasses) Delete a class:deleteclass INDEXfor allTuitionClasses in TimesTable.
- (You may skip this if you do not have
- Clear all data:
clear - Expected:
TimesTable has been cleared!and allStudents andTuitionClasses are removed from TimesTable.
- Prerequisite: TimesTable does not contain
Adding a Student: add
- Test case 1: Add a
Studentsuccessfully- Add a
Studentto TimesTable:add n/John Doe p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/Chemistry t/Sec 3 nok/ n/Jack Doe p/10987654 e/jackd@example.com a/311, Clementi Ave 2, #02-25 - Expected message:
New Student added: John Doe; Phone: 98765432; Email: johnd@example.com; Address: 311, Clementi Ave 2, #02-25; Tags: [Chemistry][Sec 3] Next-of-Kin: Jack Doe; Phone: 10987654; Email: jackd@example.com; Address: 311, Clementi Ave 2, #02-25
- Add a
- Test case 2: Cannot add duplicate
Student- Prerequisite: TimesTable contains the sample
Students. Steps to do this are below:- Delete
timestable.jsonin the data file to start of with the sample data in TimesTable.
- Delete
- Add a
Studentwith a clash inNAMEwith an existingStudent:add n/Alex Yeoh p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/Chemistry t/Sec 3 nok/ n/Elise Yeoh p/10987654 e/eliseyeoh@gmail.com a/311, Clementi Ave 2, #02-25 - Expected:
This person already exists in the address bookmessage shown.
- Prerequisite: TimesTable contains the sample
Adding a class: addclass
- Test case: Adding a
TuitionClasssuccessfully - no clash inCLASS_TIMINGwith existingTuitionClasses.- Prerequisite: TimesTable does not have any
TuitionClasses. If you have anyTuitionClass, steps to remove them are below:- (You may skip this if you do not have
TuitionClasses) Delete a class:deleteclass INDEXfor allTuitionClasses in TimesTable.
- (You may skip this if you do not have
- Add a
TuitionClass:addclass cn/Sec 4 A Maths ct/MON 11:30-13:30 r/70 l/Nex Tuition Center - Expected:
New class added: Class Timing: MON 11:30-13:30 Class Name: Sec 4 A Maths Location: Nex Tuition Center Rate: 70and switched toClassesTab. TheClassesTab now shows theTuitionClassyou added. TheTimetableTab also shows yourTuitionClassonMON 11:30-13:30.
- Prerequisite: TimesTable does not have any
- Test case: Adding a
TuitionClassunsuccessfully - clash inCLASS_TIMINGwith existingTuitionClass.- Prerequisite: TimesTable contains the sample
TuitionClasses. Steps to do this are below:- Delete
timestable.jsonin the data file to start of with the sample data in TimesTable.
- Delete
- Add a
TuitionClasswith a clash inCLASS_TIMINGwith an existingTuitionClass:addclass cn/CS2103T ct/MON 10:30-12:30 r/70 l/Nex Tuition Center - Expected:
The operation aborted because it will introduce a clash in class timing.and theTuitionClassdoes not get added to theClassesTab.
- Prerequisite: TimesTable contains the sample
Deleting a student: delete
- Test case: Delete a student successfully
- Prerequisites: Student to delete must be present. Steps to do this are below:
- Add student:
add n/Student p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/Chemistry t/Sec 3 nok/ n/Jack Doe p/10987654 e/jackd@example.com a/311, Clementi Ave 2, #02-25 - Note the students in the student list.
- Add student:
- Delete the student:
delete INDEX.INDEXis the index of the student shown in the student list. If there were no other student present before, this would be 1. Otherwise, it would be the number shown at the top left corner of the student card. - Expected:
Deleted Person: Student; Phone: 98765432; Email: johnd@example.com; Address: 311, Clementi Ave 2, #02-25; Tags: [Chemistry][Sec 3] Next-of-Kin: Jack Doe; Phone: 10987654; Email: jackd@example.com; Address: 311, Clementi Ave 2, #02-25message shown. Class no longer belongs in the class list noted in (ia).
- Prerequisites: Student to delete must be present. Steps to do this are below:
- Test case: Cannot delete a student that doesn’t exist
- Prerequisites: Student at the student index to be deleted must not exist.
- Easiest way to ensure that this happens: run
clear - Note that the student list is empty.
- Easiest way to ensure that this happens: run
- Delete the student at index 1:
deleteclass 1. - Expected:
The student index provided is invalidmessage shown.
- Prerequisites: Student at the student index to be deleted must not exist.
Deleting a tuition class: deleteclass
-
Test case: Deleting a class successfully
- Prerequisites: Class to delete must be present. Steps to do this are below:
- Add class: addclass cn/Sec 4 A Maths ct/FRI 11:30-13:30 r/70 l/Nex Tuition Center
- Note the classes in the class list.
-
Delete the class:
deleteclass INDEX.INDEXis the index of the class shown in the class list. If there were no other classes present before, this would be 1. Otherwise, it would be the number shown at the top left corner of the class card. (eg.deleteclass 1). - Expected:
Class deleted: Class Timing: FRI 11:30-13:30 Class Name: Sec 4 A Maths Location: Nex Tuition Center Rate: 70message shown. Class no longer belongs in the class list noted in (ib).
- Prerequisites: Class to delete must be present. Steps to do this are below:
-
Test case: Cannot delete a class that does not exist
- Prerequisites: Class at the class index to be deleted must not exist. Steps to do this are below:
- Easiest way to ensure that this happens: run clear
- Note that the class list is empty.
- Delete the class at index 1:
deleteclass 1.
- Expected:
The class index provided is invalidmessage shown.
- Prerequisites: Class at the class index to be deleted must not exist. Steps to do this are below:
Adding a Student to a Class: addtoclass
- Test case 1: Add a
Studentto aTuitionClasssuccessfully- Prerequisites: You don’t have any
Students orTuitionClasses. If you have at least oneStudentorTuitionClass, you can skip adding aStudent/TuitionClassrespectively. - Add a
Studentto TimesTable:add n/Student p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/Chemistry t/Sec 3 nok/ n/Jack Doe p/10987654 e/jackd@example.com a/311, Clementi Ave 2, #02-25 - Add a
TuitionClassto TimesTable:addclass cn/Sec 4 A Maths ct/MON 11:30-13:30 r/70 l/Nex Tuition Center - Add the
Studentto theTuitionClass:addtoclass 1 1
Expected:Successfully added students to classmessage shown
- Prerequisites: You don’t have any
- Test case 2: Cannot add to a class that does not exist
- Prerequisites: You don’t have any classes. If you have any, you can remove them using the
deleteclass INDEXcommand or runclear. - If you already have a student, you can skip this step.
Add a student to TimesTable:add n/Student p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/Chemistry t/Sec 3 nok/ n/Jack Doe p/10987654 e/jackd@example.com a/311, Clementi Ave 2, #02-25 - Add the student to non-existing class:
addtoclass 1 1
Expected:The class index provided is invalidmessage shown
- Prerequisites: You don’t have any classes. If you have any, you can remove them using the
- Test case 2: Cannot add to a student that does not exist to a class
- Prerequisites: You don’t have any students. If you have any, you can remove them using the
delete INDEXcommand or runclear. - If you already have a class, you can skip this step.
Add a class to TimesTable:addclass cn/Sec 4 A Maths ct/MON 11:30-13:30 r/70 l/Nex Tuition Center - Add non-existing student to the class:
addtoclass 1 1
Expected:The student index provided is invalidmessage shown
- Prerequisites: You don’t have any students. If you have any, you can remove them using the
Removing Student(s) from a class : removefromclass
- Test case: Removing a student from a class that doesn’t currently exist
- Prerequisites: Class at the class index must not exist. Steps to do this are below:
- Run command
listclassand note the index of the last class.
- Run command
- Remove students from non-existing class at index (max index + 1):
removefromclass 5 1 2 3.
Where last class is at index 4 from (ib). - Expected:
The class index provided is invalidmessage shown.
- Prerequisites: Class at the class index must not exist. Steps to do this are below:
- Test case: Removing a student from a class that has no student
- Prerequisites: There must be a class with 0 students in it. Steps to do this are below:
- Clear TimesTable usiing:
clear. - Add a new class:
addclass cn/Sec 4 A Maths ct/FRI 11:30-13:30 r/70 l/Nex Tuition Center.
- Clear TimesTable usiing:
- Remove student(s) from empty class:
removefromclass 1 1 2 3. - Expected:
The student index provided is invalidmessage shown.
- Prerequisites: There must be a class with 0 students in it. Steps to do this are below:
Editing a student: edit
- Test case 1: Editing an existing student’s own detail
- Prerequisites
- Add student:
add n/John p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/Chemistry t/Sec 3 nok/ n/Jack Doe p/10987654 e/jackd@example.com a/311, Clementi Ave 2, #02-25 - Note the student and his or her index in the displayed list in the
Studenttab.
- Add student:
- Edit the student (assuming the student’s index is 1):
edit 1 n/updated student p/99993293 e/edited@gmail.com a/edited address t/ - Expected: All fields are changed according to
editcommand inputs and all tags are removed.
- Prerequisites
- Test case 2: Edit an existing student’s NOK detail
- Prerequisites: Same as above
- Edit the student’s NOK (assuming the student’s index is 1):
edit 1 nok/ n/edited NOK name e/editedNOK@gmail.com a/edited address p/92393932 - Expected: All NOK fields are changed according to
editcommand inputs
- Negative test cases
- Out of range
- (assuming the student list does not have 100 students) enter
edit 100 n/edited name - Expected: “The student index provided is invalid” is displayed
- (assuming the student list does not have 100 students) enter
- No fields provided
- enter
edit 1 - Expected: “At least one field to edit must be provided.” is displayed
- enter
- invalid prefix provided
- enter
edit 1 prefix/ - Expected: Invalid command format message is displayed
- enter
- Out of range
Editing a class: editclass
- Test case 1: Editing an existing class
- Prerequisites
- Add a class:
addclass cn/Sec 4 A Maths ct/MON 11:30-13:30 r/70 l/Nex Tuition Center - Note the class and its index in the displayed list in the
Classtab
- Add a class:
- Edit the class (assuming the class’s index is 1):
editclass 1 cn/edited classname ct/MON 09:00-11:00 r/90 l/edited location - Expected: All fields are changed according to
editclasscommand’s inputs
- Prerequisites
- Negative test cases:
- Out of range
- (assuming the class list does not have 100 classes) enter
editclass 100 cn/edited class name - Expected: “The class index provided is invalid” is displayed
- (assuming the class list does not have 100 classes) enter
- No fields provided
- enter
editclass 1 - Expected: “At least one field to editclass must be provided.” is displayed
- enter
- invalid prefix provided
- enter
editclass 1 prefix/ - Expected: Invalid command format message is displayed
- enter
- Out of range
Sorting classes and students: sort
- Test case: Sort classes in ascending order.
- Prerequisites: Add more than 1 class in non-sorted order by timing. Steps to do this are below:
- Add later class first:
addclass cn/Sec 4 A Maths ct/FRI 11:30-13:30 r/70 l/Nex Tuition Center - Add earlier class second:
addclass cn/Sec 5 A Maths ct/FRI 10:30-11:30 r/70 l/Nex Tuition Center - Note that ‘Sec 4 A Maths’ comes before ‘Sec 5 A Maths’
- Add later class first:
- Sort classes:
sort timing asc. - Expected:
Sorted classes based on timing in asc directionmessage shown, ‘Sec 5 A Maths’ now comes before ‘Sec 4 A Maths’ in the class list.
- Prerequisites: Add more than 1 class in non-sorted order by timing. Steps to do this are below:
- Test case: Sort students in descending order.
- Prerequisites: Add more than 1 student in non-sorted order by name. Steps to do this are below:
- Add earlier student first:
add n/Amber p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/Chemistry t/Sec 3 nok/ n/Jack Doe p/10987654 e/jackd@example.com a/311, Clementi Ave 2, #02-25 - Add later student second:
add n/Zebra p/98765432 e/johnd@example.com a/311, Clementi Ave 2, #02-25 t/Chemistry t/Sec 3 nok/ n/Jack Doe p/10987654 e/jackd@example.com a/311, Clementi Ave 2, #02-25 - Note that ‘Amber’ comes before ‘Zebra’
- Add earlier student first:
- Sort students:
sort name desc. - Expected:
Sorted students based on name in desc directionmessage shown, ‘Zebra’ now comes before ‘Amber’ in the Student list.
- Prerequisites: Add more than 1 student in non-sorted order by name. Steps to do this are below:
Locating a student by name: findname
- Test case: No students has a name that matches the search term used
- Prerequisites: TimesTable contain multiple students. Steps to do this are below:
- Delete
timestable.jsonin the data file to start off with the sample data in TimesTable.
- Delete
- Find students using a name that currently do not exist:
findname Jennifer. - Expected:
0 persons listed!message shown and no students shown inStudentstab.
- Prerequisites: TimesTable contain multiple students. Steps to do this are below:
- Test case: A student is found with name that matches search term.
- Prerequisites: TimesTable contain multiple students. Steps to do this are below:
- Delete
timestable.jsonin the data file to start off with the sample data in TimesTable.
- Delete
- Find students using a single name that currently exists:
findname alex. - Expected:
1 persons listed!message shown and 2 students shown inStudentstab, namelyAlex YeohandDavid Li.
- Prerequisites: TimesTable contain multiple students. Steps to do this are below:
- Test case: Multiple students have names that matches search term.
- Prerequisites: TimesTable contain multiple students. Steps to do this are below:
- Delete
timestable.jsonin the data file to start off with the sample data in TimesTable.
- Delete
- Find students using part of a name that currently exists:
findname li. - Expected:
3 persons listed!message shown and 3 students shown inStudentstab, namelyCharlotte Oliveiro,David LiandAngelica Holcomb.
- Prerequisites: TimesTable contain multiple students. Steps to do this are below:
Locating a class by class timing: findclass
- Test case: No
TuitionClassmatches the search term used.- Prerequisite: TimesTable contains the sample
TuitionClasses. Steps to do this are below:- Delete
timestable.jsonin the data file to start of with the sample data in TimesTable.
- Delete
- Find
TuitionClasses withCLASS_TIMINGofWED:findclass WED - Expected:
0 classes listed!and tab switched toClassestab.
- Prerequisite: TimesTable contains the sample
- Test case:
TuitionClasses match the search term used.- Prerequisite: TimesTable contains the sample
TuitionClasses. Steps to do this are below:- Delete
timestable.jsonin the data file to start of with the sample data in TimesTable.
- Delete
- Find
TuitionClasses withCLASS_TIMINGof ‘MON’:findclass mon - Expected:
2 classes listed!and tab switched toClassestab. TheClassesTab contains 2TuitionClasses withCLASS_TIMINGofMON.
- Prerequisite: TimesTable contains the sample
- Test case:
TuitionClasses match the multiple search terms used.- Prerequisite: TimesTable contains the sample
TuitionClasses. Steps to do this are below:- Delete
timestable.jsonin the data file to start of with the sample data in TimesTable.
- Delete
- Find
TuitionClasses withCLASS_TIMINGofMONand11:30-13:30:findclass mon 11:30-13:30 - Expected:
1 classes listed!and tab switched toClassestab. TheClassesTab contains 1TuitionClasswithCLASS_TIMINGofMONand11:30-13:30.
- Prerequisite: TimesTable contains the sample
Locating a class by name: findclassname
- Test case: No
TuitionClassmatches the search term used.- Prerequisite: TimesTable contains the sample
TuitionClasses. Steps to do this are below:- Delete
timestable.jsonin the data file to start of with the sample data in TimesTable.
- Delete
- Find
TuitionClasses withCLASS_NAMEofCS2103T:findclassname CS2103T - Expected:
0 classes listed!and tab switched toClassestab.
- Prerequisite: TimesTable contains the sample
- Test case:
TuitionClasses match the search term used.- Prerequisite: TimesTable contains the sample
TuitionClasses. Steps to do this are below:- Delete
timestable.jsonin the data file to start of with the sample data in TimesTable.
- Delete
- Find
TuitionClasses withCLASS_NAMEof ‘math’:findclassname math - Expected:
7 classes listed!and tab switched toClassestab. TheTuitionClasses shown in theClassesTab contains 7TuitionClasses withCLASS_NAMEofmath(case insensitive).
- Prerequisite: TimesTable contains the sample
- Test case:
TuitionClasses match the multiple search terms used.- Prerequisite: TimesTable contains the sample
TuitionClasses. Steps to do this are below:- Delete
timestable.jsonin the data file to start of with the sample data in TimesTable.
- Delete
- Find
TuitionClasses withCLASS_NAMEofmathandjc:findclassname math, jc - Expected:
8 classes listed!and tab switched toClassestab. TheTuitionClasses shown in theClassesTab contains 8TuitionClasses withCLASS_NAMEofmathorjcor both (case insensitive).
- Prerequisite: TimesTable contains the sample
Finding Student(s) by tag : findtag
- Test case: No students have tags that matches the search term used
- Prerequisites: TimesTable contain multiple students with differing tags. Steps to do this are below:
- Delete
timestable.jsonin the data file to start off with the sample data in TimesTable.
- Delete
- Find students using tag that currently do not exist:
findtag social studies. - Expected:
0 persons listed!message shown and no students shown inStudentstab.
- Prerequisites: TimesTable contain multiple students with differing tags. Steps to do this are below:
- Test case: Students have tags that matches search term(single)
- Prerequisites: TimesTable contain multiple students with differing tags. Steps to do this are below:
- Delete
timestable.jsonin the data file to start off with the sample data in TimesTable.
- Delete
- Find students using a single tag that currently exists:
findtag a math. - Expected:
2 persons listed!message shown and 2 students shown inStudentstab, namelyAlex YeohandDavid Li.
- Prerequisites: TimesTable contain multiple students with differing tags. Steps to do this are below:
- Test case: Students have tags that matches search terms(multiple)
- Prerequisites: TimesTable contain multiple students with differing tags. Steps to do this are below:
- Delete
timestable.jsonin the data file to start off with the sample data in TimesTable.
- Delete
- Find students using multiple tag that currently exists:
findtag a math, physic, sec 4. - Expected:
4 persons listed!message shown and 2 students shown inStudentstab, namelyAlex Yeoh,Charlotte Oliveiro,David LiandIllana Page.
- Prerequisites: TimesTable contain multiple students with differing tags. Steps to do this are below:
Changing tabs: view
- Test case: View
Classestab, but command has a typo error- View
Classestab with typo:view clases. - Expected:
Invalid command format!This tab doesn't exists. You can only switch to students, timetable or classes.message show.
- View
- Test case: View
Classestab, but user is already onClassestab- View
Classestab:view classes. - Expected:
Successfully switched to CLASSES taband remains onClassestab.
- View
- Test case: View
Timetabletab, user is onClassestab- View
Timetabletab:view timetable. - Expected:
Successfully switched to TIMETABLE taband switched toTimeTabletab.
- View
Selecting a class: class
- Test case 1: viewing an existing class
- Prerequisites
- Add a class:
addclass cn/Sec 4 A Maths ct/MON 11:30-13:30 r/70 l/Nex Tuition Center - Note the class and its index in the displayed list in the
Classtab - Adding students to the class (assuming the class’s index is 1 and there are at least 2 students in Timestable):
addtoclass 1 1 2
- Add a class:
- view the class (assuming the class’s index is 1):
class 1 - Expected: the students list in
Classestab is showing students belonging to that class
- Prerequisites
- Negative test cases:
- Out of range
- (assuming the class list does not have 100 classes) enter
class 100 - Expected: “The class index provided is invalid” is displayed
- (assuming the class list does not have 100 classes) enter
- Out of range
Listing all students: list
- Test case: All
Students are listed and focus is moved to theStudentstab. All previous filtering is reset.- Prerequisite:
Studentfilter must be present. Steps to do this are below:- Delete
timestable.jsonin the data file to start of with the sample data in TimesTable.
- Delete
- Filter
Students:findname alex. OneStudentwith the nameAlex Yeohshould be listed. - Go to
Classestab:view classes - List all
Students:list - Expected:
Listed all studentsmessage shown and tab is changed to theStudentstab. The list ofStudents should be the same as before filtering (Step 2).
- Prerequisite:
Listing all classes: listclass
- Test case: All
TuitionClasses are listed and focus is moved toClassestab. All previous filtering is reset.- Prerequisites:
TuitionClassto filter must be present. Steps to do this are below:- Add
TuitionClass:addclass cn/Sec 4 A Maths ct/FRI 11:30-13:30 r/70 l/Nex Tuition Center - Note the
TuitionClasses in the class list.
- Add
- Filter classes:
findclassname hello. NoTuitionClasses should be listed. - Go to
Studentstab:view students - List
TuitionClasses:listclass - Expected:
Listed all classesmessage shown and tab is moved toClassestab. Class list noted in (ib) is shown.
- Prerequisites:
Appendix: Effort
The effort required to evolve AB3 to TimesTable could be estimated to be approximately the effort required to create AB3. Our team have contributed roughly 15k lines of functional code, automated unit and integration testing, and documentation.
Addition of Tabs
-
AB3did not have any different tabs. There was only one page showing thePerson’s contacts. - Addition of tabs was the start of the evolution from
AB3intoTimesTable. - By adding tabs, we could implement different UIs into each tab to give the user a better experience.
- The effort to add tabs was not very high, as we only had to add an additional JavaFx control.
- Building the contents of the Tabs was the difficult portion as we had to design the entire layout of the tabs by ourselves.
Addition of Timetable Tab
- Adding the Timetable Tab was difficult, as it was our first time building an interface like this.
- However, we were inspired by Pet Store Helper, and adapted some of their basic ui components for our application.
- Despite, adapting some of their basic ui components, the effort to build the Timetable Tab was still high, as we implemented the building process from scratch.
- We had to account for many JavaFx issues, alignments and row and column spans to build the slots, which was relatively hard as it was something new to us.
Addition of Classes Tab
- Adding the Classes Tab was difficult as we had to design an entire user interface from the ground up to both contain details of the
TuitionClasses in TimesTable and details of theStudents in each class. - We faced exceptional difficulty when making sure that the details of the
TuitionClass, such as size of the class, and the list ofStudents in each class, was being updated whenStudent(s) were being added or removed from any particular class, or when anyStudent’s orTuitionClass’s details were being edited. - The very design of the Classes Tab itself also necessitates a lot of coupling, because the view in the
StudentClassPaneldepended on the view in theClassListPanelas it changes based on what was clicked.
Addition of new fields
-
AB3initially had theName,Phone Number,Email,Address, andTagcategories. - For
TimesTable, we added additional fields likeClassTiming,ClassName,Rate,LocationandNok.
Addition of Tuition Class
- While AB3 only tracks persons, TimesTable also keeps track of Tuition Classes.
- The addition of the
TuitionClassrequired a great deal of effort as it brought a lot of problems at the start, such asTuitionClasses overlapping with one another when being added into theUniqueClassListthat contained allTuitionClasses in TimesTable, creating a clash in class timing that was undesirable for our intended user’s purpose. Another example is the problem of integratingTuitionClassandStudentwhich is further discussed below.
Addition of Commands
- TimesTable added many new commands:
addclass,deleteclass,addtoclass,removefromclass,editclass,findclass,findclassname,listclass,selectclass,findtag,sortandview - In addition, the
addandeditcommands were modified with the addition of TimesTable’s new Next-of-Kin field. Thefindcommand was also modified to allow for multi-word and partial matches. - Many of these commands required a lot of restructuring and addition of code. For instance, the class commands have to interact with both Tuition Classes and Students.
Integration of Classes and Students
- Integration of classes and students was difficult because it required
TuitionClasses to store references to theStudents. The simple solution would be to just store a list ofStudentin eachTuitionClassand store a list ofTuitionClassin eachStudent. However, we quickly found out that it was not the ideal design.This is because it would increase the overall level of dependencies in the project drastically mainly due to the fact thatTuitionClassandStudentare so tightly coupled together. It also decreased the overall testability due to high dependency. - Integration of classes and students was also cause storing and reading properly difficult due to their high degree of coupling and was very prone to error, resulting in a very large amounts of checks needed when reading from the data JSON file.
- The design that we eventually implemented was to use a list of
Names instead which effectively reduced overall dependency and the number of bugs that we had. It also reduced the number of lines in our codebase by hundreds which is great since we were able to achieve the same desired result with less code.