Project is based off of the AddressBook3 (AB3 Source Code)
URL Regex Validation - Adapted solution from Mustofa Rizwan
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 main components and how they interact with each other.
Main components of the architecture
Main
(consisting of classes Main
and MainApp
) is in charge of the app launch and shut down.
The bulk of the app's work is done by the following 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.Commons
represents a collection of classes used by multiple other components.
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 edit i:1 s/A0123456X
.
Each of the four main components (also shown in the diagram above),
interface
with the same name as the Component.{Component Name}Manager
class (which follows the corresponding API interface
mentioned 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.
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
, StudentListPanel
, StatusBarFooter
etc. 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,
Logic
component.Model
data so that the UI can be updated with the modified data.Logic
component, because the UI
relies on the Logic
to execute commands.Model
component, as it displays Student
object residing in the Model
.API : Logic.java
Here's a (partial) class diagram of the Logic
component:
The activity diagram below shows what happens in the DeleteCommandParser
and DeleteCommand
class when delete is used by the user
How the Logic
component works:
Logic
is called upon to execute a command, it is passed to an AddressBookParser
object which in turn creates a parser that matches the command (e.g., DeleteCommandParser
) and uses it to parse the command.Command
object (more precisely, an object of one of its subclasses e.g., DeleteCommand
) which is executed by the LogicManager
.Model
when it is executed (e.g. to delete a student).Model
) to achieve.CommandResult
object which is returned back from Logic
.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:
AddressBookParser
class creates an XYZCommandParser
(XYZ
is a placeholder for the specific command name e.g., AddCommandParser
) which uses the other classes shown above to parse the user command and create a XYZCommand
object (e.g., AddCommand
) which the AddressBookParser
returns back as a Command
object.XYZCommandParser
classes (e.g., AddCommandParser
, DeleteCommandParser
, ...) inherit from the Parser
interface so that they can be treated similarly where possible e.g, during testing.API : Model.java
The Model
component,
Student
objects (which are contained in a UniqueStudentList
object).Student
objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiable ObservableList<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.UserPref
object that represents the user’s preferences. This is exposed to the outside as a ReadOnlyUserPref
objects.Model
represents data entities of the domain, they should make sense on their own without depending on other components)Note: An alternative (arguably, a more OOP) model is given below. It has a Tag
list in the AddressBook
, which Student
references. This allows AddressBook
to only require one Tag
object per unique tag, instead of each Student
needing their own Tag
objects.
API : Storage.java
The Storage
component,
AddressBookStorage
and UserPrefStorage
, which means it can be treated as either one (if only the functionality of only one is needed).Model
component (because the Storage
component's job is to save/retrieve objects that belong to the Model
)Classes used by multiple components are in the educonnect.commons
package.
This section describes some noteworthy details on how certain features are implemented.
Student
object now has a Timetable
object as an attribute.Timetable
contains 5 or 7 Day
objects, by default, 5 days of the week (Monday - Friday) is used.Day
object can contain 0 to 24 1-hour Period
objects, or less if each Period
has intervals longer
than 1 hour.Period
is defined by the start time and end time, indicated by integers on a 24-hour clock,
i.e. 0-23, which refers to 12 AM till 11 PM.Day
cannot contain any overlapping Period
.
Period
is before the end time of the next Period
.Period
of 12-14, Period
of 14-16 is allowed, but Period
of 13-15 is not.add
command, or subsequently modified using the edit
command, the Timetable
is assumed
to be empty, indicating no occupied period.The Timetable
of the Student
shown during the list
command, followed by a timetable
keyword.
The timetable
keyword is optional, and if the command is used without the timetable
keyword, students will be shown without timetables.
The option of displaying timetables will be saved and will remain the same for subsequent commands, unless another list
command with different option is received.
Each time the application is launched, the timetable will be hided in default.
Below shows the sequence diagram when listing students with timetables.
Timetable
of the Student
can be specified during the add
command, indicated with a c/
prefix.Timetable
of a Student
can be modified during the edit
command, with the same prefix.c/
prefix is optional, and if not specified,
an empty Timetable
object will be created as the attribute of the Student
.
Timetable
object can be broken down into its respective day and periods that day contains.{DAY_3_LETTERS}:
, e.g. "mon:"
or "fri:"
.{HOUR-HOUR}
, in a 24-hour clock, e.g. "12-14", indicating 12 PM to 2 PM.String
is "mon: 13-15, 15-17 tue: 12-14 thu: 12-18"
.The finding a common slot feature will have a portion implemented similarly to the find
command.
The command consists of a mandatory specified duration, and optional arguments for higher specificity,
and a common empty slot across all students that fulfils the duration requirement will be outputted to the user.
The command is implemented as such: slots d/DURATION [t/TAG] [p/TIMEFRAME_PERIOD] [o/ON_WHICH_DAYS]
d/
is the prefix for duration.t/
is an optional argument for a filtered list of students.
p/
is an optional argument for specifying the timeframe to look for slots.
o/
is an optional argument for on which days specifically to look for slots.
Examples:
slot d/1
- EduConnect will look through the current list of students, i.e. can be the full list, or a filtered
list if ran after the find
command, then returns all the 1-hour slot(s) available for the week.slot d/2 t/tutorial-1
- EduConnect will first filter and get the list of students with the tag tutorial-1
,
then return all the 2-hour slot(s) available for the week.slot d/3 p/12-18 o/tue, wed, thu t/tutorial-2
- EduConnect will first filter and get the list of students
with the tag tutorial-2
, then returns all the 3-hour slot(s) available,
between 12 PM to 6 PM, on Tuesdays, Wednesdays, and Thursdays only.The command's execution will iterate through the selected list of students, accessing each Timetable
object's
list of Day
objects.
Day
object will look for valid Period
that does not overlap with its own list of Period
objects.Period
and Day
will be collected from each Timetable
of each Student
,
and returned as an AvailableSlots
objects, which is collected in a List
.AvailableSlots
will then be filtered out
and returned as a singular AvailableSlots
object.The diagram below shows the sequence diagram for an example execution of finding common slots.
{more functionality to be implemented in later versions}
The inclusion of the Link
attribute enhances the versatility of EduConnect, enabling storage and access to project or assignment weblinks for each student. This feature facilitates efficient collaboration and evaluation by Teaching Assistants (TAs) and provides students with a convenient means to showcase their work.
Student
has an additional attribute Link
Link
is responsible for storing the student's project or assignment weblink for ease of access by the TA.Link
is wrapped around a Java Optional
in Student
. This means that if the link is not specified during construction of a new Student
, the student's Link
attribute will initialized as Optional.empty
.Link
must be a valid URL, and a validation regex is present to check the validity of the link
.Link
attribute need not be unique as group members will share the same project link. Therefore, enforcing uniqueness for the Link
attribute could lead to unnecessary constraints and complexity.The regex used for validating the URL is as shown below:
^(?<scheme>(?:ftp|https?):\/\/)?+
(?:
(?<username>[a-zA-Z][\w-.]{0,31})
(?::(?<password>[!-~&&[^@$\n\r]]{6,255}))?
@)?
(?<subdomain>(?:[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?\.){0,127})
(?<domain>[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9])
(?<tld>\.[a-zA-Z]{3,63})
(?<cctld>\.[a-zA-Z]{2})?
(?<portnumber>:\d{1,5})?
(?<path>(?:\/{1,2}[\w-@.~()%]*)*)
(?<querystring>\?(?:[\w-%]+=[\w-?/:@.~!$&'()*+,;=%]+(?:&[\w-%]+=[\w-?/:@.~!$&'()*+,;=%]+)*)?)?
(?<fragment>#[\w-?/:@.~!$&'()*+,;=%]+)?$
The capture group plan is:
Group Number | Group name | Example |
---|---|---|
1 | scheme | ftp:// http:// https:// |
2 | username | user schooluser |
3 | password | password123 PxJmot@S!KL1 |
4 | subdomain | www. blog. news. |
5 | domain | google youtube github |
6 | tld | .com .net .org |
7 | cctld | .sg .jp .uk .de |
8 | port | :8080 :443 :53 |
9 | path | /article /tp/UserGuide.html |
10 | querystring | ?q=cat ?q=pokemon+red&ie=UTF-8 |
11 | fragment | #xpointer(//Rube) #dfsdf |
Hyperlink
class at StudentCard.java
.Student
, Link
can be specified during the add
command, indicated with a l/
prefix.Student
using the add command, the l/
prefix is optional.Link
can also be modified using the edit
command with the l/
prefix.Link
.Implemented similarly to the find
command, the copy
command first filters the FilteredList<Student>
to display all students with the tags specified in the command.
copy t/tutorial-1
filters and displays all students with the exact tag tutorial-1
.The FilteredList<Student>
is then iterated through, retrieving all student emails in the list and joining by ,
delimiter (ascii hexadecimal 0x2C
comma and 0x20
space).
example1@email.com, example2@email.com, example3@email.com
.Gmail
, Outlook
, Yahoo Mail
, etc.The feature is implemented using javafx.scene.input.Clipboard
instead of java.awt.datatransfer.Clipboard
as we are using JavaFX for the UI.
The fomatted email string is added to Clipboard
as a plain text String text/plain
(NOT a HTML String text/html
).
copy t\tutorial-1
.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 s/A1234567X
command to delete the student with that unique identifier in the address book. The delete
command calls Model#commitAddressBook()
, causing the modified state of the address book after the 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 student. The add
command also calls Model#commitAddressBook()
, causing another modified address book state to be saved into the addressBookStateList
.
Note: If a command fails its execution, it will not call Model#commitAddressBook()
, so the address book state will not be saved into the addressBookStateList
.
Step 4. The user now decides that adding the student 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.
Note: If the currentStatePointer
is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The undo
command uses Model#canUndoAddressBook()
to check if this is the case. If so, it will return an error to the user rather
than attempting to perform the undo.
The following sequence diagram shows how an undo operation goes through the Logic
component:
Note: The lifeline for UndoCommand
should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Similarly, how an undo operation goes through the Model
component is shown below:
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.
Note: If the currentStatePointer
is at index addressBookStateList.size() - 1
, pointing to the latest address book state, then there are no undone AddressBook states to restore. The redo
command uses Model#canRedoAddressBook()
to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
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:
Aspect: How undo & redo executes:
Alternative 1 (current choice): Saves the entire address book.
Alternative 2: Individual command knows how to undo/redo by itself.
delete
, just save the student being deleted).{more aspects and alternatives to be added}
{Explain here how the data archiving feature will be implemented}
Target user profile:
Value proposition: Our app helps you, an active TA, manage contact details of students in both big or small tutorial classes. Keep track of student progress, access links to their projects, or simply de-conflict class schedules.
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low (unlikely to have) - *
Priority | As a … | I want to … | So that I can… |
---|---|---|---|
* * * | new user | see usage instructions | refer to instructions when I forget how to use the App |
* * * | user | add a new student | |
* * * | user | delete a student | remove entries that I no longer need |
* * * | user | find a student by name / email / student ID | locate details of students without having to go through the entire list |
* * | user | filter students by their class / skill group | view details belonging to sub-group of student instead of the full list |
* * | user | edit an existing student | not have to delete and add a new student if I want to change one attribute |
* * | user | find a common available time slot amongst my students | set up a consultation / meeting / additional session(s) |
* | user with many students in the address book | filter students by their tag (class or skill group) | locate a student easily |
* | user who uses this long-term | purge all existing data | reset this application for each new semester |
* | user | have quick access for help on specific commands | get reminders / assistance on commands directly from the application |
{More to be added}
System: EduConnect
Use Case: UC1 - Adding a class of students (tagged by class)
Actor: TA
MSS:
Use case ends.
Extensions:
System: EduConnect
Use Case: UC2 - List all student contacts in a tutorial class
Actor: TA
MSS:
Extensions:
Use Case ends
System: EduConnect
Use Case: UC3 - Delete students from existing contacts in a tutorial class
Actor: TA
MSS:
Extensions:
System: EduConnect
Use Case: UC4 - Find students from existing contacts by their name
Actor: TA
MSS:
Extensions:
Use Case ends
System: EduConnect
Use Case: UC5 - TA finds a common time slot amongst one class of students
Actor: TA
Use case ends.
Extensions:
System: EduConnect
Use Case: UC6 - Exploring the application for the first time
Actor: TA (First-time user of the product)
MSS:
Use case ends.
11
or above installed.Given below are instructions to test the app manually.
Note: These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
Initial launch
Download the jar file and copy into an empty folder
Double-click the jar file
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.
Explore other test cases...
Listing all students in the address book.
Test case: list
Test case: list timetable
Deleting a student while all students are being shown
Prerequisites: List all students using the list
command. Multiple students in the list.
Test case: delete s/A1234567X
Test case: (No such student with unique identifier) delete s/A0000000U
Other incorrect delete commands to try: delete
, delete x
, ...
(where x is a non-unique identifier prefix)
Explore other test cases...
Dealing with missing/corrupted data files
Prerequisites: At least one student in the addressbook. Confirm using the list
command.
Navigate to the directory with the EduConnect jar file.
If not done, open EduConnect by double-clicking on the jar file.
Navigate to ./data
and open addressbook.json
in your preferred text editor.
Remove a field in any of the json data, save and exit.
Open the EduConnect.
Explore other test cases...
Build the application upon AB3 was a challenge for us during the starting stage of development. We took some time to get familiar with the AB3 code base, while also deciding features to adapt/remove to develop EduConnect.
In version 1.4, the debugging stage required strategies to address several challenging issues, such as regex validation and parser support for multiple timetables. Through effective teamwork and collaborative discussions, we successfully resolved these issues.
Efforts were allocated across various project phases, including requirement analysis, design, development, testing, deployment, and debugging.
We also emphasized considerable efforct on team collaboration to make the development process smooth.
Successful implementation of core functionalities, including finding common slots and copying student emails, which showcases our goal of creating an application with user-centric features.
Implementation of GUI(Graphic User Interface) which aligns with the UI design as outlined in the project planning phase.
Adherence to project timelines and deliver the milestones on time.
Team Size: 6
Use a better font: User experience is greatly influenced by font, and choosing the right font can significantly enhance readability, Especially for EduConnect with numeric details of students displayed, the current font causes confusion sometimes. We plan to adapt a new font which not only improve the overall appearance of the platform but also contribute to a smoother reading experience for users. Currently, we are aware that the number 1
and the letter l
look too similar to users.
Hover over ‘Project Link’ shows the full link: Currently, when hovering over the project link, nothing will be shown. We plan to provide users with the convenience of viewing the full link by simply hovering over it. We aim to allow users to quickly verify the complete URL without having to click on it.
Show partial ‘Project Link’ in UI: Instead of simply a text Project Link
, we plan to show the domain name and Top Level Domain (TLD) of the link. For example, https://ay2324s2-cs2103-t14-1.github.io/tp/UserGuide.html
will show up as github.io
.
Better timetable display: The current timetable of each student is displayed in text with little formatting. We plan to enhance the timetable display by incorporating a standardized graphical format, such as calendar or grid layout. This would allow users to quickly grasp their schedules at a glance and navigate through different time slots more efficiently.
View student details: The ability to view comprehensive details of each student in text, including their project link and timetable, is essential for effective management and communication within EduConnect. We plan to introduce a new "View Student" function, allowing users to access all student information conveniently.
Full Name display: If the student's name is too long, the name may be shorted and display [partial student name]...
, leaving users unable to view the full name. We plan to limit the length of the name to 100 and ensure the minimum window size would allow the full name to be viewed at all times.
Limits to Telegram Handle, Email and Tags: There is currently no character limit for the Telegram Handle
, Email
and Tag
fields. We plan to limit these fields to an appropriate character count to better represent these fields. Example:
Editing Student with the same details: Currently, when editing a student with the same details, no error message is displayed and EduConnect updates the Student with the same data. This is may confuse users and it will result in no changes while still showing a successfuull update. We plan to add a check and display the proper error message. E.g. A student with telegram handle @bunny
, when running the command edit h:@bunny h/@bunny
should return an error message Duplicate telegram handle supplied.
Saturday and Sunday timetable: Add an option to enable/disable Saturday and Sunday in the timetable. Currently, only Monday to Friday are enabled and periods can only be added within these 5 days. Extending the feature to 7 days will help for the situation where there are weekend classes.