PROJECT: Modulo


Overview

Modulo is a desktop module management application written for students with fast fingers. A GUI created with JavaFX is also provided. It is written in Java, and has about 16 kLoC.

Summary of contributions

  • Major enhancement: StatefulLogic - Enabling Multistep Commands

    • This feature allows the user to perform elaborate multistep commands by having their inputs build onto what was previously entered.

    • Justification: This feature greatly reduces the amount of repetitive commands that a user needs to enter to achieve the same result. It also helps to connect related processes.

    • Highlights: This feature was implemented from scratch with minimal changes to existing logic and classes, and instead extended on the Command Pattern. The brainstorming and implementation process required an in-depth analysis of design alternatives.

  • Major enhancement: ModuleLibrary - Understanding NUS Module JSONs

    • This feature allows the user to add modules and events using official NUS module data.

    • Justification: This feature makes the app a lot more useful and convenient to use.

    • Highlights: A lot of difficulties were faced when analysing the patterns and inconsistencies within the NUS JSON files. ModuleLibrary now makes sense of the highly nested files to give users the required data meaningfully.

    • Credits: Google’s Gson.

  • Major enhancement: JavaFX - Pleasing to the Eye

    • I designed and built the current GUI for Modulo.

  • Minor enhancement: Storage - Saving Your Progress

    • I adapted the code for the Storage classes to work with the new Model.

Code contributed

My code contributions can be found here: RepoSense Code Dashboard

