layout | title | pageNav |
---|---|---|
default.md |
Developer Guide |
3 |
Refer to the Setting Up and Getting Started guide.
The Architecture Diagram above provides a high-level overview of the application's architecture.
Below, you'll find a concise summary of the main components and their interactions.
Main
(comprising classes
Main
and MainApp
is responsible for launching and shutting down the application.
- On app launch, it initializes the other components in the correct sequence, and establishes connections between them.
- During shutdown, it closes other components and triggers cleanup operations when necessary.
The bulk of the app's work is done by the following four components:
UI
: Handles the interaction with User.Logic
: Executes user commands.Model
: Manages the in-memory data of the app.Storage
: Handles reading and writing of data to the hard disk.
Commons
encompasses a set of classes shared across
multiple components.
The Sequence Diagram below illustrates the interactions between components when the user issues the delete 1 command.
Each of the four primary components (as depicted in the diagram above),
- Defines its API through an
interface
bearing the same name as the component. - Implements its functionality using a concrete
{Component Name}Manager
class that follows the corresponding APIinterface
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
adheres to the Logic
interface. Other components interact with a given
component through its interface rather than the concrete class.
The reason for this practice is to decouple outside components from the
internal implementation of the component.
This decoupling is illustrated in the (partial) class diagram below.
For more comprehensive details on each component, please refer to the sections below.
API:
Ui.java
The UI component comprises a MainWindow
composed of various parts, such as the
CommandBox
, ResultDisplay
, InternApplicationListPanel
, StatusBarFooter
,
and more.
All of these elements, including the MainWindow
, inherit from the
abstract UiPart
class which encapsulates common characteristics among classes
representing different parts of the visible GUI.
The UI
component leverages the JavaFx UI framework.
The layout of these UI parts are defined in matching .fxml
files located in
src/main/resources/view
.
For example, the layout of
the MainWindow
is specified
in MainWindow.fxml
The UI
component,
- Executes user commands by interacting with
the
Logic
component. - Monitors changes in the data within the
Model
to update the UI accordingly. - Maintains a reference to the
Logic
component, since theUI
relies on it for command execution. - Depends on certain classes within the
Model
component, as it displaysInternApplication
objects residing in theModel
.
API:
Logic.java
The class diagram below provides a partial view of the Logic
component.
To illustrate the interactions within the Logic
component, we'll use the
execute("delete 1")
API call as an example in the sequence diagram below:
Note: The lifeline for DeleteCommandParser
and DeleteCommand
should end at the destroy marker (X) but due to a limitation in PlantUML,
the lifeline extends to the end of the diagram.
The creation of the internApplication
object has been omitted for brevity.
How the Logic
component works:
- When
Logic
is called upon to execute a command, it is passed to anInternTrackerParser
object. TheInternTrackerParser
then creates a specific parser ( e.g.,DeleteCommandParser
) tailored to match and parse the command. - This results in the creation of a
Command
object, specifically an object of one of its subclasses (e.g.DeleteCommand
). This command is then executed by theLogicManager
. - The executed command may interact with the
Model
when it is executed, such as to delete anInternApplication
object from theModel
. - The result of the command execution is encapsulated as a
CommandResult
object which is returned byLogic
.
In addition to the class diagram above, there are other classes (omitted from the class diagram above) within the Logic component that are used for parsing user commands:
How commands are parsed:
- When called upon to parse a user command, the
InternTrackerParser
class creates anXYZCommandParser
(whereXYZ
is a placeholder for the specific command name e.g.,AddCommandParser
). TheXYZCommandParser
then uses the other classes shown above to parse the user command and create aXYZCommand
object (e.g.,AddCommand
). ThisXYZCommand
is then returned as aCommand
object by theInternTrackerParser
. - All
XYZCommandParser
classes ( e.g.,AddCommandParser
,DeleteCommandParser
, ...) inherit from theParser
interface, allowing them to be treated similarly where possible, especially during testing.
API:
Model.java
The class diagram below provides an overview of the Model
component:
The Model
component has the following responsibilities:
- Stores the intern tracker data, which includes all
InternApplication
objects. These objects are stored in aUniqueApplicationList
container. - Maintains a separate filtered, sorted list of 'selected'
InternApplication
objects, which is exposed to outsiders as an unmodifiableObservableList<InternApplication>
. This list can be observed, allowing the UI to automatically update when its contents change (e.g. after afind
orsort
command). - Stores a
UserPref
object that represents the user’s preferences. This is exposed as aReadOnlyUserPref
object. - Importantly , the
Model
does not depend on any of the other 3 components (UI
,Logic
,Storage
). Since theModel
represents data entities of the domain, it's designed to stand independently of the other components.
API:
Storage.java
The Storage
component,
- Can save both intern tracker data and user preference data in JSON format
- Read data from JSON files and convert them into corresponding objects within the application.
- Inherits from both
InternTrackerStorage
andUserPrefStorage
, which allows it to be used as either one, depending on the functionality needed. - Depends on some classes in the
Model
component (because theStorage
component's job is to save/retrieve objects that belong to theModel
).
Classes that are used across multiple components are located within the
seedu.letsgethired.commons
package.
These common classes served as shared utilities and functionalities that
contribute to the application's overall functionality.
For example, the seedu.letsgethired.commons.util.StringUtil
class provides
commonly used string manipulation methods.
This section describes some noteworthy details on how certain features are implemented.
The add
command enables users to add new internship application into the
Intern Tracker.
Adding a new internship application involves executing the AddCommand
.
- The
AddCommand
is parsed by theAddCommandParser
. AddCommandParser#parse()
parses the user input and returns anAddCommand
object for execution.
Given below is an example usage scenario outlining how the add
command
behaves at each step.
Step 1. The user executes
add n/Jane Street r/Full Stack Developer c/Summer 2024
This command adds a new InternApplication
into the InternTracker
.
Note: Some fields for the add
command are optional. For more information
on the add
command, refer to
the User Guide.
Step 2. The AddCommandParser
parses the arguments, ensuring that
compulsory fields are present and valid.
It then creates a new InternApplication
object with all the provided fields
and returns an AddCommand
object containing the
InternApplication
object ready to be added to the Model
.
Step 3. The AddCommand#execute()
method is invoked by the LogicManager
.
The AddCommand#execute()
calls the Model#addInternApplication
method to add
the newly created InternApplication
object to the Model
.
Step 4. The AddCommand#execute()
method returns a new CommandResult
object that contains feedback and display messages for the user.
This result is then handed back to the LogicManager
.
The sequence diagram below shows the process of adding a new internship application:
Note: The input for the AddCommand
has been truncated for brevity.
Note: The lifeline for AddCommandParser
and AddCommand
should end at the destroy marker (X)
but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The creation of the internApplication
object has been omitted for brevity.
Aspect: Criteria for a identifying duplicate internship application entry:
- Alternative 1 (current choice): The combination of
(
COMPANY_NAME
,ROLE
andCYCLE
) must be unique.- Pros: Allow users to add an internship application to the same company for different roles or during different cycles.
- Cons: Users are required to input additional compulsory fields.
- Alternative 2: Enforce uniqueness based only on
COMPANY_NAME
- Pros: Allow users to add a new internship application quickly.
- Cons: It restricts users to having only 1 internship application with a given company.
The find
command enables the users to search internship applications by
looking up a keyword in any of the fields associated with
an internship application.
Performing a Find
operation involves executing the FindCommand
.
- The
FindCommand
is parsed by theFindCommandParser
. FindCommandParser#parse()
parses the user input to return aFindCommand
object that will be executed.
Given below is an example usage scenario and how the mechanism behaves at each step.
Step 1. The user keys in the command word to find an internship
application, find
.
find n/Jane c/Summer
Note: At least one field to be searched and the respective keyword for searching should be provided.
Step 2.
The FindCommandParser
will execute to get the field and keyword pairs
using the ArgumentTokenizer
.
The parser creates a new CompanyContainsFieldKeywordsPredicate
object,
which acts as a predicate that will be used to obtain a filtered list of
internship applications that have the specified keywords in respective fields.
The parser returns a FindCommand
object with
the Predicate<InternApplication>
, specifically the
CompanyContainsFieldKeywordsPredicate
.
Step 3. The FindCommand#execute()
method is invoked by the LogicManager
.
The FindCommand
calls the
Model#updateFilteredInternApplicationList()
to update the filtered internship
application list using the
Predicate<InternApplication>
, and then
the Model#getFilteredInternApplicationList()
to obtain the filtered, sorted
internship application list.
Step 4. Finally, the FindCommand
creates a CommandResult
object that
contains feedback and displays the filtered internship application list to the
user.
The result is then returned to the LogicManager
.
The sequence diagram below shows the process of finding internship applications.
Note: The lifeline for FindCommandParser
and FindCommand
should end at the destroy marker (X)
but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The note command enables the users to add or delete notes to an internship application.
To add or delete a Note
, the NoteCommand
must be executed.
It is worth noting that the NoteCommand is implemented differently from the other Commands.
From the above class diagram, the NoteCommand
is an abstract class that is
inherited by the NoteInsertCommand
class
and the NoteDeleteCommand
class. This is done so that
the NoteCommand#execute()
method can behave accordingly while
still having both NoteCommand
classes share the command word that is note
.
The NoteCommand
is parsed by
the NoteCommandParser
. NoteCommandParser#parse()
parses the user input to
return
either a NoteInsertCommand
or a NoteDeleteCommand
object that will be
executed.
Given below is an example usage scenario and how the mechanism behaves at each step for note addition.
Step 1. The user keys in the command word to add a note, note
.
note 1 i/Need to revise Rust
This command appends the note to the internship application with the index 1
.
Note: The INDEX
for the note
command is compulsory.
The i/
prefix is compulsory for adding a note, and cannot appear at the same
time as the o/
prefix for deleting a note.
For more information on the note
command, refer to the
User Guide.
Step 2 The NoteCommandParser
parses the arguments, ensuring that
the compulsory fields are present.
In particular, the parser checks that the i/
prefix is present and
the o/
prefix is absent.
The parser then returns a NoteInsertCommand
object containing the Note
object ready to be added into Model
Step 3. The NoteCommand#execute()
method is invoked by the LogicManager
.
The NoteCommand#execute()
method creates a new InternApplication
with the note appended to its
ArrayList
of notes.
Step 4. The NoteCommand
calls the Model#setInternApplication()
and Model#updateFilteredInternApplicationList()
methods to add the new internship application with the note to the model, and
replace the old internship application.
Step 5. The NoteCommand
creates a CommandResult
object that contains the
feedback and InternApplication
to the user,
which is returned to the LogicManager
.
The sequence diagram below shows the process of adding a note:
Note: The lifeline for NoteCommandParser
and NoteInsertCommand
should end at the destroy marker (X)
but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The creation of the internApp
and internAppToEdit
objects have
been omitted for brevity.
Given below is an example usage scenario and how the mechanism behaves at each step for note deletion.
Step 1. The user keys in the command word to add a note, note
.
note 1 o/2
This command deletes the note with index 2
from the internship application
with index 1
.
Note: The INDEX
for the note
command is compulsory.
The o/
prefix is compulsory for deleting a note, and cannot appear at the same
time as the i/
prefix for adding a note.
For more information on the note
command, refer to the
User Guide.
Step 2. The NoteCommandParser
parses the arguments and ensures
that the compulsory fields are present.
In particular, the parser needs to check if the o/
prefix
is present and the i/
prefix is absent.
The parser then returns a NoteDeleteCommand
object with the Index
of the
object to be deleted from the Model
.
Step 3. The NoteCommand#execute()
method is called by the LogicManager
.
The NoteCommand#execute()
method creates a new InternApplication
with the corresponding note removed
from its ArrayList
of notes.
Step 4. The NoteCommand
calls the Model#setInternApplication()
and Model#updateFilteredInternApplicationList()
methods to add the new internship application with the note to the model, and
replace the old internship application.
Step 5. The NoteCommand
creates a CommandResult
object that contains
feedback and InternApplication
to the user,
which is returned to the LogicManager
.
The sequence diagram below shows the process of deleting a note.
Note: The lifeline for NoteCommandParser
and NoteDeleteCommand
should end at the destroy marker (X)
but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
The creation of the internApp
and internAppToEdit
objects have
been omitted for brevity.
The sort
command enables the users to sort the internship applications by
a specific field.
Note: This implementation does not allow for sorting by multiple fields.
To introduce the sort
feature, we make the following changes to the codebase:
-
Extension of the Model Interface: We enhance the
Model
interface to include a new method:Model#updateFilteredSortedInternApplicationList(Comparator<InternApplication> comparator)
- This method sorts the intern application list by the given comparator.
-
ModelManager Enhancements: In the
ModelManager
class, we wrap the existingfilteredInternApplications
in a JavaFXSortedList
to create a newfilteredSortedInternApplications
field. This new field, allows us to sort the intern applications to be displayed based on the specified comparator. -
Update existing methods:
Model#getFilteredInternApplicationList()
is updated to return the filtered and/or sorted intern application list.
Note: JavaFX's SortedList
class extends the ObservableList
class, which
ensures that any changes made to either the FilteredList
or the original
UniqueApplicationList
will automatically propagate to the UI.
To understand how these changes are integrated into the application, refer to the sequence diagram below:
Note: The lifeline for SortCommandParser
and SortCommand
should end at the destroy marker (X)
but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
Aspect: How sorting is done
- Alternative 1 (current choice): Wrap the existing
FilteredList
in aSortedList
.- Pros: More flexible, as we can both sort and filter without modifying the
original
UniqueApplicationList
.
- Pros: More flexible, as we can both sort and filter without modifying the
original
- Alternative 2: Sort the applications in the
UniqueApplicationList
in theInternTracker
.- Cons: Requires us to revert the sorting done by
the
UniqueApplicationList
before saving the data to preserve the initial order in which the intern applications are added.
- Cons: Requires us to revert the sorting done by
the
Aspect: Comparator
- Alternative 1: Use a
Comparator<InternApplication>
object.- Pros: More flexible, as we can sort the intern applications by different comparators.
- Cons: Requires us to create a new
Comparator<InternApplication>
object for each sorting operation. - Difficult to test for functional equality, as
equals()
method forComparator
only tests for referential equality.
- Alternative 2 (current choice): Wrap the comparator in
an
InternApplicationComparator
class- Pros: Allows us to reuse the same comparator for different sorting operations, which makes it easier to test for equality.
- Allows us to strictly define which comparators are allowed.
The undo mechanism is facilitated by VersionedInternTracker
. It
extends InternTracker
and maintains an undo history internally as a
stack named savedStates
.
Additionally, it implements the following operations:
VersionedInternTracker#commit()
— Saves the current intern tracker state in its history.VersionedInternTracker#undo()
— Restores the previous intern tracker state from its history.
VersionedInternTracker#undo()
is exposed in the Model
interface
as Model#undoAction()
.
Given below is an example usage scenario and how the undo mechanism behaves at each step.
Step 1. The user launches the application.
The VersionedInternTracker
will be initialized with an empty savedStates
.
Step 2. The user executes delete 5
command to delete the 5th
internApplication
from the intern tracker.
The delete
command calls Model#deleteInternApplication()
, which
calls VersionedInternTracker#commit()
,
capturing a copy of the current internApplications
to savedStates
before
executing the delete action.
Step 3. The user adds a new internship application.
add n/Google r/Software Engineer c/Summer 2024
The add
command calls Model#add()
which also calls
VersionedInternTracker#commit()
,
adding a copy of the current internApplications
to savedStates
before executing the add action.
Note: If a command execution fails, the
internApplications
state will not be added to savedStates
(i.e. VersionedInternTracker#commit()
will not be called).
Step 4. The user now decides that adding the internApplication
was a
mistake,
and decides to undo that action
by executing the undo
command. The undo
command will
call Model#undoAction()
, which pops the latest
internApplications
state from savedStates
and assigns it to the current
internApplications
.
Note: If the size of savedStates
is 0, meaning the stack is empty, then
there are no previous
internApplications
states to restore. The undo
command
calls VersionedInternTracker#undo()
, which returns
False if there are no states to restore, and displays a message to the user that
the latest change has already been reached.
The following sequence diagram shows how the undo operation works:
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.
Step 5. The user then decides to execute the command list
. Commands that
do
not modify the intern tracker,
such as list
, will usually not
call VersionedInternTracker#commit()
, Model#undoAction()
Thus, the savedStates
remains unchanged.
The following activity diagram summarizes what happens when a user executes a new command:
Aspect: How undo executes:
-
Alternative 1 (current choice): Saves the entire intern tracker.
- Pros: Easy to implement.
- Cons: May have performance issues in terms of memory usage, especially if many operations are carried out.
-
Alternative 2: Implement an
undo
operation for each individual command.- Pros: This method conserves memory (e.g. for
delete
, it only saves theinternApplication
being deleted). - Cons: It requires updating the interface for
Command
and an implementation for each individual command.
- Pros: This method conserves memory (e.g. for
Aspect: How history is implemented:
-
Alternative 1: Using a list and pointer to implement version control
- Pros: Will allow for more feature-rich commands, such as
redo
. - Cons: Uses more memory than a stack, as saved states are still stored after the undo operation.
- Pros: Will allow for more feature-rich commands, such as
-
Alternative 2 (current choice): Store the saved state in a stack
- Pros: Will use less memory, as saved states are popped off the stack
after
undo
. - Cons: Will not allow for
redo
operations.
- Pros: Will use less memory, as saved states are popped off the stack
after
This feature allows the user to click on an InternApplicationCard
in the
InternApplicationListPanel
to display the details of the InternApplication
.
The Card click mechanism is implemented by creating a GridPane
beside
the InternApplicationListPanel
and a listener function to handle the event of a card click. The GridPane
notably comprises 1 TextArea
for notes
and 5 TextField
s for other details of an Intern Application
The following class is created:
SelectView
- This class represents the panel responsible for displaying the details of the card.
The following methods are added:
SelectView#displayDetails(InternApplication internApplication)
- sets each details in the intern application in each correspondingTextField
orTextArea
.SelectView#clearDetails()
- clears all contents in theSelectView
'sTextField
orTextArea
.InternApplicationListPanel#setSelectedItemListener()
- adds a listener method to theListView
model that calls theSelectView#displayDetails(InternApplication internApplication)
whenever a different item on the list is selectedInternApplicationListPanel#getSelectedItemIndex()
- returns the index of the currently selected item in theListView
Given below is an example usage scenario and how the mechanism behaves at each step.
Step 1. The user clicks on the intern application card he wants to view.
Step 2 The ChangeListener
that was set into the ListView
triggers from the
event and executes
a method to execute view INDEX
where INDEX
is the corresponds to the item's
relative index on the list.
Step 3. The Logic
creates a CommandResult
object from
the ViewCommand#execute()
. The CommandResult
contains
a String feedback and InternApplication
to the user.
Step 4. The InternApplication
in the CommandResult
is then passed into
the
SelectView#displayDetails(InternApplication internApplication))
where each
field in the intern application is
displayed in its respective TextArea
or TextField
.
The following sequence diagram high level view of how the Card Click feature works:
Note: The internApplication
object is present in the CommandResult
.
The method call to obtain the internApplication
object has been omitted for
brevity.
Aspect: What data type should displayDetails
take in:
-
Alternative 1 (current choice):
InternApplication
Object.- Pros: Easy to implement. We can just extract individual values from the object without needing to parse a string
- Cons: Added dependency of
InternApplication
in bothInternApplicationListPanel
andSelectView
-
Alternative 2: String containing all field data in the involved
InternApplication
Object- Pros: Reduce coupling between
InternApplicationList
,SelectView
, andInternApplication
- Cons: Requires an additional step of parsing, which makes code much more complex.
- Pros: Reduce coupling between
Here are the definitions of some terms which is used throughout the User Guide and Developer Guide.
Term | Definition |
---|---|
Command Line Interface (CLI) | A type of user interface in which the user interacts with a system by typing commands into a terminal or console. |
Graphical User Interface (GUI) | A type of user interface that allows users to interact with a system through graphical icons and visual indicators. |
Hyperlink (link) | A reference in the webpage that allows users to directly access another location or file within the same or a different webpage. |
Command Terminal | A software-based interface that provides an environment for users to interact with a computer's operating system or software by typing textual commands and receiving text-based output. |
Sample Data | Pre-populated data used for demonstration purposes, enabling new users to see how the application functions with realistic examples. |
Workflow | A systematic and repeatable pattern of activity that a user follows to accomplish a specific task. |
Command | An input from the user that tells LetsGetHired which action to perform. |
Parameter | A placeholder used in a command to represent a piece of information that needs to be provided when that command is executed. |
JSON (JavaScript Object Notation) | A lightweight data-interchange format that is easy for humans to read and write and easy for machines to parse and generate. |
Target user profile:
- CS undergraduate
- is looking for tech internships
- needs something to organise their internship applications
- prefer desktop apps over other types
- can type fast
- prefers typing to mouse interactions
- is reasonably comfortable using CLI apps
Value proposition: provides a fast and organized way to see internships and its progress, optimized for users who prefer a CLI
Priorities: High (must have) - * * *
, Medium (nice to have) - * *
, Low
(unlikely to have) - *
Priority | As a ... | I want to ... | So that I can... |
---|---|---|---|
* * * |
user | add internship applications | keep a record of my internship application |
* * * |
user | see a list of internships that I have applied for | keep track of all companies/roles I have applied for |
* * * |
user | view a specific internship application | easily access details about a specific internship application |
* * * |
user | delete an internship application | remove internship applications I do not want to track anymore |
* * * |
user | update the status of the internships that I have applied for | keep track of the progress of the roles I have applied for |
* * * |
user | edit an internship application | update or change details for an internship application |
* * * |
user | open the app with a click of a button or an exe/batch file | save time and easily access the internship tracker |
* * |
user with many applications | quickly search for a application | efficiently find the entry I am looking for |
* * |
conscientious user | attach notes to each application | jot down important information about the company or application process |
* * |
organised user | sort my applications | easily get an organised view of my applications |
(For all use cases below, the System is the LetsGetHired
application
and the Actor is the User
, unless specified otherwise)
UC1: Add an internship application
MSS
-
User inputs the details of the internship application.
-
LetsGetHired adds the internship application to the list of internship applications and displays it.
Use case ends.
Extensions
-
1a. The command format is incorrect.
-
1a1. LetsGetHired notifies the user of the error.
-
1a2. User enters the correct details for the internship application.
Use case resumes from Step 2.
-
-
1b. The internship application already exists in the list of internship applications.
-
1b1. LetsGetHired notifies the user that the internship application already exists.
Use case ends.
-
UC2: View the list of internship applications
MSS
-
User requests to list all internship applications.
-
LetsGetHired displays all the internship applications.
Use case ends.
UC3: View an internship application
MSS
-
User requests to list all internship applications (UC2)
-
User requests to view a specific internship application.
-
LetsGetHired displays the specified internship application.
Use case ends.
Extensions
-
1a. LetsGetHired displays an empty list.
Use case ends.
-
2a. The command format is incorrect.
-
2a1. LetsGetHired notifies the user of the error.
Use case resumes from Step 2.
-
-
2b. The index of internship application entered does not exist.
-
2b1. LetsGetHired shows an error message.
Use case resumes from Step 2.
-
UC4: Delete an internship application
MSS
-
User requests to list all internship applications (UC2).
-
User requests to delete a specific internship application.
-
LetsGetHired deletes the specified internship application.
Use case ends.
Extensions
-
1a. The list is empty
Use case ends.
-
2a. The command format is incorrect.
-
2a1. LetsGetHired notifies the user of the error.
Use case resumes from Step 2.
-
-
2b. The index of internship application entered does not exist
-
2b1. LetsGetHired shows an error message.
Use case ends.
-
UC5: Search for an application
MSS
-
User requests for a search by specific criteria.
-
LetsGetHired shows a list of matching applications.
Use case ends.
Extensions
-
1a. The command format is incorrect.
-
1a1. LetsGetHired notifies the user of the error.
Use case resumes from Step 1.
-
UC6: Edit the details of an application
MSS
-
User requests to list all internship applications (UC2).
-
User provides new information to edit the chosen application.
-
LetsGetHired edits the application and displays it.
Use case ends.
Extensions
-
1a. The list is empty
Use case ends.
-
2a. The command format is incorrect.
-
2a1. LetsGetHired notifies the user of the error.
Use case resumes from Step 2.
-
-
2b. The index of internship application entered does not exist
-
2b1. LetsGetHired shows an error message.
Use case ends.
-
UC7: Add a note to an application
MSS
-
User requests to list all internship applications (UC2).
-
User provides note to add to specific application.
-
LetsGetHired adds the note to the application and displays the application.
Use case ends.
Extensions
-
1a. The list is empty.
Use case ends.
-
2a. The command format is incorrect.
-
2a1. LetsGetHired notifies the user of the error.
Use case resumes from Step 2.
-
-
2b. The index of internship application entered does not exist.
-
2b1. LetsGetHired shows an error message.
Use case ends.
-
UC8: Delete a note on an application
MSS
-
User requests to view a specific application (UC3).
-
User requests to delete a specific note from the application.
-
LetsGetHired deletes the note from the application and displays the updated application.
Use case ends.
Extensions
-
1a. The application has no notes.
Use case ends.
-
2a. The command format is incorrect.
-
2a1. LetsGetHired notifies the user of the error.
Use case resumes from Step 2.
-
-
2b. The index of internship application entered does not exist.
-
2b1. LetsGetHired shows an error message.
Use case ends.
-
-
2c. The given note index is invalid.
-
2c1. LetsGetHired shows an error message.
Use case resumes from step 2.
-
UC9: Sort Applications
MSS
-
User requests to sort the applications by provided category and order.
-
LetsGetHired sorts and displays the sorted applications.
Use case ends.
Extensions
-
1a. Provided category or order is invalid
-
1a1 LetsGetHired shows an error message and shows the valid categories and orders to choose from.
Use case ends.
-
- Should work on any mainstream OS as long as it has Java
11
or above installed. - The system should not require an internet connection to operate.
- Should be able to hold up to 1000 internships without noticeable sluggishness in performance for typical usage.
- The system should respond to user interactions within 1 second for normal operations (e.g. adding an internship, searching for an internship) for a smooth user experience.
- 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's application info should be stored offline, and not uploaded to any form of cloud storage.
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
-
Type the following command in your terminal:
java -jar letsgethired.jar
Expected: Shows the GUI with a set of sample internship applications. The window size may not be optimal.
Saving window preferences
-
Resize the window to an optimum size. Move the window to a different location. Close the window.
-
Re-launch the application by typing the following command in your terminal:
java -jar letsgethired.jar
Expected: The most recent window size and location is retained.
-
Prerequisites: Launch the app
-
Test case:
add n/Optiver r/Quantitative Trader c/Summer 2024
Expected: TheInternApplication
is added to the list. The added internship application is displayed in the select view. -
Test case:
add n/Jump Trading r/Quantitative Researcher c/Summer 2024 s/Deleted
Expected: NoInternApplication
is added to the list. Error message is displayed. -
Other incorrect
add
commands to try:add
,add ...
, where (...
are parameters with invalid values or missing required parameters)
Expected: Similar to previous.
-
Prerequisites: List all
InternApplication
s using thelist
command. MultipleInternApplication
s in the list. -
Test case:
edit 1 r/Software Engineer c/Summer 2024
Expected: The firstInternApplication
in the list is edited and theRole
is set toSoftware Engineer
and theCycle
is set toSummer 2024
. The edited internship application is displayed in the select view. -
Test case:
edit 0
Expected: NoInternApplication
is edited. Error message is displayed. -
Test case:
edit s/Deleted
Expected: NoInternApplication
is edited. Error message is displayed. -
Other incorrect
edit
commands to try:edit
,edit ...
,edit x
where (...
are parameters with invalid values andx
is larger than the list size)
Expected: Similar to previous.
-
Prerequisites: List all
InternApplication
s using thelist
command. MultipleInternApplication
s in the list. -
Test case:
note 1 i/Prepare for behavioural questions
Expected: A newNote
is added to the firstInternApplication
in the list. The internship application with the new note is displayed in the select view. -
Test case:
note 0 i/Prepare for machine learning questions
Expected: NoNote
is added to anyInternApplication
. Error message is displayed. -
Other incorrect
note
commands to try:note
,note x i/Prepare for behavioural questions
where (x
is larger than the list size)
Expected: Similar to previous.
-
Prerequisites: List all
InternApplication
s using thelist
command. MultipleInternApplication
s in the list. -
Test case:
note 1 o/1
Expected: The firstNote
from the firstInternApplication
in the list is deleted. The internship application with the deleted note is displayed in the select view. -
Test case:
note 0 o/1
Expected: NoNote
is deleted from anyInternApplication
. Error message is displayed. -
Test case:
note 1 o/0
Expected: NoNote
is deleted from anyInternApplication
. Error message is displayed. -
Other incorrect
note
commands to try:note
,note x o/1
,note 1 o/y
where (y
is larger than the number of notes in the firstInternApplication
in the list andx
is larger than the list size)
Expected: Similar to previous.
-
Prerequisites: List all
InternApplication
s using thelist
command. MultipleInternApplication
s in the list. -
Test case:
view 1
Expected: The firstInternApplication
in the list is displayed in the select view. -
Test case:
view 0
Expected: NoInternApplication
is displayed in the select view. Error message is displayed. -
Other incorrect
view
commands to try:view
,view x
(wherex
is larger than the list size)
Expected: Similar to previous.
-
Prerequisites: List all
InternApplication
s using thelist
command. MultipleInternApplication
s in the list. -
Test case:
find n/Jane Street c/Summer 2024 r/Software Engineer
Expected: All theInternApplication
s with either theCompany
name containingJane Street
andRole
containingSoftware Engineer
andCycle
containingSummer 2024
are displayed in the list view. -
Test case:
find
Expected: AllInternApplication
s are displayed in the list view. Error message is displayed.
-
Prerequisites: List all
InternApplication
s using thelist
command. MultipleInternApplication
s in the list. -
Test case:
sort n/a
Expected: All theInternApplication
s are displayed in the list view in sorted order byCompany
in ascending order. -
Test case:
sort s/d
Expected: All theInternApplication
s are displayed in the list view in sorted order byStatus
in descending order. -
Test case:
sort c/n
Expected: All theInternApplication
s are displayed in the list view. Error message is displayed. -
Other incorrect
sort
commands to try:sort
,sort ...
, where (...
are parameters with invalid values or more than one parameter)
Expected: Similar to previous.
-
Prerequisites: List all
InternApplication
s using thelist
command. MultipleInternApplication
s in the list. -
Test case:
delete 1
Expected: FirstInternApplication
is deleted from the list. Details of the deleted internship application shown in the status message. -
Test case:
delete 0
Expected: NoInternApplication
is deleted. Error message is displayed. -
Other incorrect
delete
commands to try:delete
,delete x
(wherex
is larger than the list size)
Expected: Similar to previous.
-
Prerequisites: Execute some command that modifies any
InternApplication
-add
,edit
,note
ordelete
, or modifies the list of internship applications -find
. -
Test case:
undo
Expected: Undoes the modification to theInternApplication
and the list of internship applications. -
Test case:
undo
, without any command being executed before theundo
Expected: No change to anyInternApplication
or the list of internship applications.
LetsGetHired saves your data locally after any command you execute.
Dealing with a missing data folder
-
Prerequisites: On app launch, if no data folder is detected within the same directory as the jar file.
-
Test case: Run any command and a new data folder containing a
letsgethired.json
file will be generated. -
Test case: If you do not run any command and quit the app, no data folder or file will be generated.
Dealing with a missing data file (letsgethired.json
)
-
Prerequisites: On app launch, if there is an empty data folder within the same directory as the jar file.
-
Test case: Run any command and a
letsgethired.json
file will be generated within the data folder. -
Test case: If you do not run any command and quit the app, no data file will be generated.
Dealing with a corrupted data file (letsgethired.json
)
-
Prerequisites: On app launch, if the
letsgethired.json
file in the data folder within the same directory as the jar file is corrupted. -
Test case: Run any command and the contents of the
letsgethired.json
file will be overwritten to a json file with no data.
In crafting LetsGetHired, a lot of thought was put into delivering a user-centric application that simplifies internship application tracking. We prioritized user experience with a revamped GUI and enhanced internship application organization through features like sort and find. We also provided users the flexibility to attach helpful information to entries, through the introduction of notes.
Designing organizational features in LetsGetHired, such as the Find and Sort commands, presented a notable advancement beyond the capabilities of AB3. While AB3 exclusively features a basic Find function that searches for entries based on matching keywords to names in the address book, in LetsGetHired, the Find command empowers users to conduct searches across various fields associated with internship applications simultaneously. Additionally, we took it one step further, enhancing the Find command in LetsGetHired to accommodate partial matches, giving our users more flexibility and freedom.
The introduction of the Sort command in LetsGetHired stands as another milestone in organizational design. LetsGetHired enables users to sort their internship applications in ascending or descending order based on any field. This functionality provides users with the ability to customize the organization of their application.
We undertook a substantial overhaul of the GUI in LetsGetHired, distinguishing it from the interface of AB3. LetsGetHired embraces a visually appealing GUI that facilitates in-depth exploration of application details through a select view. This transition required intricate design decisions to seamlessly integrate additional functionalities for detailed application viewing and adding of notes that demand larger screen real estate. In our commitment to user experience, we also interactivity with the GUI through an ability to view applications from the list view by clicking on the corresponding card.
Notes play an integral part in LetsGetHired, allowing users to add many pieces of information associated with an internship application. We deliberated on how notes should be created, viewed, deleted and integrated into LetsGetHired's existing and future functionalities, such as searching for an application by notes. This addition allowed us to introduce another dimension to LetsGetHired, adding depth and nuance to the application management experience.
Current Implementation: In the current version of our application, when a
user inputs a command with missing compulsory fields, the application responds
with a generic error message: Invalid Command Format!
. This is followed by the
correct usage of the command. While this approach informs the user of an error,
it lacks specificity in identifying the exact cause of the error, particularly
which compulsory field(s) are missing.
Planned Enhancement: We aim to improve user experience and error feedback by implementing a more detailed error reporting system. This enhancement will enable the application to not only detect that an invalid command has been entered but also identify and highlight the specific missing compulsory fields.
Proposed Changes:
-
Error Detection Algorithm: Modify the command parsing algorithm to include checks for each compulsory field. This will enable the system to pinpoint which field(s) the user failed to provide.
-
User Feedback Enhancement: When a command is identified as invalid due to missing fields, the application will generate a tailored error message. This message will specifically list the missing compulsory field(s), guiding the user to correct the specific mistake. For example, if a user forgets to input the
CYCLE
field in a command, the error message would be:Invalid Command Format! Missing field: CYCLE
. This message will be followed by the correct usage of the command.
Expected Benefits:
- Improved User Experience: By providing specific feedback on missing fields, users can more easily understand and rectify their mistakes, leading to a smoother interaction with the application.
- Increased Efficiency: This enhancement reduces the time and effort users spend in deciphering generic error messages and figuring out what went wrong.
- Enhanced Usability: Tailored error messages make the application more user-friendly, especially for new users who are still familiarizing themselves with the command syntax.
Current Implementation: In the current version of our application, when a
user inputs an unrecognized command, the system simply displays a
message: Unknown Command
. This response, while accurate, does not assist the
user in understanding why the command was unrecognized or how to correct it.
Planned Enhancement: We plan to introduce a more intuitive error handling mechanism for unknown commands, akin to the approach used in Git. This enhancement will involve suggesting commands similar to the user's input, which can be particularly useful in cases where the user has made a typing error.
Proposed Changes:
-
Command Suggestion Algorithm: Implement an algorithm that detects and suggests similar commands when an unknown command is entered. For example, if a user mistakenly types
ad
instead ofadd
, the system will suggest the correct command:Unknown Command: 'ad'. Did you mean 'add'?
. -
Synonym Recognition: Enhance the command parsing logic to recognize synonyms or commonly used alternatives for certain commands. For instance, if a user types
search
orfilter
instead offind
, the application could respond with a suggestion:Unknown Command: 'search'. Do you mean 'find'?
.
Expected Benefits:
- Enhanced User Assistance: By providing relevant command suggestions, users can quickly rectify typing errors or understand alternative terminology used within the application.
- Increased Efficiency: This enhancement reduces the time and effort users spend in deciphering generic error messages and figuring out what went wrong.
- Improved Usability for New Users: New users, unfamiliar with specific command syntax, will find the application more approachable with these intuitive prompts and suggestions.
Current Implementation: In the current version of our application, when a new internship application is added to our list, it is placed at the bottom. This positioning often renders the new entry outside the user's current view, requiring them to manually scroll down to locate the latest addition.
Planned Enhancement: We are planning to enhance the user experience by changing how newly added internship applications are displayed. The key improvement will be automatically scrolling the list to bring the newly added application into view immediately. Additionally, we are considering placing new entries at the top of the list rather than at the bottom.
Proposed Changes:
-
Automatic Scrolling: Modify the list view functionality to automatically scroll to the position of the newly added internship application. This ensures that the latest entry is immediately visible to the user without requiring manual navigation.
-
List Ordering Modification: Change the default order of the list to display new applications at the top. This approach aligns with common user expectations, where the most recent items are readily accessible.
Expected Benefits:
- Improved Visibility of New Applications: By immediately showcasing new applications, users can immediately see and interact with the most recent entries, improving workflow efficiency.
- Adaptation to User Preferences: Adjusting the list order to display new items at the top aligns with common user behavior and expectations, thereby improving usability.
- Enhanced User Experience: Automatically scrolling to new entries saves time and improves the overall user experience, making the application more intuitive and efficient.
Current Implementation: In the current version of our application, the
application only allows sorting of internship applications by
ONE field at a time using parameters such as c/a
for sorting by cycles in
ascending order or n/d
for sorting by company names in descending order.
Planned Enhancement: Enable sorting by multiple fields to enhance the flexibility of data organization. This improvement addresses the limitation of the current sorting functionality, allowing users to sort data by more than one criterion at a time. For example, users should be able to sort first by cycle in ascending order and then by company name in ascending order using the following command:
sort c/a n/a
This means that if 2 internship applications have the same cycle, for example
Summer 2024
, they will be sorted by company name in ascending order
(Apple
before Google
).
Proposed Changes:
Note: The InternApplicationComparator
class already contains a
createCompositeComparator()
method that can be used to combine multiple
InternApplication
comparators into a single comparator.
- Update
ArgumentTokenizer
to parse the order of prefixes. - Update
SortCommandParser
to allow for multiple sorting criteria.
Expected Benefits:
- Users can organise internship applications more precisely by specifying multiple sorting criteria.
- Enhanced user experience with the ability to customise internship application sorting based on specific needs.
- Improved usability for users who require complex sorting for internship application analysis.
Current Implementation: In the current version of our application, users are able to undo changes made using the Undo command. This allows users to revert formerly destructive commands, for a more forgiving and beginner-friendly experience. We see a redo function as a natural progression from undo, where users will be given greater agency in managing their internship applications.
Planned Enhancement: We plan to implement a Redo command that will allow users to redo commands that were undone. This change empowers users to have greater flexibility in managing their internship applications by enabling users to toggle between app states with ease.
Proposed Changes:
-
Undone States History: Store undone states in a separate history, similar to how past states are stored currently.
-
Redo Command : Introduce a new command : Redo, that will redo a command that was previously undone or notify the user that there are no commands to redo.
Expected Benefits:
- Improved Beginner Experience: By providing the option to redo, new users can have an easier time exploring commands and undoing and redoing changes when necessary.
- Increased Efficiency: This enhancement allows users to manage their applications more efficiently and save time in the event of an unintentional undos.
Current Implementation: In the current version of our application, when a user sorts by a particular field, there will be no way for the user to revert to the initial sort order. The only way to revert to the default sort order is by restarting the app.
Planned Enhancement: We plan to introduce a way for users to revert the list to its default sort order. This enhancement may be particularly useful for users who which to see the list sorted in the order they added the intern application entries in.
Proposed Changes:
-
Add new
Id
field intoInternApplication
class: The idea behind this change is to mimic the identifier key that is present in most SQL databases. This way, we will be able to seamlessly sort the InternApplications according to their ID which is the order in which they are added. -
New
Id
Class: TheId
class will encapsulate the identifier key integer for the correspondingInternApplication
. The class will also have a static counter variable to count the total number of intern applications that is added while the app is running. This helps to ensure that none of theInternApplication
objects has duplicate key values.Id#generateUseableId()
is a factory method responsible for generating an ID key that is not used by any intern applications yet. It is also worth noting that the Id value will not be passed into the serialised JSON format as we wish for the keys to be dynamically assigned at every run of the application. This way, it is unlikely for integer overflow in theId
value. -
SortCommand: The
SortCommand
class will be changed to behave differently whenever the user enterssort default
into the CommandBox. TheSortCommandParser
will see that none of the prefixes are present in the input. After which, it will check the preamble. If the preamble contains the string "default", the SortCommand will execute the sort logic to sort by theId
class.
Expected Benefits:
- Enhanced User Experience: Users do not have to restart the application just to see their list in the default sorted order.
- Improved Usability for New Users: By providing a way for users to revert their sorted list to the default, it allows them to easily look at the latest entries that they have added.
Current Implementation: The current version of our application does not support the feature of editing a particular note in the note list. The only operations we offer for note management is adding and deleting notes as those two are most crucial.
Planned Enhancement: We plan to make further enhancements to facilitate editing of notes. This feature will be useful for users as it saves them the hassle of deleting a note and re-adding it to keep their notes updated.
Proposed Changes:
-
New
NoteEditCommand
Class: Create a new class calledNoteEditCommand
. Similar to theNoteInsertCommand
andNoteDeleteCommand
, theNoteEditCommand
will inherit from theNoteCommand
class and behave in accordance to edit a particular note. The class will require 3 parameters in the constructor: The index of the application, the index of the note, and the String input note that the user wants to store. -
Additional function in InternApplication Class: An additional function is required to represent the behavior that we want in note editing. Namely,
InternApplication#editNote()
will take in 2 parameters: The index of the note, and the string of input note to be stored. The function makes a copy of its immutable list of notes into a mutable one and swaps theNote
in the specified index input with a newly constructedNote
from the input string. The function then returns a newInternApplication
with the updated notes. -
NoteCommandParser Changes: The current version of our app throws an exception when both
PREFIX_NOTE_DELETE
andPREFIX_NOTE_INSERT
is detected. The proposed change to make way for note editing is to remove the thrown exception line in place of aNoteEditCommand
object.
Expected Benefits:
- Faster note management for Users: Editing notes will be reduced from a two step process (Note deleting and then Note adding) into a one step process (Note editing)
Current Implementation: The current implementation of sorting by status results in a behavior where the statuses are sorted in lexicographical order.
Planned Enhancement: We plan to change the way Status is sorted to make the sort logic more meaningful. (e.g. Rejected and Accepted internships are lower than all the other statuses because they are "completed" applications with no further follow-ups)
Proposed Changes:
-
Status
compareTo
Method: Rather than comparing the 2 strings lexicographically, we compare the enum representation of the strings from both objects. -
Status
StatusEnum
nested class: We propose to rearrange the enums such that the statuses reflect the chronological order in an internship application process. The order of importance is as follows: Pending > Assessment > Interview > Offered > Accepted > Rejected
Expected Benefits:
- More meaningful sort: When
Status
is sorted, it will now show the more urgent applications to be followed up on to the user either on the top or at the bottom depending on whether the user sorted it in ascending or descending order.