Special thanks to the authors of addressbook-level3 for their Developer Guide, used here as a reference for the following DG:
Third party libraries used:
Caution: Follow the steps in the following guide precisely. Things will not work out if you deviate in some steps.
Note:
execute(InternshipList internships, UserProfile user)
will be referenced asexecute()
throughout the document for brevity. The sequence diagrams will still show the full method signature.
First, fork this repo, and clone the fork into your computer.
If you plan to use Intellij IDEA (highly recommended):
Note: Importing a Gradle project is slightly different from importing a normal Java project.
seedu.internsprint.InternSprint
and try a few commands.src/test
directory to ensure everything is working as expected.Tip: The diagrams are created using drawio. Refer to their website for more information. All our
drawio
source files are accessible through the link here
The Architecture Diagram above shows the high-level implementation of the InternSprint application.
Given below is a quick overview of our main components and their interactions.
Main Components:
InternSprint
class is responsible for the launch and shutdown of the entire program.
StorageManager
, InternshipList
, UserProfile
, and ProjectList
components.The bulk of the application logic is done by the following 4 components:
Ui
- Handles user input and output.Logic
- Parses user input and executes commands.Model
- Stores and manages the data.Storage
- Reads and writes data to and from the disk.How the components interact:
The Sequence Diagram demonstrating the interaction between these 4 components is described below under the Ui
component. The Ui
component can be accessed here.
Each of the 4 components has its API defined either in an interface
or in an abstract
class with the same name as the package.
Ui
component is a single class.Logic
component consists of two main parts: the Parser
and the Command
packages.
command
package defines its API in the abstract Command.java
class.parser
package is made up of two single classes: CommandParser.java
and DateTimeParser.java
.Model
component consists of two packages: internship
and userprofile
.
internship
package defines its API in the abstract Internship.java
class.interview
package that contains the Interview.java
and InterviewEntry.java
classes.userprofile
package is a single class.userprofile
package consists project
package whose API is defined in the abstract Project.java
class.Storage
class defines its API in the Storage.java
interface.The text-based UI component for this app is responsible for handling user input and output. Stored under the util
package, the UI acts as the front-facing component for the application architecture.
The sequence diagram below shows how the components interact with each other highlighting the role and placement of
the UI component in our application as it:
References to the UI component exists only in the InternSprint public class itself to reduce tight coupling and UI only deals in formatting and returning Strings from and to the user such that the Logic component does not have to print to terminal directly and can be isolated to parsing and command execution, ensuring separation of concerns.
The below class diagram is a brief overview of the static and public methods contained in UI, and showcases class
dependencies. This UML diagram omits certain class level members and attribute for Internship class among others to
ensure clarity and conciseness. Essentially, UI is only referenced in one method of the InternSprint class and only holds a reference
to the Internship class, illustrating avoidance of tight coupling and singularity of purpose for UI (no overlap between
logic and UI).
The Logic
component consists of two main parts: the Parser
and the Command
classes.
Parser: Parser is made up of two classes: CommandParser
and DateTimeParser
.
CommandParser
class takes a single line of user input and splits it into a command word and key value pairs.
*Command
object (e.g., AddInternshipCommand
, DeleteCommand
, ListCommand
).HashMap<String, String>
of the Command
object. The key value pairs are
validated only during command execution in isValidParameters()
method.Natty
and PrettyTime
libraries to parse and format
date and time strings respectively.Command: The Command
class is an abstract class that represents a command that the user can execute.
It provides an additional layer of abstraction between the user input and the actual execution of the command,
achieving the SoC (Separation of Concerns) design principle.
The abstract Command
class has the following abstract methods:
isValidParameters()
: Validates the parameters of the command. The parameters are set by CommandParser
class while
parsing the user input.execute()
: Executes the command.These methods override the abstract methods of the Command
class through polymorphism.
Here is a partial class diagram of related classes in the Logic component:
DateTimeParser
class is not shown in the diagram, as it is used by the model component to parse date and time strings.
The sequence diagram below illustrates the interactions within the Logic
component when execute()
method is called
for user input delete /index 1
.
Note: The purpose of the sequence diagram above is solely to illustrate the interactions between the classes in logic component. Implementation details such as how the input is parsed, execution of command in
DeleteCommand
and steps in deleting an internship inModel
are omitted for clarity. You can take a look at the implementation section of this Developer Guide for more details.
How the Logic
Component works:
InternSprint
class calls the parseCommand(String userInput)
method from
CommandParser
class to parse the input.CommandParser
class creates a Command
object (an object of
one of its subclasses e.g., DeleteCommand
).Model
when it is executed through the execute()
method.InternSprint
class as a CommandResult
object.The Model component is responsible for storing, managing and providing access to all the data used by the InternSprint . It represents the internal state of the application and is updated based on commands entered by the user.
UserProfile
model
├── internship
│ ├── Interview
│ │ ├── Interview.java # Represents a single interview (including optional rounds)
│ │ ├── InterviewEntry.java # Wrapper class pairing an Interview with its Internship
│ ├── GeneralInternship.java # Internship subclass for general roles
│ ├── HardwareInternship.java # Internship subclass for hardware roles
│ ├── SoftwareInternship.java # Internship subclass for software roles
│ ├── Internship.java # Abstract class defining an internship's structure
│ └── InternshipList.java # Contains and manages the internship collection
└── userprofile
└── Project
│ └── GeneralProject.java # Project subclass for general projects
│ └── HardwareProject.java # Project subclass for hardware projects
│ └── SoftwareProject.java # Project subclass for software projects
│ └── ProjectList.java # Contains and manages the projects
│ └── Project.java # Project class defiing a project's structure
└── UserProfile.java # Stores user preferences (companies, roles, goals, etc.)
Class | Role |
---|---|
Internship |
Abstract base class for internships |
General/Software/HardwareInternship |
Specific implementations depending on type |
InternshipList |
Stores internships in a HashMap by category (software , etc.) |
Interview |
Represents one interview round, with optional next rounds |
InterviewEntry |
A wrapper for pairing an Interview with its parent Internship |
UserProfile |
Stores user preferences for use across the application |
Projects |
Abstract base class for projects |
General/Software/HardwareProjects |
Specific implementations depending on type |
ProjectList |
Stores projects in a Hashmap by category |
The overall system model has been divided into two separate UML diagrams for ease of understanding.
Internships and Interview Diagram
User Profile and Projects Diagram
The Storage component is responsible for managing saving and loading in the application. It ensures that user data, such as internships, projects, profiles, and interviews, are stored and retrieved efficiently.
InternshipStorageHandler
, InterviewStorageHandler
, ProjecttorageHandler
and ProfileStorageHandler
to manage the saving and loading of different types of data.Here is a class diagram of related classes in the Storage component:
How the Storage
Component works:
Command
class interacts with the InternshipList
.InternshipList
then calls the saveInternships()
method, which delegates the saving process
to the StorageManager
.StorageManager
calls the appropriate storage handler, such as InternshipStorageHandler
,
to write the updated data to a file.Class | Role |
---|---|
Storage |
Abstract base class for storage related operations |
Storage Manager |
Manages saving/loading processes for the different storage handlers |
InternshipStorageHandler |
Handles saving and loading of internship related data |
InterviewStorageHandler |
Handles data storage for interviews of internships |
ProfileStorageHandler |
Handles data storage for the user’s profile |
ProjectStorageHandler |
Handles saving and loading of project related data |
This section describes some noteworthy details on how certain features are implemented.
Overview:
This command allows the user to add a new internship to their list of internships.
The new internship is immediately added to the internships.txt
file at ../data/internships.txt
.
How the feature is implemented:
AddInternshipCommand
class is an abstract class that extends from another the abstract class Command
.general
, software
or hardware
in the input.
Each type of internship has a separate class that extends the AddCommand
class,
AddGeneralInternshipCommand
, AddSoftwareInternshipCommand
, and AddHardwareInternshipCommand
.isValidParameters()
and execute()
methods to validate the parameters of the command, depending on the type of internship.execute()
method adds the new internship to the list of internships
stored in InternshipList
which it obtains as a parameter.
InternshipList
class stores the list of internships as a HashMap. Each type of Add*InternshipCommand
will insert
the internship into the correct list.Why is it implemented this way:
Alternatives Considered:
AddCommand
class and use a switch statement to determine the type of internship.
AddCommand
class and store the type of internship as a field in the Internship
.
Sequence Diagram:
Below is the simplified sequence diagram for adding a new software internship. A similar sequence is followed for adding a general or hardware internship.
InternSprint.java
obtains the correct *Command
object from the CommandParser
class and calls the
execute()
method of that *Command
object.execute()
method first checks the validity of the provided parameters using the isValidParameters()
method of
the same *Command
object. As mentioned above, this method is overridden in each subclass to validate the parameters
according to the type of internship.
CommandResult
with the correct
usage message is returned to the user. The isSuccessful
field of the CommandResult
object is set to false
.SoftwareInternship
) is created.
CommandResult
with appropriate error message is returned.internships.txt
file,
a CommandResult
is returned. The reference frame for saving internships is omitted in the diagram to focus on the
details of adding a new internship.Overview:
This command allows the user to edit the parameters of their prexisting internship in their list. This update
is immediately added to the internships.txt
file at ../data/internships.txt
.
How the feature is implemented:
EditCommand
class is an abstract class extends from the abstract class Command
.general
, software
or
hardware
internships and additional extended parameters through the use of flags. All parameters are optional
and can be used on an as-needed basis./index
is required to be entered by the user, and checked for in isValidParameters()
.
This method also checks if all flags entered by user are predefined in POSSIBLE_PARAMETERS
set.execute()
method calls editParametersForFoundInternships()
to validates the \tech
and \hardtech
parameters of the command, depending on the type of internship and sets the edited parameters accordingly
parameters
is stored as key-value pairs(hash-map) within Command super class.Why is it implemented this way:
edit /index
format here, instead of edit general /index
we aimed to make the user experience
for simpler and more intuitive to understand. It may become tedious for the user to continue to retype lengthy
internship type every time, especially since the list
command enumerates all internships as one list cohesively.
This approach to improve simplicity and cohesion of updating internship list is maintained in other commands such as
delete
./status
or /desc
for status and description respectively.Alternatives Considered:
EditCommand
class and allow user to edit the extended set of
optional parameters using flags
Sequence Diagram:
Below is the sequence diagram for editing internship. Note this is an overview sequence diagram in which method flow has been simplified using reference frames, expanded on below to help aid in clarity.
InternSprint.java
obtains the correct EditCommand
object from the CommandParser
class and calls the
execute()
method of that EditCommand
object.execute()
method first checks the validity of the provided parameters using the isValidParameters()
method of
the same *Command
object. As mentioned above, this method is overridden in each subclass to validate the parameters
required for that command. For the EditCommand
this involves a check that flags are present in predefined set and index
is present.CommandResult
with the correct
usage message is returned to the user. The isSuccessful
field of the CommandResult
object is set to false
.internships.txt
file,
a CommandResult
is returned. The reference frame for saving internships is similar to the reference frame
under DeleteCommand
.Below are the expanded reference frames for successful and unsuccessful CommandResults returned by execute() method.
Here the opt frame is utilized and not the alt frame since this better reflects the way the code flow works.
Print calls, assert statements, logging, and other non-essential calls are omitted in the diagram for clarity. For full clarity, note below is a comprehensive sequence diagram, combining all reference frames and expanding logic behind duplicate-checking for example.
Note this is only added for completeness for this one Command class, and only to supplement an additional level of detail to above overview diagram (which should be sufficient for understanding). Such an expanded view will be isolated to this one command but execution logic resembles other Commands, hence can refer to this diagram for thoroughness for all such commands.
Overview:
This command allows the user to delete an internship from the list of internships. The deleted internship is
immediately removed from the internships.txt
file at ../data/internships.txt
.
How the feature is implemented:
DeleteCommand
class is an abstract class extends from the abstract class Command
./index
flag, which is a mandatory parameter to indicate which internship
should be deleted.isValidParameters()
method ensures that the required /index
flag is provided by the user before proceeding
with execution.execute()
method retrieves the internship entry from the internship list based on the provided index.
It then removes the internship entry from the list and attempts to save the updated internship list.
Feedback messages indicating success or failure, including errors such as missing or invalid indices are returned.
index parameter
is stored as a key-value pair in the parameters
Hashmap.Why is it implemented this way:
delete /index
format here, instead of delete general /index
we aimed to make the user
experience for simpler and more intuitive to understand. It may become tedious for the user to continue to retype
lengthy internship type every time, especially since the list
command enumerates all internships as
one list cohesively. This approach to improve simplicity and cohesion of updating internship list
is maintained in other commands such as edit
.Alternatives Considered:
DeleteCommand
class and allow user to delete an internship from
the internship list.
Sequence Diagram:
Below is the sequence diagram for deleting internship. This is an overview sequence diagram in which method flow has been simplified using reference frames, expanded on below to help aid in clarity.
InternSprint.java
obtains the correct DeleteCommand
object from the CommandParser
class and calls the
execute()
method of that DeleteCommand
object.execute()
method first checks the validity of the provided parameter using the isValidParameters()
method of
the same *Command
object. For the DeleteCommand
this methods check that if the index is valid and not missing.CommandResult
with the correct
usage message is returned to the user. The isSuccessful
field of the CommandResult
object is set to false
.internships.txt
file,
a CommandResult
is returned.Below are the expanded reference frames for successful and unsuccessful CommandResults returned by execute() method. The reference frame for saving internships can also be seen below.
Overview: This command allows the user to list all internships they have added. Data stored in internships.txt file at ../data/internships is retrieved to display the list of internships.
How the feature is implemented:
listCommand
class is a class that extends from the abstract class Command
.isValidParameters()
method ensures that no extra parameters is provided by the user before proceeding
with execution.execute()
method receives an InternshipList(which stores internships categorized by type in a HashMap) and a UserProfile.
The method then iterates over each internship category (software, hardware, general), retrieves the corresponding list from the HashMap, and constructs a formatted output. Each internship is numbered sequentially. If no internships are found, it returns a CommandResult with a specific “No internships found” message.Why is it implemented this way:
Alternatives Considered:
Sequence Diagrams
Below are the sequence diagrams for listing all internships.
The execute() method of the ListCommand class is called
Execute() method checks the validity of the parameters using the isValidParameters() method.
If extra parameters are entered(as depicted in the sequence diagram below), it will be invalid and hence, a commandResult with the correct usage message is returned to the user.
If the parameters are valid (as depicted in the sequence diagram below), then the internships in the internship list are iterated through by catergory (software, hardware, general) and added to a arrayList as formatted strings.
A command result containing these internships is then returned.
*Print calls, assert statements, logging, and other non-essential calls are omitted in the diagram for clarity.
Overview:
This command allows the user to update their own user profile with their personal details to aid in
applications and CV creation/updating. The saved data is immediately stored in the userprofile.txt
file
at ../data/userprofile.txt
.
How the feature is implemented:
UserProfileCommand
class extends from the abstract class Command
./name
or /mgoals
to their preference.isValidParameters()
method ensures that the all provided flags match with predefined set of OPTIONAL_PARAMETERS
execute()
method updates the associated parameters in the UserProfile user
passed in as an argument to this method.
It then attempts to save the updated user profile.
Feedback messages indicating success or failure, including errors such as invalid indices are returned.Why is it implemented this way:
edit
command.Overview:
This command allows the user to add a new project to their list of projects stored under their user profile.
The new project is immediately added to the userprofile.txt
file at ../data/userprofile.txt
.
How the feature is implemented:
ProjectCommand
class is an abstract class that extends from another the abstract class Command
.general
, software
or hardware
in the input.
Each type of internship has a separate class that extends the ProjectCommand
class,
ProjectGeneralCommand
, ProjectSoftwareCommand
, and ProjectHardwareCommand
.isValidParameters()
and execute()
methods to validate the parameters of the command, depending on the type of internship.execute()
method adds the new project to the list of projects
stored in UserProfile
which it obtains as a parameter.
ProjectList
class stores the list of internships as a HashMap. Each type of Project*TypeCommand
will insert
the project into the correct list.Why is it implemented this way:
AddInternshipCommand
structure, largely with only one exception -
all flags the user can enter are mandatory (to specify a project all essential information is required as per our design
requirements).Sequence Diagram:
Keeping in mind the similarity to the AddInternshipCommand
structure, to aid conciseness, the sequence diagrams for that
class can be referenced to understand execution logic for these commands. However, to help understand inheritance for this
command and how the three different project type classes extend from their superclasses, below is a class diagram for the same:
java.util.logging
package for logging.InternSprintLogger.java
class is responsible for setting up the logger and creating a singleton logger.InternSprintLogger.getLogger()
..log
file which is found at ../log/InternSprint.log
.This product is designed for NUS Computer Engineering undergraduates, especially students applying for internships or jobs for the first time. It caters to those who prefer a unified CLI-based platform over a GUI, streamlining job application processes for tech-savvy users who value automation and command-line control.
The product helps CEG students effortlessly track and maintain job applications at different stages using short commands, all within a unified CLI. Stay organized, save time, and streamline the application process with automation, ensuring a seamless and efficient job hunt.
Version | As a … | I want to … | So that I can … |
---|---|---|---|
v1.0 | New user | View the user command guide easily | learn more about the product as and when needed, and know how to work with the software |
v1.0 | Normal user | Add the job role, company and status of the job I have applied for | easily identify where I have applied |
v1.0 | Normal user | List all the jobs I have applied for | track my progress and have a masterlist reference of my applications |
v1.0 | Normal user | Delete certain job applications | only see relevant data in the list |
v1.0 | Normal user | View the detailed job description | have a better understanding of the role I am applying for |
v1.0 | Normal user | Save the previously stored data about the jobs I have applied to | reopen the application and have my old data restored so I don’t have to reenter everything repeatedly |
v2.0 | New user | Enter my goals for the year, as in what would be my ideal role, in which companies and what pay or time ranges | have a clear picture to refer back to when making applications |
v2.0 | New user | Enter in my personal details like name, age major and preferences | have a personal touch in my software |
v2.0 | New user | Have some pictorial elements and visual representations of data | be engaged and not have to deal with too text-heavy or boring visuals |
v2.0 | New user | Add in my skills in different tech stacks and different soft skills | keep my skill set updated and use it as a reference for different applications |
v2.0 | Normal user | Note important details about the job interviews | well prepare for interviews |
v2.0 | Normal user | Mark jobs based on different stages on the job portal | be aware of which application to portal to check for updates, and which stage they are in |
v2.0 | Normal user | View HR details and contact number for the interviews | be aware of the point of contact for various applications |
v2.0 | Normal user | Record interview dates and time | better track interviews |
Note: These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
Follow the instructions given in our User Guide Quick Start to set up the application.
Expected: A welcome message and a prompt for user input.
For more depth and greater variety of test cases which fully explore our extended features we highly recommend you take a look at sample commands in our User Guide Feature List.
2.1 Initial State
Expected: A welcome message and a prompt for user input.
Test case: help
Expected: List of all possible commands user may enter should be displayed.
Test case: any non-command string
Expected: Error for an unrecognized command should appear.
2.2 Add a new internship
Test case: ` add general /c Google /r Human Resource /dept HR`
Expected: Adds a general category of internship in Google, for an HR role, in the HR department. (These are the most basic required parameters).
Test case: add software /c Google /r Software Engineer /tech Java, Python
Expected: Adds a software category of internship in Google, for a Software Engineer role, with tech stack of Java and Python. (These are the most basic required parameters).
Test case: add hardware /c Google /r Hardware Engineer /hardtech Arduino, Raspberry Pi
Expected: Adds a hardware category of internship in Google, for a Hardware Engineer role, with hardware tech stack of Arduino, Raspberry Pi. (These are the most basic required parameters).
Test case: add software /c IBM /r Data Analytics /tech Python, PowerBI /ex Good project showcase
Expected: Adds a software category of internship in IBM, for a Data Analytics role, with tech stack of Python, PowerBI and experience of good project showcases. (These are some extended parameters: more info on possible extended parameters in UG).
Note: you may extend this test case to other categories of internships, with more optional parameters.
Test case: add software /company Google /role Software Engineer
Expected: Should output an error message highlighting correct usage format as one of the basic required parameter /tech
is missing.
2.3 List all internships
Test case: list
Expected: Should list all internships organized by category. Should not show extended parameters like description
among others
(should just be the essential compulsory flag information).
Test case: list /index 1
Expected: Should output error highlighting correct usage of list command.
2.4 Delete an internship
Test case: delete
Expected: Should output error highlighting correct usage of delete command.
Test case: delete /index 1
Expected: Should correctly delete the internship in the list at index 1. You may list
all internships to confirm.
Test case: delete /index -1
Expected: Should output error highlighting invalid index.
2.5 Edit an internship
Test case: edit
Expected: Should output error highlighting correct usage of edit command.
Test case: edit /index 1 /c Java /desc Some description
Expected: Should correctly edit the internship in the list at index 1 to new company of Java.
This commmand is used to potentially explore adding more optional parameters if you forgot to add such parameters when creating
the internship. You may list
all internships to confirm. (Can check optional parameters in UG)
Test case: edit /c Google /desc Some description
Expected: Should output error highlighting invalid parameters.
2.6 Describe an internship
Test case: desc
Expected: Should output error highlighting correct usage of description command.
Test case: desc /index 1
Expected: Should correctly show description of the internship in the list at index 1.
Test case: desc /index -1
Expected: Should output error highlighting invalid index.
2.7 Find an internship
Test case: find
Expected: Should output error highlighting correct usage of find command.
Test case: find software /c Google
Expected: Should find all software internships added, under company name Google.
2.8 Adding interviews for internships
Test case: interview for
Expected: Should output error highlighting correct usage of add interview command.
Test case: interview for /index 1 /date 2025-01-01 /start 10:00 /end 14:00 /type technical round
Expected: Should correctly add a technical interview to the internship in the list at index 1 with above timings.
(You can potentially explore adding more optional parameter according to user guide. You may desc
this index internship to confirm it will not appear on listing.)
Test case: interview for /date 2025-01-01 /start 10:00 /end 14:00 /type technical round
Expected: Should output error highlighting no index/invalid parameters.
2.9 Sorting interviews for internships
Test case: sort interviews
Expected: Should sort all rounds of interviews added across multiple internships by date.
2.10 Adding/Viewing user profile information
Test case: my /name John Doe /ind Software /c Google /r Developer /mgoals 100 applications /ygoals 2 internships
Expected: Should correctly edit your user profile information according to above optional parameters. (Can check optional parameters in UG)
Test case: my
Expected: Since all parameters are optional to user, this command would successfully “edit” your user profile information according to above optional parameters. (Since no flag/optional parameters provided - no changes).
Test case: view user
Expected: Should display ASCII table to user of their profile information.
2.11 Adding/Viewing projects information
Test case: project general /n Team Project /r Tester /dept Software Engineering /obj For the PE /desc Worked at identifying feature flaws in app /dur May-August
Expected: Should correctly add a general project according to above compulsary parameters. (All parameters are mandatory since they all hold valuable information for user. You may extend this to project general and project hardware)
Test case: project software /n Team Project for CS2113 /r Unit Tester /pro Java, C++ /obj To get an A+ /desc Worked at identifying feature flaws in app /dur May-August
Expected: Should correctly add a software project according to above compulsory parameters.
Test case: project hardware /n Team Project for EE2026 /r Ui Developer /hcomp Basys Board/obj To get an A+ /desc Worked at creating pixel art for the UI /dur May-August
Expected: Should correctly add a hardware project according to above compulsory parameters.
Test case: view general
Expected: Should display ASCII table to user of their general projects.
Test case: view software
Expected: Should display ASCII table to user of their software projects.
Test case: view hardware
Expected: Should display ASCII table to user of their hardware projects.