Other contributions

  • Project Management

    • Managed releases v1.2.1 - v1.4 (9 releases) on GitHub.

    • Managed the issue tracker and milestones v1.1 - v1.4 (7 milestones) on GitHub.

  • Enhancements to Existing Features

    • Designed the mockups for the app using Adobe XD.

    • Wrote tests to increase coverage by 16.5% approximately (PRs #129, #130, #138, #140, #151).

    • Did up JavaDocs: #73, #129.

    • Did cosmetic tweaks to both the app (e.g. app icon) and docs (screenshots).

  • Community:

  • Tools:

    • Integrated and managed the following GitHub plugins:

      • Travis CI - to ensure that our product builds on UNIX platforms: efdb85f

      • AppVeyor - to ensure that our product builds on Windows platforms: 3b5300a

      • Coveralls - to track the coverage of our code: 9846966

      • Codacy - to track the code quality of our project: da9c640

      • Netlify - to deploy a preview of our documentation for PRs

    • Integrated a third party library (GSON) to the project (#54).

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.

Tutorial

Isn’t the empty application just ugly? Let us get your modules into the app in just a matter of minutes!

Multistep Commands

Wait…​ Multistep?

We understand that many may be used to instant, one-step commands when using CLI apps. Here at Modulo, we strongly believe in smooth and seamless user experiences.

Why type the same thing twice when you can do it once, or even never? Modulo builds onto what you’ve already entered, to reduce the amount of typing required, and make everything easier for you!

And for the testers out there: No, we don’t believe this reduces testability. In fact, it helps you jump right into testing the exciting stuff!

In Modulo, some commands are multistep commands. These commands require you to go through all the steps before you can move on to other commands.

You will know you’re in the middle of a multistep command when you see the colour of your command box change:

Multistep

Warning: Quitting the app in the middle of a multistep command will terminate the command! Any undone operations will be lost.

If you’re interested to help us with improving Modulo, do take a look at our Developer Guide!

Adding Our First Module

Our first command, module, is a multistep command! This command helps you to add a module and all of its related events in one go!

Let us start with module m/cs2103! This add CS2103 - Software Engineering into our list of modules.

Now you may see the following prompt:

Multistep

Simply type in your slot and press Enter! For the purposes of this tutorial, we’ll go with slot 3!

You’ll see two changes. Firstly, the event is added:

SlotAdded

Secondly, the command prompt changes:

MultistepLecture

Key in your lecture slot as well. When you see the below message, you know you’re done!

AllSlotsAdded

For users who may be taking CS2103T instead, go ahead and add that instead. You’ll only have your lecture to add, so enter your lecture slot when prompted, e.g. G01.

Viewing the Events we just added

Now that we’ve added our events, it’s time to start planning! Go ahead to switch to the Event list with the following command: list event.

SwitchEventList

You’ll see the events that you just added on the left! Let us try to view the details for Tutorial 2. We just need to type: view 3, where 3 is the index of Tutorial 2!

ViewEvent

Now we get to see the details of the event on the right!

Tutorial 2 is now the focused event. We call the item that is displayed on the right the focused item. For example, earlier, CS2103 was the focused module.

Adding our first Deadline

With Tutorial 2 in focus, we can now add deadlines easily to it. Let’s say we want to practice drawing UML diagrams before the tutorial starts.

We can create a suitable deadline by typing: deadline n/Practice UML Diagrams.

DeadlineAdded

We have now just added the deadline to Tutorial 2, which is the focused event!

Completing our first Deadline

Hopefully, everyone here is hardworking! We’re now done with creating a deadline. How about completing it?

Let us complete the deadline we’ve just added by simply typing: done 2, where 2 is the index of the deadline shown!

DeadlineCompleted

And we’re done with the tutorial!

What next?

Of course, Modulo supports CLI usage, i.e. minimal references to the GUI! For that, our commands have variations that do not depend on the focused item, and commands that reduce the need for scrolling!

Want to find out more? Head over to [Features] now!

Adding a module: module (Multistep)

Adds a module for AY 19/20 Sem 2 to Modulo.
Format: module m/MODULE_CODE

Example:

  • module m/cs2100

This command will kickstart the autopopulation of module events. Refer to our tutorial for more information!

You will be prompted to enter the slot numbers for all events under this module, e.g. tutorial slot 2, lecture slot 1, lab slot 13, etc.

Example of prompts by Modulo:

  • Enter slot for CS2100 Lab:

  • Enter slot for LAJ1201 Tutorial Type Two:

SamplePrompt1
  • Known Issue: There are limitations with module data obtained from NUS. For example, based on official records, some tutorials will start from Week 1, despite actually only starting in Week 3.

  • If you quit Modulo in the middle of this process, your autopopulation will be incomplete! You may have to restart the process by deleting the module and re-adding it. Do see the section on deleting a module below.

Adding an event: event

Adds a custom event to a module. This is perhaps the lengthiest command in Modulo. Events refer to Tutorials, Lectures, Examinations, etc.

Note: You’re only able to add by slot when going through the multistep module command! The event command requires manual entry.

SampleEvents

Format: event m/MODULE_CODE n/EVENT_NAME s/START_DATETIME e/END_DATE v/VENUE [r/REPEAT] [f/FREQUENCY] [until/REPEAT_STOP_DATE]

Limitations:

  • You cannot add events of the same name under a single module.

  • The datetime format recognised is YYYY-MM-DD HH:MM.

  • The date format is YYYY-MM-DD.

  • The start and end times of the event must be within AY 19/20 Sem 2, and the end time must be after the start time.

  • Your event cannot be longer than a day.

  • By default, the event will not repeat.

  • The default repeat frequency (in weeks) is 1 week.

  • If no repeat end datetime is specified, the event will repeat until the end of the semester (Week 16).

Example:

  • event m/CS2103 n/Make Up Tutorial s/2020-01-30 10:00 e/2020-01-30 11:00 v/COM1-B103 r/YES until/2020-05-08

All events with types that are recognised come with a default deadline created.

You can view the full list of event types here.

Pro-tip (GUI-dependent)

If you’re already viewing a module (i.e. focused on a module), you can actually drop the m/MODULE_CODE!

Adding a deadline: deadline

Adds a deadline to an event. This deadline will be due when the event starts.

SampleDeadline

Format: deadline m/MODULE_CODE e/EVENT_NAME n/DEADLINE_NAME [r/REPEAT]

Limitations:

  • Deadlines are due when the event starts!

  • Repeat refers to the creation of the same deadline for events of the same type, occuring after the specified event.

  • By default, the deadline will not repeat.

  • The deadline repeat function only works for events of recognised types, e.g. Tutorial, Lecture etc. This is to prevent the creation of irrelevant deadlines for unrecognised types of events.

Pro-tip (GUI-dependent)

If you’re already viewing an event (i.e. focused on an event), you can actually drop the m/MODULE_CODE AND the e/EVENT_NAME!

Clearing all data: clear

Clears all data from Modulo and starts the app from a clean slate.

Note: This command cannot be undone! So do use it wisely.

Format: clear

UI

Although this app is designed with a fast CLI user in mind, there are UI features that can help to enhance a user’s experience. This may be of use should one’s fingers get tired.

MenuButtons

These buttons perform the equivalent of list modules and list events respectively. Just click them!

Module and Event List

ModuleList

Click on any of these list items to view them on the right panel. They perform the equivalent of view INDEX.

Modules are separated accordingly into their academic years and semesters, and events are separated based on their dates.

Note: There is unfortunately an unfixed bug with how the focus of the UI is handled. After performing an action such as typing into the Command Box or clicking the Menu Buttons, you may need to double click the list item for it to show.

Module Details

ModuleDetails

The right panel displays the details of the module. Only official events added using slots will be listed here.

You can click "Click to view description" to open the Description Window.

Clicking any of the events listed below will also bring you to the first event of that type and slot.

Description Window

DescriptionWindow

This window displays the description of the module.

Known Issue: This is currently the only feature that is only accessible via the UI. This will be updated in subsequent releases.

Event Details

EventDetails

The right panel displays the details of the event. You can check any of the deadlines to mark them as complete or incomplete, performing the equivalent of done INDEX.

The second tag / label indicates whether all deadlines have been completed.

StatusBarFooter

This status bar displays where your data is being saved at. You can head over to that folder to find the .json file for your usage.

Your exported modulo.ics will also be found in the same directory, unless otherwise specified when exporting.

Appendix

Official Event Types

Recognised official event types are:

  • Tutorial

  • Lecture

  • Sectional

  • Seminar

  • Recitation

  • Laboratory

  • Workshop

  • Packaged Tutorial

  • Packaged Lecture

  • Tutorial Type Two

  • Design Lecture

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

ModelClassDiagram
Figure 1. Structure of the Model Component

API : Model.java

The Model,

  • stores a UserPref object that represents the user’s preferences.

  • stores Modulo data.

  • exposes an unmodifiable ObservableList<Module> and ObservableList<Event> that can be 'observed' e.g. the UI can be bound to these lists so that the UI automatically updates when the data in the lists change.

  • does not depend on any of the other three components.

As of now, there are two separate ObservableList being maintained, and with each individual module keeping its own list of events as well. In the future, to better enable the concept of a single source of truth, we can discard the use of a ObservableList<Event> and expose solely the unmodifiable ObservableList<Module>, and have events accessed through its parent module.

BetterModelClassDiagram

Alternatively, we can remove the list of events under each module and instead just maintain the two separate UniqueModuleList and UniqueEventList. This may, however, make it costly to render the module list, since we now need to search through the entire list of events to find relevant ones.

Stateful Logic Feature

Multistep commands are facilitated by StatefulLogic. It is an interface with three methods exposed, and currently only has one class implementing it, AddModuleStatefulLogicManager.

StatefulLogicClassDiagram
Figure 2. Structure of the Stateful Logic Component

Let us understand how StatefulLogic works.

How StatefulLogic works

As long as a StatefulLogicManager, which is a class that implements StatefulLogic, has state, it will take over the LogicManager in executing the given String.

AddModuleHasStateSequenceDiagram
Figure 3. The current implementation

Should there be more StatefulLogicManager instances in play, we will see something like this:

MultipleHasStateSequenceDiagram
Figure 4. If more Stateful Logic Managers are added

At any point of time, only one StatefulLogicManager will have state. The LogicManager will thus check through them one by one, and will only directly parse the command itself should no StatefulLogicManager have state. We can think of these StatefulLogicManager as "consumers" that consume the input if it has state.

The abstraction of how these StatefulLogicManager execute the given String helps to maintain the Single Responsibility Principle. The interaction between the LogicManager and StatefulLogicManager is also facilitated through the interface, StatefulLogic, which upholds the Dependency Inversion Principle.

How state is loaded and maintained

State is loaded into StatefulLogicManager using special CommandResult subclasses. In the instance of the AddModuleStatefulLogicManager, its state is loaded by passing a AddModuleCommandResult into its loadStateFromCommandResult method.

Let us take a look at the full process, using AddModuleCommand as an example:

AddModuleOverviewSequenceDiagram
Figure 5. Executing the module m/CS2103 command

There is no difference for the first part from a regular Command execution. The differences lie in the state preparation and state loading.

StatePreparationSequenceDiagram
Figure 6. State Preparation for AddModuleCommandResult

The state is prepared during the initialising command, and that command will pack that state into a special subclass of CommandResult. This CommandResult is then passed back to the default LogicManager.

State loading is then done, if suitable.

StateLoadingSequenceDiagram
Figure 7. State Loading for AddModuleStatefulLogicManager

The eventList is passed on to the AddModuleStatefulLogicManager to be used as state. As long as the list is not empty, it is considered to have state.

Design Considerations

Aspect: How StatefulLogic should be positioned with respect to Logic
  • Alternative 1 (current choice): Have StatefulLogic exist as a sub-logic-circuit within Logic that activates when conditions are met.

    • Pros: Reduce repeated code (DRY) and adheres to the Open Closed Principle, since the use of a simple interface makes it easy to create future StatefulLogic classes and integrate them.

    • Cons: Logic now has to take care of checking for state prior to execution of command, as well as follow up on special subclasses of CommandResult, thus violating the Single Responsibility Principle.

  • Alternative 2: Have StatefulLogic extend Logic and have a separate LogicDispatcher class that decides which Logic to dispatch the command to.

    • Pros: Seems to follow the Single Responsibility Principle better.

    • Cons: A lot of repeated code, and to some extent, this may be an adaptation of the current implementation, where the Logic class acts as the LogicDispatcher. Furthermore, it may not be correct to say that Logic and StatefulLogic are similar. StatefulLogic does operate quite differently from Logic.

  • Future Extension: It may be worth looking into this and find a better way to handle this logic without breaking the existing Command Pattern. There may be more similarities that can be abstracted out and maximised using OOP.

Aspect: How multistep commands should be implemented and achieved
  • Alternative 1 (current choice): Use StatefulLogic to keep relevant states and logic together.

    • Pros: Uses OOP to reduce complexity. Adheres to the Open Closed Principle, since each class can just implement StatefulLogic, and the exact management of its state is open.

    • Cons: Logic now needs to handle the pre and post-command logic.

  • Alternative 2: Maintain a global state that Logic listens to when executing commands.

    • Pros: All commands can push state to this global state without having to go through Logic, reducing the pre and post-command handling.

    • Cons: The implementation of this global state will be highly complex, since the logic required for different states is different as well. Logic would be overwhelmed. If a new type of state is required, the changes required will be heavy as well, thus violating the Open Closed Principle.

[Proposed] Edit Feature

Currently, Modulo does not allow for the editing of the details of events and deadlines that have been created.

Proposed Implementation

The Edit functionality will be achieved through the introduction of an EditCommand and its parser EditCommandParser.

EditCommandClassDiagram

The edit command will have the following format:

  • Editing events: edit n/EVENT_NAME m/MODULE_CODE [nn/NEW_NAME] [s/NEW_START_DATETIME] [e/NEW_END_DATETIME] [v/NEW_VENUE]

  • Editing deadlines: edit d/INDEX m/MODULE_CODE e/EVENT_NAME nn/NEW_NAME

The flow of the command parsing will be as such:

EditCommandActivityDiagram

If an EditCommand is successfully created, it will be executed on the Model. It will work mainly through the setEvent method already exposed in the Model interface, as well as a setDeadline that will be exposed through the parent event.

Here’s an example of how it may look like if the EditCommand was to modify an event’s venue.

User input: edit n/Tutorial 1 m/CS2103 v/Home

EditCommandSequenceDiagram

Limitations

Due to the fact that repeated events are not currently being tagged or grouped in any way, it is difficult to allow mass editing of repeated events.

If there’s a need to edit a repeated event, there would be a need to edit the events one by one.

Design Considerations

Aspect: How to easily modify deadlines
  • Alternative 1 (current choice): Manually fetch the deadline from the event and replace.

    • Pros: Easy to implement.

    • Cons: May have slight performance issues in terms of speed, and a lot of coding to be done.

  • Alternative 2: Consolidate the deadlines in a UniqueDeadlineList.

    • Pros: Less code to write for this feature specifically, in terms of the setDeadline method.

    • Cons: Increases complexity of the application, since now three lists are maintained. There is also the same issue with events and modules in terms of the source of truth.

Use case: UC01 - Add a deadline

MSS Preconditions: Module data file is loaded properly.
Guarantees: Deadline is added under the correct module and event, with the correct details.

  1. User adds a module (UC02).

  2. User adds a deadline to the correct module and event, with all the required details.

  3. Modulo shows the newly created deadline.

    Use case ends.

Extensions

  • 2a. User enters incorrect information.

    • 2a1. Modulo shows user the correct format for the deadline creation.

    • 2a2. User enters new information following the correct format.

      Use case resumes from step 3.

Use case: UC02 - Add a module

MSS Preconditions: Module data files are loaded properly.
Guarantees: Module is added to the user’s Modulo.

  1. User enters a module code, e.g. CS2103.

  2. Modulo searches its data files for the module and creates the module using information from the data files.

  3. Modulo prompts user to enter the slot for an event type.

  4. User enters their slot for the event type.
    Steps 3-4 are repeated for as many times as required until the User has entered slots for all event types of the module.

  5. Modulo shows the newly created module.

    Use case ends.

Extensions

  • 1a. User enters incorrect data and the wrong module is found.

  • 1b. User enters invalid data and no modules are found.

    • 1b1. Modulo informs User that no modules with the given information can be found.

    • 1b2. Step 1 repeated until User enters a correct module code.

      Use case resumes from step 2.

  • 3a. User added a module with no events.

    • Use case resumes from step 5.

  • 3b. User exited Modulo before adding all events.

    • 3b1. Modulo saves all events that were already added.

      Use case ends.

  • 4a. User enters an invalid slot.

    • 4a1. Modulo cancels the request by the User.

    • 4a2. Modulo informs the User of the cancellation.

      Use case ends.

Appendix A: Instructions for Manual Testing

Given below are instructions to test the app manually.

These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.

Launch and Shutdown

  1. Initial launch

    1. Download the jar file and copy into an empty folder

    2. Double-click the jar file
      Expected: Shows the GUI with no data. The window size may not be optimum.

  2. Saving window preferences

    1. Resize the window to an optimum size. Move the window to a different location. Close the window.

    2. Re-launch the app by double-clicking the jar file.
      Expected: The most recent window size and location is retained.

  3. Shutting down

    1. Launch the help window by typing help.

    2. Quit the app by typing exit.
      Expected: Both the main window and the help window should close.

Adding a module

  1. Adding CS2103

    1. Prerequisites: CS2103 not already added. If added, delete it.

    2. Test case: module m/cs2103
      Expected: CS2103 to appear in the list of modules, and app to prompt for further input.

    3. If prompt is for tutorial, test case: 3
      Expected: Tutorial slot 3 should be added.

    4. If prompt is for lecture, test case: 1
      Expected: Lecture slot 1 should be added.

Adding an event

  1. Adding Exam to CS2103

    1. Prerequisites: CS2103 already added. No event named Exam has been added to CS2103 yet.

    2. Test case: event n/Exam m/CS2103 s/2020-01-15 09:00 e/2020-01-15 10:00 v/Home
      Expected: Event named Exam should appear in the list of events. To check, enter list events. It should be near the top of the list. The details should be as entered.

  2. Adding recurring events to CS2103

    1. Prerequisites: CS2103 already added. No recurring event named Self Study has been added to CS2103 yet.

    2. Test case: event n/Self Study m/CS2103 s/2020-01-20 09:00 e/2020-01-20 10:00 v/Home r/YES until/2020-02-20
      Expected: Events named Self Study 1, Self Study 2, until Self Study 5 should appear, with a frequency of 1 week, and stopping before 2020-02-20.

Adding a deadline

  1. Adding a deadline to CS2103 Exam

    1. Prerequisites: CS2103 added. Event named Exam added. No deadline named "Study hard for exam" has been added to the event yet.

    2. Test case: deadline n/Study hard for exam m/CS2103 e/Exam
      Expected: Deadline added to Exam. To check, first make sure you’re listing events with list events, then enter view INDEX, where INDEX is the index of the event on the list.

Completing a deadline

  1. Complete Study hard for exam.

    1. Prerequisites: CS2103 added. Event named Exam added. Deadline named Study hard for exam added, and is not completed.

    2. Test case: done 2 m/CS2103 e/Exam
      Expected: Deadline named Study hard for exam is completed.

Switching lists

  1. List events

    1. Test case: list events
      Expected: If not already listing events, events will now be listed.

  2. List modules

    1. Test case: list modules
      Expected: If not already listing modules, modules will not be listed.

View event or module

  1. View module

    1. Prerequisite: List all modules using the list modules command. At least one module.

    2. Test case: view 1
      Expected: Details of the first module should show on the right panel.

  2. View event

    1. Prerequisite: List all events using the list events command. At least one event.

    2. Test case: view 1
      Expected: Details of the first event should show on the right panel.

Find event or module

  1. Find event(s) with Self Study in their names

    1. Prerequisite: List all events using the list events command. Has event(s) named Self Study.

    2. Test case: find self study
      Expected: All events with Self Study in their names would appear. You can operate on this filtered list.

  2. Find Software Engineering

    1. Prerequisite: List all modules using the list modules command. CS2103 added.

    2. Test case: find software engineering
      Expected: CS2103 should show, along with any other modules that may have Software Engineering in their names.

Deleting a module

  1. Deleting a module using index while all modules are listed

    1. Prerequisites: List all modules using the list modules command. Multiple modules in the list.

    2. Test case: delete 1
      Expected: First module is deleted from the list. All events of that module are deleted. Details of the deleted module shown in the status message.

    3. Test case: delete 0
      Expected: No module is deleted. No events deleted. Error details shown in the status message.

    4. Other incorrect delete commands to try: delete, delete x (where x is larger than the list size).
      Expected: Similar to previous.

  2. Deleting a module using search terms while all modules are listed

    1. Prerequisites: List all modules using the list modules command. CS2103 in the list. Other CS modules in the list.

    2. Test case: delete CS2103
      Expected: CS2103 is deleted from the list. Details of the deleted module shown in the status message.

    3. Test case: delete cs
      Expected: All CS modules are deleted. Number of deleted modules shown in the status message.

    4. Test case: delete cs2999
      Expected: No module is deleted. Information shown in the status message.

    5. Other incorrect delete commands to try: delete x (where x is a term that does not exist in the list).
      Expected: Similar to previous.

Deleting an event

  1. Deleting an event using index while all events are listed

    1. Prerequisites: List all events using the list events command. Multiple events in the list.

    2. Test case: delete 1
      Expected: First event is deleted from the list. Details of the deleted event shown in the status message.

    3. Test case: delete 0
      Expected: No event is deleted. Error details shown in the status message.

    4. Other incorrect delete commands to try: delete, delete x (where x is larger than the list size).
      Expected: Similar to previous.

  2. Deleting an event using search terms while all events are listed

    1. Prerequisites: List all events using the list events command. At least one Tutorial 1 in the list. Other Tutorials in the list as well.

    2. Test case: delete Tutorial 1
      Expected: All events with Tutorial 1 in their names are deleted from the list. Number of deleted events shown in the status message.

    3. Test case: delete Tutorial
      Expected: All Tutorials are deleted. Number of deleted events shown in the status message.

    4. Test case: delete Tvtor!al
      Expected: No event is deleted. Information shown in the status message.

    5. Other incorrect delete commands to try: delete x (where x is a term that does not exist in the list).
      Expected: Similar to previous.

Deleting a deadline

  1. Deleting a deadline using index while an event is focused

    1. Prerequisites: List all events using the list events command. Events in the list. View first event with view 1. First event has a deadline.

    2. Test case: delete d/1
      Expected: First deadline is deleted from the list. Details of the deleted deadline shown in the status message.

    3. Test case: delete 0
      Expected: No deadline is deleted. Error details shown in the status message.

    4. Other incorrect delete commands to try: delete, delete x (where x is larger than the list size).
      Expected: Similar to previous.

Exporting data as .ics file

  1. Export data

    1. Test case: export
      Expected: A modulo.ics file should be created in the same ./data/ folder. You can use this .ics file to add your events and deadlines into your calendar.

Viewing help

  1. View help

    1. Test case: help
      Expected: Help window appears.

Clearing Modulo

  1. Clear all existing data in Modulo

    1. Prerequisites: Some data has been added to Modulo.

    2. Test case: clear
      Expected: All data cleared.

Saving data

  1. Dealing with missing/corrupted data files

    1. Corrupt the current save file under ./data/. The easiest way is to type - somewhere in one of the saved modules' academic year. Another way may be to add random characters that make the JSON format unreadable.

    2. Double-click the jar file
      Expected: Shows the GUI with no data.

    3. Delete the current save file under ./data/.

    4. Double-click the jar file
      Expected: Shows the GUI with no data.