Skip to content

Latest commit

 

History

History
1409 lines (1010 loc) · 68.7 KB

DeveloperGuide.adoc

File metadata and controls

1409 lines (1010 loc) · 68.7 KB

ArchDuke - Developer Guide

Preface

About ArchDuke

Team leaders often face problems managing multiple projects, especially software development projects where the usage of a Kanban board is common.

Having to manage multiple Kanban boards for each individual project is a huge hassle for team leaders. As such, ArchDuke solves this issue by allowing team leaders to manage

  1. Team members

    • ArchDuke allows users to assign tasks to team members, and track their workload, progress on tasks, and contributions.

  2. Tasks in a group project

    • ArchDuke allows users to track multiple tasks within a project. Tasks can be created and assigned to members.

    • ArchDuke tracks the deadlines and priority levels of tasks, to help the user organise which tasks should be assigned and completed.

  3. Multiple group projects

    • ArchDuke allows users to track multiple group projects. New group projects can be created and a default Kanban board will be created for users to start adding tasks.

Document Change History

Revision Date Summary of Changes

11 November 2019

Version 1.9: Finalised Developer Guide with Instructions for Manual Testing

10 November 2019

Version 1.8: Included Class Diagrams for Storage layer and Repository layer

9 November 2019

Version 1.7: Added more documentation regarding implementation of Assignment

8 November 2019

Version 1.6: Added documentation regarding CI and Code Quality

5 November 2019

Version 1.5: Small updates to AssignmentController and reorganising content

1 November 2019

Version 1.4: Added documentation on Reminder and logging functionality

31 October 2019

Version 1.3: Added documentation for Member and Tasks functionality

30 October 2019

Version 1.2: Added documentation on UI functionality

25 October 2019

Version 1.1: Added documentation on implementation design for Assignment

23 October 2019

Version 1.0: Added documentation on implementation design for AssignmentController and Project functions

22 October 2019

Version 0.9: Updated Architecture Design

15 October 2019

Version 0.8: Updated the name of project from Duke to ArchDuke

2 October 2019

Version 0.7: Updated Prerequisites and removed unwanted lines

30 September 2019

Version 0.6: Added table of contents, preface and document history

26 September 2019

Version 0.5: Updated use cases for a cleaner look

24 September 2019

Version 0.4: Added Non-functional Requirements to DeveloperGuide

23 September 2019

Version 0.3: Added user stories to DeveloperGuide

22 September 2019

Version 0.2: Added use cases to DeveloperGuide

18 September 2019

Version 0.1: Creation of DeveloperGuide based on template

1. Setting up

1.1. Prerequisites

  1. JDK 11 or above is required

  2. IntelliJ IDE is recommended

Note
IntelliJ by default has Gradle plugin installed. Do not disable them. If you have disabled them, go to File > Settings > Plugins to re-enable them.

1.2. Setting up the project environment on your local machine.

  1. Fork and clone the forked remote on your local machine.

  2. Launch IntelliJ (If you’re not on the IntelliJ Welcome screen please close your existing project by going to File > Close Project.)

  3. Set up the correct JDK version for Gradle

    1. Click Configure > Structure for New Projects

    2. Under Project Settings Click on Project

    3. Under Project SDK Click New… and point it to JDK 11 path.

    4. Click OK to save the configuration

  4. Click Import Project

  5. Locate the build.gradle file and select it. Click Open.

  6. Open the IntelliJ console/terminal and run the gradle command gradlew processResource on Windows or ./gradlew processResource on Mac/Linux

Note
(If you are encountered a permission error: ./gradlew: Permission denied add the executable permission to the the shell script by running chmod 744 gradlew in your terminal) It should finish with the BUILD SUCCESSFUL message. This will generate the resources required by the application and tests.

1.3. Verifying the setup

  1. Run ArchDuke to verify and try a few commands. Do refer to the user guide for a list of commands to try out.

  2. Run the JUnit Tests/gradlew test command to ensure that all the test case passes.

1.4. Configurations to do before writing code

Configuring the coding style

  • ArchDuke uses CheckStyle to check for code quality violations.

  • To configure your project to use CheckStyle, add id 'checkstyle' under plugins for your build.gradle file.

  • Ensure that your CheckStyle toolVersion is 8.23 by adding toolVersion = '8.23' into your build.gradle file.

You may refer to ArchDuke’s build.gradlew file as a reference on how to set up CheckStyle correctly.

Setting up CI

ArchDuke utilizes Travis to perform Continuous Integration (CI). Other CI tools available are AppVeyor, GitLab CI or Github Actions. ArchDuke has decided on using Travis CI due to its ease of configurations.

In order to set up Travis CI, a .travis.yml needs to be added in the root directory of your working directory. For more details on how to configure your .yml file, do refer to Travis documentation online, or ArchDuke’s .travis.yml file located here

After setting up Travis, you can set up coverage reporting for your team fork. ArchDuke utilizes JaCoCo as test coverage tool and Coveralls as a web service to track our code coverage over time.

Getting started with coding

When you are ready to start coding, we recommend that you get some sense of the overall design by reading about ArchDuke’s architecture in the next section.

2. Design

Architecture Design

ArchDuke was implemented using the N-tier architecture approach. Having a N-tier application architecture helped s to flexibly create the application by segregating the application into tiers. Hence instead of reworking the entire application when the application is modified, we only had to rework the specific layer dealing with the modification. This approach also helped us in logically structuring the elements which made up ArchDuke. The Architecture Diagram given below explains the high-level design of ArchDuke.

ArchDuke Architecture
Figure 1. Architecture Diagram

Below is a quick overview of each component based on our Architecture.

Not included in the diagram is the Main program in the folder launcher. The Main program is responsible for initializing the View layer and its subsequent dependencies.

  • In our case, as ArchDuke is a command line program, Main will initialize CLIView.

Utility layer represents a collection of classes used by multiple other components and can be accessed by all layers.

  • Factory classes : Used mainly by Repositories and Controllers to create objects based on user input.

    • Examples of Factory classes used in ArchDuke are MemberFactory, ProjectFactory and TaskFactory.

    • These factory classes are grouped under the package util.factories.

  • Logger class: Used by all classes to write log messages to ArchDuke’s log file.

  • ParserHelper class: Used by all classes for user input parsing.

  • SortHelper class: Used primarily by Repositories and Controllers for sorting objects based on description before a Response model is generated for the View layer.

  • DateTimeHelper class: Used for handling anything that is related to Date objects or parsing inputs for Date objects

  • ConstantHelper class: Stores all magic numbers and strings for better code readability

  • ValidityHelper class: Responsible for data validation before object creation

  • UIFormatter classes: Responsible for formatting data into String arrays for the View layer

