Overview
Code Camp X (CCX) is for those who prefer to use a desktop app to manage the administrative tasks of running a coding camp. More importantly, CCX is optimized for those who prefer to work with a Command Line Interface (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, CCX can allow you to manage your camp’s administrative tasks faster than traditional GUI apps.
Summary of contributions
-
Major enhancement: Implemented Code Base for
Assignment
andProgress
-
What it does: This allows the user to add
Assignments
, with a name and deadline into the program. This also allowed for future extension where aProgress
object can be created to tie aStudent
andAssignment
together. -
Justification: This allows the users to track all the
Assignments
that is in the camp and will help in the implementation of tracking student progress in the subsequent extension. -
Highlights:
-
An in-depth analysis was required to determine if
Progress
was really required since it takes up a lot of time to successfully add anotherAddressBookGeneric
into the program, while taking into account the UI, the storage the commands, parsers, etc. However, the group decided that by splitting the logic ofAssignment
andProgress
, this will allow for better usability and testability. This was discussed within the Developer’s Guide as well. -
Another highlight is that I needed to implement a special form of ID, which I call
CompositeID
, just forProgress
object, sinceProgress
objects are identified by 2 IDs, studentID and assignmentID. Due to this, I needed to implement many methods inModelManager
in order to allow for model handling via thiscompositeID
.
-
-
-
Major enhancement: Implemented all Undo/Redo-able
Assign
&Un-assign
commands-
What it does: Allow user to assign/un-assign a
Student
/Teacher
/Assignment
to aCourse
and allow for them to undo/redo those commands -
Justification:
-
This allows the user add/remove a student/teacher/assignment to and from a course, allowing for them to better manage the their coding camp.
-
Should they have executed the command wrongly, they are able to undo or redo the commands they have just executed while returning to the correct previous state.
-
-
Highlights: This was one of the most challenging portions of the program due to these reasons:
-
It ties in many of the functionality and classes implemented. For example, the Assign/Un-assign commands need to make sure that entity linking is correct and that
Progress
objects added/removed correctly. As such, it is very dependent onEdgeManager
andProgressManager
for correct implementation. -
Many design alternatives were considered. Initially, the logic of assigning the edges was within the
Assign
/Un-assign
command itself, but I refactored everything out to theModelManager
and subsequentlyEdgeManager
to ensure that we better follow design principle ofSingle-Responsibility Principle
. -
Pre-processing of Command was vital since our program works via IDs. The method is crucial in making sure that the entities are in a
consistent state
before executing the assign command.Consistent state
means that either the two targeting objects have each other’s IDs or they do not. There should never be the case where one party has the other’s ID but not vice versa. -
Allow for Undo/Redo-ability into the correct state
-
Generally, when undo/redo is called, we just have to execute the opposite command.
-
However, we realized that it was not so trivial when we discovered a huge bug where undo-ing an un-assign command does not put back the specific
Progress
objects that were removed. -
As such, special considerations had to be implemented to ensure that these
Assign
/Un-assign
commands can work correctly. -
These considerations are included in the Developer’s Guide as well.
-
-
-
-
Minor enhancement: Implemented ProgressManager to allow for successful Creation/Deletion of `Progress objects
-
Minor enhancement: Implemented Assign/Un-assign portion of EdgeManager
-
Minor enhancement: Implemented Done/Undone Commands to mark Progress objects as
Done
/Undone
-
Code contributed: [Functional code]
-
Other contributions:
-
Project management:
-
Managed releases
v1.2
(1 release) on GitHub -
Managed Deadlines and Deliverable
-
-
Enhancements to existing features:
-
Allow for additions and removal of
Assigment
object entities
-
-
Documentation:
-
Complete documentation of
Model
,Entity Linking
andStudent Progress Management
in Developer’s Guide -
Added
Assignment
andDone
/Undone
Commands into User Guide
-
-
Community:
-
Contributions to the User Guide
Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users. |
Assignment
Add an assignment: add-assignment
Add a new assignment to the list of all assignments
Format: n/NAME dl/DEADLINE [t/TAG]…
Example:
* add-assignment n/Adversarial Search Assignment 2 dl/2020-12-30 t/AI t/Difficult
|
Delete an assignment: delete-assignment
Format: delete-assignment ID
Example:
-
delete-assignment 16100
Be reminded that when you delete an assignment, the assignment will be deleted from every course as well. |
Edit an assignment: edit-assignment
Format: edit-assignment ID [n/NAME] dl/DEADLINE t/TAGS]
Example:
-
edit-assignment 16100 n/Edit Python Assignment 1
Locating items by name: find-assignment
Finds assignments whose names contain any of the given keywords.
Format: find-assignment KEYWORD [MORE_KEYWORDS]…
Examples:
-
find-assignment java
Returnsjava
andJava Assignment
Mark a Student’s Assignment as Done
/Undone
Mark a student’s assignment as Done
.
Format: done aid/ASSIGNMENTID sid/STUDENTID
Example: done aid/829 sid/21
Mark a student’s assignment as Undone
.
Format: undone aid/ASSIGNMENTID sid/STUDENTID
Example: undone aid/829 sid/21
Illustration:
Notice that George has initially not completed Assignment 44736.
After done aid/44736 sid/63865
:
Now observe 3 updates:
-
Success message as displayed in message box
-
The
status
of the Assignment has been marked as done -
The
Number of Done Progress
has been incremented by 1
Contributions to the Developer Guide
Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. |
Model component [Tee Jun Jie Ivan]
API : Model.java
The Model
,
-
stores a
UserPref
object that represents the user’s preferences. -
stores the 6 AddressBookGeneric<K extends ModelObject>, each of which holds a different type of ModelObject. The 6 types are namely
-
Student
-
Course
-
Staff
-
Assignment
-
Progress
-
Finance
-
-
exposes an unmodifiable
ObservableList<K extends ModelObject>
that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. -
does not depend on any of the other components.
Below is an example of the different types of RelevantFields that can be tied to an Assignment.
The AddressBookGeneric in the diagram above is actually an AddressBookGeneric<Assignment>. The AddressBookGeneric has been made to accept any class that extends ModelObject. This cannot be shown due to limitations in PlantUML. |
Notable Implementations in Model
-
By making use of
Generics
andPolymorphism
, the group has made it such thatAddressBookGeneric<K extends ModelObject>
can hold any class that extends from ModelObject- Benefits
-
-
Allows for code optimization by having reusable code. There is significant decrease in workload when code can be reused for each others' benefit instead of having duplicated code.
-
Allows for extension easily for future features. Future features that involve creating new AddressBooks can be developed very quickly and allow for faster development of future features.
-
-
All
ModelObjects
implementCloneable
so as to allow for Defensive Programming more easily.-
Please refer to
Step 2 of Section 2.2.2
for the team’s rationale behind having ModelObject implement Cloneable.
-
-
All Non-Crud Commands such as
Assign
/Un-assign
/Done
are handled inDiffTypesOfManagers
such asEdgeManager
orProgressManager
instead of having all implementations being done inModelManager
- Benefits
-
-
Easier implementation since lower level implementations can be abstracted away
-
More decoupling which will lead to be better testability and easier debugging
-
Entity Linking - Assigning/Un-Assigning an Entity to/from a Course [Tee Jun Jie Ivan]
In order to allow the tracking of the students/assignments/teachers that are assigned to a course and vice versa, this required us to implement a structure which allowed us to obtain information from the aforementioned objects, without causing any circular referencing errors.
The group came up with the structure above where we centralize most links around the Course
object so as for easier management of entity links.
Notice that Student does not hold a Course , but a set of CourseIDs . Hence, there should be an association between Student and ID instead of Student and Course .
However, the group found it much more intuitive to think of the associations to be from 2 modelObjects rather than to and from IDs.
Every non-directed association between 2 objects ensures that both objects have each other’s ID.
|
The only exception is Progress
objects which are created via a composite ID of studentID
and assignmentID
.
A more detailed explanation of Progress Management is explained in [progress-management].
Entity Linking is managed exclusively by Edge Manager
-
Ensures that links are maintained/removed properly during assign, un-assign, delete commands API :
EdgeManager.java
Execution of Assign/Un-assign Command [Tee Jun Jie Ivan]
For the actual execution of an assign/un-assign command, 2 main steps are performed.
-
Pre-process the targeted entities to ensure consistent state - Via
PreprocessUndoCommand
method call -
Add/Remove both object’s ID into/from each other - Handled by
EdgeManager
Step 1: Preprocess Entities
Rationale
Firstly, a pre-processing step
must be performed before executing an undo-able assign/un-assign command to ensure
that all entity links are in correct state before command execution.
This means that either
-
Both targeted objects have each other’s IDs or
-
They do not
There should be no instance where Course has an Assignment/Student/Staff’s ID but they do not have the Course’s ID or vice versa.
Current Implementation
Below is an activity diagram showing the pre-processing performed for assign commands. The diagram can be generalized for un-assign commands by checking if the course contains X and vice versa in the second stage instead.
Notice that there are 2 main exit points in the activity diagram.
-
The success case is straightforward and will lead to a the program continuing to execute the actual assign/un-assign command.
-
For the failure case, should any of the conditions fail, this means that either that the
-
specified objects does
not exist
, -
both entities are
already assigned
to each other or, -
most importantly, that the model is in an
inconsistent state
where one entity is assigned to the other but not vice versa.
-
Step 2: Assign IDs via EdgeManager
Rationale
After the necessary checks have been performed, respective IDs need to be added to the targeted course and targeted object in order to ensure correct and consistent assigning of objects.
Current Implementation
Below is a sequence diagram of how EdgeManager adds the IDs to the two objects involved.
The flow of an assign command is as follows:
-
Obtain a copy of the requested
modelObjects
fromModelManager
-
One of which must be a
Course
modelObject, the other being either aStudent
/Staff
/Assignment
modelObject
-
-
For object X', add the
courseID
into the assignedCourseIDs in X`-
For assignments, every assignment can only be assigned to at most one course. Hence, it’ll hold just an assignedCourseID instead of a set of Course IDs.
-
-
For Course C', add
X’s ID
into assignedXIDs in C'-
For courses, every course may only have at most one teacher. Hence, course will have an assignedTeacherID instead of a set of Teacher IDs.
-
-
Update the 2 affected models by executing
set(targetObj, editedObj)
in modelManager for both changed modelObjects -
Update the storage by running postDataStorageChangeEvent() - ref to
Figure 2
to understand how storage save is triggered
This sequence diagram can be generalized for un-assign command as well.
Instead of adding IDs, un-assign will remove each other’s ID from the respective objects.
|
Design Considerations
-
Manipulating the
actual
modelObjects by having modelManager#get() return referenced variable of the actualmodelObjectTags
.- Pros
-
-
Simpler implementation since any changes to the model will change the actual object directly
-
Faster execution since any changes is done to the actual modelObject
-
- Cons
-
-
Might allow for unintentional changes to the actual modelObject
-
-
(Current Implementation) Manipulate a
cloned
modelObject by having modelManager#get() return a copy of actual modelObject.- Pros
-
-
Prevents unintentional modifications of the shared object
-
- Cons
-
-
Extra processing required. For example, a method is required to replace the old modelObject with the new model object. Also, requires all ModelObject classes to implement a clone() method.
-
More memory intensive and can hurt overall program performance.
-
Overall, the second option was chosen since the program is very dependent on maintaining a consistent state
, where either 2 modelObjects have each other’s ID or they do not.
Some performance can be sacrificed in order to ensure that the links between objects cannot be modified by mistake.
Summary of Entity Linking
Overall, in order to ensure successful entity linking, the role that EdgeManager
plays is crucial.
The table below shows the method calls made to EdgeManager
during an Assign
/Un-assign
command.