diff --git a/README.md b/README.md index 13f5c77403f..d887eeab911 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,14 @@ -[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions) +[![CI Status](https://github.com/AY2223S1-CS2103T-T15-4/tp/workflows/Java%20CI/badge.svg)](https://github.com/AY2223S1-CS2103T-T15-4/tp/actions) +[![codecov](https://codecov.io/gh/AY2223S1-CS2103T-T15-4/tp/branch/master/graph/badge.svg?token=3QLCJGGTH7)](https://codecov.io/gh/AY2223S1-CS2103T-T15-4/tp) +[![Pages](https://github.com/AY2223S1-CS2103T-T15-4/tp/actions/workflows/pages/pages-build-deployment/badge.svg)](https://github.com/AY2223S1-CS2103T-T15-4/tp/actions/workflows/pages/pages-build-deployment) ![Ui](docs/images/Ui.png) -* This is **a sample project for Software Engineering (SE) students**.
+* Gim is a **desktop app for managing gym exercises, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, Gim allows you to keep track your exercises and Personal Records in a efficient way. Example usages: - * as a starting point of a course project (as opposed to writing everything from scratch) - * as a case study -* The project simulates an ongoing software project for a desktop application (called _AddressBook_) used for managing contact details. - * It is **written in OOP fashion**. It provides a **reasonably well-written** code base **bigger** (around 6 KLoC) than what students usually write in beginner-level SE modules, without being overwhelmingly big. - * It comes with a **reasonable level of user and developer documentation**. -* It is named `AddressBook Level 3` (`AB3` for short) because it was initially created as a part of a series of `AddressBook` projects (`Level 1`, `Level 2`, `Level 3` ...). -* For the detailed documentation of this project, see the **[Address Book Product Website](https://se-education.org/addressbook-level3)**. + * as a tracking tool to keep track of completed exercises + * as a tracking tool to keep track of your personal records + * as a workout generator to generate exercises based on your personal records +* It is named `Gim` as a name-play tribute to `Vim` and `Gym`. +* For the detailed documentation of this project, see the **[Gim Product Website](https://ay2223s1-cs2103t-t15-4.github.io/tp/)**. * This project is a **part of the se-education.org** initiative. If you would like to contribute code to this project, see [se-education.org](https://se-education.org#https://se-education.org/#contributing) for more info. diff --git a/build.gradle b/build.gradle index 108397716bd..08c1600fb1a 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,7 @@ plugins { id 'jacoco' } -mainClassName = 'seedu.address.Main' +mainClassName = 'gim.Main' sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 @@ -66,7 +66,11 @@ dependencies { } shadowJar { - archiveFileName = 'addressbook.jar' + archiveFileName = 'gim.jar' +} + +run { + enableAssertions = true } defaultTasks 'clean', 'test' diff --git a/config/checkstyle/checkstyle.xml b/config/checkstyle/checkstyle.xml index d618671b832..2a2c82ed494 100644 --- a/config/checkstyle/checkstyle.xml +++ b/config/checkstyle/checkstyle.xml @@ -385,10 +385,10 @@ JAVADOC CHECKS --> - + - + @@ -400,7 +400,7 @@ - + diff --git a/copyright.txt b/copyright.txt index 93aa2a39ce2..5d9601c9b13 100644 --- a/copyright.txt +++ b/copyright.txt @@ -1,7 +1,7 @@ Some code adapted from http://code.makery.ch/library/javafx-8-tutorial/ by Marco Jakob Copyright by Susumu Yoshida - http://www.mcdodesign.com/ -- address_book_32.png +- exercise_tracker_32.png - AddressApp.ico Copyright by Jan Jan Kovařík - http://glyphicons.com/ diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 1c9514e966a..559b42ffef1 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -7,53 +7,51 @@ We are a team based in the [School of Computing, National University of Singapor You can reach us at the email `seer[at]comp.nus.edu.sg` +[[homepage](https://ay2223s1-cs2103t-t15-4.github.io/tp/)] + ## Project team -### John Doe +### Donovan Lee Jun Hao - + -[[homepage](http://www.comp.nus.edu.sg/~damithch)] -[[github](https://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](https://github.com/24Donovan24)] +[[portfolio](team/24donovan24.md)] -* Role: Project Advisor +* Role: Developer -### Jane Doe +### Ervin Kin Zhe Zheng - + -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](https://github.com/ErvinK123)] +[[portfolio](team/ervink123.md)] -* Role: Team Lead -* Responsibilities: UI +* Role: Developer -### Johnny Doe +### Kavan Tan - + -[[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)] +[[github](http://github.com/kavantan)] +[[portfolio](team/kavantan.md)] * Role: Developer -* Responsibilities: Data -### Jean Doe +### Kok Ee Suan - + -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](http://github.com/ee-suan)] +[[portfolio](team/ee-suan.md)] * Role: Developer -* Responsibilities: Dev Ops + Threading -### James Doe +### Steven Lim - + -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](http://github.com/stevenlimhw)] +[[portfolio](team/stevenlimhw.md)] * Role: Developer -* Responsibilities: UI diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 46eae8ee565..9f41d936241 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -2,14 +2,24 @@ layout: page title: Developer Guide --- + +

+ +

+ +
+ +**Table of Contents** * Table of Contents {:toc} -------------------------------------------------------------------------------------------------------------------- +
## **Acknowledgements** -* {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} +* Gim is adapted from the [AddressBook-Level3](https://se-education.org/addressbook-level3/) project created by the SE-EDU initiative. +* Libraries used: [JavaFX](https://openjfx.io/), [Jackson](https://github.com/FasterXML/jackson), [JUnit5](https://github.com/junit-team/junit5) -------------------------------------------------------------------------------------------------------------------- @@ -19,6 +29,8 @@ Refer to the guide [_Setting up and getting started_](SettingUp.md). -------------------------------------------------------------------------------------------------------------------- +
+ ## **Design**
@@ -36,7 +48,7 @@ Given below is a quick overview of main components and how they interact with ea **Main components of the architecture** -**`Main`** has two classes called [`Main`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/Main.java) and [`MainApp`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/MainApp.java). It is responsible for, +**`Main`** has two classes called [`Main`](https://github.com/AY2223S1-CS2103T-T15-4/tp/blob/master/src/main/java/gim/Main.java) and [`MainApp`](https://github.com/AY2223S1-CS2103T-T15-4/tp/blob/master/src/main/java/gim/MainApp.java). It is responsible for, * At app launch: Initializes the components in the correct sequence, and connects them up with each other. * At shut down: Shuts down the components and invokes cleanup methods where necessary. @@ -52,7 +64,7 @@ The rest of the App consists of four components. **How the architecture components interact with each other** -The *Sequence Diagram* below shows how the components interact with each other for the scenario where the user issues the command `delete 1`. +The *Sequence Diagram* below shows how the components interact with each other for the scenario where the user issues the command `:del 1`. @@ -61,186 +73,461 @@ Each of the four main components (also shown in the diagram above), * defines its *API* in an `interface` with the same name as the Component. * implements its functionality using a concrete `{Component Name}Manager` class (which follows the corresponding API `interface` mentioned in the previous point. +
+ For example, the `Logic` component defines its API in the `Logic.java` interface and implements its functionality using the `LogicManager.java` class which follows the `Logic` interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component's being coupled to the implementation of a component), as illustrated in the (partial) class diagram below. The sections below give more details of each component. +
+ ### UI component -The **API** of this component is specified in [`Ui.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/Ui.java) +The **API** of this component is specified in [`Ui.java`](https://github.com/AY2223S1-CS2103T-T15-4/tp/blob/master/src/main/java/gim/ui/Ui.java) ![Structure of the UI Component](images/UiClassDiagram.png) -The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class which captures the commonalities between classes that represent parts of the visible GUI. +The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `ExerciseListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class which captures the commonalities between classes that represent parts of the visible GUI. -The `UI` component uses the JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the [`MainWindow`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/resources/view/MainWindow.fxml) +The `UI` component uses the JavaFx UI framework. The layout of these UI parts are defined in matching `.fxml` files that are in the `src/main/resources/view` folder. For example, the layout of the [`MainWindow`](https://github.com/AY2223S1-CS2103T-T15-4/tp/blob/master/src/main/java/gim/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/AY2223S1-CS2103T-T15-4/tp/blob/master/src/main/resources/view/MainWindow.fxml) The `UI` component, * executes user commands using the `Logic` component. * listens for changes to `Model` data so that the UI can be updated with the modified data. * keeps a reference to the `Logic` component, because the `UI` relies on the `Logic` to execute commands. -* depends on some classes in the `Model` component, as it displays `Person` object residing in the `Model`. +* depends on some classes in the `Model` component, as it displays `Exercise` object residing in the `Model`. + +
### Logic component -**API** : [`Logic.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/logic/Logic.java) +**API** : [`Logic.java`](https://github.com/AY2223S1-CS2103T-T15-4/tp/blob/master/src/main/java/gim/logic/Logic.java) Here's a (partial) class diagram of the `Logic` component: How the `Logic` component works: -1. When `Logic` is called upon to execute a command, it uses the `AddressBookParser` class to parse the user command. -1. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `AddCommand`) which is executed by the `LogicManager`. -1. The command can communicate with the `Model` when it is executed (e.g. to add a person). -1. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`. +1. When `Logic` is called upon to execute a command, it uses the `ExerciseTrackerParser` class to parse the user command. +2. This results in a `Command` object (more precisely, an object of one of its subclasses e.g., `AddCommand`) which is executed by the `LogicManager`. +3. The command can communicate with the `Model` when it is executed (e.g. to add an exercise). +4. The result of the command execution is encapsulated as a `CommandResult` object which is returned back from `Logic`. -The Sequence Diagram below illustrates the interactions within the `Logic` component for the `execute("delete 1")` API call. +
-![Interactions Inside the Logic Component for the `delete 1` Command](images/DeleteSequenceDiagram.png) +The Sequence Diagram below illustrates the interactions within the `Logic` component for the `execute(":del 1")` API call. + +![Interactions Inside the Logic Component for the `:del 1` Command](images/DeleteSequenceDiagram.png)
:information_source: **Note:** The lifeline for `DeleteCommandParser` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.
+
+ Here are the other classes in `Logic` (omitted from the class diagram above) that are used for parsing a user command: How the parsing works: -* When called upon to parse a user command, the `AddressBookParser` class creates an `XYZCommandParser` (`XYZ` is a placeholder for the specific command name e.g., `AddCommandParser`) which uses the other classes shown above to parse the user command and create a `XYZCommand` object (e.g., `AddCommand`) which the `AddressBookParser` returns back as a `Command` object. +* When called upon to parse a user command, the `ExerciseTrackerParser` class creates an `XYZCommandParser` (`XYZ` is a placeholder for the specific command name e.g., `AddCommandParser`) which uses the other classes shown above to parse the user command and create a `XYZCommand` object (e.g., `AddCommand`) which the `ExerciseTrackerParser` returns back as a `Command` object. * All `XYZCommandParser` classes (e.g., `AddCommandParser`, `DeleteCommandParser`, ...) inherit from the `Parser` interface so that they can be treated similarly where possible e.g, during testing. +
+ ### Model component -**API** : [`Model.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/model/Model.java) +**API** : [`Model.java`](https://github.com/AY2223S1-CS2103T-T15-4/tp/blob/master/src/main/java/gim/model/Model.java) The `Model` component, -* stores the address book data i.e., all `Person` objects (which are contained in a `UniquePersonList` object). -* stores the currently 'selected' `Person` objects (e.g., results of a search query) as a separate _filtered_ list which is exposed to outsiders as an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. +* stores the exercise tracker data i.e., all `Exercise` objects (which are contained in a `ExerciseList` and `ExerciseHashMap` object). +* stores the currently 'selected' `Exercise` objects (e.g., results of a search query) as a separate _filtered_ list which is exposed to outsiders as an unmodifiable `ObservableList` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change. * stores a `UserPref` object that represents the user’s preferences. This is exposed to the outside as a `ReadOnlyUserPref` objects. * does not depend on any of the other three components (as the `Model` represents data entities of the domain, they should make sense on their own without depending on other components) -
:information_source: **Note:** An alternative (arguably, a more OOP) model is given below. It has a `Tag` list in the `AddressBook`, which `Person` references. This allows `AddressBook` to only require one `Tag` object per unique tag, instead of each `Person` needing their own `Tag` objects.
- - - -
- +
### Storage component -**API** : [`Storage.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/storage/Storage.java) +**API** : [`Storage.java`](https://github.com/AY2223S1-CS2103T-T15-4/tp/blob/master/src/main/java/gim/storage/Storage.java) The `Storage` component, -* can save both address book data and user preference data in json format, and read them back into corresponding objects. -* inherits from both `AddressBookStorage` and `UserPrefStorage`, which means it can be treated as either one (if only the functionality of only one is needed). +* can save both exercise tracker data and user preference data in json format, and read them back into corresponding objects. +* inherits from both `ExerciseTrackerStorage` and `UserPrefStorage`, which means it can be treated as either one (if only the functionality of only one is needed). * depends on some classes in the `Model` component (because the `Storage` component's job is to save/retrieve objects that belong to the `Model`) ### Common classes -Classes used by multiple components are in the `seedu.addressbook.commons` package. +Classes used by multiple components are in the `gim.commons` package. -------------------------------------------------------------------------------------------------------------------- +
+ ## **Implementation** This section describes some noteworthy details on how certain features are implemented. -### \[Proposed\] Undo/redo feature +### **Exercise** -#### Proposed Implementation +#### Implementation + -The proposed undo/redo mechanism is facilitated by `VersionedAddressBook`. It extends `AddressBook` with an undo/redo history, stored internally as an `addressBookStateList` and `currentStatePointer`. Additionally, it implements the following operations: +An `Exercise` is stored in `ExerciseList` and `ExerciseHashmap` of Model -* `VersionedAddressBook#commit()` — Saves the current address book state in its history. -* `VersionedAddressBook#undo()` — Restores the previous address book state from its history. -* `VersionedAddressBook#redo()` — Restores a previously undone address book state from its history. +An `Exercise` contains the following attributes: +1. a `Name`, which represents the name of the Exercise +2. a `Weight`, which represents the total weight used for a certain Exercise +3. a `Reps`, which represents the number of times a specific exercise was performed +4. a `Sets`, which represents the number of cycles of reps that was completed +5. a `Date`, which represents the date an exercise was performed -These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively. +
-Given below is an example usage scenario and how the undo/redo mechanism behaves at each step. +**Date Implementation** -Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state. + -![UndoRedoState0](images/UndoRedoState0.png) +The default format for date follows `dd/MM/uuuu`. `uuuu` is chosen over `yyyy` because this avoids unexpected exceptions +under strict parsing by the Java API `DateTimeFormatter`, such as those exceptions related to year-of-era. -Step 2. The user executes `delete 5` command to delete the 5th person in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state. +The validity of a given date string depends on two factors: (1) Regex formatting and (2) Non-existent date checking. -![UndoRedoState1](images/UndoRedoState1.png) +1. For the regex formatting, the Singleton class `RegexList` contains a `List` called `regexList` that contains the +accepted regex strings. The method `isValidDateByRegex` iterates through `regexList` to check whether a given date string +follows any of the accepted regex strings. -Step 3. The user executes `add n/David …​` to add a new person. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`. +2. For the non-existent date checking, the Singleton class `FormatterList` contains a `List` called `formatterList` +that contains the accepted date patterns. The private constructor of this class uses stream mapping to obtain a `List` +called `formatterList` containing `DateTimeFormatter` objects that follows strict date validity check using +`ResolverStyle.STRICT`. -![UndoRedoState2](images/UndoRedoState2.png) +The Singleton pattern is used here to prevent multiple instantiation of this class. +1. The drawbacks of using this pattern is not really pronounced as there are not many classes having them as dependencies (only the `Date` class). +Therefore, coupling within the code base will not increase much. +2. Testing will not be affected by the fact that singleton objects carry data from one test to another because there is no mutation +of data inside the singleton objects `RegexList` and `FormatterList`. All tests will have the same singleton objects used. -
:information_source: **Note:** If a command fails its execution, it will not call `Model#commitAddressBook()`, so the address book state will not be saved into the `addressBookStateList`. +
-
+#### Design Considerations -Step 4. The user now decides that adding the person was a mistake, and decides to undo that action by executing the `undo` command. The `undo` command will call `Model#undoAddressBook()`, which will shift the `currentStatePointer` once to the left, pointing it to the previous address book state, and restores the address book to that state. +**Aspect: Fields of Exercise are Final** +* **Current choice**: The aforementioned fields in `Exercise` are final, effectively making our Exercise class immutable. + * Rationale: Code written with immutable objects is easier to reason with and easier to understand, facilitating a smoother process when it comes to debugging and testing any code related to `Exercise`. -![UndoRedoState3](images/UndoRedoState3.png) +
-
:information_source: **Note:** If the `currentStatePointer` is at index 0, pointing to the initial AddressBook state, then there are no previous AddressBook states to restore. The `undo` command uses `Model#canUndoAddressBook()` to check if this is the case. If so, it will return an error to the user rather -than attempting to perform the undo. +### **Exercise Hashmap** -
+#### Implementation +The Exercise Hashmap stores data in the form of a hashmap, where the key of the hashmap is the `Name` of an `Exercise` and its associated value is an `Exercise` ArrayList, containing a list of exercises (with the same name). + +#### Design Considerations + +**Aspect: Choosing the Data Structure** +* **Current choice**: We decided to use a hashmap data structure. + * Rationale: We wanted to create associations between exercises with the same name. Utilising a hashmap structure, we can easily identify and retrieve exercises with the same exercise name (by their unique key identifier). Hence, this facilitates commands that rely on this retrieval to be implemented, such as [Listing of Personal Records](#listing-of-personal-records) and [Generating a suggested workout routine](#generating-a-suggested-workout-routine). + +### **Sorting Exercise List** + +#### Implementation + +The sorting of exercise list is facilitated by `ModelManager` which implements `Model`. `ModelManager` contains a `filteredExercises` +list which is the list of exercises in a `FilteredList` 'wrapper' from `javafc.collections.transformation`. `filteredExercises` +gets the list of exercises to be displayed from method `getExerciseList()` in `ExerciseTracker`. + +`ExerciseTracker` has method `sortDisplayedList()` which calls `sortDisplayedList()` in `ExerciseList`. + +`ExerciseList` contains a `displayedList` of type `ObservableList` and is the list that will be displayed by the `Ui`. +It is a duplicated copy of the `internalUnmodifiableList` of type `unmodifiableObservableList`. `ExerciseList` has method +`sortDisplayedList()` which sorts the `displayedList` by order of date using the `sort()` method in `java.util.Collections` with a `Comparator`. + +
+ +**Execution** + +When the command `:sort` is entered, the `Ui` sends the command to `Logic`. `Logic` parses and identifies the `:sort` command that was entered, and creates +an instance of it. `Logic` then executes the command. `Model` will have the displayed list sorted and the sorted list will be displayed by `Ui`. + +**Example Usage** + +Given below is an example usage scenario and how the sorting mechanism behaves at each step. + +Step 1: The user launches the application which loads the set of exercises previously keyed. `displayedList` will be initialised +to be the same as the `internalUnmodifiableList` in `ExerciseList` where the exercises are sorted by the date of input. + +Step 2: The user executes `:sort` command to sort the exercises based on date of exercises done. The `ExerciseTrackerParser` +identifies that the command is a `SortCommand`. The command calls `Model` to `sortDisplayedList` and the `Ui` displays the +`displayedList` which has the exercises sorted by their respective dates. + +The following sequence diagram shows how the sort command is executed. + + + +
+ +#### Design considerations + +**Aspect: Displayed List structure** +* **Current choice**: `displayedList` is a duplicated copy of the list of exercises in `internalUnmodifiableList` of type + `UnmodifiableObservableList` in `ExerciseList` class + * Rationale: The sort command will sort the `diplayedList`, not affecting the `internalUnmodifiableList`. This allows + users to view the sorted list of exercises while maintaining a defensive copy of exercises keyed by user. + +**Aspect: Open-Closed Principle** +* **Current choice**: `sortDisplayedList()` in `ExerciseList` sorts the `displayedList` using the `sort()` method in `java.util.Collections` and a `Comparator`. + * Rationale: Using a `Comparator` in `sort()` allows one to extend the `sortDisplayedList` method to accommodate other sorting orders + by simply changing the `Comparator` used should the sorting criteria change in the future. + +### **Viewing exercises within a date range** + +#### Implementation + +* `ExerciseTrackerParser` calls `RangeCommandParser#parse`. +* `RangeCommandParser#parseArguments` will return an enum type `Variation` according to the arguments in the +`ArgumentMultimap` created. +* When we obtain `Variation.ONE`, `RangeCommandParser#getVariationOne` will be called. + * In this case, the arguments expected to be inside the `ArgumentMultimap` will be the start date and + end date. +* When we obtain `Variation.TWO`, `RangeCommandParser#getVariationTwo` will be called. + * In this case, we expect the number of days to be the only argument inside `ArgumentMultimap`. +* `ParserUtil#parseDate` will be called to obtain the `Date` object(s). +* `RangeCommand` is returned. +* Then, the `execute()` method of the resulting `RangeCommand` object will be called, returning a +`CommandResult` object with the appropriate message. + +
+ +**Execution** + +When the command `:range start/START_DATE end/END_DATE` or `:range last/NUMBER_OF_DAYS` is entered, the `Ui` sends +the command to `Logic`. `LogicManager` parses and identifies the `:range` command that was entered, and creates an instance of it. + +`LogicManager` then executes the command by calling `execute()` in `RangeCommand`. + +`RangeCommand` will call the method `sortFilteredExerciseList(predicate)` defined in `Model`. This will cause +`filteredExercises` in `ModelManager` to be filtered according to the predicate `DateWithinRangePredicate`. +The resulting list will only include exercise entries that have dates between the start date (inclusive) and +end date (inclusive), arranged from the most recent first. If two exercise entries have the same date, +they will be sorted in alphabetical order. + +`Model` will have the list sorted and the sorted list will be displayed by `Ui`. + +**Example Usage** + +Given below is an example usage scenario and how the date range view mechanism behaves at each step. + +Step 1: The user launches the application which loads the set of exercises previously keyed. + +Step 2: The user executes `:range start/10/10/2022 end/15/10/2022` command to view all the exercises done between +10 October 2022 and 15 October 2022. The `ExerciseTrackerParser` identifies that the command is a `RangeCommand`. +The command calls `Model` to `sortFilteredExerciseList(predicate)` and the `Ui` displays the `filteredExercises` list which has all the exercises between the specified dates. + +
+ +The following sequence diagram shows how the date range process is executed. + + -The following sequence diagram shows how the undo operation works: +
-![UndoSequenceDiagram](images/UndoSequenceDiagram.png) +#### Design considerations -
:information_source: **Note:** The lifeline for `UndoCommand` should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram. +**Aspect: Simplicity of command design** +* **Current choice**: The two variations of the `:range` command uses the same keyword but with different expected arguments. +This reduces the number of command keywords the user needs to remember when using the app. +* **Alternative choice**: Instead of using `:range` for both variations, another keyword such as +`:rangeLast` could be used in addition to `:range`. The drawback for this design choice is that +it goes against the simplicity of command design where the set of command keywords should be minimised where possible. + +**Aspect: Enum types are used to indicate the variations** +* **Current choice**: Within `RangeCommandParser`, the enum `Variation` has only two values: `ONE` and `TWO` to represent +`:range` command variation one and two respectively. This ensures that the value representing the command variation cannot be anything not defined in the enum type. +Adding new variations is also easily done by adding another value inside the enum type. + +### **Listing of Personal Records** + +#### Implementation + +The mechanism for listing Exercise personal record(s) is facilitated by `PrCommand`, which extends from `Command`. + +It implements the following operations: + +* `PrCommand#execute()`Executes and coordinates the necessary objects and methods to list personal record(s). +* `PrCommandParser#parse()`Parses user input from UI and initialises a PrCommand object. + +The user can choose to view personal record(s) for specific exercises with the 'n/' prefix: +* `:pr n/NAME1 [n/NAME2 n/NAME3 ...]` + +The user can also choose to view personal records for ALL exercises with the 'all/ prefix': +* `:pr all/` + +
+ +**Example Usage** + +Given below is an example usage scenario for how the mechanism for listing Exercise personal record(s) behaves at each step. + +Step 1. The user launches the application and already has 4 Exercise instances, with two unique Exercises (Squat and Deadlift), in the exercise tracker. + +Step 2: The user enters the command `:pr n/Squat` to view their personal record for the exercise 'Squat'. + +The following sequence diagram shows how the `PrCommand` works. + +![ListPersonalRecordSequenceDiagram](images/ListPersonalRecordSequenceDiagram.png) + +
+ +#### Design considerations + +**Aspect: Type of arguments to accept** +* **Alternative 1 (current choice)**: Accept exercise names. + * Pros: Being able to view and list personal records by Exercise name is more intuitive and convenient, especially since all unique Exercises are listed in the UI (bottom right). + * Cons: Would require users to type more characters; also require users to enter exercise names accurately. + +* **Alternative 2**: Accept index as arguments. + * Pros: Suggestions are generated based on PR recorded by the app. As such, the input exercise(s) must already exist in the app. Accepting indexes would guarantee this condition. + * Cons: May require users to scroll to locate index of desired exercise, when the number of exercises grow. + +
+ +### **Generating a suggested workout routine** + +#### Implementation + +Workout suggestions are suggested by `Generator` objects. The suggestion mechanism follows the command pattern. The `GeneratorFactory` creates a concrete `Generator` object, and passes it to the `GenerateCommand` object, which treats all generators as a general `Generator` type. `GenerateCommand` is able to get a workout suggestion without knowledge of the type of generator. The following class diagram illustrates this. + +![GeneratorCommandPattern](images/GeneratorCommandPattern.png) + +The mechanism for generating a suggested workout routine is facilitated by `GenerateCommand`, which extends from `Command`. + +It implements the following operations: + +* `GenerateCommand#execute()` — Executes and coordinates the necessary objects and methods to generate a suggested workout routine. +* `GenerateCommandParser#parse()` — Parses user input from UI and initializes a GenerateCommand object. + +Cases such as where the index from the user input is out of bounds, are handled by the methods. + +
+ +**Example Usage** + +Given below is an example usage scenario for how the mechanism for generating a workout routine behaves at each step. + +Step 1. The user launches the application, and already has 2 exercises, squat and deadlift, at index 1 and 2, in the exercise tracker. + +Step 2: The user enters the command `:gen 1,2 level/easy` to generate an easy workout routine consisting of the exercises squat and deadlift. + +The following sequence diagram shows how the `GenerateCommand` works. +A `Name` object `exerciseName` is returned to `g:GenerateCommand` by calling a method in `:Model`. +For the sake of brevity, this interaction is omitted from the diagram. + +![GenerateWorkoutSequenceDiagram](images/GenerateWorkoutSequenceDiagram.png) + +
+ +The diagram below illustrates the interaction between `g:GenerateCommand` and `GeneratorFactory` class. +The static method `GeneratorFactory#getGenerator()` creates a `Generator` of the correct difficulty level, such as `EasyGenerator`. +The number of `Generator` objects created is equal to the number of unique exercise names. They are `s:EasyGenerator` and `d:EasyGenerator` for squat and deadlift respectively. + +![GetSuggestionSequenceDiagram](images/GetSuggestionSequenceDiagram.png) + +
:information_source: **Note:** The sd frame should capture the entire diagram here, but due to a limitation of PlantUML, it appears as such.
-The `redo` command does the opposite — it calls `Model#redoAddressBook()`, which shifts the `currentStatePointer` once to the right, pointing to the previously undone state, and restores the address book to that state. +#### Design considerations + +**Aspect: Number of `Generator` objects:** +* **Current choice**: Pairing each unique exercise to one `Generator`. + * Rationale: The current `:gen` command specifies a single difficulty level for all exercises listed in the command. A possible extension in the future would be to allow each exercise to be linked to its own difficulty level, for example, `:gen deadlift/easy squat/hard`. This design would make such an implementation possible. -
:information_source: **Note:** If the `currentStatePointer` is at index `addressBookStateList.size() - 1`, pointing to the latest address book state, then there are no undone AddressBook states to restore. The `redo` command uses `Model#canRedoAddressBook()` to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo. +
+### **Listing of unique stored Exercises in a graphical UI** + +#### Implementation + +The display window is located in the bottom right of the application. The display mechanism has been implemented with the Observer design pattern in mind. + +It is primarily driven by `SavedExerciseListWindow` (which holds the UI for the display). The logic is +handled by `ExerciseKeys` and `ExerciseHashMap`. + +**General class diagram** + +The `SavedExerciseListWindow` class implements the `Observer` interface as it is the observer. The `ExerciseHashMap` class maintains an internal ArrayList of type `Observer`, which can be modified through the addUI function. As the UI elements are usually initialized later than the data on loading of the application, the `SavedExerciseListWindow`UI object is only added as an observer after its constructor is called. This guards against any null-pointer exceptions which may occur when preloading data from a hashmap in storage. + +![ObserverPatternClass](images/ObserverPattern.png) + +
+ +**Subscribing to updates** + +Once the `SavedExerciseListWindow` object has been added to the arraylist of `Observer` in the `ExerciseHashMap`, it 'subscribes' to notifications whenever the ExerciseHashMap changes. Based on the functionality of the Hashmap as well as the application, this can be generalised into two distinct scenarios. + +* **Adding an exercise** - Whenever a new exercise has been added, there is a possibility of a new key being added. +* **Removing an exercise** - Whenever a new exercise has been removed, there is a possibility of a key being removed permanently. + +
:information_source: **Note:** The current implementation subscribes to notification for any form of addition or deletion, regardless if the exercise is unique or already exists in the list.
-Step 5. The user then decides to execute the command `list`. Commands that do not modify the address book, such as `list`, will usually not call `Model#commitAddressBook()`, `Model#undoAddressBook()` or `Model#redoAddressBook()`. Thus, the `addressBookStateList` remains unchanged. +**Updating** + +Whenever there is a state changing operation, the `ExerciseHashMap` object will notify all observers through the notifyObservers method. All Observers in the list will run the update method that is individually specified in their class. As such , all Observers of ExerciseHashMap are required to override the update method as shown below. -![UndoRedoState4](images/UndoRedoState4.png) +``` + @Override + public void update() { + . + unique implementation detail here... + . + } +``` -Step 6. The user executes `clear`, which calls `Model#commitAddressBook()`. Since the `currentStatePointer` is not pointing at the end of the `addressBookStateList`, all address book states after the `currentStatePointer` will be purged. Reason: It no longer makes sense to redo the `add n/David …​` command. This is the behavior that most modern desktop applications follow. +
-![UndoRedoState5](images/UndoRedoState5.png) +Below is a sample sequence diagram for the current implementation of how notifyObservers work. -The following activity diagram summarizes what happens when a user executes a new command: +![NotifyObservers](images/NotifyObservers.png) - +
:information_source: **Note:** Currently, there is only SavedExerciseListWindow observing the ExerciseHashMap +
-#### Design considerations: +The logic behind the calculations and formatting of the display message is handled by the `ExerciseKeys` class. -**Aspect: How undo & redo executes:** +Through this pattern, each observer gets to define exactly what the required display/result should be. -* **Alternative 1 (current choice):** Saves the entire address book. - * Pros: Easy to implement. - * Cons: May have performance issues in terms of memory usage. +#### Design considerations -* **Alternative 2:** Individual command knows how to undo/redo by - itself. - * Pros: Will use less memory (e.g. for `delete`, just save the person being deleted). - * Cons: We must ensure that the implementation of each individual command are correct. +**Aspect: Polymorphism** +* The immediately apparent benefit of this design would be the Polymorphism that it capitalises on. In particular, the notifyObservers function in `ExerciseHashMap`. -_{more aspects and alternatives to be added}_ +``` + public void notifyObservers() { + for (Observer o: observerArrayList) { + o.update(); + } + } +``` -### \[Proposed\] Data archiving +
-_{Explain here how the data archiving feature will be implemented}_ +* Notice that `ExerciseHashMap` does not know the nature of the observers and how they interact with it. `ExerciseHashMap` only stores a list of the objects observing it. It does not have to define what they should do to update, instead, the responsibility of deciding what to do is passed on to the Observers themselves. +* This allows for flexibility in having different types of objects having different forms of updating. This keeps the code in `ExerciseHashMap` short and hides the implementation of the Observers behind the `Observer` interface which acts as an intermediary to help the UI communicate with `ExerciseHashMap`. -------------------------------------------------------------------------------------------------------------------- +
+ ## **Documentation, logging, testing, configuration, dev-ops** * [Documentation guide](Documentation.md) @@ -251,80 +538,298 @@ _{Explain here how the data archiving feature will be implemented}_ -------------------------------------------------------------------------------------------------------------------- +
+ ## **Appendix: Requirements** -### Product scope +### **Product scope** **Target user profile**: -* has a need to manage a significant number of contacts -* prefer desktop apps over other types -* can type fast -* prefers typing to mouse interactions -* is reasonably comfortable using CLI apps +* Programmers who love vim and want to hit the gym for some exercise. However, they are too occupied with work to recall their progressions and don’t know what to do next +* They may also find it hard to remember their statistics on each exercise -**Value proposition**: manage contacts faster than a typical mouse/GUI driven app +**Value proposition**: +* Leverage on their blazing speed on vim to save, write and view gym data in a familiar fashion +* Provides a fast platform for users to track their gym progress or workout routine +* Has vim-like commands to make things more efficient for vim lovers -### User stories +### **User stories** Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*` -| Priority | As a …​ | I want to …​ | So that I can…​ | -| -------- | ------------------------------------------ | ------------------------------ | ---------------------------------------------------------------------- | -| `* * *` | new user | see usage instructions | refer to instructions when I forget how to use the App | -| `* * *` | user | add a new person | | -| `* * *` | user | delete a person | remove entries that I no longer need | -| `* * *` | user | find a person by name | locate details of persons without having to go through the entire list | -| `* *` | user | hide private contact details | minimize chance of someone else seeing them by accident | -| `*` | user with many persons in the address book | sort persons by name | locate a person easily | +
+ +| Priority | As a … | I want to … | so that I can … | +|----------|---------------|----------------------------------------------------------------------|----------------------------------------------------------------------------| +| `* * *` | user | add exercises | keep track of my exercises | +| `* * *` | user | delete exercises | see what exercises I have done | +| `* * *` | user | look for all entries of a specific exercise | track my progression for that particular exercise | +| `* * *` | user | view exercises in chronological order | keep track of my gym progress | +| `* * *` | user | want to track my personal records | keep track of my progress for each exercise (and show off to my friends) | +| `* * *` | user | generate workouts of different difficulty | customise my workout based on how I’m feeling that day | +| `* * *` | user | view my recent exercises | plan for my next gym session | +| `* * *` | user | view my exercises done within a date range | track my overall progress over a period of time (eg. weekly, monthly, etc) | +| `* * *` | user | see what names the system has registered | add exercises correctly and quickly | +| `* * ` | new user | remove all sample data | input my own data | +| `* * ` | advanced user | have a quick summary of all the commands I can do in the application | save time | +| `* * ` | clumsy user | have a safeguard against accidentally clearing all data | preserve my exercise | +| `*` | user | track my calories intake | attain my fitness goals | +| `*` | user | track my calories burnt during the gym session | attain my fitness goals | +| `*` | user | have a tailored workout program | target my specific strengths and weaknesses for outstanding results | +| `*` | user | have motivation to go to the gym | stay motivated to attain my fitness goals | +| `*` | user | track my Rate of Perceived Exertion (RPE) of previous workout | better plan for my next workout | +| `*` | user | view my run timings | track my running progression | +| `*` | user | share my workout plan with my friends | progress together with them | +| `*` | user | access a workout plan done by my friends | learn from them | + +
+ +### **Use cases** + +(For all use cases below, the **System** is `Gim` and the **Actor** is the `user`, unless specified otherwise) + +**Use case 1: Help** + +System: Gim
+Use case: UC01 - Request for help
+Actor: User
+ +**MSS** + +1. User requests for help. +2. Gim displays help message. +
Use case ends. + +**Use case 2: Add an exercise** + +System: Gim
+Use case: UC02 - Add an exercise
+Actor: User
+ +**MSS** + +1. User requests to add an exercise. +2. Gim adds the exercise into storage. +
Use case ends. + +**Extensions** + +* 1a. User enters the command wrongly. + * 1a1. Gim shows an error message. +
Use case resumes at step 1. + +
+ +**Use case 3: Delete an exercise** + +System: Gim
+Use case: UC03 - Delete an exercise
+Actor: User
+ +**MSS** + +1. User requests to delete an exercise. +2. Gim deletes the exercise. +
Use case ends. + +**Extensions** + +* 1a. User enters the command wrongly. + * 1a1. Gim displays the error message. +
Use case resumes at step 1. + +* 1b. User enters an exercise that does not exist in the app. + * 1b1. Gim displays that the exercise does not exist. +
Use case ends. + +**Use case 4: Clear all exercise entries in the system** + +System: Gim
+Use case: UC04 - Clear all exercise entries in the system
+Actor: User
+ +**MSS** + +1. User requests to clear all exercise entries in the system. +2. Gim clears all exercise entries in the system. +
Use case ends. + +**Extensions** + +* 1a. User enters the command wrongly. + * 1a1. Gim shows an error message. +
Use case resumes at step 1. + +
+ +**Use case 5: List exercises** + +System: Gim
+Use case: UC05 - List exercises
+Actor: User
-*{More to be added}* +**MSS** -### Use cases +1. User requests to list all stored exercises. +2. Gim lists the stored exercises. +
Use case ends. -(For all use cases below, the **System** is the `AddressBook` and the **Actor** is the `user`, unless specified otherwise) +**Use case 6: Sort exercises** -**Use case: Delete a person** +System: Gim
+Use case: UC06 - Sort exercises
+Actor: User
**MSS** -1. User requests to list persons -2. AddressBook shows a list of persons -3. User requests to delete a specific person in the list -4. AddressBook deletes the person +1. User requests to sort the displayed list of exercises. +2. Gim sorts the displayed list of exercises by date. +
Use case ends. + +**Use case 7: View exercises within a time period** - Use case ends. +System: Gim
+Use case: UC07- View exercises within a time period
+Actor: User
+ +**MSS** + +1. User requests to view displayed exercises within a time period. +2. Gim displays exercises completed within the specified time period in an order sorted by date. +
Use case ends. **Extensions** -* 2a. The list is empty. +* 1a. User enters the command wrongly. + * 1a1. Gim displays the error message. +
Use case resumes at step 1. +* 1b. User enters an invalid date. + * 1b1. Gim displays the invalid date error message. +
Use case resumes at step 1. - Use case ends. +
-* 3a. The given index is invalid. +**Use case 8: Filter exercises by keyword(s)** - * 3a1. AddressBook shows an error message. +System: Gim
+Use case: UC08 - Filter exercises by keyword(s)
+Actor: User
- Use case resumes at step 2. +**MSS** -*{More to be added}* +1. User requests to filter the displayed list of exercises by keyword(s). +2. Gim displays the filtered list of exercises. +
Use case ends. -### Non-Functional Requirements +**Extensions** -1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed. -2. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage. -3. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse. +* 1a. User enters the command wrongly. + * 1a1. Gim displays the error message. +
Use case resumes at step 1. +* 2a. Filtered list of exercises is empty. + * 2a1. Gim displays a reminder message. +
Use case ends. -*{More to be added}* +**Use case 9: View Personal Record (PR) for exercise(s)** -### Glossary +System: Gim
+Use case: UC09 - View Personal Record (PR) for exercise(s)
+Actor: User
-* **Mainstream OS**: Windows, Linux, Unix, OS-X -* **Private contact detail**: A contact detail that is not meant to be shared with others +**MSS** + +1. User requests to view Personal Record (PR) for exercise(s). +2. Gim calculates and displays the Personal Record (PR) for exercise(s). +
Use case ends. + +**Extensions** + +* 1a. User enters the command wrongly. + * 1a1. Gim displays the error message. +
Use case resumes at step 1. +* 1b. User enters the name of exercise(s) wrongly. + * 1b1. Gim displays exercise(s) not registered in system message. +
Use case resumes at step 1. + +
+ +**Use case 10: Generate workout suggestion for exercise(s)** + +System: Gim
+Use case: UC10 - Generate workout suggestion for exercise(s)
+Actor: User
+ +**MSS** + +1. User requests to generate a workout suggestion. +2. Gim computes a sample workout for the user. +
Use case ends. + +**Extensions** + +* 1a. User enters the command wrongly. + * 1a1. Gim displays the error message. +
Use case resumes at step 1. +* 1b. User enters an invalid index. + * 1b1. Gim displays the invalid index error message. +
Use case resumes at step 1. +* 1c. User enters an incorrect format for index(es). + * 1c1. Gim displays the incorrect index format message. +
Use case resumes at step 1. +* 1d. User enters the name of exercise(s) wrongly. + * 1d1. Gim displays exercise(s) not registered in system message. +
Use case resumes at step 1. +* 1e. User enters an invalid difficulty level. + * 1e1. Gim displays the invalid difficulty level message. +
Use case resumes at step 1. + + +**Use case 11: Exit Gim** + +System: Gim
+Use case: UC11 - Exit Gim
+Actor: User
+ +**MSS** + +1. User requests to exit Gim. +2. Gim exits. +
Use case ends. + +
+ +### **Non-Functional Requirements** + +1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed. +2. Should be able to hold up to 1000 exercises without a noticeable sluggishness in performance for typical usage. +3. Should work without an internet connection. +4. Should be able to support frequent updating of data. +5. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse. +6. Should not be able to verify if the user actually perform the exercises they input. +7. Users with no coding background should be able to use Gim. +8. Should be optimised for a single user. +9. The product file size should not exceed 100MB. +10. Data should be persisted locally and be in a human-readable format, e.g. JSON. +11. Should be delivered to a user as a single JAR file. +12. Should not lose any data if application is closed through external means (i.e. not using exit command). + + +### **Glossary** +* **Exercise**: Physical activity done in a regular gym that is structured and repetitive, usually involving some weights. +* **Mainstream OS**: Windows, Linux, Unix, OS-X. +* **Personal Record (PR)**: Heaviest weight recorded in the exercise tracker for a specific exercise. +* **Rate of Perceived Exertion (RPE)**: A measure of a physical activity intensity level. +* **Reps**: Number of times you perform a specific exercise. +* **Sets**: Number of cycles of reps that you complete. +* **Vim**: A Unix text editor, known for being lightweight, fast and efficient. It can be controlled entirely with the keyboard with no need for menus or a mouse. +* **Weight**: Total weight of equipment (in kg). -------------------------------------------------------------------------------------------------------------------- +
+ ## **Appendix: Instructions for manual testing** Given below are instructions to test the app manually. @@ -334,44 +839,179 @@ testers are expected to do more *exploratory* testing.
-### Launch and shutdown +**Launch and shutdown** 1. Initial launch 1. Download the jar file and copy into an empty folder - 1. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum. + 1. Double-click the jar file Expected: Shows the GUI with a set of sample exercises. The window size may not be optimum. -1. Saving window preferences +2. Saving window preferences 1. Resize the window to an optimum size. Move the window to a different location. Close the window. 1. Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained. -1. _{ more test cases …​ }_ +
+ +**Adding an exercise** + +1. Adding an exercise to the system. -### Deleting a person + 1. Test case: `:add n/Squat w/60 s/1 r/5 d/25/01/2022`.
+ Expected: A new exercise with the name `Squat`, with weight `60kg`, with set `1`, with reps `5` and with date `25/01/2022` is added at the bottom of the Exercise List in Gim. + The Result Display Window indicates that an exercise named `Squat` has been successfully added. + + 2. Test case: `:add n/Squat w/60 s/1 r/5`.
+ Expected: A new exercise with the name `Squat`, with weight `60kg`, with set `1`, with reps `5` and with today's date is added at the bottom of the Exercise List in Gim. + The Result Display Window indicates that an exercise named `Squat` has been successfully added. -1. Deleting a person while all persons are being shown + 3. Test case: `:add n/Squat`.
+ Expected: No exercise is added. The Result Display Window indicates that the command is of an invalid format. - 1. Prerequisites: List all persons using the `list` command. Multiple persons in the list. + 4. Other incorrect `:add` commands to try: `:add`, `:add x/invalid`, `...` (where x is any invalid prefix).
+ Expected: Similar to previous. - 1. Test case: `delete 1`
- Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated. +
- 1. Test case: `delete 0`
- Expected: No person is deleted. Error details shown in the status message. Status bar remains the same. +**Deleting an exercise** - 1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
+1. Deleting an exercise while all exercises are being shown + + 1. Prerequisite: List all exercises using the `:list` command. Multiple exercises in the list. + + 2. Test case: `:del 1`
+ Expected: First exercise is deleted from the list. Details of the deleted exercise shown in the Result Display Window. Timestamp in the status bar is updated. + + 3. Test case: `:del 0`
+ Expected: No exercise is deleted. Error details shown in the Result Display Window. Status bar remains the same. + + 4. Other incorrect delete commands to try: `:del`, `:del x`, `...` (where x is larger than the list size)
Expected: Similar to previous. -1. _{ more test cases …​ }_ +**Clearing all exercises in the system** + +1. Clearing all exercises in the system + + 1. Prerequisite: There is at least one exercise in the Exercise List. + + 2. Test case: `:clear`
+ Expected: The Result Display Window will indicate that the command is invalid. + + 3. Test case: `:clear confirnm/`
+ Expected: All exercises in the system is cleared. The Result Display Window will indicate that the exercise tracker has been cleared. + +
+ +**Filtering exercises by keyword(s)** + +1. Filtering displayed list of exercises using keyword(s). + + 1. Prerequisite: There are multiple exercises in the Exercise List. + + 2. Prerequisite: There exists an exercise with exercise name `Deadlift`.
+ Test case: `:filter Deadlift`.
+ Expected: The exercise with exercise name `Deadlift` appears in the Exercise List after executing the command. + + 3. Prerequisite: There exists an exercise with exercise name `Deadlift` and an exercise with exercise name `Squat`.
+ Test case: `:filter Deadlift Squat`.
+ Expected: The exercise with exercise name `Deadlift` and exercise with exercise named `Squat` appear in the Exercise List after executing the command. + + 4. Other incorrect `:filter` commands to try: `:filter` (no keywords provided).
+ Expected: The Result Display Window will indicate that the command is invalid. + +**Sorting exercises** + +1. Sorting displayed list of exercises by order of date. + + 1. Prerequisite: There are multiple exercises in the Exercise List. + + 2. Test case: `:sort`.
+ Expected: The exercises displayed in the Exercise List will be sorted by date after executing the command. + +
+ +**Viewing exercises within a time period** + +1. Viewing exercises within a time period. + + 1. Prerequisite: There is at least one exercise in the Exercise List. + + 2. Test case: `:range last/5`.
+ Expected: List exercises completed in the last 5 days. + + 3. Test case: `:range start/01/01/2022 end/31/01/2022`.
+ Expected: List exercises completed between 01/01/2022 and 31/01/2022. + + 4. Test case: `:range start/01/01/202222 end/31/01/202222`.
+ Expected: The Result Display Window will indicate that the date input format is invalid. + + 5. Other incorrect `:range` commands to try: `:range`, `range last/abc`, `range start/01/01/2022`, ...
+ Expected: The Result Display Window will indicate that the command is invalid. + +
+ +**Generating workout suggestion for exercise(s)** + +1. Generating workout suggestion using index(es). + + 1. Prerequisite: There is at least one exercise in the Exercise List. + + 2. Test case: `:gen 1 level/easy`.
+ Expected: Generate a workout with difficulty level easy for the exercise at index 1 of the Exercise List. + + 3. Prerequisite: There is only one exercise in the Exercise List.
+ Test case: `:gen 2 level/easy`.
+ Expected: The Result Display Window will indicate that the index is invalid. + +2. Generating workout suggestion using exercise name(s). + + 1. Prerequisite: There is at least one exercise in the Exercise List. + + 2. Prerequisite: There exists an exercise with exercise name `Deadlift`.
+ Test case: `:gen n/Deadlift level/easy`.
+ Expected: Generate a workout with difficulty level easy for exercise with exercise name `Deadlift`. + + 3. Prerequisite: There does not exist an exercise with exercise name `Squat`.
+ Test case: `:gen n/Squat level/easy`.
+ Expected: The Result Display Window will indicate that the exercise is not registered in the system. + + 4. Test case: `:gen n/Deadlift level/easyyyyyy`.
+ Expected: The Result Display Window will indicate that the level is not supported. + + 5. Other incorrect `:gen` commands to try: `:gen` (no keywords provided).
+ Expected: The Result Display Window will indicate that the command is invalid. + +
+ +**Listing Personal Records (PR)** + +1. Listing Personal Record(s) of exercise(s). + + 1. Prerequisite: There is at least one exercise in the Exercise List. + + 2. Prerequisite: There exists at least one exercise with exercise name `Deadlift`.
+ Test case: `:pr n/Deadlift`.
+ Expected: List the Personal Record for exercise with exercise name `Deadlift`. + + 3. Prerequisite: There exists only exercises with exercise name `Deadlift` and exercise name `Squat`.
+ Test case: `:pr all/`.
+ Expected: List the Personal Records for exercises with exercise name `Deadlift` and exercise name `Squat`. + + 4. Prerequisite: There does not exist an exercise with exercise name `Bench press`.
+ Test case: `:pr n/Bench press`.
+ Expected: The Result Display Window will indicate that the exercise is not registered in the system. + + 5. Other incorrect `:pr` commands to try: `:pr` (no keywords provided).
+ Expected: The Result Display Window will indicate that the command is invalid. -### Saving data +**Saving data** 1. Dealing with missing/corrupted data files - 1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_ + 1. Prerequisites: Able to access the `/data` folder (created in the same folder containing the `Gim.jar` file). -1. _{ more test cases …​ }_ + 2. Test Case: Navigate to the `/data` folder and delete the `exercisetracker.json` file. Then reopen the application.
+ Expected: The application will be repopulated with the initial starting data. diff --git a/docs/SettingUp.md b/docs/SettingUp.md index 275445bd551..95b501aa529 100644 --- a/docs/SettingUp.md +++ b/docs/SettingUp.md @@ -23,7 +23,7 @@ If you plan to use Intellij IDEA (highly recommended): 1. **Import the project as a Gradle project**: Follow the guide [_[se-edu/guides] IDEA: Importing a Gradle project_](https://se-education.org/guides/tutorials/intellijImportGradleProject.html) to import the project into IDEA.
:exclamation: Note: Importing a Gradle project is slightly different from importing a normal Java project. 1. **Verify the setup**: - 1. Run the `seedu.address.Main` and try a few commands. + 1. Run the `gim.Main` and try a few commands. 1. [Run the tests](Testing.md) to ensure they all pass. -------------------------------------------------------------------------------------------------------------------- @@ -45,7 +45,7 @@ If you plan to use Intellij IDEA (highly recommended): 1. **Learn the design** - When you are ready to start coding, we recommend that you get some sense of the overall design by reading about [AddressBook’s architecture](DeveloperGuide.md#architecture). + When you are ready to start coding, we recommend that you get some sense of the overall design by reading about [Gim’s architecture](DeveloperGuide.md#architecture). 1. **Do the tutorials** These tutorials will help you get acquainted with the codebase. diff --git a/docs/Testing.md b/docs/Testing.md index 8a99e82438a..4e9823a83c9 100644 --- a/docs/Testing.md +++ b/docs/Testing.md @@ -29,8 +29,8 @@ There are two ways to run tests. This project has three types of tests: 1. *Unit tests* targeting the lowest level methods/classes.
- e.g. `seedu.address.commons.StringUtilTest` + e.g. `gim.commons.StringUtilTest` 1. *Integration tests* that are checking the integration of multiple code units (those code units are assumed to be working).
- e.g. `seedu.address.storage.StorageManagerTest` + e.g. `gim.storage.StorageManagerTest` 1. Hybrids of unit and integration tests. These test are checking multiple code units as well as how the are connected together.
- e.g. `seedu.address.logic.LogicManagerTest` + e.g. `gim.logic.LogicManagerTest` diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 3716f3ca8a4..cf3eba758da 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -3,190 +3,555 @@ layout: page title: User Guide --- -AddressBook Level 3 (AB3) is a **desktop app for managing contacts, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB3 can get your contact management tasks done faster than traditional GUI apps. +

+ +

+
+ +
+ +**Table of Contents** * Table of Contents {:toc} +-------------------------------------------------------------------------------------------------------------------- + +
+ +## 1. Introduction + +### 1.1. What is Gim? +Gim is a desktop app for **managing gym exercises**. Gim allows you to **keep track of your progress** and **craft personalised workout plans**. Gim commands are inspired by those of [Vim](#8-glossary-of-terminologies). Gim is optimised for use via a [Command Line Interface (CLI)](#8-glossary-of-terminologies) while still having the benefits of a [Graphical User Interface (GUI)](#8-glossary-of-terminologies). + +### 1.2. Who is this guide for? +Are you a gym-goer looking to use Gim to track your exercises? This user guide will get you started in no time and help you navigate through Gim's features. For a quick start guide, head over to [Getting Started](#3-getting-started). + +-------------------------------------------------------------------------------------------------------------------- + +## 2. How to use this guide? +Gim uses a Command Line Interface (CLI), which may be new to some users. If you are a new user, we strongly recommend you to look through the user guide from start to end to fully understand how to use Gim. However, you may also choose to skip to the relevant sections described below: +* Refer to our Table of Contents to easily navigate between sections of the User Guide. +* Refer to our [Getting Started](#3-getting-started) guide to learn how to setup Gim. +* Refer to our [GUI Orientation](#4-gui-orientation) to better orientate yourself around the GUI. +* Refer to our [Commands](#5-commands) section to learn in detail the different features and commands available in Gim. +* Refer to our [FAQ](#6-faq) to read common queries that new users may have. +* Refer to our [Command Summary](#7-command-summary) to have a quick overview of the different commands and their respective formats. +* Refer to our [Glossary of Terminologies](#8-glossary-of-terminologies) to learn key terms that are used in this User Guide. + +### 2.1 Useful Notations +While exploring Gim's features with this user guide, do take note of these symbols used in the user guide and what they represent. + +| Symbol | Meaning | +|:--------------------:|-------------------------| +| :information_source: | Important information | +| :exclamation: | Warning or Caution | +| :thinking: | When should I use this? | +| :bulb: | Tips | -------------------------------------------------------------------------------------------------------------------- -## Quick start +
+ +## 3. Getting Started 1. Ensure you have Java `11` or above installed in your Computer. -1. Download the latest `addressbook.jar` from [here](https://github.com/se-edu/addressbook-level3/releases). +2. Download the latest `gim.jar` [here](https://github.com/AY2223S1-CS2103T-T15-4/tp/releases). + +3. Copy the file to the folder you want to use as the _home folder_ for your Gim. + +4. Double-click the file to start the app. The GUI similar to the one shown below should appear in a few seconds. Note how the app contains some sample data.
+
![Ui](images/Ui.png) + + +5. Type the command in the command box and press Enter to execute it. e.g. typing **`:help`** and pressing Enter will open the help window.
+ +6. Refer to the [Commands Section](#5-commands) below for details of each command. + +Back To Table of Contents + +-------------------------------------------------------------------------------------------------------------------- +
+ +## 4. GUI Orientation + +![GUI](images/GUIOrientation.png) + +### 4.1. Command Box + +The `Command Box` is where you can input your commands. + +### 4.2. Exercise List -1. Copy the file to the folder you want to use as the _home folder_ for your AddressBook. +The `Exercise List` displays exercise entries. When the application is first launched, the `Exercise List` displays all exercise entries in the system, arranged by the order in which they were added. Whenever you issue commands that may truncate/reorder the `Exercise List`, they will **only act upon the entries that are currently displayed in the** `Exercise List`. -1. Double-click the file to start the app. The GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
- ![Ui](images/Ui.png) +
-1. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
- Some example commands you can try: +### 4.3. Result Display - * **`list`** : Lists all contacts. +The `Result Display Window` displays feedback after executing a command. This includes feedback for both correctly and incorrectly entered commands. - * **`add`**`n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : Adds a contact named `John Doe` to the Address Book. +### 4.4. Recognised Exercise Name List - * **`delete`**`3` : Deletes the 3rd contact shown in the current list. +The `Recognised Exercise Name List Window` provides you a list of all unique exercise names that are currently registered in the system. +

- * **`clear`** : Deletes all contacts. +Notice that there are two counts. - * **`exit`** : Exits the app. +* **Count #1**: Displays the number of exercise names registered in the system (i.e. does not include duplicates) +* **Count #2**: Displays the total number of exercise entries in the system (i.e. includes duplicates) -1. Refer to the [Features](#features) below for details of each command. +For illustrative purposes, let us refer to the image below. There are multiple Squat entries in the system registered under the same name Squat, which is reflected by **Count #1**. On the other hand, because **Count #2** includes duplicates, it will count both "Squat" entries individually even if they are registered under the same name. + +![RecognisedList](images/RecognisedExercisesOrientation.png) + +
+ +
:bulb: +**Tip:** Use the list circled in green to identify any mispellings in your exercise entries!

+ +E.g. If you see an entry for Squatz in the green list when you normally name your exercise Squat, it means you may have an incorrectly spelled entry. +
+ +
:exclamation: **Caution:**
+Exercise names are recognised as equal if, upon removing white spaces and setting the names to lowercase, the names are the same.

+i.e. Bench Press, BENCH PRESS, BenchPress will be logged as the same exercise for your convenience in adding.

+However, the first time you add an exercise with an unrecognised name, the Recognised Exercise Name List will save the form you have input. Choose wisely! +
+ +Back To Table of Contents -------------------------------------------------------------------------------------------------------------------- -## Features +
+ +## 5. Commands
**:information_source: Notes about the command format:**
-* Words in `UPPER_CASE` are the parameters to be supplied by the user.
- e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`. +* Words in `UPPER_CASE` are the [parameters](#8-glossary-of-terminologies) to be supplied by you.
+ E.g. In `n/NAME w/WEIGHT`, `NAME` and `WEIGHT` are parameters which can be used as `n/Squat w/100`. * Items in square brackets are optional.
- e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`. + E.g. `n/NAME [d/DATE]` can be used as `n/Deadlift d/27-10-2022` or as `n/Deadlift`. -* Items with `…`​ after them can be used multiple times including zero times.
- e.g. `[t/TAG]…​` can be used as ` ` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. +* Items with `…` after them can be used multiple times including zero times.
+ E.g. `[n/NAME]…` can be used as ` ` (i.e. 0 times), `n/Squat` (i.e. 1 time), `n/Squat n/Deadlift` (i.e. 2 times) etc. * Parameters can be in any order.
- e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable. + E.g. If the command specifies `n/NAME w/WEIGHT`, `w/WEIGHT n/NAME` is also acceptable. -* If a parameter is expected only once in the command but you specified it multiple times, only the last occurrence of the parameter will be taken.
- e.g. if you specify `p/12341234 p/56785678`, only `p/56785678` will be taken. +* If a parameter is expected only once in the command but you specify it multiple times, only the last occurrence of the parameter will be taken.
+ E.g. If you specify `n/Squat n/Deadlift`, only `n/Deadlift` will be taken. -* Extraneous parameters for commands that do not take in parameters (such as `help`, `list`, `exit` and `clear`) will be ignored.
- e.g. if the command specifies `help 123`, it will be interpreted as `help`. +* Redundant inputs for commands that do not take in additional parameters (such as `:list`, `:sort`, `:help` `:wq`) will be ignored.
+ E.g. If you specify `:help 123`, it will be interpreted as `:help`.
-### Viewing help : `help` +
-Shows a message explaning how to access the help page. +### 5.1. Adding an exercise: `:add` -![help message](images/helpMessage.png) +Adds an exercise that we have done for the day. + +
-Format: `help` +**:information_source: Note about add:**
+If an exercise (identified by their names) is added for the first time, it is automatically registered as a new unique exercise. +
+ +Format: `:add n/NAME w/WEIGHT s/SETS r/REPS [d/DATE]` + +
:bulb: +**Tip:** If `d/DATE` field is left empty, the system will store the exercise with the current date. +
+ +Parameter constraints: +* The name **must only contain alphanumeric** (alphabets & numbers) **characters and spaces**. + * Examples: Squat, Bench press, Deadlift... +* The [weight](#8-glossary-of-terminologies) **must be a non-negative decimal number, up to 3 digits for the whole number and up to 2 digits for the decimal place**. + * Examples: 0, 0.55, 35, 100.1, 200.00... +* The [sets](#8-glossary-of-terminologies) **must be a positive integer, up to 3 digits, with no leading zeroes**. + * Examples: 1, 2, 3, 10, 100... +* The [reps](#8-glossary-of-terminologies) **must be a positive integer, up to 3 digits, with no leading zeroes**. + * Examples: 1, 2, 3, 10, 100... +* The date **must be a valid date**. + * Accepted formats: + * day/month/year + * year/month/day + * day-month-year + * year-month-day + * day month year + * year month day + * The day **must be a positive integer, up to 2 digits**. + * The month **must be a positive integer, up to 2 digits**. + * The year **must be a positive integer, with exactly 4 digits**. + * Examples: 27/10/2022, 01-10-2022... + +
+ +Examples: +* `:add n/Squat w/30 s/3 r/5` Adds a Squat exercise of weight 30kg for 3 sets of 5 reps for today's date. +* `:add n/Deadlift w/60 s/1 r/1 d/27/01/2022` Adds a Deadlift exercise of weight 60kg for 1 set of 1 rep for 27th January 2022. -### Adding a person: `add` +![AddCommand](images/AddCommand.png) -Adds a person to the address book. +
-Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​` +### 5.2. Deleting an exercise : `:del` + +Deletes a particular exercise from our list. + +
+ +**:information_source: Note about delete:**
+If the deleted exercise was the last exercise with the same name, then the exercise is automatically de-registered from the list of unique exercises. -
:bulb: **Tip:** -A person can have any number of tags (including 0)
-Examples: -* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` -* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` +Format: `:del INDEX` -### Listing all persons : `list` +Parameter constraints: +* The [index](#8-glossary-of-terminologies) **must be a positive integer**. + * Example: 1, 2, 3, ... -Shows a list of all persons in the address book. +Example: +* `:del 9` Deletes an exercise at index 9 of the list. -Format: `list` +### 5.3. Clearing all exercises : `:clear` -### Editing a person : `edit` +Clears the saved exercises and resets the data in the system. -Edits an existing person in the address book. +Format: `:clear confirm/` -Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​` +
:exclamation: **Caution:**
+Redundant inputs (before and after the `confirm/` flag) will be ignored.
E.g. If the command specifies `:clear abc confirm/ 123`, it will be interpreted as `:clear confirm/`. +
-* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. The index **must be a positive integer** 1, 2, 3, …​ -* At least one of the optional fields must be provided. -* Existing values will be updated to the input values. -* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative. -* You can remove all the person’s tags by typing `t/` without - specifying any tags after it. +Example: +* `:clear confirm/` Clears all saved exercises, resetting the data in the system. -Examples: -* `edit 1 p/91234567 e/johndoe@example.com` Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively. -* `edit 2 n/Betsy Crower t/` Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. +
-### Locating persons by name: `find` +### 5.4. Filtering exercises by keyword(s) : `:filter` -Finds persons whose names contain any of the given keywords. +Filters exercises, in the current [Exercise List](#42-exercise-list), with names containing any of the given keywords. -Format: `find KEYWORD [MORE_KEYWORDS]` +Format: `:filter KEYWORD [KEYWORD]...` -* The search is case-insensitive. e.g `hans` will match `Hans` -* The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans` -* Only the name is searched. -* Only full words will be matched e.g. `Han` will not match `Hans` -* Persons matching at least one keyword will be returned (i.e. `OR` search). - e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` +
-Examples: -* `find John` returns `john` and `John Doe` -* `find alex david` returns `Alex Yeoh`, `David Li`
- ![result for 'find alex david'](images/findAlexDavidResult.png) +**:information_source: Notes about filter:**
+ +* Only the exercise name is searched. +* The keyword is case-insensitive. e.g bench will match Bench. +* The order of the keywords does not matter. e.g. Deadlift Squat will match Squat Deadlift. +* Only full words will be matched e.g. Squat will not match Squats. +* Exercises matching at least one keyword will be returned e.g. `:filter Bench press` will return Bench press and Leg press. + +
+ +
+ +**:thinking: When should I use this?**
+I should use this when I want to find the entries of a specific exercise. + +
+ +Example: +* `:filter Deadlift Squat` Shows the list of Deadlift and Squat exercises. + +![FilterCommand](images/FilterCommand.png) + +
+ +### 5.5. Sorting exercises : `:sort` + +Sorts the exercises, in the current [Exercise List](#42-exercise-list), according to their date of completion, with the latest exercise completed displayed at the top of the list. + +Format: `:sort` + +Example: +* `:sort` Shows the sorted list of exercises. + +![ListAfterSortCommand](images/ListAfterSortCommand.png) + + +### 5.6. Viewing all exercises within a time period : `:range` + +Shows all exercises, among exercises in the current [Exercise List](#42-exercise-list), within the specified date range; the latest exercise completed is displayed at the top of the list. + +
+ +**:information_source: There are 2 formats supported for this command.**
+ +
+ +
+ +Format (1) : `:range start/START_DATE end/END_DATE` + +Parameter constraints: +* The START_DATE and END_DATE **must be a valid date**. + * Accepted formats: + * day/month/year + * year/month/day + * day-month-year + * year-month-day + * day month year + * year month day + * The day **must be a positive integer, up to 2 digits**. + * The month **must be a positive integer, up to 2 digits**. + * The year **must be a positive integer, with exactly 4 digits**. +* Start date should be before end date. Otherwise, no exercises will be displayed. + +Example: +* `:range start/25/10/2022 end/26/10/2022` Shows the exercises done between October 25, 2022 and October 26, 2022 (both inclusive). + +![RangeCommandOne](images/RangeCommandOneSample.png) -### Deleting a person : `delete` +
-Deletes the specified person from the address book. +Format (2) : `:range last/NUMBER_OF_DAYS` -Format: `delete INDEX` +Parameter constraints: +* Number of days **can only take non-negative integer values** up to 5 digits, excluding leading zeroes. -* Deletes the person at the specified `INDEX`. -* The index refers to the index number shown in the displayed person list. -* The index **must be a positive integer** 1, 2, 3, …​ +Example: +* `:range last/3` Shows the exercises done today and the last 3 days. + +![RangeCommandTwo](images/RangeCommandTwoSample.png) + +
+ +### 5.7. Listing all exercises : `:list` + +Shows a list of all exercises. + +
+ +**:thinking: When should I use this?**
+I should use this when I want to reset my Exercise List back to the default state (before any sorting/filtering commands were used). + +
+ +Format: `:list` + +Example: +* `:list` Shows the list of exercises you have completed. + +
:bulb: +**Tip: Tracking exercise progressions over time**
+If you want to view your squat progression over the past week, here's a nifty sequence of commands you can try!

+1. `:list` Current exercise list now shows all exercises.
+2. `:filter Squat` Current exercise list now shows 'Squat' exercises.
+3. `:range last/7` Current exercise list now shows 'Squat' exercises in the past 7 days. + +
+ +
+ +### 5.8. Listing Personal Records (PR): `:pr` + +Finds the [Personal Record](#8-glossary-of-terminologies) of certain exercises in the exercise tracker. + +
+ +**:information_source: There are 2 formats supported for this command.**
+ +
+ +Format (1): `:pr n/NAME [n/NAME]...` + +Parameter constraints: +* Name **must only contain alphanumeric** (alphabets & numbers) **characters and spaces**. + * Examples: Squat, Bench press, Deadlift... Examples: -* `list` followed by `delete 2` deletes the 2nd person in the address book. -* `find Betsy` followed by `delete 1` deletes the 1st person in the results of the `find` command. +* `:pr n/Squat` Lists the personal record for the Squat exercise (if found). +* `:pr n/Deadlift n/Bench press n/Squat` Lists the personal records for the Deadlift, Bench press and Squat exercises (if found). -### Clearing all entries : `clear` +![PrCommandExample1](images/PrCommandExample1.png) -Clears all entries from the address book. +
-Format: `clear` +Format (2): `:pr all/` -### Exiting the program : `exit` +
:exclamation: **Caution:**
+Redundant inputs (before and after the `all/` flag) will be ignored.
E.g. If the command specifies `:pr abc all/ 123`, it will be interpreted as `:pr all/`. +
-Exits the program. +Example: +* `:pr all/` Lists the personal records for all uniquely registered exercises in the exercise tracker. + +![PrCommandExample2](images/PrCommandExample2.png) + +
+ +### 5.9. Generating a sample workout based on Personal Records: `:gen` + +Generates a sample workout suggestion based on existing personal records of the exercises, according to the difficulty level specified. Exercises are indicated either by their [index](#8-glossary-of-terminologies) or their exercise names. + +
+ +**:thinking: When should I use this?**
+I should use this when I want to get a quick workout plan based on how I am feeling. + +
+ +
+ +**:information_source: There are 2 formats supported for this command.**
+ +
+ +
+ +Format (1): `:gen INDEX [, INDEX]... level/DIFFICULTY_LEVEL` -Format: `exit` +Parameter constraints: +* The index **must be a positive integer**. + * Example: 1, 2, 3, ... +* The difficulty level must be supported; currently supported are: easy, medium, hard. -### Saving the data +Example: +* `:gen 4, 5 level/easy` Generates a sample workout for Squat; this command is equivalent to `:gen 4 level/easy` since both index 4 and 5 in the displayed list are Squat exercises. +* `:gen 1, 2 level/easy` Generates a sample workout for exercises at index 1 and 2 of the list, Deadlift and Incline Bench. -AddressBook data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually. +![GenerateCommandExample1](images/GenerateCommandExample1.png) -### Editing the data file +
-AddressBook data are saved as a JSON file `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file. +Format (2): `:gen n/NAME [n/NAME]... level/DIFFICULTY_LEVEL` -
:exclamation: **Caution:** -If your changes to the data file makes its format invalid, AddressBook will discard all data and start with an empty data file at the next run. +Parameter constraints: +* Name **must only contain alphanumeric** (alphabets & numbers) **characters and spaces**. +* The difficulty level must be one that is supported; currently supported are: easy, medium, hard. + +
:exclamation: **Caution:**
+Redundant inputs (before the first `n/` flag) will be ignored.
+E.g. if the command specifies `:gen 1,2,3 n/Squat level/easy`, it will be interpreted as `:gen n/Squat level/easy`.
-### Archiving data files `[coming in v2.0]` +Example: +* `:gen n/Squat n/Squat level/easy` Generates a sample workout for Squat; this command is equivalent to `:gen n/Squat level/easy` since both exercise names are the same. +* `:gen n/Squat n/Deadlift level/easy` Generates a sample workout for exercises Squat and Deadlift (if found). + +![GenerateCommandNameExample1](images/GenerateCommandNameExample1.png) + +
+ +### 5.10. Viewing help : `:help` + +Accesses the help menu. The help menu contains a brief summary of the commands supported and provides a link to the user guide. + +Format: `:help` + +![HelpCommand](images/HelpCommand.png) -_Details coming soon ..._ +
+ +### 5.11. Exiting the program : `:wq` + +Exits the program. + +Format: `:wq` + +
+ +**:information_source: Gim data is saved in the hard disk automatically after any command that changes the data. There is no need to save manually.**
+ +
+ +Back To Table of Contents -------------------------------------------------------------------------------------------------------------------- -## FAQ +
+ +## 6. FAQ + +**Q**: Do I have to update the [Recognised Exercise Name List Window](#44-recognised-exercise-name-list) manually? +
+**A**: You do not have to update it manually as the Recognised Exercise Name List is already updated automatically whenever you add or delete an exercise entry from the system. + +**Q**: Can I change the name of my uniquely registered exercise? +
+**A**: To change the way it is represented, you can find the exercise with the name, delete the entries and re-enter the exercises with your new name of choice. + +
+ +**:information_source: The way you format the exercise name when you first add it will be the way it is displayed in the system. After that, all exercises added that have the same name will be categorised under the same exercise.**
+ +
+ +**Q**: Can I edit an exercise? +
+**A**: You can do so by deleting the entry and adding a new entry. + +**Q**: Why is `:filter`, `:range` or `:sort` not showing the "correct" list even though I have input valid parameters? +
+**A**: The three commands works on the exercises in the current [Exercise List](#42-exercise-list). If your current Exercise List has been altered by list-changing commands such as `:range` or `:filter`, the commands will act on the current Exercise List rather than the full list comprising all exercises in the system. + +
:bulb: +**Tip:** If you would like to operate on the full list instead, try executing the command `:list` to display the full list before running the commands again. +
+ +**Q**: How is data stored in Gim? +
+**A**: Gim data is stored in `[JAR file location]/data/exercisetracker.json`. If you are comfortable working with [JSON](#8-glossary-of-terminologies) files, you are welcome to update Gim's data by editing the data file directly. + +
:exclamation: **Caution:** +If your changes to the data file makes its format invalid, Gim will discard all data and start with an empty data file at the next run. +
+ +Back To Table of Contents + +-------------------------------------------------------------------------------------------------------------------- -**Q**: How do I transfer my data to another Computer?
-**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AddressBook home folder. +
+ +## 7. Command Summary + +| Action | Format | Examples | +|------------------------------------|------------------------------------------------|-------------------------------------------| +| **Add exercise** | :add n/NAME w/WEIGHT s/SETS r/REPS [d/DATE] | :add n/Deadlift w/60 s/1 r/1 d/27/10/2022 | +| **Delete exercise** | :del INDEX | :del 3 | +| **Clear all exercises** | :clear confirm/ | :clear confirm/ | +| **Filter exercise(s)** | :filter KEYWORD [KEYWORD]... | :filter Deadlift Squat | +| **Sort exercises** | :sort | :sort | +| **View range (1)** | :range start/START_DATE end/END_DATE | :range start/25/10/2022 end/26/10/2022 | +| **View range (2)** | :range last/NUMBER_OF_DAYS | :range last/3 | +| **List all exercises** | :list | :list | +| **List Personal Record(s) (1)** | :pr n/NAME [n/NAME]... | :pr n/Deadlift n/Squat | +| **List Personal Record(s) (2)** | :pr all/ | :pr all/ | +| **Generate workout (1)** | :gen INDEX [, INDEX]... level/DIFFICULTY_LEVEL | :gen 1, 2 level/easy | +| **Generate workout (2)** | :gen n/NAME [n/NAME]... level/DIFFICULTY_LEVEL | :gen n/Deadlift level/easy | +| **Help menu** | :help | :help | +| **Exit program** | :wq | :wq | + +Back To Table of Contents -------------------------------------------------------------------------------------------------------------------- -## Command summary - -Action | Format, Examples ---------|------------------ -**Add** | `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​`
e.g., `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague` -**Clear** | `clear` -**Delete** | `delete INDEX`
e.g., `delete 3` -**Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g.,`edit 2 n/James Lee e/jameslee@example.com` -**Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` -**List** | `list` -**Help** | `help` +
+ +## 8. Glossary of Terminologies +* **Command**: An instruction to perform an action in Gim, preceded by a colon, i.e. `:instruction` +* **Command Line Interface (CLI)**: Interface that relies on keyboard inputs to interact with the system. +* **Exercise**: Physical activity done in a regular gym that is structured and repetitive, usually involving some weights. +* **Graphical User Interface (GUI)**: Interface that relies on mouse inputs on visible components to interact with the system. +* **Index**: Number associated to an Exercise in the [Exercise List](#42-exercise-list). +* **JavaScript Object Notation (JSON)**: Filetype used for storing the user's data that can be edited using a text editor. +* **Parameters**: Inputs for commands that you come up with. +* **Personal Record (PR)**: Heaviest weight recorded in the exercise tracker for a specific exercise. +* **Reps**: Number of times you perform a specific exercise. +* **Sets**: Number of cycles of reps that you complete. +* **Vim**: A text editor, known for being lightweight, fast and efficient. It can be controlled entirely with the keyboard with no need for menus or a mouse. +* **Weight**: Total weight of equipment (in kg). + +Back To Table of Contents diff --git a/docs/_config.yml b/docs/_config.yml index 6bd245d8f4e..b176aeb2764 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,4 +1,4 @@ -title: "AB-3" +title: "Gim" theme: minima header_pages: @@ -8,7 +8,7 @@ header_pages: markdown: kramdown -repository: "se-edu/addressbook-level3" +repository: "AY2223S1-CS2103T-T15-4/tp" github_icon: "images/github-icon.png" plugins: diff --git a/docs/_sass/minima/_base.scss b/docs/_sass/minima/_base.scss index 0d3f6e80ced..4e602615818 100644 --- a/docs/_sass/minima/_base.scss +++ b/docs/_sass/minima/_base.scss @@ -288,8 +288,7 @@ table { text-align: center; } .site-header:before { - content: "AB-3"; + content: "Gim"; font-size: 32px; } } - diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml index ef81d18c337..96431b17948 100644 --- a/docs/diagrams/ArchitectureSequenceDiagram.puml +++ b/docs/diagrams/ArchitectureSequenceDiagram.puml @@ -7,19 +7,19 @@ Participant ":Logic" as logic LOGIC_COLOR Participant ":Model" as model MODEL_COLOR Participant ":Storage" as storage STORAGE_COLOR -user -[USER_COLOR]> ui : "delete 1" +user -[USER_COLOR]> ui : ":del 1" activate ui UI_COLOR -ui -[UI_COLOR]> logic : execute("delete 1") +ui -[UI_COLOR]> logic : execute(":del 1") activate logic LOGIC_COLOR -logic -[LOGIC_COLOR]> model : deletePerson(p) +logic -[LOGIC_COLOR]> model : deleteExercise(p) activate model MODEL_COLOR model -[MODEL_COLOR]-> logic deactivate model -logic -[LOGIC_COLOR]> storage : saveAddressBook(addressBook) +logic -[LOGIC_COLOR]> storage : saveExerciseTracker(exerciseTracker) activate storage STORAGE_COLOR storage -[STORAGE_COLOR]> storage : Save to file diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/BetterModelClassDiagram.puml index 5731f9cbaa1..afa48044358 100644 --- a/docs/diagrams/BetterModelClassDiagram.puml +++ b/docs/diagrams/BetterModelClassDiagram.puml @@ -4,18 +4,18 @@ skinparam arrowThickness 1.1 skinparam arrowColor MODEL_COLOR skinparam classBackgroundColor MODEL_COLOR -AddressBook *-right-> "1" UniquePersonList -AddressBook *-right-> "1" UniqueTagList -UniqueTagList -[hidden]down- UniquePersonList -UniqueTagList -[hidden]down- UniquePersonList +ExerciseTracker *-right-> "1" UniqueExerciseList +ExerciseTracker *-right-> "1" UniqueTagList +UniqueTagList -[hidden]down- UniqueExerciseList +UniqueTagList -[hidden]down- UniqueExerciseList UniqueTagList *-right-> "*" Tag -UniquePersonList -right-> Person +UniqueExerciseList -right-> Exercise -Person -up-> "*" Tag +Exercise -up-> "*" Tag -Person *--> Name -Person *--> Phone -Person *--> Email -Person *--> Address +Exercise *--> Name +Exercise *--> Weight +Exercise *--> Sets +Exercise *--> Address @enduml diff --git a/docs/diagrams/CommitActivityDiagram.puml b/docs/diagrams/CommitActivityDiagram.puml index 6a6b23a006f..85eef30fdc7 100644 --- a/docs/diagrams/CommitActivityDiagram.puml +++ b/docs/diagrams/CommitActivityDiagram.puml @@ -5,10 +5,10 @@ start 'Since the beta syntax does not support placing the condition outside the 'diamond we place it as the true branch instead. -if () then ([command commits AddressBook]) +if () then ([command commits ExerciseTracker]) :Purge redundant states; - :Save AddressBook to - addressBookStateList; + :Save ExerciseTracker to + exerciseTrackerStateList; else ([else]) endif stop diff --git a/docs/diagrams/DateClassDiagram.puml b/docs/diagrams/DateClassDiagram.puml new file mode 100644 index 00000000000..d85cbd2abb2 --- /dev/null +++ b/docs/diagrams/DateClassDiagram.puml @@ -0,0 +1,19 @@ +@startuml +!include style.puml +skinparam arrowThickness 1.1 +skinparam arrowColor MODEL_COLOR +skinparam classBackgroundColor MODEL_COLOR + +Package Model <>{ + +Class Date +Class FormatterList +Class RegexList + +} + +Date --> "1" FormatterList: uses > +Date --> "1" RegexList: uses > + + +@enduml diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeleteSequenceDiagram.puml index 1dc2311b245..7d8a4695498 100644 --- a/docs/diagrams/DeleteSequenceDiagram.puml +++ b/docs/diagrams/DeleteSequenceDiagram.puml @@ -3,7 +3,7 @@ box Logic LOGIC_COLOR_T1 participant ":LogicManager" as LogicManager LOGIC_COLOR -participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR +participant ":ExerciseTrackerParser" as ExerciseTrackerParser LOGIC_COLOR participant ":DeleteCommandParser" as DeleteCommandParser LOGIC_COLOR participant "d:DeleteCommand" as DeleteCommand LOGIC_COLOR participant ":CommandResult" as CommandResult LOGIC_COLOR @@ -13,20 +13,20 @@ box Model MODEL_COLOR_T1 participant ":Model" as Model MODEL_COLOR end box -[-> LogicManager : execute("delete 1") +[-> LogicManager : execute(":del 1") activate LogicManager -LogicManager -> AddressBookParser : parseCommand("delete 1") -activate AddressBookParser +LogicManager -> ExerciseTrackerParser : parseCommand(":del 1") +activate ExerciseTrackerParser create DeleteCommandParser -AddressBookParser -> DeleteCommandParser +ExerciseTrackerParser -> DeleteCommandParser activate DeleteCommandParser -DeleteCommandParser --> AddressBookParser +DeleteCommandParser --> ExerciseTrackerParser deactivate DeleteCommandParser -AddressBookParser -> DeleteCommandParser : parse("1") +ExerciseTrackerParser -> DeleteCommandParser : parse("1") activate DeleteCommandParser create DeleteCommand @@ -36,19 +36,19 @@ activate DeleteCommand DeleteCommand --> DeleteCommandParser : d deactivate DeleteCommand -DeleteCommandParser --> AddressBookParser : d +DeleteCommandParser --> ExerciseTrackerParser : d deactivate DeleteCommandParser 'Hidden arrow to position the destroy marker below the end of the activation bar. -DeleteCommandParser -[hidden]-> AddressBookParser +DeleteCommandParser -[hidden]-> ExerciseTrackerParser destroy DeleteCommandParser -AddressBookParser --> LogicManager : d -deactivate AddressBookParser +ExerciseTrackerParser --> LogicManager : d +deactivate ExerciseTrackerParser LogicManager -> DeleteCommand : execute() activate DeleteCommand -DeleteCommand -> Model : deletePerson(1) +DeleteCommand -> Model : deleteExercise(1) activate Model Model --> DeleteCommand diff --git a/docs/diagrams/GenerateWorkoutSequenceDiagram.puml b/docs/diagrams/GenerateWorkoutSequenceDiagram.puml new file mode 100644 index 00000000000..77687bfc217 --- /dev/null +++ b/docs/diagrams/GenerateWorkoutSequenceDiagram.puml @@ -0,0 +1,76 @@ +@startuml +!include style.puml +skinparam sequenceReferenceBackgroundColor AntiqueWhite + +box Logic LOGIC_COLOR_T1 +participant ":Logic\nManager" as LogicManager LOGIC_COLOR +participant ":ExerciseTracker\nParser" as ExerciseTrackerParser LOGIC_COLOR +participant ":Generate\nCommandParser" as GenerateCommandParser LOGIC_COLOR +participant "g:Generate\nCommand" as GenerateCommand LOGIC_COLOR +participant GeneratorFactory as "<>\nGenerator\nFactory" LOGIC_COLOR +participant ":Command\nResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Model" as Model MODEL_COLOR +end box + +[-> LogicManager : execute\n(":gen 1,2 level/easy") +activate LogicManager + +LogicManager -> ExerciseTrackerParser : parseCommand\n(":gen 1,2 level/easy") +activate ExerciseTrackerParser + +create GenerateCommandParser +ExerciseTrackerParser -> GenerateCommandParser +activate GenerateCommandParser + +GenerateCommandParser --> ExerciseTrackerParser +deactivate GenerateCommandParser + +ExerciseTrackerParser -> GenerateCommandParser : parse\n("1,2 level/easy") +activate GenerateCommandParser + +create GenerateCommand +GenerateCommandParser -> GenerateCommand +activate GenerateCommand + +GenerateCommand --> GenerateCommandParser : g +deactivate GenerateCommand + +GenerateCommandParser --> ExerciseTrackerParser : g +deactivate GenerateCommandParser + +GenerateCommandParser -[hidden]-> ExerciseTrackerParser +destroy GenerateCommandParser + +ExerciseTrackerParser --> LogicManager : g +deactivate ExerciseTrackerParser + +LogicManager -> GenerateCommand : execute() +activate GenerateCommand + + +GenerateCommand -> Model : getExercisePR(exerciseName) +activate Model +Model --> GenerateCommand : exercisePR +deactivate Model + +ref over GenerateCommand, GeneratorFactory +get suggested workouts +end ref + +create CommandResult +GenerateCommand -> CommandResult +activate CommandResult + +CommandResult --> GenerateCommand +deactivate CommandResult + +GenerateCommand --> LogicManager : result +deactivate GenerateCommand + +[<--LogicManager +deactivate LogicManager + +@enduml diff --git a/docs/diagrams/GeneratorCommandPattern.puml b/docs/diagrams/GeneratorCommandPattern.puml new file mode 100644 index 00000000000..d4c08eaf493 --- /dev/null +++ b/docs/diagrams/GeneratorCommandPattern.puml @@ -0,0 +1,19 @@ +@startuml +!include style.puml +skinparam arrowThickness 1.1 +skinparam arrowColor LOGIC_COLOR_T4 +skinparam classBackgroundColor LOGIC_COLOR +skinparam classAttributeIconSize 0 + + +Class "<>\nGenerator" as Generator +Generator : + suggest() +GenerateCommand .right.> Generator : gets suggestion from > + + +GeneratorFactory .right.> XYZGenerator : creates > +XYZGenerator -up-|> Generator + +note right of XYZGenerator: XYZGenerator = EasyGenerator, \nMediumGenerator, etc + +@enduml diff --git a/docs/diagrams/GetSuggestionSequenceDiagram.puml b/docs/diagrams/GetSuggestionSequenceDiagram.puml new file mode 100644 index 00000000000..0365609fcab --- /dev/null +++ b/docs/diagrams/GetSuggestionSequenceDiagram.puml @@ -0,0 +1,61 @@ +@startuml +!include style.puml + +group sd get suggested workouts +box LOGIC_COLOR_T1 + +participant "g:GenerateCommand" as GenerateCommand LOGIC_COLOR +participant GeneratorFactory as "<>\nGeneratorFactory" LOGIC_COLOR +participant "s:EasyGenerator" as EasyGeneratorSquat LOGIC_COLOR +participant "d:EasyGenerator" as EasyGeneratorDeadlift LOGIC_COLOR + + +activate GenerateCommand +GenerateCommand -> GeneratorFactory : getGenerator(squatPR, EASY) + +activate GeneratorFactory +create EasyGeneratorSquat + +GeneratorFactory -> EasyGeneratorSquat : EasyGenerator(squatPR) +activate EasyGeneratorSquat + +EasyGeneratorSquat --> GeneratorFactory : s +deactivate EasyGeneratorSquat + +GeneratorFactory --> GenerateCommand : s +deactivate GeneratorFactory + +GenerateCommand -> EasyGeneratorSquat : suggest() +activate EasyGeneratorSquat + +EasyGeneratorSquat --> GenerateCommand : suggested workout for squat +deactivate EasyGeneratorSquat + +EasyGeneratorSquat -[hidden]> GenerateCommand +destroy EasyGeneratorSquat + +GenerateCommand -> GeneratorFactory : getGenerator(deadliftPR, EASY) + +activate GeneratorFactory +create EasyGeneratorDeadlift + +GeneratorFactory -> EasyGeneratorDeadlift : EasyGenerator(deadliftPR) +activate EasyGeneratorDeadlift + +EasyGeneratorDeadlift --> GeneratorFactory : d +deactivate EasyGeneratorDeadlift + +GeneratorFactory --> GenerateCommand : d +deactivate GeneratorFactory + +GenerateCommand -> EasyGeneratorDeadlift : suggest() +activate EasyGeneratorDeadlift + +EasyGeneratorDeadlift --> GenerateCommand : suggested workout for deadlift +deactivate EasyGeneratorDeadlift + +EasyGeneratorDeadlift -[hidden]> GenerateCommand +destroy EasyGeneratorDeadlift + +end +@enduml diff --git a/docs/diagrams/ListPersonalRecordSequenceDiagram.puml b/docs/diagrams/ListPersonalRecordSequenceDiagram.puml new file mode 100644 index 00000000000..019f01d74fd --- /dev/null +++ b/docs/diagrams/ListPersonalRecordSequenceDiagram.puml @@ -0,0 +1,72 @@ +@startuml +!include style.puml +skinparam sequenceReferenceBackgroundColor AntiqueWhite + +box Logic LOGIC_COLOR_T1 +participant ":Logic\nManager" as LogicManager LOGIC_COLOR +participant ":ExerciseTracker\nParser" as ExerciseTrackerParser LOGIC_COLOR +participant ":Pr\nCommandParser" as PrCommandParser LOGIC_COLOR +participant "command:Pr\nCommand" as PrCommand LOGIC_COLOR +participant GeneratorFactory as "<>\nGenerator\nFactory" LOGIC_COLOR +participant ":Command\nResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Model" as Model MODEL_COLOR +end box + +[-> LogicManager : execute\n(":pr n/Squat") +activate LogicManager + +LogicManager -> ExerciseTrackerParser : parseCommand\n(":pr n/Squat") +activate ExerciseTrackerParser + +create PrCommandParser +ExerciseTrackerParser -> PrCommandParser +activate PrCommandParser + +PrCommandParser --> ExerciseTrackerParser +deactivate PrCommandParser + +ExerciseTrackerParser -> PrCommandParser : parse("n/Squat") +activate PrCommandParser + +create PrCommand +PrCommandParser -> PrCommand +activate PrCommand + +PrCommand --> PrCommandParser : command +deactivate PrCommand + +PrCommandParser --> ExerciseTrackerParser : command +deactivate PrCommandParser + +PrCommandParser -[hidden]-> ExerciseTrackerParser +destroy PrCommandParser + +ExerciseTrackerParser --> LogicManager : command +deactivate ExerciseTrackerParser + +LogicManager -> PrCommand : execute() +activate PrCommand + + +PrCommand -> Model : getExercisePR(exerciseName) +activate Model +Model --> PrCommand : exerciseWithPR +deactivate Model + +create CommandResult +PrCommand -> CommandResult +activate CommandResult + +CommandResult --> PrCommand +deactivate CommandResult + +PrCommand --> LogicManager : commandResult +deactivate PrCommand + +[<--LogicManager +deactivate LogicManager + +@enduml diff --git a/docs/diagrams/LogicClassDiagram.puml b/docs/diagrams/LogicClassDiagram.puml index d4193173e18..f2ced9dd900 100644 --- a/docs/diagrams/LogicClassDiagram.puml +++ b/docs/diagrams/LogicClassDiagram.puml @@ -6,7 +6,7 @@ skinparam classBackgroundColor LOGIC_COLOR package Logic { -Class AddressBookParser +Class ExerciseTrackerParser Class XYZCommand Class CommandResult Class "{abstract}\nCommand" as Command @@ -27,8 +27,8 @@ Class HiddenOutside #FFFFFF HiddenOutside ..> Logic LogicManager .right.|> Logic -LogicManager -right->"1" AddressBookParser -AddressBookParser ..> XYZCommand : creates > +LogicManager -right->"1" ExerciseTrackerParser +ExerciseTrackerParser ..> XYZCommand : creates > XYZCommand -up-|> Command LogicManager .left.> Command : executes > @@ -38,7 +38,7 @@ LogicManager --> Storage Storage --[hidden] Model Command .[hidden]up.> Storage Command .right.> Model -note right of XYZCommand: XYZCommand = AddCommand, \nFindCommand, etc +note right of XYZCommand: XYZCommand = AddCommand, \nFilterCommand, etc Logic ..> CommandResult LogicManager .down.> CommandResult diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml index 4439108973a..e37d4327d07 100644 --- a/docs/diagrams/ModelClassDiagram.puml +++ b/docs/diagrams/ModelClassDiagram.puml @@ -5,46 +5,45 @@ skinparam arrowColor MODEL_COLOR skinparam classBackgroundColor MODEL_COLOR Package Model <>{ -Class "<>\nReadOnlyAddressBook" as ReadOnlyAddressBook +Class "<>\nReadOnlyExerciseTracker" as ReadOnlyExerciseTracker Class "<>\nReadOnlyUserPrefs" as ReadOnlyUserPrefs Class "<>\nModel" as Model -Class AddressBook +Class ExerciseTracker Class ModelManager Class UserPrefs -Class UniquePersonList -Class Person -Class Address -Class Email +Class ExerciseList +Class ExerciseHashMap +Class Exercise Class Name -Class Phone -Class Tag +Class Weight +Class Reps +Class Sets +Class Date } Class HiddenOutside #FFFFFF HiddenOutside ..> Model -AddressBook .up.|> ReadOnlyAddressBook +ExerciseTracker .up.|> ReadOnlyExerciseTracker ModelManager .up.|> Model Model .right.> ReadOnlyUserPrefs -Model .left.> ReadOnlyAddressBook -ModelManager -left-> "1" AddressBook +Model .left.> ReadOnlyExerciseTracker +ModelManager -left-> "1" ExerciseTracker ModelManager -right-> "1" UserPrefs UserPrefs .up.|> ReadOnlyUserPrefs -AddressBook *--> "1" UniquePersonList -UniquePersonList --> "~* all" Person -Person *--> Name -Person *--> Phone -Person *--> Email -Person *--> Address -Person *--> "*" Tag - -Name -[hidden]right-> Phone -Phone -[hidden]right-> Address -Address -[hidden]right-> Email - -ModelManager -->"~* filtered" Person +ExerciseTracker *--> "1" ExerciseList +ExerciseTracker *--> "1" ExerciseHashMap +ExerciseHashMap ---> "~*" Exercise +ExerciseList ---> "~*" Exercise +Exercise *--> Name +Exercise *--> Weight +Exercise *--> Reps +Exercise *--> Sets +Exercise *--> Date + +ModelManager -->"~* filtered" Exercise @enduml diff --git a/docs/diagrams/NotifyObservers.puml b/docs/diagrams/NotifyObservers.puml new file mode 100644 index 00000000000..fa9887f2b40 --- /dev/null +++ b/docs/diagrams/NotifyObservers.puml @@ -0,0 +1,39 @@ +@startuml +!include style.puml + +box MODEL_COLOR_T1 +participant ":ExerciseHashMap" as ExerciseHashMap MODEL_COLOR +end box +box + +box UI_COLOR_T1 +participant ":SavedExerciseListWindow" as SavedExerciseListWindow UI_COLOR +end box + +box MODEL_COLOR_T1 +participant ":ExerciseKeys" as ExerciseKeys MODEL_COLOR +end box + +[-> ExerciseHashMap : notifyObservers() +activate ExerciseHashMap + +ExerciseHashMap -> SavedExerciseListWindow : update() +activate SavedExerciseListWindow + +create ExerciseKeys +SavedExerciseListWindow -> ExerciseKeys +activate ExerciseKeys + +ExerciseKeys -> ExerciseKeys :getDisplay() +ExerciseKeys --> SavedExerciseListWindow +deactivate ExerciseKeys + +SavedExerciseListWindow -> SavedExerciseListWindow :setText(display) +SavedExerciseListWindow --> ExerciseHashMap +deactivate SavedExerciseListWindow + +[<-- ExerciseHashMap +deactivate ExerciseHashMap + + +@enduml diff --git a/docs/diagrams/ObserverPattern.puml b/docs/diagrams/ObserverPattern.puml new file mode 100644 index 00000000000..850427fff60 --- /dev/null +++ b/docs/diagrams/ObserverPattern.puml @@ -0,0 +1,27 @@ +@startuml +!include style.puml +skinparam classAttributeIconSize 0 + +Package " " <> { + Class "<>\nObserver" as Observer LOGIC_COLOR + Class ExerciseHashMap MODEL_COLOR + Class SavedExerciseListWindow UI_COLOR + Class ExerciseKeys MODEL_COLOR +} + +ExerciseHashMap : - internalArrayList : ArrayList +ExerciseHashMap : - notifyObservers() +ExerciseHashMap : + addUI(Observer) + +SavedExerciseListWindow : + update() +SavedExerciseListWindow : -exerciseHashMap : ExerciseHashMap + +Observer : + update() + +ExerciseKeys : + getDisplay() + +ExerciseHashMap - "*" Observer +SavedExerciseListWindow ..|> Observer +SavedExerciseListWindow --> ExerciseKeys + +@enduml diff --git a/docs/diagrams/ParserClasses.puml b/docs/diagrams/ParserClasses.puml index 0c7424de6e0..243335feb71 100644 --- a/docs/diagrams/ParserClasses.puml +++ b/docs/diagrams/ParserClasses.puml @@ -9,7 +9,7 @@ Class XYZCommand package "Parser classes"{ Class "<>\nParser" as Parser -Class AddressBookParser +Class ExerciseTrackerParser Class XYZCommandParser Class CliSyntax Class ParserUtil @@ -19,12 +19,12 @@ Class Prefix } Class HiddenOutside #FFFFFF -HiddenOutside ..> AddressBookParser +HiddenOutside ..> ExerciseTrackerParser -AddressBookParser .down.> XYZCommandParser: creates > +ExerciseTrackerParser .down.> XYZCommandParser: creates > XYZCommandParser ..> XYZCommand : creates > -AddressBookParser ..> Command : returns > +ExerciseTrackerParser ..> Command : returns > XYZCommandParser .up.|> Parser XYZCommandParser ..> ArgumentMultimap XYZCommandParser ..> ArgumentTokenizer diff --git a/docs/diagrams/RangeSequenceDiagram.puml b/docs/diagrams/RangeSequenceDiagram.puml new file mode 100644 index 00000000000..d8693bb2c11 --- /dev/null +++ b/docs/diagrams/RangeSequenceDiagram.puml @@ -0,0 +1,69 @@ +@startuml +!include style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":ExerciseTrackerParser" as ExerciseTrackerParser LOGIC_COLOR +participant ":RangeCommandParser" as RangeCommandParser LOGIC_COLOR +participant "r:RangeCommand" as RangeCommand LOGIC_COLOR +participant ":CommandResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Model" as Model MODEL_COLOR +end box + +[-> LogicManager : execute(command) +activate LogicManager + +LogicManager -> ExerciseTrackerParser : parseCommand(command) +activate ExerciseTrackerParser + +create RangeCommandParser +ExerciseTrackerParser -> RangeCommandParser +activate RangeCommandParser + +RangeCommandParser --> ExerciseTrackerParser +deactivate RangeCommandParser + +ExerciseTrackerParser -> RangeCommandParser : parse(arguments) +activate RangeCommandParser + +create RangeCommand +RangeCommandParser -> RangeCommand +activate RangeCommand + +RangeCommand --> RangeCommandParser : r +deactivate RangeCommand + +RangeCommandParser --> ExerciseTrackerParser : r +deactivate RangeCommandParser +'Hidden arrow to position the destroy marker below the end of the activation bar. +RangeCommandParser -[hidden]-> ExerciseTrackerParser +destroy RangeCommandParser + +ExerciseTrackerParser --> LogicManager : r +deactivate ExerciseTrackerParser + +LogicManager -> RangeCommand : execute() +activate RangeCommand + +RangeCommand -> Model : sortFilteredExerciseList(DateWithinRangePredicate) +activate Model + +Model --> RangeCommand +deactivate Model + +create CommandResult +RangeCommand -> CommandResult +activate CommandResult + +CommandResult --> RangeCommand +deactivate CommandResult + +RangeCommand --> LogicManager : result +deactivate RangeCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/SortSequenceDiagram.puml b/docs/diagrams/SortSequenceDiagram.puml new file mode 100644 index 00000000000..ab6ee0b471a --- /dev/null +++ b/docs/diagrams/SortSequenceDiagram.puml @@ -0,0 +1,52 @@ +@startuml +!include style.puml + +box Logic LOGIC_COLOR_T1 +participant ":LogicManager" as LogicManager LOGIC_COLOR +participant ":ExerciseTrackerParser" as ExerciseTrackerParser LOGIC_COLOR +participant "s:SortCommand" as SortCommand LOGIC_COLOR +participant ":CommandResult" as CommandResult LOGIC_COLOR +end box + +box Model MODEL_COLOR_T1 +participant ":Model" as Model MODEL_COLOR +end box + +[-> LogicManager : execute(":sort") +activate LogicManager + +LogicManager -> ExerciseTrackerParser : parseCommand(":sort") +activate ExerciseTrackerParser + +create SortCommand +ExerciseTrackerParser -> SortCommand +activate SortCommand + +SortCommand --> ExerciseTrackerParser +deactivate SortCommand + +ExerciseTrackerParser --> LogicManager : s +deactivate ExerciseTrackerParser + +LogicManager -> SortCommand : execute() +activate SortCommand + +SortCommand -> Model : sortDisplayedList() +activate Model + +Model --> SortCommand +deactivate Model + +create CommandResult +SortCommand -> CommandResult +activate CommandResult + +CommandResult --> SortCommand +deactivate CommandResult + +SortCommand --> LogicManager : result +deactivate SortCommand + +[<--LogicManager +deactivate LogicManager +@enduml diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml index 760305e0e58..047cd6924e8 100644 --- a/docs/diagrams/StorageClassDiagram.puml +++ b/docs/diagrams/StorageClassDiagram.puml @@ -14,12 +14,12 @@ Class JsonUserPrefsStorage Class "<>\nStorage" as Storage Class StorageManager -package "AddressBook Storage" #F4F6F6{ -Class "<>\nAddressBookStorage" as AddressBookStorage -Class JsonAddressBookStorage -Class JsonSerializableAddressBook -Class JsonAdaptedPerson -Class JsonAdaptedTag +package "ExerciseTracker Storage" #F4F6F6{ +Class "<>\nExerciseTrackerStorage" as ExerciseTrackerStorage +Class JsonExerciseTrackerStorage +Class JsonSerializableExerciseTracker +Class JsonAdaptedExercise +Class JsonAdaptedDate } } @@ -29,15 +29,15 @@ HiddenOutside ..> Storage StorageManager .up.|> Storage StorageManager -up-> "1" UserPrefsStorage -StorageManager -up-> "1" AddressBookStorage +StorageManager -up-> "1" ExerciseTrackerStorage Storage -left-|> UserPrefsStorage -Storage -right-|> AddressBookStorage +Storage -right-|> ExerciseTrackerStorage JsonUserPrefsStorage .up.|> UserPrefsStorage -JsonAddressBookStorage .up.|> AddressBookStorage -JsonAddressBookStorage ..> JsonSerializableAddressBook -JsonSerializableAddressBook --> "*" JsonAdaptedPerson -JsonAdaptedPerson --> "*" JsonAdaptedTag +JsonExerciseTrackerStorage .up.|> ExerciseTrackerStorage +JsonExerciseTrackerStorage ..> JsonSerializableExerciseTracker +JsonSerializableExerciseTracker --> "*" JsonAdaptedExercise +JsonAdaptedExercise --> "1" JsonAdaptedDate @enduml diff --git a/docs/diagrams/UiClassDiagram.puml b/docs/diagrams/UiClassDiagram.puml index 95473d5aa19..d7f273d591b 100644 --- a/docs/diagrams/UiClassDiagram.puml +++ b/docs/diagrams/UiClassDiagram.puml @@ -11,10 +11,11 @@ Class UiManager Class MainWindow Class HelpWindow Class ResultDisplay -Class PersonListPanel -Class PersonCard +Class ExerciseListPanel +Class ExerciseCard Class StatusBarFooter Class CommandBox +Class SavedExerciseListWindow } package Model <> { @@ -31,27 +32,30 @@ HiddenOutside ..> Ui UiManager .left.|> Ui UiManager -down-> "1" MainWindow MainWindow *-down-> "1" CommandBox +MainWindow *-down-> "1" SavedExerciseListWindow MainWindow *-down-> "1" ResultDisplay -MainWindow *-down-> "1" PersonListPanel +MainWindow *-down-> "1" ExerciseListPanel MainWindow *-down-> "1" StatusBarFooter MainWindow --> "0..1" HelpWindow -PersonListPanel -down-> "*" PersonCard +ExerciseListPanel -down-> "*" ExerciseCard MainWindow -left-|> UiPart ResultDisplay --|> UiPart CommandBox --|> UiPart -PersonListPanel --|> UiPart -PersonCard --|> UiPart +ExerciseListPanel --|> UiPart +ExerciseCard --|> UiPart StatusBarFooter --|> UiPart HelpWindow --|> UiPart +SavedExerciseListWindow --up|> UiPart -PersonCard ..> Model + +ExerciseCard ..> Model UiManager -right-> Logic MainWindow -left-> Logic -PersonListPanel -[hidden]left- HelpWindow +ExerciseListPanel -[hidden]left- HelpWindow HelpWindow -[hidden]left- CommandBox CommandBox -[hidden]left- ResultDisplay ResultDisplay -[hidden]left- StatusBarFooter diff --git a/docs/diagrams/UndoRedoState0.puml b/docs/diagrams/UndoRedoState0.puml index 96e30744d24..df9a43272cb 100644 --- a/docs/diagrams/UndoRedoState0.puml +++ b/docs/diagrams/UndoRedoState0.puml @@ -6,9 +6,9 @@ skinparam ClassBorderColor #000000 title Initial state package States { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" + class State1 as "__ab0:ExerciseTracker__" + class State2 as "__ab1:ExerciseTracker__" + class State3 as "__ab2:ExerciseTracker__" } State1 -[hidden]right-> State2 State2 -[hidden]right-> State3 diff --git a/docs/diagrams/UndoRedoState1.puml b/docs/diagrams/UndoRedoState1.puml index 01fcb9b2b96..be16fefe60a 100644 --- a/docs/diagrams/UndoRedoState1.puml +++ b/docs/diagrams/UndoRedoState1.puml @@ -6,9 +6,9 @@ skinparam ClassBorderColor #000000 title After command "delete 5" package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" + class State1 as "__ab0:ExerciseTracker__" + class State2 as "__ab1:ExerciseTracker__" + class State3 as "__ab2:ExerciseTracker__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoRedoState2.puml b/docs/diagrams/UndoRedoState2.puml index bccc230a5d1..c556df9c9f8 100644 --- a/docs/diagrams/UndoRedoState2.puml +++ b/docs/diagrams/UndoRedoState2.puml @@ -6,9 +6,9 @@ skinparam ClassBorderColor #000000 title After command "add n/David" package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" + class State1 as "__ab0:ExerciseTracker__" + class State2 as "__ab1:ExerciseTracker__" + class State3 as "__ab2:ExerciseTracker__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoRedoState3.puml b/docs/diagrams/UndoRedoState3.puml index ea29c9483e4..b5ad64b9e1e 100644 --- a/docs/diagrams/UndoRedoState3.puml +++ b/docs/diagrams/UndoRedoState3.puml @@ -6,9 +6,9 @@ skinparam ClassBorderColor #000000 title After command "undo" package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" + class State1 as "__ab0:ExerciseTracker__" + class State2 as "__ab1:ExerciseTracker__" + class State3 as "__ab2:ExerciseTracker__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoRedoState4.puml b/docs/diagrams/UndoRedoState4.puml index 1b784cece80..f468a7ca528 100644 --- a/docs/diagrams/UndoRedoState4.puml +++ b/docs/diagrams/UndoRedoState4.puml @@ -6,9 +6,9 @@ skinparam ClassBorderColor #000000 title After command "list" package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab2:AddressBook__" + class State1 as "__ab0:ExerciseTracker__" + class State2 as "__ab1:ExerciseTracker__" + class State3 as "__ab2:ExerciseTracker__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoRedoState5.puml b/docs/diagrams/UndoRedoState5.puml index 88927be32bc..4f5be72f718 100644 --- a/docs/diagrams/UndoRedoState5.puml +++ b/docs/diagrams/UndoRedoState5.puml @@ -6,9 +6,9 @@ skinparam ClassBorderColor #000000 title After command "clear" package States <> { - class State1 as "__ab0:AddressBook__" - class State2 as "__ab1:AddressBook__" - class State3 as "__ab3:AddressBook__" + class State1 as "__ab0:ExerciseTracker__" + class State2 as "__ab1:ExerciseTracker__" + class State3 as "__ab3:ExerciseTracker__" } State1 -[hidden]right-> State2 diff --git a/docs/diagrams/UndoSequenceDiagram.puml b/docs/diagrams/UndoSequenceDiagram.puml index 410aab4e412..e43dff2eb58 100644 --- a/docs/diagrams/UndoSequenceDiagram.puml +++ b/docs/diagrams/UndoSequenceDiagram.puml @@ -3,42 +3,42 @@ box Logic LOGIC_COLOR_T1 participant ":LogicManager" as LogicManager LOGIC_COLOR -participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR +participant ":ExerciseTrackerParser" as ExerciseTrackerParser LOGIC_COLOR participant "u:UndoCommand" as UndoCommand LOGIC_COLOR end box box Model MODEL_COLOR_T1 participant ":Model" as Model MODEL_COLOR -participant ":VersionedAddressBook" as VersionedAddressBook MODEL_COLOR +participant ":VersionedExerciseTracker" as VersionedExerciseTracker MODEL_COLOR end box [-> LogicManager : execute(undo) activate LogicManager -LogicManager -> AddressBookParser : parseCommand(undo) -activate AddressBookParser +LogicManager -> ExerciseTrackerParser : parseCommand(undo) +activate ExerciseTrackerParser create UndoCommand -AddressBookParser -> UndoCommand +ExerciseTrackerParser -> UndoCommand activate UndoCommand -UndoCommand --> AddressBookParser +UndoCommand --> ExerciseTrackerParser deactivate UndoCommand -AddressBookParser --> LogicManager : u -deactivate AddressBookParser +ExerciseTrackerParser --> LogicManager : u +deactivate ExerciseTrackerParser LogicManager -> UndoCommand : execute() activate UndoCommand -UndoCommand -> Model : undoAddressBook() +UndoCommand -> Model : undoExerciseTracker() activate Model -Model -> VersionedAddressBook : undo() -activate VersionedAddressBook +Model -> VersionedExerciseTracker : undo() +activate VersionedExerciseTracker -VersionedAddressBook -> VersionedAddressBook :resetData(ReadOnlyAddressBook) -VersionedAddressBook --> Model : -deactivate VersionedAddressBook +VersionedExerciseTracker -> VersionedExerciseTracker :resetData(ReadOnlyExerciseTracker) +VersionedExerciseTracker --> Model : +deactivate VersionedExerciseTracker Model --> UndoCommand deactivate Model diff --git a/docs/diagrams/style.puml b/docs/diagrams/style.puml index fad8b0adeaa..15af441b367 100644 --- a/docs/diagrams/style.puml +++ b/docs/diagrams/style.puml @@ -71,5 +71,5 @@ skinparam DefaultTextAlignment center skinparam packageStyle Rectangle hide footbox -hide members +hide empty members hide circle diff --git a/docs/diagrams/tracing/LogicSequenceDiagram.puml b/docs/diagrams/tracing/LogicSequenceDiagram.puml index fdcbe1c0ccc..73e6480e8ba 100644 --- a/docs/diagrams/tracing/LogicSequenceDiagram.puml +++ b/docs/diagrams/tracing/LogicSequenceDiagram.puml @@ -2,7 +2,7 @@ !include ../style.puml Participant ":LogicManager" as logic LOGIC_COLOR -Participant ":AddressBookParser" as abp LOGIC_COLOR +Participant ":ExerciseTrackerParser" as abp LOGIC_COLOR Participant ":EditCommandParser" as ecp LOGIC_COLOR Participant "command:EditCommand" as ec LOGIC_COLOR @@ -13,7 +13,7 @@ create ecp abp -> ecp abp -> ecp ++: parse(arguments) create ec -ecp -> ec ++: index, editPersonDescriptor +ecp -> ec ++: index, editExerciseDescriptor ec --> ecp -- ecp --> abp --: command abp --> logic --: command diff --git a/docs/images/24donovan24.png b/docs/images/24donovan24.png new file mode 100644 index 00000000000..9ec4a3c6956 Binary files /dev/null and b/docs/images/24donovan24.png differ diff --git a/docs/images/AddCommand.png b/docs/images/AddCommand.png new file mode 100644 index 00000000000..43fd73bedac Binary files /dev/null and b/docs/images/AddCommand.png differ diff --git a/docs/images/ArchitectureSequenceDiagram.png b/docs/images/ArchitectureSequenceDiagram.png index 2f1346869d0..273a8097e29 100644 Binary files a/docs/images/ArchitectureSequenceDiagram.png and b/docs/images/ArchitectureSequenceDiagram.png differ diff --git a/docs/images/DateClassDiagram.png b/docs/images/DateClassDiagram.png new file mode 100644 index 00000000000..fb3d8027f0a Binary files /dev/null and b/docs/images/DateClassDiagram.png differ diff --git a/docs/images/DateRangeSequenceDiagram.png b/docs/images/DateRangeSequenceDiagram.png new file mode 100644 index 00000000000..efd0eb9d3cd Binary files /dev/null and b/docs/images/DateRangeSequenceDiagram.png differ diff --git a/docs/images/DeleteCommand.png b/docs/images/DeleteCommand.png new file mode 100644 index 00000000000..3b5d51cb7ee Binary files /dev/null and b/docs/images/DeleteCommand.png differ diff --git a/docs/images/DeleteSequenceDiagram.png b/docs/images/DeleteSequenceDiagram.png index fa327b39618..f9e1e899890 100644 Binary files a/docs/images/DeleteSequenceDiagram.png and b/docs/images/DeleteSequenceDiagram.png differ diff --git a/docs/images/FilterCommand.png b/docs/images/FilterCommand.png new file mode 100644 index 00000000000..08ca51b7821 Binary files /dev/null and b/docs/images/FilterCommand.png differ diff --git a/docs/images/GUIOrientation.png b/docs/images/GUIOrientation.png new file mode 100644 index 00000000000..5ddebf0a977 Binary files /dev/null and b/docs/images/GUIOrientation.png differ diff --git a/docs/images/GenerateCommandExample1.png b/docs/images/GenerateCommandExample1.png new file mode 100644 index 00000000000..2d9efd96c3e Binary files /dev/null and b/docs/images/GenerateCommandExample1.png differ diff --git a/docs/images/GenerateCommandExample2.png b/docs/images/GenerateCommandExample2.png new file mode 100644 index 00000000000..6d5d0c4c628 Binary files /dev/null and b/docs/images/GenerateCommandExample2.png differ diff --git a/docs/images/GenerateCommandNameExample1.png b/docs/images/GenerateCommandNameExample1.png new file mode 100644 index 00000000000..3dbf30fc7b1 Binary files /dev/null and b/docs/images/GenerateCommandNameExample1.png differ diff --git a/docs/images/GenerateWorkoutSequenceDiagram.png b/docs/images/GenerateWorkoutSequenceDiagram.png new file mode 100644 index 00000000000..4b1dceb066e Binary files /dev/null and b/docs/images/GenerateWorkoutSequenceDiagram.png differ diff --git a/docs/images/GeneratorCommandPattern.png b/docs/images/GeneratorCommandPattern.png new file mode 100644 index 00000000000..909bec8ea74 Binary files /dev/null and b/docs/images/GeneratorCommandPattern.png differ diff --git a/docs/images/GetSuggestionSequenceDiagram.png b/docs/images/GetSuggestionSequenceDiagram.png new file mode 100644 index 00000000000..d61306dae68 Binary files /dev/null and b/docs/images/GetSuggestionSequenceDiagram.png differ diff --git a/docs/images/GimLogo.png b/docs/images/GimLogo.png new file mode 100644 index 00000000000..46a74c1f9df Binary files /dev/null and b/docs/images/GimLogo.png differ diff --git a/docs/images/HelpCommand.png b/docs/images/HelpCommand.png new file mode 100644 index 00000000000..3a47ec97557 Binary files /dev/null and b/docs/images/HelpCommand.png differ diff --git a/docs/images/ListAfterSortCommand.png b/docs/images/ListAfterSortCommand.png new file mode 100644 index 00000000000..20942668485 Binary files /dev/null and b/docs/images/ListAfterSortCommand.png differ diff --git a/docs/images/ListPersonalRecord.png b/docs/images/ListPersonalRecord.png new file mode 100644 index 00000000000..7f33034e072 Binary files /dev/null and b/docs/images/ListPersonalRecord.png differ diff --git a/docs/images/ListPersonalRecordSequenceDiagram.png b/docs/images/ListPersonalRecordSequenceDiagram.png new file mode 100644 index 00000000000..0dd57d47ab9 Binary files /dev/null and b/docs/images/ListPersonalRecordSequenceDiagram.png differ diff --git a/docs/images/LogicClassDiagram.png b/docs/images/LogicClassDiagram.png index 9e9ba9f79e5..9c56788c1cc 100644 Binary files a/docs/images/LogicClassDiagram.png and b/docs/images/LogicClassDiagram.png differ diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png index 04070af60d8..d80e9e766dd 100644 Binary files a/docs/images/ModelClassDiagram.png and b/docs/images/ModelClassDiagram.png differ diff --git a/docs/images/NotifyObservers.png b/docs/images/NotifyObservers.png new file mode 100644 index 00000000000..6b585b6ea41 Binary files /dev/null and b/docs/images/NotifyObservers.png differ diff --git a/docs/images/ObserverPattern.png b/docs/images/ObserverPattern.png new file mode 100644 index 00000000000..1cd8eac69de Binary files /dev/null and b/docs/images/ObserverPattern.png differ diff --git a/docs/images/ParserClasses.png b/docs/images/ParserClasses.png index e7b4c8880cd..de096a28266 100644 Binary files a/docs/images/ParserClasses.png and b/docs/images/ParserClasses.png differ diff --git a/docs/images/PrCommandExample1.png b/docs/images/PrCommandExample1.png new file mode 100644 index 00000000000..f3d11620599 Binary files /dev/null and b/docs/images/PrCommandExample1.png differ diff --git a/docs/images/PrCommandExample2.png b/docs/images/PrCommandExample2.png new file mode 100644 index 00000000000..d8218ef6ae1 Binary files /dev/null and b/docs/images/PrCommandExample2.png differ diff --git a/docs/images/RangeCommandOneSample.png b/docs/images/RangeCommandOneSample.png new file mode 100644 index 00000000000..6b081711345 Binary files /dev/null and b/docs/images/RangeCommandOneSample.png differ diff --git a/docs/images/RangeCommandTwoSample.png b/docs/images/RangeCommandTwoSample.png new file mode 100644 index 00000000000..69a42e53f5a Binary files /dev/null and b/docs/images/RangeCommandTwoSample.png differ diff --git a/docs/images/RangeSequenceDiagram.png b/docs/images/RangeSequenceDiagram.png new file mode 100644 index 00000000000..687779693c6 Binary files /dev/null and b/docs/images/RangeSequenceDiagram.png differ diff --git a/docs/images/RecognisedExercisesOrientation.png b/docs/images/RecognisedExercisesOrientation.png new file mode 100644 index 00000000000..29d91f8a607 Binary files /dev/null and b/docs/images/RecognisedExercisesOrientation.png differ diff --git a/docs/images/SortSequenceDiagram.png b/docs/images/SortSequenceDiagram.png new file mode 100644 index 00000000000..18bf6842cf7 Binary files /dev/null and b/docs/images/SortSequenceDiagram.png differ diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png index 2533a5c1af0..1d07a5492f9 100644 Binary files a/docs/images/StorageClassDiagram.png and b/docs/images/StorageClassDiagram.png differ diff --git a/docs/images/Ui.png b/docs/images/Ui.png index 5bd77847aa2..8c9a15c7928 100644 Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ diff --git a/docs/images/UiClassDiagram.png b/docs/images/UiClassDiagram.png index 785e04dbab4..e8089f27af0 100644 Binary files a/docs/images/UiClassDiagram.png and b/docs/images/UiClassDiagram.png differ diff --git a/docs/images/default_Ui.png b/docs/images/default_Ui.png new file mode 100644 index 00000000000..5bd77847aa2 Binary files /dev/null and b/docs/images/default_Ui.png differ diff --git a/docs/images/ee-suan.png b/docs/images/ee-suan.png new file mode 100644 index 00000000000..e1f4f320e5e Binary files /dev/null and b/docs/images/ee-suan.png differ diff --git a/docs/images/ervink123.png b/docs/images/ervink123.png new file mode 100644 index 00000000000..36f8dd04352 Binary files /dev/null and b/docs/images/ervink123.png differ diff --git a/docs/images/kavantan.png b/docs/images/kavantan.png new file mode 100644 index 00000000000..4fe8cb30126 Binary files /dev/null and b/docs/images/kavantan.png differ diff --git a/docs/images/stevenlimhw.png b/docs/images/stevenlimhw.png new file mode 100644 index 00000000000..c6bac8c88ac Binary files /dev/null and b/docs/images/stevenlimhw.png differ diff --git a/docs/index.md b/docs/index.md index 7601dbaad0d..ad7b276ba28 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,17 +1,17 @@ --- layout: page -title: AddressBook Level-3 +title: Gim --- -[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions) -[![codecov](https://codecov.io/gh/se-edu/addressbook-level3/branch/master/graph/badge.svg)](https://codecov.io/gh/se-edu/addressbook-level3) +[![CI Status](https://github.com/AY2223S1-CS2103T-T15-4/tp/workflows/Java%20CI/badge.svg)](https://github.com/AY2223S1-CS2103T-T15-4/tp/actions) +[![codecov](https://codecov.io/gh/AY2223S1-CS2103T-T15-4/tp/branch/master/graph/badge.svg?token=3QLCJGGTH7)](https://codecov.io/gh/AY2223S1-CS2103T-T15-4/tp) ![Ui](images/Ui.png) -**AddressBook is a desktop application for managing your contact details.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface). +Gim is a **desktop app for managing gym exercises, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). Gim builds on the commands of Vim so if you can type fast and are an avid Vim user, Gim can optimize your exercise routines to a much greater capacity than traditional GUI apps. -* If you are interested in using AddressBook, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start). -* If you are interested about developing AddressBook, the [**Developer Guide**](DeveloperGuide.html) is a good place to start. +* If you are interested in using Gim, head over to the [_Getting Started_ section of the **User Guide**](UserGuide.html#3-getting-started). +* If you are interested about developing Gim, the [**Developer Guide**](DeveloperGuide.html) is a good place to start. **Acknowledgements** diff --git a/docs/team/24donovan24.md b/docs/team/24donovan24.md new file mode 100644 index 00000000000..f93d5f75d80 --- /dev/null +++ b/docs/team/24donovan24.md @@ -0,0 +1,50 @@ +--- +layout: page +title: Donovan Lee's Project Portfolio Page +--- + +### Project: Gim + +Gim is a **desktop app for managing gym exercises, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, Gim allows you to keep track your exercises and Personal Records in an efficient way. + +Example usages: +* as a tracking tool to keep track of completed exercises +* as a tracking tool to keep track of your personal records +* as a workout generator to generate exercises based on your personal records + +Given below are my contributions to the project. + +* **New Feature**: Sort command ([PR #100](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/100)) + * What it does: Allows users to sort any displayed list of exercises by date of completion. + * Justification: This feature is essential as sorting the exercises by date of completion allows users to better track their workout progression. + * Highlights: + * Tracing of the code base was necessary to ensure that the sort command is executed on the displayed list of exercises without altering the default ordering of exercises stored in the system. + * A defensive copy of the default ordering of exercises based off entry date has to be maintained to allow users to toggle between a sorted ordering and the default ordering. + * Utilise Open-Closed Principle to accommodate other sorting orders should sorting criteria change in the future. + +* **Code contributed**: [RepoSense Link](https://nus-cs2103-ay2223s1.github.io/tp-dashboard/?search=24donovan24&breakdown=true&sort=groupTitle&sortWithin=title&since=2022-09-16&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) + +* **Enhancements to existing features**: + * Updated the GUI colour scheme ([PR #111](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/111)) + * Added a welcome message when the application is launched ([PR #113](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/113)) + * Added Sets as a field of an Exercise ([PR #53](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/53), [PR #62](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/62), [PR #72](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/72)) + * Added unit tests for Sets ([PR #62](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/62)) + +
+ +* **Documentation**: + * User Guide: + * Added documentation for `:sort` command ([PR #125](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/125)) + * Added documentation for `:filter` command with some edits to existing documentation as per discussed by team ([PR #133](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/133)) + * FAQ ([PR #133](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/133)) + + * Developer Guide: + * Added implementation details for `:sort` command ([PR #101](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/101)) + * Added user stories, use cases and instructions for manual testing as per discussed by team ([PR #211](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/211)) + +* **Contribution to team-based tasks**: + * Reviewed Team Members' PRs. + * Participated and contributed to weekly team meetings. + +* **Tools**: + * PlantUML: Creating UML diagrams. diff --git a/docs/team/ee-suan.md b/docs/team/ee-suan.md new file mode 100644 index 00000000000..4d2f768e232 --- /dev/null +++ b/docs/team/ee-suan.md @@ -0,0 +1,46 @@ +--- +layout: page +title: Ee Suan's Project Portfolio Page +--- + +### Project: Gim + +* Gim is a **desktop app for managing gym exercises, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, Gim allows you to keep track your exercises and Personal Records in a efficient way. + Example usages: + * as a tracking tool to keep track of completed exercises + * as a tracking tool to keep track of your personal records + * as a workout generator to generate exercises based on your personal records + +Given below are my contributions to the project. + +* **New Feature**: Generate command ([PR #118](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/118)) + * What it does: Generates workout suggestions for users based on their personal records, based on difficulty level specified. + * Justification: This feature makes use of the information provided by users to generate a personalised workout session. It makes sensible use of users' personal records. + * Highlights: + * Applied Command pattern in designing how the suggested workout is generated. + * Supports both indexes and exercise names as input. + * Added tests and increased project coverage by +5.73% ([PR #227](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/227)) + +* **Code contributed**: [RepoSense Link](https://nus-cs2103-ay2223s1.github.io/tp-dashboard/?search=ee-suan&breakdown=true&sort=groupTitle&sortWithin=title&since=2022-09-16&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) + + +* **Enhancements to existing features**: + * Added Weight as field for Exercise ([PR #51](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/51)) + * Added unit tests for Weight ([PR #63](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/63)) + +* **Documentation**: + * User Guide: + * Added documentation for `:gen` command ([PR #129](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/129)) + * Updated UML diagrams to reflect current implementation ([PR #213](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/213)) + + * Developer Guide: + * Added implementation and design details to support `:gen` command ([PR #104](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/104)) + +* **Contribution to team-based tasks**: + * Reviewed Team Member's PRs + * Suggested alternative implementation to abide by Open-Closed Principle ([PR #100](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/100)) + * Provided ideas and contributed in discussions during weekly team meeting. + * Suggested alternative phrasing for clarification in UG ([Issue #150](https://github.com/AY2223S1-CS2103T-T15-4/tp/issues/150)) + +* **Tools**: + * PlantUML: Creating UML diagrams. diff --git a/docs/team/ervink123.md b/docs/team/ervink123.md new file mode 100644 index 00000000000..76b4bd87f8e --- /dev/null +++ b/docs/team/ervink123.md @@ -0,0 +1,61 @@ +--- +layout: page +title: Ervin Kin's Project Portfolio Page +--- + +### Project: Gim + +* Gim is a **desktop app for managing gym exercises, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, Gim allows you to keep track your exercises and Personal Records in an efficient way. + +Given below are my contributions to the project. + +* **New Feature**: Recognised Exercises list in bottom right of the GUI ([PR #107](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/107)) + * What it does: Provides User with an idea of what unique exercises they have inputted in the system, updated in real time. + * Justification: This is especially important when the exercise list is populated/ the user has been using the app for a long time. He may accidentally misspell an exercise name when keying it in, causing the system to miss out on a potential personal record/entry. + * Highlights: + * Added Exercise Keys Class which handles logic behind ExerciseHashMap keys. + * Used Observer Pattern design in facilitating real time interaction between ExerciseHashMap and UI. + * Update ExerciseHashMap with relevant methods and fields to support Observer pattern. + * Conducted testing (specifically for ExerciseKeys class and added onto ExerciseHashMap Tests) while designing the feature such that code coverage remained consistent (no change in coverage after push). +* **Code contributed**: [RepoSense Link](https://nus-cs2103-ay2223s1.github.io/tp-dashboard/?search=ervink123&breakdown=true&sort=groupTitle&sortWithin=title&since=2022-09-16&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) + +* **Project management**: + * Managed issue tracker for v1.3 and v1.4 + +* **Enhancements to existing features**: + * Redesigned Help Window ([PR #115](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/115), [PR #141](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/141), [PR #142](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/142)) + * What I did: + * Help window now provides a brief summary of available commands on top of a link to the user guide + * Justification: + * Provides convenience as users can now get some basic help in the help window instead of being redirected to the user guide. This enhancement saves clicks and time in the long run. + * Redesigned User Interface ([PR #84](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/84), [PR #94](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/94), [PR #116](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/116)) + * What I did: + * Moved Result Display window to the right and added Saved Exercises List window. + * Justification: + * For moving the Result Display window and adding the Saved Exercises List window, the previous UI had a lot of wasted real estate as the cards were taking up a lot of space. Furthermore, the result display window was too small and needed to scroll, especially when a long error message came up, which was inconvenient. + * What I did: + * Separated Date as a standalone label in the Exercise Card UI. + * Justification: + * The date of an exercise is especially important when keeping track of progress, hence making sure it is easily visible and distinct from the rest of the fields is important. + * Added Reps as a field to the creation of an Exercise. ([PR #67](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/67)) + * In charge of REGEX and operations relating to reps + * Removing edit feature and tests relating to it ([PR #127](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/127)) + +* **Documentation**: + * User Guide: + * Standardised pictures in User guide, included callouts for important information in each picture. ([PR #202](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/202)). + * Wrote entire section for GUI orientation. + * Helped with formatting of commands (placement of tips, phrasing of parameter constraints). + + * Developer Guide: + * Wrote section on listing of unique stored Exercises in the graphical UI ([PR #216](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/216), [PR #102](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/102)) + * Added UML diagrams (class and sequence diagrams) for recognised exercise list implementation. + * Added User stories as discussed. + +* **Contribution to team-based tasks**: + * Reviewed Team Member's PRs and provided feedback where appropriate. + * PED bugs triaging. + +* **Tools**: + * PlantUML: Creating UML diagrams. + * SceneBuilder: Edit FXML files which Gim UI components use. diff --git a/docs/team/johndoe.md b/docs/team/johndoe.md index 773a07794e2..b65036e4c90 100644 --- a/docs/team/johndoe.md +++ b/docs/team/johndoe.md @@ -3,9 +3,9 @@ layout: page title: John Doe's Project Portfolio Page --- -### Project: AddressBook Level 3 +### Project: ExerciseTracker Level 3 -AddressBook - Level 3 is a desktop address book application used for teaching Software Engineering principles. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC. +ExerciseTracker - Level 3 is a desktop exercise tracker application used for teaching Software Engineering principles. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC. Given below are my contributions to the project. diff --git a/docs/team/kavantan.md b/docs/team/kavantan.md new file mode 100644 index 00000000000..ce1651dd270 --- /dev/null +++ b/docs/team/kavantan.md @@ -0,0 +1,49 @@ +--- +layout: page +title: Kavan Tan's Project Portfolio Page +--- + +### Project: Gim + +Gim is a **desktop app for managing gym exercises, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, Gim allows you to keep track your exercises and Personal Records in an efficient way. + +Given below are my contributions to the project. + +* **Code contributed**: [RepoSense Link](https://nus-cs2103-ay2223s1.github.io/tp-dashboard/?search=kavantan&breakdown=true&sort=groupTitle&sortWithin=title&since=2022-09-16&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) + +* **New Addition**: Exercise Hashmap ([PR #85](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/85)) + * What it does: Stores exercise data in the form of a hashmap, where the key is the exercise name and the value is a list of exercises with that exercise name. + * Justification: This hashmap is crucial because it creates precedence for the implementation for many of our other features. For instance, we can now easily find all the exercises (for a certain exercise name) and find the exercise instance with the highest weight amongst them. + * Highlights: The exercise hashmap was very challenging to implement, because a strong understanding of how data is loaded/saved was necessary. Furthermore, upon tracing the code to learn of this system, it took meticulous effort to ensure that the existing commands/features work in conjunction with the exercise hashmap as well (e.g. add, delete, clear etc.). + +* **New Feature**: Personal Record Listing ([PR #114](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/114) and [PR #117](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/117)) + * What it does: Finds the personal record of certain exercises + * Justification: With this command, users will be able to keep track of their progression of certain exercises in the gym. + * Highlights: This command was tricky to implement because of two reasons. Firstly, this command has to 'perform calculations' based on specific exercises from the exercise tracker, hence it was difficult tricky to understand and implement the retrieval of these specific exercises. Secondly, because of the nature of how the command is parsed, there were many considerations to be made. E.g. If the name input was not in the exercise tracker, if there were multiple similar entries etc. +
+ +* **Enhancements to existing features**: + * Refactor AB3-specific references in original AB3 to relatable references for Gim ([PR #49](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/49) and [PR #65](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/65)) + * What I did: Refactored 'seedu.address' package to 'gim', instances of 'person' to 'exercise' and 'address book' references to 'exercise tracker' + * Justification: In Gim, we are storing exercises instead of persons. Hence, to eliminate future confusion using the OOP paradigm, it was best that we refactored the no-longer-relevant references from the original AB3 to more relevant references that we would be use in Gim. + * Allow addition of duplicate exercises ([PR #69](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/69)) + * What I did: Allow users to add 'duplicate' exercises into the system. + * Justification: Unlike in the original address book (where users cannot add duplicate names), users should be able to add the same exercise into the system to signify that they performed that exercise on multiple occasions. + * Implement mandatory use of confirm flag for 'clear' function ([PR #138](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/138)) + * What I did: Mandate that a user must type in 'confirm' before they can successfully clear their exercise tracker. + * Justification: For new users that may be unfamiliar with the 'clear' command, they might not understand what it does and may accidentally clear their exercise tracker unknowingly. The mandatory 'confirm' serves as a safety warning, aiming to prevent such accidental deletions of the exercise tracker. + +* **Documentation**: + * User Guide: + * Notes about command format ([PR #124](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/124)) + * Personal Record ([PR #124](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/124)) + * Useful notations ([PR #195](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/195)) + + * Developer Guide: + * Exercise Model ([PR #98](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/98)) + * Exercise Hashmap ([PR #214](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/214)) + * Listing of Personal Records ([PR #120](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/120)) + +* **Contribution to team-based tasks** + * Reviewed Team Members' PRs. + * Provided ideas and contributed in discussions during weekly team meeting. diff --git a/docs/team/stevenlimhw.md b/docs/team/stevenlimhw.md new file mode 100644 index 00000000000..698eb9ba31b --- /dev/null +++ b/docs/team/stevenlimhw.md @@ -0,0 +1,66 @@ +--- +layout: page +title: Steven's Project Portfolio Page +--- + +### Project: Gim + +Gim is a **desktop app for managing gym exercises, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). Gim builds on the commands of Vim so if you can type fast and are an avid Vim user, Gim can optimize your exercise routines to a much greater capacity than traditional GUI apps. + +Given below are my contributions to the project. + +* **New Feature**: `:range start/START_DATE end/END_DATE` command (PR [#92](https://github.com/AY2223S1-CS2103T-T15-4/tp/issues/92), [#119](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/119)) + * What it does: Displays a list of exercises within the time period defined by the start date and end date. + * Justification: This allows users to easily view exercise within a time period, which is a common operation. + * Highlights: Tracing of the original AB3 code base is necessary to understand how a new command can be added. The integration + of Java's LocalDate APIs is crucial to this command as well. + + +* **New Feature**: `:range last/NUMBER_OF_DAYS` (PR [#92](https://github.com/AY2223S1-CS2103T-T15-4/tp/issues/92), [#119](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/119)) + * What it does: Displays a list of exercises the last N days, where N is the number of days the user inputs. + * Justification: This allows users to easily view exercise within a time period, without inputting the specific dates. + * Highlights: Tracing of the original AB3 code base is necessary to understand how a new command can be added. The integration + of Java's LocalDate APIs is crucial to this command as well. + +* **Code contributed**: [RepoSense Link](https://nus-cs2103-ay2223s1.github.io/tp-dashboard/?search=stevenlimhw&breakdown=true&sort=groupTitle&sortWithin=title&since=2022-09-16&timeframe=commit&mergegroup=&groupSelect=groupByRepos&checkedFileTypes=docs~functional-code~test-code~other) + +* **Enhancements to existing features**: + * Allow date to be optional when adding an exercise using `:add` (PR [#86](https://github.com/AY2223S1-CS2103T-T15-4/tp/issues/86), [#108](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/108)) + * What I did: + * When the date field for `:add` is empty, the date will be set as today's date by default. + * Justification: + * This is to make the `:add` command shorter and increases speed of adding an exercise + when one wants to add exercises for today. + * Allow a variety of common date formats (PR [#108](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/108), [#119](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/119)) + * What I did: + * Allow different separators, such as `15/05/2002`, `15 05 2002`, + `15-05-2022`. + * Allow Day-Month-Year and Year-Month-Day formats, such as + `15/05/2022` or `2022/05/15`. + * Justification: + * Improve user experience by allowing more input variations. + +* **Testing**: + * Add unit tests for `Date`, `FormatterList`, `RegexList`, `RangeCommand`, `RangeCommandParser`, + `AddCommandParser`, `DateWithinRangePredicate` to improve Codecov code coverage. (PR [#217](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/217) etc.) + +* **Documentation**: + * User Guide: + * Common date formats accepted for command inputs. (PR [#130](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/130)) + * Explanation on `:range start/START_DATE end/END_DATE` command. (PR [#105](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/105), [#128](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/128)) + * Explanation on `:range last/NUMBER_OF_DAYS` command. (PR [#128](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/128)) + + * Developer Guide: + * Class diagram showing the relationship between `Date`, `RegexList` and `FormatterList`. + * Sequence diagram for `:range` command. + * Explanation on the implementation of `:range start/START_DATE end/END_DATE` command. + * Explanation on the implementation of `:range last/NUMBER_OF_DAYS` command. + * Explanation on the implementation of the `Date` class. + +* **Community**: + * Add a guide for the team to refer to on how to use Gradle to run tests and checkstyle for + CI checks locally before making a pull request. (PR [#29](https://github.com/AY2223S1-CS2103T-T15-4/tp/pull/29)) + * Add a guide for using Codecov to see which parts of the code base can be covered better. (Issue [#224](https://github.com/AY2223S1-CS2103T-T15-4/tp/issues/224)) + * Discussed design choices with their benefits and trade-offs and implementation options with the team. + * Analyzed team member's Pull Requests (PRs) and provided feedback. + * Brainstormed on the potential bugs in the app and ways to rigorously test the features. diff --git a/docs/tutorials/AddRemark.md b/docs/tutorials/AddRemark.md index 880c701042f..ccbc9ec6a5a 100644 --- a/docs/tutorials/AddRemark.md +++ b/docs/tutorials/AddRemark.md @@ -5,7 +5,7 @@ title: "Tutorial: Adding a command" Let's walk you through the implementation of a new command — `remark`. -This command allows users of the AddressBook application to add optional remarks to people in their address book and edit it if required. The command should have the following format: +This command allows users of the ExerciseTracker application to add optional remarks to people in their exercise tracker and edit it if required. The command should have the following format: `remark INDEX r/REMARK` (e.g., `remark 2 r/Likes baseball`) @@ -23,12 +23,12 @@ For now, let’s keep `RemarkCommand` as simple as possible and print some outpu **`RemarkCommand.java`:** ``` java -package seedu.address.logic.commands; +package gim.logic.commands; -import seedu.address.model.Model; +import gim.model.Model; /** - * Changes the remark of an existing person in the address book. + * Changes the remark of an existing exercise in the exercise tracker. */ public class RemarkCommand extends Command { @@ -43,9 +43,9 @@ public class RemarkCommand extends Command { ### Hook `RemarkCommand` into the application -Now that we have our `RemarkCommand` ready to be executed, we need to update `AddressBookParser#parseCommand()` to recognize the `remark` keyword. Add the new command to the `switch` block by creating a new `case` that returns a new instance of `RemarkCommand`. +Now that we have our `RemarkCommand` ready to be executed, we need to update `ExerciseTrackerParser#parseCommand()` to recognize the `remark` keyword. Add the new command to the `switch` block by creating a new `case` that returns a new instance of `RemarkCommand`. -You can refer to the changes in this [diff](https://github.com/se-edu/addressbook-level3/commit/35eb7286f18a029d39cb7a29df8f172a001e4fd8#diff-399c284cb892c20b7c04a69116fcff6ccc0666c5230a1db8e4a9145def8fa4ee). +You can refer to the changes in this [diff](https://github.com/se-edu/exercisetracker-level3/commit/35eb7286f18a029d39cb7a29df8f172a001e4fd8#diff-399c284cb892c20b7c04a69116fcff6ccc0666c5230a1db8e4a9145def8fa4ee). ### Run the application @@ -65,8 +65,8 @@ Following the convention in other commands, we add relevant messages as constant ``` java public static final String MESSAGE_USAGE = COMMAND_WORD - + ": Edits the remark of the person identified " - + "by the index number used in the last person listing. " + + ": Edits the remark of the exercise identified " + + "by the index number used in the last exercise listing. " + "Existing remark will be overwritten by the input.\n" + "Parameters: INDEX (must be a positive integer) " + "r/ [REMARK]\n" @@ -91,7 +91,7 @@ Let’s change `RemarkCommand` to parse input from the user. We start by modifying the constructor of `RemarkCommand` to accept an `Index` and a `String`. While we are at it, let’s change the error message to echo the values. While this is not a replacement for tests, it is an obvious way to tell if our code is functioning as intended. ``` java -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import static gim.commons.util.CollectionUtil.requireAllNonNull; //... public class RemarkCommand extends Command { //... @@ -101,8 +101,8 @@ public class RemarkCommand extends Command { private final String remark; /** - * @param index of the person in the filtered person list to edit the remark - * @param remark of the person to be updated to + * @param index of the exercise in the filtered exercise list to edit the remark + * @param remark of the exercise to be updated to */ public RemarkCommand(Index index, String remark) { requireAllNonNull(index, remark); @@ -136,13 +136,13 @@ public class RemarkCommand extends Command { } ``` -Your code should look something like [this](https://github.com/se-edu/addressbook-level3/commit/dc6d5139d08f6403da0ec624ea32bd79a2ae0cbf#diff-a8e35af8f9c251525063fae36c9852922a7e7195763018eacec60f3a4d87c594) after you are done. +Your code should look something like [this](https://github.com/se-edu/exercisetracker-level3/commit/dc6d5139d08f6403da0ec624ea32bd79a2ae0cbf#diff-a8e35af8f9c251525063fae36c9852922a7e7195763018eacec60f3a4d87c594) after you are done. ### Parse user input Now let’s move on to writing a parser that will extract the index and remark from the input provided by the user. -Create a `RemarkCommandParser` class in the `seedu.address.logic.parser` package. The class must extend the `Parser` interface. +Create a `RemarkCommandParser` class in the `gim.logic.parser` package. The class must extend the `Parser` interface. ![The relationship between Parser and RemarkCommandParser](../images/add-remark/ParserInterface.png) @@ -216,22 +216,22 @@ public RemarkCommand parse(String args) throws ParseException {
-:information_source: Don’t forget to update `AddressBookParser` to use our new `RemarkCommandParser`! +:information_source: Don’t forget to update `ExerciseTrackerParser` to use our new `RemarkCommandParser`!
If you are stuck, check out the sample -[here](https://github.com/se-edu/addressbook-level3/commit/dc6d5139d08f6403da0ec624ea32bd79a2ae0cbf#diff-8bf239e8e9529369b577701303ddd96af93178b4ed6735f91c2d8488b20c6b4a). +[here](https://github.com/se-edu/exercisetracker-level3/commit/dc6d5139d08f6403da0ec624ea32bd79a2ae0cbf#diff-8bf239e8e9529369b577701303ddd96af93178b4ed6735f91c2d8488b20c6b4a). ## Add `Remark` to the model -Now that we have all the information that we need, let’s lay the groundwork for propagating the remarks added into the in-memory storage of person data. We achieve that by working with the `Person` model. Each field in a Person is implemented as a separate class (e.g. a `Name` object represents the person’s name). That means we should add a `Remark` class so that we can use a `Remark` object to represent a remark given to a person. +Now that we have all the information that we need, let’s lay the groundwork for propagating the remarks added into the in-memory storage of exercise data. We achieve that by working with the `Exercise` model. Each field in an Exercise is implemented as a separate class (e.g. a `Name` object represents the exercise’s name). That means we should add a `Remark` class so that we can use a `Remark` object to represent a remark given to an exercise. ### Add a new `Remark` class -Create a new `Remark` in `seedu.address.model.person`. Since a `Remark` is a field that is similar to `Address`, we can reuse a significant bit of code. +Create a new `Remark` in `gim.model.exercise`. Since a `Remark` is a field that is similar to `Address`, we can reuse a significant bit of code. -A copy-paste and search-replace later, you should have something like [this](https://github.com/se-edu/addressbook-level3/commit/4516e099699baa9e2d51801bd26f016d812dedcc#diff-41bb13c581e280c686198251ad6cc337cd5e27032772f06ed9bf7f1440995ece). Note how `Remark` has no constrains and thus does not require input +A copy-paste and search-replace later, you should have something like [this](https://github.com/se-edu/exercisetracker-level3/commit/4516e099699baa9e2d51801bd26f016d812dedcc#diff-41bb13c581e280c686198251ad6cc337cd5e27032772f06ed9bf7f1440995ece). Note how `Remark` has no constrains and thus does not require input validation. ### Make use of `Remark` @@ -240,11 +240,11 @@ Let’s change `RemarkCommand` and `RemarkCommandParser` to use the new `Remark` ## Add a placeholder element for remark to the UI -Without getting too deep into `fxml`, let’s go on a 5 minute adventure to get some placeholder text to show up for each person. +Without getting too deep into `fxml`, let’s go on a 5 minute adventure to get some placeholder text to show up for each exercise. -Simply add the following to [`seedu.address.ui.PersonCard`](https://github.com/se-edu/addressbook-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-639834f1e05afe2276a86372adf0fe5f69314642c2d93cfa543d614ce5a76688). +Simply add the following to [`gim.ui.ExerciseCard`](https://github.com/se-edu/exercisetracker-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-639834f1e05afe2276a86372adf0fe5f69314642c2d93cfa543d614ce5a76688). -**`PersonCard.java`:** +**`ExerciseCard.java`:** ``` java @FXML @@ -254,9 +254,9 @@ private Label remark; `@FXML` is an annotation that marks a private or protected field and makes it accessible to FXML. It might sound like Greek to you right now, don’t worry — we will get back to it later. -Then insert the following into [`main/resources/view/PersonListCard.fxml`](https://github.com/se-edu/addressbook-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-d44c4f51c24f6253c277a2bb9bc440b8064d9c15ad7cb7ceda280bca032efce9). +Then insert the following into [`main/resources/view/ExerciseListCard.fxml`](https://github.com/se-edu/exercisetracker-level3/commit/850b78879582f38accb05dd20c245963c65ea599#diff-d44c4f51c24f6253c277a2bb9bc440b8064d9c15ad7cb7ceda280bca032efce9). -**`PersonListCard.fxml`:** +**`ExerciseListCard.fxml`:** ``` xml