The rest of the App consists of four main layers.

  • View layer: The UI of ArchDuke. Responsible for printing everything that the user will see and reading inputs from the user.

  • Controller layer: Responsible for handling user inputs and sending them to the respective classes for parsing, cleaning, or object creation.

  • Repository layer: Responsible for holding data in-memory during program runtime

  • Storage layer: Responsible for serializing and serializing persistent JSON data files from hard disk.

Each layer will be discussed in detail below.

2.1. View Layer

Our main UI Component is a class called CLIView. It is mainly responsible for reading the user input and displaying formatted messages to the user.

When ArchDuke is running, CLIView repeatedly reads the user input line by line, and sends it to the parsing components (Controllers) to make sense of the input. Eventually, the controllers will retrieve the relevant messages and information for CLIView to display.

ViewLayer ClassDiagram
Figure 2. Structure of the UI Component

2.2. Controller Layer

2.2.1. ConsoleInputController

ConsoleInputController is the class which deals with the CRUD functionality for all the projects of the user. Upon entry of ArchDuke, the input commands from CLIview would be passed to the ConsoleInputController to be parsed and processed. Subsequently, based on what is interpreted from the user input, the ConsoleInputController will call the relevant methods from the other classes from the next layer, and returns to CLIview either the desired data by the user or the success/error messages to inform the user of the result of the input command.

Rationale for implementation

The ConsoleInputController is meant to process command inputs from the user and subsequently call methods from other classes. It mainly allows the user to navigate between the different projects available, to give the user an overview of the current projects.

2.2.2 ProjectInputController

ProjectInputController is the class which deals with the management of a specific project.

Rationale for implementation

We realized that the commands related to managing a project are extremely complex. Hence we had to segregate the methods related to managing a single project from the ConsoleInputController and this resulted in the creation of the ProjectInputController.

When the project is being managed, all the commands input by the user are directly handled by the ProjectInputController. Hence, ProjectInputController acts like a parser for commands dealing with the CRUD functionality for Members, Tasks, Task Assignments and Reminders. Control is handed back to the ConsoleInputController after exiting from managing a project.

2.2.3 AssignmentController

AssignmentController is a class which manages the assignment of tasks to group members. It is invoked by ProjectInputController when the user inputs the "assign task" command. It first ensures that the input is valid by ensuring that there are sufficient parameters (task index numbers, member index numbers). It then accesses the respective Project to create or remove assignments between Member and Task objects. These assignments are recorded within the Project itself in the form of Java HashMaps.

This controller contains a ParserHelper to help parse assignment commands, and two separate ArrayLists to store error or success messages to display to the user regarding task assignments.

Rationale for implementation Before the implementation of AssignmentController, the parsing of assign commands was planned to be done within the ProjectInputController class. However, we realised that parsing for assignment commands would be extremely complex due to the potentially high number of arguments and operations that need to be done. Separate methods would be needed to handle assignments and unassignments, with one unifying method that combines and executes one or both based on the user input.

For these reasons, we decided to separate these methods into AssignmentController class. This allows for higher cohesion as all methods related to managing assignments between tasks and members are isolated into a single, focused class. It can help to fulfill the Separation of Concerns Principle.

2.3. Repository layer

The repository layer is responsible for the storage of information in ArchDuke. It consists of the ProjectRepository class, which keeps track of all the Project objects. Each Project contains the following components:

RepositoryLayerClassDiagram
Figure 3. Simplified Class Diagram of Repository Layer

An implementation of IRepository: ProjectRepository ProjectRepository.java

The Repository Layer is responsible for serving as a boundary between the Storage layer and the Controller layer. It uses the IRepository interface, making it easy should other developers choose to implement their own Repository layer.

The responsibilities of the Repository layer includes

  • Storing the data in-memory during programme runtime. It stores all Project objects created in an ArrayList<Project>.

  • Separation of concern between data and persistence. In a full-fledged application, the Repository layer will serve as a boundary between the database and the domain logic

In our implementation of ProjectRepository that implements the IRepository interface, it

  • Calls ProjectFactory for creation of Project objects and stores it in an ArrayList<>

  • Exposes APIs to retrieve details of the stored Project objects for Controller to send back to View layer.

  • Exposes CRUD APIs for creation, deletion and getting a Project object from the stored ArrayList<Project>.

2.4. Storage Layer

StorageLayerClassDiagram
Figure 4. Simplified Class Diagram of Storage Layer

The Storage layer is responsible for saving and loading data to and from persistent data. It utilizes a 3rd-party plugin called GSON, a serialization and deserialization library by Google to convert Java Objects into JSON and back.

  • It can save Project objects in JSON format and read it back.

  • It saves all JSON in the current working directory that ArchDuke is saved in

    • This can be changed by editing userDirectory component to the desired directory where saved data should be.

  • Each new Project object saved inside the Repository will be saved in a new JSON file, named after the name of the Project.

2.5. Utility Classes

Classes used by multiple components are in the 'util' package. Within this package are several subpackages that assist the functionality of ArchDuke. The following table shows a brief description of these classes and a link to their API.

Class

Functionality

API

ArchDukeLogger

Help with the logging functionally for ArchDuke for easy debugging for the developers.

ArchDukeLogger.java

AssignmentViewHelper

Handles view assignments commands, retrieves and organises task assignment information to display to the user.

AssignmentViewHelper.java

CommandHelper

Contains the command help instruction for the user to consume.

CommandHelper.java

ConstantHelper

Contains most of the constants used throughout ArchDuke.

ConstantHelper.java

DateTimeHelper

Handles the Date Format specific to ArchDuke

DateTimeHelper.java

ParserHelper

Contains methods used by other classes to parse the user input to retrieve and validate the desired information.

ParserHelper.java

ProjectFactory

The ProjectFactory manages the object creation for ConsoleInputController.

ProjectFactory.java

ReminderFactory

The ReminderFactory manages the object creation for ProjectInputController.

ReminderFactory.java

MemberFactory

The MemberFactory manages the object creation for ProjectInputController.

MemberFactory.java

TaskFactory

The TaskFactory manages the object creation for ProjectInputController.

TaskFactory.java

SortHelper

Contains various function for sorting the item in different format.

SortHelper.java

ViewHelper

Formats and organises information in a presentable and user-friendly manner to display to the user.

ViewHelper.java

3. Implementation

This section describes in detail on how certain features of ArchDuke are implemented. Most features are based on Create, Read, Update, Delete, also known as CRUD functions

3.1. CRUD functionality for Projects

Implementation

CRUD functions are facilitated by ConsoleInputController, ProjectRepository and ProjectFactory. It allows ArchDuke to be able to do some basic CRUD functions for a Project, namely Creation, Reading, Update and Deletion.

ConsoleInputController will read the relevant commands from the View layer and call the relevant methods in ProjectRepository.

