PROJECT: MINDEF Duty Planner


Overview

MINDEF Duty Planner is a platform to assist military units in the SAF in the assignment of daily duties amongst the servicemen. The application 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). The software is designed to automate the process of fairly assigning duties to available servicemen for an entire month. It also enables servicemen to conveniently indicate the days they are unavailable for duty. It seeks to fairly distribute duties by taking into account the varying importance of each duty (e.g. Sunday duties are worth more than weekday duties).

Summary of contributions

  • Major enhancement: Added the ability to request swapping of duties (using the 'swap' command), respond to swap requests (using the 'acceptSwap' command), view paired swaps (using the 'viewSwaps' command) and approve or reject swap requests (using the 'approveSwap' or 'rejectSwap' command).

    • What it does: allows a user who is a particular person in the personnel database to request for a swap of his duty with another person’s duty. Both duties have to be in the next month.

    • Justification: This feature is very useful for a serviceman who is suddenly unavailable to perform guard duty due to ad hoc reasons. He can broadcast his swap request onto the app in the large panel on the bottom right and other servicemen can view his request and respond if they are willing and able to swap with him. After that, an admin user will approve or reject the swap.

    • Highlights: This functionality is very convenient for the users because it requires no verbal communication at all and the process is completely streamlined to be performed on the app. Physical or verbal communication is only necessary if there are disputes. This enhancement involves changes in logic (commands), UI (browser panel), storage (storing of requests) and model (structure of requests). Implementing this feature required understanding how and when saving to a json file happens so as to trigger the save event when needed. It was also difficult to convert the browser panel from an object that displays web pages to a text object, having no prior experience in GUI.

    • Credits: Valavan for the idea of swap requests and my team for helping me to develop the idea

  • Minor enhancement: Converted the Person class to one suitable for the duty planner. This means removing the email and address fields (which are classes in themselves) and adding in Company, Section, Rank and NRIC. This was very time-consuming, especially with having to adapt all the tests involving Person objects with no exception. We could theoretically have done away with the individual classes for each field but I decided to preserve the existing structure to reduce complications after analysis of the trade-offs.

  • Minor enhancement: Morphed the browser panel to display the list of open swap requests (i.e swap requests that are awaiting response) instead of a website.

  • Code contributed: [Code]

  • Other contributions:

    • Project management:

      • Curated Issues Tracker

    • Enhancements to existing features:

      • Renamed the internal address book class to personnel database to reflect our product differentiation: #33, #70, #71

      • Added and edited tests for existing features (example: JsonAdaptedPersonTest.java, see #34, #70, #71)

    • Documentation:

      • Edited the User Guide to reflect our product: #33, #71

    • Community:

      • Reported bugs and suggestions for other teams in the class (examples: 1, 2, 3, 4)

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.

Make an open swap request : swap

The user can request for a duty swap with another user for the next month by keying in his current duty date and his requested date. This request will appear on the browser panel on the bottom right of the app for all to see. Another user can use the acceptSwap command to agree to the swap request. This is then subject to the approval of an admin user (i.e. commander).

Format: `swap ad/ALLOCATEDDUTYDATE (DDMMYY) rd/REQUESTEDDUTYDATE (DDMMYY)

  • The command is only valid if the user has a duty allocated on the ad/ date and does not have a duty on the rd/ date. Otherwise, an error message will be shown.

  • At the start of a new month, all existing swaps, open or paired, will be deleted.

  • The user must refrain from requesting for two swaps for a duty on the same day. The code to restrict this behaviour will be implemented in v2.0.

Example:

  • swap ad/140219 rd/210219

Accept Swap Command : acceptSwap

The user can use this command to respond to and accept a certain swap at the given index on the open swap request list in the browser panel.

Format : acceptSwap INDEX

  • The command is only valid if the user has a duty allocated on the rd/ date and does not have a duty on the ad/ date. Otherwise, an error message will be shown.

  • A non-positive index or an index which exceeds the list size will result in an error message.

  • At the start of a new month, all existing swaps, open or paired, will be deleted.

  • The user must refrain from accepting two swaps for a duty on the same day. The code to restrict this behaviour will be implemented in v2.0.

Example:

  • 'acceptSwap 1'

View Swaps Command : viewSwaps

Used to view all the swap requests that have a requester-accepter pair. The list will be shown in the results display. The Admin User can then accept or reject the swap using the AcceptSwap or RejectSwap command.

Format : viewSwaps

Approve Swap Command : approveSwap

The Admin User can use this command to approve a certain swap at the given index in the list of paired swap requests in the results display after a viewSwaps command. This will edit the duties in the schedule as well as the points for each user. Thereafter, the request will be deleted.

Format : approveSwap INDEX

  • A non-positive index or an index which exceeds the list size will result in an error message.

  • At the start of a new month, all existing swaps, open or paired, will be deleted.

  • The users involved in the swap request must refrain from making or accepting two swaps for a duty on the same day. The code to restrict this behaviour will be implemented in v2.0.

  • The approve swap request will still work even if the list is not showing at the results display. The index will refer to the request that would be in the list if the list were displayed (The order of the list does not change)

Example: 'approveSwap 1'

Reject Swap Command : rejectSwap

The Admin User can use this command to reject a certain swap at the given index in the list of paired swap requests in the results display after a viewSwaps command. Thereafter, the request will be deleted.

Format : rejectSwap INDEX

  • A non-positive index or an index which exceeds the list size will result in an error message.

  • At the start of a new month, all existing swaps, open or paired, will be deleted.

  • The users involved in the swap request must refrain from making or accepting two swaps for a duty on the same day. The code to restrict this behaviour will be implemented in v2.0.

  • The reject swap request will still work even if the list is not showing at the results display. The index will refer to the request that would be in the list if the list were displayed (The order of the list does not change)

Example:'rejectSwap 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.

Request for swapping of duties

Current Implementation

Swap Request Creation

SwapRequestSequenceDiagram

There is currently a Java class called Request in the request folder in the model package. This request represents a swap request that a duty personnel submits using the 'swap' command. It has 4 fields, the requester Person object, the allocated date (out of which the requester wants to swap) as a java.time.LocalDate object, the requested date (into which the requester wants to swap) also as a LocalDate object, and the accepter Person object, which could be null.

A Request object is created when the 'swap' command is entered by a non-master-admin user. Since he is an actual human user with an associated Person object and NRIC, he is able to request a swap if he is unwilling or unable to do his current allocated duty. This must happen after the duties are scheduled. Otherwise, the list of duties associated with the user is empty and a swap request cannot be made.

The swap command is wrapped in a SwapCommand object that extends the abstract class Command, just like any other command. The user inputs 2 dates, his allocated and requested date, and the 2 dates are parsed as LocalDate objects, from which the Request object is made.

Thereafter, the Request object is added to the personnel database through the model so the personnel database now contains the request in a list.

After this, the new personnel database is committed (making it undoable) and the listener in LogicManager is informed. As a result, the new personnel database is saved into the JSON file. Finally, the browser panel is refreshed to reflect the newest request list.

The browser panel was transformed from implementing FXML WebView to FXML TextArea. After the request list is updated, a new string is passed to the TextArea field for it to display in the browser panel.

Accept Swap Command

Next, there is a command 'acceptSwap' that allows a non-master-admin user to accept a swap that another user has requested (we call this an open swap.) The list of open swaps would be on the list in the browser panel and the 'acceptSwap' command takes in a positive integer as argument and this integer refers to the index number of the request in the request list.

Again, this is encapsulated in an AcceptSwapCommand object, which extends the abstract Command class. An AcceptSwapCommand constructor takes in the index mentioned above and the username (i.e NRIC) of the current user. It sets the accepter Person in the relevant Request object to be the current user.

View Swaps Command

The 'viewSwaps' command is only for admin users. It takes in no arguments and it is for admin users to view all the swap requests which have found an accepter (From now on we call these paired requests.) This command is encapsulated in the ViewSwapsCommand object. When this ViewSwapsCommand object is executed by the LogicManager, a string showing all the paired requests pending approval is generated and passed into the TextArea of the ResultDisplay. This allows the admin user to view the requests and then proceed to approve or reject them.

Approve / Reject Swap Command

The admin user can then use 'approveSwap' or 'rejectSwap' to approve or reject a paired swap in the list displayed in the ResultDisplay after executing the viewSwaps command. These are encapsulated in the ApproveSwapCommand and RejectSwapCommand classes.

Design Considerations

Aspect : Nature of swap request

Alternative 1 (current choice):

  • Allow users to submit an open swap request, giving only their allocated date and requested date. This is then broadcast onto the app for other users to view.

    • Pros: Everything is done on the app and the user doesn’t have to go around asking everyone if they are available to swap.

    • Cons: More steps in the process. 3 step process: request swap, accept swap, approve/reject swap.

Alternative 2:

  • Users are to find a swap partner offline before requesting a swap, keying in the 2 dates and the partner’s NRIC. This request will then go straight to the admin for approval.

    • Pros: Simpler implementation

    • Cons: The admin needs to verify with the accepter if he really accepted the swap.

Aspect: Container for Requests

Alternative 1 (current choice):

  • Requests are contained in a list in the personnel database, with each request containing its requester’s Person object and its accepter’s Person object, if present.

    • Pros: The requests can be easily looked up and the persons found within them.

    • Cons: When the edit command is executed, the program needs to iterate through the entire list of requests to update the relevant person to a new Person object.

Alternative 2:

  • Requests are stored inside a Person object, presumably the requester’s Person object.

    • Pros: This eliminates the need for the Request object to store the requester and a person’s requests can be easily looked up. When a person is deleted, their requests will be deleted along with it, which is very convenient.

    • Cons: If the accepter Person does not contain the request that he accepted, it would be even more complicated to find his request. The program would need to look through every person, in which every request is looked up to find the right accepter.

Aspect: Viewing of Open Swap Requests

Alternative 1 (current choice):

  • Display the list of open swap requests in the browser panel for all to see.

    • Pros: Wide viewership. A user can easily advertise his swap request.

    • Cons: -

Alternative 2:

  • Create a command for personnel to view open swap requests

    • Pros: The browser panel can be used for something else.

    • Cons: No incentive for users to view open swap requests.