It implements the following commands:

  • create PROJECT_NAME — Creation of a new Project

  • list —  Viewing all Projects that have been created

  • delete PROJECT_INDEX — Delete a Project that has been created previously

These operations are exposed in the IRepository interface as addToRepo(), getAll() and deleteItem().

Note
However, in order to create a object, inputs sent to the Repository layer must be sent to a Factory class as the Repository layer is not responsible for the creation of Objects.

The example usage scenario below will explain in detail the data flow and how the program behaves at each step of CRUD functions with regards to a Project object.

Step 1) ArchDuke is launched for the first time by the user. A new CLIView() and ConsoleInputController is created upon initialization. Immediately after initialization, CLIView.start() will be called which prints a welcome message to the user and awaits for user input.

Step 2) The user executes the command create Avengers Assemble! to create a new Project with the description "Avengers Assemble!". User input is fed from CLIView to ConsoleInputController, where simple parsing will be done to determine the type of command that the user has executed.

Step 3) User input will be understood as a command to create a new project and thus sent to ProjectRepository where it will call on ProjectFactory for the creation of a new Project object.

Step 4) ProjectRepository will check if ProjectFactory managed to create an object successfully. Any unsuccessful creation will be due to wrong user commands or a bug during data validation in ProjectFactory.

Step 5) Assuming Project creation was a success, ProjectRepository will store it in an ArrayList and return True back to ConsoleInputController to signify the successful creation of a new Project object. ConsoleInputController will call CLIView to print appropriate messages to the user based on whether a new Project object was created successfully or not.

The following sequence diagram shows how the create PROJECT_NAME command works.

ProjectCreation Sequence

The delete PROJECT_INDEX command works similarly to create PROJECT_NAME. Both commands will result in a Boolean of either True or False to indicate whether command was executed successfully. There are minor differences, listed below:

  • Instead of creating a new Project object, the delete PROJECT_INDEX command will call deleteItem() in ProjectRepository instead of addToRepo().

  • Deletion of Project works by Project Index instead of Project Name.

Manage project

ArchDuke allows users to manage each individual project in the ProjectRepository. The following sequence diagram shows how the manage PROJECT_INDEX command works.

ManageProject Sequence

Design Considerations

Aspect: How projects creation executes
  • Alternative 1 (current choice): Use Factory creational design pattern

    • Pros:

      • Reduces complexities by creating objects without using the new operator

      • Avoids tight coupling by separating the object creation process from the class that needs it

      • Frequent changes to the Interface can be accommodated

      • Aids scalability as other classes only need to refer to the Factory class to create more objects

    • Cons:

      • Requires deep technical knowledge on handling Null objects

  • Alternative 2: Using the new operator to create new Objects

    • Pros:

      • Simple, basic and easy to learn

    • Cons:

      • High coupling, as instances of the Object created cannot be isolated for unit testing

      • Breaks Single Responsibility Principle as sometimes the Object needs to be modified frequently

3.2 CRUD functionality for Members

Implementation

CRUD Member functions are handled by Member, MemberList, MemberFactory, Project and ProjectInputController. It allows ArchDuke to perform simple CRUD function for Member in the Project, these simple functions include Create, Read, Update and Delete. ProjectInputController will read the relevant command related to the member function and call the relevant methods in ParserHelper.

It implements the following commands:

  • add member -n MEMBER_NAME [-i MEMBER_PHONE_NUMBER] [-e MEMBER_EMAIL] — Creates a new Member with the member name, phone number (optional) and email address (optional).

  • edit member MEMBER_INDEX [-n MEMBER_NAME] [-i PHONE_NUMBER] [-e MEMBER_EMAIL] — Updates an existing member details based on the member index with the new attributes specified.

  • view members-- Displays all the members in the current project.

  • view credits-- Displays the compiled credits of all members from their individually assigned tasks.

  • role INDEX -n MEMBER_NAME-- Assigns roles to specific members using their names.

  • delete member MEMBER_INDEX--Deletes a member from the current project using the member index.

The example usage scenario will explain in detail the data flow and how the program behaves at each step of CRUD functions with regards to a Member object.

Step 1) The user creates a new project and chooses to manage it.

Step 2) The user executes the command add member -n Charles Wong -i 95674325 -e [email protected] to create a new member with the name "Charles Wong" whose phone number is "95674325" and whose email address is "[email protected]".

Step 3) The ProjectInputController.manageProject() method triggers the MemberFactory which does the validation of the input.

Step 4) MemberFactory then goes on to call parser.parseMemberDetails() to do a simple parsing which will clean up the flags and will return an ArrayList<String> for MemberFactory to create the member.

Step 5) MemberFactory will create the member based on the information provided by the user. The created member will subsequently be added into memberList which holds all the members in the current project. Upon doing successfully or unsuccessfully doing so, a String message will be returned.

CreateMember Sequence
Figure 5. Sequence diagram of add member command

3.3. CRUD functionality for Tasks

Implementation

CRUD Task functions are handled by Task, TaskList, TaskFactory, Project and ProjectInputController. It allows ArchDuke to perform simple CRUD function for Task in the Project, these simple functions include Create, Read, Update and Delete. TaskFactory will create the relevant task with the appropriate input from the user which will then be added into the TaskList managed by the Project. ProjectInputController will read the relevant command related to task function and call the relevant methods in TaskFactory And ParserHelper.

It implements the following commands:

  • add task -n TASK_NAME -p TASK_PRIORITY -c TASK_CREDIT [-d TASK_DUE_DATE] [-s TASK_STATE] [-r TASK_REQUIREMENTS] — Creates a new Task with the task name, priority, credit, due date (optional), state(optional) and additional requirements (if any).

  • edit task TASK_INDEX -n TASK_NAME -p TASK_PRIORITY -c TASK_CREDIT [-d TASK_DUE_DATE] [-s TASK_STATE] — Updates existing task attributes with the new input values.

  • view tasks — Displays all tasks in current project.

  • view tasks [-MODIFIER] — Displays tasks sorted based on the attribute specified by the user.

  • view task requirements TASK_INDEX — Displays all additional requirements of a specified task.

  • edit task requirements TASK_INDEX rm/TASK_INDEXES r/TASK_REQUIREMENT1 — Updates task requirements of specified task by removing unwanted requirements and adding new ones.

  • delete task TASK_INDEX — Deletes task with stated index.

The example usage scenario below will explain in detail the data flow and how the program behaves at each step of CRUD functions with regards to a Task object.

Step 1) Assuming Project have been created and the user is currently managing a specific project.

Step 2) The user execute the command add task -n kill Thanos! -p 100 -c 100 to create a new task with the task name “kill Thanos!”, priority value “100” and a credit of “100”. These input will be consumed by ProjectInputController.manageProject()

Step 3) The ProjectInputController.manageProject() will trigger the TaskFactory which will do a validation to ensure the required input are given.

Step 4) TaskFactory will then call parserHelper.parseTaskDetails() to do a simple parsing which will clean up the flags and return ArrayList<String> for TaskFactory to create the task.

Step 5) TaskFactory will create the task based on the information given by the user. The created task will subsequently be added into taskList managed by the project and a successfully or unsuccessfully a message in String[] will be returned.

The following sequence diagram show how add task operation works.

CreateTask Sequence
Figure 6. Sequence diagram of add task command

3.4. CRUD functionality for Reminder

Implementation

CRUD Reminder functions are handled by Reminder, ReminderList and ReminderFactory,Project and ProjectInputController. It allows ArchDuke to perform simple CRUD function for Reminder in the Project, these simple functions include Create, Read, Update and Delete. ReminderFactory will create the relevant task with the appropriated input from the user which will then be added into the ReminderList managed by the Project. ProjectInputController will read the relevant command related to task function and call the relevant methods in ReminderFactory And ParserHelper.

Reminder function implements the following commands:

  • add reminder -n REMINDER_NAME -r REMINDER_REMARKS -d REMINDER_DUEDATE -l REMINDER_LIST_NAME — Creation of a new Reminder with the reminder name and due date (optional) the remarks of the reminder and the reminder list name.

  • edit reminder TASK_INDEX -n REMINDER_NAME -r REMINDER_REMARKS -d REMINDER_DUEDATE -l REMINDER_LIST_NAME — Edits existing reminders with the new input values specified by the user.

  • delete reminder REMINDER_INDEX — Delete existing reminder with the specified index.

  • view reminders — Viewing of all reminders in current project

  • view reminders by list — Viewing of all reminders in current project sort in their respective list.

The following sequence diagram show how add reminder operation works.

The example usage scenario below will explain in detail the data flow and how the program behaves at each step of CRUD functions with regards to a Reminder object.

Step 1) Assuming Project have been created and the user is currently managing a specific project.

Step 2) The user execute the command add Reminder -n Do System integration -d 31/10/2019 to create a new reminder with the reminder name “Do System integration” on a specific date "31.10/2019". These input will be consumed by ProjectInputController.manageProject()

Step 3) The ProjectInputController.manageProject() will trigger the ReminderFactory which will do a validation to ensure the required input are given.

Step 4) ReminderFactory will then call parserHelper.parseReminderDetails() to do a simple parsing which will clean up the flags and return a ArrayList<String> with the relevant details for ReminderFactory to create the task.

Step 5) ReminderFactory will create the reminder based on the information given by the user. The created Reminder will subsequently be added into ReminderList managed by the project and a successfully or unsuccessfully a message in String[] will be returned.

CreateReminder Sequence
Figure 7. Sequence diagram of add reminder command
ViewReminder Sequence
Figure 8. Sequence diagram of view reminders by list command

3.5. Assignment between Tasks and Members feature

Implementation

ArchDuke allows users to track tasks and their assignments to members in a project. Assignments establish a relationship between a task and a member. When a member is assigned a task, they are expected to complete it, and will be given the stipulated credit when the task state is marked as DONE. The degree of each member’s contributions are measured by task credit.

Assignment functions are handled by ProjectInputController, ParserHelper, AssignmentController, AssignmentViewHelper and Project.

Assignment functions implement the following commands:

  • assign task -i TASK_INDEX -to [MEMBER1_INDEX] [MEMBER2_INDEX] -rm [MEMBER3_INDEX]

  • view assignments MODIFIER

Upon creation, each Task and Member object are given a unique ID using the UUID class in Java. The ID is stored as a String and is immutable throughout the lifetime of the object. Assignments are tracked in the Project class by mapping the task IDs to the member IDs using 2 Java HashMaps:

  • taskAndListOfMembersAssigned

    • Key: String taskID of each task.

    • Value: ArrayList<String> containing memberID of all members assigned to the respective task.

  • memberAndIndividualListOfTasks

    • Key: String representing memberID of each member.

    • Value: ArrayList<String> containing taskID of all the tasks assigned to that particular member.

Making or Changing Assignments

The following steps show how the assign task command is implemented in ArchDuke.

Step 1) Assume Project has been created and the user is currently managing a specific project.

Step 2) User enters the command assign task -i 1 2 -to 1 2 3 -rm 4. This indicates the user would like to assign tasks with index number 1 and 2 to members 1, 2 and 3, and also unassign/remove the task from member 4.

Step 3) The ProjectInputController.manageProject() will call projectAssignTask(). A new AssignmentController will be created, and the assignAndUnassign() method is called to manage the assignment.

Step 4) ParserHelper.parseAssignmentParams() is called to parse and split the input into 3 parts: the task index numbers, the assignee index numbers, and the unassignees index numbers.

Step 5) ParserHelper checks all 3 sets of index numbers to ensure that they are valid (non-negative integers, and exist within the project) using ParserHelper.parseMembersIndexes() and ParserHelper.parseTasksIndexes(). AssignmentController.checkForSameMemberIndexes() checks if the list of assignees and unassignees contain any identical index numbers, and removes them to avoid redundant work. ParserHelper returns all 3 sets of valid indexes to AssignmentController.

Step 6) If there are valid task numbers, a for loop is used to iterate through the tasks to handle the assignments one by one. AssignmentController.assign() and AssignmentController.unassign() are called to assign or unassign tasks to the members.

Step 7) Project.containsAssignment() is used to check if an assignment between a task and member already exists to avoid any errors (for example, duplicating assignments or trying to remove an assignment which does not exist). The errors are noted down by adding error messages to the ArrayList errorMessages which will be displayed to the user later.

Step 8) If the input is valid, the assignment is created by calling Project.createAssignment() or removed by calling Project.removeAssignment(). The 2 HashMaps in the project are manipulated accordingly to note down the assignment between the specified task and member. Success messages are stored in successMessages.

Step 9) The errorMessages and successMessages from AssignmentController are retrieved by ProjectInputController. The messages are validated, and then formatted with the help of ViewHelper, which organises the information into easy-to-read tables and displayed to the user.

The following sequence diagram shows how the assign task command works. Certain objects, such as Project and ViewHelper are omitted for simplicity.

AssignmentSequenceDiagram
Figure 9. Sequence diagram of assign task command

Viewing Assignments

The following steps show how view assignments is implemented in ArchDuke.

Step 1) Assume Project has been created and the user is currently managing a specific project.

Step 2) User enters a command to view assignments. This can be in one of the following formats:

  • view assignments -m (to view each member’s tasks)

  • view assignments -t (to view each task’s assigned members)

Each command is accompanied with a suffix all, or selected index numbers of members or tasks.

Step 3) The ProjectInputController.manageProject() will call projectViewAssignments().

Step 4) AssignmentViewHelper is created, and calls viewAssignments() to to retrieve the necessary assignment information. The input length is checked to ensure that there are sufficient parameters. Depending on the flag in the user input, viewAssignments() calls 1 of 2 the helper methods:

  • Task flag -t: viewTasksAssignments() is called.

    • ParserHelper.parseTaskIndexes() is called to parse and retrieve valid task indexes.

    • AssignmentViewHelper.getTaskOutput() is called to access the HashMap taskAndListOfMembersAssigned to retrieve the assigned members for selected tasks.

  • Member flag -m: viewMembersAssignments() is called.

    • ParserHelper.parseMemberIndexes() is called to parse and retrieve valid member indexes.

    • AssignmentViewHelper.getMemberOutput() is called to access the HashMap memberAndIndividualListOfTasks to retrieve the assignments for the selected members.

The necessary information is stored in an ArrayList of String totalOutputToPrint in both cases.

Step 5) The helper class ViewHelper formats the output in an organised table, and the output is returned to ProjectInputController, and subsequently back to CLIView to be displayed to the user.

The following sequence diagram shows how the view assignments command works.

ViewAssignmentSequence
Figure 10. Sequence diagram of view assignments command

Design Considerations

Aspect: How to keep track of Assignments
  • Alternative 1 (current choice): Use 2 HashMaps which store IDs of tasks and members in Project class

  • taskAndListOfMembersAssigned

    • Key: String taskID of each task.

    • Value: ArrayList<String> containing memberID of all members assigned to the respective task.

  • memberAndIndividualListOfTasks

    • Key: String representing memberID of each member.

    • Value: ArrayList<String> containing taskID of all the tasks assigned to that particular member.

    • Pros:

      • 1) Allows fast and easy writing and retrieval of data.

      • 2) Task and Member objects to not need to be aware of each other in order to maintain the assignment. Assignments can be managed entirely by the project itself, which reduces coupling between Task and Member objects.

    • Cons:

      • 1) Task and Member objects must be retrieved manually by iterating through the taskList/memberList to find the corresponding object with the matching ID.

  • Alternative 2: Use 2 HashMaps in Project class which store Similar to Alternative 1, but instead of storing String IDs, the objects themselves are stored.

    • taskAndListOfMembersAssigned

      • Key: Task

      • Value: ArrayList of assigned Member objects (List of members assigned to task)

    • memberAndIndividualListOfTasks

      • Key: Member

      • Value: ArrayList of Task objects (List of each member’s individual tasks)

    • Pros: (same as in Alternative 1)

      • 1) Allows fast and easy writing and retrieval of data.

      • 2) Task and Member objects to not need to be aware of each other in order to maintain the assignment. Assignments can be managed entirely by the project itself.

    • Cons:

      • 1) Complications associated with hashing non-primitive objects.

      • 2) Key or values cannot be updated consistently in the HashMap when task/member details are changed. This results in inconsistent task and member information being stored in the 2 HashMaps, and outdated information being retrieved when viewing assignments.

  • Alternative 3: Each Task maintains an ArrayList of assigned members, and each Member maintains an ArrayList of assigned tasks.

    • Pros:

      • 1) More intuitive.

    • Cons:

      • 1) Increases coupling between Member and Task as each member has to keep a list of assigned tasks and vice versa.

      • 2) Cyclic dependencies will exist between Task and Member objects, making it difficult to edit and change task assignments.

  • Alternative 4: Use an association class to record the assignment.

    • Pros:

      • 1) Reduces coupling between Member and Task.

    • Cons:

      • 1) Since the association class does not belong to Member or Task in particular, it might be more difficult to retrieve specific information about the assignments of a particular task/member.

      • 2) No additional information needs to be stored by the association class.

3.6. UI functionality for displaying information

Implementation

UI functions are handled by CLIView, ViewHelper, and the repository layer which stores the details of projects, members and tasks. It allows ArchDuke to present useful information to the user in an easily readable format when requested. The information will be presented in a table form with a clear header that describes the content and has the information in bullet point form.

The UI display uses the following methods to produce a table:

  • consolePrintTable() — Main method that constructs the table. Returns a String array with each element representing one row of the table

  • consolePrintTableHoriBorder() —  Returns a String containing the horizontal border of the table

  • getRemainingSpaces() — Returns a String containing the remaining number of spaces required to fill up the rest of the line

  • getArrayOfSplitStrings() — When a String that is meant to be in one row in the table is too long, it is passed into this method to split the string up into an array of Strings of suitable length to fit into one row of the table

  • consolePrintMultipleTables() — This method reuses consolePrintTable() and expands on it to create a table containing multiple smaller tables each with its own header. Returns a String array with each element containing the String corresponding to the line of the table to be printed

The following steps show how the UI table display are made in ArchDuke.

Step 1) User enters a command that requires information to be presented in a clear format such as list, view members, view tasks etc.

Step 2) Assume the command list is entered. The user is requesting an overview of all the projects that he is currently doing. This would call the method getAllProjectDetailsForTable() in ProjectRepository.

Step 3) The method getAllProjectDetailsForTable() would return an ArrayList containing multiple ArrayLists of String, with each ArrayList of String containing all the details of each project which will be stored in one table. The parent ArrayList would then contain information to be printed in different tables. In this case, each project will fill one table.

Step 4) The ArrayList of ArrayLists would then be passed into the consolePrintMultipleTables() method in the ViewHelper class, which will create an overall table containing information to all the projects and pack each individual ArrayList of Strings into a formatted table. Each String in the ArrayList of Strings is an entry that is meant to be presented in one line of the table.

Step 5) Within the consolePrintMutlipleTables() method, each ArrayList of String is supposed to be stored within one smaller table. Hence, for each ArrayList of String, the consolePrintTable() method is used to generate a string array containing the contents in the ArrayList of String. The width of each of the smaller tables will be calculated based on the width of the overall table and the input parameter for the number of columns required.

Step 6) Within the consolePrintTable() method, when the String is shorter that the full table width, there are spaces that need to be added to maintain the visual implementation of the table. Hence, the getRemainingSpaces() method is called to fill up the remaining spaces.

Step 7) When the String is longer than the full table width, it needs to be split into multiple lines in order to fit it within the table. Hence, the getArrayOfSplitStrings() method is called to split the string up nicely to fit the table width. It will ensure that the String is split at the spaces as much as possible so that the words remain intact. If the point of the string that exceeds the table width is in the middle of a word and it is within a predefined length, the entire word will be shifted to the next line. If it exceeds that predefined length, that word will be split with a hyphen '-' with the remaining half of the word to be pushed to the next line. This process repeats and each line will be stored in an individual string.

Step 8) The consolePrintTableHoriBorder() method is called at any point where the horizontal border of the table is required.

Step 9) After the tables are generated, the tables would be lined up in each column one by one. The tables will be added to the shortest column at any point in time. If 2 or more columns are of the same length, the next table will be added to the left most column.

Step 10) The consolePrintMultipleTables() method would then store the entire series of tables to be displayed into a String array with each element containing a line to be printed to be passed into consolePrint() where it will be printed with indentation and horizontal borders on the top and bottom.

The following sequence diagram show how list operation works.

ViewAllProjects Sequence

Design Considerations

Aspect: Data structure used for input content of multiple tables for consolePrintMultipleTables()
  • Alternative 1 (current choice): Use ArrayList of ArrayLists, with each ArrayList being an ArrayList of Strings.

    • Pros:

      • 1) Allows fast and easy retrieval of data.

      • 2) Allows orderly storing of individual separate table information in separate ArrayLists.

      • 3) Allows easy manipulation of consolePrintTable() to print each individual table’s content.

    • Cons:

      • 1) Tedious to have multiple nested loops as code may be prone to bugs.

  • Alternative 2: Use one ArrayList of Strings to store all content to be in the table.

    • Pros:

      • 1) Simple data structure used.

    • Cons:

      • 1) Difficult to separate contents from different tables.

      • 2) Difficult to account for formatting of different table lengths and widths.

3.7. Logging

We are using org.apache.logging.log4j package for logging. The ArchDukeLogger class under Utility layer is used for logging every step that ArchDuke takes so that debugging will be easier.

  • The logging level is controlled by property name rootLogger.level in log4j2.properties. Currently the level is set to all. (Show all log level message)

  • The ArchDukeLogger call by using ArchDukeLogger.logInfo(className, Message); function which will log the message according to the specified logging level method called.

  • Currently all the log messages are store in the log file located in the logs directory

The log4j2.properties file in the resource folder is used configure the following:

  • RootLogger level - The level root logger to be shown in the log file. Currently it is set to all to view all the logs level.

  • File Appender - The file direction and log file name. The log file can be found in the logs folder.

  • PatternLayout - The output format message displayed in the log file

The following shows the class diagram of ArchDukeLogger

ArchDukeLogger ClassDiagram
Figure 11. Class diagram of ArchDuke logger
Note
If any bugs or errors encountered during the testing, please do create an issue on this repo and upload the logs file located is the logs directory.

4. Activity Diagram of ArchDuke

The following shows the activity diagram illustrating the overarching flow of ArchDuke.

ActivityDiagram
Figure 12. Activity diagram of ArchDuke

5. Documentation

We chose to use AsciiDoc writing format to write the documentation. This is because Ascii syntax is consistent and there is a flexibility offered for essential syntax unlike MarkDown.

5.1 Written documentation

The user and developer guide are written and formatted using AsciiDoc.

5.2 Diagrams

Diagrams are drawn and edited using the tool draw.io. The tool provides support for a wide range of UML diagrams, such as class, object and sequence diagrams.

6. Testing

Running Tests

There are two ways to run tests.

Method 1: Using IntelliJ JUnit test runner

  • To run all tests, right-click on the src/test/java folder and choose Run 'All Tests'

  • To run a subset of tests, you can right-click on a test package, test class, or a test and choose Run 'ABC'

Method 2: Using Gradle

  • Open a console and run the command gradlew clean test (Mac/Linux: ./gradlew clean test)

Note
See UsingGradle.adoc for more info on how to run tests using Gradle.

Types of tests

We have three types of tests:

  1. Unit tests targeting the lowest level methods/classes.
    e.g. java.factorytests.TaskFactoryTests

  2. Integration tests that are checking the integration of multiple code units (those code units are assumed to be working).
    e.g. java.controllers.ProjectInputControllerManageTest

  3. Hybrids of unit and integration tests. These test are checking multiple code units as well as how the are connected together.
    e.g. java.helpertests.AssignmentViewHelperTest

7. Dev Ops

7.1 Build Automation

About

Gradle is an open-source build automation tool that automates build-related tasks by running scripts. It is mainly used for the following tasks:

  • Automating tests

  • Performing checks on code style

  • Managing dependencies on external libraries

Note
The Gradle configuration for ArchDuke is defined in build script build.gradle.

Gradle commands

Gradle commands are run on the command prompt window. Navigate to the project folder and enter the desired commands. The following are some examples of gradle commands:

  • Windows: gradlew [command1] [command2]

  • Mac/Linux: ./gradlew [command1] [command2]

Cleaning the project

Cleaning deletes the files leftover from previous builds. This prevents existing builds from failing.

Command: clean (eg. ./gradlew clean)

Running the application

Builds and runs the application. Command: run (eg. ./gradlew run)

Running tests

This command runs all the tests located in the test directory. Command: test (eg. ./gradlew test)

Performing coding style checks

  • checkstyleMain Runs the code style check for the main code base

  • checkstyleTest Runs the code style check for the test code base

Note
The two tests are often run side by side (eg. ./gradlew checkstyleMain checkstyleTest). Any code style violations found will be documented in HTML reports found in build/reports/checkstyle.
Note
Code style rules can be found in config/checkstyle/checkstyle.xml. These can be reconfigured to suit the purposes of the project.

7.2 Continuous Integration

We use Travis CI to perform Continuous Integration (CI) for ArchDuke. Other CI tools can be used so long as an appriopriate .yml file is provided and the relevant toolchain is set up properly. Some examples are

  • GitLab CI

  • AppVeyor

  • Github Actions

Travis CI can be configured to run JUnit tests automatically with the help of Gradle. This ensures that existing features and functionality are working as intended and are not broken by new code.

For ArchDuke, TravisCI is configured to run the following things every time code is pushed or a pull request is submitted:

  • Runs ./gradlew clean checkstyleMain checkstyleTest test command

    • This is to run all unit and code style tests and ensures all tests passes.

  • Upon success, it will run ./gradlew jacocoTestReport coveralls

    • This utilizes JaCoCo to generate test coverage and send it to Coveralls

Further customization can be done by referring to Travis documentation online.

7.3 Making a Release

Here are the steps to create a new release.

  1. Update the archiveVersion number in build.gradle shadowJar section.

  2. Generate a JAR file using Gradle shadowJar.

  3. Create a Tag to the current repo release with the version number e.g v.1.4.

  4. Create a new release using GitHub and upload the JAR generated earlier.

Appendix A: Product Scope

Target user profile:

  • Team leaders of group projects

  • Group project team leaders who monitor contributions of team members

  • Project managers who track progress for multiple projects

  • Teachers who evaluate and act upon their students’ progress

  • Technical professionals who keep track of task deadlines

  • Project planners who plan out priority and assignment of roles

  • People who prefer Command Line Interfaces (CLI)

  • People who prefer desktop applications

Appendix B: User Stories

Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *

Priority As a …​ I want to …​ So that I can…​

* * *

project leader

be able to track deadlines for each project

prioritize which project to be completed earlier

* * *

project leader

be able to manage multiple projects and view all the task delegations of my team members in them

distribute my resources appropriately

* * *

project leader

be able to create projects

keep track of all my projects using a command line application

* * *

project leader

be able delete projects that are completed

have a cleaner working environment

* * *

project leader

view a progress bar for each project

have a clearer view of the total progress for each project

* * *

project leader

manage my team members

assign different roles to team members so that they are clear of their relevant roles

* * *

project leader

manage my team members

assign different tasks to team members so that they will be clear of the work that they are supposed to do

* * *

project leader

add team members to a specific group project

assign different roles and tasks to them based on the project they belong to

* * *

project leader

update the details of my team members

have up to date information about them whenever needed

* * *

project leader

remove members from a particular project

remove unwanted or old members from a project that they are no longer contributing

* * *

project leader

keep track of each member’s progress and contributions

ensure all students contribute to their respective tasks sufficiently

* * *

project leader

find a person by name

locate details of persons without having to go through the entire list

* * *

project leader

generate a report of the contributions of the members

credit can be rightfully assigned to the respective members

* * *

project leader

indicate the credit of each task

track the level of contribution by each member

* * *

project leader

track the status of every task

track the progress of each project

* * *

project leader

indicate the priority of the tasks

ensure members know what order to be done

* * *

project leader

input the requirements of the tasks I have been assigned

ensure needs members are clear about what needs to be done

* * *

project leader

be able to track deadlines for each task

I will know if a group member is slacking.

* * *

project leader

assign one task to multiple students

more than one student can contribute to the task

* * *

project leader

delete erroneous tasks from the project I am managing

prevent any confusion and achieve a cleaner work space

* * *

project leader

view tasks sorted by name, index, date, priority, credit, assigned member names or Kanban board style

I can view all the tasks in a customised manner according to the required scenario.

* * *

project leader

import files from other sources

track all my projects from different workstations or work environments

* * *

project leader

be able to edit and read the exported file

have other people can add in details as well into the file and send back

* * *

project leader

have a good overview of all the projects I am managing

I can distribute my resources appropriately

* * *

project leader

define a clear end goal/target for the project

that we stay on the right track

* * *

project leader

I can view the tasks and roles that I have assigned

ensure members can complete them

* * *

project leader

keep track of the contributions of members

ensure everyone does his/her fair share

* * *

project leader

create task dependencies

members can complete tasks in a certain order

* * *

project leader

calculate the total weightage of tasks done by each member

keep track of the amount of contributions done by each member

* *

project leader

schedule project meet-ups

group members can meet at a stipulated date and time

* *

project leader

be able to export the relevant details for each project

send it to other people for viewing

* *

project leader

be able to export the details for each project in different formats

avoid compatibility issues with a specific file format

* *

project leader

view a calendar with all tasks, milestones and deadlines

easily visualise the progress of the project

* *

project leader

have a more intuitive way to view the current task and role assigned to a particular team member

better manage their well being

* *

project leader

be able to track the technical and non-technical roles assigned to my team members

I can keep track of the overall progress of the project

* *

project leader

define milestones to track the progress of the entire project

have users work towards each milestone sequentially

*

project leader

save time managing my team members from the manual way of tracking my group progress

make this group can be as efficient as possible

*

project leader

change the assignment of tasks halfway through the project

cater to different needs and schedules of team members

{To be edited}

Appendix C: Use Cases

(For all use cases below, the System is the ArchDuke and the Actor is the user, unless specified otherwise)

Use case: Create project (UC01)

MSS

  1. User requests to create project with desired project name and number of members

  2. ArchDuke creates a project named after desired project name and number of members

    Use case ends.

Extensions

  • 1a. The given input is wrong.

    • 1a1. ArchDuke shows an error message.

      Use case ends.

Use case: View all projects (UC02)

MSS

  1. User requests to view all projects.

  2. ArchDuke shows a list of all projects with their respective details.

    Use case ends.

Extensions

  • 1a. The given input is wrong.

    • 1a1. ArchDuke shows an error message.

      Use case ends.

Use case: Manage a project (UC03)

MSS

  1. User requests to view all projects.

  2. ArchDuke shows a list of all projects with their respective details.

  3. User requests to manage a project specified in the list.

  4. ArchDuke opens up the specified project.

    Use case ends.

Extensions

  • 2a. The list is empty.

    Use case ends.

  • 3a. The given index is invalid.

    • 3a1. ArchDuke shows an error message.

      Use case resumes at step 2.

Use case: Add members to a specific project (UC04)

MSS

  1. User selects a specific project to manage (UC03).

  2. User enters command to add member specifying at least the member’s name. Phone number and email address are optional.

  3. ArchDuke adds specified member into current project.

    Use case ends.

Extensions

  • 2a. The given information (member details) is invalid.

    • 2a1. ArchDuke shows an error message.

      Use case resumes at step 1.

  • 2b. The user enters the name of a member already in the project.

    • 2b1. ArchDuke shows an error message informing user of existing member.

Use case: Edit members in a specific project (UC05)

MSS

  1. User selects a specific project to manage (UC03).

  2. User requests to edit member specifying member index and fields that require editing.

  3. ArchDuke edits specified fields of specified member in current project.

    Use case ends.

Extensions

  • 2a. The given index is invalid.

    • 2a1. ArchDuke shows an error message prompting user to check again and enter the correct index.

      Use case resumes at step 1.

Use case: Add task in a specific project (UC06)

MSS

  1. User selects a specific project to manage (UC03).

  2. User requests to add task.

  3. ArchDuke adds task to current project.

    Use case ends.

Use case: Edit task in a specific project (UC07)

MSS

  1. User selects a specific project to manage (UC03).

  2. User requests to edit task specifying task index and fields that require editing

  3. ArchDuke edits specified fields of specified task in current project.

    Use case ends.

Extensions

  • 2a. The given index is invalid.

    • 2a1. ArchDuke shows an error message.

      Use case resumes at step 1.

Use case: Assign tasks to members (UC08)

MSS

  1. User selects a specific project to manage (UC03).

  2. User requests to assign/unassign a specific task to one or several members.

  3. ArchDuke assigns/unassigns specified members to specified task in current project.

    Use case ends.

Extensions

  • 2a. User enters invalid index numbers of tasks/members.

    • 2a1. ArchDuke shows error messages indicating invalid index numbers of respective tasks/members.

      Use case resumes from step 2.

  • 2b. User tries to assign task to someone who has already been assigned the task, or unassigns

    • 2b1. ArchDuke shows error message indicating unsuccessful assignments.

      Use case resumes from step 2.

Use case: Complete tasks in a specific project (UC09)

MSS

  1. User selects a specific project to manage (UC03).

  2. User requests to mark a specific task as completed.

  3. ArchDuke marks specified task in current project as completed.

    Use case ends.

Extensions

  • 2a. The given index is invalid.

    • 2a1. ArchDuke shows an error message.

      Use case resumes at step 1.

Appendix D: Instructions for Manual Testing

The following is a summary of all the commands in ArchDuke, and some examples of input. The commands are organised into sections, each relating to a particular feature. There is already some data preloaded into the ArchDuke jar file. You may follow the steps in numerical order to test all the features of ArchDuke.

Note
Inputs in square brackets [EXAMPLE] are optional.

Command Summary and Testing Instructions

Project Commands

  1. Creating projects.

    1. Please use the following commands to create, view or delete projects.

      • Create project: create PROJECT_NAME

        • Example: create Infinity Gauntlet

        • Example: create New Project

      • View projects: list

      • Delete project: delete PROJECT_INDEX

        • Example: delete 3

  2. Managing projects.

    1. Please use this command to select a project you would like to manage. The rest of the commands can only be used after this command is successfully executed. For the purposes of this test, we will manage the project avengers preloaded in the ArchDuke jar file.

      • Manage project: manage PROJECT_INDEX

        • Example: manage 1

  3. Managing members

    1. Please use these commands to manage members in the project. Before starting, ensure that you are managing the project avengers. You may follow the commands provided in sequence to test the member functionalities.

Member Commands

  1. View members: view members

    • To check that member details were updated successfully, you may use view members again at any point in time.

  2. Add members: add member -n NAME [-i PHONE_NUMBER] [-e EMAIL] [-r ROLE]

    • Example: add member -n Cynthia

    • Example: add member -n Jerry Zuang -i 9123456 -e [email protected] -r Lead

  3. Delete members: delete member INDEX1 [INDEX2]

    • Example: delete member 1 2

  4. Edit members: edit member INDEX [-n NAME] [-i PHONE_NUMBER] [-e EMAIL]

  5. Give roles for members: role INDEX -n ROLE_NAME

    • Example: role 2 -n Tester

      1. Managing members

        1. Please use these commands to manage tasks. You may follow these commands in sequence to test task functionalities.

Task Commands You may first view all the tasks existing in the project by using view tasks

  1. Add task: add task -n TASK_NAME -p TASK_PRIORITY [-d TASK_DUEDATE-(dd/mm/yyyy)] -c TASK_CREDIT [-s STATE] [-r TASK_REQUIREMENT1] [-r TASK_REQUIREMENT2]

    • Example: add task -n Hello World Code -p 5 -c 5

    • Example: add task -n Documentation for product -p 2 -d 21/09/2019 -c 40 -r do something -r do another thing -r do another thing

  2. Edit task: edit task TASK_INDEX [-n TASK_NAME] [-p TASK_PRIORITY] [-d TASK_DUEDATE-(dd/mm/yyyy)] [-c TASK_CREDIT] [-s TASK_STATE]

    • Example: edit task 1 -n Finish CS2113 -p 4 -c 80 -d 11/11/2019

    • Example: edit task 2 -n JUnit tests -s doing -c 55 -d 5/11/2019

    • Example: edit task 3 -n Submit UG -s done -d 8/11/2019 -c 35

  3. Delete tasks: delete task INDEX

    • Example: delete task 4 5

  4. View tasks: view tasks MODIFIER

    • The following are examples of MODIFIER suffixes which can be added to be tested.

      • Example: view tasks -state done

      • Example: view tasks -name

      • Example: view tasks -priority

      • Example: view tasks -credits

      • Example: view tasks -date

      • Example: view tasks -who EXISTING_MEMBER_NAME

  5. View task requirements: view task requirements TASK_INDEX

    • Example: view task requirements 2

  6. View task requirements: view task requirements TASK_INDEX

    • Example: view task requirements 1

  7. Edit task requirements: edit task requirements TASK_INDEX [-r TASK_REQUIREMENT_TO_ADD] [-rm TASK_REQUIREMENT_INDEX_TO_REMOVE]

    • Example: edit task requirements 1 -r Testing -r Documentation

    • Example: edit task requirements 1 -rm 1 2 3 -r Submit

  8. Agenda of Tasks: agenda

    1. Assignment Commands

  9. Assign/Unassign members to tasks: assign task -i TASK_INDEX1 [TASK_INDEX2] [-to MEMBER1_INDEX [MEMBER2_INDEX]] [-rm MEMBER3_INDEX [MEMBER4_INDEX]]

    • Example: assign task -i 1 2 -to 1 2

    • Example: assign task -i 2 4 -to 3 4 5

    • Example: assign task -i 1 -to 5 -rm 2

    • Example: assign task -i 3 -to all

  10. View assignments: view assignments MODIFIER

    • Example: view assignments -m all (show all members' tasks)

    • Example: view assignments -m 1 2 (show tasks of member 1 and 2)

    • Example: view assignments -t all (show all the members assigned to a task)

    • Example: view assignments -t 3 4 (show members assigned to tasks 3, 4, 5)

  11. View total credits completed by each member: view credits

    1. Requirement Commands

  12. Create reminder: add reminder -n reminder_NAME [-d TASK_DUEDATE-(dd/mm/yyyy) -l REMINDER_LIST_NAME]

    • Example: add reminder -n Fix important bug -d 21/09/2019 -l Software Reminder List

  13. View reminders: view reminders [by list]

    • Example: view reminders

    • Example: view reminders by list

  14. Delete reminder: delete reminder INDEX_NUMBER

    • Example: delete reminder 1

  15. Edit reminder: edit reminder INDEX_NUMBER -n REMINDER_NAME [-d REMINDER_DUEDATE-(dd/mm/yyyy) -l REMINDER_LIST_NAME]

    • Example: edit reminder 1 -n Fix important bug -d 21/09/2019

  16. Mark reminder: mark reminder INDEX_NUMBER

    • Example: mark reminder 1

      1. Miscellaneous

  17. View current details of project: view

  18. Edit the name of the current project : rename PROJECT_NAME

    • Example: rename Avengers

  19. Report progress : report [coming in v2.0]

  20. Exit managing a project: exit

  21. Exiting the program from anywhere: bye

  22. Display help: help

Appendix E: Non Functional Requirements

  1. ArchDuke should be able to run on any machine with Java Development Kit (JDK 11) installed.

  2. ArchDuke should be able to handle up to a thousand tasks and projects.

  3. ArchDuke should be secure, to prevent unauthorised modification.

  4. ArchDuke should not save passwords in plain text.

  5. ArchDuke should be smooth and fast to view and edit.

  6. ArchDuke output should be organised clearly with proper tabbing.