From 650320b8f34849c73285f0e026f13bb867f176cb Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 3 Mar 2020 15:21:17 +0800 Subject: [PATCH 001/415] Set theme jekyll-theme-hacker --- docs/_config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/_config.yml diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 000000000..fc24e7a62 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-hacker \ No newline at end of file From 92097d76a318b1c665a5e9d5d0a4b5a758dcb151 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 3 Mar 2020 15:21:53 +0800 Subject: [PATCH 002/415] Set theme jekyll-theme-hacker From 22fa03690abde3a5b564f2bf00aeaaa3fde84b0f Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Tue, 3 Mar 2020 16:03:13 +0800 Subject: [PATCH 003/415] ananda's branch --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953e..7e17fda48 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,7 +2,7 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ananda Lye | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From fcb57670598aa858c1548cbdc991a2214e54e0fb Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 3 Mar 2020 16:06:45 +0800 Subject: [PATCH 004/415] Add name to about us. --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953e..3055aecae 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -3,7 +3,7 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ng Siu Hian | [Github](https://github.com/siuhian) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From c4c78fac7760a916edad44dcbb8aaff5755d58fe Mon Sep 17 00:00:00 2001 From: btricec Date: Tue, 3 Mar 2020 16:06:45 +0800 Subject: [PATCH 005/415] Change aboutus --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953e..d2854c4ae 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -4,6 +4,6 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Beatrice Chan | [Github](https://github.com/btricec) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From e0d80f71468280d61b27c562d7e10d4f5b7bb624 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Tue, 3 Mar 2020 16:08:06 +0800 Subject: [PATCH 006/415] Update AboutUs file --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953e..f8fa341da 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -5,5 +5,5 @@ Display | Name | Github Profile | Portfolio ![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Nigelle Leo | [Github](https://github.com/nigellenl) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From 73ab2660105ffdb1ebce8aa847355c1cb85295df Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 3 Mar 2020 17:15:36 +0800 Subject: [PATCH 007/415] Include information in AboutUs --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 37740c621..444661d07 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -6,5 +6,5 @@ Display | Name | Github Profile | Portfolio ![](https://via.placeholder.com/100.png?text=Photo) | Ananda Lye | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Beatrice Chan | [Github](https://github.com/btricec) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Nigelle Leo | [Github](https://github.com/nigellenl) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Riccardo Di Maio | [Github](https://github.com/rdimaio) | [Portfolio](docs/team/johndoe.md) From 9fe9955c4b30d085360e98f7d02f1f971465c6db Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Thu, 5 Mar 2020 16:10:54 +0800 Subject: [PATCH 008/415] Created main file for Jikan, the Actitivy and Parser Classes --- src/main/java/Activity.java | 15 ++++++++++++ src/main/java/ActivityList.java | 11 +++++++++ src/main/java/Jikan.java | 28 ++++++++++++++++++++++ src/main/java/Parser.java | 38 ++++++++++++++++++++++++++++++ src/main/java/Tag.java | 7 ++++++ src/main/java/seedu/duke/Duke.java | 21 ----------------- 6 files changed, 99 insertions(+), 21 deletions(-) create mode 100644 src/main/java/Activity.java create mode 100644 src/main/java/ActivityList.java create mode 100644 src/main/java/Jikan.java create mode 100644 src/main/java/Parser.java create mode 100644 src/main/java/Tag.java delete mode 100644 src/main/java/seedu/duke/Duke.java diff --git a/src/main/java/Activity.java b/src/main/java/Activity.java new file mode 100644 index 000000000..859f9d08c --- /dev/null +++ b/src/main/java/Activity.java @@ -0,0 +1,15 @@ +public class Activity { + protected String name; + protected String startTime; + protected String endTime; + + public Activity(String name, String startTime) { + this.name = name; + this.startTime = startTime; + } + + public String endActivity(String endTime) { + this.endTime = endTime; + return ("You have ended " + this.name + " . Great job !\n"); + } +} diff --git a/src/main/java/ActivityList.java b/src/main/java/ActivityList.java new file mode 100644 index 000000000..618653aef --- /dev/null +++ b/src/main/java/ActivityList.java @@ -0,0 +1,11 @@ +import java.util.ArrayList; + +public class ActivityList { + ArrayList activities; + int size; + + public ActivityList() { + this.activities = new ArrayList<>(); + size = 0; + } +} diff --git a/src/main/java/Jikan.java b/src/main/java/Jikan.java new file mode 100644 index 000000000..730ddb684 --- /dev/null +++ b/src/main/java/Jikan.java @@ -0,0 +1,28 @@ +import java.util.Scanner; + +public class Jikan { + public static final String GREETING = + "\n" + + " _\n" + + " _/ }\n" + + " `>' \\\n" + + " `| \\\n" + + " | /'-. .-.\n" + + " \\' ';`--' .'\n" + + " \\'. `'-./\n" + + " '.`\"-..-;`\n" + + " `;-..'\n" + + " _| _|\n" + + " /` /` \n" + + "Hello! I'm Jikan\n" + "What can I do for you?\n" + + "____________________________________________________________\n"; + /** + * Main entry-point for the java.duke.Duke application. + */ + public static void main(String[] args) { + System.out.println(GREETING); + Scanner in = new Scanner(System.in); + ActivityList activityList = new ActivityList(); + Parser.parseUserCommands(in, activityList); + } +} diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java new file mode 100644 index 000000000..0cef97372 --- /dev/null +++ b/src/main/java/Parser.java @@ -0,0 +1,38 @@ +/* +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.time.temporal.ChronoUnit; + */ +import java.util.Scanner; + +public class Parser { + + public static void parseUserCommands(Scanner scanner, ActivityList activityList) { + boolean exit = false; + while (exit == false) { + String userInput = scanner.nextLine(); + String[] tokenizedInputs = userInput.split(" ", 2); + String instruction = tokenizedInputs[0]; + + switch (instruction) { + case "bye": + System.out.println("Bye! See you again.\n"); + exit = true; + break; + case "start": + System.out.println("Started " + tokenizedInputs[1] + "\n"); + break; + case "end": + System.out.println("Ended " + tokenizedInputs[1] + "\n"); + break; + case "list": + break; + case "delete": + break; + default: + System.out.println("☹ OOPS!!! I'm sorry, but I don't know what that means :-("); + break; + } + } + } +} diff --git a/src/main/java/Tag.java b/src/main/java/Tag.java new file mode 100644 index 000000000..cb597dbb3 --- /dev/null +++ b/src/main/java/Tag.java @@ -0,0 +1,7 @@ +public class Tag { + protected String name; + + public Tag(String name) { + this.name = name; + } +} diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java deleted file mode 100644 index 5c74e68d5..000000000 --- a/src/main/java/seedu/duke/Duke.java +++ /dev/null @@ -1,21 +0,0 @@ -package seedu.duke; - -import java.util.Scanner; - -public class Duke { - /** - * Main entry-point for the java.duke.Duke application. - */ - public static void main(String[] args) { - String logo = " ____ _ \n" - + "| _ \\ _ _| | _____ \n" - + "| | | | | | | |/ / _ \\\n" - + "| |_| | |_| | < __/\n" - + "|____/ \\__,_|_|\\_\\___|\n"; - System.out.println("Hello from\n" + logo); - System.out.println("What is your name?"); - - Scanner in = new Scanner(System.in); - System.out.println("Hello " + in.nextLine()); - } -} From 1a6cb0b1fcdc4e427179185d2fe438d09d3e559c Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sun, 8 Mar 2020 17:05:27 +0800 Subject: [PATCH 009/415] Added JavaDocs and fixed style vialotions from gradle style check --- src/main/java/Activity.java | 14 ++++++++++++++ src/main/java/ActivityList.java | 6 ++++++ src/main/java/Jikan.java | 34 ++++++++++++++++++--------------- src/main/java/Parser.java | 8 ++++++++ src/main/java/Tag.java | 3 +++ 5 files changed, 50 insertions(+), 15 deletions(-) diff --git a/src/main/java/Activity.java b/src/main/java/Activity.java index 859f9d08c..0826e8bc3 100644 --- a/src/main/java/Activity.java +++ b/src/main/java/Activity.java @@ -1,13 +1,27 @@ +/** + * Represents an activity entry with a name and total time spent. + */ + public class Activity { protected String name; protected String startTime; protected String endTime; + /** + * Constructor for a new activity entry. + * @param name represents the name of the activity + * @param startTime the time that the activity first started + */ public Activity(String name, String startTime) { this.name = name; this.startTime = startTime; } + /** + * Ends an ongoing activity and updates the total time spent on the activity. + * @param endTime date and time when the activity ended + * @return a confirmation message that the tracking of the activity has ended + */ public String endActivity(String endTime) { this.endTime = endTime; return ("You have ended " + this.name + " . Great job !\n"); diff --git a/src/main/java/ActivityList.java b/src/main/java/ActivityList.java index 618653aef..981c96de0 100644 --- a/src/main/java/ActivityList.java +++ b/src/main/java/ActivityList.java @@ -1,9 +1,15 @@ import java.util.ArrayList; +/** + * Represents the list of activities. + */ public class ActivityList { ArrayList activities; int size; + /** + * Constructor for a new activity list. + */ public ActivityList() { this.activities = new ArrayList<>(); size = 0; diff --git a/src/main/java/Jikan.java b/src/main/java/Jikan.java index 730ddb684..f745a5eed 100644 --- a/src/main/java/Jikan.java +++ b/src/main/java/Jikan.java @@ -1,23 +1,27 @@ import java.util.Scanner; +/** + * Represents the Jikan time tracker. + */ public class Jikan { public static final String GREETING = - "\n" + - " _\n" + - " _/ }\n" + - " `>' \\\n" + - " `| \\\n" + - " | /'-. .-.\n" + - " \\' ';`--' .'\n" + - " \\'. `'-./\n" + - " '.`\"-..-;`\n" + - " `;-..'\n" + - " _| _|\n" + - " /` /` \n" + - "Hello! I'm Jikan\n" + "What can I do for you?\n" + - "____________________________________________________________\n"; + "\n" + + " _\n" + + " _/ }\n" + + " `>' \\\n" + + " `| \\\n" + + " | /'-. .-.\n" + + " \\' ';`--' .'\n" + + " \\'. `'-./\n" + + " '.`\"-..-;`\n" + + " `;-..'\n" + + " _| _|\n" + + " /` /` \n" + + "Hello! I'm Jikan\n" + "What can I do for you?\n" + + "____________________________________________________________\n"; + /** - * Main entry-point for the java.duke.Duke application. + * Main entry-point for the Jikan application. */ public static void main(String[] args) { System.out.println(GREETING); diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java index 0cef97372..b3a4f6b0b 100644 --- a/src/main/java/Parser.java +++ b/src/main/java/Parser.java @@ -5,8 +5,16 @@ */ import java.util.Scanner; +/** + * Represents the object which parses user input to relevant functions for the execution of commands. + */ public class Parser { + /** + * Parses user commands to relevant functions to carry out the commands. + * @param scanner scanner object which reads user input + * @param activityList the list of activities + */ public static void parseUserCommands(Scanner scanner, ActivityList activityList) { boolean exit = false; while (exit == false) { diff --git a/src/main/java/Tag.java b/src/main/java/Tag.java index cb597dbb3..c450b2482 100644 --- a/src/main/java/Tag.java +++ b/src/main/java/Tag.java @@ -1,3 +1,6 @@ +/** + * Represents a tag object to tag activities. + */ public class Tag { protected String name; From 0f87c816143fa0b94b44a15c2f115a6745b24cc7 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sun, 8 Mar 2020 17:31:41 +0800 Subject: [PATCH 010/415] Add Storage and StorageHandler --- src/main/java/Activity.java | 26 ++++ src/main/java/ActivityList.java | 45 +++++++ src/main/java/Jikan.java | 30 ++++- src/main/java/storage/Storage.java | 70 +++++++++++ src/main/java/storage/StorageHandler.java | 139 ++++++++++++++++++++++ 5 files changed, 308 insertions(+), 2 deletions(-) create mode 100644 src/main/java/storage/Storage.java create mode 100644 src/main/java/storage/StorageHandler.java diff --git a/src/main/java/Activity.java b/src/main/java/Activity.java index 859f9d08c..97ba81ae4 100644 --- a/src/main/java/Activity.java +++ b/src/main/java/Activity.java @@ -8,8 +8,34 @@ public Activity(String name, String startTime) { this.startTime = startTime; } + /** + * Constructor to create activity when endTime is previously known + * (i.e. when loading from storage) + * + * @param name Name of activity. + * @param startTime Time at which activity started. + * @param endTime Time at which activity ended. + */ + public Activity(String name, String startTime, String endTime) { + this.name = name; + this.startTime = startTime; + this.endTime = endTime; + } + public String endActivity(String endTime) { this.endTime = endTime; return ("You have ended " + this.name + " . Great job !\n"); } + + /** + * Converts the Activity object to data representation to be stored in a data file. + * File format: + * name, startTime, endTime + * + * @return String representing the Task object in comma-separated data format. + */ + public String toData() { + String dataLine = (this.name + "," + this.startTime + "," + this.endTime); + return dataLine; + } } diff --git a/src/main/java/ActivityList.java b/src/main/java/ActivityList.java index 618653aef..627676a9f 100644 --- a/src/main/java/ActivityList.java +++ b/src/main/java/ActivityList.java @@ -1,4 +1,9 @@ +import java.io.File; +import java.io.FileNotFoundException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; public class ActivityList { ArrayList activities; @@ -8,4 +13,44 @@ public ActivityList() { this.activities = new ArrayList<>(); size = 0; } + + /** + * Loads activityList from data file. + * + * @param dataFile Data file to load from. + */ + public ActivityList(File dataFile) { + this.activities = new ArrayList<>(); + populateTaskList(dataFile); + } + + /** + * Populates task list from file. + * + * @param dataFile Data file to populate from. + */ + private void populateTaskList(File dataFile) { + try { + Scanner dataScanner = new Scanner(dataFile); + while (dataScanner.hasNext()) { + parseDataLine(dataScanner.nextLine()); + } + } catch (FileNotFoundException e) { + System.out.println("Error: data file not found. Could not load into the current session's task list."); + } + } + + /** + * Parses the current line in the data file to an Activity object. + * + * @param s String to parse. + */ + private void parseDataLine(String s) { + + List strings = Arrays.asList(s.split(",")); + + // strings[0] = name, strings[1] = startDate, string[2] = endDate + Activity e = new Activity(strings.get(0), strings.get(1), strings.get(2)); + activities.add(e); + } } diff --git a/src/main/java/Jikan.java b/src/main/java/Jikan.java index 730ddb684..ad2054c13 100644 --- a/src/main/java/Jikan.java +++ b/src/main/java/Jikan.java @@ -1,6 +1,18 @@ +import storage.Storage; + import java.util.Scanner; + public class Jikan { + /** Constant file path of data file. */ + private static final String DATA_FILE_PATH = "data/data.csv"; + + /** Storage object for data file. */ + private static Storage storage; + + /** Activity list to store current tasks in. */ + private static ActivityList activityList; + public static final String GREETING = "\n" + " _\n" + @@ -16,13 +28,27 @@ public class Jikan { " /` /` \n" + "Hello! I'm Jikan\n" + "What can I do for you?\n" + "____________________________________________________________\n"; + + /** + * Creates ActivityList and loads data from data file if the data file previously existed; + * otherwise, an empty task list is initialized. + */ + private static void createActivityList() { + if (storage.loadFile()) { + activityList = new ActivityList(storage.dataFile); + } else { + activityList = new ActivityList(); + } + } + /** - * Main entry-point for the java.duke.Duke application. + * Main entry-point for the Jikan application. */ public static void main(String[] args) { System.out.println(GREETING); Scanner in = new Scanner(System.in); - ActivityList activityList = new ActivityList(); + createActivityList(); + storage = new Storage(DATA_FILE_PATH); Parser.parseUserCommands(in, activityList); } } diff --git a/src/main/java/storage/Storage.java b/src/main/java/storage/Storage.java new file mode 100644 index 000000000..3a45a9d40 --- /dev/null +++ b/src/main/java/storage/Storage.java @@ -0,0 +1,70 @@ +package storage; + +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; + +/** + * Class that holds the path and File object for the current data file. + */ +public class Storage { + + /** Path to current data file. */ + public String dataFilePath; + + /** File object for current data file. */ + public File dataFile; + + /** + * Constructs a Storage object for the input file path. + * + * @param dataFilePath The data file's file path. + */ + public Storage(String dataFilePath) { + this.dataFilePath = dataFilePath; + dataFile = new File(dataFilePath); + } + + /** + * Writes the input string to file. + * + * @param s The input string. + * @throws IOException If an error occurs while writing. + */ + public void writeToFile(String s) throws IOException { + FileWriter fw = new FileWriter(dataFilePath, true); + fw.write(s + System.lineSeparator()); + fw.close(); + } + + // Return true if file previously existed, false if it didn't exist (and it created a new one) + + /** + * Loads the data file. Creates file and directories if data file did not previously exist. + * + * @return True if file previously existed (and was not created); False if file did not exist and was created. + */ + public boolean loadFile() { + + // Create data file if it does not exist already + if (!dataFile.exists()) { + try { + createDataFile(); + return false; // false = file didn't previously exist, so it was created + } catch (IOException e) { + System.out.println("Error loading data file."); + } + } + return true; // true = file previously existed, and was not created + } + + /** + * Creates a file and any non-existing directories to that file. + * + * @throws IOException If an error occurs while creating the file or directories. + */ + private void createDataFile() throws IOException { + dataFile.getParentFile().mkdirs(); // Create data directory (does nothing if directory already exists) + dataFile.createNewFile(); + } +} diff --git a/src/main/java/storage/StorageHandler.java b/src/main/java/storage/StorageHandler.java new file mode 100644 index 000000000..c35e735ff --- /dev/null +++ b/src/main/java/storage/StorageHandler.java @@ -0,0 +1,139 @@ +package storage; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/** + * Class containing useful functions for modifying the data file. + */ +public class StorageHandler { + + /** + * Removes the line whose index matches lineNumber from file at dataFilePath. + * + * @param lineNumber Index of line to remove. + * @param dataFilePath Path to data file. + * @throws IOException If an error occurs while writing the new list to file. + */ + public static void removeLine(int lineNumber, String dataFilePath) throws IOException { + // Read file into list of strings, where each string is a line in the file + List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(dataFilePath), StandardCharsets.UTF_8)); + int removedIndex = 0; + + // Remove line from fileContent list + removedIndex = removeLineFromList(lineNumber, fileContent, removedIndex); + + // Rewrite list into data file + Files.write(Paths.get(dataFilePath), fileContent, StandardCharsets.UTF_8); + + // Update indexes of subsequent lines + updateIndexes(fileContent, removedIndex, dataFilePath); + } + + /** + * Removes line from a list based on its index. Returns index at which the line was removed. + * + * @param lineNumber Index of line to remove. + * @param list List of strings containing lines, each with a starting index. + * @param removedIndex Index at which line was removed. + * @return Index of the removed line. + */ + private static int removeLineFromList(int lineNumber, List list, int removedIndex) { + // Iterate through the lines + for (int i = 0; i < list.size(); i++) { + // If the current line matches the taskId + if (list.get(i).startsWith(String.valueOf(lineNumber))) { + // Remove current line + removedIndex = i; // Store index of removed line to use as initial index of next loop + list.remove(i); + break; + } + } + return removedIndex; + } + + /** + * After a line has been removed, updates subsequent indexes. + * + * @param fileContent List of strings from the data file. + * @param removedIndex Index at which line was removed. + * @param dataFilePath Path to data file. + * @throws IOException If an error occurs while writing to file. + */ + private static void updateIndexes(List fileContent, int removedIndex, String dataFilePath) throws IOException { + // Update indexes of subsequent tasks (e.g. if you remove task 2, task 3 becomes task 2) + for (int i = removedIndex; i < fileContent.size(); i++) + { + // Get current comma separated string + String currString = fileContent.get(i); + + String updatedString = decrementIndex(currString, i); + + // Replace the line with the updated string + replaceLine(i+1, updatedString, dataFilePath); + } + } + + /** + * Decrements index at beginning of string by 1. + * + * @param currString String whose index must be decremented. + * @param i Index that the currString's index must be set to. + * @return Original string with its index decremented by 1. + */ + private static String decrementIndex(String currString, int i) { + + // Split into different cells + List cells = Arrays.asList(currString.split(",")); + + // Change first cell (taskID) to new ID (taskID-1) + // Task 3 becomes task 2, task 4 becomes task 3, until end of list + cells.set(0, String.valueOf(i)); + + // Recombine the comma separated string + return String.join(",", cells); + } + + /** + * Replaces line in a data file. + * + * @param lineNumber Index of the line to replace. + * @param newString String that replaces the original line. + * @param dataFilePath Path to data file. + * @throws IOException If an error occurs while writing to file. + */ + public static void replaceLine(int lineNumber, String newString, String dataFilePath) throws IOException { + // Read file into list of strings, where each string is a line in the file + List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(dataFilePath), StandardCharsets.UTF_8)); + + // Replace line in the list of strings + replaceLineInList(lineNumber, newString, fileContent); + + // Write new list of strings to file + Files.write(Paths.get(dataFilePath), fileContent, StandardCharsets.UTF_8); + } + + /** + * Replaces a line in a list of Strings. + * + * @param lineNumber Number at which line must be replaced. + * @param newString String that replaces the original string. + * @param list List of strings. + */ + private static void replaceLineInList(int lineNumber, String newString, List list) { + // Iterate through the lines + for (int i = 0; i < list.size(); i++) { + // If the current line matches the taskId + if (list.get(i).startsWith(String.valueOf(lineNumber))) { + // Replace it with the new task string + list.set(i, newString); + break; + } + } + } +} From 4a63e7f72a025058458b133f052a07918f21ee25 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sun, 8 Mar 2020 17:33:31 +0800 Subject: [PATCH 011/415] Fix order in main --- src/main/java/Jikan.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/Jikan.java b/src/main/java/Jikan.java index ad2054c13..c35feb10e 100644 --- a/src/main/java/Jikan.java +++ b/src/main/java/Jikan.java @@ -47,8 +47,8 @@ private static void createActivityList() { public static void main(String[] args) { System.out.println(GREETING); Scanner in = new Scanner(System.in); - createActivityList(); storage = new Storage(DATA_FILE_PATH); + createActivityList(); Parser.parseUserCommands(in, activityList); } } From 5cf1fbe4add0636d31068570c8762f9e13316c8b Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 8 Mar 2020 18:21:50 +0800 Subject: [PATCH 012/415] Add start, end, abort and list commands --- src/main/java/Activity.java | 18 ++++++++++------- src/main/java/ActivityList.java | 34 +++++++++++++++++++++++++++++++-- src/main/java/Parser.java | 26 ++++++++++++++++++++++--- 3 files changed, 66 insertions(+), 12 deletions(-) diff --git a/src/main/java/Activity.java b/src/main/java/Activity.java index 859f9d08c..9587ee9b6 100644 --- a/src/main/java/Activity.java +++ b/src/main/java/Activity.java @@ -1,15 +1,19 @@ +import java.time.Duration; +import java.time.LocalDateTime; + public class Activity { protected String name; - protected String startTime; - protected String endTime; + protected String[] tags; + protected LocalDateTime startTime; + protected LocalDateTime endTime; + protected Duration duration; - public Activity(String name, String startTime) { + public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, String[] tags) { this.name = name; this.startTime = startTime; - } - - public String endActivity(String endTime) { + this.tags = tags; this.endTime = endTime; - return ("You have ended " + this.name + " . Great job !\n"); + this.duration = Duration.between(startTime, endTime); } + } diff --git a/src/main/java/ActivityList.java b/src/main/java/ActivityList.java index 618653aef..730e1194f 100644 --- a/src/main/java/ActivityList.java +++ b/src/main/java/ActivityList.java @@ -1,11 +1,41 @@ +import java.time.Duration; import java.util.ArrayList; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; public class ActivityList { ArrayList activities; - int size; + //int size; public ActivityList() { this.activities = new ArrayList<>(); - size = 0; + //this.size = activities.size(); + } + + public void add(Activity activity) { + activities.add(activity); + } + + public int getSize() { + return activities.size(); + } + + public void printList() { + System.out.println("Your completed activities:"); + for (int i = 0; i < this.getSize(); i++) { + long durationInNanos = (activities.get(i).duration).toNanos(); + String duration = String.format("%02d:%02d:%02d", + TimeUnit.NANOSECONDS.toHours(durationInNanos), + TimeUnit.NANOSECONDS.toMinutes(durationInNanos) - + TimeUnit.HOURS.toMinutes(TimeUnit.NANOSECONDS.toHours(durationInNanos)), + TimeUnit.NANOSECONDS.toSeconds(durationInNanos) - + TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(durationInNanos))); + System.out.print(i + 1 + ". " + activities.get(i).name + " " + duration); + if(activities.get(i).tags != null) { + System.out.println(" " + Arrays.toString(activities.get(i).tags)); + } else { + System.out.print("\n"); + } + } } } diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java index 0cef97372..ec425117d 100644 --- a/src/main/java/Parser.java +++ b/src/main/java/Parser.java @@ -3,15 +3,22 @@ import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; */ +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.Arrays; import java.util.Scanner; public class Parser { public static void parseUserCommands(Scanner scanner, ActivityList activityList) { boolean exit = false; + Activity newActivity; + LocalDateTime startTime = null; + String[] tags = null; + while (exit == false) { String userInput = scanner.nextLine(); - String[] tokenizedInputs = userInput.split(" ", 2); + String[] tokenizedInputs = userInput.split(" "); String instruction = tokenizedInputs[0]; switch (instruction) { @@ -21,13 +28,26 @@ public static void parseUserCommands(Scanner scanner, ActivityList activityList) break; case "start": System.out.println("Started " + tokenizedInputs[1] + "\n"); + if (tokenizedInputs.length > 2) { + tags = Arrays.copyOfRange(tokenizedInputs, 2, tokenizedInputs.length); + } + startTime = LocalDateTime.now(); break; case "end": - System.out.println("Ended " + tokenizedInputs[1] + "\n"); + if (startTime == null) { + System.out.println("You have not started any activity!"); + } else { + System.out.println("Ended " + tokenizedInputs[1] + "\n"); + newActivity = new Activity(tokenizedInputs[1], startTime, LocalDateTime.now(), tags); + activityList.add(newActivity); + } break; case "list": + activityList.printList(); break; - case "delete": + case "abort": + startTime = null; + System.out.println("You have aborted the current activity!"); break; default: System.out.println("☹ OOPS!!! I'm sorry, but I don't know what that means :-("); From 0227af373f7e80b2dbf1f6049eae96795d37963f Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 9 Mar 2020 21:40:16 +0800 Subject: [PATCH 013/415] Refactor storage in jikan, add template for StorageTest --- .gitignore | 3 +++ src/main/java/Activity.java | 2 +- src/main/java/Jikan.java | 2 +- src/main/java/{ => jikan}/storage/Storage.java | 2 +- src/main/java/{ => jikan}/storage/StorageHandler.java | 2 +- .../duke/DukeTest.java => jikan/storage/StorageTest.java} | 6 ++---- 6 files changed, 9 insertions(+), 8 deletions(-) rename src/main/java/{ => jikan}/storage/Storage.java (98%) rename src/main/java/{ => jikan}/storage/StorageHandler.java (99%) rename src/test/java/{seedu/duke/DukeTest.java => jikan/storage/StorageTest.java} (79%) diff --git a/.gitignore b/.gitignore index cfc40b7dd..e774712e5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ +# data files +/data/ + # IDEA files /.idea/ /out/ diff --git a/src/main/java/Activity.java b/src/main/java/Activity.java index 97ba81ae4..aacff51bb 100644 --- a/src/main/java/Activity.java +++ b/src/main/java/Activity.java @@ -10,7 +10,7 @@ public Activity(String name, String startTime) { /** * Constructor to create activity when endTime is previously known - * (i.e. when loading from storage) + * (i.e. when loading from jikan.storage) * * @param name Name of activity. * @param startTime Time at which activity started. diff --git a/src/main/java/Jikan.java b/src/main/java/Jikan.java index c35feb10e..b3120fc16 100644 --- a/src/main/java/Jikan.java +++ b/src/main/java/Jikan.java @@ -1,4 +1,4 @@ -import storage.Storage; +import jikan.storage.Storage; import java.util.Scanner; diff --git a/src/main/java/storage/Storage.java b/src/main/java/jikan/storage/Storage.java similarity index 98% rename from src/main/java/storage/Storage.java rename to src/main/java/jikan/storage/Storage.java index 3a45a9d40..085484916 100644 --- a/src/main/java/storage/Storage.java +++ b/src/main/java/jikan/storage/Storage.java @@ -1,4 +1,4 @@ -package storage; +package jikan.storage; import java.io.File; import java.io.FileWriter; diff --git a/src/main/java/storage/StorageHandler.java b/src/main/java/jikan/storage/StorageHandler.java similarity index 99% rename from src/main/java/storage/StorageHandler.java rename to src/main/java/jikan/storage/StorageHandler.java index c35e735ff..845a820ea 100644 --- a/src/main/java/storage/StorageHandler.java +++ b/src/main/java/jikan/storage/StorageHandler.java @@ -1,4 +1,4 @@ -package storage; +package jikan.storage; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/src/test/java/seedu/duke/DukeTest.java b/src/test/java/jikan/storage/StorageTest.java similarity index 79% rename from src/test/java/seedu/duke/DukeTest.java rename to src/test/java/jikan/storage/StorageTest.java index 495ab98a3..f04a38970 100644 --- a/src/test/java/seedu/duke/DukeTest.java +++ b/src/test/java/jikan/storage/StorageTest.java @@ -1,10 +1,8 @@ -package seedu.duke; - +package jikan.storage; import static org.junit.jupiter.api.Assertions.assertTrue; - import org.junit.jupiter.api.Test; -class DukeTest { +class StorageTest { @Test public void sampleTest() { assertTrue(true); From 047165c8815ee93054ebfec7bdd1261967f57fcd Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 9 Mar 2020 21:45:29 +0800 Subject: [PATCH 014/415] Update .gitignore --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index cfc40b7dd..a09b206ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -# IDEA files +# IDEAg files /.idea/ /out/ /*.iml From 8208055dac39f88f20c05f971744c1b01a80c6c0 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 9 Mar 2020 22:12:04 +0800 Subject: [PATCH 015/415] Merge Ananda's pr --- src/main/java/Activity.java | 14 ++++++++++++++ src/main/java/ActivityList.java | 6 ++++++ src/main/java/Jikan.java | 32 +++++++++++++++++--------------- src/main/java/Parser.java | 8 ++++++++ src/main/java/Tag.java | 3 +++ 5 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/main/java/Activity.java b/src/main/java/Activity.java index aacff51bb..06dedf887 100644 --- a/src/main/java/Activity.java +++ b/src/main/java/Activity.java @@ -1,8 +1,17 @@ +/** + * Represents an activity entry with a name and total time spent. + */ + public class Activity { protected String name; protected String startTime; protected String endTime; + /** + * Constructor for a new activity entry. + * @param name represents the name of the activity + * @param startTime the time that the activity first started + */ public Activity(String name, String startTime) { this.name = name; this.startTime = startTime; @@ -22,6 +31,11 @@ public Activity(String name, String startTime, String endTime) { this.endTime = endTime; } + /** + * Ends an ongoing activity and updates the total time spent on the activity. + * @param endTime date and time when the activity ended + * @return a confirmation message that the tracking of the activity has ended + */ public String endActivity(String endTime) { this.endTime = endTime; return ("You have ended " + this.name + " . Great job !\n"); diff --git a/src/main/java/ActivityList.java b/src/main/java/ActivityList.java index 627676a9f..046e54af6 100644 --- a/src/main/java/ActivityList.java +++ b/src/main/java/ActivityList.java @@ -5,10 +5,16 @@ import java.util.List; import java.util.Scanner; +/** + * Represents the list of activities. + */ public class ActivityList { ArrayList activities; int size; + /** + * Constructor for a new activity list. + */ public ActivityList() { this.activities = new ArrayList<>(); size = 0; diff --git a/src/main/java/Jikan.java b/src/main/java/Jikan.java index b3120fc16..3cf4b2670 100644 --- a/src/main/java/Jikan.java +++ b/src/main/java/Jikan.java @@ -2,7 +2,9 @@ import java.util.Scanner; - +/** + * Represents the Jikan time tracker. + */ public class Jikan { /** Constant file path of data file. */ private static final String DATA_FILE_PATH = "data/data.csv"; @@ -14,20 +16,20 @@ public class Jikan { private static ActivityList activityList; public static final String GREETING = - "\n" + - " _\n" + - " _/ }\n" + - " `>' \\\n" + - " `| \\\n" + - " | /'-. .-.\n" + - " \\' ';`--' .'\n" + - " \\'. `'-./\n" + - " '.`\"-..-;`\n" + - " `;-..'\n" + - " _| _|\n" + - " /` /` \n" + - "Hello! I'm Jikan\n" + "What can I do for you?\n" + - "____________________________________________________________\n"; + "\n" + + " _\n" + + " _/ }\n" + + " `>' \\\n" + + " `| \\\n" + + " | /'-. .-.\n" + + " \\' ';`--' .'\n" + + " \\'. `'-./\n" + + " '.`\"-..-;`\n" + + " `;-..'\n" + + " _| _|\n" + + " /` /` \n" + + "Hello! I'm Jikan\n" + "What can I do for you?\n" + + "____________________________________________________________\n"; /** * Creates ActivityList and loads data from data file if the data file previously existed; diff --git a/src/main/java/Parser.java b/src/main/java/Parser.java index 0cef97372..b3a4f6b0b 100644 --- a/src/main/java/Parser.java +++ b/src/main/java/Parser.java @@ -5,8 +5,16 @@ */ import java.util.Scanner; +/** + * Represents the object which parses user input to relevant functions for the execution of commands. + */ public class Parser { + /** + * Parses user commands to relevant functions to carry out the commands. + * @param scanner scanner object which reads user input + * @param activityList the list of activities + */ public static void parseUserCommands(Scanner scanner, ActivityList activityList) { boolean exit = false; while (exit == false) { diff --git a/src/main/java/Tag.java b/src/main/java/Tag.java index cb597dbb3..c450b2482 100644 --- a/src/main/java/Tag.java +++ b/src/main/java/Tag.java @@ -1,3 +1,6 @@ +/** + * Represents a tag object to tag activities. + */ public class Tag { protected String name; From 19cdf1ca7f0b8b66659074f2bba38a40d2c2aaeb Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 9 Mar 2020 22:14:36 +0800 Subject: [PATCH 016/415] Change welcome logo --- src/main/java/Jikan.java | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/src/main/java/Jikan.java b/src/main/java/Jikan.java index 730ddb684..a7705f2d4 100644 --- a/src/main/java/Jikan.java +++ b/src/main/java/Jikan.java @@ -1,21 +1,18 @@ import java.util.Scanner; public class Jikan { - public static final String GREETING = - "\n" + - " _\n" + - " _/ }\n" + - " `>' \\\n" + - " `| \\\n" + - " | /'-. .-.\n" + - " \\' ';`--' .'\n" + - " \\'. `'-./\n" + - " '.`\"-..-;`\n" + - " `;-..'\n" + - " _| _|\n" + - " /` /` \n" + - "Hello! I'm Jikan\n" + "What can I do for you?\n" + - "____________________________________________________________\n"; + public static final String GREETING = "___________________________________________\n" + + " 0101 01010101 01 01 .010. 101 01 \n" + + " `10' `10' 10 ,10' 10' `10 101o 01 \n" + + " 01 01 01,01 01 01 0101o 10 \n" + + " 10 10 10`10 10ooo10 10 11o01 \n" + + "01. 01 .01. 01 `01. 01 01 01 1010 \n" + + "010101 01010101 10 10 10 10 10 110 \n" + + "___________________________________________\n" + + " Hello! I'm Jikan\n" + + " What can I do for you today?\n" + + "-------------------------------------------\n"; + /** * Main entry-point for the java.duke.Duke application. */ From 4dc58b4929c6b57f9773881ecb066480ff575aa0 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 9 Mar 2020 22:19:05 +0800 Subject: [PATCH 017/415] Fix style --- src/main/java/jikan/storage/StorageHandler.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/storage/StorageHandler.java b/src/main/java/jikan/storage/StorageHandler.java index 845a820ea..093ccd965 100644 --- a/src/main/java/jikan/storage/StorageHandler.java +++ b/src/main/java/jikan/storage/StorageHandler.java @@ -65,17 +65,17 @@ private static int removeLineFromList(int lineNumber, List list, int rem * @param dataFilePath Path to data file. * @throws IOException If an error occurs while writing to file. */ - private static void updateIndexes(List fileContent, int removedIndex, String dataFilePath) throws IOException { + private static void updateIndexes(List fileContent, int removedIndex, String dataFilePath) + throws IOException { // Update indexes of subsequent tasks (e.g. if you remove task 2, task 3 becomes task 2) - for (int i = removedIndex; i < fileContent.size(); i++) - { + for (int i = removedIndex; i < fileContent.size(); i++) { // Get current comma separated string String currString = fileContent.get(i); String updatedString = decrementIndex(currString, i); // Replace the line with the updated string - replaceLine(i+1, updatedString, dataFilePath); + replaceLine(i + 1, updatedString, dataFilePath); } } From f1cb9281ed3090b17bda98acdd67bdb5f2929ed5 Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Mon, 9 Mar 2020 22:19:22 +0800 Subject: [PATCH 018/415] Fix style --- src/main/java/jikan/storage/StorageHandler.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/storage/StorageHandler.java b/src/main/java/jikan/storage/StorageHandler.java index 845a820ea..093ccd965 100644 --- a/src/main/java/jikan/storage/StorageHandler.java +++ b/src/main/java/jikan/storage/StorageHandler.java @@ -65,17 +65,17 @@ private static int removeLineFromList(int lineNumber, List list, int rem * @param dataFilePath Path to data file. * @throws IOException If an error occurs while writing to file. */ - private static void updateIndexes(List fileContent, int removedIndex, String dataFilePath) throws IOException { + private static void updateIndexes(List fileContent, int removedIndex, String dataFilePath) + throws IOException { // Update indexes of subsequent tasks (e.g. if you remove task 2, task 3 becomes task 2) - for (int i = removedIndex; i < fileContent.size(); i++) - { + for (int i = removedIndex; i < fileContent.size(); i++) { // Get current comma separated string String currString = fileContent.get(i); String updatedString = decrementIndex(currString, i); // Replace the line with the updated string - replaceLine(i+1, updatedString, dataFilePath); + replaceLine(i + 1, updatedString, dataFilePath); } } From 6a1ea2bc6a8c395ad89b2706f8c7663f9f4c9819 Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Mon, 9 Mar 2020 22:21:25 +0800 Subject: [PATCH 019/415] Fix style --- src/test/java/jikan/storage/StorageTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/jikan/storage/StorageTest.java b/src/test/java/jikan/storage/StorageTest.java index f04a38970..ca61366e9 100644 --- a/src/test/java/jikan/storage/StorageTest.java +++ b/src/test/java/jikan/storage/StorageTest.java @@ -1,4 +1,5 @@ package jikan.storage; + import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; @@ -7,4 +8,4 @@ class StorageTest { public void sampleTest() { assertTrue(true); } -} \ No newline at end of file +} From 33e2e6f30047e86ea380b9cc813e1d8103b7c5c2 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 9 Mar 2020 22:25:40 +0800 Subject: [PATCH 020/415] Remove old text redirection --- text-ui-test/EXPECTED.TXT | 9 --------- text-ui-test/input.txt | 1 - 2 files changed, 10 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 892cb6cae..e69de29bb 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,9 +0,0 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - -What is your name? -Hello James Gosling diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index f6ec2e9f9..e69de29bb 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1 +0,0 @@ -James Gosling \ No newline at end of file From 0e21b4c199b83631ea796dd5b22fb3555e9e7a55 Mon Sep 17 00:00:00 2001 From: btricec Date: Tue, 10 Mar 2020 00:50:38 +0800 Subject: [PATCH 021/415] Refactor files and add tests --- src/main/java/{ => seedu/jikan}/Activity.java | 15 +++++++++- .../java/{ => seedu/jikan}/ActivityList.java | 9 ++++-- src/main/java/{ => seedu/jikan}/Jikan.java | 14 +++++---- src/main/java/{ => seedu/jikan}/Parser.java | 3 +- src/main/java/{ => seedu/jikan}/Tag.java | 2 ++ .../{ => seedu}/jikan/storage/Storage.java | 2 +- .../jikan/storage/StorageHandler.java | 2 +- src/test/java/jikan/storage/StorageTest.java | 11 ------- .../java/seedu/jikan/ActivityListTest.java | 27 +++++++++++++++++ src/test/java/seedu/jikan/ActivityTest.java | 29 +++++++++++++++++++ src/test/java/seedu/jikan/ParserTest.java | 12 ++++++++ 11 files changed, 102 insertions(+), 24 deletions(-) rename src/main/java/{ => seedu/jikan}/Activity.java (87%) rename src/main/java/{ => seedu/jikan}/ActivityList.java (94%) rename src/main/java/{ => seedu/jikan}/Jikan.java (79%) rename src/main/java/{ => seedu/jikan}/Parser.java (98%) rename src/main/java/{ => seedu/jikan}/Tag.java (88%) rename src/main/java/{ => seedu}/jikan/storage/Storage.java (98%) rename src/main/java/{ => seedu}/jikan/storage/StorageHandler.java (99%) delete mode 100644 src/test/java/jikan/storage/StorageTest.java create mode 100644 src/test/java/seedu/jikan/ActivityListTest.java create mode 100644 src/test/java/seedu/jikan/ActivityTest.java create mode 100644 src/test/java/seedu/jikan/ParserTest.java diff --git a/src/main/java/Activity.java b/src/main/java/seedu/jikan/Activity.java similarity index 87% rename from src/main/java/Activity.java rename to src/main/java/seedu/jikan/Activity.java index dc9d164d3..ffc78329c 100644 --- a/src/main/java/Activity.java +++ b/src/main/java/seedu/jikan/Activity.java @@ -1,3 +1,4 @@ +package seedu.jikan; import java.time.Duration; import java.time.LocalDateTime; @@ -59,8 +60,20 @@ public String endActivity(LocalDateTime endTime) { return ("You have ended " + this.name + " . Great job !\n"); } + public Duration getDuration() { + return duration; + } + + public String getName() { + return name; + } + + public String[] getTags() { + return tags; + } + /** - * Converts the Activity object to data representation to be stored in a data file. + * Converts the seedu.jikan.Activity object to data representation to be stored in a data file. * File format: * name, startTime, endTime * diff --git a/src/main/java/ActivityList.java b/src/main/java/seedu/jikan/ActivityList.java similarity index 94% rename from src/main/java/ActivityList.java rename to src/main/java/seedu/jikan/ActivityList.java index 7c4f8af2b..b7db67c3c 100644 --- a/src/main/java/ActivityList.java +++ b/src/main/java/seedu/jikan/ActivityList.java @@ -1,4 +1,5 @@ -import java.time.Duration; +package seedu.jikan; + import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; @@ -33,6 +34,10 @@ public ActivityList(File dataFile) { populateTaskList(dataFile); } + public Activity get(int i) { + return activities.get(i); + } + public void add(Activity activity) { activities.add(activity); } @@ -80,7 +85,7 @@ private void populateTaskList(File dataFile) { } /** - * Parses the current line in the data file to an Activity object. + * Parses the current line in the data file to an seedu.jikan.Activity object. * * @param s String to parse. */ diff --git a/src/main/java/Jikan.java b/src/main/java/seedu/jikan/Jikan.java similarity index 79% rename from src/main/java/Jikan.java rename to src/main/java/seedu/jikan/Jikan.java index 81982a2c6..a6c56498f 100644 --- a/src/main/java/Jikan.java +++ b/src/main/java/seedu/jikan/Jikan.java @@ -1,9 +1,11 @@ -import jikan.storage.Storage; +package seedu.jikan; + +import seedu.jikan.storage.Storage; import java.util.Scanner; /** - * Represents the Jikan time tracker. + * Represents the seedu.jikan.Jikan time tracker. */ public class Jikan { /** Constant file path of data file. */ @@ -12,7 +14,7 @@ public class Jikan { /** Storage object for data file. */ private static Storage storage; - /** Activity list to store current tasks in. */ + /** seedu.jikan.Activity list to store current tasks in. */ private static ActivityList activityList; public static final String GREETING = "___________________________________________\n" @@ -23,12 +25,12 @@ public class Jikan { + "01. 01 .01. 01 `01. 01 01 01 1010 \n" + "010101 01010101 10 10 10 10 10 110 \n" + "___________________________________________\n" - + " Hello! I'm Jikan\n" + + " Hello! I'm seedu.jikan.Jikan\n" + " What can I do for you today?\n" + "-------------------------------------------\n"; /** - * Creates ActivityList and loads data from data file if the data file previously existed; + * Creates seedu.jikan.ActivityList and loads data from data file if the data file previously existed; * otherwise, an empty task list is initialized. */ private static void createActivityList() { @@ -40,7 +42,7 @@ private static void createActivityList() { } /** - * Main entry-point for the Jikan application. + * Main entry-point for the seedu.jikan.Jikan application. */ public static void main(String[] args) { System.out.println(GREETING); diff --git a/src/main/java/Parser.java b/src/main/java/seedu/jikan/Parser.java similarity index 98% rename from src/main/java/Parser.java rename to src/main/java/seedu/jikan/Parser.java index 620657f89..d86148c1f 100644 --- a/src/main/java/Parser.java +++ b/src/main/java/seedu/jikan/Parser.java @@ -1,4 +1,4 @@ -/* +package seedu.jikan;/* import java.time.LocalDate; import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; @@ -6,7 +6,6 @@ import java.time.LocalDateTime; import java.util.Arrays; import java.util.Scanner; -import jikan.storage.Storage; /** * Represents the object which parses user input to relevant functions for the execution of commands. diff --git a/src/main/java/Tag.java b/src/main/java/seedu/jikan/Tag.java similarity index 88% rename from src/main/java/Tag.java rename to src/main/java/seedu/jikan/Tag.java index c450b2482..f485e495e 100644 --- a/src/main/java/Tag.java +++ b/src/main/java/seedu/jikan/Tag.java @@ -1,3 +1,5 @@ +package seedu.jikan; + /** * Represents a tag object to tag activities. */ diff --git a/src/main/java/jikan/storage/Storage.java b/src/main/java/seedu/jikan/storage/Storage.java similarity index 98% rename from src/main/java/jikan/storage/Storage.java rename to src/main/java/seedu/jikan/storage/Storage.java index 085484916..6243b9c12 100644 --- a/src/main/java/jikan/storage/Storage.java +++ b/src/main/java/seedu/jikan/storage/Storage.java @@ -1,4 +1,4 @@ -package jikan.storage; +package seedu.jikan.storage; import java.io.File; import java.io.FileWriter; diff --git a/src/main/java/jikan/storage/StorageHandler.java b/src/main/java/seedu/jikan/storage/StorageHandler.java similarity index 99% rename from src/main/java/jikan/storage/StorageHandler.java rename to src/main/java/seedu/jikan/storage/StorageHandler.java index 093ccd965..203d0fc4d 100644 --- a/src/main/java/jikan/storage/StorageHandler.java +++ b/src/main/java/seedu/jikan/storage/StorageHandler.java @@ -1,4 +1,4 @@ -package jikan.storage; +package seedu.jikan.storage; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/src/test/java/jikan/storage/StorageTest.java b/src/test/java/jikan/storage/StorageTest.java deleted file mode 100644 index ca61366e9..000000000 --- a/src/test/java/jikan/storage/StorageTest.java +++ /dev/null @@ -1,11 +0,0 @@ -package jikan.storage; - -import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.jupiter.api.Test; - -class StorageTest { - @Test - public void sampleTest() { - assertTrue(true); - } -} diff --git a/src/test/java/seedu/jikan/ActivityListTest.java b/src/test/java/seedu/jikan/ActivityListTest.java new file mode 100644 index 000000000..3a49c53cc --- /dev/null +++ b/src/test/java/seedu/jikan/ActivityListTest.java @@ -0,0 +1,27 @@ +package seedu.jikan; + +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.*; + +class ActivityListTest { + + @Test + void getIndex() { + ActivityList activities = new ActivityList(); + String[] tags = {"tag1", "tag2"}; + Activity activity1 = new Activity("Activity1", LocalDateTime.parse("2020-01-01T08:00:00"), + LocalDateTime.parse("2020-01-01T10:00:00"), tags); + Activity activity2 = new Activity("Activity2", LocalDateTime.parse("2020-01-01T10:00:00"), + LocalDateTime.parse("2020-01-01T11:00:00"), tags); + Activity activity3 = new Activity("Activity3", LocalDateTime.parse("2020-01-01T05:00:00"), + LocalDateTime.parse("2020-01-01T07:00:00"), tags); + activities.add(activity1); + activities.add(activity2); + activities.add(activity3); + + assertEquals(activity2, activities.get(1)); + } +} \ No newline at end of file diff --git a/src/test/java/seedu/jikan/ActivityTest.java b/src/test/java/seedu/jikan/ActivityTest.java new file mode 100644 index 000000000..34e38a905 --- /dev/null +++ b/src/test/java/seedu/jikan/ActivityTest.java @@ -0,0 +1,29 @@ +package seedu.jikan; + +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.*; + +class ActivityTest { + + String[] tags = {"tag1", "tag2"}; + Activity activity = new Activity("Activity", LocalDateTime.parse("2020-01-01T08:00:00"), + LocalDateTime.parse("2020-01-01T10:00:00"), tags); + + @Test + void getDuration() { + assertEquals("PT2H", activity.getDuration().toString()); + } + + @Test + void getName() { + assertEquals("Activity", activity.getName()); + } + + @Test + void getTags() { + assertEquals(tags, activity.getTags()); + } +} \ No newline at end of file diff --git a/src/test/java/seedu/jikan/ParserTest.java b/src/test/java/seedu/jikan/ParserTest.java new file mode 100644 index 000000000..e3afd9f60 --- /dev/null +++ b/src/test/java/seedu/jikan/ParserTest.java @@ -0,0 +1,12 @@ +package seedu.jikan; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ParserTest { + + @Test + void parseUserCommands() { + } +} \ No newline at end of file From 0da563d30f8f68d0eef6c865cc5eed5584aeb585 Mon Sep 17 00:00:00 2001 From: btricec Date: Tue, 10 Mar 2020 09:20:24 +0800 Subject: [PATCH 022/415] Fix style violations --- src/main/java/seedu/jikan/Parser.java | 7 ++----- src/test/java/seedu/jikan/ActivityListTest.java | 2 +- src/test/java/seedu/jikan/ActivityTest.java | 2 +- src/test/java/seedu/jikan/ParserTest.java | 12 ------------ 4 files changed, 4 insertions(+), 19 deletions(-) delete mode 100644 src/test/java/seedu/jikan/ParserTest.java diff --git a/src/main/java/seedu/jikan/Parser.java b/src/main/java/seedu/jikan/Parser.java index d86148c1f..dfa7fa1e1 100644 --- a/src/main/java/seedu/jikan/Parser.java +++ b/src/main/java/seedu/jikan/Parser.java @@ -1,8 +1,5 @@ -package seedu.jikan;/* -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; - */ +package seedu.jikan; + import java.time.LocalDateTime; import java.util.Arrays; import java.util.Scanner; diff --git a/src/test/java/seedu/jikan/ActivityListTest.java b/src/test/java/seedu/jikan/ActivityListTest.java index 3a49c53cc..18821f8a5 100644 --- a/src/test/java/seedu/jikan/ActivityListTest.java +++ b/src/test/java/seedu/jikan/ActivityListTest.java @@ -4,7 +4,7 @@ import java.time.LocalDateTime; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class ActivityListTest { diff --git a/src/test/java/seedu/jikan/ActivityTest.java b/src/test/java/seedu/jikan/ActivityTest.java index 34e38a905..d56ecaa2c 100644 --- a/src/test/java/seedu/jikan/ActivityTest.java +++ b/src/test/java/seedu/jikan/ActivityTest.java @@ -4,7 +4,7 @@ import java.time.LocalDateTime; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class ActivityTest { diff --git a/src/test/java/seedu/jikan/ParserTest.java b/src/test/java/seedu/jikan/ParserTest.java deleted file mode 100644 index e3afd9f60..000000000 --- a/src/test/java/seedu/jikan/ParserTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package seedu.jikan; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class ParserTest { - - @Test - void parseUserCommands() { - } -} \ No newline at end of file From d5a7fa3649911000999d03ce50068f5efb3da1ef Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 10 Mar 2020 15:58:21 +0800 Subject: [PATCH 023/415] Refactor --- src/main/java/{seedu => }/jikan/Jikan.java | 16 +++++++++------- .../jikan => jikan/activity}/Activity.java | 4 ++-- .../jikan => jikan/activity}/ActivityList.java | 4 ++-- .../{seedu/jikan => jikan/parser}/Parser.java | 5 ++++- .../java/{seedu => }/jikan/storage/Storage.java | 2 +- .../jikan/storage/StorageHandler.java | 2 +- src/main/java/seedu/jikan/Tag.java | 12 ------------ .../activity}/ActivityListTest.java | 4 +++- .../jikan => jikan/activity}/ActivityTest.java | 3 ++- 9 files changed, 24 insertions(+), 28 deletions(-) rename src/main/java/{seedu => }/jikan/Jikan.java (77%) rename src/main/java/{seedu/jikan => jikan/activity}/Activity.java (94%) rename src/main/java/{seedu/jikan => jikan/activity}/ActivityList.java (96%) rename src/main/java/{seedu/jikan => jikan/parser}/Parser.java (96%) rename src/main/java/{seedu => }/jikan/storage/Storage.java (98%) rename src/main/java/{seedu => }/jikan/storage/StorageHandler.java (99%) delete mode 100644 src/main/java/seedu/jikan/Tag.java rename src/test/java/{seedu/jikan => jikan/activity}/ActivityListTest.java (91%) rename src/test/java/{seedu/jikan => jikan/activity}/ActivityTest.java (91%) diff --git a/src/main/java/seedu/jikan/Jikan.java b/src/main/java/jikan/Jikan.java similarity index 77% rename from src/main/java/seedu/jikan/Jikan.java rename to src/main/java/jikan/Jikan.java index a6c56498f..d5abf4c9c 100644 --- a/src/main/java/seedu/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -1,11 +1,13 @@ -package seedu.jikan; +package jikan; -import seedu.jikan.storage.Storage; +import jikan.activity.ActivityList; +import jikan.parser.Parser; +import jikan.storage.Storage; import java.util.Scanner; /** - * Represents the seedu.jikan.Jikan time tracker. + * Represents the jikan.Jikan time tracker. */ public class Jikan { /** Constant file path of data file. */ @@ -14,7 +16,7 @@ public class Jikan { /** Storage object for data file. */ private static Storage storage; - /** seedu.jikan.Activity list to store current tasks in. */ + /** jikan.activity.Activity list to store current tasks in. */ private static ActivityList activityList; public static final String GREETING = "___________________________________________\n" @@ -25,12 +27,12 @@ public class Jikan { + "01. 01 .01. 01 `01. 01 01 01 1010 \n" + "010101 01010101 10 10 10 10 10 110 \n" + "___________________________________________\n" - + " Hello! I'm seedu.jikan.Jikan\n" + + " Hello! I'm jikan.Jikan\n" + " What can I do for you today?\n" + "-------------------------------------------\n"; /** - * Creates seedu.jikan.ActivityList and loads data from data file if the data file previously existed; + * Creates jikan.activity.ActivityList and loads data from data file if the data file previously existed; * otherwise, an empty task list is initialized. */ private static void createActivityList() { @@ -42,7 +44,7 @@ private static void createActivityList() { } /** - * Main entry-point for the seedu.jikan.Jikan application. + * Main entry-point for the jikan.Jikan application. */ public static void main(String[] args) { System.out.println(GREETING); diff --git a/src/main/java/seedu/jikan/Activity.java b/src/main/java/jikan/activity/Activity.java similarity index 94% rename from src/main/java/seedu/jikan/Activity.java rename to src/main/java/jikan/activity/Activity.java index ffc78329c..2095c0b58 100644 --- a/src/main/java/seedu/jikan/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -1,4 +1,4 @@ -package seedu.jikan; +package jikan.activity; import java.time.Duration; import java.time.LocalDateTime; @@ -73,7 +73,7 @@ public String[] getTags() { } /** - * Converts the seedu.jikan.Activity object to data representation to be stored in a data file. + * Converts the jikan.activity.Activity object to data representation to be stored in a data file. * File format: * name, startTime, endTime * diff --git a/src/main/java/seedu/jikan/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java similarity index 96% rename from src/main/java/seedu/jikan/ActivityList.java rename to src/main/java/jikan/activity/ActivityList.java index b7db67c3c..ce4b728cb 100644 --- a/src/main/java/seedu/jikan/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -1,4 +1,4 @@ -package seedu.jikan; +package jikan.activity; import java.time.LocalDateTime; import java.util.ArrayList; @@ -85,7 +85,7 @@ private void populateTaskList(File dataFile) { } /** - * Parses the current line in the data file to an seedu.jikan.Activity object. + * Parses the current line in the data file to an jikan.activity.Activity object. * * @param s String to parse. */ diff --git a/src/main/java/seedu/jikan/Parser.java b/src/main/java/jikan/parser/Parser.java similarity index 96% rename from src/main/java/seedu/jikan/Parser.java rename to src/main/java/jikan/parser/Parser.java index dfa7fa1e1..5da590107 100644 --- a/src/main/java/seedu/jikan/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,4 +1,7 @@ -package seedu.jikan; +package jikan.parser; + +import jikan.activity.Activity; +import jikan.activity.ActivityList; import java.time.LocalDateTime; import java.util.Arrays; diff --git a/src/main/java/seedu/jikan/storage/Storage.java b/src/main/java/jikan/storage/Storage.java similarity index 98% rename from src/main/java/seedu/jikan/storage/Storage.java rename to src/main/java/jikan/storage/Storage.java index 6243b9c12..085484916 100644 --- a/src/main/java/seedu/jikan/storage/Storage.java +++ b/src/main/java/jikan/storage/Storage.java @@ -1,4 +1,4 @@ -package seedu.jikan.storage; +package jikan.storage; import java.io.File; import java.io.FileWriter; diff --git a/src/main/java/seedu/jikan/storage/StorageHandler.java b/src/main/java/jikan/storage/StorageHandler.java similarity index 99% rename from src/main/java/seedu/jikan/storage/StorageHandler.java rename to src/main/java/jikan/storage/StorageHandler.java index 203d0fc4d..093ccd965 100644 --- a/src/main/java/seedu/jikan/storage/StorageHandler.java +++ b/src/main/java/jikan/storage/StorageHandler.java @@ -1,4 +1,4 @@ -package seedu.jikan.storage; +package jikan.storage; import java.io.IOException; import java.nio.charset.StandardCharsets; diff --git a/src/main/java/seedu/jikan/Tag.java b/src/main/java/seedu/jikan/Tag.java deleted file mode 100644 index f485e495e..000000000 --- a/src/main/java/seedu/jikan/Tag.java +++ /dev/null @@ -1,12 +0,0 @@ -package seedu.jikan; - -/** - * Represents a tag object to tag activities. - */ -public class Tag { - protected String name; - - public Tag(String name) { - this.name = name; - } -} diff --git a/src/test/java/seedu/jikan/ActivityListTest.java b/src/test/java/jikan/activity/ActivityListTest.java similarity index 91% rename from src/test/java/seedu/jikan/ActivityListTest.java rename to src/test/java/jikan/activity/ActivityListTest.java index 18821f8a5..f5c91e62d 100644 --- a/src/test/java/seedu/jikan/ActivityListTest.java +++ b/src/test/java/jikan/activity/ActivityListTest.java @@ -1,5 +1,7 @@ -package seedu.jikan; +package jikan.activity; +import jikan.activity.Activity; +import jikan.activity.ActivityList; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; diff --git a/src/test/java/seedu/jikan/ActivityTest.java b/src/test/java/jikan/activity/ActivityTest.java similarity index 91% rename from src/test/java/seedu/jikan/ActivityTest.java rename to src/test/java/jikan/activity/ActivityTest.java index d56ecaa2c..a1b67fb6c 100644 --- a/src/test/java/seedu/jikan/ActivityTest.java +++ b/src/test/java/jikan/activity/ActivityTest.java @@ -1,5 +1,6 @@ -package seedu.jikan; +package jikan.activity; +import jikan.activity.Activity; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; From 1c6886eb90c3f48a8e16d6f46eb735adda6d820a Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 10 Mar 2020 16:11:25 +0800 Subject: [PATCH 024/415] Fix storage to save task on end --- src/main/java/jikan/Jikan.java | 3 +- .../java/jikan/activity/ActivityList.java | 29 +++++++++++++++++-- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index d5abf4c9c..e1b372b9d 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -37,9 +37,10 @@ public class Jikan { */ private static void createActivityList() { if (storage.loadFile()) { - activityList = new ActivityList(storage.dataFile); + activityList = new ActivityList(storage); } else { activityList = new ActivityList(); + activityList.storage = storage; } } diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index ce4b728cb..6067edc2a 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -1,5 +1,8 @@ package jikan.activity; +import jikan.storage.Storage; + +import java.io.IOException; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; @@ -14,6 +17,8 @@ */ public class ActivityList { ArrayList activities; + public Storage storage; // Storage the list was loaded from + //int size; /** @@ -27,11 +32,12 @@ public ActivityList() { /** * Loads activityList from data file. * - * @param dataFile Data file to load from. + * @param storage Storage to load from. */ - public ActivityList(File dataFile) { + public ActivityList(Storage storage) { this.activities = new ArrayList<>(); - populateTaskList(dataFile); + this.storage = storage; + populateTaskList(storage.dataFile); } public Activity get(int i) { @@ -40,6 +46,23 @@ public Activity get(int i) { public void add(Activity activity) { activities.add(activity); + + String dataLine = activity.toData(); + + updateFile(dataLine); + } + + /** + * Updates data file with new task. + * + * @param dataLine Line to write to file. + */ + private void updateFile(String dataLine) { + try { + storage.writeToFile(dataLine); + } catch (IOException e) { + System.out.println("Error saving task to data file."); + } } public int getSize() { From c480d59358cca2456c94445e185f2c76c22f67d0 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 10 Mar 2020 16:40:57 +0800 Subject: [PATCH 025/415] Add javadoc --- src/main/java/jikan/activity/ActivityList.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 6067edc2a..3f8e63d5b 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -44,6 +44,10 @@ public Activity get(int i) { return activities.get(i); } + /** + * Adds activity to activity list and stores it in the data file. + * @param activity + */ public void add(Activity activity) { activities.add(activity); From c132b0f57f134df8b0108f29f096cb5941ce81ae Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 10 Mar 2020 17:38:28 +0800 Subject: [PATCH 026/415] Add Storage tests --- src/main/java/jikan/Jikan.java | 15 +++-- .../java/jikan/activity/ActivityList.java | 2 +- src/main/java/jikan/storage/Storage.java | 12 +--- .../jikan/storage/StorageHandlerTest.java | 4 ++ src/test/java/jikan/storage/StorageTest.java | 65 +++++++++++++++++++ 5 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 src/test/java/jikan/storage/StorageHandlerTest.java create mode 100644 src/test/java/jikan/storage/StorageTest.java diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index e1b372b9d..56f62c2e9 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -4,6 +4,7 @@ import jikan.parser.Parser; import jikan.storage.Storage; +import java.io.IOException; import java.util.Scanner; /** @@ -36,11 +37,15 @@ public class Jikan { * otherwise, an empty task list is initialized. */ private static void createActivityList() { - if (storage.loadFile()) { - activityList = new ActivityList(storage); - } else { - activityList = new ActivityList(); - activityList.storage = storage; + try { + if (storage.loadFile()) { + activityList = new ActivityList(storage); + } else { + activityList = new ActivityList(); + activityList.storage = storage; + } + } catch (IOException e) { + System.out.println("Error loading/creating data file."); } } diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 3f8e63d5b..7e5bd4e2f 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -46,7 +46,7 @@ public Activity get(int i) { /** * Adds activity to activity list and stores it in the data file. - * @param activity + * @param activity Activity to add. */ public void add(Activity activity) { activities.add(activity); diff --git a/src/main/java/jikan/storage/Storage.java b/src/main/java/jikan/storage/Storage.java index 085484916..0ecb7d229 100644 --- a/src/main/java/jikan/storage/Storage.java +++ b/src/main/java/jikan/storage/Storage.java @@ -37,23 +37,17 @@ public void writeToFile(String s) throws IOException { fw.close(); } - // Return true if file previously existed, false if it didn't exist (and it created a new one) - /** * Loads the data file. Creates file and directories if data file did not previously exist. * * @return True if file previously existed (and was not created); False if file did not exist and was created. */ - public boolean loadFile() { + public boolean loadFile() throws IOException { // Create data file if it does not exist already if (!dataFile.exists()) { - try { - createDataFile(); - return false; // false = file didn't previously exist, so it was created - } catch (IOException e) { - System.out.println("Error loading data file."); - } + createDataFile(); + return false; // false = file didn't previously exist, so it was created } return true; // true = file previously existed, and was not created } diff --git a/src/test/java/jikan/storage/StorageHandlerTest.java b/src/test/java/jikan/storage/StorageHandlerTest.java new file mode 100644 index 000000000..3b95ee7a9 --- /dev/null +++ b/src/test/java/jikan/storage/StorageHandlerTest.java @@ -0,0 +1,4 @@ +package jikan.storage; + +public class StorageHandlerTest { +} diff --git a/src/test/java/jikan/storage/StorageTest.java b/src/test/java/jikan/storage/StorageTest.java new file mode 100644 index 000000000..54b9f4601 --- /dev/null +++ b/src/test/java/jikan/storage/StorageTest.java @@ -0,0 +1,65 @@ +package jikan.storage; + +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Scanner; + +import static org.junit.jupiter.api.Assertions.*; + +public class StorageTest { + + @Test + public void loadFile_fileDoesNotExist() throws IOException { + Storage storage = new Storage("data/test.txt"); + // First time calling loadFile, so file does not exist yet + assertFalse(storage.loadFile()); + storage.dataFile.delete(); + } + + @Test + public void loadFile_fileExists() throws IOException { + Storage storage = new Storage("data/test.txt"); + + // First time calling loadFile, so file does not exist yet + storage.loadFile(); + + // loadFile was called once already, so now file exists + assertTrue(storage.loadFile()); + + storage.dataFile.delete(); + } + + @Test + public void testCreateDataFile() throws IOException{ + Storage storage = new Storage("data/test.txt"); + storage.loadFile(); + assertTrue(storage.dataFile.exists()); + storage.dataFile.delete(); + } + + @Test + public void testCreateDataFile_IOException() { + Storage storage = new Storage("//\\-@#4/\\/**3"); + + IOException thrown = assertThrows( + IOException.class, + storage::loadFile, + "IOException during file creation" + ); + } + + @Test + public void testWriteToFile() throws IOException { + Storage storage = new Storage("data/test.txt"); + storage.loadFile(); + String originalString = "This is a test string."; + String writtenString = ""; + storage.writeToFile(originalString); + Scanner dataScanner = new Scanner(storage.dataFile); + while (dataScanner.hasNext()) { + writtenString = dataScanner.nextLine(); + } + assertEquals(originalString, writtenString); + } +} From f51926779555902e4411ff59259747787d4d47db Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 10 Mar 2020 18:18:05 +0800 Subject: [PATCH 027/415] Add StorageHandler tests --- .../jikan/storage/StorageHandlerTest.java | 78 +++++++++++++++++++ src/test/java/jikan/storage/StorageTest.java | 15 +++- 2 files changed, 90 insertions(+), 3 deletions(-) diff --git a/src/test/java/jikan/storage/StorageHandlerTest.java b/src/test/java/jikan/storage/StorageHandlerTest.java index 3b95ee7a9..31e13f263 100644 --- a/src/test/java/jikan/storage/StorageHandlerTest.java +++ b/src/test/java/jikan/storage/StorageHandlerTest.java @@ -1,4 +1,82 @@ package jikan.storage; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Scanner; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + public class StorageHandlerTest { + + @Test + public void removeLine() throws IOException { + // Generate random suffix for file + // (quick solution to avoid conflicts with tests in StorageTest + int random = (int )(Math.random() * 500 + 1); + String filepath = "data/test" + random + ".txt"; + Storage storage = new Storage(filepath); + + String line1 = "1. a"; + String line2 = "2. b"; + String line3 = "3. c"; + String writtenString = ""; + + storage.writeToFile(line1); + storage.writeToFile(line2); + storage.writeToFile(line3); + + StorageHandler.removeLine(2, storage.dataFilePath); + + int i = 0; + Scanner dataScanner = new Scanner(storage.dataFile); + while (dataScanner.hasNext()) { + writtenString = dataScanner.nextLine(); + if (i == 0) { + assertEquals(line1, writtenString); + } else { + assertEquals(line3, writtenString); + } + i++; + } + storage.dataFile.delete(); + } + + @Test + public void test_replaceLine() throws IOException { + List list = Arrays.asList("1. a", "2. b", "10. c"); + + String replace = "This string has been replaced."; + + // Generate random suffix for file + // (quick solution to avoid conflicts with tests in StorageTest) + int random = (int )(Math.random() * 500 + 1); + String filepath = "data/test" + random + ".txt"; + Storage storage = new Storage(filepath); + + for (int i = 0 ; i < list.size() ; i++) { + storage.writeToFile(list.get(i)); + } + + int j = 0; + Scanner dataScanner = new Scanner(storage.dataFile); + StorageHandler.replaceLine(2, replace, storage.dataFilePath); + + String replacedString = ""; + + while (dataScanner.hasNext()) { + replacedString = dataScanner.nextLine(); + // Check second line + if (j == 1) { + assertEquals(replace, replacedString); + j++; + } + } + storage.dataFile.delete(); + } } diff --git a/src/test/java/jikan/storage/StorageTest.java b/src/test/java/jikan/storage/StorageTest.java index 54b9f4601..780951415 100644 --- a/src/test/java/jikan/storage/StorageTest.java +++ b/src/test/java/jikan/storage/StorageTest.java @@ -5,7 +5,10 @@ import java.io.IOException; import java.util.Scanner; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; public class StorageTest { @@ -39,7 +42,7 @@ public void testCreateDataFile() throws IOException{ } @Test - public void testCreateDataFile_IOException() { + public void testCreateDataFile_IOException() throws IOException { Storage storage = new Storage("//\\-@#4/\\/**3"); IOException thrown = assertThrows( @@ -47,11 +50,16 @@ public void testCreateDataFile_IOException() { storage::loadFile, "IOException during file creation" ); + storage.dataFile.delete(); } @Test public void testWriteToFile() throws IOException { - Storage storage = new Storage("data/test.txt"); + // Generate random suffix for file + // (quick solution to avoid conflicts with other tests) + int random = (int )(Math.random() * 500 + 1); + String filepath = "data/test" + random + ".txt"; + Storage storage = new Storage(filepath); storage.loadFile(); String originalString = "This is a test string."; String writtenString = ""; @@ -61,5 +69,6 @@ public void testWriteToFile() throws IOException { writtenString = dataScanner.nextLine(); } assertEquals(originalString, writtenString); + storage.dataFile.delete(); } } From 36e8a100458709e20c800828cf61dbe2e6ce7d48 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 10 Mar 2020 18:21:14 +0800 Subject: [PATCH 028/415] Fix style errors --- src/test/java/jikan/storage/StorageHandlerTest.java | 2 +- src/test/java/jikan/storage/StorageTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/jikan/storage/StorageHandlerTest.java b/src/test/java/jikan/storage/StorageHandlerTest.java index 31e13f263..dd337e658 100644 --- a/src/test/java/jikan/storage/StorageHandlerTest.java +++ b/src/test/java/jikan/storage/StorageHandlerTest.java @@ -59,7 +59,7 @@ public void test_replaceLine() throws IOException { String filepath = "data/test" + random + ".txt"; Storage storage = new Storage(filepath); - for (int i = 0 ; i < list.size() ; i++) { + for (int i = 0; i < list.size(); i++) { storage.writeToFile(list.get(i)); } diff --git a/src/test/java/jikan/storage/StorageTest.java b/src/test/java/jikan/storage/StorageTest.java index 780951415..93cdc1340 100644 --- a/src/test/java/jikan/storage/StorageTest.java +++ b/src/test/java/jikan/storage/StorageTest.java @@ -34,7 +34,7 @@ public void loadFile_fileExists() throws IOException { } @Test - public void testCreateDataFile() throws IOException{ + public void testCreateDataFile() throws IOException { Storage storage = new Storage("data/test.txt"); storage.loadFile(); assertTrue(storage.dataFile.exists()); From a71e84dd73981e5adda7c824c28ae63ae5afeeab Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 10 Mar 2020 18:23:09 +0800 Subject: [PATCH 029/415] Fix style errors --- src/test/java/jikan/storage/StorageTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/jikan/storage/StorageTest.java b/src/test/java/jikan/storage/StorageTest.java index 93cdc1340..3e2647db5 100644 --- a/src/test/java/jikan/storage/StorageTest.java +++ b/src/test/java/jikan/storage/StorageTest.java @@ -42,7 +42,7 @@ public void testCreateDataFile() throws IOException { } @Test - public void testCreateDataFile_IOException() throws IOException { + public void testCreateDataFile_IoException() throws IOException { Storage storage = new Storage("//\\-@#4/\\/**3"); IOException thrown = assertThrows( From bd12ac0e5bd70160cfd486126e2a6d81305762bd Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 10 Mar 2020 18:25:57 +0800 Subject: [PATCH 030/415] Fix errors in tests --- src/test/java/jikan/storage/StorageHandlerTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/jikan/storage/StorageHandlerTest.java b/src/test/java/jikan/storage/StorageHandlerTest.java index dd337e658..df4e36931 100644 --- a/src/test/java/jikan/storage/StorageHandlerTest.java +++ b/src/test/java/jikan/storage/StorageHandlerTest.java @@ -21,6 +21,7 @@ public void removeLine() throws IOException { int random = (int )(Math.random() * 500 + 1); String filepath = "data/test" + random + ".txt"; Storage storage = new Storage(filepath); + storage.loadFile(); String line1 = "1. a"; String line2 = "2. b"; @@ -58,6 +59,7 @@ public void test_replaceLine() throws IOException { int random = (int )(Math.random() * 500 + 1); String filepath = "data/test" + random + ".txt"; Storage storage = new Storage(filepath); + storage.loadFile(); for (int i = 0; i < list.size(); i++) { storage.writeToFile(list.get(i)); From b2ef6f01115c46daefbb19b89e7a48b6d810ac56 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 10 Mar 2020 18:30:17 +0800 Subject: [PATCH 031/415] Fixed error in tests --- src/test/java/jikan/activity/ActivityListTest.java | 6 ++++-- src/test/java/jikan/storage/StorageHandlerTest.java | 3 --- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/java/jikan/activity/ActivityListTest.java b/src/test/java/jikan/activity/ActivityListTest.java index f5c91e62d..a9f8dbea6 100644 --- a/src/test/java/jikan/activity/ActivityListTest.java +++ b/src/test/java/jikan/activity/ActivityListTest.java @@ -1,7 +1,6 @@ package jikan.activity; -import jikan.activity.Activity; -import jikan.activity.ActivityList; +import jikan.storage.Storage; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; @@ -13,6 +12,7 @@ class ActivityListTest { @Test void getIndex() { ActivityList activities = new ActivityList(); + activities.storage = new Storage("data/activityList_test.txt"); String[] tags = {"tag1", "tag2"}; Activity activity1 = new Activity("Activity1", LocalDateTime.parse("2020-01-01T08:00:00"), LocalDateTime.parse("2020-01-01T10:00:00"), tags); @@ -25,5 +25,7 @@ void getIndex() { activities.add(activity3); assertEquals(activity2, activities.get(1)); + + activities.storage.dataFile.delete(); } } \ No newline at end of file diff --git a/src/test/java/jikan/storage/StorageHandlerTest.java b/src/test/java/jikan/storage/StorageHandlerTest.java index df4e36931..d9365ccec 100644 --- a/src/test/java/jikan/storage/StorageHandlerTest.java +++ b/src/test/java/jikan/storage/StorageHandlerTest.java @@ -8,9 +8,6 @@ import java.util.Scanner; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assertions.assertTrue; public class StorageHandlerTest { From 5dce5610ec26b0378cbe404d130b3f9c51e62323 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 10 Mar 2020 23:56:06 +0800 Subject: [PATCH 032/415] Add a Ui class and refactor some code --- src/main/java/jikan/Jikan.java | 29 +++---- src/main/java/jikan/Ui.java | 63 ++++++++++++++ src/main/java/jikan/activity/Activity.java | 10 +-- .../java/jikan/activity/ActivityList.java | 24 +----- src/main/java/jikan/parser/Parser.java | 82 +++++++++++++------ .../java/jikan/activity/ActivityTest.java | 1 - src/test/java/jikan/parser/ParserTest.java | 28 +++++++ 7 files changed, 163 insertions(+), 74 deletions(-) create mode 100644 src/main/java/jikan/Ui.java create mode 100644 src/test/java/jikan/parser/ParserTest.java diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 56f62c2e9..88f09504b 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -8,7 +8,7 @@ import java.util.Scanner; /** - * Represents the jikan.Jikan time tracker. + * Represents the Jikan time tracker. */ public class Jikan { /** Constant file path of data file. */ @@ -17,26 +17,19 @@ public class Jikan { /** Storage object for data file. */ private static Storage storage; - /** jikan.activity.Activity list to store current tasks in. */ + /** Activity list to store current tasks in. */ private static ActivityList activityList; - public static final String GREETING = "___________________________________________\n" - + " 0101 01010101 01 01 .010. 101 01 \n" - + " `10' `10' 10 ,10' 10' `10 101o 01 \n" - + " 01 01 01,01 01 01 0101o 10 \n" - + " 10 10 10`10 10ooo10 10 11o01 \n" - + "01. 01 .01. 01 `01. 01 01 01 1010 \n" - + "010101 01010101 10 10 10 10 10 110 \n" - + "___________________________________________\n" - + " Hello! I'm jikan.Jikan\n" - + " What can I do for you today?\n" - + "-------------------------------------------\n"; + /** Ui to handle printing. */ + private static Ui ui = new Ui(); + + private static Parser parser = new Parser(); /** - * Creates jikan.activity.ActivityList and loads data from data file if the data file previously existed; + * Creates ActivityList and loads data from data file if the data file previously existed; * otherwise, an empty task list is initialized. */ - private static void createActivityList() { + public static void createActivityList() { try { if (storage.loadFile()) { activityList = new ActivityList(storage); @@ -50,13 +43,13 @@ private static void createActivityList() { } /** - * Main entry-point for the jikan.Jikan application. + * Main entry-point for the Jikan application. */ public static void main(String[] args) { - System.out.println(GREETING); + ui.printGreeting(); Scanner in = new Scanner(System.in); storage = new Storage(DATA_FILE_PATH); createActivityList(); - Parser.parseUserCommands(in, activityList); + parser.parseUserCommands(in, activityList); } } diff --git a/src/main/java/jikan/Ui.java b/src/main/java/jikan/Ui.java new file mode 100644 index 000000000..5688ae4b5 --- /dev/null +++ b/src/main/java/jikan/Ui.java @@ -0,0 +1,63 @@ +package jikan; + +import jikan.activity.ActivityList; +import java.util.Arrays; +import java.util.concurrent.TimeUnit; + +public class Ui { + public static final String GREETING = "___________________________________________\n" + + " 0101 01010101 01 01 .010. 101 01 \n" + + " `10' `10' 10 ,10' 10' `10 101o 01 \n" + + " 01 01 01,01 01 01 0101o 10 \n" + + " 10 10 10`10 10ooo10 10 11o01 \n" + + "01. 01 .01. 01 `01. 01 01 01 1010 \n" + + "010101 01010101 10 10 10 10 10 110 \n" + + "___________________________________________\n" + + " Hello! I'm Jikan\n" + + " What can I do for you today?"; + + public static final String DIVIDER = "-------------------------------------------"; + + /** Prints the logo and greeting so users know the app is working. */ + public void printGreeting() { + System.out.println(GREETING); + System.out.println(DIVIDER); + } + + /** Prints exit message and exits the app. */ + public void exitFromApp() { + System.out.println(DIVIDER); + System.out.println(" Bye! See you again."); + System.out.println(DIVIDER); + System.exit(0); + } + + /** Prints divider between user input and app feedback. */ + public void printDivider(String line) { + System.out.println(DIVIDER); + System.out.println(line); + System.out.println(DIVIDER); + } + + /** Prints all the activities in the list. */ + public void printList(ActivityList activityList) { + System.out.println(DIVIDER); + System.out.println("Your completed activities:"); + for (int i = 0; i < activityList.getSize(); i++) { + long durationInNanos = (activityList.get(i).duration).toNanos(); + String duration = String.format("%02d:%02d:%02d", + TimeUnit.NANOSECONDS.toHours(durationInNanos), + TimeUnit.NANOSECONDS.toMinutes(durationInNanos) + - TimeUnit.HOURS.toMinutes(TimeUnit.NANOSECONDS.toHours(durationInNanos)), + TimeUnit.NANOSECONDS.toSeconds(durationInNanos) + - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(durationInNanos))); + System.out.print(i + 1 + ". " + activityList.get(i).name + " " + duration); + if (activityList.get(i).tags != null) { + System.out.println(" " + Arrays.toString(activityList.get(i).tags)); + } else { + System.out.print("\n"); + } + } + System.out.println(DIVIDER); + } +} diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 2095c0b58..7d5529845 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -9,11 +9,11 @@ */ public class Activity { - protected String name; - protected String[] tags; - protected LocalDateTime startTime; - protected LocalDateTime endTime; - protected Duration duration; + public String name; + public String[] tags; + public LocalDateTime startTime; + public LocalDateTime endTime; + public Duration duration; /* protected String name; diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 7e5bd4e2f..81b68a83e 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -16,7 +16,7 @@ * Represents the list of activities. */ public class ActivityList { - ArrayList activities; + public ArrayList activities; public Storage storage; // Storage the list was loaded from //int size; @@ -73,27 +73,6 @@ public int getSize() { return activities.size(); } - /** - * Prints the activityList. - */ - public void printList() { - System.out.println("Your completed activities:"); - for (int i = 0; i < this.getSize(); i++) { - long durationInNanos = (activities.get(i).duration).toNanos(); - String duration = String.format("%02d:%02d:%02d", - TimeUnit.NANOSECONDS.toHours(durationInNanos), - TimeUnit.NANOSECONDS.toMinutes(durationInNanos) - - TimeUnit.HOURS.toMinutes(TimeUnit.NANOSECONDS.toHours(durationInNanos)), - TimeUnit.NANOSECONDS.toSeconds(durationInNanos) - - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(durationInNanos))); - System.out.print(i + 1 + ". " + activities.get(i).name + " " + duration); - if (activities.get(i).tags != null) { - System.out.println(" " + Arrays.toString(activities.get(i).tags)); - } else { - System.out.print("\n"); - } - } - } /** * Populates task list from file. @@ -119,7 +98,6 @@ private void populateTaskList(File dataFile) { private void parseDataLine(String s) { List strings = Arrays.asList(s.split(",")); - String[] tags; // if there are tags diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 5da590107..67f31d1e7 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,5 +1,6 @@ package jikan.parser; +import jikan.Ui; import jikan.activity.Activity; import jikan.activity.ActivityList; @@ -12,54 +13,81 @@ */ public class Parser { + protected LocalDateTime startTime = null; + protected LocalDateTime endTime = null; + private String[] tags = null; + private Ui ui = new Ui(); + protected String[] tokenizedInputs; + String instruction; + /** * Parses user commands to relevant functions to carry out the commands. * @param scanner scanner object which reads user input * @param activityList the list of activities */ - public static void parseUserCommands(Scanner scanner, ActivityList activityList) { - boolean exit = false; - Activity newActivity; - LocalDateTime startTime = null; - String[] tags = null; - - while (exit == false) { + public void parseUserCommands(Scanner scanner, ActivityList activityList) { + while (true) { String userInput = scanner.nextLine(); - String[] tokenizedInputs = userInput.split(" "); - String instruction = tokenizedInputs[0]; + tokenizedInputs = userInput.split(" "); + instruction = tokenizedInputs[0]; switch (instruction) { case "bye": - System.out.println("Bye! See you again.\n"); - exit = true; + ui.exitFromApp(); break; case "start": - System.out.println("Started " + tokenizedInputs[1] + "\n"); - if (tokenizedInputs.length > 2) { - tags = Arrays.copyOfRange(tokenizedInputs, 2, tokenizedInputs.length); - } - startTime = LocalDateTime.now(); + parseStart(); break; case "end": - if (startTime == null) { - System.out.println("You have not started any activity!"); - } else { - System.out.println("Ended " + tokenizedInputs[1] + "\n"); - newActivity = new Activity(tokenizedInputs[1], startTime, LocalDateTime.now(), tags); - activityList.add(newActivity); - } + parseEnd(activityList); break; case "list": - activityList.printList(); + ui.printList(activityList); break; case "abort": - startTime = null; - System.out.println("You have aborted the current activity!"); + parseAbort(); break; default: - System.out.println("☹ OOPS!!! I'm sorry, but I don't know what that means :-("); + parseDefault(); break; } } } + + /** Method to parse user inputs that are not recognised. */ + private void parseDefault() { + String line = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; + ui.printDivider(line); + } + + /** Method to parse the abort command. */ + private void parseAbort() { + startTime = null; + String line = "You have aborted the current activity!"; + ui.printDivider(line); + } + + /** Method to parse the start activity command. */ + public void parseStart() { + String line = "Started " + tokenizedInputs[1]; + ui.printDivider(line); + if (tokenizedInputs.length > 2) { + tags = Arrays.copyOfRange(tokenizedInputs, 2, tokenizedInputs.length); + } + startTime = LocalDateTime.now(); + } + + /** Method to parse the end activity command. */ + public void parseEnd(ActivityList activityList) { + if (startTime == null) { + String line = "You have not started any activity!"; + ui.printDivider(line); + } else { + String line = "Ended " + tokenizedInputs[1]; + ui.printDivider(line); + endTime = LocalDateTime.now(); + Activity newActivity = new Activity(tokenizedInputs[1], startTime, endTime, tags); + activityList.add(newActivity); + } + } } diff --git a/src/test/java/jikan/activity/ActivityTest.java b/src/test/java/jikan/activity/ActivityTest.java index a1b67fb6c..b560d9905 100644 --- a/src/test/java/jikan/activity/ActivityTest.java +++ b/src/test/java/jikan/activity/ActivityTest.java @@ -1,6 +1,5 @@ package jikan.activity; -import jikan.activity.Activity; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; diff --git a/src/test/java/jikan/parser/ParserTest.java b/src/test/java/jikan/parser/ParserTest.java new file mode 100644 index 000000000..813a16977 --- /dev/null +++ b/src/test/java/jikan/parser/ParserTest.java @@ -0,0 +1,28 @@ +package jikan.parser; + +import jikan.activity.ActivityList; +import jikan.storage.Storage; +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; + +import static org.junit.jupiter.api.Assertions.*; + +class ParserTest { + + Parser parser = new Parser(); + + ActivityList activityList = new ActivityList(); + + @Test + void parseEnd() { + parser.startTime = null; + parser.parseEnd(activityList); + assertTrue(activityList.activities.isEmpty()); + parser.tokenizedInputs = new String[]{"start", "studying"}; + parser.startTime = LocalDateTime.parse("2020-01-01T08:00:00"); + activityList.storage = new Storage("data/Parser_test.txt"); + parser.parseEnd(activityList); + assertFalse(activityList.activities.isEmpty()); + } +} \ No newline at end of file From 24570dafd2a98c36d6dc94ff9ea48151c9a14330 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 10 Mar 2020 23:59:35 +0800 Subject: [PATCH 033/415] Fix some style issues --- src/test/java/jikan/parser/ParserTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/jikan/parser/ParserTest.java b/src/test/java/jikan/parser/ParserTest.java index 813a16977..35f0aa17d 100644 --- a/src/test/java/jikan/parser/ParserTest.java +++ b/src/test/java/jikan/parser/ParserTest.java @@ -6,7 +6,8 @@ import java.time.LocalDateTime; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; class ParserTest { From 4319bf0a0e150758baa4540dcd083c034413ea36 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Wed, 11 Mar 2020 00:30:19 +0800 Subject: [PATCH 034/415] Move Ui class into a package --- src/main/java/jikan/Jikan.java | 1 + src/main/java/jikan/parser/Parser.java | 2 +- src/main/java/jikan/{ => ui}/Ui.java | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) rename src/main/java/jikan/{ => ui}/Ui.java (99%) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 88f09504b..6f4659d73 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -3,6 +3,7 @@ import jikan.activity.ActivityList; import jikan.parser.Parser; import jikan.storage.Storage; +import jikan.ui.Ui; import java.io.IOException; import java.util.Scanner; diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 67f31d1e7..368acb8c4 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,8 +1,8 @@ package jikan.parser; -import jikan.Ui; import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.ui.Ui; import java.time.LocalDateTime; import java.util.Arrays; diff --git a/src/main/java/jikan/Ui.java b/src/main/java/jikan/ui/Ui.java similarity index 99% rename from src/main/java/jikan/Ui.java rename to src/main/java/jikan/ui/Ui.java index 5688ae4b5..eb12dddf1 100644 --- a/src/main/java/jikan/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -1,4 +1,4 @@ -package jikan; +package jikan.ui; import jikan.activity.ActivityList; import java.util.Arrays; From 2a6fef173818114ada1d9dbb9b775a0a25b8859b Mon Sep 17 00:00:00 2001 From: btricec Date: Wed, 11 Mar 2020 10:14:29 +0800 Subject: [PATCH 035/415] Add tag delimiter --- src/main/java/jikan/parser/Parser.java | 14 +++++++++----- src/main/java/jikan/ui/Ui.java | 6 +++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 368acb8c4..86a4342f6 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -28,7 +28,7 @@ public class Parser { public void parseUserCommands(Scanner scanner, ActivityList activityList) { while (true) { String userInput = scanner.nextLine(); - tokenizedInputs = userInput.split(" "); + tokenizedInputs = userInput.split(" ", 2); instruction = tokenizedInputs[0]; switch (instruction) { @@ -69,12 +69,16 @@ private void parseAbort() { /** Method to parse the start activity command. */ public void parseStart() { - String line = "Started " + tokenizedInputs[1]; - ui.printDivider(line); - if (tokenizedInputs.length > 2) { - tags = Arrays.copyOfRange(tokenizedInputs, 2, tokenizedInputs.length); + String line; + int delimiter = tokenizedInputs[1].indexOf("/t"); + if (delimiter == -1) { + line = "Started " + tokenizedInputs[1]; + } else { + line = "Started " + tokenizedInputs[1].substring(0, delimiter); + tags = tokenizedInputs[1].substring(delimiter + 3).split(" "); } startTime = LocalDateTime.now(); + ui.printDivider(line); } /** Method to parse the end activity command. */ diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index eb12dddf1..d12adb803 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -53,7 +53,11 @@ public void printList(ActivityList activityList) { - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(durationInNanos))); System.out.print(i + 1 + ". " + activityList.get(i).name + " " + duration); if (activityList.get(i).tags != null) { - System.out.println(" " + Arrays.toString(activityList.get(i).tags)); + if (!activityList.get(i).tags[0].equals("null")) { + System.out.println(" " + Arrays.toString(activityList.get(i).tags)); + } else { + System.out.println(); + } } else { System.out.print("\n"); } From 0e5611729a04f63a5906b47c44683071c9b4a465 Mon Sep 17 00:00:00 2001 From: btricec Date: Wed, 11 Mar 2020 11:07:38 +0800 Subject: [PATCH 036/415] Add error handling --- src/main/java/jikan/activity/Activity.java | 18 +++----- .../java/jikan/activity/ActivityList.java | 29 ++++++------ src/main/java/jikan/parser/Parser.java | 45 +++++++++++++------ src/main/java/jikan/ui/Ui.java | 10 ++--- 4 files changed, 59 insertions(+), 43 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 7d5529845..7c95dc455 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -9,17 +9,11 @@ */ public class Activity { - public String name; - public String[] tags; - public LocalDateTime startTime; - public LocalDateTime endTime; - public Duration duration; - - /* - protected String name; - protected String startTime; - protected String endTime; - */ + private String name; + private String[] tags; + private LocalDateTime startTime; + private LocalDateTime endTime; + private Duration duration; /** * Constructor for a new activity entry. @@ -29,7 +23,7 @@ public class Activity { * @param endTime the time that the activity ended */ public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, String[] tags) { - this.name = name; + this.name = name.strip(); this.startTime = startTime; this.tags = tags; this.endTime = endTime; diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 81b68a83e..7aef26f12 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -97,19 +97,22 @@ private void populateTaskList(File dataFile) { */ private void parseDataLine(String s) { - List strings = Arrays.asList(s.split(",")); - String[] tags; - - // if there are tags - if (strings.size() > 3) { - tags = strings.get(3).split(" "); - } else { - tags = null; - } + if (!s.isEmpty()) { + List strings = Arrays.asList(s.split(",")); + String[] tags; + + // if there are tags + if (!strings.get(3).equals("null")) { + // remove square brackets surrounding tags + tags = strings.get(3).substring(1,strings.get(3).length() - 1).split(" "); + } else { + tags = null; + } - // strings[0] = name, strings[1] = startDate, string[2] = endDate - Activity e = new Activity(strings.get(0), LocalDateTime.parse(strings.get(1)), - LocalDateTime.parse(strings.get(2)), tags); - activities.add(e); + // strings[0] = name, strings[1] = startDate, string[2] = endDate + Activity e = new Activity(strings.get(0), LocalDateTime.parse(strings.get(1)), + LocalDateTime.parse(strings.get(2)), tags); + activities.add(e); + } } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 86a4342f6..cc1eea913 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -15,6 +15,7 @@ public class Parser { protected LocalDateTime startTime = null; protected LocalDateTime endTime = null; + private String activityName = null; private String[] tags = null; private Ui ui = new Ui(); protected String[] tokenizedInputs; @@ -62,23 +63,40 @@ private void parseDefault() { /** Method to parse the abort command. */ private void parseAbort() { - startTime = null; - String line = "You have aborted the current activity!"; - ui.printDivider(line); + if (startTime == null) { + String line = "You have not started any activity!"; + ui.printDivider(line); + } else { + startTime = null; + tags = null; + activityName = null; + String line = "You have aborted the current activity!"; + ui.printDivider(line); + } + } /** Method to parse the start activity command. */ public void parseStart() { - String line; - int delimiter = tokenizedInputs[1].indexOf("/t"); - if (delimiter == -1) { - line = "Started " + tokenizedInputs[1]; + // check if an activity has already been started + if (startTime != null) { + String line = activityName + " is ongoing!"; + ui.printDivider(line); } else { - line = "Started " + tokenizedInputs[1].substring(0, delimiter); - tags = tokenizedInputs[1].substring(delimiter + 3).split(" "); + String line; + int delimiter = tokenizedInputs[1].indexOf("/t"); + if (delimiter == -1) { + activityName = tokenizedInputs[1]; + line = "Started " + activityName; + } else { + activityName = tokenizedInputs[1].substring(0, delimiter); + line = "Started " + activityName; + tags = tokenizedInputs[1].substring(delimiter + 3).split(" "); + } + startTime = LocalDateTime.now(); + ui.printDivider(line); } - startTime = LocalDateTime.now(); - ui.printDivider(line); + } /** Method to parse the end activity command. */ @@ -87,11 +105,12 @@ public void parseEnd(ActivityList activityList) { String line = "You have not started any activity!"; ui.printDivider(line); } else { - String line = "Ended " + tokenizedInputs[1]; + String line = "Ended " + activityName; ui.printDivider(line); endTime = LocalDateTime.now(); - Activity newActivity = new Activity(tokenizedInputs[1], startTime, endTime, tags); + Activity newActivity = new Activity(activityName, startTime, endTime, tags); activityList.add(newActivity); + startTime = null; } } } diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index d12adb803..14f38db13 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -44,17 +44,17 @@ public void printList(ActivityList activityList) { System.out.println(DIVIDER); System.out.println("Your completed activities:"); for (int i = 0; i < activityList.getSize(); i++) { - long durationInNanos = (activityList.get(i).duration).toNanos(); + long durationInNanos = (activityList.get(i).getDuration()).toNanos(); String duration = String.format("%02d:%02d:%02d", TimeUnit.NANOSECONDS.toHours(durationInNanos), TimeUnit.NANOSECONDS.toMinutes(durationInNanos) - TimeUnit.HOURS.toMinutes(TimeUnit.NANOSECONDS.toHours(durationInNanos)), TimeUnit.NANOSECONDS.toSeconds(durationInNanos) - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(durationInNanos))); - System.out.print(i + 1 + ". " + activityList.get(i).name + " " + duration); - if (activityList.get(i).tags != null) { - if (!activityList.get(i).tags[0].equals("null")) { - System.out.println(" " + Arrays.toString(activityList.get(i).tags)); + System.out.print(i + 1 + ". " + activityList.get(i).getName() + " " + duration); + if (activityList.get(i).getTags() != null) { + if (!activityList.get(i).getTags()[0].equals("null")) { + System.out.println(" " + Arrays.toString(activityList.get(i).getTags())); } else { System.out.println(); } From 7f6aecd7c572eae4510c354bef0b6d3b6a989808 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Wed, 11 Mar 2020 12:25:15 +0800 Subject: [PATCH 037/415] Add exception handling for start command --- src/main/java/jikan/EmptyNameException.java | 4 ++++ src/main/java/jikan/Jikan.java | 1 + src/main/java/jikan/parser/Parser.java | 21 ++++++++++++++++++--- 3 files changed, 23 insertions(+), 3 deletions(-) create mode 100644 src/main/java/jikan/EmptyNameException.java diff --git a/src/main/java/jikan/EmptyNameException.java b/src/main/java/jikan/EmptyNameException.java new file mode 100644 index 000000000..15780eb4b --- /dev/null +++ b/src/main/java/jikan/EmptyNameException.java @@ -0,0 +1,4 @@ +package jikan; + +public class EmptyNameException extends Exception { +} diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 6f4659d73..0a5414e5e 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -42,6 +42,7 @@ public static void createActivityList() { System.out.println("Error loading/creating data file."); } } + /** * Main entry-point for the Jikan application. diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index cc1eea913..6dc7569c4 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,11 +1,14 @@ package jikan.parser; +import jikan.EmptyNameException; import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.ui.Ui; +import java.lang.reflect.Array; import java.time.LocalDateTime; import java.util.Arrays; +import java.util.NoSuchElementException; import java.util.Scanner; /** @@ -37,7 +40,13 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { ui.exitFromApp(); break; case "start": - parseStart(); + try { + parseStart(); + } catch (EmptyNameException e) { + ui.printDivider("Task name cannot be empty!"); + } catch (ArrayIndexOutOfBoundsException e) { + ui.printDivider("Task name cannot be empty!"); + } break; case "end": parseEnd(activityList); @@ -77,7 +86,7 @@ private void parseAbort() { } /** Method to parse the start activity command. */ - public void parseStart() { + public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameException { // check if an activity has already been started if (startTime != null) { String line = activityName + " is ongoing!"; @@ -87,9 +96,15 @@ public void parseStart() { int delimiter = tokenizedInputs[1].indexOf("/t"); if (delimiter == -1) { activityName = tokenizedInputs[1]; + if (activityName.equals("")) { + throw new EmptyNameException(); + } line = "Started " + activityName; } else { activityName = tokenizedInputs[1].substring(0, delimiter); + if (activityName.equals("")) { + throw new EmptyNameException(); + } line = "Started " + activityName; tags = tokenizedInputs[1].substring(delimiter + 3).split(" "); } @@ -100,7 +115,7 @@ public void parseStart() { } /** Method to parse the end activity command. */ - public void parseEnd(ActivityList activityList) { + public void parseEnd(ActivityList activityList) throws ArrayIndexOutOfBoundsException { if (startTime == null) { String line = "You have not started any activity!"; ui.printDivider(line); From 06588c6fdcd858f772f63fc73092d07dc2a5aa8e Mon Sep 17 00:00:00 2001 From: btricec Date: Wed, 11 Mar 2020 21:52:02 +0800 Subject: [PATCH 038/415] Put list into table format --- src/main/java/jikan/activity/Activity.java | 7 ++++ .../java/jikan/activity/ActivityList.java | 15 ++++++-- src/main/java/jikan/parser/Parser.java | 12 +++--- src/main/java/jikan/ui/Ui.java | 38 +++++++++++-------- 4 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 7c95dc455..49f570322 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -1,6 +1,7 @@ package jikan.activity; import java.time.Duration; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Arrays; @@ -14,6 +15,7 @@ public class Activity { private LocalDateTime startTime; private LocalDateTime endTime; private Duration duration; + private LocalDate date; /** * Constructor for a new activity entry. @@ -28,6 +30,7 @@ public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Str this.tags = tags; this.endTime = endTime; this.duration = Duration.between(startTime, endTime); + this.date = endTime.toLocalDate(); } /** @@ -66,6 +69,10 @@ public String[] getTags() { return tags; } + public LocalDate getDate() { + return date; + } + /** * Converts the jikan.activity.Activity object to data representation to be stored in a data file. * File format: diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 7aef26f12..f6eb27b4d 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -99,12 +99,21 @@ private void parseDataLine(String s) { if (!s.isEmpty()) { List strings = Arrays.asList(s.split(",")); - String[] tags; + String[] tags = new String[strings.size() - 3]; // if there are tags if (!strings.get(3).equals("null")) { - // remove square brackets surrounding tags - tags = strings.get(3).substring(1,strings.get(3).length() - 1).split(" "); + int tagsIndex = 0; + for (int i = 3; i < strings.size(); i++) { + if (i == 3) { + tags[tagsIndex] = strings.get(i).substring(1); + } else if (i == strings.size() - 1) { + tags[tagsIndex] = strings.get(i).substring(0, strings.get(i).length() - 1); + } else { + tags[tagsIndex] = strings.get(i); + } + tagsIndex++; + } } else { tags = null; } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 6dc7569c4..242396c9a 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -42,10 +42,8 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { case "start": try { parseStart(); - } catch (EmptyNameException e) { - ui.printDivider("Task name cannot be empty!"); - } catch (ArrayIndexOutOfBoundsException e) { - ui.printDivider("Task name cannot be empty!"); + } catch (EmptyNameException | ArrayIndexOutOfBoundsException e) { + ui.printDivider("Activity name cannot be empty!"); } break; case "end": @@ -99,13 +97,13 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti if (activityName.equals("")) { throw new EmptyNameException(); } - line = "Started " + activityName; + line = "Started: " + activityName; } else { activityName = tokenizedInputs[1].substring(0, delimiter); if (activityName.equals("")) { throw new EmptyNameException(); } - line = "Started " + activityName; + line = "Started: " + activityName; tags = tokenizedInputs[1].substring(delimiter + 3).split(" "); } startTime = LocalDateTime.now(); @@ -120,7 +118,7 @@ public void parseEnd(ActivityList activityList) throws ArrayIndexOutOfBoundsExce String line = "You have not started any activity!"; ui.printDivider(line); } else { - String line = "Ended " + activityName; + String line = "Ended: " + activityName; ui.printDivider(line); endTime = LocalDateTime.now(); Activity newActivity = new Activity(activityName, startTime, endTime, tags); diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 14f38db13..f28a428a1 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -39,27 +39,35 @@ public void printDivider(String line) { System.out.println(DIVIDER); } + private void printTableFormat(ActivityList activityList, int index, boolean gotTags) { + long durationInNanos = (activityList.get(index).getDuration()).toNanos(); + String duration = String.format("%02d:%02d:%02d", + TimeUnit.NANOSECONDS.toHours(durationInNanos), + TimeUnit.NANOSECONDS.toMinutes(durationInNanos) + - TimeUnit.HOURS.toMinutes(TimeUnit.NANOSECONDS.toHours(durationInNanos)), + TimeUnit.NANOSECONDS.toSeconds(durationInNanos) + - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(durationInNanos))); + if (gotTags) { + System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %-100s", index + 1, "|", + activityList.get(index).getName(), "|", duration, "|", activityList.get(index).getDate().toString(), "|", + Arrays.toString(activityList.get(index).getTags()))); + } else { + System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %s", index + 1, "|", + activityList.get(index).getName(), "|", duration, "|", activityList.get(index).getDate().toString(), "|", "")); + } + } + /** Prints all the activities in the list. */ public void printList(ActivityList activityList) { System.out.println(DIVIDER); System.out.println("Your completed activities:"); + System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", "|", "Name", "|", + "Duration", "|", "Date", "|", "Tags")); for (int i = 0; i < activityList.getSize(); i++) { - long durationInNanos = (activityList.get(i).getDuration()).toNanos(); - String duration = String.format("%02d:%02d:%02d", - TimeUnit.NANOSECONDS.toHours(durationInNanos), - TimeUnit.NANOSECONDS.toMinutes(durationInNanos) - - TimeUnit.HOURS.toMinutes(TimeUnit.NANOSECONDS.toHours(durationInNanos)), - TimeUnit.NANOSECONDS.toSeconds(durationInNanos) - - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(durationInNanos))); - System.out.print(i + 1 + ". " + activityList.get(i).getName() + " " + duration); - if (activityList.get(i).getTags() != null) { - if (!activityList.get(i).getTags()[0].equals("null")) { - System.out.println(" " + Arrays.toString(activityList.get(i).getTags())); - } else { - System.out.println(); - } + if (activityList.get(i).getTags() != null && !activityList.get(i).getTags()[0].equals("null")) { + printTableFormat(activityList, i, true); } else { - System.out.print("\n"); + printTableFormat(activityList, i, false); } } System.out.println(DIVIDER); From 5d8dc2fff8631c4f2aed0b574140e0aa2a563520 Mon Sep 17 00:00:00 2001 From: btricec Date: Wed, 11 Mar 2020 22:26:44 +0800 Subject: [PATCH 039/415] Fix style --- src/main/java/jikan/ui/Ui.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index f28a428a1..d58ae833f 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -48,12 +48,14 @@ private void printTableFormat(ActivityList activityList, int index, boolean gotT TimeUnit.NANOSECONDS.toSeconds(durationInNanos) - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(durationInNanos))); if (gotTags) { - System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %-100s", index + 1, "|", - activityList.get(index).getName(), "|", duration, "|", activityList.get(index).getDate().toString(), "|", + System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %-100s", + index + 1, "|", activityList.get(index).getName(), "|", duration, "|", + activityList.get(index).getDate().toString(), "|", Arrays.toString(activityList.get(index).getTags()))); } else { - System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %s", index + 1, "|", - activityList.get(index).getName(), "|", duration, "|", activityList.get(index).getDate().toString(), "|", "")); + System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %s", + index + 1, "|", activityList.get(index).getName(), "|", duration, "|", + activityList.get(index).getDate().toString(), "|", "")); } } @@ -61,8 +63,8 @@ private void printTableFormat(ActivityList activityList, int index, boolean gotT public void printList(ActivityList activityList) { System.out.println(DIVIDER); System.out.println("Your completed activities:"); - System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", "|", "Name", "|", - "Duration", "|", "Date", "|", "Tags")); + System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", + "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); for (int i = 0; i < activityList.getSize(); i++) { if (activityList.get(i).getTags() != null && !activityList.get(i).getTags()[0].equals("null")) { printTableFormat(activityList, i, true); From a8f8a1a32d22bc9b928d7a8e18aa3b1e8f56b653 Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 16 Mar 2020 13:05:15 +0800 Subject: [PATCH 040/415] Add delete command --- .../java/jikan/activity/ActivityList.java | 14 ++++++++++ src/main/java/jikan/parser/Parser.java | 10 +++++++ .../java/jikan/storage/StorageHandler.java | 28 +++++++++++++++++-- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index f6eb27b4d..291d429a9 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -1,6 +1,7 @@ package jikan.activity; import jikan.storage.Storage; +import jikan.storage.StorageHandler; import java.io.IOException; import java.time.LocalDateTime; @@ -69,6 +70,19 @@ private void updateFile(String dataLine) { } } + public void delete(int index) { + activities.remove(index); + deleteUpdateFile(index); + } + + private void deleteUpdateFile(int index) { + try { + StorageHandler.removeLine(index, storage); + } catch (IOException e) { + System.out.println("Error while deleting task from data file."); + } + } + public int getSize() { return activities.size(); } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 242396c9a..456ab012f 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -55,6 +55,9 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { case "abort": parseAbort(); break; + case "delete": + parseDelete(activityList); + break; default: parseDefault(); break; @@ -126,4 +129,11 @@ public void parseEnd(ActivityList activityList) throws ArrayIndexOutOfBoundsExce startTime = null; } } + + public void parseDelete(ActivityList activityList) { + int index = Integer.parseInt(tokenizedInputs[1]) - 1; + String line = "You have deleted " + activityList.get(index).getName(); + ui.printDivider(line); + activityList.delete(index); + } } diff --git a/src/main/java/jikan/storage/StorageHandler.java b/src/main/java/jikan/storage/StorageHandler.java index 093ccd965..f54ea09cd 100644 --- a/src/main/java/jikan/storage/StorageHandler.java +++ b/src/main/java/jikan/storage/StorageHandler.java @@ -1,6 +1,9 @@ package jikan.storage; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.PrintWriter; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Paths; @@ -20,11 +23,17 @@ public class StorageHandler { * @param dataFilePath Path to data file. * @throws IOException If an error occurs while writing the new list to file. */ - public static void removeLine(int lineNumber, String dataFilePath) throws IOException { + public static void removeLine(int lineNumber, Storage storage) throws IOException { // Read file into list of strings, where each string is a line in the file - List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(dataFilePath), StandardCharsets.UTF_8)); - int removedIndex = 0; + List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(storage.dataFilePath), StandardCharsets.UTF_8)); + + //int removedIndex = 0; + + fileContent.remove(lineNumber); + saveNewList(fileContent, storage.dataFile); + + /* // Remove line from fileContent list removedIndex = removeLineFromList(lineNumber, fileContent, removedIndex); @@ -33,6 +42,19 @@ public static void removeLine(int lineNumber, String dataFilePath) throws IOExce // Update indexes of subsequent lines updateIndexes(fileContent, removedIndex, dataFilePath); + + */ + } + + public static void saveNewList(List newList, File dataFile) throws IOException { + FileOutputStream fo = new FileOutputStream(dataFile); + PrintWriter pw = new PrintWriter(fo); + + for (int i = 0; i < newList.size(); i++) { + pw.println(newList.get(i)); + } + pw.close(); + fo.close(); } /** From 0e0a376c0e904dd41c36dbd87dd53e9e44ebc99a Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 16 Mar 2020 14:25:55 +0800 Subject: [PATCH 041/415] Add log --- src/main/java/jikan/Log.java | 40 ++++++++++++++++++++++++++ src/main/java/jikan/parser/Parser.java | 8 +++++- 2 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 src/main/java/jikan/Log.java diff --git a/src/main/java/jikan/Log.java b/src/main/java/jikan/Log.java new file mode 100644 index 000000000..ab361c8ad --- /dev/null +++ b/src/main/java/jikan/Log.java @@ -0,0 +1,40 @@ +package jikan; + +import java.util.logging.*; + +public class Log { + private static Logger logger; + static private SimpleFormatter formatterTxt; + + public Log() { + logger = Logger.getLogger(Log.class.getName()); + LogManager.getLogManager().reset(); + logger.setLevel(Level.ALL); + + ConsoleHandler consoleHandler = new ConsoleHandler(); + consoleHandler.setLevel(Level.WARNING); + logger.addHandler(consoleHandler); + + try { + FileHandler fileHandler = new FileHandler("data/LogRecord.txt"); + formatterTxt = new SimpleFormatter(); + fileHandler.setFormatter(formatterTxt); + fileHandler.setLevel(Level.INFO); + logger.addHandler(fileHandler); + } catch (java.io.IOException e){ + logger.log(Level.SEVERE, "File logger not working", e); + } + } + + public void makeInfoLog(String message) { + logger.log(Level.INFO, message); + } + + public void makeWarningLog(String message) { + logger.log(Level.WARNING, message); + } + + public void makeSevereLog(String message) { + logger.log(Level.SEVERE, message); + } +} diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 6dc7569c4..c924ef60d 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -4,6 +4,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.ui.Ui; +import jikan.Log; import java.lang.reflect.Array; import java.time.LocalDateTime; @@ -24,12 +25,15 @@ public class Parser { protected String[] tokenizedInputs; String instruction; + Log logger = new Log(); + /** * Parses user commands to relevant functions to carry out the commands. * @param scanner scanner object which reads user input * @param activityList the list of activities */ public void parseUserCommands(Scanner scanner, ActivityList activityList) { + logger.makeInfoLog("Starting to parse inputs."); while (true) { String userInput = scanner.nextLine(); tokenizedInputs = userInput.split(" ", 2); @@ -90,6 +94,7 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti // check if an activity has already been started if (startTime != null) { String line = activityName + " is ongoing!"; + logger.makeWarningLog("Could not start activity due to ongoing activity."); ui.printDivider(line); } else { String line; @@ -111,7 +116,7 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti startTime = LocalDateTime.now(); ui.printDivider(line); } - + logger.makeInfoLog("Started: " + activityName); } /** Method to parse the end activity command. */ @@ -127,5 +132,6 @@ public void parseEnd(ActivityList activityList) throws ArrayIndexOutOfBoundsExce activityList.add(newActivity); startTime = null; } + logger.makeInfoLog("Ended: " + activityName); } } From 9e974a02799ee20b863ddb2a969b704e666c83ca Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 16 Mar 2020 14:35:36 +0800 Subject: [PATCH 042/415] Add assertion to check if tags is null when activity is started --- src/main/java/jikan/parser/Parser.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index c924ef60d..0a13d8413 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -97,6 +97,9 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti logger.makeWarningLog("Could not start activity due to ongoing activity."); ui.printDivider(line); } else { + // tags should be reset + assert tags == null; + String line; int delimiter = tokenizedInputs[1].indexOf("/t"); if (delimiter == -1) { @@ -130,7 +133,9 @@ public void parseEnd(ActivityList activityList) throws ArrayIndexOutOfBoundsExce endTime = LocalDateTime.now(); Activity newActivity = new Activity(activityName, startTime, endTime, tags); activityList.add(newActivity); + // reset activity info startTime = null; + tags = null; } logger.makeInfoLog("Ended: " + activityName); } From fcf112776a5b5c93c9b8db0a5207596ca4132a64 Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 16 Mar 2020 14:40:51 +0800 Subject: [PATCH 043/415] Fix style error --- src/main/java/jikan/Log.java | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/main/java/jikan/Log.java b/src/main/java/jikan/Log.java index ab361c8ad..8ddb97a5f 100644 --- a/src/main/java/jikan/Log.java +++ b/src/main/java/jikan/Log.java @@ -1,11 +1,20 @@ package jikan; -import java.util.logging.*; +import java.util.logging.Level; +import java.util.logging.LogManager; +import java.util.logging.Logger; +import java.util.logging.SimpleFormatter; +import java.util.logging.ConsoleHandler; +import java.util.logging.FileHandler; + public class Log { private static Logger logger; - static private SimpleFormatter formatterTxt; + private static SimpleFormatter formatterTxt; + /** + * Constructor for a new logger. + */ public Log() { logger = Logger.getLogger(Log.class.getName()); LogManager.getLogManager().reset(); @@ -21,7 +30,7 @@ public Log() { fileHandler.setFormatter(formatterTxt); fileHandler.setLevel(Level.INFO); logger.addHandler(fileHandler); - } catch (java.io.IOException e){ + } catch (java.io.IOException e) { logger.log(Level.SEVERE, "File logger not working", e); } } From 070fc9ee74f04c5ecb9e0a6f513aa5a03df076b2 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 16 Mar 2020 15:37:16 +0800 Subject: [PATCH 044/415] Add Junit test for add exception --- src/main/java/jikan/EmptyNameException.java | 4 --- .../jikan/exception/EmptyNameException.java | 7 +++++ src/main/java/jikan/parser/Parser.java | 11 ++++---- src/test/java/jikan/parser/ExceptionTest.java | 28 +++++++++++++++++++ 4 files changed, 40 insertions(+), 10 deletions(-) delete mode 100644 src/main/java/jikan/EmptyNameException.java create mode 100644 src/main/java/jikan/exception/EmptyNameException.java create mode 100644 src/test/java/jikan/parser/ExceptionTest.java diff --git a/src/main/java/jikan/EmptyNameException.java b/src/main/java/jikan/EmptyNameException.java deleted file mode 100644 index 15780eb4b..000000000 --- a/src/main/java/jikan/EmptyNameException.java +++ /dev/null @@ -1,4 +0,0 @@ -package jikan; - -public class EmptyNameException extends Exception { -} diff --git a/src/main/java/jikan/exception/EmptyNameException.java b/src/main/java/jikan/exception/EmptyNameException.java new file mode 100644 index 000000000..12930d399 --- /dev/null +++ b/src/main/java/jikan/exception/EmptyNameException.java @@ -0,0 +1,7 @@ +package jikan.exception; + +/** + * An exception that is thrown when the task name field is empty + */ +public class EmptyNameException extends Exception { +} diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 6dc7569c4..dd71a6755 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,14 +1,11 @@ package jikan.parser; -import jikan.EmptyNameException; +import jikan.exception.EmptyNameException; import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.ui.Ui; -import java.lang.reflect.Array; import java.time.LocalDateTime; -import java.util.Arrays; -import java.util.NoSuchElementException; import java.util.Scanner; /** @@ -46,6 +43,8 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { ui.printDivider("Task name cannot be empty!"); } catch (ArrayIndexOutOfBoundsException e) { ui.printDivider("Task name cannot be empty!"); + } catch (NullPointerException e) { + ui.printDivider("Task name cannot be empty!"); } break; case "end": @@ -86,7 +85,7 @@ private void parseAbort() { } /** Method to parse the start activity command. */ - public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameException { + public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameException, NullPointerException { // check if an activity has already been started if (startTime != null) { String line = activityName + " is ongoing!"; @@ -115,7 +114,7 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti } /** Method to parse the end activity command. */ - public void parseEnd(ActivityList activityList) throws ArrayIndexOutOfBoundsException { + public void parseEnd(ActivityList activityList) { if (startTime == null) { String line = "You have not started any activity!"; ui.printDivider(line); diff --git a/src/test/java/jikan/parser/ExceptionTest.java b/src/test/java/jikan/parser/ExceptionTest.java new file mode 100644 index 000000000..eea8f4adf --- /dev/null +++ b/src/test/java/jikan/parser/ExceptionTest.java @@ -0,0 +1,28 @@ +package jikan.parser; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; +import jikan.parser.Parser; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.time.LocalDateTime; + +class ExceptionTest { + + Parser parser = new Parser(); + + @Test + public void testEmptyNameException() { + Assertions.assertThrows(EmptyNameException.class, () -> { + parser.tokenizedInputs = new String[]{"start", ""}; + parser.parseStart(); + }); + } + +} + + From 958a2b0672e28fbb8c2b78c5d385fb1282f6d7a5 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 16 Mar 2020 16:09:29 +0800 Subject: [PATCH 045/415] Add stop/abort exception and junit test --- .../jikan/exception/EmptyNameException.java | 2 +- .../exception/NoSuchActivityException.java | 7 +++++ src/main/java/jikan/parser/Parser.java | 23 ++++++++++------ src/test/java/jikan/parser/ExceptionTest.java | 19 ++++++++----- src/test/java/jikan/parser/ParserTest.java | 27 ++++++++++++------- 5 files changed, 53 insertions(+), 25 deletions(-) create mode 100644 src/main/java/jikan/exception/NoSuchActivityException.java diff --git a/src/main/java/jikan/exception/EmptyNameException.java b/src/main/java/jikan/exception/EmptyNameException.java index 12930d399..9e380e6e9 100644 --- a/src/main/java/jikan/exception/EmptyNameException.java +++ b/src/main/java/jikan/exception/EmptyNameException.java @@ -1,7 +1,7 @@ package jikan.exception; /** - * An exception that is thrown when the task name field is empty + * An exception that is thrown when the task name field is empty. */ public class EmptyNameException extends Exception { } diff --git a/src/main/java/jikan/exception/NoSuchActivityException.java b/src/main/java/jikan/exception/NoSuchActivityException.java new file mode 100644 index 000000000..90f080c70 --- /dev/null +++ b/src/main/java/jikan/exception/NoSuchActivityException.java @@ -0,0 +1,7 @@ +package jikan.exception; + +/** + * An exception that is thrown when the task name is unknown. + */ +public class NoSuchActivityException extends Exception { +} diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 554a4bdd2..c8dc543e1 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -3,6 +3,7 @@ import jikan.exception.EmptyNameException; import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.NoSuchActivityException; import jikan.ui.Ui; import jikan.Log; @@ -52,13 +53,21 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { } break; case "end": - parseEnd(activityList); + try { + parseEnd(activityList); + } catch (NoSuchActivityException e) { + ui.printDivider("There is no such task!"); + } break; case "list": ui.printList(activityList); break; case "abort": - parseAbort(); + try { + parseAbort(); + } catch (NoSuchActivityException e) { + ui.printDivider("There is no such task!"); + } break; default: parseDefault(); @@ -74,10 +83,9 @@ private void parseDefault() { } /** Method to parse the abort command. */ - private void parseAbort() { + public void parseAbort() throws NoSuchActivityException { if (startTime == null) { - String line = "You have not started any activity!"; - ui.printDivider(line); + throw new NoSuchActivityException(); } else { startTime = null; tags = null; @@ -122,10 +130,9 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti } /** Method to parse the end activity command. */ - public void parseEnd(ActivityList activityList) { + public void parseEnd(ActivityList activityList) throws NoSuchActivityException { if (startTime == null) { - String line = "You have not started any activity!"; - ui.printDivider(line); + throw new NoSuchActivityException(); } else { String line = "Ended " + activityName; ui.printDivider(line); diff --git a/src/test/java/jikan/parser/ExceptionTest.java b/src/test/java/jikan/parser/ExceptionTest.java index eea8f4adf..ebdbefd22 100644 --- a/src/test/java/jikan/parser/ExceptionTest.java +++ b/src/test/java/jikan/parser/ExceptionTest.java @@ -1,19 +1,15 @@ package jikan.parser; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.fail; - import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; -import jikan.parser.Parser; +import jikan.exception.NoSuchActivityException; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import java.time.LocalDateTime; - class ExceptionTest { Parser parser = new Parser(); + ActivityList activityList = new ActivityList(); @Test public void testEmptyNameException() { @@ -23,6 +19,17 @@ public void testEmptyNameException() { }); } + @Test + public void testNoSuchActivityException() { + Assertions.assertThrows(NoSuchActivityException.class, () -> { + parser.startTime = null; + parser.parseEnd(activityList); + parser.parseAbort(); + }); + + } + + } diff --git a/src/test/java/jikan/parser/ParserTest.java b/src/test/java/jikan/parser/ParserTest.java index 35f0aa17d..f7669d7b5 100644 --- a/src/test/java/jikan/parser/ParserTest.java +++ b/src/test/java/jikan/parser/ParserTest.java @@ -1,6 +1,8 @@ package jikan.parser; import jikan.activity.ActivityList; +import jikan.ui.Ui; +import jikan.exception.NoSuchActivityException; import jikan.storage.Storage; import org.junit.jupiter.api.Test; @@ -12,18 +14,23 @@ class ParserTest { Parser parser = new Parser(); - + Ui ui = new Ui(); ActivityList activityList = new ActivityList(); @Test - void parseEnd() { - parser.startTime = null; - parser.parseEnd(activityList); - assertTrue(activityList.activities.isEmpty()); - parser.tokenizedInputs = new String[]{"start", "studying"}; - parser.startTime = LocalDateTime.parse("2020-01-01T08:00:00"); - activityList.storage = new Storage("data/Parser_test.txt"); - parser.parseEnd(activityList); - assertFalse(activityList.activities.isEmpty()); + void parseEnd() throws NoSuchActivityException { + try { + parser.startTime = null; + parser.parseEnd(activityList); + assertTrue(activityList.activities.isEmpty()); + parser.tokenizedInputs = new String[]{"start", "studying"}; + parser.startTime = LocalDateTime.parse("2020-01-01T08:00:00"); + activityList.storage = new Storage("data/Parser_test.txt"); + parser.parseEnd(activityList); + assertFalse(activityList.activities.isEmpty()); + } catch (NoSuchActivityException e) { + ui.printDivider("There is no such task!"); + } + } } \ No newline at end of file From 3683d98ff69bb147cf7cd0409ce296954f733c6d Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Mon, 16 Mar 2020 16:18:57 +0800 Subject: [PATCH 046/415] Adding logging for successful commands as well as errors. Added some minor assertions, checking if startTime and activityName has been reset after end and abort commands. --- src/main/java/jikan/Jikan.java | 5 ++++- src/main/java/jikan/Log.java | 16 +++++++++++++++- src/main/java/jikan/parser/Parser.java | 14 +++++++++++++- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 0a5414e5e..ab4e6dd54 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -24,7 +24,10 @@ public class Jikan { /** Ui to handle printing. */ private static Ui ui = new Ui(); + /** Parser to parse commands*/ private static Parser parser = new Parser(); + + private static Log logger = new Log(); /** * Creates ActivityList and loads data from data file if the data file previously existed; @@ -52,6 +55,6 @@ public static void main(String[] args) { Scanner in = new Scanner(System.in); storage = new Storage(DATA_FILE_PATH); createActivityList(); - parser.parseUserCommands(in, activityList); + parser.parseUserCommands(in, activityList, logger); } } diff --git a/src/main/java/jikan/Log.java b/src/main/java/jikan/Log.java index 8ddb97a5f..dbe6f0667 100644 --- a/src/main/java/jikan/Log.java +++ b/src/main/java/jikan/Log.java @@ -7,7 +7,9 @@ import java.util.logging.ConsoleHandler; import java.util.logging.FileHandler; - +/** + * Represents a logger object to log user commands and outcomes to a logfile. + */ public class Log { private static Logger logger; private static SimpleFormatter formatterTxt; @@ -35,14 +37,26 @@ public Log() { } } + /** + * Creates a long entry at info level. + * @param message the info message to be logged + */ public void makeInfoLog(String message) { logger.log(Level.INFO, message); } + /** + * Creates a long entry at warning level. + * @param message the warning message to be logged + */ public void makeWarningLog(String message) { logger.log(Level.WARNING, message); } + /** + * Creates a long entry at severe level. + * @param message the severe warning message to be logged + */ public void makeSevereLog(String message) { logger.log(Level.SEVERE, message); } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 0a13d8413..67e8dc488 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -11,6 +11,7 @@ import java.util.Arrays; import java.util.NoSuchElementException; import java.util.Scanner; +import java.util.logging.Level; /** * Represents the object which parses user input to relevant functions for the execution of commands. @@ -32,7 +33,7 @@ public class Parser { * @param scanner scanner object which reads user input * @param activityList the list of activities */ - public void parseUserCommands(Scanner scanner, ActivityList activityList) { + public void parseUserCommands(Scanner scanner, ActivityList activityList, Log logger) { logger.makeInfoLog("Starting to parse inputs."); while (true) { String userInput = scanner.nextLine(); @@ -48,18 +49,24 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { parseStart(); } catch (EmptyNameException e) { ui.printDivider("Task name cannot be empty!"); + logger.makeWarningLog("Activity started without task name"); } catch (ArrayIndexOutOfBoundsException e) { ui.printDivider("Task name cannot be empty!"); + logger.makeWarningLog("Activity started without task name"); } break; case "end": parseEnd(activityList); + assert startTime == null; break; case "list": ui.printList(activityList); break; case "abort": parseAbort(); + assert activityName == null; + assert startTime == null; + assert endTime == null; break; default: parseDefault(); @@ -71,6 +78,7 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { /** Method to parse user inputs that are not recognised. */ private void parseDefault() { String line = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; + logger.makeInfoLog("Invalid command entered"); ui.printDivider(line); } @@ -78,8 +86,10 @@ private void parseDefault() { private void parseAbort() { if (startTime == null) { String line = "You have not started any activity!"; + logger.makeWarningLog("Abort command failed as no activity was ongoing"); ui.printDivider(line); } else { + logger.makeInfoLog("Aborted " + activityName); startTime = null; tags = null; activityName = null; @@ -114,6 +124,7 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti throw new EmptyNameException(); } line = "Started " + activityName; + logger.makeInfoLog("Started " + activityName); tags = tokenizedInputs[1].substring(delimiter + 3).split(" "); } startTime = LocalDateTime.now(); @@ -126,6 +137,7 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti public void parseEnd(ActivityList activityList) throws ArrayIndexOutOfBoundsException { if (startTime == null) { String line = "You have not started any activity!"; + logger.makeWarningLog("End command failed as there was no ongoing activity"); ui.printDivider(line); } else { String line = "Ended " + activityName; From d101a9fdfe6a61b2254fe80610d30c7527dee6fe Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 16 Mar 2020 16:39:25 +0800 Subject: [PATCH 047/415] Reimplement IO redirection --- text-ui-test/EXPECTED.TXT | 39 +++++++++++++++++++++++++++++++++++++++ text-ui-test/input.txt | 9 +++++++++ 2 files changed, 48 insertions(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index e69de29bb..e219d5558 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -0,0 +1,39 @@ +___________________________________________ + 0101 01010101 01 01 .010. 101 01 + `10' `10' 10 ,10' 10' `10 101o 01 + 01 01 01,01 01 01 0101o 10 + 10 10 10`10 10ooo10 10 11o01 +01. 01 .01. 01 `01. 01 01 01 1010 +010101 01010101 10 10 10 10 10 110 +___________________________________________ + Hello! I'm Jikan + What can I do for you today? +------------------------------------------- +------------------------------------------- +Started studying +------------------------------------------- +------------------------------------------- +Ended studying +------------------------------------------- +------------------------------------------- +Started exercising +------------------------------------------- +------------------------------------------- +You have aborted the current activity! +------------------------------------------- +------------------------------------------- +Task name cannot be empty! +------------------------------------------- +------------------------------------------- +There is no such task! +------------------------------------------- +------------------------------------------- +There is no such task! +------------------------------------------- +------------------------------------------- +Your completed activities: +1. studying 00:00:02 +------------------------------------------- +------------------------------------------- + Bye! See you again. +------------------------------------------- \ No newline at end of file diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e69de29bb..650571f88 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -0,0 +1,9 @@ +start studying +end studying +start exercising +abort exercising +start +end +abort +list +bye \ No newline at end of file From b1557f83838a4205d4e586830211ccd795d88d51 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 16 Mar 2020 16:45:28 +0800 Subject: [PATCH 048/415] Change project name in gradle and fix style error --- build.gradle | 6 +++--- src/main/java/jikan/Jikan.java | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/build.gradle b/build.gradle index a6db99138..7698de8a7 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'com.github.johnrengelman.shadow' version '5.1.0' } -group 'seedu.duke' +group 'jikan' version '0.1.0' repositories { @@ -21,11 +21,11 @@ test { } application { - mainClassName = "seedu.duke.Duke" + mainClassName = "jikan.Jikan" } shadowJar { - archiveBaseName = "duke" + archiveBaseName = "jikan" archiveVersion = "0.0.1" archiveClassifier = null archiveAppendix = null diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 0a5414e5e..770550a97 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -24,10 +24,11 @@ public class Jikan { /** Ui to handle printing. */ private static Ui ui = new Ui(); + /** Parser for input commands. */ private static Parser parser = new Parser(); /** - * Creates ActivityList and loads data from data file if the data file previously existed; + * Creates ActivityList and loads data from data file if the data file previously existed. * otherwise, an empty task list is initialized. */ public static void createActivityList() { From f794abdaf8e99be399d28076995046ed1fbac0e0 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 16 Mar 2020 16:53:05 +0800 Subject: [PATCH 049/415] Fix style check --- src/main/java/jikan/Jikan.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 770550a97..47698c1e3 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -29,7 +29,7 @@ public class Jikan { /** * Creates ActivityList and loads data from data file if the data file previously existed. - * otherwise, an empty task list is initialized. + * Otherwise, an empty task list is initialized. */ public static void createActivityList() { try { From c6f79c0bfeb5717487d96bfc8b2abdf4315c1a2d Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Mon, 16 Mar 2020 16:57:56 +0800 Subject: [PATCH 050/415] Reduced severity from WARNING to INFO, and INFO to FINE. Reduces unnecessary warnings printed to user. --- src/main/java/jikan/Log.java | 24 ++++++++++++------------ src/main/java/jikan/parser/Parser.java | 21 ++++++++++----------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/src/main/java/jikan/Log.java b/src/main/java/jikan/Log.java index dbe6f0667..e2ade1789 100644 --- a/src/main/java/jikan/Log.java +++ b/src/main/java/jikan/Log.java @@ -38,26 +38,26 @@ public Log() { } /** - * Creates a long entry at info level. - * @param message the info message to be logged + * Creates a long entry at FINE level. + * @param message the FINE message to be logged */ - public void makeInfoLog(String message) { - logger.log(Level.INFO, message); + public void makeFineLog(String message) { + logger.log(Level.FINE, message); } /** - * Creates a long entry at warning level. - * @param message the warning message to be logged + * Creates a long entry at INFO level. + * @param message the INFO message to be logged */ - public void makeWarningLog(String message) { - logger.log(Level.WARNING, message); + public void makeINFOLog(String message) { + logger.log(Level.INFO, message); } /** - * Creates a long entry at severe level. - * @param message the severe warning message to be logged + * Creates a long entry at WARNING level. + * @param message the WARNING warning message to be logged */ - public void makeSevereLog(String message) { - logger.log(Level.SEVERE, message); + public void makeWarningLog(String message) { + logger.log(Level.WARNING, message); } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 0e165a499..a2ab4a88f 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -32,7 +32,7 @@ public class Parser { * @param activityList the list of activities */ public void parseUserCommands(Scanner scanner, ActivityList activityList, Log logger) { - logger.makeInfoLog("Starting to parse inputs."); + logger.makeFineLog("Starting to parse inputs."); while (true) { String userInput = scanner.nextLine(); tokenizedInputs = userInput.split(" ", 2); @@ -46,13 +46,13 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList, Log lo try { parseStart(); } catch (EmptyNameException e) { - logger.makeWarningLog("Activity started without task name"); + logger.makeInfoLog("Activity started without task name"); ui.printDivider("Task name cannot be empty!"); } catch (ArrayIndexOutOfBoundsException e) { - logger.makeWarningLog("Activity started without task name"); + logger.makeInfoLog("Activity started without task name"); ui.printDivider("Task name cannot be empty!"); } catch (NullPointerException e) { - logger.makeWarningLog("Activity started without task name"); + logger.makeInfoLog("Activity started without task name"); ui.printDivider("Task name cannot be empty!"); } break; @@ -60,7 +60,7 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList, Log lo try { parseEnd(activityList); } catch (NoSuchActivityException e) { - logger.makeWarningLog("End command failed as no activity was ongoing"); + logger.makeInfoLog("End command failed as no activity was ongoing"); ui.printDivider("You have not started any activity!"); } break; @@ -72,7 +72,7 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList, Log lo parseAbort(); } catch (NoSuchActivityException e) { ui.printDivider("You have not started any activity!"); - logger.makeWarningLog("Abort command failed as no activity was ongoing"); + logger.makeInfoLog("Abort command failed as no activity was ongoing"); } break; default: @@ -94,7 +94,7 @@ public void parseAbort() throws NoSuchActivityException { if (startTime == null) { throw new NoSuchActivityException(); } else { - logger.makeInfoLog("Aborted " + activityName); + logger.makeFineLog("Aborted " + activityName); startTime = null; tags = null; activityName = null; @@ -109,7 +109,7 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti // check if an activity has already been started if (startTime != null) { String line = activityName + " is ongoing!"; - logger.makeWarningLog("Could not start activity due to ongoing activity."); + logger.makeInfoLog("Could not start activity due to already ongoing activity."); ui.printDivider(line); } else { // tags should be reset @@ -129,13 +129,12 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti throw new EmptyNameException(); } line = "Started " + activityName; - logger.makeInfoLog("Started " + activityName); tags = tokenizedInputs[1].substring(delimiter + 3).split(" "); } startTime = LocalDateTime.now(); ui.printDivider(line); } - logger.makeInfoLog("Started: " + activityName); + logger.makeFineLog("Started: " + activityName); } /** Method to parse the end activity command. */ @@ -152,6 +151,6 @@ public void parseEnd(ActivityList activityList) throws NoSuchActivityException { startTime = null; tags = null; } - logger.makeInfoLog("Ended: " + activityName); + logger.makeFineLog("Ended: " + activityName); } } From 2552d92515a8a8bd6254f4eae312f1a0c4747962 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 16 Mar 2020 17:29:14 +0800 Subject: [PATCH 051/415] Handle ioexception for log in Parser instead of Log --- src/main/java/jikan/Log.java | 18 ++++++++---------- src/main/java/jikan/parser/Parser.java | 13 ++++++++++++- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/main/java/jikan/Log.java b/src/main/java/jikan/Log.java index 8ddb97a5f..67482c880 100644 --- a/src/main/java/jikan/Log.java +++ b/src/main/java/jikan/Log.java @@ -1,5 +1,6 @@ package jikan; +import java.io.IOException; import java.util.logging.Level; import java.util.logging.LogManager; import java.util.logging.Logger; @@ -15,7 +16,7 @@ public class Log { /** * Constructor for a new logger. */ - public Log() { + public Log() throws IOException { logger = Logger.getLogger(Log.class.getName()); LogManager.getLogManager().reset(); logger.setLevel(Level.ALL); @@ -24,15 +25,12 @@ public Log() { consoleHandler.setLevel(Level.WARNING); logger.addHandler(consoleHandler); - try { - FileHandler fileHandler = new FileHandler("data/LogRecord.txt"); - formatterTxt = new SimpleFormatter(); - fileHandler.setFormatter(formatterTxt); - fileHandler.setLevel(Level.INFO); - logger.addHandler(fileHandler); - } catch (java.io.IOException e) { - logger.log(Level.SEVERE, "File logger not working", e); - } + FileHandler fileHandler = new FileHandler("data/LogRecord.txt", true); + + formatterTxt = new SimpleFormatter(); + fileHandler.setFormatter(formatterTxt); + fileHandler.setLevel(Level.INFO); + logger.addHandler(fileHandler); } public void makeInfoLog(String message) { diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index c8dc543e1..fcc69b3f6 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -7,6 +7,7 @@ import jikan.ui.Ui; import jikan.Log; +import java.io.IOException; import java.time.LocalDateTime; import java.util.Scanner; @@ -22,8 +23,18 @@ public class Parser { private Ui ui = new Ui(); protected String[] tokenizedInputs; String instruction; + Log logger; - Log logger = new Log(); + /** + * Constructor for Parser. + */ + public Parser() { + try { + logger = new Log(); + } catch (IOException e) { + ui.printDivider("Could not initialize logger."); + } + } /** * Parses user commands to relevant functions to carry out the commands. From bee98cd466bda1efcf465ac1e000cd92e9dcb74f Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Mon, 16 Mar 2020 17:54:03 +0800 Subject: [PATCH 052/415] fixed info logger error --- src/main/java/jikan/Log.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/Log.java b/src/main/java/jikan/Log.java index e2ade1789..b85d43414 100644 --- a/src/main/java/jikan/Log.java +++ b/src/main/java/jikan/Log.java @@ -49,7 +49,7 @@ public void makeFineLog(String message) { * Creates a long entry at INFO level. * @param message the INFO message to be logged */ - public void makeINFOLog(String message) { + public void makeInfoLog(String message) { logger.log(Level.INFO, message); } From b8d127f18a2ae4a0dde890f68396c02c1b2edac9 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 16 Mar 2020 17:59:07 +0800 Subject: [PATCH 053/415] Fix file creation for log file --- src/main/java/jikan/Jikan.java | 4 +-- src/main/java/jikan/Log.java | 44 +++++++++++++++++++++++++- src/main/java/jikan/parser/Parser.java | 15 ++------- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 4f294981f..3ea26fd49 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -27,8 +27,6 @@ public class Jikan { /** Parser to parse commands. */ private static Parser parser = new Parser(); - private static Log logger = new Log(); - /** * Creates ActivityList and loads data from data file if the data file previously existed. * Otherwise, an empty task list is initialized. @@ -55,6 +53,6 @@ public static void main(String[] args) { Scanner in = new Scanner(System.in); storage = new Storage(DATA_FILE_PATH); createActivityList(); - parser.parseUserCommands(in, activityList, logger); + parser.parseUserCommands(in, activityList); } } diff --git a/src/main/java/jikan/Log.java b/src/main/java/jikan/Log.java index c2832bb94..81460b819 100644 --- a/src/main/java/jikan/Log.java +++ b/src/main/java/jikan/Log.java @@ -1,5 +1,8 @@ package jikan; +import jikan.ui.Ui; + +import java.io.File; import java.io.IOException; import java.util.logging.Level; import java.util.logging.LogManager; @@ -14,10 +17,13 @@ public class Log { private static Logger logger; private static SimpleFormatter formatterTxt; + public String logFilePath = "data/LogRecord.txt"; + private static File logFile; + /* /** * Constructor for a new logger. - */ + * public Log() throws IOException { logger = Logger.getLogger(Log.class.getName()); LogManager.getLogManager().reset(); @@ -29,6 +35,42 @@ public Log() throws IOException { FileHandler fileHandler = new FileHandler("data/LogRecord.txt", true); + formatterTxt = new SimpleFormatter(); + fileHandler.setFormatter(formatterTxt); + fileHandler.setLevel(Level.INFO); + logger.addHandler(fileHandler); + } */ + + /** + * Constructor for a new logger. + */ + public Log(){ + logger = Logger.getLogger(Log.class.getName()); + LogManager.getLogManager().reset(); + logger.setLevel(Level.ALL); + + ConsoleHandler consoleHandler = new ConsoleHandler(); + consoleHandler.setLevel(Level.WARNING); + logger.addHandler(consoleHandler); + + logFile = new File(logFilePath); + + if (!logFile.exists()) { + try { + // Create file + logFile.getParentFile().mkdirs(); // Create data directory (does nothing if directory already exists) + logFile.createNewFile(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + FileHandler fileHandler = null; + try { + fileHandler = new FileHandler("data/LogRecord.txt", true); + } catch (IOException e) { + e.printStackTrace(); + } formatterTxt = new SimpleFormatter(); fileHandler.setFormatter(formatterTxt); fileHandler.setLevel(Level.INFO); diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index cd6c88128..9a6bb95c6 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -24,25 +24,14 @@ public class Parser { private Ui ui = new Ui(); protected String[] tokenizedInputs; String instruction; - Log logger; - - /** - * Constructor for Parser. - */ - public Parser() { - try { - logger = new Log(); - } catch (IOException e) { - ui.printDivider("Could not initialize logger."); - } - } + Log logger = new Log(); /** * Parses user commands to relevant functions to carry out the commands. * @param scanner scanner object which reads user input * @param activityList the list of activities */ - public void parseUserCommands(Scanner scanner, ActivityList activityList, Log logger) { + public void parseUserCommands(Scanner scanner, ActivityList activityList) { logger.makeInfoLog("Starting to parse inputs."); while (true) { String userInput = scanner.nextLine(); From 7f5eb075cae5765b6a3139760290be3b89e2871e Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 16 Mar 2020 18:04:16 +0800 Subject: [PATCH 054/415] Fix style --- src/main/java/jikan/Log.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/Log.java b/src/main/java/jikan/Log.java index 81460b819..9abb12cd6 100644 --- a/src/main/java/jikan/Log.java +++ b/src/main/java/jikan/Log.java @@ -44,7 +44,7 @@ public Log() throws IOException { /** * Constructor for a new logger. */ - public Log(){ + public Log() { logger = Logger.getLogger(Log.class.getName()); LogManager.getLogManager().reset(); logger.setLevel(Level.ALL); From 1be57102f7ed000d77e0c155bee89cc4b0b0db0c Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 16 Mar 2020 18:09:32 +0800 Subject: [PATCH 055/415] Fix expected io output --- text-ui-test/EXPECTED.TXT | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index e219d5558..89e12efda 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -25,15 +25,19 @@ You have aborted the current activity! Task name cannot be empty! ------------------------------------------- ------------------------------------------- -There is no such task! +You have not started any activity! ------------------------------------------- ------------------------------------------- -There is no such task! +You have not started any activity! ------------------------------------------- ------------------------------------------- Your completed activities: -1. studying 00:00:02 +1. studying 00:00:00 +2. studying 00:00:00 +3. studying 00:00:00 +4. studying 00:00:00 +5. studying 00:00:00 ------------------------------------------- ------------------------------------------- Bye! See you again. -------------------------------------------- \ No newline at end of file +------------------------------------------- From c318c13584634878234616281ba01eb29bf76f42 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 16 Mar 2020 18:14:43 +0800 Subject: [PATCH 056/415] Remove list command from test --- text-ui-test/EXPECTED.TXT | 8 -------- text-ui-test/input.txt | 1 - 2 files changed, 9 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 89e12efda..074d01dd9 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -30,14 +30,6 @@ You have not started any activity! ------------------------------------------- You have not started any activity! ------------------------------------------- -------------------------------------------- -Your completed activities: -1. studying 00:00:00 -2. studying 00:00:00 -3. studying 00:00:00 -4. studying 00:00:00 -5. studying 00:00:00 -------------------------------------------- ------------------------------------------- Bye! See you again. ------------------------------------------- diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 650571f88..5f0a1f4d7 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -5,5 +5,4 @@ abort exercising start end abort -list bye \ No newline at end of file From 0918f8da6baf7dcf099c7c2381c685b4819427d7 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Mon, 16 Mar 2020 18:28:44 +0800 Subject: [PATCH 057/415] Change logo to plain characters --- src/main/java/jikan/ui/Ui.java | 11 +---------- text-ui-test/EXPECTED.TXT | 11 +---------- 2 files changed, 2 insertions(+), 20 deletions(-) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 14f38db13..75cf72048 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -5,16 +5,7 @@ import java.util.concurrent.TimeUnit; public class Ui { - public static final String GREETING = "___________________________________________\n" - + " 0101 01010101 01 01 .010. 101 01 \n" - + " `10' `10' 10 ,10' 10' `10 101o 01 \n" - + " 01 01 01,01 01 01 0101o 10 \n" - + " 10 10 10`10 10ooo10 10 11o01 \n" - + "01. 01 .01. 01 `01. 01 01 01 1010 \n" - + "010101 01010101 10 10 10 10 10 110 \n" - + "___________________________________________\n" - + " Hello! I'm Jikan\n" - + " What can I do for you today?"; + public static final String GREETING = "Jikan"; public static final String DIVIDER = "-------------------------------------------"; diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 074d01dd9..04de01a38 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,13 +1,4 @@ -___________________________________________ - 0101 01010101 01 01 .010. 101 01 - `10' `10' 10 ,10' 10' `10 101o 01 - 01 01 01,01 01 01 0101o 10 - 10 10 10`10 10ooo10 10 11o01 -01. 01 .01. 01 `01. 01 01 01 1010 -010101 01010101 10 10 10 10 10 110 -___________________________________________ - Hello! I'm Jikan - What can I do for you today? +Jikan ------------------------------------------- ------------------------------------------- Started studying From 46212558a636415dff02a243606dac678f53476d Mon Sep 17 00:00:00 2001 From: btricec Date: Tue, 17 Mar 2020 00:31:17 +0800 Subject: [PATCH 058/415] Change list format --- src/main/java/jikan/activity/Activity.java | 7 ++++ src/main/java/jikan/ui/Ui.java | 38 ++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 7c95dc455..49f570322 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -1,6 +1,7 @@ package jikan.activity; import java.time.Duration; +import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Arrays; @@ -14,6 +15,7 @@ public class Activity { private LocalDateTime startTime; private LocalDateTime endTime; private Duration duration; + private LocalDate date; /** * Constructor for a new activity entry. @@ -28,6 +30,7 @@ public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Str this.tags = tags; this.endTime = endTime; this.duration = Duration.between(startTime, endTime); + this.date = endTime.toLocalDate(); } /** @@ -66,6 +69,10 @@ public String[] getTags() { return tags; } + public LocalDate getDate() { + return date; + } + /** * Converts the jikan.activity.Activity object to data representation to be stored in a data file. * File format: diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 75cf72048..5ffeb5e96 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -30,7 +30,44 @@ public void printDivider(String line) { System.out.println(DIVIDER); } + private void printTableFormat(ActivityList activityList, int index, boolean gotTags) { + long durationInNanos = (activityList.get(index).getDuration()).toNanos(); + String duration = String.format("%02d:%02d:%02d", + TimeUnit.NANOSECONDS.toHours(durationInNanos), + TimeUnit.NANOSECONDS.toMinutes(durationInNanos) + - TimeUnit.HOURS.toMinutes(TimeUnit.NANOSECONDS.toHours(durationInNanos)), + TimeUnit.NANOSECONDS.toSeconds(durationInNanos) + - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(durationInNanos))); + if (gotTags) { + System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %-100s", + index + 1, "|", activityList.get(index).getName(), "|", duration, "|", + activityList.get(index).getDate().toString(), "|", + Arrays.toString(activityList.get(index).getTags()))); + } else { + System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %s", + index + 1, "|", activityList.get(index).getName(), "|", duration, "|", + activityList.get(index).getDate().toString(), "|", "")); + } + } + /** Prints all the activities in the list. */ + public void printList(ActivityList activityList) { + System.out.println(DIVIDER); + System.out.println("Your completed activities:"); + System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", + "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); + for (int i = 0; i < activityList.getSize(); i++) { + if (activityList.get(i).getTags() != null && !activityList.get(i).getTags()[0].equals("null")) { + printTableFormat(activityList, i, true); + } else { + printTableFormat(activityList, i, false); + } + } + System.out.println(DIVIDER); + } + + + /* public void printList(ActivityList activityList) { System.out.println(DIVIDER); System.out.println("Your completed activities:"); @@ -55,4 +92,5 @@ public void printList(ActivityList activityList) { } System.out.println(DIVIDER); } + */ } From 76c738fd439c111e2f2dfdb89e27df7b20e1a23d Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 17 Mar 2020 15:53:48 +0800 Subject: [PATCH 059/415] Fix issue with tags saving incorrectly --- src/main/java/jikan/activity/Activity.java | 10 +++++++++- src/main/java/jikan/activity/ActivityList.java | 2 +- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 49f570322..5fb4232fb 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -81,7 +81,15 @@ public LocalDate getDate() { * @return String representing the Task object in comma-separated data format. */ public String toData() { - String dataLine = (this.name + "," + this.startTime + "," + this.endTime + "," + Arrays.toString(this.tags)); + + // Convert tags to a single space-separated + String tagString = ""; + + for (int i = 0; i < this.tags.length; i++) { + tagString = tagString + this.tags[i] + " "; + } + + String dataLine = (this.name + "," + this.startTime + "," + this.endTime + "," + tagString); return dataLine; } } \ No newline at end of file diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 7aef26f12..0ea8fbf38 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -104,7 +104,7 @@ private void parseDataLine(String s) { // if there are tags if (!strings.get(3).equals("null")) { // remove square brackets surrounding tags - tags = strings.get(3).substring(1,strings.get(3).length() - 1).split(" "); + tags = strings.get(3).substring(0,strings.get(3).length() - 1).split(" "); } else { tags = null; } From d8f11d063af51deef9bc16569991c23092355249 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 17 Mar 2020 16:04:37 +0800 Subject: [PATCH 060/415] Fix bug with tasks with no tags --- src/main/java/jikan/activity/Activity.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 5fb4232fb..8d25878fc 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -85,8 +85,10 @@ public String toData() { // Convert tags to a single space-separated String tagString = ""; - for (int i = 0; i < this.tags.length; i++) { - tagString = tagString + this.tags[i] + " "; + if (this.tags != null) { + for (int i = 0; i < this.tags.length; i++) { + tagString = tagString + this.tags[i] + " "; + } } String dataLine = (this.name + "," + this.startTime + "," + this.endTime + "," + tagString); From cbd8d8cfdcf68cd0955b9d8f1cb51e14d467e9de Mon Sep 17 00:00:00 2001 From: btricec Date: Tue, 17 Mar 2020 17:27:23 +0800 Subject: [PATCH 061/415] Add exception handling and update StorageHandlerTest --- src/main/java/jikan/parser/Parser.java | 7 +++++- .../java/jikan/storage/StorageHandler.java | 24 ++++++++++++------- .../jikan/storage/StorageHandlerTest.java | 8 +++---- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 456ab012f..f400fa242 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -56,7 +56,11 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { parseAbort(); break; case "delete": - parseDelete(activityList); + try { + parseDelete(activityList); + } catch (IndexOutOfBoundsException | NumberFormatException e) { + ui.printDivider("Invalid index number."); + } break; default: parseDefault(); @@ -130,6 +134,7 @@ public void parseEnd(ActivityList activityList) throws ArrayIndexOutOfBoundsExce } } + /** Deletes an activity from the activity list. */ public void parseDelete(ActivityList activityList) { int index = Integer.parseInt(tokenizedInputs[1]) - 1; String line = "You have deleted " + activityList.get(index).getName(); diff --git a/src/main/java/jikan/storage/StorageHandler.java b/src/main/java/jikan/storage/StorageHandler.java index f54ea09cd..85e2f1dd6 100644 --- a/src/main/java/jikan/storage/StorageHandler.java +++ b/src/main/java/jikan/storage/StorageHandler.java @@ -20,12 +20,13 @@ public class StorageHandler { * Removes the line whose index matches lineNumber from file at dataFilePath. * * @param lineNumber Index of line to remove. - * @param dataFilePath Path to data file. + * @param storage Storage object which contains path to save file. * @throws IOException If an error occurs while writing the new list to file. */ public static void removeLine(int lineNumber, Storage storage) throws IOException { // Read file into list of strings, where each string is a line in the file - List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(storage.dataFilePath), StandardCharsets.UTF_8)); + List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(storage.dataFilePath), + StandardCharsets.UTF_8)); //int removedIndex = 0; @@ -46,15 +47,22 @@ public static void removeLine(int lineNumber, Storage storage) throws IOExceptio */ } + /** + * Saves a the updated activity list to the csv file. + * + * @param newList The list containing the updated data. + * @param dataFile The file to save to. + * @throws IOException If an error occurs while writing the new list to file. + */ public static void saveNewList(List newList, File dataFile) throws IOException { - FileOutputStream fo = new FileOutputStream(dataFile); - PrintWriter pw = new PrintWriter(fo); + FileOutputStream fileOutputStream = new FileOutputStream(dataFile); + PrintWriter printWriter = new PrintWriter(fileOutputStream); - for (int i = 0; i < newList.size(); i++) { - pw.println(newList.get(i)); + for (String s : newList) { + printWriter.println(s); } - pw.close(); - fo.close(); + printWriter.close(); + fileOutputStream.close(); } /** diff --git a/src/test/java/jikan/storage/StorageHandlerTest.java b/src/test/java/jikan/storage/StorageHandlerTest.java index d9365ccec..a210374a1 100644 --- a/src/test/java/jikan/storage/StorageHandlerTest.java +++ b/src/test/java/jikan/storage/StorageHandlerTest.java @@ -20,16 +20,16 @@ public void removeLine() throws IOException { Storage storage = new Storage(filepath); storage.loadFile(); - String line1 = "1. a"; - String line2 = "2. b"; - String line3 = "3. c"; + String line1 = "a"; + String line2 = "b"; + String line3 = "c"; String writtenString = ""; storage.writeToFile(line1); storage.writeToFile(line2); storage.writeToFile(line3); - StorageHandler.removeLine(2, storage.dataFilePath); + StorageHandler.removeLine(1, storage); int i = 0; Scanner dataScanner = new Scanner(storage.dataFile); From a6101b32cbfb8d390b7ed8473765bbbb7b79e55f Mon Sep 17 00:00:00 2001 From: btricec Date: Tue, 17 Mar 2020 17:48:51 +0800 Subject: [PATCH 062/415] Updated text-ui test --- text-ui-test/EXPECTED.TXT | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 04de01a38..6b070cb3a 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,13 +1,13 @@ Jikan ------------------------------------------- ------------------------------------------- -Started studying +Started: studying ------------------------------------------- ------------------------------------------- -Ended studying +Ended: studying ------------------------------------------- ------------------------------------------- -Started exercising +Started: exercising ------------------------------------------- ------------------------------------------- You have aborted the current activity! From ef5c6b7f613d8ed63bcb4cf0e45f27088cedc1c9 Mon Sep 17 00:00:00 2001 From: btricec Date: Tue, 17 Mar 2020 18:10:18 +0800 Subject: [PATCH 063/415] Fixed storage bugs --- src/main/java/jikan/activity/ActivityList.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 37e7cde0a..f7399473a 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -113,12 +113,13 @@ private void parseDataLine(String s) { if (!s.isEmpty()) { List strings = Arrays.asList(s.split(",")); - String[] tags = new String[strings.size() - 3]; + String[] tags; // if there are tags - if (!strings.get(3).equals("null")) { + if (strings.size() > 3) { // remove square brackets surrounding tags - tags = strings.get(3).substring(0,strings.get(3).length() - 1).split(" "); + // tags = strings.get(3).substring(0,strings.get(3).length() - 1).split(" "); + tags = strings.get(3).split(" "); } else { tags = null; } From 4edfeed93848f8ce83c275ab17f2f23379b10ea2 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 18 Mar 2020 15:21:41 +0800 Subject: [PATCH 064/415] Find and PrintResult methods working --- src/main/java/jikan/parser/Parser.java | 44 ++++++++++++++++++++++++-- src/main/java/jikan/ui/Ui.java | 25 ++++++++++++--- 2 files changed, 63 insertions(+), 6 deletions(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index d1832b1e6..0af0d5a38 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -6,7 +6,7 @@ import jikan.exception.NoSuchActivityException; import jikan.ui.Ui; import jikan.Log; - +import java.util.ArrayList; import java.io.IOException; import java.time.LocalDateTime; import java.util.Scanner; @@ -25,7 +25,7 @@ public class Parser { protected String[] tokenizedInputs; String instruction; Log logger = new Log(); - + private ActivityList lastShownList = new ActivityList(); /** * Parses user commands to relevant functions to carry out the commands. * @param scanner scanner object which reads user input @@ -33,6 +33,8 @@ public class Parser { */ public void parseUserCommands(Scanner scanner, ActivityList activityList) { logger.makeInfoLog("Starting to parse inputs."); + //lastShownList is initialised here to facilitate subsequent delete and edit commands referencing by index of this list. + lastShownList.activities.addAll(activityList.activities); while (true) { String userInput = scanner.nextLine(); tokenizedInputs = userInput.split(" ", 2); @@ -82,6 +84,12 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { ui.printDivider("Invalid index number."); } break; + case "find": + parseFind(activityList, lastShownList, tokenizedInputs[1]); + break; + case "filter": + parseFilter(activityList, lastShownList, tokenizedInputs[1]); + break; default: parseDefault(); break; @@ -89,6 +97,38 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { } } + private void parseFind(ActivityList activityList, ActivityList lastShownList, String keyword) { + lastShownList.activities.clear(); + for(Activity i : activityList.activities) { + if (i.getName().contains(keyword)) { + lastShownList.activities.add(i); + } + } + Ui.printResults(lastShownList); + } + + private void parseFilter(ActivityList activityList, ActivityList lastShownList, String query) { + lastShownList.activities.clear(); + String[] keywords = query.split(" "); + + for(String keyword : keywords) { + for (Activity i : activityList.activities) { + String tagString = ""; + + if (i.getTags() != null) { + //for (int j = 0; j < this.tags.length; j++) { + //tagString = tagString + this.tags[j] + " "; + //} + } + + if (tagString.contains(keyword)) { + lastShownList.activities.add(i); + } + } + } + Ui.printResults(lastShownList); + } + /** Method to parse user inputs that are not recognised. */ private void parseDefault() { String line = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index b0a0e3e31..8d14ce76b 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -24,13 +24,13 @@ public void exitFromApp() { } /** Prints divider between user input and app feedback. */ - public void printDivider(String line) { + public static void printDivider(String line) { System.out.println(DIVIDER); System.out.println(line); System.out.println(DIVIDER); } - private void printTableFormat(ActivityList activityList, int index, boolean gotTags) { + private static void printTableFormat(ActivityList activityList, int index, boolean gotTags) { long durationInNanos = (activityList.get(index).getDuration()).toNanos(); String duration = String.format("%02d:%02d:%02d", TimeUnit.NANOSECONDS.toHours(durationInNanos), @@ -50,8 +50,25 @@ private void printTableFormat(ActivityList activityList, int index, boolean gotT } } - /** Prints all the activities in the list. */ - public void printList(ActivityList activityList) { + public static void printResults(ActivityList lastShownList) { + if (lastShownList.activities.size() > 0) { + System.out.println("Here are the matching activities in your list:\n"); + System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", + "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); + for (int i = 0; i < lastShownList.getSize(); i++) { + if (lastShownList.get(i).getTags() != null && !lastShownList.get(i).getTags()[0].equals("null")) { + printTableFormat(lastShownList, i, true); + } else { + printTableFormat(lastShownList, i, false); + } + } + } else { + System.out.println("There are no activities matching that description.\n"); + } + } + + /** Prints all the activities in a list. */ + public static void printList(ActivityList activityList) { System.out.println(DIVIDER); System.out.println("Your completed activities:"); System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", From 3761e55091dd009232dc00f7ac761828c58990e5 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 18 Mar 2020 16:06:52 +0800 Subject: [PATCH 065/415] Completed find and filter with exceptions handling. Arrowhead code still, to be fixed after tags get changed to an ArrayList of Strings --- .../jikan/exception/EmptyQueryException.java | 7 ++ src/main/java/jikan/parser/Parser.java | 80 +++++++++++++------ 2 files changed, 61 insertions(+), 26 deletions(-) create mode 100644 src/main/java/jikan/exception/EmptyQueryException.java diff --git a/src/main/java/jikan/exception/EmptyQueryException.java b/src/main/java/jikan/exception/EmptyQueryException.java new file mode 100644 index 000000000..fa3d27802 --- /dev/null +++ b/src/main/java/jikan/exception/EmptyQueryException.java @@ -0,0 +1,7 @@ +package jikan.exception; + +/** + * An exception that is thrown when the query for find or filter is not provided + */ +public class EmptyQueryException extends Exception { +} \ No newline at end of file diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 0af0d5a38..6ecb055a5 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -3,6 +3,7 @@ import jikan.exception.EmptyNameException; import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.EmptyQueryException; import jikan.exception.NoSuchActivityException; import jikan.ui.Ui; import jikan.Log; @@ -85,10 +86,18 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { } break; case "find": - parseFind(activityList, lastShownList, tokenizedInputs[1]); + try { + parseFind(activityList, lastShownList, tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { + ui.printDivider("No keyword was given."); + } break; case "filter": - parseFilter(activityList, lastShownList, tokenizedInputs[1]); + try { + parseFilter(activityList, lastShownList, tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { + ui.printDivider("No keyword was given."); + } break; default: parseDefault(); @@ -97,36 +106,55 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { } } - private void parseFind(ActivityList activityList, ActivityList lastShownList, String keyword) { - lastShownList.activities.clear(); - for(Activity i : activityList.activities) { - if (i.getName().contains(keyword)) { - lastShownList.activities.add(i); - } - } - Ui.printResults(lastShownList); - } - - private void parseFilter(ActivityList activityList, ActivityList lastShownList, String query) { - lastShownList.activities.clear(); - String[] keywords = query.split(" "); - - for(String keyword : keywords) { + /** + * Shows the user all past activities that has names which match the keyword queried by the user. + * @param activityList the activity list to search for matching activities + * @param lastShownList the activity list to populate with matching activities only + * @param keyword the keyword queried by the user + */ + private void parseFind(ActivityList activityList, ActivityList lastShownList, String keyword) throws EmptyQueryException{ + if (keyword.length() < 1) { + throw new EmptyQueryException(); + } else { + lastShownList.activities.clear(); for (Activity i : activityList.activities) { - String tagString = ""; - - if (i.getTags() != null) { - //for (int j = 0; j < this.tags.length; j++) { - //tagString = tagString + this.tags[j] + " "; - //} + if (i.getName().contains(keyword)) { + lastShownList.activities.add(i); } + } + Ui.printResults(lastShownList); + } + } - if (tagString.contains(keyword)) { - lastShownList.activities.add(i); + /** + * Shows the user all past activities that has tags which match the keywords queried by the user. + * @param activityList the activity list to search for matching activities + * @param lastShownList the activity list to populate with matching activities only + * @param query the keywords queried by the user + */ + private void parseFilter(ActivityList activityList, ActivityList lastShownList, String query) throws EmptyQueryException { + if (query.length() < 1) { + throw new EmptyQueryException(); + } else { + lastShownList.activities.clear(); + String[] keywords = query.split(" "); + + for (String keyword : keywords) { + for (Activity i : activityList.activities) { + String tagString = ""; + + if (i.getTags() != null) { + for (int j = 0; j < i.getTags().length; j++) { + tagString = tagString + i.getTags()[j] + " "; + } + } + if (tagString.contains(keyword)) { + lastShownList.activities.add(i); + } } } + Ui.printResults(lastShownList); } - Ui.printResults(lastShownList); } /** Method to parse user inputs that are not recognised. */ From fe2d68224b7ef00cb4aab3f56bdde5e6a2f7d704 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Thu, 19 Mar 2020 14:03:20 +0800 Subject: [PATCH 066/415] Added Divider, --- src/main/java/jikan/ui/Ui.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 8d14ce76b..9ad34dc22 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -52,6 +52,7 @@ private static void printTableFormat(ActivityList activityList, int index, boole public static void printResults(ActivityList lastShownList) { if (lastShownList.activities.size() > 0) { + System.out.println(DIVIDER); System.out.println("Here are the matching activities in your list:\n"); System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); @@ -62,6 +63,7 @@ public static void printResults(ActivityList lastShownList) { printTableFormat(lastShownList, i, false); } } + System.out.println(DIVIDER); } else { System.out.println("There are no activities matching that description.\n"); } From 39677980e8b52506747645a403e3fd64b972a597 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Thu, 19 Mar 2020 14:44:22 +0800 Subject: [PATCH 067/415] Added Dividers --- src/main/java/jikan/ui/Ui.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 8d14ce76b..9ad34dc22 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -52,6 +52,7 @@ private static void printTableFormat(ActivityList activityList, int index, boole public static void printResults(ActivityList lastShownList) { if (lastShownList.activities.size() > 0) { + System.out.println(DIVIDER); System.out.println("Here are the matching activities in your list:\n"); System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); @@ -62,6 +63,7 @@ public static void printResults(ActivityList lastShownList) { printTableFormat(lastShownList, i, false); } } + System.out.println(DIVIDER); } else { System.out.println("There are no activities matching that description.\n"); } From b58134999ce09123d297787e37cd31e30f768cdd Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Thu, 19 Mar 2020 19:49:17 +0800 Subject: [PATCH 068/415] changed tags to be stored as Set --- src/main/java/jikan/activity/Activity.java | 25 +++++---- .../java/jikan/activity/ActivityList.java | 17 +++--- src/main/java/jikan/parser/Parser.java | 53 ++++++++++++------- src/main/java/jikan/ui/Ui.java | 7 +-- 4 files changed, 60 insertions(+), 42 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 8d25878fc..bf12945b9 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -4,6 +4,8 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.util.Arrays; +import java.util.Iterator; +import java.util.Set; /** * Represents an activity entry with a name and total time spent. @@ -11,7 +13,7 @@ public class Activity { private String name; - private String[] tags; + private Set tags; private LocalDateTime startTime; private LocalDateTime endTime; private Duration duration; @@ -24,7 +26,7 @@ public class Activity { * @param tags activity tags * @param endTime the time that the activity ended */ - public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, String[] tags) { + public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Set tags) { this.name = name.strip(); this.startTime = startTime; this.tags = tags; @@ -65,7 +67,7 @@ public String getName() { return name; } - public String[] getTags() { + public Set getTags() { return tags; } @@ -83,15 +85,18 @@ public LocalDate getDate() { public String toData() { // Convert tags to a single space-separated - String tagString = ""; - - if (this.tags != null) { - for (int i = 0; i < this.tags.length; i++) { - tagString = tagString + this.tags[i] + " "; - } - } + String tagString = tagsToString(tagString); String dataLine = (this.name + "," + this.startTime + "," + this.endTime + "," + tagString); return dataLine; } + + private String tagsToString(String tagString) { + Iterator i = this.tags.iterator(); + + while (i.hasNext()) { + tagString += i.next() + " "; + } + return tagString; + } } \ No newline at end of file diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index f7399473a..bd87bce83 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -5,13 +5,10 @@ import java.io.IOException; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Arrays; +import java.util.*; import java.util.concurrent.TimeUnit; import java.io.File; import java.io.FileNotFoundException; -import java.util.List; -import java.util.Scanner; /** * Represents the list of activities. @@ -113,15 +110,17 @@ private void parseDataLine(String s) { if (!s.isEmpty()) { List strings = Arrays.asList(s.split(",")); - String[] tags; + String[] tagString; + Set tags = new HashSet(); // if there are tags if (strings.size() > 3) { // remove square brackets surrounding tags - // tags = strings.get(3).substring(0,strings.get(3).length() - 1).split(" "); - tags = strings.get(3).split(" "); - } else { - tags = null; + tagString = strings.get(3).substring(0,strings.get(3).length() - 1).split(" "); + tagString = strings.get(3).split(" "); + for (String i : tagString) { + tags.add(i); + } } // strings[0] = name, strings[1] = startDate, string[2] = endDate Activity e = new Activity(strings.get(0), LocalDateTime.parse(strings.get(1)), diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 6ecb055a5..4637e7a32 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -7,11 +7,10 @@ import jikan.exception.NoSuchActivityException; import jikan.ui.Ui; import jikan.Log; -import java.util.ArrayList; -import java.io.IOException; import java.time.LocalDateTime; +import java.util.HashSet; import java.util.Scanner; -import java.util.logging.Level; +import java.util.Set; /** * Represents the object which parses user input to relevant functions for the execution of commands. @@ -21,7 +20,7 @@ public class Parser { protected LocalDateTime startTime = null; protected LocalDateTime endTime = null; private String activityName = null; - private String[] tags = null; + private Set tags = new HashSet(); private Ui ui = new Ui(); protected String[] tokenizedInputs; String instruction; @@ -140,23 +139,26 @@ private void parseFilter(ActivityList activityList, ActivityList lastShownList, String[] keywords = query.split(" "); for (String keyword : keywords) { - for (Activity i : activityList.activities) { - String tagString = ""; - - if (i.getTags() != null) { - for (int j = 0; j < i.getTags().length; j++) { - tagString = tagString + i.getTags()[j] + " "; - } - } - if (tagString.contains(keyword)) { - lastShownList.activities.add(i); - } - } + populateLastShownList(activityList, lastShownList, keyword); } Ui.printResults(lastShownList); } } + /** + * Populates the last shown list with activities that contain tags which match the given keyword + * @param activityList the list of activity to search + * @param lastShownList the last shown list to populate + * @param keyword the keyword to match + */ + private void populateLastShownList(ActivityList activityList, ActivityList lastShownList, String keyword) { + for (Activity i : activityList.activities) { + if (i.getTags().contains(keyword)){ + lastShownList.add(i); + } + } + } + /** Method to parse user inputs that are not recognised. */ private void parseDefault() { String line = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; @@ -171,7 +173,7 @@ public void parseAbort() throws NoSuchActivityException { } else { logger.makeFineLog("Aborted " + activityName); startTime = null; - tags = null; + tags = new HashSet(); activityName = null; String line = "You have aborted the current activity!"; ui.printDivider(line); @@ -188,7 +190,7 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti ui.printDivider(line); } else { // tags should be reset - assert tags == null; + assert tags.isEmpty(); String line; int delimiter = tokenizedInputs[1].indexOf("/t"); @@ -204,7 +206,7 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti throw new EmptyNameException(); } line = "Started: " + activityName; - tags = tokenizedInputs[1].substring(delimiter + 3).split(" "); + parseTags(delimiter); } startTime = LocalDateTime.now(); ui.printDivider(line); @@ -212,6 +214,17 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti logger.makeFineLog("Started: " + activityName); } + /** + * Inserts the tags into the activity object when it has ended. + * @param delimiter the index of the tag delimiter + */ + private void parseTags(int delimiter) { + String[] tagString = tokenizedInputs[1].substring(delimiter + 3).split(" "); + for (String i :tagString) { + tags.add(i); + } + } + /** Method to parse the end activity command. */ public void parseEnd(ActivityList activityList) throws NoSuchActivityException { if (startTime == null) { @@ -224,7 +237,7 @@ public void parseEnd(ActivityList activityList) throws NoSuchActivityException { activityList.add(newActivity); // reset activity info startTime = null; - tags = null; + tags = new HashSet(); } logger.makeFineLog("Ended: " + activityName); } diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 9ad34dc22..41105e65f 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -42,7 +42,8 @@ private static void printTableFormat(ActivityList activityList, int index, boole System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %-100s", index + 1, "|", activityList.get(index).getName(), "|", duration, "|", activityList.get(index).getDate().toString(), "|", - Arrays.toString(activityList.get(index).getTags()))); + activityList.get(index).getTags().toString())); + //Arrays.toString(activityList.get(index).getTags()))); } else { System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %s", index + 1, "|", activityList.get(index).getName(), "|", duration, "|", @@ -57,7 +58,7 @@ public static void printResults(ActivityList lastShownList) { System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); for (int i = 0; i < lastShownList.getSize(); i++) { - if (lastShownList.get(i).getTags() != null && !lastShownList.get(i).getTags()[0].equals("null")) { + if (lastShownList.get(i).getTags() != null && !lastShownList.get(i).getTags().isEmpty()) { printTableFormat(lastShownList, i, true); } else { printTableFormat(lastShownList, i, false); @@ -76,7 +77,7 @@ public static void printList(ActivityList activityList) { System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); for (int i = 0; i < activityList.getSize(); i++) { - if (activityList.get(i).getTags() != null && !activityList.get(i).getTags()[0].equals("null")) { + if (activityList.get(i).getTags() != null && !activityList.get(i).getTags().isEmpty()) { printTableFormat(activityList, i, true); } else { printTableFormat(activityList, i, false); From 86b66144d01f0038df08fe85d4304b8ea4667958 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Thu, 19 Mar 2020 20:09:00 +0800 Subject: [PATCH 069/415] fixed Style issues --- src/main/java/jikan/activity/Activity.java | 3 ++- src/main/java/jikan/activity/ActivityList.java | 8 ++++++-- .../java/jikan/exception/EmptyQueryException.java | 2 +- src/main/java/jikan/parser/Parser.java | 15 ++++++++++----- src/main/java/jikan/ui/Ui.java | 5 ++++- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index bf12945b9..fbbbff134 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -85,7 +85,8 @@ public LocalDate getDate() { public String toData() { // Convert tags to a single space-separated - String tagString = tagsToString(tagString); + String tagString = ""; + tagString = tagsToString(tagString); String dataLine = (this.name + "," + this.startTime + "," + this.endTime + "," + tagString); return dataLine; diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index bd87bce83..b606386a8 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -5,8 +5,12 @@ import java.io.IOException; import java.time.LocalDateTime; -import java.util.*; -import java.util.concurrent.TimeUnit; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Scanner; +import java.util.Set; +import java.util.HashSet; +import java.util.List; import java.io.File; import java.io.FileNotFoundException; diff --git a/src/main/java/jikan/exception/EmptyQueryException.java b/src/main/java/jikan/exception/EmptyQueryException.java index fa3d27802..f6cef53b6 100644 --- a/src/main/java/jikan/exception/EmptyQueryException.java +++ b/src/main/java/jikan/exception/EmptyQueryException.java @@ -1,7 +1,7 @@ package jikan.exception; /** - * An exception that is thrown when the query for find or filter is not provided + * An exception that is thrown when the query for find or filter is not provided. */ public class EmptyQueryException extends Exception { } \ No newline at end of file diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 4637e7a32..3a240bd9b 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -26,6 +26,7 @@ public class Parser { String instruction; Log logger = new Log(); private ActivityList lastShownList = new ActivityList(); + /** * Parses user commands to relevant functions to carry out the commands. * @param scanner scanner object which reads user input @@ -33,7 +34,9 @@ public class Parser { */ public void parseUserCommands(Scanner scanner, ActivityList activityList) { logger.makeInfoLog("Starting to parse inputs."); - //lastShownList is initialised here to facilitate subsequent delete and edit commands referencing by index of this list. + /*lastShownList is initialised here to facilitate subsequent delete and edit commands + referencing by index of this list. + */ lastShownList.activities.addAll(activityList.activities); while (true) { String userInput = scanner.nextLine(); @@ -111,7 +114,8 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { * @param lastShownList the activity list to populate with matching activities only * @param keyword the keyword queried by the user */ - private void parseFind(ActivityList activityList, ActivityList lastShownList, String keyword) throws EmptyQueryException{ + private void parseFind(ActivityList activityList, ActivityList lastShownList, String keyword) + throws EmptyQueryException { if (keyword.length() < 1) { throw new EmptyQueryException(); } else { @@ -131,7 +135,8 @@ private void parseFind(ActivityList activityList, ActivityList lastShownList, St * @param lastShownList the activity list to populate with matching activities only * @param query the keywords queried by the user */ - private void parseFilter(ActivityList activityList, ActivityList lastShownList, String query) throws EmptyQueryException { + private void parseFilter(ActivityList activityList, ActivityList lastShownList, String query) + throws EmptyQueryException { if (query.length() < 1) { throw new EmptyQueryException(); } else { @@ -146,14 +151,14 @@ private void parseFilter(ActivityList activityList, ActivityList lastShownList, } /** - * Populates the last shown list with activities that contain tags which match the given keyword + * Populates the last shown list with activities that contain tags which match the given keyword. * @param activityList the list of activity to search * @param lastShownList the last shown list to populate * @param keyword the keyword to match */ private void populateLastShownList(ActivityList activityList, ActivityList lastShownList, String keyword) { for (Activity i : activityList.activities) { - if (i.getTags().contains(keyword)){ + if (i.getTags().contains(keyword)) { lastShownList.add(i); } } diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 41105e65f..8dabf4731 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -43,7 +43,6 @@ private static void printTableFormat(ActivityList activityList, int index, boole index + 1, "|", activityList.get(index).getName(), "|", duration, "|", activityList.get(index).getDate().toString(), "|", activityList.get(index).getTags().toString())); - //Arrays.toString(activityList.get(index).getTags()))); } else { System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %s", index + 1, "|", activityList.get(index).getName(), "|", duration, "|", @@ -51,6 +50,10 @@ private static void printTableFormat(ActivityList activityList, int index, boole } } + /** + * Prints the results from a 'find' or 'filter' command. + * @param lastShownList the list of activities to print + */ public static void printResults(ActivityList lastShownList) { if (lastShownList.activities.size() > 0) { System.out.println(DIVIDER); From e1465167ed36a52b670017fb8c2d50e87aa9f7f6 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Thu, 19 Mar 2020 20:42:24 +0800 Subject: [PATCH 070/415] Fixed Test Files Type Incompatibility --- src/main/java/jikan/activity/ActivityList.java | 8 ++++---- src/test/java/jikan/activity/ActivityListTest.java | 5 ++++- src/test/java/jikan/activity/ActivityTest.java | 3 ++- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index b606386a8..2397a255d 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -114,15 +114,15 @@ private void parseDataLine(String s) { if (!s.isEmpty()) { List strings = Arrays.asList(s.split(",")); - String[] tagString; + String[] tagStrings; Set tags = new HashSet(); // if there are tags if (strings.size() > 3) { // remove square brackets surrounding tags - tagString = strings.get(3).substring(0,strings.get(3).length() - 1).split(" "); - tagString = strings.get(3).split(" "); - for (String i : tagString) { + tagStrings = strings.get(3).substring(0,strings.get(3).length() - 1).split(" "); + tagStrings = strings.get(3).split(" "); + for (String i : tagStrings) { tags.add(i); } } diff --git a/src/test/java/jikan/activity/ActivityListTest.java b/src/test/java/jikan/activity/ActivityListTest.java index a9f8dbea6..af0d473fe 100644 --- a/src/test/java/jikan/activity/ActivityListTest.java +++ b/src/test/java/jikan/activity/ActivityListTest.java @@ -4,6 +4,7 @@ import org.junit.jupiter.api.Test; import java.time.LocalDateTime; +import java.util.HashSet; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -13,7 +14,9 @@ class ActivityListTest { void getIndex() { ActivityList activities = new ActivityList(); activities.storage = new Storage("data/activityList_test.txt"); - String[] tags = {"tag1", "tag2"}; + HashSet tags = new HashSet(); + tags.add("tag1"); + tags.add("tag2"); Activity activity1 = new Activity("Activity1", LocalDateTime.parse("2020-01-01T08:00:00"), LocalDateTime.parse("2020-01-01T10:00:00"), tags); Activity activity2 = new Activity("Activity2", LocalDateTime.parse("2020-01-01T10:00:00"), diff --git a/src/test/java/jikan/activity/ActivityTest.java b/src/test/java/jikan/activity/ActivityTest.java index b560d9905..0e4f32d72 100644 --- a/src/test/java/jikan/activity/ActivityTest.java +++ b/src/test/java/jikan/activity/ActivityTest.java @@ -3,12 +3,13 @@ import org.junit.jupiter.api.Test; import java.time.LocalDateTime; +import java.util.HashSet; import static org.junit.jupiter.api.Assertions.assertEquals; class ActivityTest { - String[] tags = {"tag1", "tag2"}; + HashSet tags = new HashSet(); Activity activity = new Activity("Activity", LocalDateTime.parse("2020-01-01T08:00:00"), LocalDateTime.parse("2020-01-01T10:00:00"), tags); From 5977f52b820d4cb9aa11088142dc16c7c245e997 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Thu, 19 Mar 2020 20:49:52 +0800 Subject: [PATCH 071/415] added comment --- src/test/java/jikan/activity/ActivityTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/jikan/activity/ActivityTest.java b/src/test/java/jikan/activity/ActivityTest.java index 0e4f32d72..03131876f 100644 --- a/src/test/java/jikan/activity/ActivityTest.java +++ b/src/test/java/jikan/activity/ActivityTest.java @@ -10,6 +10,7 @@ class ActivityTest { HashSet tags = new HashSet(); + //the tags is empty here as adding needs to be done in a method. Activity activity = new Activity("Activity", LocalDateTime.parse("2020-01-01T08:00:00"), LocalDateTime.parse("2020-01-01T10:00:00"), tags); From c84d871569060c38b550ffdd0146980ba22be771 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Thu, 19 Mar 2020 21:06:41 +0800 Subject: [PATCH 072/415] Fixed Filter error --- src/main/java/jikan/parser/Parser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 3a240bd9b..92f9fe958 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -159,7 +159,7 @@ private void parseFilter(ActivityList activityList, ActivityList lastShownList, private void populateLastShownList(ActivityList activityList, ActivityList lastShownList, String keyword) { for (Activity i : activityList.activities) { if (i.getTags().contains(keyword)) { - lastShownList.add(i); + lastShownList.activities.add(i); } } } From 2fedef35386f052bcb20a3aca5884183ffba4478 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Thu, 19 Mar 2020 21:12:29 +0800 Subject: [PATCH 073/415] Update Parser.java --- src/main/java/jikan/parser/Parser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 92f9fe958..a26448169 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -158,7 +158,7 @@ private void parseFilter(ActivityList activityList, ActivityList lastShownList, */ private void populateLastShownList(ActivityList activityList, ActivityList lastShownList, String keyword) { for (Activity i : activityList.activities) { - if (i.getTags().contains(keyword)) { + if (!lastShownList.activities.contains(i) && i.getTags().contains(keyword)) { lastShownList.activities.add(i); } } From 64523c084e1d6b497ef8d135089d6232a0a44037 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Thu, 19 Mar 2020 21:14:00 +0800 Subject: [PATCH 074/415] Remove duplicate entries for filtering multiple tags --- src/main/java/jikan/parser/Parser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 92f9fe958..a26448169 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -158,7 +158,7 @@ private void parseFilter(ActivityList activityList, ActivityList lastShownList, */ private void populateLastShownList(ActivityList activityList, ActivityList lastShownList, String keyword) { for (Activity i : activityList.activities) { - if (i.getTags().contains(keyword)) { + if (!lastShownList.activities.contains(i) && i.getTags().contains(keyword)) { lastShownList.activities.add(i); } } From 3dc215d2f1cb9bb6bf8158a872989cd5fc93cb1e Mon Sep 17 00:00:00 2001 From: rdimaio Date: Fri, 20 Mar 2020 00:05:39 +0800 Subject: [PATCH 075/415] Add InvalidTimeFrameException --- src/main/java/jikan/activity/Activity.java | 32 +++++----- .../exception/InvalidTimeFrameException.java | 7 +++ src/main/java/jikan/parser/Parser.java | 61 ++++++++++++++++++- 3 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 src/main/java/jikan/exception/InvalidTimeFrameException.java diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index fbbbff134..a184f926e 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -1,5 +1,7 @@ package jikan.activity; +import jikan.exception.InvalidTimeFrameException; + import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; @@ -26,7 +28,13 @@ public class Activity { * @param tags activity tags * @param endTime the time that the activity ended */ - public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Set tags) { + public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Set tags) + throws InvalidTimeFrameException { + + if (endTime.isBefore(startTime)) { + throw new InvalidTimeFrameException(); + } + this.name = name.strip(); this.startTime = startTime; this.tags = tags; @@ -35,20 +43,6 @@ public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Set this.date = endTime.toLocalDate(); } - /** - * Constructor to create activity when endTime is previously known - * (i.e. when loading from jikan.storage) - * - * @param name Name of activity. - * @param startTime Time at which activity started. - * @param endTime Time at which activity ended. - */ - public Activity(String name, LocalDateTime startTime, LocalDateTime endTime) { - this.name = name; - this.startTime = startTime; - this.endTime = endTime; - } - /** * Ends an ongoing activity and updates the total time spent on the activity. * @param endTime date and time when the activity ended @@ -75,6 +69,14 @@ public LocalDate getDate() { return date; } + public LocalDateTime getStartTime() { + return startTime; + } + + public LocalDateTime getEndTime() { + return endTime; + } + /** * Converts the jikan.activity.Activity object to data representation to be stored in a data file. * File format: diff --git a/src/main/java/jikan/exception/InvalidTimeFrameException.java b/src/main/java/jikan/exception/InvalidTimeFrameException.java new file mode 100644 index 000000000..2ad7eb7d5 --- /dev/null +++ b/src/main/java/jikan/exception/InvalidTimeFrameException.java @@ -0,0 +1,7 @@ +package jikan.exception; + +/** + * An exception that is thrown when the time frame is invalid (e.g., the end time comes before the start time) + */ +public class InvalidTimeFrameException extends Exception { +} diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index a26448169..4860d2be3 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -4,10 +4,12 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.exception.EmptyQueryException; +import jikan.exception.InvalidTimeFrameException; import jikan.exception.NoSuchActivityException; import jikan.ui.Ui; import jikan.Log; import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.HashSet; import java.util.Scanner; import java.util.Set; @@ -70,7 +72,12 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { } break; case "list": - ui.printList(activityList); + try { + parseList(activityList); + } catch (InvalidTimeDate e) { + logger.makeInfoLog("Specified time range not valid"); + ui.printDivider("The time range specified is not valid."); + } break; case "abort": try { @@ -254,4 +261,54 @@ public void parseDelete(ActivityList activityList) { ui.printDivider(line); activityList.delete(index); } -} + + /** + * Parse a list command. The user can specify either a single date or a specific time frame. + * + * @param activityList The activity list to search for matching activities. + */ + private void parseList(ActivityList activityList) throws InvalidTimeFrameException { + + // If no time frame is specified, print the entire list + if (tokenizedInputs.length == 1) { + lastShownList.activities.clear(); + ui.printList(activityList); + lastShownList = activityList; + return; + } + + // parse both formats (use optional section, delimited by []) + DateTimeFormatter parser = DateTimeFormatter.ofPattern("[dd/MM/yyyy][yyyy-MM-dd'T'HH:mm:ss]"); + + // Only one date is specified; return all entries with start date coinciding with that date + if (tokenizedInputs.length == 2) { + + // Read from activityList + // Update lastShownList + // Clear lastShownList + lastShownList.activities.clear(); + for (Activity i : activityList.activities) { + // If startTime is in the range, then activity + LocalDateTime startTime = i.getStartTime(); + if (i.getName().contains(keyword)) { + lastShownList.activities.add(i); + } + } + } + } + + private void parseFind(ActivityList activityList, ActivityList lastShownList, String keyword) + throws EmptyQueryException { + if (keyword.length() < 1) { + throw new EmptyQueryException(); + } else { + lastShownList.activities.clear(); + for (Activity i : activityList.activities) { + if (i.getName().contains(keyword)) { + lastShownList.activities.add(i); + } + } + Ui.printResults(lastShownList); + } + } +} \ No newline at end of file From cb29b4230d5ecfd6cd7a84462d6c80329b7fe08b Mon Sep 17 00:00:00 2001 From: rdimaio Date: Fri, 20 Mar 2020 00:25:57 +0800 Subject: [PATCH 076/415] Add parseList --- src/main/java/jikan/activity/Activity.java | 14 ++++++ .../java/jikan/activity/ActivityList.java | 10 +++- src/main/java/jikan/parser/Parser.java | 46 +++++++++---------- 3 files changed, 45 insertions(+), 25 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index a184f926e..4e11764a4 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -77,6 +77,20 @@ public LocalDateTime getEndTime() { return endTime; } + /** + * Returns true if the Activity's date is within the date range specified (inclusive). + * + * @param startDate Start date of range + * @param endDate End date of range + * @return True if Activity is within date range; false otherwise + */ + public boolean isWithinDateFrame(LocalDate startDate, LocalDate endDate) { + if (!this.date.isBefore(startDate) && !this.date.isAfter (endDate)) { + return true; + } + return false; + } + /** * Converts the jikan.activity.Activity object to data representation to be stored in a data file. * File format: diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 2397a255d..71c3ac2e8 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -1,5 +1,6 @@ package jikan.activity; +import jikan.exception.InvalidTimeFrameException; import jikan.storage.Storage; import jikan.storage.StorageHandler; @@ -127,8 +128,13 @@ private void parseDataLine(String s) { } } // strings[0] = name, strings[1] = startDate, string[2] = endDate - Activity e = new Activity(strings.get(0), LocalDateTime.parse(strings.get(1)), - LocalDateTime.parse(strings.get(2)), tags); + Activity e = null; + try { + e = new Activity(strings.get(0), LocalDateTime.parse(strings.get(1)), + LocalDateTime.parse(strings.get(2)), tags); + } catch (InvalidTimeFrameException ex) { + ex.printStackTrace(); + } activities.add(e); } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 4860d2be3..b6c75c7f3 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -8,6 +8,8 @@ import jikan.exception.NoSuchActivityException; import jikan.ui.Ui; import jikan.Log; + +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.HashSet; @@ -69,12 +71,15 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { } catch (NoSuchActivityException e) { logger.makeInfoLog("End command failed as no activity was ongoing"); ui.printDivider("You have not started any activity!"); + } catch (InvalidTimeFrameException e) { + logger.makeInfoLog("End date must be before start date"); + ui.printDivider("End date must be before start date."); } break; case "list": try { parseList(activityList); - } catch (InvalidTimeDate e) { + } catch (InvalidTimeFrameException e) { logger.makeInfoLog("Specified time range not valid"); ui.printDivider("The time range specified is not valid."); } @@ -238,7 +243,7 @@ private void parseTags(int delimiter) { } /** Method to parse the end activity command. */ - public void parseEnd(ActivityList activityList) throws NoSuchActivityException { + public void parseEnd(ActivityList activityList) throws NoSuchActivityException, InvalidTimeFrameException { if (startTime == null) { throw new NoSuchActivityException(); } else { @@ -277,38 +282,33 @@ private void parseList(ActivityList activityList) throws InvalidTimeFrameExcepti return; } - // parse both formats (use optional section, delimited by []) - DateTimeFormatter parser = DateTimeFormatter.ofPattern("[dd/MM/yyyy][yyyy-MM-dd'T'HH:mm:ss]"); + lastShownList.activities.clear(); + + // Parse either format + DateTimeFormatter parser = DateTimeFormatter.ofPattern("[dd/MM/yyyy][yyyy-MM-dd]"); + + LocalDate startDate = LocalDate.parse(tokenizedInputs[1], parser); // Only one date is specified; return all entries with start date coinciding with that date if (tokenizedInputs.length == 2) { - - // Read from activityList - // Update lastShownList - // Clear lastShownList - lastShownList.activities.clear(); for (Activity i : activityList.activities) { - // If startTime is in the range, then activity - LocalDateTime startTime = i.getStartTime(); - if (i.getName().contains(keyword)) { + if (i.getDate().equals(startDate)) { lastShownList.activities.add(i); } } - } - } - - private void parseFind(ActivityList activityList, ActivityList lastShownList, String keyword) - throws EmptyQueryException { - if (keyword.length() < 1) { - throw new EmptyQueryException(); - } else { - lastShownList.activities.clear(); + ui.printList(lastShownList); + // Both start and end dates are specified + } else if (tokenizedInputs.length == 3) { + LocalDate endDate = LocalDate.parse(tokenizedInputs[2], parser); for (Activity i : activityList.activities) { - if (i.getName().contains(keyword)) { + if (i.isWithinDateFrame(startDate, endDate)) { lastShownList.activities.add(i); } } - Ui.printResults(lastShownList); + ui.printList(lastShownList); + } else { + throw new InvalidTimeFrameException(); } + } } \ No newline at end of file From 3f45cedddc72067039a74e383ab5f813969d8d9d Mon Sep 17 00:00:00 2001 From: rdimaio Date: Fri, 20 Mar 2020 00:52:27 +0800 Subject: [PATCH 077/415] Complete all cases for parseList --- src/main/java/jikan/parser/Parser.java | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index b6c75c7f3..a46ca5290 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -12,6 +12,7 @@ import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.HashSet; import java.util.Scanner; import java.util.Set; @@ -44,7 +45,7 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { lastShownList.activities.addAll(activityList.activities); while (true) { String userInput = scanner.nextLine(); - tokenizedInputs = userInput.split(" ", 2); + tokenizedInputs = userInput.split(" ", 3); instruction = tokenizedInputs[0]; switch (instruction) { @@ -82,6 +83,9 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { } catch (InvalidTimeFrameException e) { logger.makeInfoLog("Specified time range not valid"); ui.printDivider("The time range specified is not valid."); + } catch (DateTimeParseException e) { + logger.makeInfoLog("Specified time range was not in the valid format"); + ui.printDivider("Please input your dates as either yyyy-MM-dd or dd/MM/yyyy."); } break; case "abort": @@ -272,13 +276,17 @@ public void parseDelete(ActivityList activityList) { * * @param activityList The activity list to search for matching activities. */ - private void parseList(ActivityList activityList) throws InvalidTimeFrameException { + private void parseList(ActivityList activityList) throws InvalidTimeFrameException, DateTimeParseException { // If no time frame is specified, print the entire list if (tokenizedInputs.length == 1) { lastShownList.activities.clear(); ui.printList(activityList); - lastShownList = activityList; + + // Can't do lastShownList = activityList, otherwise we just copy + for (Activity i : activityList.activities) { + lastShownList.activities.add(i); + } return; } @@ -286,7 +294,6 @@ private void parseList(ActivityList activityList) throws InvalidTimeFrameExcepti // Parse either format DateTimeFormatter parser = DateTimeFormatter.ofPattern("[dd/MM/yyyy][yyyy-MM-dd]"); - LocalDate startDate = LocalDate.parse(tokenizedInputs[1], parser); // Only one date is specified; return all entries with start date coinciding with that date @@ -300,6 +307,11 @@ private void parseList(ActivityList activityList) throws InvalidTimeFrameExcepti // Both start and end dates are specified } else if (tokenizedInputs.length == 3) { LocalDate endDate = LocalDate.parse(tokenizedInputs[2], parser); + + if (endDate.isBefore(startDate)) { + throw new InvalidTimeFrameException(); + } + for (Activity i : activityList.activities) { if (i.isWithinDateFrame(startDate, endDate)) { lastShownList.activities.add(i); From d8a50d00ec61a527e95104db074a3bcdc6d91b37 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Fri, 20 Mar 2020 00:54:34 +0800 Subject: [PATCH 078/415] Fix style check --- src/main/java/jikan/activity/Activity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 4e11764a4..bea397566 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -85,7 +85,7 @@ public LocalDateTime getEndTime() { * @return True if Activity is within date range; false otherwise */ public boolean isWithinDateFrame(LocalDate startDate, LocalDate endDate) { - if (!this.date.isBefore(startDate) && !this.date.isAfter (endDate)) { + if (!this.date.isBefore(startDate) && !this.date.isAfter(endDate)) { return true; } return false; From 07ca78691bd001a53edd40f665b38b3ae6354a89 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Fri, 20 Mar 2020 00:58:55 +0800 Subject: [PATCH 079/415] Add InvalidTimeFrameException in test --- src/test/java/jikan/activity/ActivityListTest.java | 3 ++- src/test/java/jikan/activity/ActivityTest.java | 13 +++++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/test/java/jikan/activity/ActivityListTest.java b/src/test/java/jikan/activity/ActivityListTest.java index af0d473fe..8955995c7 100644 --- a/src/test/java/jikan/activity/ActivityListTest.java +++ b/src/test/java/jikan/activity/ActivityListTest.java @@ -1,5 +1,6 @@ package jikan.activity; +import jikan.exception.InvalidTimeFrameException; import jikan.storage.Storage; import org.junit.jupiter.api.Test; @@ -11,7 +12,7 @@ class ActivityListTest { @Test - void getIndex() { + void getIndex() throws InvalidTimeFrameException { ActivityList activities = new ActivityList(); activities.storage = new Storage("data/activityList_test.txt"); HashSet tags = new HashSet(); diff --git a/src/test/java/jikan/activity/ActivityTest.java b/src/test/java/jikan/activity/ActivityTest.java index 03131876f..1a2d05d7c 100644 --- a/src/test/java/jikan/activity/ActivityTest.java +++ b/src/test/java/jikan/activity/ActivityTest.java @@ -1,5 +1,6 @@ package jikan.activity; +import jikan.exception.InvalidTimeFrameException; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; @@ -11,8 +12,16 @@ class ActivityTest { HashSet tags = new HashSet(); //the tags is empty here as adding needs to be done in a method. - Activity activity = new Activity("Activity", LocalDateTime.parse("2020-01-01T08:00:00"), - LocalDateTime.parse("2020-01-01T10:00:00"), tags); + Activity activity; + + { + try { + activity = new Activity("Activity", LocalDateTime.parse("2020-01-01T08:00:00"), + LocalDateTime.parse("2020-01-01T10:00:00"), tags); + } catch (InvalidTimeFrameException e) { + e.printStackTrace(); + } + } @Test void getDuration() { From 84c3abca0baa4e63837bf0c3213cd70328e57290 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Fri, 20 Mar 2020 01:01:05 +0800 Subject: [PATCH 080/415] Add InvalidTimeFrameException in test --- src/test/java/jikan/parser/ParserTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/jikan/parser/ParserTest.java b/src/test/java/jikan/parser/ParserTest.java index f7669d7b5..07fc0dae2 100644 --- a/src/test/java/jikan/parser/ParserTest.java +++ b/src/test/java/jikan/parser/ParserTest.java @@ -1,6 +1,7 @@ package jikan.parser; import jikan.activity.ActivityList; +import jikan.exception.InvalidTimeFrameException; import jikan.ui.Ui; import jikan.exception.NoSuchActivityException; import jikan.storage.Storage; @@ -18,7 +19,7 @@ class ParserTest { ActivityList activityList = new ActivityList(); @Test - void parseEnd() throws NoSuchActivityException { + void parseEnd() throws NoSuchActivityException, InvalidTimeFrameException { try { parser.startTime = null; parser.parseEnd(activityList); From ace1828d6c316b2b17548be7ec46e73bac779efe Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 21 Mar 2020 11:54:45 +0800 Subject: [PATCH 081/415] Add continue command --- src/main/java/jikan/activity/Activity.java | 14 +++----- .../java/jikan/activity/ActivityList.java | 14 ++++++++ src/main/java/jikan/parser/Parser.java | 32 ++++++++++++++++++- 3 files changed, 49 insertions(+), 11 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index bea397566..e17253592 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -43,20 +43,14 @@ public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Set this.date = endTime.toLocalDate(); } - /** - * Ends an ongoing activity and updates the total time spent on the activity. - * @param endTime date and time when the activity ended - * @return a confirmation message that the tracking of the activity has ended - */ - public String endActivity(LocalDateTime endTime) { - this.endTime = endTime; - return ("You have ended " + this.name + " . Great job !\n"); - } - public Duration getDuration() { return duration; } + public void setDuration(Duration duration) { + this.duration = duration; + } + public String getName() { return name; } diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 71c3ac2e8..eb3bc7535 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -5,6 +5,7 @@ import jikan.storage.StorageHandler; import java.io.IOException; +import java.time.Duration; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.Arrays; @@ -59,6 +60,19 @@ public void add(Activity activity) { updateFile(dataLine); } + public void updateDuration(Duration duration, int index) { + activities.get(index).setDuration(duration); + } + + public int findActivity(String name) { + for (int i = 0; i < activities.size(); i++) { + if(activities.get(i).getName().equals(name)) { + return i; + } + } + return -1; + } + /** * Updates data file with new task. * diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index a46ca5290..b6aa0baa8 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -9,6 +9,7 @@ import jikan.ui.Ui; import jikan.Log; +import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; @@ -32,6 +33,9 @@ public class Parser { Log logger = new Log(); private ActivityList lastShownList = new ActivityList(); + // flag to check if the current activity is a continued one + public int continuedIndex = -1; + /** * Parses user commands to relevant functions to carry out the commands. * @param scanner scanner object which reads user input @@ -45,7 +49,7 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { lastShownList.activities.addAll(activityList.activities); while (true) { String userInput = scanner.nextLine(); - tokenizedInputs = userInput.split(" ", 3); + tokenizedInputs = userInput.split(" ", 2); instruction = tokenizedInputs[0]; switch (instruction) { @@ -117,6 +121,9 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { ui.printDivider("No keyword was given."); } break; + case "continue": + parseContinue(activityList); + break; default: parseDefault(); break; @@ -250,6 +257,15 @@ private void parseTags(int delimiter) { public void parseEnd(ActivityList activityList) throws NoSuchActivityException, InvalidTimeFrameException { if (startTime == null) { throw new NoSuchActivityException(); + } else if (continuedIndex != -1) { + String line = "Ended: " + activityName; + ui.printDivider(line); + endTime = LocalDateTime.now(); + Duration duration = Duration.between(startTime, endTime); + Duration oldDuration = activityList.get(continuedIndex).getDuration(); + Duration newDuration = duration.plus(oldDuration); + activityList.updateDuration(newDuration, continuedIndex); + continuedIndex = -1; } else { String line = "Ended: " + activityName; ui.printDivider(line); @@ -271,6 +287,20 @@ public void parseDelete(ActivityList activityList) { activityList.delete(index); } + public void parseContinue(ActivityList activityList) { + int index = activityList.findActivity(tokenizedInputs[1]); + if (index != -1) { + // activity is found + activityName = activityList.get(index).getName(); + startTime = LocalDateTime.now(); + tags = activityList.get(index).getTags(); + continuedIndex = index; + } else { + // activity not found + System.out.println("No such activity is found!"); + } + } + /** * Parse a list command. The user can specify either a single date or a specific time frame. * From 017439b769e37434f8f99a50f6dfa2c29ecc1777 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 21 Mar 2020 12:23:26 +0800 Subject: [PATCH 082/415] Check for duplicate activity name --- .../java/jikan/activity/ActivityList.java | 3 +- src/main/java/jikan/parser/Parser.java | 63 +++++++++++-------- 2 files changed, 39 insertions(+), 27 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index eb3bc7535..99c89296d 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -62,6 +62,7 @@ public void add(Activity activity) { public void updateDuration(Duration duration, int index) { activities.get(index).setDuration(duration); + } public int findActivity(String name) { @@ -95,7 +96,7 @@ private void deleteUpdateFile(int index) { try { StorageHandler.removeLine(index, storage); } catch (IOException e) { - System.out.println("Error while deleting task from data file."); + System.out.println("Error while deleting activity from data file."); } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index b6aa0baa8..630bc24d1 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -58,7 +58,7 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { break; case "start": try { - parseStart(); + parseStart(activityList); } catch (EmptyNameException e) { logger.makeInfoLog("Activity started without task name"); ui.printDivider("Task name cannot be empty!"); @@ -200,9 +200,7 @@ public void parseAbort() throws NoSuchActivityException { throw new NoSuchActivityException(); } else { logger.makeFineLog("Aborted " + activityName); - startTime = null; - tags = new HashSet(); - activityName = null; + resetInfo(); String line = "You have aborted the current activity!"; ui.printDivider(line); } @@ -210,7 +208,7 @@ public void parseAbort() throws NoSuchActivityException { } /** Method to parse the start activity command. */ - public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameException, NullPointerException { + public void parseStart(ActivityList activityList) throws ArrayIndexOutOfBoundsException, EmptyNameException, NullPointerException { // check if an activity has already been started if (startTime != null) { String line = activityName + " is ongoing!"; @@ -221,36 +219,41 @@ public void parseStart() throws ArrayIndexOutOfBoundsException, EmptyNameExcepti assert tags.isEmpty(); String line; - int delimiter = tokenizedInputs[1].indexOf("/t"); - if (delimiter == -1) { - activityName = tokenizedInputs[1]; - if (activityName.equals("")) { - throw new EmptyNameException(); - } - line = "Started: " + activityName; + // check if there exists an activity with this name + if (activityList.findActivity(tokenizedInputs[1]) != -1) { + line = "There is already an activity with this name."; } else { - activityName = tokenizedInputs[1].substring(0, delimiter); - if (activityName.equals("")) { - throw new EmptyNameException(); - } - line = "Started: " + activityName; - parseTags(delimiter); + int delimiter = tokenizedInputs[1].indexOf("/t"); + line = parseActivity(delimiter); + startTime = LocalDateTime.now(); + logger.makeFineLog("Started: " + activityName); } - startTime = LocalDateTime.now(); ui.printDivider(line); } - logger.makeFineLog("Started: " + activityName); } /** * Inserts the tags into the activity object when it has ended. * @param delimiter the index of the tag delimiter */ - private void parseTags(int delimiter) { - String[] tagString = tokenizedInputs[1].substring(delimiter + 3).split(" "); - for (String i :tagString) { - tags.add(i); + private String parseActivity(int delimiter) throws EmptyNameException { + if(delimiter == -1) { + // no tags + activityName = tokenizedInputs[1]; + if (activityName.isEmpty()) { + throw new EmptyNameException(); + } + } else { + activityName = tokenizedInputs[1].substring(0, delimiter); + if (activityName.isEmpty()) { + throw new EmptyNameException(); + } + String[] tagString = tokenizedInputs[1].substring(delimiter + 3).split(" "); + for (String i : tagString) { + tags.add(i); + } } + return "Started: " + activityName; } /** Method to parse the end activity command. */ @@ -266,6 +269,7 @@ public void parseEnd(ActivityList activityList) throws NoSuchActivityException, Duration newDuration = duration.plus(oldDuration); activityList.updateDuration(newDuration, continuedIndex); continuedIndex = -1; + resetInfo(); } else { String line = "Ended: " + activityName; ui.printDivider(line); @@ -273,12 +277,17 @@ public void parseEnd(ActivityList activityList) throws NoSuchActivityException, Activity newActivity = new Activity(activityName, startTime, endTime, tags); activityList.add(newActivity); // reset activity info - startTime = null; - tags = new HashSet(); + resetInfo(); } logger.makeFineLog("Ended: " + activityName); } + public void resetInfo() { + startTime = null; + activityName = null; + tags = new HashSet<>(); + } + /** Deletes an activity from the activity list. */ public void parseDelete(ActivityList activityList) { int index = Integer.parseInt(tokenizedInputs[1]) - 1; @@ -295,6 +304,8 @@ public void parseContinue(ActivityList activityList) { startTime = LocalDateTime.now(); tags = activityList.get(index).getTags(); continuedIndex = index; + String line = activityName + " was continued"; + ui.printDivider(line); } else { // activity not found System.out.println("No such activity is found!"); From 79ddecc7cfc18f8c34022d461288788c797c32c8 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 21 Mar 2020 13:00:33 +0800 Subject: [PATCH 083/415] Add storage handler for continue --- src/main/java/jikan/activity/Activity.java | 13 +++++++--- .../java/jikan/activity/ActivityList.java | 25 +++++++++++++------ src/main/java/jikan/parser/Parser.java | 5 ++-- .../java/jikan/storage/StorageHandler.java | 11 ++++++++ 4 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index e17253592..5b27cdf1d 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -28,8 +28,8 @@ public class Activity { * @param tags activity tags * @param endTime the time that the activity ended */ - public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Set tags) - throws InvalidTimeFrameException { + public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Duration duration, + Set tags) throws InvalidTimeFrameException { if (endTime.isBefore(startTime)) { throw new InvalidTimeFrameException(); @@ -39,7 +39,7 @@ public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Set this.startTime = startTime; this.tags = tags; this.endTime = endTime; - this.duration = Duration.between(startTime, endTime); + this.duration = duration; this.date = endTime.toLocalDate(); } @@ -71,6 +71,10 @@ public LocalDateTime getEndTime() { return endTime; } + public void setEndTime(LocalDateTime endTime) { + this.endTime = endTime; + } + /** * Returns true if the Activity's date is within the date range specified (inclusive). * @@ -98,7 +102,8 @@ public String toData() { String tagString = ""; tagString = tagsToString(tagString); - String dataLine = (this.name + "," + this.startTime + "," + this.endTime + "," + tagString); + String dataLine = (this.name + "," + this.startTime + "," + this.endTime + "," + + this.duration.toString() + "," + tagString); return dataLine; } diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 99c89296d..a7e19eef7 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -60,9 +60,10 @@ public void add(Activity activity) { updateFile(dataLine); } - public void updateDuration(Duration duration, int index) { + public void updateDuration(Duration duration, LocalDateTime endTime, int index) { activities.get(index).setDuration(duration); - + activities.get(index).setEndTime(endTime); + fieldChangeUpdateFile(); } public int findActivity(String name) { @@ -100,6 +101,14 @@ private void deleteUpdateFile(int index) { } } + private void fieldChangeUpdateFile() { + try { + StorageHandler.updateField(activities, storage); + } catch (IOException e) { + System.out.println("Error while deleting activity from data file."); + } + } + public int getSize() { return activities.size(); } @@ -134,10 +143,10 @@ private void parseDataLine(String s) { Set tags = new HashSet(); // if there are tags - if (strings.size() > 3) { + if (strings.size() > 4) { // remove square brackets surrounding tags - tagStrings = strings.get(3).substring(0,strings.get(3).length() - 1).split(" "); - tagStrings = strings.get(3).split(" "); + tagStrings = strings.get(4).substring(0,strings.get(4).length() - 1).split(" "); + tagStrings = strings.get(4).split(" "); for (String i : tagStrings) { tags.add(i); } @@ -145,8 +154,10 @@ private void parseDataLine(String s) { // strings[0] = name, strings[1] = startDate, string[2] = endDate Activity e = null; try { - e = new Activity(strings.get(0), LocalDateTime.parse(strings.get(1)), - LocalDateTime.parse(strings.get(2)), tags); + LocalDateTime startTime = LocalDateTime.parse(strings.get(1)); + LocalDateTime endTime = LocalDateTime.parse(strings.get(2)); + Duration duration = Duration.parse(strings.get(3)); + e = new Activity(strings.get(0), startTime, endTime, duration, tags); } catch (InvalidTimeFrameException ex) { ex.printStackTrace(); } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 630bc24d1..c79e33ae5 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -267,14 +267,15 @@ public void parseEnd(ActivityList activityList) throws NoSuchActivityException, Duration duration = Duration.between(startTime, endTime); Duration oldDuration = activityList.get(continuedIndex).getDuration(); Duration newDuration = duration.plus(oldDuration); - activityList.updateDuration(newDuration, continuedIndex); + activityList.updateDuration(newDuration, endTime, continuedIndex); continuedIndex = -1; resetInfo(); } else { String line = "Ended: " + activityName; ui.printDivider(line); endTime = LocalDateTime.now(); - Activity newActivity = new Activity(activityName, startTime, endTime, tags); + Duration duration = Duration.between(startTime, endTime); + Activity newActivity = new Activity(activityName, startTime, endTime, duration, tags); activityList.add(newActivity); // reset activity info resetInfo(); diff --git a/src/main/java/jikan/storage/StorageHandler.java b/src/main/java/jikan/storage/StorageHandler.java index 85e2f1dd6..eb26d2922 100644 --- a/src/main/java/jikan/storage/StorageHandler.java +++ b/src/main/java/jikan/storage/StorageHandler.java @@ -1,5 +1,8 @@ package jikan.storage; +import jikan.activity.Activity; +import jikan.activity.ActivityList; + import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -47,6 +50,14 @@ public static void removeLine(int lineNumber, Storage storage) throws IOExceptio */ } + public static void updateField(ArrayList activities, Storage storage) throws IOException { + List fileContent = new ArrayList<>(); + for (Activity a : activities) { + fileContent.add(a.toData()); + } + saveNewList(fileContent, storage.dataFile); + } + /** * Saves a the updated activity list to the csv file. * From db735dd7ef6089d4537b536cc869cf692b5d7143 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 21 Mar 2020 13:10:50 +0800 Subject: [PATCH 084/415] Option to continue activity with same name --- src/main/java/jikan/parser/Parser.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index c79e33ae5..36a63cbe9 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -58,7 +58,7 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { break; case "start": try { - parseStart(activityList); + parseStart(activityList, scanner); } catch (EmptyNameException e) { logger.makeInfoLog("Activity started without task name"); ui.printDivider("Task name cannot be empty!"); @@ -208,7 +208,7 @@ public void parseAbort() throws NoSuchActivityException { } /** Method to parse the start activity command. */ - public void parseStart(ActivityList activityList) throws ArrayIndexOutOfBoundsException, EmptyNameException, NullPointerException { + public void parseStart(ActivityList activityList, Scanner scanner) throws ArrayIndexOutOfBoundsException, EmptyNameException, NullPointerException { // check if an activity has already been started if (startTime != null) { String line = activityName + " is ongoing!"; @@ -221,13 +221,26 @@ public void parseStart(ActivityList activityList) throws ArrayIndexOutOfBoundsEx String line; // check if there exists an activity with this name if (activityList.findActivity(tokenizedInputs[1]) != -1) { - line = "There is already an activity with this name."; + line = "There is already an activity with this name. Would you like to continue it?"; + ui.printDivider(line); + continueActivity(activityList, scanner); } else { int delimiter = tokenizedInputs[1].indexOf("/t"); line = parseActivity(delimiter); startTime = LocalDateTime.now(); logger.makeFineLog("Started: " + activityName); + ui.printDivider(line); } + } + } + + private void continueActivity(ActivityList activityList, Scanner scanner) { + String line; + String userInput = scanner.nextLine(); + if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { + parseContinue(activityList); + } else { + line = "Okay then, what else can I do for you?"; ui.printDivider(line); } } From 90664afa8c3cca6e40b969b50108d351e1b2712b Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 21 Mar 2020 13:28:20 +0800 Subject: [PATCH 085/415] Add option to save ongoing activity before exit --- src/main/java/jikan/activity/Activity.java | 6 +- .../java/jikan/activity/ActivityList.java | 12 ++-- src/main/java/jikan/parser/Parser.java | 62 +++++++++++++------ 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 5b27cdf1d..0e884215c 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -29,11 +29,7 @@ public class Activity { * @param endTime the time that the activity ended */ public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Duration duration, - Set tags) throws InvalidTimeFrameException { - - if (endTime.isBefore(startTime)) { - throw new InvalidTimeFrameException(); - } + Set tags) { this.name = name.strip(); this.startTime = startTime; diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index a7e19eef7..787645b9d 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -153,14 +153,10 @@ private void parseDataLine(String s) { } // strings[0] = name, strings[1] = startDate, string[2] = endDate Activity e = null; - try { - LocalDateTime startTime = LocalDateTime.parse(strings.get(1)); - LocalDateTime endTime = LocalDateTime.parse(strings.get(2)); - Duration duration = Duration.parse(strings.get(3)); - e = new Activity(strings.get(0), startTime, endTime, duration, tags); - } catch (InvalidTimeFrameException ex) { - ex.printStackTrace(); - } + LocalDateTime startTime = LocalDateTime.parse(strings.get(1)); + LocalDateTime endTime = LocalDateTime.parse(strings.get(2)); + Duration duration = Duration.parse(strings.get(3)); + e = new Activity(strings.get(0), startTime, endTime, duration, tags); activities.add(e); } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 36a63cbe9..b2b1339d8 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -54,7 +54,8 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { switch (instruction) { case "bye": - ui.exitFromApp(); + //ui.exitFromApp(); + parseBye(activityList, scanner); break; case "start": try { @@ -207,6 +208,46 @@ public void parseAbort() throws NoSuchActivityException { } + public void parseBye(ActivityList activityList, Scanner scanner) { + if (startTime != null) { + String line = activityName + " is still running! If you exit now it will be aborted.\n" + + "Would you like to end this activity to save it?"; + ui.printDivider(line); + String userInput = scanner.nextLine(); + if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { + saveActivity(activityList); + ui.exitFromApp(); + } else { + ui.exitFromApp(); + } + } else { + ui.exitFromApp(); + } + } + + private void saveActivity(ActivityList activityList) { + if (continuedIndex != -1) { + String line = "Ended: " + activityName; + ui.printDivider(line); + endTime = LocalDateTime.now(); + Duration duration = Duration.between(startTime, endTime); + Duration oldDuration = activityList.get(continuedIndex).getDuration(); + Duration newDuration = duration.plus(oldDuration); + activityList.updateDuration(newDuration, endTime, continuedIndex); + continuedIndex = -1; + resetInfo(); + } else { + String line = "Ended: " + activityName; + ui.printDivider(line); + endTime = LocalDateTime.now(); + Duration duration = Duration.between(startTime, endTime); + Activity newActivity = new Activity(activityName, startTime, endTime, duration, tags); + activityList.add(newActivity); + // reset activity info + resetInfo(); + } + } + /** Method to parse the start activity command. */ public void parseStart(ActivityList activityList, Scanner scanner) throws ArrayIndexOutOfBoundsException, EmptyNameException, NullPointerException { // check if an activity has already been started @@ -273,25 +314,8 @@ private String parseActivity(int delimiter) throws EmptyNameException { public void parseEnd(ActivityList activityList) throws NoSuchActivityException, InvalidTimeFrameException { if (startTime == null) { throw new NoSuchActivityException(); - } else if (continuedIndex != -1) { - String line = "Ended: " + activityName; - ui.printDivider(line); - endTime = LocalDateTime.now(); - Duration duration = Duration.between(startTime, endTime); - Duration oldDuration = activityList.get(continuedIndex).getDuration(); - Duration newDuration = duration.plus(oldDuration); - activityList.updateDuration(newDuration, endTime, continuedIndex); - continuedIndex = -1; - resetInfo(); } else { - String line = "Ended: " + activityName; - ui.printDivider(line); - endTime = LocalDateTime.now(); - Duration duration = Duration.between(startTime, endTime); - Activity newActivity = new Activity(activityName, startTime, endTime, duration, tags); - activityList.add(newActivity); - // reset activity info - resetInfo(); + saveActivity(activityList); } logger.makeFineLog("Ended: " + activityName); } From d01ca2ee8610ddc5fef2e76807ecd7e2d72cc496 Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 22 Mar 2020 00:19:14 +0800 Subject: [PATCH 086/415] Fixed warnings --- src/main/java/jikan/Jikan.java | 3 +- src/main/java/jikan/activity/Activity.java | 7 +- .../java/jikan/activity/ActivityList.java | 4 +- src/main/java/jikan/parser/Parser.java | 295 +++++++++--------- src/main/java/jikan/ui/Ui.java | 2 +- text-ui-test/EXPECTED.TXT | 33 +- text-ui-test/data/LogRecord.txt | 1 + text-ui-test/data/data.csv | 1 + text-ui-test/input.txt | 20 +- 9 files changed, 196 insertions(+), 170 deletions(-) create mode 100644 text-ui-test/data/LogRecord.txt create mode 100644 text-ui-test/data/data.csv diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 3ea26fd49..e5537b107 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -1,6 +1,7 @@ package jikan; import jikan.activity.ActivityList; +import jikan.exception.InvalidTimeFrameException; import jikan.parser.Parser; import jikan.storage.Storage; import jikan.ui.Ui; @@ -48,7 +49,7 @@ public static void createActivityList() { /** * Main entry-point for the Jikan application. */ - public static void main(String[] args) { + public static void main(String[] args) throws InvalidTimeFrameException { ui.printGreeting(); Scanner in = new Scanner(System.in); storage = new Storage(DATA_FILE_PATH); diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 0e884215c..285d7f1df 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -29,7 +29,12 @@ public class Activity { * @param endTime the time that the activity ended */ public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Duration duration, - Set tags) { + Set tags) throws InvalidTimeFrameException { + + if (endTime.isBefore(startTime)) { + throw new InvalidTimeFrameException(); + } + this.name = name.strip(); this.startTime = startTime; diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 787645b9d..80c24326c 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -127,6 +127,8 @@ private void populateTaskList(File dataFile) { } } catch (FileNotFoundException e) { System.out.println("Error: data file not found. Could not load into the current session's task list."); + } catch (InvalidTimeFrameException e) { + System.out.println("Error: Invalid time frame."); } } @@ -135,7 +137,7 @@ private void populateTaskList(File dataFile) { * * @param s String to parse. */ - private void parseDataLine(String s) { + private void parseDataLine(String s) throws InvalidTimeFrameException { if (!s.isEmpty()) { List strings = Arrays.asList(s.split(",")); diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index b2b1339d8..64c36a327 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -14,6 +14,7 @@ import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import java.util.Arrays; import java.util.HashSet; import java.util.Scanner; import java.util.Set; @@ -26,7 +27,7 @@ public class Parser { protected LocalDateTime startTime = null; protected LocalDateTime endTime = null; private String activityName = null; - private Set tags = new HashSet(); + private Set tags = new HashSet<>(); private Ui ui = new Ui(); protected String[] tokenizedInputs; String instruction; @@ -41,7 +42,7 @@ public class Parser { * @param scanner scanner object which reads user input * @param activityList the list of activities */ - public void parseUserCommands(Scanner scanner, ActivityList activityList) { + public void parseUserCommands(Scanner scanner, ActivityList activityList) throws InvalidTimeFrameException { logger.makeInfoLog("Starting to parse inputs."); /*lastShownList is initialised here to facilitate subsequent delete and edit commands referencing by index of this list. @@ -60,13 +61,7 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { case "start": try { parseStart(activityList, scanner); - } catch (EmptyNameException e) { - logger.makeInfoLog("Activity started without task name"); - ui.printDivider("Task name cannot be empty!"); - } catch (ArrayIndexOutOfBoundsException e) { - logger.makeInfoLog("Activity started without task name"); - ui.printDivider("Task name cannot be empty!"); - } catch (NullPointerException e) { + } catch (EmptyNameException | NullPointerException | ArrayIndexOutOfBoundsException e) { logger.makeInfoLog("Activity started without task name"); ui.printDivider("Task name cannot be empty!"); } @@ -132,83 +127,7 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) { } } - /** - * Shows the user all past activities that has names which match the keyword queried by the user. - * @param activityList the activity list to search for matching activities - * @param lastShownList the activity list to populate with matching activities only - * @param keyword the keyword queried by the user - */ - private void parseFind(ActivityList activityList, ActivityList lastShownList, String keyword) - throws EmptyQueryException { - if (keyword.length() < 1) { - throw new EmptyQueryException(); - } else { - lastShownList.activities.clear(); - for (Activity i : activityList.activities) { - if (i.getName().contains(keyword)) { - lastShownList.activities.add(i); - } - } - Ui.printResults(lastShownList); - } - } - - /** - * Shows the user all past activities that has tags which match the keywords queried by the user. - * @param activityList the activity list to search for matching activities - * @param lastShownList the activity list to populate with matching activities only - * @param query the keywords queried by the user - */ - private void parseFilter(ActivityList activityList, ActivityList lastShownList, String query) - throws EmptyQueryException { - if (query.length() < 1) { - throw new EmptyQueryException(); - } else { - lastShownList.activities.clear(); - String[] keywords = query.split(" "); - - for (String keyword : keywords) { - populateLastShownList(activityList, lastShownList, keyword); - } - Ui.printResults(lastShownList); - } - } - - /** - * Populates the last shown list with activities that contain tags which match the given keyword. - * @param activityList the list of activity to search - * @param lastShownList the last shown list to populate - * @param keyword the keyword to match - */ - private void populateLastShownList(ActivityList activityList, ActivityList lastShownList, String keyword) { - for (Activity i : activityList.activities) { - if (!lastShownList.activities.contains(i) && i.getTags().contains(keyword)) { - lastShownList.activities.add(i); - } - } - } - - /** Method to parse user inputs that are not recognised. */ - private void parseDefault() { - String line = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; - logger.makeInfoLog("Invalid command entered"); - ui.printDivider(line); - } - - /** Method to parse the abort command. */ - public void parseAbort() throws NoSuchActivityException { - if (startTime == null) { - throw new NoSuchActivityException(); - } else { - logger.makeFineLog("Aborted " + activityName); - resetInfo(); - String line = "You have aborted the current activity!"; - ui.printDivider(line); - } - - } - - public void parseBye(ActivityList activityList, Scanner scanner) { + public void parseBye(ActivityList activityList, Scanner scanner) throws InvalidTimeFrameException { if (startTime != null) { String line = activityName + " is still running! If you exit now it will be aborted.\n" + "Would you like to end this activity to save it?"; @@ -216,36 +135,9 @@ public void parseBye(ActivityList activityList, Scanner scanner) { String userInput = scanner.nextLine(); if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { saveActivity(activityList); - ui.exitFromApp(); - } else { - ui.exitFromApp(); } - } else { - ui.exitFromApp(); - } - } - - private void saveActivity(ActivityList activityList) { - if (continuedIndex != -1) { - String line = "Ended: " + activityName; - ui.printDivider(line); - endTime = LocalDateTime.now(); - Duration duration = Duration.between(startTime, endTime); - Duration oldDuration = activityList.get(continuedIndex).getDuration(); - Duration newDuration = duration.plus(oldDuration); - activityList.updateDuration(newDuration, endTime, continuedIndex); - continuedIndex = -1; - resetInfo(); - } else { - String line = "Ended: " + activityName; - ui.printDivider(line); - endTime = LocalDateTime.now(); - Duration duration = Duration.between(startTime, endTime); - Activity newActivity = new Activity(activityName, startTime, endTime, duration, tags); - activityList.add(newActivity); - // reset activity info - resetInfo(); } + ui.exitFromApp(); } /** Method to parse the start activity command. */ @@ -293,19 +185,17 @@ private void continueActivity(ActivityList activityList, Scanner scanner) { private String parseActivity(int delimiter) throws EmptyNameException { if(delimiter == -1) { // no tags - activityName = tokenizedInputs[1]; + activityName = tokenizedInputs[1].strip(); if (activityName.isEmpty()) { throw new EmptyNameException(); } } else { - activityName = tokenizedInputs[1].substring(0, delimiter); + activityName = tokenizedInputs[1].substring(0, delimiter).strip(); if (activityName.isEmpty()) { throw new EmptyNameException(); } String[] tagString = tokenizedInputs[1].substring(delimiter + 3).split(" "); - for (String i : tagString) { - tags.add(i); - } + tags.addAll(Arrays.asList(tagString)); } return "Started: " + activityName; } @@ -320,35 +210,6 @@ public void parseEnd(ActivityList activityList) throws NoSuchActivityException, logger.makeFineLog("Ended: " + activityName); } - public void resetInfo() { - startTime = null; - activityName = null; - tags = new HashSet<>(); - } - - /** Deletes an activity from the activity list. */ - public void parseDelete(ActivityList activityList) { - int index = Integer.parseInt(tokenizedInputs[1]) - 1; - String line = "You have deleted " + activityList.get(index).getName(); - ui.printDivider(line); - activityList.delete(index); - } - - public void parseContinue(ActivityList activityList) { - int index = activityList.findActivity(tokenizedInputs[1]); - if (index != -1) { - // activity is found - activityName = activityList.get(index).getName(); - startTime = LocalDateTime.now(); - tags = activityList.get(index).getTags(); - continuedIndex = index; - String line = activityName + " was continued"; - ui.printDivider(line); - } else { - // activity not found - System.out.println("No such activity is found!"); - } - } /** * Parse a list command. The user can specify either a single date or a specific time frame. @@ -360,12 +221,10 @@ private void parseList(ActivityList activityList) throws InvalidTimeFrameExcepti // If no time frame is specified, print the entire list if (tokenizedInputs.length == 1) { lastShownList.activities.clear(); - ui.printList(activityList); + Ui.printList(activityList); // Can't do lastShownList = activityList, otherwise we just copy - for (Activity i : activityList.activities) { - lastShownList.activities.add(i); - } + lastShownList.activities.addAll(activityList.activities); return; } @@ -382,7 +241,7 @@ private void parseList(ActivityList activityList) throws InvalidTimeFrameExcepti lastShownList.activities.add(i); } } - ui.printList(lastShownList); + Ui.printList(lastShownList); // Both start and end dates are specified } else if (tokenizedInputs.length == 3) { LocalDate endDate = LocalDate.parse(tokenizedInputs[2], parser); @@ -396,10 +255,138 @@ private void parseList(ActivityList activityList) throws InvalidTimeFrameExcepti lastShownList.activities.add(i); } } - ui.printList(lastShownList); + Ui.printList(lastShownList); } else { throw new InvalidTimeFrameException(); } } + + /** Method to parse the abort command. */ + public void parseAbort() throws NoSuchActivityException { + if (startTime == null) { + throw new NoSuchActivityException(); + } else { + logger.makeFineLog("Aborted " + activityName); + resetInfo(); + String line = "You have aborted the current activity!"; + ui.printDivider(line); + } + } + + /** Deletes an activity from the activity list. */ + public void parseDelete(ActivityList activityList) { + int index = Integer.parseInt(tokenizedInputs[1]) - 1; + String line = "You have deleted " + activityList.get(index).getName(); + ui.printDivider(line); + activityList.delete(index); + } + + /** + * Shows the user all past activities that has names which match the keyword queried by the user. + * @param activityList the activity list to search for matching activities + * @param lastShownList the activity list to populate with matching activities only + * @param keyword the keyword queried by the user + */ + private void parseFind(ActivityList activityList, ActivityList lastShownList, String keyword) + throws EmptyQueryException { + if (keyword.length() < 1) { + throw new EmptyQueryException(); + } else { + lastShownList.activities.clear(); + for (Activity i : activityList.activities) { + if (i.getName().contains(keyword)) { + lastShownList.activities.add(i); + } + } + Ui.printResults(lastShownList); + } + } + + /** + * Shows the user all past activities that has tags which match the keywords queried by the user. + * @param activityList the activity list to search for matching activities + * @param lastShownList the activity list to populate with matching activities only + * @param query the keywords queried by the user + */ + private void parseFilter(ActivityList activityList, ActivityList lastShownList, String query) + throws EmptyQueryException { + if (query.length() < 1) { + throw new EmptyQueryException(); + } else { + lastShownList.activities.clear(); + String[] keywords = query.split(" "); + + for (String keyword : keywords) { + populateLastShownList(activityList, lastShownList, keyword); + } + Ui.printResults(lastShownList); + } + } + + public void parseContinue(ActivityList activityList) { + int index = activityList.findActivity(tokenizedInputs[1]); + if (index != -1) { + // activity is found + activityName = activityList.get(index).getName(); + startTime = LocalDateTime.now(); + tags = activityList.get(index).getTags(); + continuedIndex = index; + String line = activityName + " was continued"; + ui.printDivider(line); + } else { + // activity not found + System.out.println("No such activity is found!"); + } + } + + /** Method to parse user inputs that are not recognised. */ + private void parseDefault() { + String line = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; + logger.makeInfoLog("Invalid command entered"); + ui.printDivider(line); + } + + /** + * Populates the last shown list with activities that contain tags which match the given keyword. + * @param activityList the list of activity to search + * @param lastShownList the last shown list to populate + * @param keyword the keyword to match + */ + private void populateLastShownList(ActivityList activityList, ActivityList lastShownList, String keyword) { + for (Activity i : activityList.activities) { + if (!lastShownList.activities.contains(i) && i.getTags().contains(keyword)) { + lastShownList.activities.add(i); + } + } + } + + private void saveActivity(ActivityList activityList) throws InvalidTimeFrameException { + if (continuedIndex != -1) { + String line = "Ended: " + activityName; + ui.printDivider(line); + endTime = LocalDateTime.now(); + Duration duration = Duration.between(startTime, endTime); + Duration oldDuration = activityList.get(continuedIndex).getDuration(); + Duration newDuration = duration.plus(oldDuration); + activityList.updateDuration(newDuration, endTime, continuedIndex); + continuedIndex = -1; + resetInfo(); + } else { + String line = "Ended: " + activityName; + ui.printDivider(line); + endTime = LocalDateTime.now(); + Duration duration = Duration.between(startTime, endTime); + Activity newActivity = new Activity(activityName, startTime, endTime, duration, tags); + activityList.add(newActivity); + // reset activity info + resetInfo(); + } + } + + public void resetInfo() { + startTime = null; + activityName = null; + tags = new HashSet<>(); + } } \ No newline at end of file diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 8dabf4731..35b88bee6 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -24,7 +24,7 @@ public void exitFromApp() { } /** Prints divider between user input and app feedback. */ - public static void printDivider(String line) { + public void printDivider(String line) { System.out.println(DIVIDER); System.out.println(line); System.out.println(DIVIDER); diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 6b070cb3a..9e7602ea5 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,25 +1,46 @@ Jikan ------------------------------------------- ------------------------------------------- -Started: studying +Started: activity one ------------------------------------------- ------------------------------------------- -Ended: studying +Ended: activity one ------------------------------------------- ------------------------------------------- -Started: exercising +Started: activity two +------------------------------------------- +------------------------------------------- +activity two is ongoing! +------------------------------------------- +------------------------------------------- +Ended: activity two +------------------------------------------- +------------------------------------------- +activity one was continued ------------------------------------------- ------------------------------------------- You have aborted the current activity! ------------------------------------------- ------------------------------------------- -Task name cannot be empty! +There is already an activity with this name. Would you like to continue it? +------------------------------------------- +------------------------------------------- +activity two was continued +------------------------------------------- +------------------------------------------- +Ended: activity two +------------------------------------------- +------------------------------------------- +Started: activity three +------------------------------------------- +------------------------------------------- +Ended: activity three ------------------------------------------- ------------------------------------------- -You have not started any activity! +Started: four ------------------------------------------- ------------------------------------------- -You have not started any activity! +Ended: four ------------------------------------------- ------------------------------------------- Bye! See you again. diff --git a/text-ui-test/data/LogRecord.txt b/text-ui-test/data/LogRecord.txt new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/text-ui-test/data/LogRecord.txt @@ -0,0 +1 @@ + diff --git a/text-ui-test/data/data.csv b/text-ui-test/data/data.csv new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/text-ui-test/data/data.csv @@ -0,0 +1 @@ + diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 5f0a1f4d7..39250f515 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,8 +1,16 @@ -start studying -end studying -start exercising -abort exercising -start +start activity one /t tag tag1 tag2 end +start activity two /t tag2 +start activity 3 +end +continue activity one abort -bye \ No newline at end of file +start activity two +y +end +start activity three /t tag tag1 +end +start four /t tag +end +bye + From 77e6d8f7627d646d3a33f9a7d187e7d11aa2e75b Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 22 Mar 2020 00:38:23 +0800 Subject: [PATCH 087/415] Change delete to delete by name --- src/main/java/jikan/parser/Parser.java | 78 +++++++++++++++++++------- 1 file changed, 57 insertions(+), 21 deletions(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 64c36a327..6ad96c363 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -99,8 +99,8 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) throws case "delete": try { parseDelete(activityList); - } catch (IndexOutOfBoundsException | NumberFormatException e) { - ui.printDivider("Invalid index number."); + } catch (NoSuchActivityException e) { + ui.printDivider("No activity with this name exists!"); } break; case "find": @@ -118,7 +118,11 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) throws } break; case "continue": - parseContinue(activityList); + try { + parseContinue(activityList); + } catch (NoSuchActivityException e) { + ui.printDivider("No activity with this name exists!"); + } break; default: parseDefault(); @@ -127,6 +131,14 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) throws } } + /** + * Checks for ongoing activities and ask if user wants to save them + * before exiting the app. + * + * @param activityList List of activities. + * @param scanner To parse user input. + * @throws InvalidTimeFrameException precautionary measure for if endTime is greater than startTime. + */ public void parseBye(ActivityList activityList, Scanner scanner) throws InvalidTimeFrameException { if (startTime != null) { String line = activityName + " is still running! If you exit now it will be aborted.\n" + @@ -140,7 +152,12 @@ public void parseBye(ActivityList activityList, Scanner scanner) throws InvalidT ui.exitFromApp(); } - /** Method to parse the start activity command. */ + /** + * Method to parse the start activity command. + * + * @param activityList List of activities. + * @param scanner To parse user input. + */ public void parseStart(ActivityList activityList, Scanner scanner) throws ArrayIndexOutOfBoundsException, EmptyNameException, NullPointerException { // check if an activity has already been started if (startTime != null) { @@ -153,10 +170,11 @@ public void parseStart(ActivityList activityList, Scanner scanner) throws ArrayI String line; // check if there exists an activity with this name - if (activityList.findActivity(tokenizedInputs[1]) != -1) { + int index = activityList.findActivity(tokenizedInputs[1]); + if (index != -1) { line = "There is already an activity with this name. Would you like to continue it?"; ui.printDivider(line); - continueActivity(activityList, scanner); + continueActivity(activityList, scanner, index); } else { int delimiter = tokenizedInputs[1].indexOf("/t"); line = parseActivity(delimiter); @@ -167,20 +185,29 @@ public void parseStart(ActivityList activityList, Scanner scanner) throws ArrayI } } - private void continueActivity(ActivityList activityList, Scanner scanner) { - String line; + /** + * Received user input on whether or not to continue the activity. + * + * @param activityList List of activities. + * @param scanner Parse user input. + */ + private void continueActivity(ActivityList activityList, Scanner scanner, int index) { String userInput = scanner.nextLine(); if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { - parseContinue(activityList); + activityName = activityList.get(index).getName(); + startTime = LocalDateTime.now(); + tags = activityList.get(index).getTags(); + continuedIndex = index; + ui.printDivider(activityName + " was continued"); } else { - line = "Okay then, what else can I do for you?"; - ui.printDivider(line); + ui.printDivider("Okay then, what else can I do for you?"); } } /** - * Inserts the tags into the activity object when it has ended. - * @param delimiter the index of the tag delimiter + * Parses the started activity for name and tags. + * + * @param delimiter The index of the tag delimiter. */ private String parseActivity(int delimiter) throws EmptyNameException { if(delimiter == -1) { @@ -275,11 +302,17 @@ public void parseAbort() throws NoSuchActivityException { } /** Deletes an activity from the activity list. */ - public void parseDelete(ActivityList activityList) { - int index = Integer.parseInt(tokenizedInputs[1]) - 1; - String line = "You have deleted " + activityList.get(index).getName(); - ui.printDivider(line); - activityList.delete(index); + public void parseDelete(ActivityList activityList) throws NoSuchActivityException { + //int index = Integer.parseInt(tokenizedInputs[1]) - 1; + int index = activityList.findActivity(tokenizedInputs[1]); + if (index != -1) { + // activity was found + String line = "You have deleted " + tokenizedInputs[1]; + ui.printDivider(line); + activityList.delete(index); + } else { + throw new NoSuchActivityException(); + } } /** @@ -324,7 +357,11 @@ private void parseFilter(ActivityList activityList, ActivityList lastShownList, } } - public void parseContinue(ActivityList activityList) { + /** + * Continues an activity in the activityList. + * @param activityList To search for the activity and retrieve relevant details. + */ + public void parseContinue(ActivityList activityList) throws NoSuchActivityException { int index = activityList.findActivity(tokenizedInputs[1]); if (index != -1) { // activity is found @@ -335,8 +372,7 @@ public void parseContinue(ActivityList activityList) { String line = activityName + " was continued"; ui.printDivider(line); } else { - // activity not found - System.out.println("No such activity is found!"); + throw new NoSuchActivityException(); } } From 47f281cbfb6b8cb5754c7013dd6896ea7ed37860 Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 22 Mar 2020 00:51:37 +0800 Subject: [PATCH 088/415] Fix style and tests --- src/main/java/jikan/activity/ActivityList.java | 13 ++++++++++++- src/main/java/jikan/parser/Parser.java | 11 ++++++----- src/main/java/jikan/storage/StorageHandler.java | 6 ++++++ src/test/java/jikan/activity/ActivityListTest.java | 13 +++++++------ src/test/java/jikan/activity/ActivityTest.java | 7 +++++-- src/test/java/jikan/parser/ExceptionTest.java | 5 ++++- 6 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 80c24326c..b10e3823d 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -60,15 +60,26 @@ public void add(Activity activity) { updateFile(dataLine); } + /** + * Updates the duration of an activity. + * @param duration The new duration. + * @param endTime Thew new end time. + * @param index Index of the activity to be updated. + */ public void updateDuration(Duration duration, LocalDateTime endTime, int index) { activities.get(index).setDuration(duration); activities.get(index).setEndTime(endTime); fieldChangeUpdateFile(); } + /** + * Searches for an activity in activityList by name. + * @param name Name of the activity to search for. + * @return Index of activity with that name. + */ public int findActivity(String name) { for (int i = 0; i < activities.size(); i++) { - if(activities.get(i).getName().equals(name)) { + if (activities.get(i).getName().equals(name)) { return i; } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 6ad96c363..da87f3b78 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -141,8 +141,8 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) throws */ public void parseBye(ActivityList activityList, Scanner scanner) throws InvalidTimeFrameException { if (startTime != null) { - String line = activityName + " is still running! If you exit now it will be aborted.\n" + - "Would you like to end this activity to save it?"; + String line = activityName + " is still running! If you exit now it will be aborted.\n" + + "Would you like to end this activity to save it?"; ui.printDivider(line); String userInput = scanner.nextLine(); if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { @@ -158,7 +158,8 @@ public void parseBye(ActivityList activityList, Scanner scanner) throws InvalidT * @param activityList List of activities. * @param scanner To parse user input. */ - public void parseStart(ActivityList activityList, Scanner scanner) throws ArrayIndexOutOfBoundsException, EmptyNameException, NullPointerException { + public void parseStart(ActivityList activityList, Scanner scanner) + throws ArrayIndexOutOfBoundsException, EmptyNameException, NullPointerException { // check if an activity has already been started if (startTime != null) { String line = activityName + " is ongoing!"; @@ -210,7 +211,7 @@ private void continueActivity(ActivityList activityList, Scanner scanner, int in * @param delimiter The index of the tag delimiter. */ private String parseActivity(int delimiter) throws EmptyNameException { - if(delimiter == -1) { + if (delimiter == -1) { // no tags activityName = tokenizedInputs[1].strip(); if (activityName.isEmpty()) { @@ -420,7 +421,7 @@ private void saveActivity(ActivityList activityList) throws InvalidTimeFrameExce } } - public void resetInfo() { + private void resetInfo() { startTime = null; activityName = null; tags = new HashSet<>(); diff --git a/src/main/java/jikan/storage/StorageHandler.java b/src/main/java/jikan/storage/StorageHandler.java index eb26d2922..5fe6686fe 100644 --- a/src/main/java/jikan/storage/StorageHandler.java +++ b/src/main/java/jikan/storage/StorageHandler.java @@ -50,6 +50,12 @@ public static void removeLine(int lineNumber, Storage storage) throws IOExceptio */ } + /** + * Saves the updated activity list to a list of strings to write to the save file. + * @param activities New activity list. + * @param storage Storage object to obtain file path. + * @throws IOException If an error occurs while writing the new list to file. + */ public static void updateField(ArrayList activities, Storage storage) throws IOException { List fileContent = new ArrayList<>(); for (Activity a : activities) { diff --git a/src/test/java/jikan/activity/ActivityListTest.java b/src/test/java/jikan/activity/ActivityListTest.java index 8955995c7..01eaba0d3 100644 --- a/src/test/java/jikan/activity/ActivityListTest.java +++ b/src/test/java/jikan/activity/ActivityListTest.java @@ -4,6 +4,7 @@ import jikan.storage.Storage; import org.junit.jupiter.api.Test; +import java.time.Duration; import java.time.LocalDateTime; import java.util.HashSet; @@ -18,12 +19,12 @@ void getIndex() throws InvalidTimeFrameException { HashSet tags = new HashSet(); tags.add("tag1"); tags.add("tag2"); - Activity activity1 = new Activity("Activity1", LocalDateTime.parse("2020-01-01T08:00:00"), - LocalDateTime.parse("2020-01-01T10:00:00"), tags); - Activity activity2 = new Activity("Activity2", LocalDateTime.parse("2020-01-01T10:00:00"), - LocalDateTime.parse("2020-01-01T11:00:00"), tags); - Activity activity3 = new Activity("Activity3", LocalDateTime.parse("2020-01-01T05:00:00"), - LocalDateTime.parse("2020-01-01T07:00:00"), tags); + LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); + LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); + Duration duration = Duration.between(startTime, endTime); + Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags); + Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags); + Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags); activities.add(activity1); activities.add(activity2); activities.add(activity3); diff --git a/src/test/java/jikan/activity/ActivityTest.java b/src/test/java/jikan/activity/ActivityTest.java index 1a2d05d7c..0e074e58d 100644 --- a/src/test/java/jikan/activity/ActivityTest.java +++ b/src/test/java/jikan/activity/ActivityTest.java @@ -3,6 +3,7 @@ import jikan.exception.InvalidTimeFrameException; import org.junit.jupiter.api.Test; +import java.time.Duration; import java.time.LocalDateTime; import java.util.HashSet; @@ -16,8 +17,10 @@ class ActivityTest { { try { - activity = new Activity("Activity", LocalDateTime.parse("2020-01-01T08:00:00"), - LocalDateTime.parse("2020-01-01T10:00:00"), tags); + LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); + LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); + Duration duration = Duration.between(startTime, endTime); + activity = new Activity("Activity", startTime, endTime, duration, tags); } catch (InvalidTimeFrameException e) { e.printStackTrace(); } diff --git a/src/test/java/jikan/parser/ExceptionTest.java b/src/test/java/jikan/parser/ExceptionTest.java index ebdbefd22..f3fca4ee6 100644 --- a/src/test/java/jikan/parser/ExceptionTest.java +++ b/src/test/java/jikan/parser/ExceptionTest.java @@ -6,16 +6,19 @@ import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; +import java.util.Scanner; + class ExceptionTest { Parser parser = new Parser(); + Scanner scanner = new Scanner(System.in); ActivityList activityList = new ActivityList(); @Test public void testEmptyNameException() { Assertions.assertThrows(EmptyNameException.class, () -> { parser.tokenizedInputs = new String[]{"start", ""}; - parser.parseStart(); + parser.parseStart(activityList, scanner); }); } From f8de66613022eda3929a108118c0840022bade1a Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 22 Mar 2020 01:01:04 +0800 Subject: [PATCH 089/415] Added some logs --- src/main/java/jikan/parser/Parser.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index da87f3b78..b91215413 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -122,6 +122,7 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) throws parseContinue(activityList); } catch (NoSuchActivityException e) { ui.printDivider("No activity with this name exists!"); + logger.makeInfoLog("Continue command failed as there was no such activity saved."); } break; default: @@ -147,6 +148,7 @@ public void parseBye(ActivityList activityList, Scanner scanner) throws InvalidT String userInput = scanner.nextLine(); if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { saveActivity(activityList); + logger.makeInfoLog("Activity " + activityName + " was saved before app terminated."); } } ui.exitFromApp(); @@ -169,16 +171,14 @@ public void parseStart(ActivityList activityList, Scanner scanner) // tags should be reset assert tags.isEmpty(); - String line; // check if there exists an activity with this name int index = activityList.findActivity(tokenizedInputs[1]); if (index != -1) { - line = "There is already an activity with this name. Would you like to continue it?"; - ui.printDivider(line); + ui.printDivider("There is already an activity with this name. Would you like to continue it?"); continueActivity(activityList, scanner, index); } else { int delimiter = tokenizedInputs[1].indexOf("/t"); - line = parseActivity(delimiter); + String line = parseActivity(delimiter); startTime = LocalDateTime.now(); logger.makeFineLog("Started: " + activityName); ui.printDivider(line); @@ -200,6 +200,7 @@ private void continueActivity(ActivityList activityList, Scanner scanner, int in tags = activityList.get(index).getTags(); continuedIndex = index; ui.printDivider(activityName + " was continued"); + logger.makeFineLog(activityName + " was continued."); } else { ui.printDivider("Okay then, what else can I do for you?"); } @@ -372,6 +373,7 @@ public void parseContinue(ActivityList activityList) throws NoSuchActivityExcept continuedIndex = index; String line = activityName + " was continued"; ui.printDivider(line); + logger.makeFineLog(activityName + " was continued."); } else { throw new NoSuchActivityException(); } From 7d0beacbd4228d28fe406a2071d51608e08c3629 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sun, 22 Mar 2020 19:41:26 +0800 Subject: [PATCH 090/415] Enable assertions --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index 7698de8a7..0971b27d6 100644 --- a/build.gradle +++ b/build.gradle @@ -37,4 +37,5 @@ checkstyle { run{ standardInput = System.in + enableAssertions = true } \ No newline at end of file From decda3c665e7bbacf7df5cbf03bfade1d3f66b7c Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sun, 22 Mar 2020 21:29:54 +0800 Subject: [PATCH 091/415] Move the createActivityList method from Jikan Class to Storage Class --- src/main/java/jikan/Jikan.java | 22 ++--------------- src/main/java/jikan/Log.java | 23 ------------------ .../java/jikan/activity/ActivityList.java | 15 ++++-------- src/main/java/jikan/parser/Parser.java | 1 - src/main/java/jikan/storage/Storage.java | 24 +++++++++++++++++++ 5 files changed, 30 insertions(+), 55 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index e5537b107..5cf7391b7 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -6,7 +6,6 @@ import jikan.storage.Storage; import jikan.ui.Ui; -import java.io.IOException; import java.util.Scanner; /** @@ -28,24 +27,6 @@ public class Jikan { /** Parser to parse commands. */ private static Parser parser = new Parser(); - /** - * Creates ActivityList and loads data from data file if the data file previously existed. - * Otherwise, an empty task list is initialized. - */ - public static void createActivityList() { - try { - if (storage.loadFile()) { - activityList = new ActivityList(storage); - } else { - activityList = new ActivityList(); - activityList.storage = storage; - } - } catch (IOException e) { - System.out.println("Error loading/creating data file."); - } - } - - /** * Main entry-point for the Jikan application. */ @@ -53,7 +34,8 @@ public static void main(String[] args) throws InvalidTimeFrameException { ui.printGreeting(); Scanner in = new Scanner(System.in); storage = new Storage(DATA_FILE_PATH); - createActivityList(); + activityList = storage.createActivityList(); + activityList.storage = storage; parser.parseUserCommands(in, activityList); } } diff --git a/src/main/java/jikan/Log.java b/src/main/java/jikan/Log.java index 48cd36a3f..5b8f3f46c 100644 --- a/src/main/java/jikan/Log.java +++ b/src/main/java/jikan/Log.java @@ -1,7 +1,5 @@ package jikan; -import jikan.ui.Ui; - import java.io.File; import java.io.IOException; import java.util.logging.Level; @@ -20,27 +18,6 @@ public class Log { public String logFilePath = "data/LogRecord.txt"; private static File logFile; - /* - /** - * Constructor for a new logger. - * - public Log() throws IOException { - logger = Logger.getLogger(Log.class.getName()); - LogManager.getLogManager().reset(); - logger.setLevel(Level.ALL); - - ConsoleHandler consoleHandler = new ConsoleHandler(); - consoleHandler.setLevel(Level.WARNING); - logger.addHandler(consoleHandler); - - FileHandler fileHandler = new FileHandler("data/LogRecord.txt", true); - - formatterTxt = new SimpleFormatter(); - fileHandler.setFormatter(formatterTxt); - fileHandler.setLevel(Level.INFO); - logger.addHandler(fileHandler); - } */ - /** * Constructor for a new logger. */ diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index b10e3823d..d3ca238a7 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -23,14 +23,11 @@ public class ActivityList { public ArrayList activities; public Storage storage; // Storage the list was loaded from - //int size; - /** * Constructor for a new activity list. */ public ActivityList() { this.activities = new ArrayList<>(); - //this.size = activities.size(); } /** @@ -38,10 +35,9 @@ public ActivityList() { * * @param storage Storage to load from. */ - public ActivityList(Storage storage) { + public ActivityList(File dataFile) { this.activities = new ArrayList<>(); - this.storage = storage; - populateTaskList(storage.dataFile); + populateTaskList(dataFile); } public Activity get(int i) { @@ -54,9 +50,7 @@ public Activity get(int i) { */ public void add(Activity activity) { activities.add(activity); - String dataLine = activity.toData(); - updateFile(dataLine); } @@ -158,14 +152,13 @@ private void parseDataLine(String s) throws InvalidTimeFrameException { // if there are tags if (strings.size() > 4) { // remove square brackets surrounding tags - tagStrings = strings.get(4).substring(0,strings.get(4).length() - 1).split(" "); tagStrings = strings.get(4).split(" "); for (String i : tagStrings) { tags.add(i); } } - // strings[0] = name, strings[1] = startDate, string[2] = endDate - Activity e = null; + + Activity e; LocalDateTime startTime = LocalDateTime.parse(strings.get(1)); LocalDateTime endTime = LocalDateTime.parse(strings.get(2)); Duration duration = Duration.parse(strings.get(3)); diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index b91215413..221300645 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -55,7 +55,6 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) throws switch (instruction) { case "bye": - //ui.exitFromApp(); parseBye(activityList, scanner); break; case "start": diff --git a/src/main/java/jikan/storage/Storage.java b/src/main/java/jikan/storage/Storage.java index 0ecb7d229..3d88b2272 100644 --- a/src/main/java/jikan/storage/Storage.java +++ b/src/main/java/jikan/storage/Storage.java @@ -1,5 +1,7 @@ package jikan.storage; +import jikan.activity.ActivityList; + import java.io.File; import java.io.FileWriter; import java.io.IOException; @@ -15,6 +17,8 @@ public class Storage { /** File object for current data file. */ public File dataFile; + public ActivityList activityList; + /** * Constructs a Storage object for the input file path. * @@ -61,4 +65,24 @@ private void createDataFile() throws IOException { dataFile.getParentFile().mkdirs(); // Create data directory (does nothing if directory already exists) dataFile.createNewFile(); } + + + /** + * Creates ActivityList and loads data from data file if the data file previously existed. + * Otherwise, an empty task list is initialized. + * @return an ActivityList object containing a list of activities provided by the data file. + */ + public ActivityList createActivityList() { + try { + if (loadFile()) { + activityList = new ActivityList(dataFile); + } else { + activityList = new ActivityList(); + } + } catch (IOException e) { + System.out.println("Error loading/creating data file."); + } + return activityList; + } + } From d4b30ee44c8fcceb2519256e8aa5115a231c5277 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sun, 22 Mar 2020 22:22:06 +0800 Subject: [PATCH 092/415] Add edit name command --- src/main/java/jikan/activity/Activity.java | 4 +++ .../java/jikan/activity/ActivityList.java | 5 +++ src/main/java/jikan/parser/Parser.java | 36 +++++++++++++++++++ 3 files changed, 45 insertions(+) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 285d7f1df..efd34bfe0 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -56,6 +56,10 @@ public String getName() { return name; } + public void setName(String name) { + this.name = name.strip(); + } + public Set getTags() { return tags; } diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index b10e3823d..1f3fb4358 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -99,6 +99,11 @@ private void updateFile(String dataLine) { } } + public void updateName(int index, String newName) { + activities.get(index).setName(newName); + fieldChangeUpdateFile(); + } + public void delete(int index) { activities.remove(index); deleteUpdateFile(index); diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index b91215413..11f740783 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -125,6 +125,20 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) throws logger.makeInfoLog("Continue command failed as there was no such activity saved."); } break; + case "edit": + try { + parseEdit(activityList); + } catch (NoSuchActivityException e) { + ui.printDivider("No activity with this name exists!"); + logger.makeInfoLog("Edit command failed as there was no such activity saved."); + } catch (ArrayIndexOutOfBoundsException | EmptyNameException e) { + ui.printDivider("Activity name cannot be empty!"); + logger.makeInfoLog("Edit command failed as there was no existing activity name provided."); + } catch (StringIndexOutOfBoundsException e) { + ui.printDivider("New activity name not provided!"); + logger.makeInfoLog("Edit command failed as there was no new activity name provided."); + } + break; default: parseDefault(); break; @@ -379,6 +393,28 @@ public void parseContinue(ActivityList activityList) throws NoSuchActivityExcept } } + /** + * Edits the detail of an activity in the activityList. + * @param activityList the activity list containing the activity to edit. + */ + public void parseEdit(ActivityList activityList) throws EmptyNameException, NoSuchActivityException { + int delimiter = tokenizedInputs[1].indexOf("/e"); + activityName = tokenizedInputs[1].substring(0, delimiter).strip(); + if (activityName.isEmpty()) { + throw new EmptyNameException(); + } + int index = activityList.findActivity(activityName); + String newName = tokenizedInputs[1].substring(delimiter + 3); + if (index != -1) { + activityList.updateName(index,newName); + ui.printDivider("Activity named " + activityName + " has been updated to " + newName); + } else { + // activity is not found + throw new NoSuchActivityException(); + } + logger.makeFineLog("Activity name has been updated!"); + } + /** Method to parse user inputs that are not recognised. */ private void parseDefault() { String line = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; From 455b385f157f055f7460f8f0014a5d14b94e6f95 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 23 Mar 2020 01:12:36 +0800 Subject: [PATCH 093/415] Add storage cleaner v1.0 --- src/main/java/jikan/Jikan.java | 11 +- src/main/java/jikan/parser/Parser.java | 28 +++- .../java/jikan/storage/StorageCleaner.java | 127 ++++++++++++++++++ src/main/java/jikan/ui/Ui.java | 2 +- 4 files changed, 164 insertions(+), 4 deletions(-) create mode 100644 src/main/java/jikan/storage/StorageCleaner.java diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 5cf7391b7..e4d8f4839 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -4,8 +4,10 @@ import jikan.exception.InvalidTimeFrameException; import jikan.parser.Parser; import jikan.storage.Storage; +import jikan.storage.StorageCleaner; import jikan.ui.Ui; +import java.io.IOException; import java.util.Scanner; /** @@ -27,15 +29,20 @@ public class Jikan { /** Parser to parse commands. */ private static Parser parser = new Parser(); + /** CLeaner to delete entries in data.csv when it gets too long */ + private static StorageCleaner cleaner; + /** * Main entry-point for the Jikan application. */ - public static void main(String[] args) throws InvalidTimeFrameException { + public static void main(String[] args) throws InvalidTimeFrameException, IOException { ui.printGreeting(); Scanner in = new Scanner(System.in); storage = new Storage(DATA_FILE_PATH); + cleaner = new StorageCleaner(storage); + cleaner.autoClean(); activityList = storage.createActivityList(); activityList.storage = storage; - parser.parseUserCommands(in, activityList); + parser.parseUserCommands(in, activityList, cleaner); } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 221300645..f874d1dac 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -6,9 +6,11 @@ import jikan.exception.EmptyQueryException; import jikan.exception.InvalidTimeFrameException; import jikan.exception.NoSuchActivityException; +import jikan.storage.StorageCleaner; import jikan.ui.Ui; import jikan.Log; +import java.io.IOException; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; @@ -29,6 +31,7 @@ public class Parser { private String activityName = null; private Set tags = new HashSet<>(); private Ui ui = new Ui(); + private StorageCleaner cleaner; protected String[] tokenizedInputs; String instruction; Log logger = new Log(); @@ -42,8 +45,10 @@ public class Parser { * @param scanner scanner object which reads user input * @param activityList the list of activities */ - public void parseUserCommands(Scanner scanner, ActivityList activityList) throws InvalidTimeFrameException { + public void parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) + throws InvalidTimeFrameException { logger.makeInfoLog("Starting to parse inputs."); + this.cleaner = cleaner; /*lastShownList is initialised here to facilitate subsequent delete and edit commands referencing by index of this list. */ @@ -124,6 +129,13 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) throws logger.makeInfoLog("Continue command failed as there was no such activity saved."); } break; + case "clean": + try { + parseClean(tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException | IOException e) { + ui.printDivider("No keyword was given."); + } + break; default: parseDefault(); break; @@ -131,6 +143,20 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList) throws } } + private void parseClean(String tokenizedInput) throws IOException { + String line; + if (tokenizedInput.equals("on")) { + cleaner.setStatus(true); + line = "Auto cleaning enabled"; + } else if (tokenizedInput.equals("off")) { + cleaner.setStatus(false); + line = "Auto cleaning disabled"; + } else { + line = "Invalid Command!"; + } + ui.printDivider(line); + } + /** * Checks for ongoing activities and ask if user wants to save them * before exiting the app. diff --git a/src/main/java/jikan/storage/StorageCleaner.java b/src/main/java/jikan/storage/StorageCleaner.java new file mode 100644 index 000000000..c1cd18775 --- /dev/null +++ b/src/main/java/jikan/storage/StorageCleaner.java @@ -0,0 +1,127 @@ +package jikan.storage; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +public class StorageCleaner { + private static final String STATUS_FILE_PATH = "data/recycled/status.txt"; + private static final String DATA_FILE_PATH = "data/recycled/data.csv"; + private File status; + private File recycledData; + public boolean toClean; + private int numberOfActivitiesToClean = 3; + public Storage storage; + + public StorageCleaner(Storage storage) { + this.storage = storage; + status = new File(STATUS_FILE_PATH); + recycledData = new File(DATA_FILE_PATH); + initialiseCleaner(); + initialiseDataFile(); + } + + private void initialiseDataFile() { + try { + loadFile(recycledData); + } catch (IOException e) { + System.out.println("Error loading/creating recycled file"); + } + } + + private void initialiseCleaner() { + try { + if (loadCleaner(status)) { + Scanner sc = new Scanner(status); + String status = sc.nextLine(); + int value = Integer.parseInt(status); + if (value == 1) { + this.toClean = true; + } else { + this.toClean = false; + } + } else { + FileWriter fw = new FileWriter(status); + fw.write("0"); + fw.close(); + } + } catch (IOException e) { + System.out.println("Error loading/creating cleaning file."); + } + } + + private boolean loadCleaner(File file) throws IOException { + if (!file.exists()) { + createFile(file); + return false; + } else { + return true; + } + } + + private void loadFile(File file) throws IOException { + if (!file.exists()) { + createFile(file); + } + } + + private void createFile(File file) throws IOException { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + + public void setStatus(boolean status) throws IOException { + this.toClean = status; + File dataFile = new File(STATUS_FILE_PATH); + if (!dataFile.exists()) { + dataFile.createNewFile(); + } + BufferedWriter writer = new BufferedWriter(new FileWriter(dataFile)); + if (this.toClean) { + writer.write("1"); + } else { + writer.write("0"); + } + writer.close(); + } + + public void autoClean() throws IOException { + List activitiesForRecycling = new ArrayList<>(); + List activitiesLeftInData = new ArrayList<>(); + if (this.toClean) { + String filePath = storage.dataFilePath; + File liveData = new File(filePath); + Scanner recycledDataScanner = new Scanner(recycledData); + Scanner liveDataScanner = new Scanner(liveData); + while (recycledDataScanner.hasNext()) { + String line = recycledDataScanner.nextLine(); + activitiesForRecycling.add(line); + } + while (numberOfActivitiesToClean != 0) { + String line = liveDataScanner.nextLine(); + activitiesForRecycling.add(line); + numberOfActivitiesToClean -= 1; + } + while (liveDataScanner.hasNext()) { + String line = liveDataScanner.nextLine(); + activitiesLeftInData.add(line); + } + + BufferedWriter recycledDataWriter = new BufferedWriter(new FileWriter(recycledData)); + for (String line : activitiesForRecycling) { + recycledDataWriter.write(line + "\n"); + } + recycledDataWriter.close(); + BufferedWriter liveDataWriter = new BufferedWriter(new FileWriter(liveData)); + for (String line : activitiesLeftInData) { + liveDataWriter.write(line + "\n"); + } + liveDataWriter.close(); + } + + } +} diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 35b88bee6..f45484e96 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -7,7 +7,7 @@ public class Ui { public static final String GREETING = "Jikan"; - public static final String DIVIDER = "-------------------------------------------"; + public static final String DIVIDER = "-----------------------------------------------------------------"; /** Prints the logo and greeting so users know the app is working. */ public void printGreeting() { From 6d9d8fee4850dc2e1571e199e95463fd2d96f00d Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 23 Mar 2020 02:01:20 +0800 Subject: [PATCH 094/415] Updated EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 63 ++++++++++++++------------- text-ui-test/data/LogRecord.txt | 12 +++++ text-ui-test/data/data.csv | 13 +++++- text-ui-test/data/recycled/data.csv | 0 text-ui-test/data/recycled/status.txt | 1 + 5 files changed, 57 insertions(+), 32 deletions(-) create mode 100644 text-ui-test/data/recycled/data.csv create mode 100644 text-ui-test/data/recycled/status.txt diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 9e7602ea5..c4e289259 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,47 +1,48 @@ Jikan -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- Started: activity one -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- Ended: activity one -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- Started: activity two -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- activity two is ongoing! -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- Ended: activity two -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- activity one was continued -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- You have aborted the current activity! -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- There is already an activity with this name. Would you like to continue it? -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- activity two was continued -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- Ended: activity two -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- Started: activity three -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- Ended: activity three -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- Started: four -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- Ended: four -------------------------------------------- -------------------------------------------- +----------------------------------------------------------------- +----------------------------------------------------------------- Bye! See you again. -------------------------------------------- +----------------------------------------------------------------- + diff --git a/text-ui-test/data/LogRecord.txt b/text-ui-test/data/LogRecord.txt index 8b1378917..a5645a647 100644 --- a/text-ui-test/data/LogRecord.txt +++ b/text-ui-test/data/LogRecord.txt @@ -1 +1,13 @@ +Mar 23, 2020 1:58:04 AM jikan.Log makeInfoLog +INFO: Starting to parse inputs. +Mar 23, 2020 1:58:04 AM jikan.Log makeInfoLog +INFO: Could not start activity due to already ongoing activity. +Mar 23, 2020 1:58:20 AM jikan.Log makeInfoLog +INFO: Starting to parse inputs. +Mar 23, 2020 1:58:20 AM jikan.Log makeInfoLog +INFO: Could not start activity due to already ongoing activity. +Mar 23, 2020 2:00:14 AM jikan.Log makeInfoLog +INFO: Starting to parse inputs. +Mar 23, 2020 2:00:14 AM jikan.Log makeInfoLog +INFO: Could not start activity due to already ongoing activity. diff --git a/text-ui-test/data/data.csv b/text-ui-test/data/data.csv index 8b1378917..52603b27b 100644 --- a/text-ui-test/data/data.csv +++ b/text-ui-test/data/data.csv @@ -1 +1,12 @@ - +activity one,2020-03-23T01:58:04.634544500,2020-03-23T01:58:04.637536700,PT0.0029922S,tag1 tag tag2 +activity two,2020-03-23T01:58:04.713335600,2020-03-23T02:00:14.918670400,PT0.01097S,tag2 +activity three,2020-03-23T01:58:04.729292400,2020-03-23T01:58:04.730288200,PT0.0009958S,tag1 tag +four,2020-03-23T01:58:04.732089400,2020-03-23T01:58:04.732452600,PT0.0003632S,tag +activity one,2020-03-23T01:58:20.293251,2020-03-23T01:58:20.295246400,PT0.0019954S,tag1 tag tag2 +activity two,2020-03-23T01:58:20.369048900,2020-03-23T01:58:20.372096600,PT0.0030477S,tag2 +activity three,2020-03-23T01:58:20.382014200,2020-03-23T01:58:20.383111400,PT0.0010972S,tag1 tag +four,2020-03-23T01:58:20.384009,2020-03-23T01:58:20.384009,PT0S,tag +activity one,2020-03-23T02:00:14.836888400,2020-03-23T02:00:14.838883,PT0.0019946S,tag1 tag tag2 +activity two,2020-03-23T02:00:14.910753,2020-03-23T02:00:14.913683700,PT0.0029307S,tag2 +activity three,2020-03-23T02:00:14.922660,2020-03-23T02:00:14.923659300,PT0.0009993S,tag1 tag +four,2020-03-23T02:00:14.924713600,2020-03-23T02:00:14.924713600,PT0S,tag diff --git a/text-ui-test/data/recycled/data.csv b/text-ui-test/data/recycled/data.csv new file mode 100644 index 000000000..e69de29bb diff --git a/text-ui-test/data/recycled/status.txt b/text-ui-test/data/recycled/status.txt new file mode 100644 index 000000000..c22708346 --- /dev/null +++ b/text-ui-test/data/recycled/status.txt @@ -0,0 +1 @@ +0 \ No newline at end of file From 30be23b1292b9f37c3e4121dc0b8f733fab267b4 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 23 Mar 2020 02:07:48 +0800 Subject: [PATCH 095/415] Some more edits to EXPECTED.TXT --- text-ui-test/EXPECTED.TXT | 1 - text-ui-test/data/LogRecord.txt | 8 ++++++++ text-ui-test/data/data.csv | 10 +++++++++- 3 files changed, 17 insertions(+), 2 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index c4e289259..03809fa1c 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -45,4 +45,3 @@ Ended: four ----------------------------------------------------------------- Bye! See you again. ----------------------------------------------------------------- - diff --git a/text-ui-test/data/LogRecord.txt b/text-ui-test/data/LogRecord.txt index a5645a647..9b6acc4bd 100644 --- a/text-ui-test/data/LogRecord.txt +++ b/text-ui-test/data/LogRecord.txt @@ -11,3 +11,11 @@ Mar 23, 2020 2:00:14 AM jikan.Log makeInfoLog INFO: Starting to parse inputs. Mar 23, 2020 2:00:14 AM jikan.Log makeInfoLog INFO: Could not start activity due to already ongoing activity. +Mar 23, 2020 2:05:41 AM jikan.Log makeInfoLog +INFO: Starting to parse inputs. +Mar 23, 2020 2:05:41 AM jikan.Log makeInfoLog +INFO: Could not start activity due to already ongoing activity. +Mar 23, 2020 2:07:09 AM jikan.Log makeInfoLog +INFO: Starting to parse inputs. +Mar 23, 2020 2:07:10 AM jikan.Log makeInfoLog +INFO: Could not start activity due to already ongoing activity. diff --git a/text-ui-test/data/data.csv b/text-ui-test/data/data.csv index 52603b27b..9614798e3 100644 --- a/text-ui-test/data/data.csv +++ b/text-ui-test/data/data.csv @@ -1,5 +1,5 @@ activity one,2020-03-23T01:58:04.634544500,2020-03-23T01:58:04.637536700,PT0.0029922S,tag1 tag tag2 -activity two,2020-03-23T01:58:04.713335600,2020-03-23T02:00:14.918670400,PT0.01097S,tag2 +activity two,2020-03-23T01:58:04.713335600,2020-03-23T02:07:10.115384500,PT0.0153143S,tag2 activity three,2020-03-23T01:58:04.729292400,2020-03-23T01:58:04.730288200,PT0.0009958S,tag1 tag four,2020-03-23T01:58:04.732089400,2020-03-23T01:58:04.732452600,PT0.0003632S,tag activity one,2020-03-23T01:58:20.293251,2020-03-23T01:58:20.295246400,PT0.0019954S,tag1 tag tag2 @@ -10,3 +10,11 @@ activity one,2020-03-23T02:00:14.836888400,2020-03-23T02:00:14.838883,PT0.001994 activity two,2020-03-23T02:00:14.910753,2020-03-23T02:00:14.913683700,PT0.0029307S,tag2 activity three,2020-03-23T02:00:14.922660,2020-03-23T02:00:14.923659300,PT0.0009993S,tag1 tag four,2020-03-23T02:00:14.924713600,2020-03-23T02:00:14.924713600,PT0S,tag +activity one,2020-03-23T02:05:41.553188600,2020-03-23T02:05:41.554188500,PT0.0009999S,tag1 tag tag2 +activity two,2020-03-23T02:05:41.633972,2020-03-23T02:05:41.637024800,PT0.0030528S,tag2 +activity three,2020-03-23T02:05:41.648931600,2020-03-23T02:05:41.649927800,PT0.0009962S,tag1 tag +four,2020-03-23T02:05:41.651922600,2020-03-23T02:05:41.651922600,PT0S,tag +activity one,2020-03-23T02:07:10.031313500,2020-03-23T02:07:10.032423700,PT0.0011102S,tag1 tag tag2 +activity two,2020-03-23T02:07:10.108257100,2020-03-23T02:07:10.110102300,PT0.0018452S,tag2 +activity three,2020-03-23T02:07:10.121074100,2020-03-23T02:07:10.121074100,PT0S,tag1 tag +four,2020-03-23T02:07:10.123067900,2020-03-23T02:07:10.123067900,PT0S,tag From 3db3976e1ad9f76f8d815e0d11f24be92daa55ad Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 23 Mar 2020 15:32:21 +0800 Subject: [PATCH 096/415] Refactor code to extract out command classes --- src/main/java/jikan/Jikan.java | 14 +- src/main/java/jikan/Log.java | 2 +- src/main/java/jikan/command/AbortCommand.java | 30 +++ src/main/java/jikan/command/ByeCommand.java | 40 ++++ src/main/java/jikan/command/CleanCommand.java | 31 +++ src/main/java/jikan/command/Command.java | 25 ++ .../java/jikan/command/ContinueCommand.java | 30 +++ .../java/jikan/command/DeleteCommand.java | 27 +++ src/main/java/jikan/command/EditCommand.java | 38 +++ src/main/java/jikan/command/EndCommand.java | 38 +++ .../java/jikan/command/FilterCommand.java | 30 +++ src/main/java/jikan/command/FindCommand.java | 30 +++ src/main/java/jikan/command/ListCommand.java | 34 +++ src/main/java/jikan/command/StartCommand.java | 34 +++ src/main/java/jikan/parser/Parser.java | 216 +++++++----------- src/main/java/jikan/ui/Ui.java | 4 +- 16 files changed, 491 insertions(+), 132 deletions(-) create mode 100644 src/main/java/jikan/command/AbortCommand.java create mode 100644 src/main/java/jikan/command/ByeCommand.java create mode 100644 src/main/java/jikan/command/CleanCommand.java create mode 100644 src/main/java/jikan/command/Command.java create mode 100644 src/main/java/jikan/command/ContinueCommand.java create mode 100644 src/main/java/jikan/command/DeleteCommand.java create mode 100644 src/main/java/jikan/command/EditCommand.java create mode 100644 src/main/java/jikan/command/EndCommand.java create mode 100644 src/main/java/jikan/command/FilterCommand.java create mode 100644 src/main/java/jikan/command/FindCommand.java create mode 100644 src/main/java/jikan/command/ListCommand.java create mode 100644 src/main/java/jikan/command/StartCommand.java diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 6bcf063d8..74ba7c518 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -1,6 +1,8 @@ package jikan; import jikan.activity.ActivityList; +import jikan.command.ByeCommand; +import jikan.command.Command; import jikan.exception.InvalidTimeFrameException; import jikan.parser.Parser; import jikan.storage.Storage; @@ -43,6 +45,16 @@ public static void main(String[] args) throws InvalidTimeFrameException, IOExcep activityList = storage.createActivityList(); activityList.storage = storage; Scanner in = new Scanner(System.in); - parser.parseUserCommands(in, activityList, cleaner); + while (true) { + Command command = parser.parseUserCommands(in,activityList,cleaner); + if (command == null) { + continue; + } + if (ByeCommand.isExit(command)) { + command.executeCommand(activityList); + break; + } + command.executeCommand(activityList); + } } } diff --git a/src/main/java/jikan/Log.java b/src/main/java/jikan/Log.java index 5b8f3f46c..dee90be03 100644 --- a/src/main/java/jikan/Log.java +++ b/src/main/java/jikan/Log.java @@ -66,7 +66,7 @@ public void makeFineLog(String message) { * Creates a long entry at INFO level. * @param message the INFO message to be logged */ - public void makeInfoLog(String message) { + public static void makeInfoLog(String message) { logger.log(Level.INFO, message); } diff --git a/src/main/java/jikan/command/AbortCommand.java b/src/main/java/jikan/command/AbortCommand.java new file mode 100644 index 000000000..fb9bcb7ee --- /dev/null +++ b/src/main/java/jikan/command/AbortCommand.java @@ -0,0 +1,30 @@ +package jikan.command; + +import jikan.Log; +import jikan.activity.ActivityList; +import jikan.exception.NoSuchActivityException; +import jikan.parser.Parser; +import jikan.ui.Ui; +import jikan.Log; + +/** + * Represents a command to abort a currently running activity. + */ +public class AbortCommand extends Command { + + /** + * Constructor to create a new abort command. + */ + public AbortCommand() { + } + + @Override + public void executeCommand(ActivityList activityList) { + try { + Parser.parseAbort(); + } catch (NoSuchActivityException e) { + Ui.printDivider("You have not started any activity!"); + Log.makeInfoLog("Abort command failed as no activity was ongoing"); + } + } +} diff --git a/src/main/java/jikan/command/ByeCommand.java b/src/main/java/jikan/command/ByeCommand.java new file mode 100644 index 000000000..1ebb369ca --- /dev/null +++ b/src/main/java/jikan/command/ByeCommand.java @@ -0,0 +1,40 @@ +package jikan.command; + +import jikan.Log; +import jikan.activity.ActivityList; +import jikan.exception.InvalidTimeFrameException; +import jikan.parser.Parser; +import jikan.ui.Ui; + +import java.util.Scanner; + + +/** + * Terminates the program. + */ +public class ByeCommand extends Command { + + private Scanner scanner; + + /** + * Constructor to create a new exit command. + */ + public ByeCommand() { + } + + @Override + public void executeCommand(ActivityList activityList) { + + try { + Parser.parseBye(activityList, scanner); + } catch (InvalidTimeFrameException e) { + Log.makeInfoLog("End date must be before start date"); + Ui.printDivider("End date must be before start date."); + } + } + + public static boolean isExit(Command command) { + return command instanceof ByeCommand; // instanceof returns false if it is null + } + +} diff --git a/src/main/java/jikan/command/CleanCommand.java b/src/main/java/jikan/command/CleanCommand.java new file mode 100644 index 000000000..08df1378c --- /dev/null +++ b/src/main/java/jikan/command/CleanCommand.java @@ -0,0 +1,31 @@ +package jikan.command; + +import jikan.activity.ActivityList; +import jikan.parser.Parser; +import jikan.ui.Ui; + +import java.io.IOException; + +import static jikan.parser.Parser.tokenizedInputs; + +/** + * Represents a command to clear previously saved log files. + */ +public class CleanCommand extends Command { + + /** + * Constructor to create a new clean command. + */ + public CleanCommand() { + } + + @Override + public void executeCommand(ActivityList activityList) { + try { + Parser.parseClean(tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException | IOException e) { + Ui.printDivider("No keyword was given."); + } + } + +} diff --git a/src/main/java/jikan/command/Command.java b/src/main/java/jikan/command/Command.java new file mode 100644 index 000000000..4cfa6398b --- /dev/null +++ b/src/main/java/jikan/command/Command.java @@ -0,0 +1,25 @@ +package jikan.command; + +import jikan.activity.ActivityList; + + +/** + * Represents an executable command. + */ +public class Command { + + /** + * Constructor to create a new command. + */ + public Command() { + } + + /** + * Executes the command and returns the result. + */ + public void executeCommand(ActivityList activityList) { + } + + +} + diff --git a/src/main/java/jikan/command/ContinueCommand.java b/src/main/java/jikan/command/ContinueCommand.java new file mode 100644 index 000000000..e0ff411a9 --- /dev/null +++ b/src/main/java/jikan/command/ContinueCommand.java @@ -0,0 +1,30 @@ +package jikan.command; + +import jikan.Log; +import jikan.activity.ActivityList; +import jikan.exception.NoSuchActivityException; +import jikan.parser.Parser; +import jikan.ui.Ui; + +/** + * Represents a command to continue recording an existing activity. + */ +public class ContinueCommand extends Command { + + /** + * Constructor to create a new continue command. + */ + public ContinueCommand() { + } + + @Override + public void executeCommand(ActivityList activityList) { + try { + Parser.parseContinue(activityList); + } catch (NoSuchActivityException e) { + Ui.printDivider("No activity with this name exists!"); + Log.makeInfoLog("Continue command failed as there was no such activity saved."); + } + } +} + diff --git a/src/main/java/jikan/command/DeleteCommand.java b/src/main/java/jikan/command/DeleteCommand.java new file mode 100644 index 000000000..1704ed6fe --- /dev/null +++ b/src/main/java/jikan/command/DeleteCommand.java @@ -0,0 +1,27 @@ +package jikan.command; + +import jikan.activity.ActivityList; +import jikan.exception.NoSuchActivityException; +import jikan.parser.Parser; +import jikan.ui.Ui; + +/** + * Represents a command to delete an activity from the activity list. + */ +public class DeleteCommand extends Command { + + /** + * Constructor to create a new delete command. + */ + public DeleteCommand() { + } + + @Override + public void executeCommand(ActivityList activityList) { + try { + Parser.parseDelete(activityList); + } catch (NoSuchActivityException e) { + Ui.printDivider("No activity with this name exists!"); + } + } +} diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java new file mode 100644 index 000000000..924d61213 --- /dev/null +++ b/src/main/java/jikan/command/EditCommand.java @@ -0,0 +1,38 @@ +package jikan.command; + +import jikan.Log; +import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; +import jikan.exception.NoSuchActivityException; +import jikan.parser.Parser; +import jikan.ui.Ui; + +/** + * Represents a command to edit an activity in the activity list. + */ +public class EditCommand extends Command { + + /** + * Constructor to create a new edit command. + */ + public EditCommand() { + } + + @Override + public void executeCommand(ActivityList activityList) { + try { + Parser.parseEdit(activityList); + } catch (NoSuchActivityException e) { + Ui.printDivider("No activity with this name exists!"); + Log.makeInfoLog("Edit command failed as there was no such activity saved."); + } catch (ArrayIndexOutOfBoundsException | EmptyNameException e) { + Ui.printDivider("Activity name cannot be empty!"); + Log.makeInfoLog("Edit command failed as there was no existing activity name provided."); + } catch (StringIndexOutOfBoundsException e) { + Ui.printDivider("New activity name not provided!"); + Log.makeInfoLog("Edit command failed as there was no new activity name provided."); + } + } + + +} diff --git a/src/main/java/jikan/command/EndCommand.java b/src/main/java/jikan/command/EndCommand.java new file mode 100644 index 000000000..3ab6660b9 --- /dev/null +++ b/src/main/java/jikan/command/EndCommand.java @@ -0,0 +1,38 @@ +package jikan.command; + +import jikan.Log; +import jikan.activity.ActivityList; +import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NoSuchActivityException; +import jikan.parser.Parser; +import jikan.ui.Ui; + +import java.util.Scanner; + +/** + * Represents a command to end an activity. + */ +public class EndCommand extends Command { + + + private Scanner scanner; + + /** + * Constructor to create a new end command. + */ + public EndCommand() { + } + + @Override + public void executeCommand(ActivityList activityList) { + try { + Parser.parseEnd(activityList); + } catch (NoSuchActivityException e) { + Log.makeInfoLog("End command failed as no activity was ongoing"); + Ui.printDivider("You have not started any activity!"); + } catch (InvalidTimeFrameException e) { + Log.makeInfoLog("End date must be before start date"); + Ui.printDivider("End date must be before start date."); + } + } +} diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java new file mode 100644 index 000000000..ac081c3ac --- /dev/null +++ b/src/main/java/jikan/command/FilterCommand.java @@ -0,0 +1,30 @@ +package jikan.command; + +import jikan.activity.ActivityList; +import jikan.exception.EmptyQueryException; +import jikan.parser.Parser; +import jikan.ui.Ui; + +import static jikan.parser.Parser.lastShownList; +import static jikan.parser.Parser.tokenizedInputs; + +/** + * Represents a command to filter activities based on user-specified criterias. + */ +public class FilterCommand extends Command { + + /** + * Constructor to create a new filter command. + */ + public FilterCommand() { + } + + @Override + public void executeCommand(ActivityList activityList) { + try { + Parser.parseFilter(activityList, lastShownList, tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { + Ui.printDivider("No keyword was given."); + } + } +} diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java new file mode 100644 index 000000000..b01ef5261 --- /dev/null +++ b/src/main/java/jikan/command/FindCommand.java @@ -0,0 +1,30 @@ +package jikan.command; + +import jikan.activity.ActivityList; +import jikan.exception.EmptyQueryException; +import jikan.parser.Parser; +import jikan.ui.Ui; + +import static jikan.parser.Parser.lastShownList; +import static jikan.parser.Parser.tokenizedInputs; + +/** + * Represents a command to find activities in the activity list. + */ +public class FindCommand extends Command { + + /** + * Constructor to create a new find command. + */ + public FindCommand() { + } + + @Override + public void executeCommand(ActivityList activityList) { + try { + Parser.parseFind(activityList, lastShownList, tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { + Ui.printDivider("No keyword was given."); + } + } +} diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java new file mode 100644 index 000000000..6e1710611 --- /dev/null +++ b/src/main/java/jikan/command/ListCommand.java @@ -0,0 +1,34 @@ +package jikan.command; + +import jikan.Log; +import jikan.activity.ActivityList; +import jikan.ui.Ui; +import jikan.parser.Parser; + +import jikan.exception.InvalidTimeFrameException; +import java.time.format.DateTimeParseException; + +/** + * Represents a command to list all activities in the activity list to the user. + */ +public class ListCommand extends Command { + + /** + * Constructor to create a new list command. + */ + public ListCommand() { + } + + @Override + public void executeCommand(ActivityList activityList) { + try { + Parser.parseList(activityList); + } catch (InvalidTimeFrameException e) { + Log.makeInfoLog("Specified time range not valid"); + Ui.printDivider("The time range specified is not valid."); + } catch (DateTimeParseException e) { + Log.makeInfoLog("Specified time range was not in the valid format"); + Ui.printDivider("Please input your dates as either yyyy-MM-dd or dd/MM/yyyy."); + } + } +} diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java new file mode 100644 index 000000000..34dfd2c5f --- /dev/null +++ b/src/main/java/jikan/command/StartCommand.java @@ -0,0 +1,34 @@ +package jikan.command; + +import jikan.Log; +import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; +import jikan.parser.Parser; +import jikan.ui.Ui; + +import java.util.Scanner; + +/** + * Represents a command to start an activity. + */ +public class StartCommand extends Command { + + private Scanner scanner; + + /** + * Constructor to create a new start command. + */ + public StartCommand() { + } + + @Override + public void executeCommand(ActivityList activityList) { + try { + Parser.parseStart(activityList, scanner); + } catch (EmptyNameException | NullPointerException | ArrayIndexOutOfBoundsException e) { + Log.makeInfoLog("Activity started without task name"); + Ui.printDivider("Task name cannot be empty!"); + } + } + +} diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 807b120e4..db1723c61 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,5 +1,18 @@ package jikan.parser; +import jikan.command.AbortCommand; +import jikan.command.ByeCommand; +import jikan.command.Command; +import jikan.command.CleanCommand; +import jikan.command.ContinueCommand; +import jikan.command.DeleteCommand; +import jikan.command.EditCommand; +import jikan.command.EndCommand; +import jikan.command.FindCommand; +import jikan.command.FilterCommand; +import jikan.command.ListCommand; +import jikan.command.StartCommand; + import jikan.exception.EmptyNameException; import jikan.activity.Activity; import jikan.activity.ActivityList; @@ -26,26 +39,26 @@ */ public class Parser { - protected LocalDateTime startTime = null; - protected LocalDateTime endTime = null; - private String activityName = null; - private Set tags = new HashSet<>(); - private Ui ui = new Ui(); - private StorageCleaner cleaner; - protected String[] tokenizedInputs; + protected static LocalDateTime startTime = null; + protected static LocalDateTime endTime = null; + private static String activityName = null; + private static Set tags = new HashSet<>(); + private static Ui ui = new Ui(); + private static StorageCleaner cleaner; + public static String[] tokenizedInputs; String instruction; - Log logger = new Log(); - private ActivityList lastShownList = new ActivityList(); + static Log logger = new Log(); + public static ActivityList lastShownList = new ActivityList(); // flag to check if the current activity is a continued one - public int continuedIndex = -1; + public static int continuedIndex = -1; /** * Parses user commands to relevant functions to carry out the commands. * @param scanner scanner object which reads user input * @param activityList the list of activities */ - public void parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) + public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) throws InvalidTimeFrameException { logger.makeInfoLog("Starting to parse inputs."); this.cleaner = cleaner; @@ -53,111 +66,58 @@ public void parseUserCommands(Scanner scanner, ActivityList activityList, Storag referencing by index of this list. */ lastShownList.activities.addAll(activityList.activities); - while (true) { - String userInput = scanner.nextLine(); - tokenizedInputs = userInput.split(" ", 2); - instruction = tokenizedInputs[0]; - - switch (instruction) { - case "bye": - parseBye(activityList, scanner); - break; - case "start": - try { - parseStart(activityList, scanner); - } catch (EmptyNameException | NullPointerException | ArrayIndexOutOfBoundsException e) { - logger.makeInfoLog("Activity started without task name"); - ui.printDivider("Task name cannot be empty!"); - } - break; - case "end": - try { - parseEnd(activityList); - } catch (NoSuchActivityException e) { - logger.makeInfoLog("End command failed as no activity was ongoing"); - ui.printDivider("You have not started any activity!"); - } catch (InvalidTimeFrameException e) { - logger.makeInfoLog("End date must be before start date"); - ui.printDivider("End date must be before start date."); - } - break; - case "list": - try { - parseList(activityList); - } catch (InvalidTimeFrameException e) { - logger.makeInfoLog("Specified time range not valid"); - ui.printDivider("The time range specified is not valid."); - } catch (DateTimeParseException e) { - logger.makeInfoLog("Specified time range was not in the valid format"); - ui.printDivider("Please input your dates as either yyyy-MM-dd or dd/MM/yyyy."); - } - break; - case "abort": - try { - parseAbort(); - } catch (NoSuchActivityException e) { - ui.printDivider("You have not started any activity!"); - logger.makeInfoLog("Abort command failed as no activity was ongoing"); - } - break; - case "delete": - try { - parseDelete(activityList); - } catch (NoSuchActivityException e) { - ui.printDivider("No activity with this name exists!"); - } - break; - case "find": - try { - parseFind(activityList, lastShownList, tokenizedInputs[1]); - } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { - ui.printDivider("No keyword was given."); - } - break; - case "filter": - try { - parseFilter(activityList, lastShownList, tokenizedInputs[1]); - } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { - ui.printDivider("No keyword was given."); - } - break; - case "continue": - try { - parseContinue(activityList); - } catch (NoSuchActivityException e) { - ui.printDivider("No activity with this name exists!"); - logger.makeInfoLog("Continue command failed as there was no such activity saved."); - } - break; - case "clean": - try { - parseClean(tokenizedInputs[1]); - } catch (ArrayIndexOutOfBoundsException | IOException e) { - ui.printDivider("No keyword was given."); - } - break; - case "edit": - try { - parseEdit(activityList); - } catch (NoSuchActivityException e) { - ui.printDivider("No activity with this name exists!"); - logger.makeInfoLog("Edit command failed as there was no such activity saved."); - } catch (ArrayIndexOutOfBoundsException | EmptyNameException e) { - ui.printDivider("Activity name cannot be empty!"); - logger.makeInfoLog("Edit command failed as there was no existing activity name provided."); - } catch (StringIndexOutOfBoundsException e) { - ui.printDivider("New activity name not provided!"); - logger.makeInfoLog("Edit command failed as there was no new activity name provided."); - } - break; - default: - parseDefault(); - break; - } + String userInput = scanner.nextLine(); + tokenizedInputs = userInput.split(" ", 2); + instruction = tokenizedInputs[0]; + Command command = null; + + switch (instruction) { + case "bye": + command = new ByeCommand(); + break; + case "start": + command = new StartCommand(); + break; + case "end": + command = new EndCommand(); + break; + case "abort": + command = new AbortCommand(); + break; + case "list": + command = new ListCommand(); + break; + case "delete": + command = new DeleteCommand(); + break; + case "find": + command = new FindCommand(); + break; + case "filter": + command = new FilterCommand(); + break; + case "edit": + command = new EditCommand(); + break; + case "clean": + command = new CleanCommand(); + break; + case "continue": + command = new ContinueCommand(); + break; + default: + parseDefault(); + break; } + return command; } - private void parseClean(String tokenizedInput) throws IOException { + /** + * Method to enable or disable cleaning of log files. + * @param tokenizedInput user input of 'on' or 'off' + * @throws IOException if input is incorrect. + */ + public static void parseClean(String tokenizedInput) throws IOException { String line; if (tokenizedInput.equals("on")) { cleaner.setStatus(true); @@ -179,7 +139,7 @@ private void parseClean(String tokenizedInput) throws IOException { * @param scanner To parse user input. * @throws InvalidTimeFrameException precautionary measure for if endTime is greater than startTime. */ - public void parseBye(ActivityList activityList, Scanner scanner) throws InvalidTimeFrameException { + public static void parseBye(ActivityList activityList, Scanner scanner) throws InvalidTimeFrameException { if (startTime != null) { String line = activityName + " is still running! If you exit now it will be aborted.\n" + "Would you like to end this activity to save it?"; @@ -199,7 +159,7 @@ public void parseBye(ActivityList activityList, Scanner scanner) throws InvalidT * @param activityList List of activities. * @param scanner To parse user input. */ - public void parseStart(ActivityList activityList, Scanner scanner) + public static void parseStart(ActivityList activityList, Scanner scanner) throws ArrayIndexOutOfBoundsException, EmptyNameException, NullPointerException { // check if an activity has already been started if (startTime != null) { @@ -231,7 +191,7 @@ public void parseStart(ActivityList activityList, Scanner scanner) * @param activityList List of activities. * @param scanner Parse user input. */ - private void continueActivity(ActivityList activityList, Scanner scanner, int index) { + private static void continueActivity(ActivityList activityList, Scanner scanner, int index) { String userInput = scanner.nextLine(); if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { activityName = activityList.get(index).getName(); @@ -250,7 +210,7 @@ private void continueActivity(ActivityList activityList, Scanner scanner, int in * * @param delimiter The index of the tag delimiter. */ - private String parseActivity(int delimiter) throws EmptyNameException { + private static String parseActivity(int delimiter) throws EmptyNameException { if (delimiter == -1) { // no tags activityName = tokenizedInputs[1].strip(); @@ -269,7 +229,7 @@ private String parseActivity(int delimiter) throws EmptyNameException { } /** Method to parse the end activity command. */ - public void parseEnd(ActivityList activityList) throws NoSuchActivityException, InvalidTimeFrameException { + public static void parseEnd(ActivityList activityList) throws NoSuchActivityException, InvalidTimeFrameException { if (startTime == null) { throw new NoSuchActivityException(); } else { @@ -284,7 +244,7 @@ public void parseEnd(ActivityList activityList) throws NoSuchActivityException, * * @param activityList The activity list to search for matching activities. */ - private void parseList(ActivityList activityList) throws InvalidTimeFrameException, DateTimeParseException { + public static void parseList(ActivityList activityList) throws InvalidTimeFrameException, DateTimeParseException { // If no time frame is specified, print the entire list if (tokenizedInputs.length == 1) { @@ -331,7 +291,7 @@ private void parseList(ActivityList activityList) throws InvalidTimeFrameExcepti } /** Method to parse the abort command. */ - public void parseAbort() throws NoSuchActivityException { + public static void parseAbort() throws NoSuchActivityException { if (startTime == null) { throw new NoSuchActivityException(); } else { @@ -343,7 +303,7 @@ public void parseAbort() throws NoSuchActivityException { } /** Deletes an activity from the activity list. */ - public void parseDelete(ActivityList activityList) throws NoSuchActivityException { + public static void parseDelete(ActivityList activityList) throws NoSuchActivityException { //int index = Integer.parseInt(tokenizedInputs[1]) - 1; int index = activityList.findActivity(tokenizedInputs[1]); if (index != -1) { @@ -362,7 +322,7 @@ public void parseDelete(ActivityList activityList) throws NoSuchActivityExceptio * @param lastShownList the activity list to populate with matching activities only * @param keyword the keyword queried by the user */ - private void parseFind(ActivityList activityList, ActivityList lastShownList, String keyword) + public static void parseFind(ActivityList activityList, ActivityList lastShownList, String keyword) throws EmptyQueryException { if (keyword.length() < 1) { throw new EmptyQueryException(); @@ -383,7 +343,7 @@ private void parseFind(ActivityList activityList, ActivityList lastShownList, St * @param lastShownList the activity list to populate with matching activities only * @param query the keywords queried by the user */ - private void parseFilter(ActivityList activityList, ActivityList lastShownList, String query) + public static void parseFilter(ActivityList activityList, ActivityList lastShownList, String query) throws EmptyQueryException { if (query.length() < 1) { throw new EmptyQueryException(); @@ -402,7 +362,7 @@ private void parseFilter(ActivityList activityList, ActivityList lastShownList, * Continues an activity in the activityList. * @param activityList To search for the activity and retrieve relevant details. */ - public void parseContinue(ActivityList activityList) throws NoSuchActivityException { + public static void parseContinue(ActivityList activityList) throws NoSuchActivityException { int index = activityList.findActivity(tokenizedInputs[1]); if (index != -1) { // activity is found @@ -422,7 +382,7 @@ public void parseContinue(ActivityList activityList) throws NoSuchActivityExcept * Edits the detail of an activity in the activityList. * @param activityList the activity list containing the activity to edit. */ - public void parseEdit(ActivityList activityList) throws EmptyNameException, NoSuchActivityException { + public static void parseEdit(ActivityList activityList) throws EmptyNameException, NoSuchActivityException { int delimiter = tokenizedInputs[1].indexOf("/e"); activityName = tokenizedInputs[1].substring(0, delimiter).strip(); if (activityName.isEmpty()) { @@ -453,7 +413,7 @@ private void parseDefault() { * @param lastShownList the last shown list to populate * @param keyword the keyword to match */ - private void populateLastShownList(ActivityList activityList, ActivityList lastShownList, String keyword) { + private static void populateLastShownList(ActivityList activityList, ActivityList lastShownList, String keyword) { for (Activity i : activityList.activities) { if (!lastShownList.activities.contains(i) && i.getTags().contains(keyword)) { lastShownList.activities.add(i); @@ -461,7 +421,7 @@ private void populateLastShownList(ActivityList activityList, ActivityList lastS } } - private void saveActivity(ActivityList activityList) throws InvalidTimeFrameException { + private static void saveActivity(ActivityList activityList) throws InvalidTimeFrameException { if (continuedIndex != -1) { String line = "Ended: " + activityName; ui.printDivider(line); @@ -484,7 +444,7 @@ private void saveActivity(ActivityList activityList) throws InvalidTimeFrameExce } } - private void resetInfo() { + private static void resetInfo() { startTime = null; activityName = null; tags = new HashSet<>(); diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 2aa842b90..d62b3351a 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -15,7 +15,7 @@ public void printGreeting() { } /** Prints exit message and exits the app. */ - public void exitFromApp() { + public static void exitFromApp() { System.out.println(DIVIDER); System.out.println(" Bye! See you again."); System.out.println(DIVIDER); @@ -23,7 +23,7 @@ public void exitFromApp() { } /** Prints divider between user input and app feedback. */ - public void printDivider(String line) { + public static void printDivider(String line) { System.out.println(DIVIDER); System.out.println(line); System.out.println(DIVIDER); From 2bdcf91c8ff4584e234661a7da8e235cb77e6c65 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 23 Mar 2020 16:06:01 +0800 Subject: [PATCH 097/415] Edit exception message to be consistent with others. --- src/main/java/jikan/command/StartCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 34dfd2c5f..589b8236d 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -26,8 +26,8 @@ public void executeCommand(ActivityList activityList) { try { Parser.parseStart(activityList, scanner); } catch (EmptyNameException | NullPointerException | ArrayIndexOutOfBoundsException e) { - Log.makeInfoLog("Activity started without task name"); - Ui.printDivider("Task name cannot be empty!"); + Log.makeInfoLog("Activity started without activity name"); + Ui.printDivider("Activity name cannot be empty!"); } } From 4d196a0458f937b6e198d4535b8b43edc39a71ba Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 23 Mar 2020 16:10:58 +0800 Subject: [PATCH 098/415] Initialise scanner object in start command --- src/main/java/jikan/command/StartCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 589b8236d..f2355577d 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -13,7 +13,7 @@ */ public class StartCommand extends Command { - private Scanner scanner; + private Scanner scanner = new Scanner(System.in); /** * Constructor to create a new start command. From b9a36ac3672b3bebf09e7123436664d251abaddb Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 23 Mar 2020 16:24:30 +0800 Subject: [PATCH 099/415] Edit EXPECTED.TXT file --- src/main/java/jikan/command/ByeCommand.java | 2 +- text-ui-test/EXPECTED.TXT | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/ByeCommand.java b/src/main/java/jikan/command/ByeCommand.java index 1ebb369ca..539dd013d 100644 --- a/src/main/java/jikan/command/ByeCommand.java +++ b/src/main/java/jikan/command/ByeCommand.java @@ -14,7 +14,7 @@ */ public class ByeCommand extends Command { - private Scanner scanner; + private Scanner scanner = new Scanner(System.in);; /** * Constructor to create a new exit command. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 03809fa1c..c42fea3cb 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -44,4 +44,4 @@ Ended: four ----------------------------------------------------------------- ----------------------------------------------------------------- Bye! See you again. ------------------------------------------------------------------ +----------------------------------------------------------------- \ No newline at end of file From 27e9573ec04e03cbf95bd330b75d2efdc537550c Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 23 Mar 2020 16:28:12 +0800 Subject: [PATCH 100/415] Fix gradle style error --- src/main/java/jikan/command/ByeCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/command/ByeCommand.java b/src/main/java/jikan/command/ByeCommand.java index 539dd013d..7444685d4 100644 --- a/src/main/java/jikan/command/ByeCommand.java +++ b/src/main/java/jikan/command/ByeCommand.java @@ -14,7 +14,7 @@ */ public class ByeCommand extends Command { - private Scanner scanner = new Scanner(System.in);; + private Scanner scanner = new Scanner(System.in); /** * Constructor to create a new exit command. From 9326edc399ff73555a6d2cde6c68958c4fd5e149 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 23 Mar 2020 16:50:25 +0800 Subject: [PATCH 101/415] Fix bug in scanner reading line for continue parser. --- src/main/java/jikan/parser/Parser.java | 25 +++++++++++++++---------- text-ui-test/input.txt | 1 - 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index db1723c61..5cf97fe01 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -192,16 +192,21 @@ public static void parseStart(ActivityList activityList, Scanner scanner) * @param scanner Parse user input. */ private static void continueActivity(ActivityList activityList, Scanner scanner, int index) { - String userInput = scanner.nextLine(); - if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { - activityName = activityList.get(index).getName(); - startTime = LocalDateTime.now(); - tags = activityList.get(index).getTags(); - continuedIndex = index; - ui.printDivider(activityName + " was continued"); - logger.makeFineLog(activityName + " was continued."); - } else { - ui.printDivider("Okay then, what else can I do for you?"); + String userInput; + while (scanner.hasNext()) { + userInput = scanner.nextLine(); + if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { + activityName = activityList.get(index).getName(); + startTime = LocalDateTime.now(); + tags = activityList.get(index).getTags(); + continuedIndex = index; + ui.printDivider(activityName + " was continued"); + logger.makeFineLog(activityName + " was continued."); + break; + } else { + ui.printDivider("Okay then, what else can I do for you?"); + break; + } } } diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 39250f515..751a396a1 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -13,4 +13,3 @@ end start four /t tag end bye - From 912435230b56132d9aae38f8bccb6e888ff83377 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 23 Mar 2020 18:17:56 +0800 Subject: [PATCH 102/415] Fix bugs from scanner object redirecting input output --- src/main/java/jikan/Jikan.java | 5 +++- src/main/java/jikan/command/ByeCommand.java | 6 +++-- src/main/java/jikan/command/StartCommand.java | 5 ++-- src/main/java/jikan/parser/Parser.java | 26 +++++++------------ text-ui-test/EXPECTED.TXT | 2 +- 5 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 74ba7c518..c689c5f5f 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -34,6 +34,8 @@ public class Jikan { /** CLeaner to delete entries in data.csv when it gets too long */ private static StorageCleaner cleaner; + public static final Scanner in = new Scanner(System.in); + /** * Main entry-point for the Jikan application. */ @@ -44,7 +46,8 @@ public static void main(String[] args) throws InvalidTimeFrameException, IOExcep cleaner.autoClean(); activityList = storage.createActivityList(); activityList.storage = storage; - Scanner in = new Scanner(System.in); + //public static final Scanner in = new Scanner(System.in); + while (true) { Command command = parser.parseUserCommands(in,activityList,cleaner); if (command == null) { diff --git a/src/main/java/jikan/command/ByeCommand.java b/src/main/java/jikan/command/ByeCommand.java index 7444685d4..27d60d00c 100644 --- a/src/main/java/jikan/command/ByeCommand.java +++ b/src/main/java/jikan/command/ByeCommand.java @@ -1,5 +1,6 @@ package jikan.command; +import jikan.Jikan; import jikan.Log; import jikan.activity.ActivityList; import jikan.exception.InvalidTimeFrameException; @@ -9,12 +10,13 @@ import java.util.Scanner; + /** * Terminates the program. */ public class ByeCommand extends Command { - private Scanner scanner = new Scanner(System.in); + //private Scanner scanner = new Scanner(System.in); /** * Constructor to create a new exit command. @@ -26,7 +28,7 @@ public ByeCommand() { public void executeCommand(ActivityList activityList) { try { - Parser.parseBye(activityList, scanner); + Parser.parseBye(activityList, Jikan.in); } catch (InvalidTimeFrameException e) { Log.makeInfoLog("End date must be before start date"); Ui.printDivider("End date must be before start date."); diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index f2355577d..dc7c1ac4e 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -1,5 +1,6 @@ package jikan.command; +import jikan.Jikan; import jikan.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; @@ -13,7 +14,7 @@ */ public class StartCommand extends Command { - private Scanner scanner = new Scanner(System.in); + //private Scanner scanner = new Scanner(System.in); /** * Constructor to create a new start command. @@ -24,7 +25,7 @@ public StartCommand() { @Override public void executeCommand(ActivityList activityList) { try { - Parser.parseStart(activityList, scanner); + Parser.parseStart(activityList, Jikan.in); } catch (EmptyNameException | NullPointerException | ArrayIndexOutOfBoundsException e) { Log.makeInfoLog("Activity started without activity name"); Ui.printDivider("Activity name cannot be empty!"); diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 5cf97fe01..d78d52f45 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -49,7 +49,6 @@ public class Parser { String instruction; static Log logger = new Log(); public static ActivityList lastShownList = new ActivityList(); - // flag to check if the current activity is a continued one public static int continuedIndex = -1; @@ -192,21 +191,16 @@ public static void parseStart(ActivityList activityList, Scanner scanner) * @param scanner Parse user input. */ private static void continueActivity(ActivityList activityList, Scanner scanner, int index) { - String userInput; - while (scanner.hasNext()) { - userInput = scanner.nextLine(); - if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { - activityName = activityList.get(index).getName(); - startTime = LocalDateTime.now(); - tags = activityList.get(index).getTags(); - continuedIndex = index; - ui.printDivider(activityName + " was continued"); - logger.makeFineLog(activityName + " was continued."); - break; - } else { - ui.printDivider("Okay then, what else can I do for you?"); - break; - } + String userInput = scanner.nextLine(); + if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { + activityName = activityList.get(index).getName(); + startTime = LocalDateTime.now(); + tags = activityList.get(index).getTags(); + continuedIndex = index; + ui.printDivider(activityName + " was continued"); + logger.makeFineLog(activityName + " was continued."); + } else { + ui.printDivider("Okay then, what else can I do for you?"); } } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index c42fea3cb..03809fa1c 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -44,4 +44,4 @@ Ended: four ----------------------------------------------------------------- ----------------------------------------------------------------- Bye! See you again. ------------------------------------------------------------------ \ No newline at end of file +----------------------------------------------------------------- From 42e9d5e673dc5b683a282e8f7a5b47fcceb8330c Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 24 Mar 2020 11:15:57 +0800 Subject: [PATCH 103/415] Add assertions and logging --- src/main/java/jikan/parser/Parser.java | 9 ++++++--- src/main/java/jikan/storage/StorageCleaner.java | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index d78d52f45..c770997fd 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -47,7 +47,7 @@ public class Parser { private static StorageCleaner cleaner; public static String[] tokenizedInputs; String instruction; - static Log logger = new Log(); + private static Log logger = new Log(); public static ActivityList lastShownList = new ActivityList(); // flag to check if the current activity is a continued one public static int continuedIndex = -1; @@ -57,8 +57,7 @@ public class Parser { * @param scanner scanner object which reads user input * @param activityList the list of activities */ - public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) - throws InvalidTimeFrameException { + public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) { logger.makeInfoLog("Starting to parse inputs."); this.cleaner = cleaner; /*lastShownList is initialised here to facilitate subsequent delete and edit commands @@ -120,10 +119,14 @@ public static void parseClean(String tokenizedInput) throws IOException { String line; if (tokenizedInput.equals("on")) { cleaner.setStatus(true); + assert cleaner.toClean; line = "Auto cleaning enabled"; + logger.makeInfoLog("User has turned on automated cleaning"); } else if (tokenizedInput.equals("off")) { cleaner.setStatus(false); + assert !cleaner.toClean; line = "Auto cleaning disabled"; + logger.makeInfoLog("User has turned off automated cleaning"); } else { line = "Invalid Command!"; } diff --git a/src/main/java/jikan/storage/StorageCleaner.java b/src/main/java/jikan/storage/StorageCleaner.java index 93134c170..40ca4593e 100644 --- a/src/main/java/jikan/storage/StorageCleaner.java +++ b/src/main/java/jikan/storage/StorageCleaner.java @@ -53,6 +53,7 @@ private void initialiseCleaner() { Scanner sc = new Scanner(status); String status = sc.nextLine(); int value = Integer.parseInt(status); + assert value == 0 || value == 1; if (value == 1) { this.toClean = true; } else { @@ -165,6 +166,5 @@ public void autoClean() throws IOException { } liveDataWriter.close(); } - } } From 073b5d8d9e1736268eac1126d1c6a8b82075d6e3 Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Tue, 24 Mar 2020 23:50:53 +0800 Subject: [PATCH 104/415] Added Storage and StorageHandler implementations to DG --- docs/DeveloperGuide.md | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 8b5ef5cb3..187499122 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -4,6 +4,27 @@ {Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} +### Storage feature +The Storage and Storage Handler features handle the data back-end of the application. Storage Handler provides functions that can be used to manipulate the data file. Additionally, Storage supports multiple data files at the same time, allowing implementation of features like multiple sessions and multiple user profiles. + +Jikan uses a `.csv` file to store its data, formatted in the following way: + +`entry-name, start-time, end-time, tags` + +All tags are saved in the same cell, separated by a white space; this design decision was taken to make sure that each entry occupies the same number of cells regardless of each entry’s number of tags. The tags are then separately parsed when the data is loaded. +Storage is the main interface between the application and the data file. Each Storage objects contains the path to the data file (`Storage.dataFilePath`), the File object representing the data file (`Storage.dataFile`), and an activityList populated with the data from the data file (`Storage.activityList`). Additionally, it provides functions that provide high-level services such as: +- Constructing a Storage object via `Storage(String dataFilePath)`, which takes in the path to the desired data file (or the path where the user wants to create the data file) as a String object. +- Creating a data file via `createDataFile` +- Writing to a data file via `writeToFile`. This function takes a single string as parameter and writes it to the data file. It is recommended to only pass single-line strings to keep the file nicely formatted. +Loading a pre-existing data file via `loadFile`. If a data file already exists for the provided data file path, the function will return `true`; if the specified data file did not previously exist, this function will call the `createDataFile` method and returns `false`. The return value is useful so that the application knows whether or not this is the first session with a specific data file or if data already exists. +- Creating an ActivityList via `createActivityList`. This function calls `loadFile()` to check whether the file already existed or not; if the data file previously existed, it will construct an ActivityList object by passing the data from the data file to it, and return this populated ActivityList object; if the data file did not previously exist, it will return an empty activityList object. + +### Storage handler +The storage handler provides features so that the main application can interact with the stored data file. The main features are: +- Removing an entry from the data file via `removeLine`. This function takes in the number of the line to remove. +- Replacing an entry in the data file via `replaceLine`. This function takes in the number of the line to replace, along with the String object that needs to be written to the data file in place of the replaced line. + + ## Product Scope ### Target user profile From befc955bc23acfa3251d43ca56e366db4d5960d5 Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Tue, 24 Mar 2020 23:54:38 +0800 Subject: [PATCH 105/415] Update Storage in DG --- docs/DeveloperGuide.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 187499122..2fbade658 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -5,22 +5,24 @@ {Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} ### Storage feature -The Storage and Storage Handler features handle the data back-end of the application. Storage Handler provides functions that can be used to manipulate the data file. Additionally, Storage supports multiple data files at the same time, allowing implementation of features like multiple sessions and multiple user profiles. - +The Storage class represents the back-end of Jikan, handling the creation, saving and loading of data. Jikan uses a `.csv` file to store its data, formatted in the following way: `entry-name, start-time, end-time, tags` All tags are saved in the same cell, separated by a white space; this design decision was taken to make sure that each entry occupies the same number of cells regardless of each entry’s number of tags. The tags are then separately parsed when the data is loaded. -Storage is the main interface between the application and the data file. Each Storage objects contains the path to the data file (`Storage.dataFilePath`), the File object representing the data file (`Storage.dataFile`), and an activityList populated with the data from the data file (`Storage.activityList`). Additionally, it provides functions that provide high-level services such as: + +Each Storage objects contains the path to the data file (`Storage.dataFilePath`), the File object representing the data file (`Storage.dataFile`), and an activityList populated with the data from the data file (`Storage.activityList`). Storage optionally supports multiple data files at the same time, allowing implementation of features like multiple sessions and multiple user profiles. + +Storage provides the following functions: - Constructing a Storage object via `Storage(String dataFilePath)`, which takes in the path to the desired data file (or the path where the user wants to create the data file) as a String object. -- Creating a data file via `createDataFile` +- Creating a data file via `createDataFile`. - Writing to a data file via `writeToFile`. This function takes a single string as parameter and writes it to the data file. It is recommended to only pass single-line strings to keep the file nicely formatted. Loading a pre-existing data file via `loadFile`. If a data file already exists for the provided data file path, the function will return `true`; if the specified data file did not previously exist, this function will call the `createDataFile` method and returns `false`. The return value is useful so that the application knows whether or not this is the first session with a specific data file or if data already exists. - Creating an ActivityList via `createActivityList`. This function calls `loadFile()` to check whether the file already existed or not; if the data file previously existed, it will construct an ActivityList object by passing the data from the data file to it, and return this populated ActivityList object; if the data file did not previously exist, it will return an empty activityList object. ### Storage handler -The storage handler provides features so that the main application can interact with the stored data file. The main features are: +The StorageHandler class functions as a support to the main Storage class, allowing the Jikan application to manipulate the stored data file. Its main provided functions are: - Removing an entry from the data file via `removeLine`. This function takes in the number of the line to remove. - Replacing an entry in the data file via `replaceLine`. This function takes in the number of the line to replace, along with the String object that needs to be written to the data file in place of the replaced line. From 425c1460a5bae6b990ca8174fc8f9eb61948aa17 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Wed, 25 Mar 2020 00:12:10 +0800 Subject: [PATCH 106/415] Add setup and appendix to DG --- docs/DeveloperGuide.md | 57 ++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 2fbade658..6727e8028 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,6 +1,26 @@ # Developer Guide -## Design & Implementation +##1. Setting Up + * Prerequisites + * JDK 11 or above + * IntelliJ IDE + * Setting up the project in your computer + * Fork this repo, and clone the fork to your computer + * Open IntelliJ (if you are not in the welcome screen, click File > Close Project to close the existing project dialog first) + * Set up the correct JDK version for Gradle + * Click Configure > Project Defaults > Project Structure + * Click New…​ and find the directory of the JDK + * Click Import Project + * Locate the build.gradle file and select it. Click OK + * Click Open as Project + * Click OK to accept the default settings. + * Verifying the setup + * Run the jikan.jikan and try a few commands + * Run the tests and ensure they all pass. + +## 2. Design + +## 3. Implementation {Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} @@ -27,31 +47,42 @@ The StorageHandler class functions as a support to the main Storage class, allow - Replacing an entry in the data file via `replaceLine`. This function takes in the number of the line to replace, along with the String object that needs to be written to the data file in place of the replaced line. +## 4. Appendix +### Product Scope +#### Target user profile -## Product Scope -### Target user profile +* Students with time management issues/poor time management skills. +* Users who are reasonably comfortable using CLI apps. -{Describe the target user profile} +#### Value proposition -### Value proposition +Allow users to record their daily activities and track their time usage in a user-friendly manner. -{Describe the value proposition: what problem does it solve?} - -## User Stories +### User Stories |Version| As a ... | I want to ... | So that I can ...| |--------|----------|---------------|------------------| -|v1.0|new user|see usage instructions|refer to them when I forget how to use the application| -|v2.0|user|find a to-do item by name|locate a to-do without having to go through the entire list| +|v1.0|user|start a new activity|track the time spent on the activity| +|v1.0|user|end an activity|track the total time i spent on the activity| +|v1.0|user|abort an activity|record a different activity| +|v1.0|user|store the completed activities in a list|analyse how I spent my time| +|v2.0|user|delete an activity|remove activities that I do not want to track| +|v2.0|user|search by activity name|view similar activities| +|v2.0|user|filter activities by tags|view activities of the same category| +|v2.0|user|view the activities by date|see how much time I have spent on different activities| +|v2.0|user|continue my activities at another time|do other things between activities| +|v2.0|user|edit past activities|keep a more accurate record of activities| +|v2.0|user|automate the deletion of old activities|keep a more concise log of activities| + -## Non-Functional Requirements +### Non-Functional Requirements {Give non-functional requirements} -## Glossary +### Glossary * *glossary item* - Definition -## Instructions for Manual Testing +### Instructions for Manual Testing {Give instructions on how to do a manual product testing e.g., how to load sample data to be used for testing} From 16825e9c4fe702f5ba44c97d4e47e1706844f721 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Wed, 25 Mar 2020 01:03:31 +0800 Subject: [PATCH 107/415] Updated DG --- docs/DeveloperGuide.md | 61 ++++++++++++++++++++++++- docs/pictures/FlowchartinitCleaner.png | Bin 0 -> 36903 bytes docs/pictures/FlowchartsetStatus.png | Bin 0 -> 18311 bytes docs/pictures/SDautoClean.png | Bin 0 -> 21415 bytes 4 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 docs/pictures/FlowchartinitCleaner.png create mode 100644 docs/pictures/FlowchartsetStatus.png create mode 100644 docs/pictures/SDautoClean.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 6727e8028..d2da2e019 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -24,7 +24,64 @@ {Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} -### Storage feature +### 3.1 Automated Storage Cleanup feature + +#### 3.1.1 Current Implementation + +The storage cleanup mechanism is stored internally as a StorageCleaner java class. The StorageCleaner class has an association with the Storage class and thus it is able to access and edit the datafile which contains the list of activities. + +Additionally, when the StorageCleaner class is first initialised, it will create two files namely a status file and a data file in the “recycled” folder under the “data” folder. The status file keeps track of the activation status of the storage cleaner while the data file serves as a recycle bin for deleted data. + +Moreover, the class also implements the following operations: + +`StorageCleaner#initialiseCleaner - Loads up the status file to decide whether to activate/deactivate the automated cleaner.` + +`StorageCleaner#setStatus - Gives the user the freedom to activate/de-activate the cleaner using commands during application runtime.` + +`StorageCleaner#autoClean - This operation is called whenever the application is executed. Storage cleaning will only be done if the cleaner is activated.` + +Given below is the example scenario of how the operations work. + +##### initialiseCleaner + +Step 1. Loads up the status file for reading. If the status file is not found, create a new status file and write the character ‘0’ to the first line of the status file. + +Step 2. Read the first line of the status file, if a character ‘0’ is found, deactivate the automated cleanup. Else if a character ‘1’ is found, activate the automated cleanup. + +![image_info](./pictures/FlowchartinitCleaner.png) + +##### setStatus + +Step 1. Read the boolean parameter ‘status’. + +Step 2a. If ‘status’ is equal to true, activate the automated cleanup and write the character ‘1’ to the first line of the status file. (overwrite any existing value at the first line). + +Step 2b. If ‘status’ is equal to false, deactivate the automated cleanup and write the character ‘0’ to the first line of the status file. + +![image_info](./pictures/FlowchartsetStatus.png) + +##### autoClean + +Step 1. Check activation status of StorageCleaner through the class level attribute boolean toClean. + +Step 2a. If the attribute toClean is equal to false, return the operation and give control back to the caller. + +Step 2b. If the attribute toClean is equal to true, access the storage data file and remove some of the activities starting from the oldest. Put these deleted activities into the data file under the ‘recycled’ folder. + +![image_info](./pictures/SDautoClean.png) + +#### 3.1.2 Additional Implementation (proposed) + +`StorageCleaner#setDeleteQuota - Allows the user to manipulate how much activity is deleted when auto cleanup is activated. Currently only delete the oldest 3 activities.` + +`StorageCleaner#setTimeFrame - Set a particular time frame for auto cleanup to activate. (i.e auto cleanup after every 2 weeks etc).` + +`StorageCleaner#initialiseLogCleaner - Gives the storage cleaner an added functionality of being able to clear log files too.` + + + + +### 3.2 Storage feature The Storage class represents the back-end of Jikan, handling the creation, saving and loading of data. Jikan uses a `.csv` file to store its data, formatted in the following way: @@ -41,7 +98,7 @@ Storage provides the following functions: Loading a pre-existing data file via `loadFile`. If a data file already exists for the provided data file path, the function will return `true`; if the specified data file did not previously exist, this function will call the `createDataFile` method and returns `false`. The return value is useful so that the application knows whether or not this is the first session with a specific data file or if data already exists. - Creating an ActivityList via `createActivityList`. This function calls `loadFile()` to check whether the file already existed or not; if the data file previously existed, it will construct an ActivityList object by passing the data from the data file to it, and return this populated ActivityList object; if the data file did not previously exist, it will return an empty activityList object. -### Storage handler +### 3.3 Storage handler The StorageHandler class functions as a support to the main Storage class, allowing the Jikan application to manipulate the stored data file. Its main provided functions are: - Removing an entry from the data file via `removeLine`. This function takes in the number of the line to remove. - Replacing an entry in the data file via `replaceLine`. This function takes in the number of the line to replace, along with the String object that needs to be written to the data file in place of the replaced line. diff --git a/docs/pictures/FlowchartinitCleaner.png b/docs/pictures/FlowchartinitCleaner.png new file mode 100644 index 0000000000000000000000000000000000000000..f90a23d70916ddecc05c8e04a4ffdef579ae9eee GIT binary patch literal 36903 zcmeFYXCPcr*FQQ4Nt8(R7822Gm{Fr9h&B;KuhDz&J%vOU-ROcu9d-1Q7(^GH!306{ z=$(6pJn#GebidvE;oiq5XWM7*wb%Ns_B&hX%NNgy@M-WtAP|v)yo?$Mgl7c;;rQIb z14hD(I<`QdAdrHL^eeBa^%<3qxhwt*e?>+f4yrj4j~N!z;Z=RS`)AaH`*&8;-Zx{u znCbXuAL?|v@;vKlZJXYe(aZ@vJz_k$OXjA~`kIW(P5TxVi&8Gs&o$jW`?mB3cBkub0FnNG{bT#5 zO=xQ~@MvlF_<8g}hTqg4~Ga7xmlYW1o9-}5a9^x%G37;y@ z*IrDFjEqXWHnWYs=ig`>4#jaWszm6)bWqpf2VE^;z5GMcq8 z3v?wPFk-xhe2H|D$Bfm@=oByQ7ZU=b6CCB$ALn8|e*CB{i&-t^Cq^VH!qAT&e}oah z9u0H@gFz)GY?!?{d9CPY{MU7;fw3|T!eC%68R@IHQnE2iumP9@f%w5>fGqcLiGbgw zEJB_FFXm)n0S`ZVUt+c=gJ5Q*P~!u8e0+-m=mYSxhrk=EgP1>=SQnEAr#)MK zD|L1Y?rf;Bwa2|ehV%jFd}+KVoeY<7%a)U#%fH*z$E#obFMprVbNdIrNVTS4-oEUa z-~JVF_bLvwrV$1+?T4M{;ppJ@c~C&mULwa{Ux&=x+j%b+TKcul{P%}j*jWUva7P-+ zAlKnS8zK}91G+!C<7GYN0L+<#p-YoR?vC?RLFuiW3MVfQUR%Uf{#u=1_k z^+}b05Qk5L+gIYZTkWnN|MOar zB^%QuJ`C<>BV5J6AjnWeJ0IwHC*^X-qRWTdhhKzla%ca6rr#eFw9G}^$KyORNaCLDDLO@9s^_kXpo9p33PS1!P#>fqoz z+-WuZ)*@=hdT3nIU79qy^V?~}R!!~ZHoC2IfG%3$T4Q!}&mMNE4I(+hzk8@xf9M@2 zf-mUD<1sAf(|r|9{e5Z#Zzd|Ind8jVm6smgGiCbl3o0@8tA0$O#3ZFUE7Vr70783b zQ%Ns1PeRiLRWdXvxi4(D<7J(rZPn|}z#JAx|gFMqGl2Tpp2ctlR|Qa@*Ru$zl~Mo-gBAOP#xf$9i%x`VG#6eK3y0=BGCVh`5w)DbhwW4s>pI8QCk|(zUDjYK zu6SKmwq+y!@zXq9?iWxy6$;dXM)3>wMCXNQt!CaLgs`5Ow0g7s0!rMkA*|DSX3W{1 z-Aavlz05C+8|S8DDu-j5>7%P`X1qp?-^EV=8|kEJ_G#8mYus1c*~p;PXGPF8XoxZ4 zoi09fGVfBa6;EJprJ;bd*}goZ;Y7ryF8O6z*H9HbA+}Hx8FM?WTb8)^RsQmV=ELFK zdz6ue30HBJLj0$KHMNTq7W>Yc16=4dL#Rn%BmbYVaeMN}tE?Pk4**q((~1OVty|h9 zC&+u#-gJWY+1z*OjT*%d$YoCA)VLx$8iyW1cj-9o;EF$QS-k)FP7D>C?TPzzO`Ywe&X}xY4zwOHjNCu`w;d#?yV&r zE44%0!n?})nNz#@*R?{~3SqFBH7?Y|NzaqMn^9t`3KwerdL(N-Wo6CCSQ;!=#M*`* zJ~yUM)W4BZYp*r@HeWin$WGH>5J_PfI;!L>Nd)gq%j>OLUWbSTTHeEju5LLZ+&S9? zEw6#Z_LwZzoE%c1!RC%LIkCDjhDsuS$#8Z_b*t09_z5qIh}{dqk86k|T{&s>{rv&8 z!I1=>MeZ+499CiD7kWlii2~5l^AZg*bpUWj)EOniPUHha1h8-863zroNK@hJJVOK3 zy4$!=^-8-Y*6TVY^7WN=X^MrDS2tRYb$9HNz42l7L*_FCuzJ*RRa!D;(@)KWp3(&7~JwK@S#D~me#(v*+Nby!OM{!+ez0wMrU zR%t%>())@$CSRx&3b{ENc)8Yf7`XXh#~L4IZttvF?!s8-WA*)I^JdI`u!FN;r;b1+ z8AJp1zJ2^Ib!nEOU$gtfyj`OGoCQ03tmO<7f=nsDYILd*7i!Z`x9u;$zFW$4?J!bB z08EGavr=}-PDZ2}9OT8ssG4hWbys5!=3h!|A12gTcB5vieiuxsaq9@jhg^1L`?U=` zQI{qi_i&<(UG8GK6Qok&;8RLyr8daq;9EGMX8{DCwhlBUwEtzOt?*PL+=jVt8n=%Q zcbXp|?23rEE*xn9!{w1fLf`mp)UoF!khWpxZwe-8V(0cZrc|Y?k3N?0{(H=*DVp1S z0r%rDP*i5KinZM9bsBrIx}M}RIrRHH4i^;<;2|wZFSB9Qhx=<*0Y`Hz?nsraO#6X- z+s6Eq?jX}DZZOdUNNOXtn=X2}-@( ze4Gmxy5o@)a-#8}SO{?KcYj9`)z$5p6WG*PG8p2ihS2rVGw(LR1-?2 z9qj)7uZ}&}U=f`_L%6!eQlAXSRNc`6O2CHI zk#P0VNp2_sER~V7bX1R*S<=v)T~muoL;u~;QJWeYelQyo-Z(dY=*ViUUQrwgkmpWW ztKYIn^#3W3<;W~7)v}RQDg0V^lH8W?#F;^3`a?~>3A=xD;hN!vpFMiMcvY9!arkHh zZ#?@K%WL{!_^+1nGsAfAg>w>iRYRfX9v*2eH zgz|p=fPjT4y$0Cp4zM|lCh<k-gJg-oH(rttVRH->T;Y@CQl*)G9;cWsJ0oeUH5j3lDZsU#Kjrct_w0TtpJ+I!ENr`2 z_sw@EdyQQ0Em6%3M?gO^t5&R)-XT1Zilx(@ia5Gw5m}529sTxqd;0^YuZfi8GimTF z3s3jE-xQ_=Ikq9leJiyx@fvr7zRqxX-GNy85sZX0Y<_{bCExj2y&N=fRdT4*P6+QEFXW*2u9QA*7 zB&>0$x+>wn>C?C41wZz2;2+pe**kwy&p;D6)4o-5BynGoCF!`9?7BUq1-ihhN8!Q^ z|LG*lSb&aiN@uXQvLxYOcWB%W43R+?8UME>{J(pe`eYQatTeE!XXIq?uRR^q{BIZf zzsmcMs{h+o{g;0D{{~xAEa6L;k$|C?^q39HZLYa01L@tRng8%tJKq?l#RaJ_9GS+_ z`E%bxG0rRQtlQV9xpH?d)e}zi0q_emSyZa{cElAirpVA(?u))A%sv@4UW8JL(_XzZ z_Q7#8ot6Y(ujKpB+GsQV`YIm-TN|(WA1%%JqtY>dh_df1PQwVqRx8#xOieEEoI#@g zR2#F!z2iSWXJy4&ye@yviVxHRb3mY_z11SPge&>g1BhSkiU33D3}DWbuV^-a zo=dqR%rKPMRRF~>Y*(I*;mWQnMu1vlzvAHl+p7O}A&g4@-_;S<&mwrUPyCO{oy?}4 zZccce?zLG71~)v=)a3lt)QvOa`rKE8LAb)g!d?@(S=46eQS7TB?Vxw>-ci!VgC*Vb zu3w~J!>2-}V$cLYf($oeqwjj0KMcF$z~cJ%6!(Ui%*j~{ashCBcBnb+LUjU&?=0Of0DVKOWXe;VrxK{Ye+A2?GIh>pH)|m#enu z$tV7Yv*~R;QAO9wmr1F9Z*-apZ1fxpOzbAGJYSoMoBfo7;dKG0F#M2|J`;E0t-F%VR09AzPGN%C)n2X``N6oeh-QyU2ZIPaOZmAXYet<2yG_}vNm&B(Vo8YqIbD{)9o{FtmgnJ!Byf8y3&Ps9^BPlY zD}O6Umuu`4MbsnyolaYlxYR?iI*r;ASo(L=^^wP(rVW$my|H%@*-eej58R}`d9{tE zO=@?_vLXyHx-Y}k$Pb==^T~XZ{N#y#sKPZ4%&Pkq|FifH2Vl|0jVnuywM5y^ig8>Y zDlc?bi|jwfc<`aEr+-%G^65i$gCQisk)G{pQmYA_p~rk9xoq$6|7hq~ymm^pUpWbb ztebbPW<8D*)?!9%s@3Ph*c63_B)-3RX`Y?MSQr`9v}qQptA)-YBg>`B33%Iv-(?4s^D)76W1 zwN1mGTkMu&Je1`#Y0p`&2eX6^WvDAMLN}J;uRf80%3jBVx!JAh^*6k#t_<0V_tEtQ z*#ls#|76@*F6Q}l6sbyfk^5(b-!5L0-g8x#+H*f=kq9^XA6H8cQna}&t&lQ*_-Fhd z4-g${{dSrjDn6a`lUGy9@C+$-`65-jbekGQ% zbjYGIF!=s1Gv+H32*hPXhYe5rWKCj8*6!ie?0Y>6&$;yDcWDbw>kNs15u!Cd9$fJe z5VLc4=El_|BBTf-KAw)eg6mj|=5-ipz0pmrBd0)WNqxL|rS_nTww@Pso24&f%$X5= zyOGzHx$VDG(>@n@ zWY1aR)ADG^;5dJT!#VQD}a11xc%P;ekhYjD*&c z#u6c{=dS3k>v!ei!Oj^U9=81NdCUw%9;L=l-KrbbHcGT7`_Jep$m~_T z{*S#zL&$@m0NB-Tk0&uo{rT9KQb+k8B1hEwKXNfQur@uCG`^Zs%iP~H z@xteaY)|gP87jb~F-s6w6y4nRV@w#^LRA zi+D@_BgCZtM1$i?o{H~RAqhorVtsYSGUjVyoC zvxE=7OX-`5|4SYdkZ$Tvnr4_Nf0F_uED%I?xes1s8d3*@SLNldWS(|i;bhPRqg9HK zS;mqc*dZm5sn;40|eE+Na&q`Iu9^RJ5 zU7&E9re(coDH>t~+ig_a8jRPu(Y9Rz=p4g^Uh`_#NI142&B%o2$01h`BP> zoJZ()rtQ-czwfS}=27$-O$KMp(a{244u6^U8;$ptDKjWBrzyD$7v&}vwlNHyqE28G za-?PMKH{a+9&{@V;nk3h)EX#dSnSy6 z^noAfb_#^s9=2UPAKc{dk$Ih%R0KIzzUY&yQ2NgXn;QI)qyfFVrP=m~{h7?7|VU2jE0Z@k1CVOYu2yN=~O`{2X17PtW_aTLN z`qOqHDtk_~Q=17FX;M@+`9M^G;`~DVO)kns+O!Fqjk-~>;urB?Jb;yha$1>~D?11G zX`kt=4oF_I1}?zz6=65E5E)ZW0szCfOhMjq7|r6}`19b)=|V}b+<@wVdXb~J5Js0{ zhJ=s1+oI>uNj*v0i)t5Cp>LOFt7;yVFX}FKCvPv)5}DD{elMN{?Ed3{&ps~ntj4x^ z;w=k;k28_KToE`>c|A+%X>D=nW%Z0s&Q)D>@F76gVQ)9I`)&T&bk5(?#)>S3G}*(W z7yDt8FH8jB0adcR!rXN{(S! zS7DeD@btyrd3+f9&zPGR@VN8M4|sDyApE0K~~XO7eP&MExO;_i7}!V7TbSys(jWMF4zq*nbaa!9)^ z?Uvr5$h;}J_qrA<;@KXK+b)x0!uinFz8>$+R}QQB7E5oQyN*ID`m}(cLDi&sNz4b{ zjy^vey>a`Gt!mX$6>1)CD^7nd^k45<#{^?VDnZ`-EOv)a8q60GVQ~PZs`^rfnoog@ zuHcZjd8?Q+Ff5P~S2?$T{PJu$K~_DU&wU&cmRShU$c~MHXZ~@O<{jpVS|soU@PoED|2uVu^(VT3k;kR0qij61S-z zFQV?LEjJ_WdBdVL8W9W8I$R0emV*$eGj1P0q5}0J4X8I%hWkDNIvMEUJz|r{{Hi0p z>y=p2Em!0b7CcCLh>3KA_%9!|o`OIEBw$ z&2KsOmPL^Zw{OpK2x%iGsUfr^A_G7(9jbohkFLt96Y8<2vM<7T_~4zzZ288W{TJ2) zM|fMiW_y;^)=sXXsxZ!#SYgGtx2)?VZ;N@SLKom<5XD1kKD00^pGaa(};65TE&Mc=OTK@#UYHw*V(imhy=tq`xvo!xH^qcKFGOZ6Z>#Nubeh&iKMZmz| zZrna%m|Y!H1-DM++k8^Xt_X?#{oH8P0A`2mEN3*2$Z2NFC0gP%xYBYVe(Pr2(h330 zCFP}liW zae?K@nQ`LV0Woo{*9N9pWwVK**4l9=QBJkEmavl&Ewgr0-Zfeu>>no&^IzrE8C@cjA_&5lX z!)n9}kERbvdHXAxsMjvUcc+d-_Wo?!$O1*s2E^;>Y31!A%ZsL>8-2iy2Woriu|FE` z7qn{fLpVR{M_gbvNY>jIfUS6@U5}|ac$>4>Geb$tm5aOO$psc;Enxhgd4`L#LZ9Y9 zar<(y%>n3WTTG7GH3MDN!1=2gLg3T?&)tI}761+?P6r3Wcs`$OIWg8+d3)a}HzkPn z&F!b(z34hkeY;RMa6qjtgc-d74W(JzGL$eq8EG&y44wJezCYjR^62Kq{b$L=n5GD? zr-#!jEY!X-OwT%)%`p)OHIgdvGSGpnP)6%SlU%Q*J|LQ#e5?KewhBWv$i80UlQ5Fl zK6%1>0yq_n0`i$sAHr_c!LaMoy^J@WaXS1|$daprAWk3XUUkjCd)y9O!T+X@Rsrsg zY%jyT-R(t|5xn|ufIh=c$*i{V?5#zkZeFd)XZ?>{g;^;}(@AVjh0Xc-=Fgp<)R>b& z+R3HegVp1Whshw$fk>20+7s~dYRZSE(||08DB$yQ-)=}D*g_O))cQJ=ZOY-*kbbmQ zG7dDb~z@n5c^IL~^+m?5B-zXFr&imsJ2!#z0gbZj9R!!b5k6kL<>)ZUs8ExkT zl`{jIYNcaa>-zQ-a!7wVmUg1*o0Z@Y5U5JY&Rlb9{@3_B)*51c>LBKdnMr+Is5i3$ z8I5X0gi`d;DR00jD*-1sUq==^yK1MeEkk`T(1;77#;M+Iq)w)|Er2|w>`9e%bWWU- zDAg8j5A58aqU72}FQ8sFa>wDrylaZp`}d;Gf89tvazxD)I%{Erg2pg(p0=U1YiEU1 z(4zWKufQNLe}zD&2}Xz}WlT%qR0 zk9pGNSMA;!0ixK-tO()CJ|Lmn`;wdv|6EO}F(3*WodEI*wQ~4J7d&GRz^h6PZUcD# zjM@lrta@vK9tCNqPxSu?(lrb3Ndc(8O|jak?cuw|77OINyKWURSL_ouf-{ zw61OdoZABVUdSk;o_0T-q38sS@kJn-!wLkliuT$O{o${LZ7hyFkW-}jRMH&`Y{`eA zz>8}D9i_Sd{ce4^?F8~V3Cxt8Z&?_a-y*yX(&SWxH4T5!!W(By#qg4KnO>mq&j8DA zEFKx2f(P%8s!<&Q6<;iS*!h}$(TOG7~_A$X-^Jz&#j)6KHqEqk#b#mQs&I)v5skU6CkDB0awr><4F?mKCv! zU)a4f`^r6Zf!yU-Bm@XAI=Ztj3b@e5NKRZ(t0EHA$|;T|_%2p1_Z;9kco)A=x0bL2dc}l4P6yWKcH$YMp+hMC|ZK5Bhv5Pgy7J*~$_c_^W1BVy_7-(XWB1;J; zfOh?1f*}Cw=bmj%h=a;#CN*D#eRMqqjlBX)I{;Mr_F8zLpheNf_4V|9-ZA65&U55B zprTWQvfj#08M9SNINkBL8!-bwTHA^zfE|G`)AOhu>?`GP>T0?B^RTq)SnD&?Vnq>nIq*7Tsk;Rf<}Fg7n3d*YqLTxJpi_KVl_Lp z%^6FR6`{i~OxYC!fT)`~Xw(;&fDxwagRGd*eChp74<93+xvDk6`bgzjQ?Ob{n6a#SZmRrSv z<=@&O3H08AikA+##5Im+ z{4UZgw>$(YZY|4QkrcF}OyNP;1oz!Tu~2)3SAh}YIG{ue)EyW4fRcCcNpa#BBfDX< zKRiS0$K3$?fmR`!AY^c~MR=MIau1Dd^dFSYpH8TNLB{3pDu6tOAi#RCwnYyZ8R^my zW;DU&{I~XDjeG+sx-$TV1;R7CGmUH2G=b=PV2Jc6F5{jra|S301U#qidX<1Xw#@>! zLT%^YV8tZG${}4zCMcW-Yq4tNdw{E4hvk_TpjQ2P@)VTYY($9+Xbgo&f5)O`(7(sP zX=&_A?GSD!H;cK0FZmM$@I#ylMBi4GV6}4e>>zLN?Vt&l(ZnL)A{#^=h=@-K!`F3gviH_~`tyz@y{!ih4WhQQoqnn=tZ13s4E#NcibOV;Mo>wr=MGesn!f@NvtqLhfZf3w0~ zCu-3>K~fsKA_ZRt+zc&Ie}e!|0F4v~l-m2PdoqO6xkUUIXh(JE<1(=nirNn7X+c3m z9(^Et{1f-hyhb~oW)Zvf{FLtv?BAbr@1Z_p+nbkhV{YOJMzqC^ zzy3S)!g2m^u#Yhn!jPLW1uS=*c-{y&>O zo}O)gX~Ru?>CQtWC1+Utpqn~N_WE6^o(&9#JbSw4&jX!)PG0~zMp82b-0Z3sBmQeb zlofV;T&rEsDuCm;=Sl}@4AWZlFOPi+Q^{o!-IQ%zToB_aJjZ zvwMp{XH@WuCqTL%@!VLYx>f>l? zQ%g@pa3KGVult=dNQl=t)5i?wcXsY4F1-|N$CWI<^ydI=B{S*|jle~5q*)tK-}O%>t< zW8eaKGArWq>_darGA>IK6GxTNP(xC};nj8dsprZQ23_iN!oizClJ=tk^4rq$wp9b7tH;{X8md#z%xmtsEKH3+aZGOtv zi#<6f?VESFD4snCN(hVXILMhl6gN;+6M;Z=ettOGn+=8gWKK)8Ves%-K1HZWstSoOjGTKS-6-95j;` z)AZ{Eab?EJ#R7?k?xVsA#P&d zwLZ-t(}L#E58~}=^M@CEmZWG2gwW}j(b;?*@KHfQeekzP?nE5~L=AkxGV$d!Z}(tE z)S^T-H%{?D|FZK6g9lKZ_|44IPdA^r7~ zkdWsfZ+2@$QQ9`+tp}9XUKe9pwp-@e0xgouXSXt8hN>D+lW^K~Th1UothX&O{1Od0 zzcWfrued$49S!C1pWiZFRH@Srb9IvdNV;Lz+a(Lfvu~z7o>WpH=tY3U#_b4M-djm< z!TZs5eM&C%aD*J@a`#X!n??+hBT4wPMJ(G3pi4NSDllQu7g8IzQoh2vyCm1lEWzQ~l=ZXo;dPib6AJ$EP#$M9invfb^9#krva_c%4XmnUT2 z44H9OZ=WU+B-BT%p6M@;3#qosgmJot)zlE-Mt&oa0>0Z6?KVw{5G?j@=r^JPz|ugW^jbjsAC zONN*?qs$=g!?rJQUu{Cbu&&@Zf>=Q7yq6UaocMwj=_J}dkL5AR^Zie|*I+38^N6rSdPF}#)O zzrCATyt+#)DSW!#i55TI+u(#9DN5mh*6XEr_uRT8!~7VMvgZTrAIkMsC>#bC9Qs-p zx#20Jw>vf-S#{y$KE#3={c$10>Pxa+l@zbemuQuZzM@n-m6RC?l_ z&m484&*po|mL_1kTZX3<@5!)%+$UM+{wF$%uTnv3Sb#LI>av$A&zLEZfwOOxy$c5h zIZIKJQg`&TGolHa316&u&+wr|3$^Q+slPviPZy>jl!tC`Kj=hXB93abdo!#_D{V|V z`cxrH=;jI^gQxgdk!UMW+0E_e7v**&Vs6ARKlZBdTUI8=l?YIQp$E5-4|gDuX`%`( z>5`Q^)=SbMx`VnwT!Pl@6dSN;BG|S!>iFETD7u8({9v=%W~`TzLDG=GDJq*ivzhqc z>P|nQ$>W)gKFX2d*;vr#=St&TFh~}41yV;haEG_qCvEGp9W8iJ5!wlrH1cUK4YGIv zwkob6Huigb>eOMU_Dc%tJ|-{f%JMx)d$rgx8YY%25@P<%WZ*tlB*`GCRkq>$=rX?Eun zU!3Lsw7WLNK#doJ<`(oE79uvD%IoKiUOXi+syTApKMIE{plogZ&PAIIHQL9&F8G@7 z`zQ{uW?=bwED_air3;l`splx*!MJdsp7EiT7I8-jN`5590_g*Mqu(LWMj zG9|Qv6oGg;__*JR&g{+%t1mzK6$AAiNZ^S7W7AQyuBR@rL;!Z6>B($5{yudfXi%v& zG-5Q8UbGmsm0f_T7SwBU;5@R zi>MiUCK;c-jTSR2ut0Me8m-jrQj0k^RG)SdrkT6rD(u@O`gFVqAY3N0+F9moV!hW& z*7oVpp_;+=z^4cvNK&=So$35u%5Y}TC zt9!M3;(_#~$O{33hbn$tL~mEc9qTRTtHfUbV#4a@eNigHt(!9PuE!Uw47Z{0!Js;J zUPlV))>3TPC|BfDSBcE~6%?(F$KQ43%MXOZFSpXHEA{7#wyA>izWG>2nhmJqKGu0m zG7yJHnc7RGL!d$tJ+8f3oIxGO)1{eg5FgO&R(x!li^f?w)zDw!PVv`hnVmlzoEI6O z)xK>7`t?H}6Wi!u)TuWh$Al?}6!w)NQ|D8!vt(yd^2--E$w!{_d&pR`mGeifp}&|U z47Z+;GDJt`b*f9Mu>T1~$+nVZD~r9jFWBBWydZuMwA3Rv7S|9kgyr$)W0Ji499HX6 zKHXr|W_3kgP`>?=%%cZ?v?;iv;QJn3%AZP8r2M}r7)izTcd+Bp2QN%A#s9#8VPqgN zJuc3I9Ic9tF-ckXA{DTc{U}svej)u=K_y4Jafc?ThgpEeStgaeeMFN&I#{rv)?*6R z1(nH7u@V8P2pwVXyRXy+dKE0!M}|5Tp21>;FZQ&T?+$8zVfdBPLH?9xj<8iLpJI^k zHWp%gA`dUnnm8@{bn%t+_dD1H&8F6V&E}Kvd3%CNchRH_+S(c=(H>^v=QQwY+pP?{ z+ZB*n#kNYsVFi9j>|GYgF}DMCv@Z+bRF5=Es3j{|6nhmzjTsAV;mL@+{?*ft7L)_! zoWe8CNr zO(6yfx5NSuyEJG|Hk%pQR`AX0IX1Om)~=sAoqD0AN7R2)LB^i%At-Ujx>`^&hf-Sg zdukkupa>1Z`?Jkz!9?5jJ4EZQpK)MZgw&?%5)f;t;bZreTULS+V|&N3DSVMS!d<&# z-=O!AkVHPEgY~W?V^Sc<+R?D6Y+8A+X>2IDb~@e&x*sKC7`Rio8<~>X+6d*&vQ8B# z-w(2oy6Zd}WU+2)U?m0KX%hF8io5a1RN!sAnT7Jn_Q}zZ4qu+X)sVkaN60H6wr!SYan#_RXteKHHT8-(vTZ{sPZ zPS!My{lw~P^>;rYAN;))NTWOYrb{m2hWh9_%q?H}z)2;p@SSa4LH#jXS}Z7+q@bCm>izF-xO)3*QJn?P>fE|2ha?~?htJ1N z2>{5+PdLi4Yw_UFr2z(e58)vJEt$q*K?PAJqk~(?4@vqCtpggt?xY81r zq0hp_oaEod&D(vdF|-2;k5ujv%2#>W&sGE|lN?aS-f;UHkQKtj{us0E?Gsy_ru?U0 zUu`jyW*YUyDja6AH%huoy~20FDAJ5)#@FTf=Vt}32H*TT9Z7=j7d(Z1`O+^0nC%EE zkQJKmN8>WmcVtxo7px21(%jz?>n))98@zP+>s)u%FZ}(WBp? zr{fR%=H2sNtI_zyTde28OYk}8cU2Yc#x<*qmgiRbP;`=?R^-Ah;}+WyB!f)f6#a`w zGx*#=m41#ViT*t}U*<2s+}VR!lTR=pMl5eh)D`~B9y#U=NIa9nnz&!-zwri-uB8hP z(v!tx|A$yL_#tYgDv{TQ3RWw>tER_^gaIHo%f?BZz-A}UV5Z9$JlU_g`t=$JzVao?QN>M z-ot{PdxejqeTu^m84Z=jV?Asu!$lLhd(bV-o#cSi$NMjTUKSWjm@;f1h&STGL^t0) zp0v8lu1CvM#&@C^v%21XyoFU5^Wgg@yE=Hf1{e9k1*Z`=T+kx!xP4n=PPKk-0&l=* zMzV0LE~&=gzO8l002a4-O%nV|5S}r8sX@cR8F1mn&t27XL~K>%V&(GK$hMHPx+yG^ zy+v;XYjjk&hIZ~juE<-brGo`hBX=pO&+$ObN0+@e4sY4p>EX@fS>;+?>PwAIyo5)! zKt>a$Ot=H1PiArs40~LUSAF^W_vOUsQhN>q_lF1*ZT#8Nux>yU*|CUPokbOBgozgv z^&Go;wda-DmC~F?62YbnW0c0oI&{N#zEE+UD1qG2a}U4ZH+4TJG=Y-;F+q)xMIE>|;^_=3>euKX>8e{++m|C|r+?vRt4gQSE= zVhqc{_%<%?lA@^|=BRWq@Ic}m;j4L$KGSp&br&lvsMw)*hLO~Qq9v6n^$;?Gm(tov zzc6NLWhLIy1m7~KZusiFP9rAXq_%_VBx`95yXz@Op6?%EO7;^!E?dnHk5)Q)D=zkK zwupEJ4UvBzfja{KBD;PMq~{qMakDjfN$Puwc440uaq^Sv{_J^?;Z$!1xGJ zS0(elo|NlXu)Il~09GF)Df_4L!mSQmVpF?c>A$q0bKm18gjf?Tc1N*~VmlCO*fc?( zUm3ACu%&7bZ#`iUmt2hWc(nKNq$M+;9-jwO0hUM@eh|3)GuNWy&y`5SDK0miZy3h4 zNy!ktIJC1I!8~-)z;MxGiM|YPDS4aywbsCoD{y_UZrHRqv(im06%Vpvx};RJxb?g- zB>5*Pd~TcfvTaphWb0eZq|~;TbIZxawzl&nAKa3pud03EqY;_1LB#Fe;>C&kF7l7k zu(ZFFm&6C*{rZ~vc=k3P(94(=o(}C5w1t&Y3l`ks2{>&S2$z=k>)!#m-!A4#wj$8Fhy)mD554}Ip#O$RbR1JN2Bxj@5E>-Fxl=f}!-=_;UZ z2qFRFIJP)TQGG#^$UI+_O=V~6%C8Woua<5yqu{3@z(M%UyeIB~&2}EJSgegyzEu47 z@|E~7iw1+yNb=)_Ml2|urBCrbVY0q83zU6A!RYx#U3R7O9dMer3s4h8K_iGvA^;;y z+*gxV4+ewC{-Ig%r(b!$SgOy(W?Yf_bW*+}F$`z~-xJ=`j;DV_#Lrl~LhyL!mpSce zXPQu!!n=e$fsXS0Ema8uHjeLKOF=A#fhSbuxhS&3)X+?bl6{_kDi%8}D@WD7B0mbKn@uBe&~ zJ`?N8>`K$2Lm$OTt9f6E=EHNm)+109a-);=lx6@KAlwWB%|H;N{c9VXmYL1I8$CX2 z?Yxo{mwl3&TI0)r#iVdT!X0hI#MAYp)L|lOH_2AklarwpeNKyvKyf_CM3lXg#jzRJ z-@GE);l^HDdTw`zGtJw_CJ+=s{7bkK9FE>4?nB-X7NbGgBz^0pl)O|}*g^pTWZF{l zVsq7WduuPiAX6PkF+@}c^FvLnp37u|@rgV|oajuJr?6WNKv^tvclh9l@5$Fai9EQt z#ZCA7rZ=8EYfHnKbnJ*#p<-zL8Eu&%QTx%ULs>a!4meHe>TYIJB|8&9(T-;8`E<81@^;V|E>s5XY`8O{$Joft@D z)YJ1R{!3?lSG`X{!NN(#EA9hj-Xwe8ON-BoE%n&2c4zkxs`3$ClCj^fhXfC@CWW(f z8ZB+X=0k9e-eQHPHACZS7(c^la6aAc8sCx>7heiuNvBo^g2jSN@+UM4F)L%4g5@~! z{PWI(-!HLYXRa#?BTDJ*6%H%KDSHBPU#nM?vp3#@Ra7>Fa5`>2wh$u)^Y8)%F>C)r z)$(|q-sF1+ICf}#Y?!E60nGt-kH_dYscJ%Ov>9@~R_j>Jc=u}(A!qO-gG{)jgoWv;SEKe2*Y||4 zw;ZN28r;y1m&fQ=hYY)E{+&|?bw0=CUz>mBZuxVGJ2W1g>~Fb_DflvCi(pnI&uwntcIea-7|Dlu7ZMaCeWRkxEf%+ zo!STht1#TM1e^?%oG5||*_UA9Q_AI(XXid1r5$YawBGuG-2-#o_T9`JL4YjQqi8IUvFOtr;@0x=;61s`3aH5dZ~qT-lxU@7WBi z7O#&HjXP2a#@(DW@7t|HK?VGK)o^ZkQ*%p~O(-1bPH6tRaT9r{f~`#I5Rq*WLPlSo zrgW6cBv)^VTMZ3b#|_F~IoF2=f=)HOky9N3;O(a0toRr!t-xj?QZmGChM24HZbBT5 zR){oLmsQ@S0f2#cbv?_KGmh_lYfWTTKO5a{YxDkv>7mo4tkmvUc;BIAT;4d)chWp| zx(gK3$0z4szP!b&))C&_8wmg#`+-2pXgZqldp0AlpN+34c97^!5=M6PCfFTUig{V1 zwwQ>trmz#6BR7Bo@!$h{QzF+7s~eDVt$zN-6@0HT!{LWFAd}+{X9r4y3IaApFC?#R zCzG@(UdQS5^7BEej^Dsh7ZwKW!oAtfO@iQjGC{L9GF-A_x3nbAvcOadNjyDUw9y7= z$@IzCfuREIk7m~8^Sw!Sh!^C>BVYxJOK98I`318%D7g!n#Sjpi9 zBp1Zrw7K4t$*AFSP4DeZf!ulDb`?U50Xj{2lu{Rc|F8DGGOP*qZ+ip80x=L|l!-yh z2x$`m0Y#)?=yYr}0+NH>HjUCDpaM!u_dt|QB!+Yk86hQ(h7s?zq5i$^=YHPfc;n;a zzB#V`<@r0WYiSplRnCQOyRMN?XZb$qBHByjpXtfs4$$5X)HWQaxrPTKC$8efki1>9Q_KueLgl zz!u&~JGPUj{k~s~tp@QqxzJijyZ#hLp*@p@Pk{~nSYV_3iqPgL`Ct?sf$c~2oGPPr z1iI`Qx=VqVHMB<7;Vz=DwGo5UH}o4;gVr$PA;*~>ShZ_S+V1^&_GG=0qPCL48)NhI z{AjF5UWERbdqmzjKhnOUBA2e%k#GV@rgO=t3pej?>R4OQ7r7dk%K%`6ItB`&^_Hk5|NjFbRpI<>}v zqg&zC%>W-=RrQx&;MXZlsq8h>p!IhJLAo}$H!;#V;E0|~E>J?V$vz&Zs^k_NM#fUt zPz)o%{i}BgC_@lG$u+N`xDY1fuk^v|gBh6=2t=cvX7_E(i~dD$yy2yVwR`}Eme7Iq zY);(b9GDe;aW2{cIY?LQ$D2oM(f@mHt$H8`oVna2*|vsKcE7!8?|x5ipUYT(%T}h~ z)G687xxXCfM+Uk7d*pYFkmrZwGY1s4V1|Du0bIC}{ylBS$mxyoV>D2o0#-nJ=EV-0 z>)OhEB$rE_0u;i>wE1_$Zd{4W>_|gd|Mro?GI2%X4L85b?nCgBUxItm+Ke0m;vhml zpw)^u99xcTz0LvL?h|2Di^w{~k`vO&yV;L|wTDO~Pr6kXOUYGPyWS<#%xV!G%qU+> zI8*FAU2FFBQ~V;(V|K6OcOPosa}!fCipv%d8MnE{;kv5mYS&-B{AH$Oywphqku>RY z;|?DL@E=@R z8iJfF-r&6u>$}+RdT^gSVlH0zR&CQor8N5@MWV7>mIMu8Yw58p%ym?P(F~uf>zs!m zDtmdZvoVw!KS}{EAHpZZSWuOtw2^j;3gOB6m;U)Dv=E|A3Avx?{%X_~I8#hX+CuW4 zW>d5rvXV#04eu5aC!EElypcE@2Rron^=NJg>Wrr}zbu>aIUDz{msgfJ3fGJy^E5je z1M3_=yf{KDjo$$v#2=fe;P++hC7H8gUcQ;-l6tZhrKs)v zV~h83kH!1Ez4r39?Yw%AuTi8QNo$ap&p97=zO3=s{Ak{6-G^#qVc^BmxTD-5iaj;O zhZ2;otEdHV1la~01n53yQ=<5$1u1XFMvWs@VW%IAGzvi*@SIseSecgTEl_rLAm-SE zm%G~No^ojyGOc;1!_Mw$UbsZ+Fy?3Y9=j0xjljfDr8ca~Qny%g*17+wPdWG~=Und(~ zF~atniW#)a85D?~iAX>WDu%tN6Zn2tFj}iYB+;F|*bkfdfn1gfVS0`Q{>J5U&P`RP z(yuw3%=gg(`3;l4!NHhGPE_OE)LAFp&J)FwvnisjpJcfO9AfjbSg$o7^wgINGL%o@ zE8+8p>`fM&4-C1SxbQP$u)0pj+e5XGcH09Hkakn9k4$CAOa=MZ_h}XbB54 ze_T2iB*`oL(S0`Gz8yS!BRDkLHSF#@RTA;F6|-XM*fTt(J<~JXHeWg}kv@#)h@^xn z)Q$Rt1*rLP2Z@j)6_#z@czFTP3-=*ubAJyjK^xj8H@0qpcLjuHZh_bBekp#{sO*%h z>Vs6-L?fAt@$ByFtA2ykvvCTEW1iv~(`QZOLZx4@z&UF!Ei5FTA%jT^tY{Bjjtg7x z@mUNx)4!beuF%u zr_7N1gz)8^fzMlRFXu*TWLMzL;CD2nJeq}Zu6vqp6Fs_5`wQ86g)_YvY<6LS83Reb zyX>hWxWn{P#|O7*FJ{Nd#(hmTW6RCBk(*;)#t9rx9&=!k3B!hmD=$-$9Qv^mgK<7@ zEDOJMM;$TpD4>?uC^|oXBtdFctrvhpB-k0|7`H5AesAT8rw(#d-yrW+*Fhsu$LFN= zvF4&ljrHC=pV*46mbyAqT0h}Nj8$SV8smo z1IKg2L-(0uvexXhpO~vQ%Px#{7agm#=Xz`d;zkvNV)RhsQwC(rf@UC?aPwV<61$9X zP25eK5&PUb@2*-VFIuWW8@eTjG+*7;dX{ZP#}50=24Nc|WA6w`p^c|q_fQle77Clra@MwdQaW*a-7#H(xh>M9{ivt;JiJZ$ z(k`W_L^ia>3mb*R)Pzcj2ct%HRF&OL?@~eLru>dv-?A0IFDfrg8YJdofC`&Um>k88oa=`o_cU#Ti_|=M?w- zaH5fz`%1>K1M;=!;eQA%8|OLSLoQj5y>+S_r0sDc_C9Z#KDp_~+>shA=s(G4BH$1w z+HqHW3$Nv)tPPFZ4!pAw{EyJo+HI9AV;$0QsAB4QDnrGvu zC{LVCaPG70dV8kthHBpG>W3htoBlSC0mt>w0cL?dZz=zdA>o}BqwUVY#g=s_pUJlT za6mEEi;FmQ=6HPj&DxpDH^@d?+hDI7o~d|?x_Yr&87Pw7K$M=nucF9T2ec6Z1{jpuT~`UFvIyP!L!l1X6|H3~nF? zerfxcq3Y-w$sT)ftx=9;vqy-`J$iK8(nUuP5#WWCfvcOg5+WB#k8I}$K7b}G8sOgF zlM9=nXjO?Bej`0{mm?x(Jc^4r0$_}8{70z#$R>4 zu{ZTjD#>hZotQaN*#I&s3uAimKXy{{`jl*5aklJk2F&suu*FwZolH_O2CIBDTUL-B zwKxHtqKhtDwAQ{N-yQw!9vE3r?V7E)2RH37JlREsZy*?f>kEN;8OHmfA^xlHn ze3lX_9SuT3clxWVE28x7h-wF!=}EQJkEI2t;|s5@S;csgK9aJ@w*b5VVXXDqmm%rU zOR1QKI8e<+S3w{kt*LtUv_j++mG(py@0hkdtM%rMRZ{}#jglo;3Iqax0mv?&Rre7y zh(*wGRrUiAdIpEX2B`qdtA2*%EtDBTAM_oG3aYF)qj-q)&sGa();XIX5_S6$S=k`; zt*TNcCIIh-a%XDAK|xsp-1Hb-x~|GxC8C4-IY9`G&j-ZsQN!D>GP6SHE44_V=m0yG zrwFy$oGxV2Y4v0x)FR@4Ci6c#Ll^4*zcNF)2NHP`$7)_(N0aFTK(racJ)AT8;@pd2 zL8%3nfzCKK+p3SY6+j`p7-C)6Tkbyly(wojkXP1xF$n5lbG&+^V4CGX5mg(Cqy9yo zV~;b15NIE?4UHe;XC8RVW<>bNsS5<0A>!Oz$U4NXZD{YY7fb^OUKrw8Hbq}BqAm{G zF1fHOVn+er80tJ!nKZ-?J?TI6yCoe5@FLfob>yAqgs5Rk0@TMe9+5;4OhB{gki}#( zs9kQj5NpnEbStn_Nh;)cZU3o^rj_1nZLzZU-q*HS;-8Y-pFrfS{P*=EIJNKle0>20 znormLd#TpZQgyLVhq*zkhc-N+BvXK1Z1!#X5VT%*`8t?bxzGr4nA0#gReX-F*mTt{ z-u6go_Y`(pl~)pPZWoT7v7!N{7oD`-xGs$d$=~yMRO&uE!V&8K!226N)Iz5D&K3IX z>AUXm46OeKQU{DKp^)S3JFK~Bjur+!&Y&Rm`XXkxmiPWNN5!C%O1~Lx$Yd2b1$;?d zmYW*Cxu`a712YeF$i=JQT7bn&36oDM zT|MEgOc`yp7w!xWwXg7^%$JVM$Zo9atlrWc=i9Gx-bG5tyD&aaNZ7(FF^nM)Qgd`0 zoq%^-ewl;Q4c%@nKpdQxM}s-=lHxYPWAtlCnIWuVmql`R8&EO$69r{LS5^az8d)TiuWIlJLL`o(8c#@1 zMZ>-Q-*0*9@(!80rP4X9+pLCUxSFvX2>iu~WN=(j4?63rm(5daNl7`!*(aOnd&pz( z-RQb`YG3vlK^1GN)Tk`rNGFD!R)!2LF~`(##7&2v_GkU(Kvx&4+Dn9t#uPrHE~3@a_Z12O~v0&kA5rb&RiwYaHT`EiBSsShP0zX%e!(BQl{b*$oINe%%coXiL)y%xl>f%NY zD{$J3>HTEwfG#jqK#op;ErT$@l0gj}ZV}dugM!(81}2bfCNO*A!w?BI}J&jRLfqLXKZ?Y>u!4Gw-LXztkbBx(WPLSu(niYnNYFu z8N^E!a@kJJJqBruht?-nZT>i(1%!P?ar?(JVUM-o&#lhEK(s-55aF?Cyub9qQtpo1 z-WxsRiZS}?y_Q^O8)C)vrfaP-jwDI`vH!Fz^tYj1LTv7f#x9DI{z5Qeyg7(12wT@i z8^(K=XA{CmwCPG+Hf!aLvBltZFV1Yo{TgRfcm*MJ!2+Ak9)&d!ncrg&mU33BV3l|g zuHn6)ZOx3iG2JI$?tpUNZ&z-Ke?mWl2Pd}xPGPsRZ;O?_dYsd7<&-f6Sp&^7{%;+k z>(+m)3YE|0Sz50CT0L(fStWwh(W5FqV5G(bR#&xTkqgzj*_FMts28c=KX4~)bj0IQ zD30~Fbk@HeFBqSAtm<)Wsw7f=Y`fcd2oexGo9kh1EHOqc7nwmg7^SM3r-*oSs3DPd z@u}07JQGjC{`mta@Mkm9yo&ly7uUBfG=WXpR16$zeR-rTZOxvyF1n^)Dli?b#>(xu z0nRb;%eU0U5F=?Xt|I>*Z}3`pUq?9K_&l{mBl4*4i01n8-1@RS&ALcELdSoD6kKGC z&&cN>%`A-RI?N*@m@>!Z@`jOv8>8eZgRoJ=ukm^`=d`Cprh58tCM&pD-c>}d$jSI_r~TUkyc>cEc9i^QkB&sQ9obL4Hv zL10w->3C{m*?%RFg;BYM0;bIJiSfUVpT_ zW;qYWec|A#?q`|5@M=pM4K84tRpibnwK_L5M7C6;g#6B`8R`)s^2H5A_O?=lbiVG18 zuBl117>IgWC1+#Sa(FU00o#Q=s!z;*;p^6#3eTS77SZ9_p+7piqL!! zfr4c>v}W2Po(R`w44);21tQxCySiqax$%>6z`B}VQ4M`8h>Ws($h|2Ik`7Z2m zAa{Cj@LpTzX)*KhvbASh^u`WI3#Q8`1KvCfJT{@%;4cmGjeMo!L+~by!dQpq8(Rgy z*0?QP5dltf!Pr0VVMLz4AE~ETFByL2m~kG_>8UxKNqLLU#>k^i ziju5=9=C9yXLhPTW)Z7B@N#xAG{U>-+nwp-yPJ|IS?xRRknJuvefyo~!)safcpJ00 z>Hb4u^^VEvdFAZ~9!ojRS2xh}G#2=WbeFEyLVrx&ov%;kF2M3$6V0!dPSW&lxMi&{^Fe^*RCz%5iW%+(^gzxW(HH+I^3%kzh)KLcFr#X3k0{gr;lxTL{JtndtcXM z@K{<`{+yrF7C3W+0mkI|x!_^iL)IN{txjws=vngJJi@sJL8}zkEY?6x1)Et z+ZY8u+X9@cRKsw?I40RYRHs|ga=wHyL+w8)yrq>US&L5NoJ zJQ@s>N>R#yH(Bvcgx?RFw0?I@HP1`DUF=(GI%Umw6j7n#D1s!A9^tZPt;6vfw!}zp zjv;JuR!69!IX=#~$5zcpg?@-5A!+N$WLN169((N-&L(R;I@EFpK*8{=TW^D1-0$1Q z8kah5%X@UJaYUaUg1x`F6&~p1?IAso@|R92+<5g%Sm2rN2svw02T38DPLyhBh2Z>B ziqi)Ew%3gcpDw`(1+&3=5b&Y)HNhj?rVURf?b?&(s9s96BR(p?{J2{Bqd>s_Ba(BG zNi2}p6NTg^M*2JItt?qD`sNISD4>+2>2dQK7n;4RrKELhPZBrWqb*#dzBZij3K`jC ztrRir+3w-B9OXr==qSdW-0&cFlu`=xib#Y?ZlzdLdQ_+oyH^3NRPVK7Gsf+8@<5lG zYG`ISjCe!Vpj-P&;HA$pi-~85x%L1Yp*+|L5U)|%T<`#)M7WE5yWZO_(COwOGzM6* z_n)FFrV9B0EmJ2@MJ#p&*tTh$IwA&#?Q04<7v}NU)oxPxOV2L! zc=V7hV%oVk!CPmPj96YWp|2t|dxd+TDfHrsCSLA5svh=MVHX-^O%RVn^PaXisl0K9 zDW)JbVl%E8xXK)J=SS1R)~0Sj3ue+R*0VN$3p`WP+SC~w(BqZhy7sQ>BdCrbc3_~x z)z)9y0#Q`sYC6hI%FhbWH6#ezhAjr(neo5d>}Y}{2NxfZFV5FdSzCM@Hm{V9m1S_3vHv6KhKg-*RgnG6djM2LteP#XC;Jr{$K}5R-K^r(ops@gy%Zdd5m`KQi&e{8EPMR` z?`f2J_U%cxJ|t62^ZtZPWSp~&Ll6(VW+!^4OHsklqz4G4(B3AtsHtncPD0V{EuLpD zw~t;ZD27@*pL2jANA_or#4z~*PvPf`%ByFzb~D4 zkv2EZYUy{mfs$t~ww-J)K7ewJ9jDIr)I<%I^Nzv@1%9MR zcn)0mYri@KtoGA3BbZcHQEQyN$aG;~mzcsfG%Mm=Xl0})8@ik6Re{kglK75(fYG<| zglr#w6t7&`XuQ+Nu`CIXm$jZtdJtLoE+zk-RXKNHx)~~0Es!3^zU%RuMaEs9QAwoqnr1&T z6Wxf;)TuDOYf(jsY=4jy$!SJowslmt>*+1PBPga(@jXcQ$JH^d^MN)`o_5rQ(Ylm74KsvC@677_UK~lRjm!{SSt;5d5`Zly)Lb%w`M3z2FLdtA3br?a zYFS5d=Z%CS`S_c+(LJOetud(~I=>XQ*LLxw?OXkXqew`I>=XS;o1N?-rC+bx3+Qh- zDq*KKFelOm0BD&mcZWvABB_XSP^;9Bj@3(uWw+D<&} z5hVquJK5L8+a-@$zi^LLLafM_5u~uA6f2#w=DTmfYjrb&VdDn|LDMxsqFA+YCmMEOiT4Z9Or5T*w8^>F9U+}p$T)!rD9?j5p2ZNR5MRJTOY@?B1n7q z(*6Auta_jg?@5U~JeLFdu3K8tFT5r3R^;A6T>VF)4%y1xlyp!SQguao5% z5vsYNP+<M{f6dO9bie**()=zP z+-YssRN9wh%ahSOV;R^bmmIDmCYPvg>CKUPHvNr_JE2yYIpz>eBf%B3MmHd$TrIWyFbPyr>OS`v?fpj6J$Vtc z^O6|gKL=TNurJ~llf@5O^~yy1I^Tq9O;UTgn~r+QX`f0QGhE1`Dv1L7av(YEH_(E^ zZh^ZOKbOh(r`@}qrvfhhosS3qH8z^wwbzzdnXZA_JHO>%;9`k=VM8Gx8_zyU{-%+g zJnQ*&H(<~sO}xa|V_;;@f0<|KlO6K{0$Awz3b^q@sdOdl!EBpM)d^fzj6Qi2vW;^d`h81^y z2+#B!Gqp$r*WCXO-Dp|9m2mdWa&E5=2^=i~SMa1<(}*WogvSCB3wu5~!58|wES9ql zX+~zoSK6%-eaK~PZr^RE!&{a-!XmUa`^hh-zotx+vMhlVnYxrU2P7V4Gw~Gl&sL*U zd|SbD{^L*&CU&iywp4dJ?c9}F?n{O}wvkFyM}5!Wx33HE^>}>oq1u>D!XaXLCRS&h zN8S3bcCN*EjOSFc#bFgZffo8uU{s0lLfkRpk$8H?Ud{Ra=9*(U8i>fk;jf$U4Qs&f z69T|M-)B?`o7GiI&#<{EOl~GFg_A8jsEAWO@WrwGsSs4h*DIKNS9?UF3Ku2KX40*F ziyw47Kv64Vw@Mysqi{w@@UE=U{mP%`4tmWqf~Uje(vut$@Tm2&4*jAj)6)}~+_Ydy zg-P4!>oI||YSsh$f(zUNRtnR5h&lHjs+**P7bf?xWX3C)w`3*Iri9z9vn*@$rgbnr z;nlP}4|0)102V=vt_Cl!&bHY$6WwT^$HzOHiu(o)HMIPf zO!=;3y^=?5mGEx$Zv4}I#uWsT&q8Blf+m7ISUgVCBT?6dC$d#M`P&>t1+3@sH59^{ zu^j@zuQ237q`>h);97mQ`k0boZx$Z0=ABH+q{kVXpZ~zLyU`#IPWntT`6LbWQRKVZ@>6))4e~j#GLl*FxJWaXMAM%uz#2#O)<&mIQ z9)xyIYVg(T&CWD>*8j%NIf)2kk91aAlguugavMk5Syz9ww(Y&=Zn`|tK?j95KmS2; zw>IN2aJGIA$F`4eV|MdvI%b$bP0&}941D!t2ZY$;(s-^KG#jFOH!4grH50>RS{q_D z+V)r0rC)1F(eCc_O}{qL1Bc1^_Y_s&)1YDIeKBxj*rI=r&5u%pY1{UIQxzj}>uqbf zDP7&P)W2_nw1;|kfh7Ij*Ir;d>O)wstWx_+gxuR9UBytT0VnHV1X^g0AF)z0NKFoW zj(+8AqibrTDw=)C%o8zKAQ~%@Obc}HYYTtJZ%~yIn2>)+`rE|IzmIV&@fzLmo>>hg zbqmfb*j43A!)6MoJ=(Ym_9$7zHzoHJgSa4!p>v;o>x3BGwfUGub4Qz7Z^WYJ-=)f` z4%%>6=e@^5!J;N3C!b-DYJ)B2=z9_+Q#1nutg1xPvY{=-Os*F`yqfUFW_z}Vf2f_X z%CIHhHT{RAo9vb$jJ(9MOf$(vS(k`S9cF^A z<~1%O3R#@(e?PvxO(&r2=qkQ(*sO|&t;sgOF;#O${I0p?c!m;#(hR*?w+-ETfhp#IPl0G(kAZ)VrOU=rcJ?zmCX%we^RO95 zh5Y-Z%Fe}thqbtQGOb;o?7}Q$CZFuF8Zkn0heFI7k`ll~^jsH^NMhF-t&tt>`F$-p)9d5Em)l|ybRdJ?djvW8~5>ZE>6qY0YaqzV5XnkZ!b(AoFXr|fGf&+pn znlU$mp9S-9ZzL!ic)xtkkcyXLH=o-X#@cCcRd%*qI{(u58o6jC8PVC4kzV`UF44p$ zeP2c#mMCC zf7qXbN)WuEG&{DO8CxoYAzdf0w;b51<7@+h22>kPo%hhZZ_@gm{*G;*IvO&*$F4pj zcQ(n`gK;BE)%Pw2roKq;5z#gdL|rsp<_XSQvVZ;8^daUyW>t#P(9b-H;!cMVNcps3sJ`{k5UKz-PB z2fsu}4`fIV$J_%}&!zPHM;Q~!uthf*>Kt-7FwC&gxMO^U6=kAH4;3z|%dNr=-7 zOmBv*n-PslnF{Tyhq8Uzo}N_9{)eK}OrDjxEm)%nBqVaaI5)F-RJgHTpD~x-OIPOW zR;Pqx$wlu1)a`3#*-OYXXY_d!U9OClH~CS>Lj}aO$K@T%69V!|()|gNMgK6w-A1Y{ zvagc?3#?4_4T)2{d`}Z(*7omptk$zz;IVrFH4eDQlc2!$v!JL7?tykyv&G<#HNpyN zMcnA>^!FHsq9~q-`F_^PMzaktPW~Pd2Fe4XD)5Si*j3;o$sK@@{f{CT3mhPY%AOnH zZA4^AUKa6bkN%-X&myme|5`%Z(_{l{(xWx4j&LIyUM+ViR1gifoLNZR^N+X?1Ouvh z?yCEwZs~$sO-pq|6U9Z~rZbIMMbAaIIaO@Z7x=3# z3XYauXasbJKTE}+Zu?Wz|E%whSD5@PWv+cINc%D~)??7vfpedIG`oK$%1)(Cze z97&s)f}^&T1h8N|$+?ug-%=w)e!KO13> zD&3=NR?(IF*b{qWB8v5jsc(1pk59a?W!R*sW^CM>?a$4l%i3>uIWh~GBRrBPO*`U% zk=cx!8L{(b*&D}trBK4VT3R!74x(|e>m&il<~CpE%vA{(*=LGnPH52|CxBd^jk#pWcjzy zP%pcu<%jkJzVw>y?;V0k)b2gyWM*l;DXKr?(%-CxFSz9&53*q#%PD0hR#o|ChkD-L zZkV5o8gzVJa*e;IH9JI$SHi5W=8rA=RVHPRI)bP^is1{uTRGM572;Jy!EXh*1iEWR z{p;>FvPTW2HCzjPz9$wE3FA5sJD2P-8jRXEkn`X5o;IY>o+i0FcFHalIt!i`yfsIW zkzo~spA>rqZMm2H!<|6M8V_(7aH^7uB~hT(zhQEPIp= z+3RLoD|qta#`R+nLcTA)dPzOF8k4Ix-Fp06Yk}nTa<2{Y2E6p9JmrA&& z&+_?T$yU)(HN>Bm5qcIB*yRaN=%#2#{ZEBA53)2GGI_m-o9uz5!dHk&ys;^%kE-Sd>H9BAjZm0#$Q#P2UGPD2}p z)f(qDw93|h5Qc+SWtjhr6>!^^KX8btIDlVuA9q=PNk-AJK!&>0`7;u!xDj517Zc$z zOKdSUq?~_#E$KL4FFxg)@azn|q4T<` z9-fCuVZvhC>v_Ji{Vg`(^X;q~q;ri2T4cpkPP1MeA2=7SMxDiwc<3af-+UjryBq6) zb>b(J7Z9jAderc{ZwTZ!pt<^8|1;Py$lv25$lqfv@LM{6b_@Z$;jlkqlz(gddwVzA zGCVi~6ahp1Z3n^c4}f^@Qb*aw(&w(CjrDn-;om$oz!xu}zs$74u`xM~{Thr+zK5XZ zaj7_Y&(aYVI%N-x9TiD`(kG9M-B6j?nyagjvBcw_P_Ps|`Xb@9gMTqzgYV4!+w1^Vd=b4D!<;U%|FO<;5GT>yhI7u%BcwaO3ksfptgx#zK+Z>S>viYw12SZ`K|3t#l7CW+t{U zLK?bkLvY%RJE9qn))3eUur+n|eM>$O)=1%GR=w5wk0k9?wi?oN@`+z$HqhjM{{7$Y dKvedIpx_a|HtUdre0neH7qu^BowKMU+{Q+FmK+=hQ#d$&J^0&xV1x*3eh>Wk)m`_hE(b?h0vFTq0Py^mvytUh z4vr8>4vxF`IXD==(A`-Mj-YcK9CNogIMmZQI0XE&Fcz8|9Q$mpU9r;N+1Z(=GKmXY zMcwOLOji5orp9CPp#W0d08KJtW^HrZId{=Kb^duX^-=BWXA%QZvTXQlzPM-obl6N< z6V(O1D0gr6Va>|XJ0wBGG>Jso+S;03VFtZjUR+!>Ffh1q;R0@GGbAKrV`C#DBcrCK z1`GzPKPLB+7}gn-!oos49{=szx7gU&mX;PzPtV#q>|x)L%Bq^!*e6GBe+fp0rl+R| z1O(XG+4=hV(rC2&{CqSTt*WXT5fP!Qt9$X{#nI8xl#~=TH8nUK-rwIJ8XEfX59J=V^6s=){s+A46} zN;6_Sl4nGTv!*{YF%KCD8m!gX?Qb~dhx9F!4I|_jvn*&U>l(8@hS{3o;^LyLtZZRn z5fv5XdFG#jFnIy%*p?|_yPuD7VcwvN|Ir$O!mxqzpYuS!eh%EwPtx{Z6 zT+A5lAB8M+hiG2V$az-R-<$G9GttmZLE_tF6?kU{6#KsQ^z-hhU!yKIE};#xjeogi z)fNrnSmyf67~uDR{`{9%AY;K$hh;q1uJd?=hhwoJA%aoC`2e-OhW`3?-?+mT8l`h% znF_oV0}S}D-M`CbcI9-oO6#HMh3=S=Hr8oVyf zb8&$+dr-<``tvXEcy%zu7|Q_6DEd!ELeQvn=v?>t8-lI)3h zRL*kZa_4lPsd8wn6Hp^TSN>pi15B`YsDaBeW@*P__P;x=lC6S`QLEyhe0aOZ>HU|I zkSBc$$mJs(-|B9wZH7GluJnYo-jab<_0dvX*~-1lfb{f5{ZG1}1BWBBO$ zu0`&K`tDHORL&Rhk88);{uq)Ot{=ME{rW&{+QgnvYC7 zs&4|9*8zil=Z*fM&f?!uvb)nRc8QGc5%Z|HEWbB&TV(FXP(cf5Z-`4|%{ixtIEBptwG{eN5hu|*SDzdg2pm4~uq9@N?Kq_FnYnkPp=4WFsLA5B*Y z)dE~s{b27XuDve{&Ol@-!aQfQQRJVB`0N+D`pIAbGwd2*A2CvNkLHuPpo96S3 zgvY15GvA^BK~$#Bn{16YnR2KQfnO$oUj{9C8g&3qR|W*ZvDsWy+Z<&J!l!9)_8_mr zFEiAac&6$f37F>*z+&-if`$4OfW&u0Q8cU;5V#hR93`fpKk+8JBpWzi7|Hnk`)0 z>_{p=41Y)xN0x7f4rkf*8pD`GQgitdRHPvcx#sP7+mTu-mS!qWDqNfB zm>lewcZb^CZv2faznCA)4;2y73Rzz3uvleyxNiRG8ip6s-dbK=Nt%M1`Ep#=d8Rl`8b{(GXN^3Q&mv4)9C%HGuK71S9x`hAo z#00N%OlF46Kvu0 z;>G8@DzNG3Qm~UUG;a*EZ&-eHv(AWUtS$ZE{AsP$KU&PR#qXQ{p83blcf;2FzLSfj z;&;D7MFEb5eG`yc@M(=@x(E-sxgBkw0w)Hri}viW}l{?khnb z+Vh8j(p0fvE1TXGIpC#HuMDrc>UCrhzBY>JO>k&10`*WkWT$ zpXN=-wzzj`$+f>|*LT!|Un*CZCefJ|iBR4v(Rb5^ZqN#kuQgAjQe<=-j;ClJ6Wb~b z(|W=|#DU@;<9R26@|vt*4oxjk;}Xj(wXdfZGTZMTUe`bWL4vN-($4iQ+}?*4j$}~h zklH*tAcIeD2&L1RYDH~dDB13ZtzyhhfuW)Vo z^0PN6EAXPjRDlY<|0qgxq)}SlK?2#^o3t}mxJJ~iqfCaqIop;%quZGm@rLJ2J=g9q z$b(&DUd!64?}nP2m#)S-L-~cWp?_&e8&p3?kTc84nc6?yGDs>oHm{joL-81aqtY(- zBt57q>Tjo@s4hhF>gC=FCiJ*+xuT^n(LGe|2vjtsap{dnN;4NKJTv_FEoHaa7OiV> zCVr#GaFJU*gV0x{;b~Urz8do33B*_gKfh^v0eaQWK~t)B|Gpnzdk8bZdTj|1(a~ z*E^M~W%yN;gSZS|cxf@w1&QwZ*0ZCv)P>W%G4EJ?@qD7|Oc?Jpx^Ih)8h2#%5t?zZ z(5IQNr9nc@KRlt{&@+;6|&xJ|Y3PxITYo#50>cVO@sirh@qz>$Nk-9_z zUoz)6%tO;Npz_{pNJiOGlGj?WO;uQsRfx_`nRHZWa!Ht?SPDO9T*^XY5$i8&JCqAI z(q0~gvyNC!qIcX3FhD9o;Q||~1#nj@MlI7bz=}~K9M`8cQE}rLFHNsns?nIQK*z6w zn18%z)#B{P1)Wfu@#+QyUX+Y`nr+g$+&|*lm}fzrZPnbC|M)O^247@ZIn~rBo+l+_ zm?vP`Vi=K{+>Lk5nTpXoYhJ`}mlW=8qi7LMY4-e*Vey*zb+9$TTny*HRFUOLxLv)~ z_?9)?dBK-_s|^s#73@8gmf9HR&4B$7K~{e_&oz%tw1&mBcP)KZkltR&x#TrcxVDmSLC#ct z$s0;rK`d=7EqGP6w4)x}L?ZxUrJz&T$$}x<{+Xc+F+-09EMjLQ653Um9H(Lq;+7p4 zUkPdaym}25wUh$5Qb93z*}>YmWq#nb_EIqhQ+|(VfbQ#}v?Ix5gt@{>N31DevbiIZ z89GBrrp})hf%9kQ@-{)tUP(IKp>a(T7pSGf6MKa5d_NAX@OHHWi&sZA4B^aY(0v6% zE_r^`(jef>5~oXMmaJGu902(R-v82wr0THDHM&F0(?F$sgUi})cz6?v{}gLjogpBpY4;j_qY>ItT=e4BOKIYq1-Xl!5L-3xnlj!u&{trwdPt8M^U^h2md_%P{*<3w9&^FY%#_JE&)3~cGk@PvO4Q0pOKXU{Ikiq3P&gTf#|d@H z)878c+j`gf*pbB|VCYe@@Od2oAkNr0#+k@fC_CX~KO#ZUC| zP33G(Q9by4(hTzaV;1L4m4Y1$wxzQq!bRdwIxq6ATWM&1^mAXX46Z7C8<7m1mo}GQ z)fjFFes|9FY<(bklxL_DPd%YCM8eI)qMKspMDLKqzlaM7O;atQQxzU!si&_7okqo> z`OSqiBa+{p#iDq<(Wp+ zrmh_&GB5AUQZhnjm{fSohu;T~G_jptV|-%Xbv!bXV{AUGST#E&{3!KfLD8$su{*2t zh^59Y@z8Cbl`m3aku*AZfV8$W8qQk4dK8#+_%5kdrhjYcFkwMD(vXYW*Q^d{@)m%M zH$J>_Hxw%;U$k|Lq;Jyum8dD@?Zc8{ory6s2~_5GEvAc>6hN16%#iF6x%JugAaq|8ZODU$3CpppU7>ZkFST5~k&tSb_h3Q$Y)$Aup%phFA+}As zbNF~fh($e>VnHALMl7tvYw+|GuUz^Jrn9j4u`rr)sLGg1U--l~JWl)3iAq%1j_uk} z<(msvKiG9DeU4x3#dP!+m&U-WSEyM*T4WEA63$=mQ(M)kyq2|aT4 z?hN?2;q+(auVONsIIZ0Y+1JEJtvZ{Q^ma+AL^zuHoZhxn+sxkOxzK5zEw9vzr)_xS zs-LM8Cd>{$&(;c#(Hfd@PQGcdyC(Wrj7kj9pYJUIdT^!a_A@@0ci+`$2ERT5RL&Z! z2iFfnux@5P`+*KVbx#ztXPYkp1W0LD4#D*6p&tP}WZ&+Sdhl`|arJl}N!oqN<^;7)pEuEv^1CKRu-4&qc-#f7GvC!h>{v`Y zTDYEPSBX%-LbB66UoP#wGS>_~doaPGD5hRFTyJnR{W=yQinbEim2=xdyb%gO45!&7 ztIVfAFD4)>f&k{Ns2%;eNIJBCXN&svYMqK^uqPD2B;+G4NO3!I@arDgI7%{$2D~x^ zUWoy(w0H8a2<=G1O+8S4MZnn)yfQx)Gia_B9LMr`uFUeGq<*@zV|W-6$%j2jd!kmg zuHaW~vr{6R!h*10MLOsWLfd^mhEFz`1_5@>*xu6g0o;1wMO1?8n>j1@WAFMX-ly8EREn0JYK%A0vl}VYw>@q~eje)bYFpfPTdGjMnif&t?p(EslZO-N8##z&NY93VGJLr-~YlWOb8&ngkz?Cm3z^k9k6fdFTk_F z(>-m=1JE|#eOs&ZxP`@UJ5@Au<~L|N>w?%RUI&a&f`y6GRNM{&N{S05M&mRZL9E4{ z`0aM>i-1FgilW8+uA#@6%5c;Y!EXokHF9zPDkUz_k9H6*0K1;vFq8GG zw562rLpVFLhO>|rxBnwW?))|6vgP=BllgxQ`6HJT+s{BG{r&Sw$cTQH0X*k*?k?sxmAK2gjBe)SBy0bT;|@^;3)<|47k#0P#~f{Li$4kZsmQm`MGWg?NcD z(`_S1;$dj-kyQgdL`;INj*@T=MS3*xl?;YwEIgepE%$Nz zh(41(URLTH3t4RW7bpO`SLj}{e&D*1LY+^l(UZLu{1Yzx5AziM2x(#2Mwa`3?$=mK z05MDlH=Dtk6=B2xc(0O1&V%NdQKxmisw=oin-U$N`~pS+$&zdsx0Qq)uzOUpP+7)S zUv5EmF#7OWk>>`cARF6>SDi;124v66#EP5s$r6@O$3Qs+(H$+0e&LsfAJ>(XW(?<66S`_+kasQS z`oU>ctaQ5HIj$~GKcv;1jhIqH3psIi_$Kx-dkaR*R+$0H)v$^k9U18J2eQu=wkA!{ zmd9Hte1WYw z_N#t|PH)mhqa*!AqbL8AoV3l5=u4C5FW1wSj-v{+1R7U&>PNT?&nG-)5Sev^Ac*%-bD@HrNJShVWwSN%L$>8o}@yR?XZ^<2h6G{NMHlIm`Hp`r< z1cwoy$9YxI14)I}VH?k9AHU+hPJ*YV*M7UaN7!>K=bjud__HG6wGOcr(Cyn?T@DX&~XIvc3cAX=4Ywf$9f z1l46m)t*P^%nsx7ck@&Qz-6*k27yK@+!)>HEQDE1J+}==v?factxEoVn96F~==Yb1 zM4(gFhtDd^@pn$*!@)Pxs9D)2vrw) zcGKR-!e3ot;51_VO#7=eU!7_N=@k8`f%BA=4o%ZzUF)&yow5O5R$l2EYi8w|(xigE zk*-WFRBxo1yu%TPm>Pvc_*K*3$<<3x9ow6@nW@^4_`FQ^W2zkerfD)pZs@pXe_UJmxU)r zd9?GQ@YDffzf+lSbwq8AMWCnEP5K!EpZWEf&lxJ%6u>}XHXZkfdyV>} zd-Taw=#|;4NoV^eNle8(TKuHZ(N|~{))fpV8;JGKHTwqGCwVvC6Zn#z>U=#SJNVt& z-(2A3YD~eS+2Oa6{J;q@*2hyG7BP;wmAtgkHFm5t-lW32j(UnSxk7@PQRGw?Xf?c& z9X%D-PzS_sEV{2laYwKaC-^H@fkEpZ1)0Sn<$q=0C(6l`pRgj@ep!~Y((tynJdJ_B zL9)GPbo0`zRs*y8mNh(9aAL}19LICW+;$GkxQ z7Ei4C$B8ON;kU5~6WGAZv+Tna;lybh5%kNXr?yetV+|fY6+s~ZumMmzs(!yxk^bgb zV>r)=an0xa#nDT3T}j1c%m2h=-g*IvUCA^OYE$C;zV^!6h&c7Kj6z9K^6!* ztJ0zT33@!`(i3Y5RmW~2*ZJtQ%Xh8iaw0#A_^OIyy!!5|RZaISe&i`<29w%kTd%%v z8IhyP9`>!dsp<9tcTUGwpqR)o9%{Zn7XmZYjDp9&z2S3UZ<&`zX{J!}3y zRak7v#$&cM>*aqIgI;A{*&+M(>d%t#rkoo)(gc5&n#H8t9zghNvwy9_sB~-*t4)7+p#1`2;9SsdYCR3KsNW@O^9P1oZs*>H+sLWskO(PR z$3R*5)pXyhsBHJ%4jL7Y3X$EgymN# z5e9_v{|?mtv!L^&y!^xVmgTXC!;pR##owb<`e8(t_^&39@+aTbvEHSLY+h+L=o4rg zGPv|2Psf#0d!}7~YTewer2=NhR`~1@Fi#^CXtnFY{U11|Qf|20Fy9G7TIi9@0tvvZR=iSrz+@tN^P z&@@bRHn$iFhp+=+X^%{X238(}AvGEE%LpK0*=aa|lZnS1Z8DC%l}68di|W!z;}OU| zlSQ^4l^h&iV7nTPjUpgoi<69X1{&lsW-}={t(S~Xm~7AapLxwc$BplQ8=pj)opTe& zyg(;@y0q^q7^d`jkzG@@|K)cLh5cX?*~pllH4!-D&ee@B9yW+n!$|g%Y*I|Gqz!+A zsQ)GyThca6VDmz=JI4j*dGRo!>H@rdP>d?;9hr_oN`Vc)He4aY3l8ejw!VG{@U^Cv#!SE&eiqY4x_|${taPqgci16F9Gu1uqBfxM zM#<&gema$x`Z9rfbkRSq=23}mnVy>Ktqfd}y%40K+*<#thte~7y`|uDUG73tp!-hO z2m{^-Ilz%bQ-B!s9Z?zhyBk^SXQ4PUnT+QAhE1m%z_{;`@k0+?N7i89-!_$;x zZf=@Csd(2c)=#db?4u_wck`tVIoi%b4m|kA0IcdSm>s>E)uex;KxNEGwOlq|?C=JsVfm!>j19JMiS^tj0uV*6iX%}mM0)(6B%;YIhT(G~rgOvu@s?6^eVFH2I}i;5?Lwp#f{eQP$G13oSAq(bMiQTgqbj_c?4 z)u;JQDdGrDJF?&XgY8EgU5<=mjtir#?11zJr?PW+G#i9O#FRWd3W=W0XZwWKZ$A@n zu747H66dL({dO|&xkyk{Un%f0%cGws&iR@;b`mB2JP`!Al-X%~8doKexQQTFU_?int z51*3dDs{p(crrq16Q{P#70yDBXRo&tqwuk_Cg6hy$iINdXf=ib3+9CBB$(vXWJi)mGC3!w|JX5!YGaA*4XpvZvWH7f(fs8h! zkH~)GE48DgWkANKrH>K4(lcxbN}bRw39#Xyzh^}*mlFW};^i^(eN9HJPy{(@wV$ku zuxh-fH`v;z9t9kW0t1Shob3H#F!+ukc;~4VLFsv^ zIA)wCZL+Cte`?rZ|I(|Dkvi4t7ad!f6pQ5usNmVJ(hO<&S-;5H*1uwXNmB3So? za&bxz)JGliLVkK6WXWBwj`utvMVGBLC0J(%o9DNhI}(xtPtW9X@!VxAbObV_b*a}} za?(@OycOQ^XH5l>;^J>3Ov!S?nfE4oZo&gq?T$i-*W5LQpCpnCAD56}{(+i*F4dy= zgnt2Co+62HvnEfIy+zLsZ5Q)9lth^GK5br$TFjUgOuc;tV+~6|aORl7`)&{p*s)6r z-`x34Rcw=AMEi#axoJt7bNQ1Kw_K0#*c%9tpRd3A1`&d^w|HN6Pntx+M0m?X_oEhb z>#xI_Hh`F`D4y-?^!O6A)8SvM`oKrI9-gt@(f5bGP;`rk7S8>R#}7k*K>x8|<|Z8y zr7s}-^sA>XyH0F6`uFTTxt~?&|80I?gR1wYeSaP4ie^&q{T^jzl!F{`{V^jPH{Tq^?z=b%b5gm>KmWm(E^@fuQiD#|@2u@j zB!^is6ybIr+2%#FAws~s%gh=DA7;&0xt9-Eb&pDRRN$BI=5NlS9-GQSTYZ0*v$AjA z5)fFvD-<$+glnCy2isS(R*D?n90ab!QdqXYBXtB<`{9yLBTI^K;CrWC+KocI9q?P9 zPR5i`IE!#Va~$5Rlo}c6%sIC*f=j=|_1(lqa^0AH`{f6Dzu%XP(#VdCA31n)9?E{4 znKx@cpgFe+0sbAg0q&)MtK*=3ytR2a);w@i)!G<0!tuhhkuC}6`kFAtWFgu^X*&x$ zrz2@wV;@-8FW=Vd5IX!(Xp7b&=0szNZWE)wM*4ajKt>HSm%n}0Y6Ro9Pi}|_-((+^ zH1Z><&C3)W)k+|d`$QbY*3f#DoW7?16N|mNyx#2UgNAyENi#k@2#pi6zacL&MU$boy&EK4F&M&UZ`iJ4TUv1 zCc^v#4>x$_v0kZ+eSeFt5WA_RX|~wt{7C+5AB)=N&8ny;1m1Q&`TI6F{T0sY*?FTx za`Qcv_!32N2K}H}g}DgiyYF_LZgu1Az4VPNmA;^SE}br+h3bu^NOj)3lL44dw}@#K zt>-ATikjY1u0#dQ!GW3hLH)sH#?uoL9iEX28jG~8Oo1%>AxYp+9`+km)o%PvEM%Zi z+^@3Ry6IZb)!}UVAxoyhjSA)_W;SE$Fkd`MUb0MXuB9jHtpjj8AF zq&3=y?*uE%(gbirvMsZkT)hO%cuCtgvU-F5>7tg_W6yG~Ft$575g82==)Q%SF1|6~ zYqj(H0> zdT4#bu`G{r$XTH$QVjxJ`)(-BBC7_L5A+8sVfZtT{UVoc#;?*35;%*i`t#YaMvqRY z<(oc{-kPe7ckJ4E%~6g4*fs?$GG?OW6DigacK> z?xTeUgXvy;nO^+SSBMe-{B>Agn(V*5xj{YJiyl{V92r}x0 zc*wGY#^PC&|GtpSp*`_{K`j zI#v1-MA!8MK6|2&lWlA|N5E_Ekpx@;@vEy%7O%j`qq(=s;l3-Q|2HaP>p;su&DTBsP(6Nn&0&Y;_B% zh@?!#Ro6;mR`+Ll2AE`JKTUXyNxe!?n(KvRJcjoR*0Y+q^)WJK!9g$)8iU>)xoU^54lrEY8J)U`a{>~jm5 zA%1i(Nv0DZopflyDzVB-zMM>%@aVK%WtG zvk?|jJgeRd;=HoAS?HT&hK2E{#{-$Dzkcnnee?ASZ$vM?^BPtG^N`M*m06#*xZt1x zI{6$NyisJGIJ9~StPd{xDvQeoauHi-E18iO3ihKOQE`_)77FU;ci0ATjRz4@Q0RoB z(&L;RLm761sMIC%RMaokhak3AamD7dr3X9s2m=~d4fKP9x@Ixbefk34o~1~%y=M!1 z%Q{jBL0MXTuj(h@{1Ix{Q<&!DDqYd*t-QphXK4keA6#E|IS1TRYs9|6CT4Y`4yulg z`@23{Z`bs^g{b(LHC24y_z3vdGN624Q1Z+A^Exp%a&swzb`*(*l*E@%QXi6Bt0^bT zqhxYr!djmDNr$9>wQ4cf zPfgJ;sn-rukk-Ly*!co|y2!WNqqV;5?Vg^S{Uf1POqOK{UwbzO>WvR29Z8BnWEtA~ zeOiLI&w#b#f|cuL<2k_%;e9$9^Z25LH4x}Vgwt?N>p_>e;|OfQNJQzd4Lh-8s|M@O z&w>D|OPj32Kv4g0(r2{lgsyyk#u`XC)mUd6nUUq--SFHl?CW2e4<)`!>)38-ni39Z zu%Sjwu1u(6AY#7f`<0FH62Jp@F?S%T!mv@3a<2FnlpMbsFUD}I+20~Uf;(3#HPjks z;pTv=v$0xs=g%1Q@$x6-ky&qr0?L>l*7abz4Qyx!3iHv<6oa0CxYzjVA=I*t5Du)f zdspDN$dcP0#+J|UkJTvyh^9`6vi*&q%C6arx0MdCCLVUreig>|>@dUo%hJOKMHf%F z;Bs=-<%4W@6zeajYn;VsR2-LlIVuqZAMM)zg0V(a-3k~+iQvb`ZaQxt&Yj!YjLqW! z)dbP)x{@lEgWPHZWihwX*j=p}rt@5fsgk=p>1Kb*ew0H^h&%gG=?{$QC(R04T|Lp0 znmZ3u!nh4YzY(2qk=Gx5!T3lrx&EW=ZksjHsMR=O-rrgtmF4dr_(jaEp<38s#J^iX zn5TCYVb&bb9jvPP9CTPYNLzTraHuW1<=rjS9UgrZvQU)&M;QOGe@=vVwHrbSb8sj+ z>(4g*zf#|d=FjJ6F22_%;e%aUJw=Tt zCoa0LGyE}&im{J|6pbG%bW`G}t8uz3CPB{_masfjh(p9j%i83@=rptpMPw)yU(jj@ zltt_>0=?r)q+NQacYX(ecthO>6-C%Cgbn)kwYQ-P9j9J0XPau%vp>mb0~y-XeZo4_ zEsEH8V6F<-FR>HWj%P8qq}Vn*k1=Q`1sJO=Eq2uF2o$`LaK(YS-U1NrXIu3vCi2$7 zX2nNm7dwx%wzUmB8+cqr7$}`kyT36(EBJvB#SxSoLbMnxRchW zA|gE1Y~xA}DI_sl3|za9fgdDM3Yzq5Hb2=0M$HOJ4xI1z*E}!812+O9SO|T)d@bZm zbccHicOuCae=@&3ww|aL8WyI8Y4(JRMm9K|ZWSD;$Hab0k9D$3aynW-e5+gg*LQpb zD8DA#`efZnOnIIg$xvSO4Nw{G*&7^5UiV(SNDDi@$XTx-Cnx;w31ml0_8)^dRQyDE+9uR_$ zXzS?ULHY7oZ?8mSXQ#pOu{-csXg{gN<>8cfp2QE&pA1)58wxqvpu`(fFYzO%IH2dx z0paED34IKo`jodaEg9~=tj6wb+=yCA2aXmwsmT~S3{QBmgHIrVerxMyU&|Ca?melDJF Y$p7aBVVLAkY}*;@o9UHYx^?gW0)wM_*#H0l literal 0 HcmV?d00001 diff --git a/docs/pictures/SDautoClean.png b/docs/pictures/SDautoClean.png new file mode 100644 index 0000000000000000000000000000000000000000..d1ed7b5df9c38679aa8da1384fa0e7f460f679b2 GIT binary patch literal 21415 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%0D9gmg+L?-slDP(3oEvjfM9kxvl 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 prmU=^tZbN-aq(YG@Iu_U Date: Wed, 25 Mar 2020 01:13:39 +0800 Subject: [PATCH 108/415] Fix subheading in DG --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index d2da2e019..e9b51e2cd 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,6 +1,6 @@ # Developer Guide -##1. Setting Up +## 1. Setting Up * Prerequisites * JDK 11 or above * IntelliJ IDE From 7b2407f536908ad5cd0afe1a471fec55b75bc7b1 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Wed, 25 Mar 2020 02:05:12 +0800 Subject: [PATCH 109/415] Update DG with edit feature --- docs/DeveloperGuide.md | 27 +++++++++++++++++++++++++- docs/pictures/ClassDiagram.png | Bin 0 -> 110951 bytes docs/pictures/EditSequenceDiagram.png | Bin 0 -> 37085 bytes 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 docs/pictures/ClassDiagram.png create mode 100644 docs/pictures/EditSequenceDiagram.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index e9b51e2cd..1a23b74f9 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -19,10 +19,12 @@ * Run the tests and ensure they all pass. ## 2. Design +![image_info](./pictures/ClassDiagram.png) +_Fig 2.1. Class diagram of the Jikan program_ ## 3. Implementation -{Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} +This section describes some noteworthy details on how certain features are implemented. ### 3.1 Automated Storage Cleanup feature @@ -103,6 +105,29 @@ The StorageHandler class functions as a support to the main Storage class, allow - Removing an entry from the data file via `removeLine`. This function takes in the number of the line to remove. - Replacing an entry in the data file via `replaceLine`. This function takes in the number of the line to replace, along with the String object that needs to be written to the data file in place of the replaced line. +### 3.5 Edit feature +The edit feature allows the user to make changes to activities that have been saved in the activity list. This is to allow the user to rectify any mistakes that may have been made during the initial recording of the activity. + +#### 3.5.1 Current Implementation +The following sequence diagram shows how the edit feature works. +![image_info](./pictures/EditSequenceDiagram.png) +The current implementation of the edit feature allows the user to edit only the name parameter of the activity. When the user wants to edit an activity using the edit command, the Parser creates a new EditCommand object. The executeCommand() method of the EditCommand object is called and the specified parameters are updated accordingly. + +The order of method calls to edit the activity details is as follows if the specified activity exists (meaning index != -1) else an exception is thrown: +1. The updateName() method of the ActivityList class is called, with the user-specified parameters of the activity index and new activity name +2. The get() method is self-invoked by the ActivityList class to obtain the activity at the given index +3. The setName() method of the Activity class is called to edit the activity name to the user-specified name +4. The activity with the updated name is returned to the activityList + +#### 3.5.2 Additional Implementations +The current implementation of the edit feature only allows the user to edit the activity name. Hence, additional implementations of the edit feature should allow the user to edit other parameters of the activity such as the tags and the start and end dates. + +This will require the implementation of more update methods in the ActivityList class to allow for the changes to be updated in the activityList after it has been edited. + +#### 3.5.3 Design Considerations +By letting the user edit the name and tags of the activity, it will allow them to correct any mistakes made during the data entry. This ensures that there is an accurate record of activities such as in cases where the user may be trying to record the same activity but has misspelled it, resulting in the program regarding it as a different activity where there would be multiple unnecessary new entries in the activity list, making the analysis of the time spent more tedious and inaccurate. + +However, by allowing the user to edit the start date and time, there may be potential inaccuracies in the actual activity recording. This is due to the fact that the time recorded in the program is based on the LocalDateTime. By introducing user input, the dates and time may be recorded incorrectly, defeating the purpose of the time tracking program. ## 4. Appendix ### Product Scope diff --git a/docs/pictures/ClassDiagram.png b/docs/pictures/ClassDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..ff6d64917b8b7bf3e08f2ffa8fcdb42c310707ca GIT binary patch literal 110951 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

#vU+*l0 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 IXur+;e>k0RBLDyZ literal 0 HcmV?d00001 diff --git a/docs/pictures/EditSequenceDiagram.png b/docs/pictures/EditSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..d3c9b64b7b68cf122dd5876f2e92b0ce3b8ca339 GIT binary patch literal 37085 zcmeFZcT`hL*EoDA0xBR_C?ds*N(Yr*>>aTJ(l1SVD4{1rQMgwGR1}b|h^RnNASCn% zVw5UU0t6C@)DS`u0tCW033^}e^FHtT%KOi^e(O1ZWSw(nX74?F@7ZnUJ+8&?_vYR6zA~^w`&y2b)k1X?(;qp=&_vF+Fq_hSnev&TrMoD?CH5l>CWjL#yD@s zOkrBf=YKfO*0s-`;)fu`i1zmOq5Y=Z5M+C-aV|SP$%0DamT$MBW(qh*Z-t=5Fa-q# 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 literal 0 HcmV?d00001 From c65a37175d96af968dd797d77fdbf61c8cd646c0 Mon Sep 17 00:00:00 2001 From: btricec Date: Wed, 25 Mar 2020 02:05:33 +0800 Subject: [PATCH 110/415] Add continue feature in implementation --- docs/DeveloperGuide.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index e9b51e2cd..b0f8932ce 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -103,6 +103,46 @@ The StorageHandler class functions as a support to the main Storage class, allow - Removing an entry from the data file via `removeLine`. This function takes in the number of the line to remove. - Replacing an entry in the data file via `replaceLine`. This function takes in the number of the line to replace, along with the String object that needs to be written to the data file in place of the replaced line. +### 3.5 Continue Feature +The continue feature allows the user to continue a previously ended activity. + +#### 3.5.1 Current Implementation +![Continue command sequence diagram](https://i.imgur.com/MuaxFts.png) + +**Continuing an activity:** +When the user enters the command to continue an activity, a *ContinueCommand* object is created in *Parser*. The method *executeCommand()* of the *ContinueCommand* object is then called and does the following: + + 1. Checks if the given activity name exists in the activityList by calling *findActivity()* (if it doesn’t an exception is thrown, omitted in the sequence diagram above) + 2. Gets the *name* and *tags* of the activity to be continued and saves it to a public static variable of *Parser* object + 3. Gets the current time and saves it to a public static variable of *Parser* object + + **Ending a continued activity:** + ![End command sequence diagram](https://i.imgur.com/soaCCXk.png) + +When the user wants to end the continued activity, an *EndCommand* object is created in *Parser.* The method *executeCommand()* of the *ContinueCommand* object is then called and it in turn executes the *saveActivity()* method of the *ActivityList* class. The continued activity is then saved by executing the following: + + 1. Gets the current time and saves it to a public static variable of *Parser* object +2. Calculates the elapsed time using *between()* method of *Duration* class +3. Adds the elapsed time with the previous duration of the activity to get the *newDuration* using *plus()* method of Duration class +4. Calls the *updateDuration()* method, which updates the *duration* attribute of the continued activity in the *activityList* as well as the data.csv file + +#### 3.5.2 Design Considerations + +**Execution:** + - Continue by activity name (current implementation) + **Cons:** Activity names have to be unique. + **Pros:** More versatile, resistant to changes in the activity list + - Continue by activity index + **Cons:** need to add an additional index field to the Activity class, + index is not fixed, changes when an activity is deleted + **Pros:** Can reuse activity names. + +Although the current implementation of the continue feature disallows users to have multiple activities with the same name, we felt that the versatility of this choice outweighed the cons. Firstly because if the activityList got too big, it would be hard for the user to get the index of the task he/she wanted to continue. Also, the index would constantly be changing when changes are made to the list. + +#### 3.5.3 Additional Features +As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, he/she will be given the option to continue the stated activity. +![decision flowchart](https://i.imgur.com/mCCPuun.png) + ## 4. Appendix ### Product Scope From 9bf34374b11d7d80177ab90e9f85ba8443753c05 Mon Sep 17 00:00:00 2001 From: btricec Date: Wed, 25 Mar 2020 03:19:30 +0800 Subject: [PATCH 111/415] Refactor commands --- src/main/java/jikan/Log.java | 2 +- .../java/jikan/activity/ActivityList.java | 25 +- src/main/java/jikan/command/AbortCommand.java | 12 +- src/main/java/jikan/command/ByeCommand.java | 20 +- src/main/java/jikan/command/CleanCommand.java | 3 +- src/main/java/jikan/command/Command.java | 4 +- .../java/jikan/command/ContinueCommand.java | 20 +- .../java/jikan/command/DeleteCommand.java | 12 +- src/main/java/jikan/command/EditCommand.java | 19 +- src/main/java/jikan/command/EndCommand.java | 11 +- .../java/jikan/command/FilterCommand.java | 30 ++- src/main/java/jikan/command/FindCommand.java | 22 +- src/main/java/jikan/command/ListCommand.java | 7 +- src/main/java/jikan/command/StartCommand.java | 73 +++++- src/main/java/jikan/parser/Parser.java | 244 +++--------------- src/test/java/jikan/parser/ExceptionTest.java | 16 +- src/test/java/jikan/parser/ParserTest.java | 37 --- 17 files changed, 279 insertions(+), 278 deletions(-) delete mode 100644 src/test/java/jikan/parser/ParserTest.java diff --git a/src/main/java/jikan/Log.java b/src/main/java/jikan/Log.java index dee90be03..9b5a6f2f7 100644 --- a/src/main/java/jikan/Log.java +++ b/src/main/java/jikan/Log.java @@ -58,7 +58,7 @@ public Log() { * Creates a long entry at FINE level. * @param message the FINE message to be logged */ - public void makeFineLog(String message) { + public static void makeFineLog(String message) { logger.log(Level.FINE, message); } diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 60d959575..4bcab1a85 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -1,8 +1,10 @@ package jikan.activity; import jikan.exception.InvalidTimeFrameException; +import jikan.parser.Parser; import jikan.storage.Storage; import jikan.storage.StorageHandler; +import jikan.ui.Ui; import java.io.IOException; import java.time.Duration; @@ -114,7 +116,7 @@ private void fieldChangeUpdateFile() { try { StorageHandler.updateField(activities, storage); } catch (IOException e) { - System.out.println("Error while deleting activity from data file."); + System.out.println("Error while updating activity from data file."); } } @@ -122,6 +124,27 @@ public int getSize() { return activities.size(); } + public void saveActivity(ActivityList activityList) throws InvalidTimeFrameException { + if (Parser.continuedIndex != -1) { + Ui.printDivider("Ended: " + Parser.activityName); + Parser.endTime = LocalDateTime.now(); + Duration duration = Duration.between(Parser.startTime, Parser.endTime); + Duration oldDuration = activityList.get(Parser.continuedIndex).getDuration(); + Duration newDuration = duration.plus(oldDuration); + activityList.updateDuration(newDuration, Parser.endTime, Parser.continuedIndex); + Parser.continuedIndex = -1; + Parser.resetInfo(); + } else { + Ui.printDivider("Ended: " + Parser.activityName); + Parser.endTime = LocalDateTime.now(); + Duration duration = Duration.between(Parser.startTime, Parser.endTime); + Activity newActivity = new Activity(Parser.activityName, Parser.startTime, Parser.endTime, duration, Parser.tags); + activityList.add(newActivity); + // reset activity info + Parser.resetInfo(); + } + } + /** * Populates task list from file. diff --git a/src/main/java/jikan/command/AbortCommand.java b/src/main/java/jikan/command/AbortCommand.java index fb9bcb7ee..78f249ef3 100644 --- a/src/main/java/jikan/command/AbortCommand.java +++ b/src/main/java/jikan/command/AbortCommand.java @@ -15,13 +15,21 @@ public class AbortCommand extends Command { /** * Constructor to create a new abort command. */ - public AbortCommand() { + public AbortCommand(String parameters) { + super(parameters); } @Override public void executeCommand(ActivityList activityList) { try { - Parser.parseAbort(); + // Parser.parseAbort(); + if (Parser.startTime == null) { + throw new NoSuchActivityException(); + } else { + Parser.resetInfo(); + String line = "You have aborted the current activity!"; + Ui.printDivider(line); + } } catch (NoSuchActivityException e) { Ui.printDivider("You have not started any activity!"); Log.makeInfoLog("Abort command failed as no activity was ongoing"); diff --git a/src/main/java/jikan/command/ByeCommand.java b/src/main/java/jikan/command/ByeCommand.java index 27d60d00c..103616d72 100644 --- a/src/main/java/jikan/command/ByeCommand.java +++ b/src/main/java/jikan/command/ByeCommand.java @@ -21,14 +21,30 @@ public class ByeCommand extends Command { /** * Constructor to create a new exit command. */ - public ByeCommand() { + public ByeCommand(String parameters) { + super(parameters); } + /** + * Checks for ongoing activities and ask if user wants to save them + * before exiting the app. + */ @Override public void executeCommand(ActivityList activityList) { try { - Parser.parseBye(activityList, Jikan.in); + //Parser.parseBye(activityList, Jikan.in); + if (Parser.startTime != null) { + String line = Parser.activityName + " is still running! If you exit now it will be aborted.\n" + + "Would you like to end this activity to save it?"; + Ui.printDivider(line); + Scanner scanner = new Scanner(System.in); + String userInput = scanner.nextLine(); + if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { + activityList.saveActivity(activityList); + } + } + Ui.exitFromApp(); } catch (InvalidTimeFrameException e) { Log.makeInfoLog("End date must be before start date"); Ui.printDivider("End date must be before start date."); diff --git a/src/main/java/jikan/command/CleanCommand.java b/src/main/java/jikan/command/CleanCommand.java index 08df1378c..4537df686 100644 --- a/src/main/java/jikan/command/CleanCommand.java +++ b/src/main/java/jikan/command/CleanCommand.java @@ -16,7 +16,8 @@ public class CleanCommand extends Command { /** * Constructor to create a new clean command. */ - public CleanCommand() { + public CleanCommand(String parameters) { + super(parameters); } @Override diff --git a/src/main/java/jikan/command/Command.java b/src/main/java/jikan/command/Command.java index 4cfa6398b..5f8d9dfc0 100644 --- a/src/main/java/jikan/command/Command.java +++ b/src/main/java/jikan/command/Command.java @@ -7,11 +7,13 @@ * Represents an executable command. */ public class Command { + protected String parameters; /** * Constructor to create a new command. */ - public Command() { + public Command(String parameters) { + this.parameters = parameters; } /** diff --git a/src/main/java/jikan/command/ContinueCommand.java b/src/main/java/jikan/command/ContinueCommand.java index e0ff411a9..70a80d036 100644 --- a/src/main/java/jikan/command/ContinueCommand.java +++ b/src/main/java/jikan/command/ContinueCommand.java @@ -1,11 +1,14 @@ package jikan.command; import jikan.Log; +import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.exception.NoSuchActivityException; import jikan.parser.Parser; import jikan.ui.Ui; +import java.time.LocalDateTime; + /** * Represents a command to continue recording an existing activity. */ @@ -14,13 +17,26 @@ public class ContinueCommand extends Command { /** * Constructor to create a new continue command. */ - public ContinueCommand() { + public ContinueCommand(String parameters) { + super(parameters); } @Override public void executeCommand(ActivityList activityList) { try { - Parser.parseContinue(activityList); + //Parser.parseContinue(activityList); + int index = activityList.findActivity(parameters); + if (index != -1) { + // activity is found + Parser.activityName = activityList.get(index).getName(); + Parser.startTime = LocalDateTime.now(); + Parser.tags = activityList.get(index).getTags(); + Parser.continuedIndex = index; + String line = Parser.activityName + " was continued"; + Ui.printDivider(line); + } else { + throw new NoSuchActivityException(); + } } catch (NoSuchActivityException e) { Ui.printDivider("No activity with this name exists!"); Log.makeInfoLog("Continue command failed as there was no such activity saved."); diff --git a/src/main/java/jikan/command/DeleteCommand.java b/src/main/java/jikan/command/DeleteCommand.java index 1704ed6fe..cdf3e0e89 100644 --- a/src/main/java/jikan/command/DeleteCommand.java +++ b/src/main/java/jikan/command/DeleteCommand.java @@ -13,13 +13,21 @@ public class DeleteCommand extends Command { /** * Constructor to create a new delete command. */ - public DeleteCommand() { + public DeleteCommand(String parameters) { + super(parameters); } @Override public void executeCommand(ActivityList activityList) { try { - Parser.parseDelete(activityList); + int index = activityList.findActivity(parameters); + if (index != -1) { + // activity was found + Ui.printDivider("You have deleted " + parameters); + activityList.delete(index); + } else { + throw new NoSuchActivityException(); + } } catch (NoSuchActivityException e) { Ui.printDivider("No activity with this name exists!"); } diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index 924d61213..bfc8d9823 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -15,13 +15,28 @@ public class EditCommand extends Command { /** * Constructor to create a new edit command. */ - public EditCommand() { + public EditCommand(String parameters) { + super(parameters); } @Override public void executeCommand(ActivityList activityList) { try { - Parser.parseEdit(activityList); + // Parser.parseEdit(activityList); + int delimiter = parameters.indexOf("/e"); + Parser.activityName = parameters.substring(0, delimiter).strip(); + if ( Parser.activityName.isEmpty()) { + throw new EmptyNameException(); + } + int index = activityList.findActivity( Parser.activityName); + String newName = parameters.substring(delimiter + 3); + if (index != -1) { + activityList.updateName(index,newName); + Ui.printDivider("Activity named " + Parser.activityName + " has been updated to " + newName); + } else { + // activity is not found + throw new NoSuchActivityException(); + } } catch (NoSuchActivityException e) { Ui.printDivider("No activity with this name exists!"); Log.makeInfoLog("Edit command failed as there was no such activity saved."); diff --git a/src/main/java/jikan/command/EndCommand.java b/src/main/java/jikan/command/EndCommand.java index 3ab6660b9..725c2422d 100644 --- a/src/main/java/jikan/command/EndCommand.java +++ b/src/main/java/jikan/command/EndCommand.java @@ -20,13 +20,20 @@ public class EndCommand extends Command { /** * Constructor to create a new end command. */ - public EndCommand() { + public EndCommand(String parameters) { + super(parameters); } + /** Method to parse the end activity command. */ @Override public void executeCommand(ActivityList activityList) { try { - Parser.parseEnd(activityList); + // Parser.parseEnd(activityList); + if (Parser.startTime == null) { + throw new NoSuchActivityException(); + } else { + activityList.saveActivity(activityList); + } } catch (NoSuchActivityException e) { Log.makeInfoLog("End command failed as no activity was ongoing"); Ui.printDivider("You have not started any activity!"); diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index ac081c3ac..570f13216 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -1,5 +1,6 @@ package jikan.command; +import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.exception.EmptyQueryException; import jikan.parser.Parser; @@ -16,15 +17,40 @@ public class FilterCommand extends Command { /** * Constructor to create a new filter command. */ - public FilterCommand() { + public FilterCommand(String parameters) { + super(parameters); } + /** + * Shows the user all past activities that has tags which match the keywords queried by the user. + * @param activityList the activity list to search for matching activities + */ @Override public void executeCommand(ActivityList activityList) { try { - Parser.parseFilter(activityList, lastShownList, tokenizedInputs[1]); + // Parser.parseFilter(activityList, lastShownList, tokenizedInputs[1]); + String query = parameters; + if (query.length() < 1) { + throw new EmptyQueryException(); + } else { + lastShownList.activities.clear(); + String[] keywords = query.split(" "); + + for (String keyword : keywords) { + populateLastShownList(activityList, lastShownList, keyword); + } + Ui.printResults(lastShownList); + } } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { Ui.printDivider("No keyword was given."); } } + + private void populateLastShownList(ActivityList activityList, ActivityList lastShownList, String keyword) { + for (Activity i : activityList.activities) { + if (!lastShownList.activities.contains(i) && i.getTags().contains(keyword)) { + lastShownList.activities.add(i); + } + } + } } diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index b01ef5261..ff2fbb18b 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -1,5 +1,6 @@ package jikan.command; +import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.exception.EmptyQueryException; import jikan.parser.Parser; @@ -16,13 +17,30 @@ public class FindCommand extends Command { /** * Constructor to create a new find command. */ - public FindCommand() { + public FindCommand(String parameters) { + super(parameters); } + /** + * Shows the user all past activities that has names which match the keyword queried by the user. + * @param activityList the activity list to search for matching activities + */ @Override public void executeCommand(ActivityList activityList) { try { - Parser.parseFind(activityList, lastShownList, tokenizedInputs[1]); + // Parser.parseFind(activityList, lastShownList, tokenizedInputs[1]); + String keyword = parameters; + if (keyword.length() < 1) { + throw new EmptyQueryException(); + } else { + lastShownList.activities.clear(); + for (Activity i : activityList.activities) { + if (i.getName().contains(keyword)) { + lastShownList.activities.add(i); + } + } + Ui.printResults(lastShownList); + } } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { Ui.printDivider("No keyword was given."); } diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index 6e1710611..8f53f8302 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -1,11 +1,15 @@ package jikan.command; import jikan.Log; +import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.ui.Ui; import jikan.parser.Parser; import jikan.exception.InvalidTimeFrameException; + +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; /** @@ -16,7 +20,8 @@ public class ListCommand extends Command { /** * Constructor to create a new list command. */ - public ListCommand() { + public ListCommand(String parameters) { + super(parameters); } @Override diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index dc7c1ac4e..22dcb6085 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -7,6 +7,8 @@ import jikan.parser.Parser; import jikan.ui.Ui; +import java.time.LocalDateTime; +import java.util.Arrays; import java.util.Scanner; /** @@ -14,22 +16,87 @@ */ public class StartCommand extends Command { - //private Scanner scanner = new Scanner(System.in); + private Scanner scanner; /** * Constructor to create a new start command. */ - public StartCommand() { + public StartCommand(String parameters, Scanner scanner) { + super(parameters); + this.scanner = scanner; } @Override public void executeCommand(ActivityList activityList) { try { - Parser.parseStart(activityList, Jikan.in); + // Parser.parseStart(activityList, Jikan.in); + // check if an activity has already been started + if (Parser.startTime != null) { + String line = Parser.activityName + " is ongoing!"; + Log.makeInfoLog("Could not start activity due to already ongoing activity."); + Ui.printDivider(line); + } else { + // tags should be reset + assert Parser.tags.isEmpty(); + + // check if there exists an activity with this name + int index = activityList.findActivity(parameters); + if (index != -1) { + Ui.printDivider("There is already an activity with this name. Would you like to continue it?"); + continueActivity(activityList, scanner, index); + } else { + int delimiter = parameters.indexOf("/t"); + String line = parseActivity(delimiter); + Parser.startTime = LocalDateTime.now(); + Log.makeFineLog("Started: " + Parser.activityName); + Ui.printDivider(line); + } + } } catch (EmptyNameException | NullPointerException | ArrayIndexOutOfBoundsException e) { Log.makeInfoLog("Activity started without activity name"); Ui.printDivider("Activity name cannot be empty!"); } } + /** + * Received user input on whether or not to continue the activity. + * + * @param activityList List of activities. + * @param scanner Parse user input. + */ + private static void continueActivity(ActivityList activityList, Scanner scanner, int index) { + String userInput = scanner.nextLine(); + if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { + Parser.activityName = activityList.get(index).getName(); + Parser.startTime = LocalDateTime.now(); + Parser.tags = activityList.get(index).getTags(); + Parser.continuedIndex = index; + Ui.printDivider(Parser.activityName + " was continued"); + Log.makeFineLog(Parser.activityName + " was continued."); + } else { + Ui.printDivider("Okay then, what else can I do for you?"); + } + } + /** + * Parses the started activity for name and tags. + * + * @param delimiter The index of the tag delimiter. + */ + private String parseActivity(int delimiter) throws EmptyNameException { + if (delimiter == -1) { + // no tags + Parser.activityName = this.parameters.strip(); + if (Parser.activityName.isEmpty()) { + throw new EmptyNameException(); + } + } else { + Parser.activityName = this.parameters.substring(0, delimiter).strip(); + if (Parser.activityName.isEmpty()) { + throw new EmptyNameException(); + } + String[] tagString = this.parameters.substring(delimiter + 3).split(" "); + Parser.tags.addAll(Arrays.asList(tagString)); + } + return "Started: " + Parser.activityName; + } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index c770997fd..a2f51425f 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -39,15 +39,16 @@ */ public class Parser { - protected static LocalDateTime startTime = null; - protected static LocalDateTime endTime = null; - private static String activityName = null; - private static Set tags = new HashSet<>(); + public static LocalDateTime startTime = null; + public static LocalDateTime endTime = null; + public static String activityName = null; + public static Set tags = new HashSet<>(); private static Ui ui = new Ui(); private static StorageCleaner cleaner; public static String[] tokenizedInputs; String instruction; private static Log logger = new Log(); + // public static ActivityList lastShownList = new ActivityList(); public static ActivityList lastShownList = new ActivityList(); // flag to check if the current activity is a continued one public static int continuedIndex = -1; @@ -58,8 +59,8 @@ public class Parser { * @param activityList the list of activities */ public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) { - logger.makeInfoLog("Starting to parse inputs."); - this.cleaner = cleaner; + Log.makeInfoLog("Starting to parse inputs."); + Parser.cleaner = cleaner; /*lastShownList is initialised here to facilitate subsequent delete and edit commands referencing by index of this list. */ @@ -71,37 +72,37 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto switch (instruction) { case "bye": - command = new ByeCommand(); - break; + command = new ByeCommand(null); + break; case "start": - command = new StartCommand(); + command = new StartCommand(tokenizedInputs[1], scanner); break; case "end": - command = new EndCommand(); + command = new EndCommand(null); break; case "abort": - command = new AbortCommand(); + command = new AbortCommand(null); break; case "list": - command = new ListCommand(); + command = new ListCommand(null); break; case "delete": - command = new DeleteCommand(); + command = new DeleteCommand(tokenizedInputs[1]); break; case "find": - command = new FindCommand(); + command = new FindCommand(tokenizedInputs[1]); break; case "filter": - command = new FilterCommand(); + command = new FilterCommand(tokenizedInputs[1]); break; case "edit": - command = new EditCommand(); + command = new EditCommand(tokenizedInputs[1]); break; case "clean": - command = new CleanCommand(); + command = new CleanCommand(tokenizedInputs[1]); break; case "continue": - command = new ContinueCommand(); + command = new ContinueCommand(tokenizedInputs[1]); break; default: parseDefault(); @@ -121,38 +122,16 @@ public static void parseClean(String tokenizedInput) throws IOException { cleaner.setStatus(true); assert cleaner.toClean; line = "Auto cleaning enabled"; - logger.makeInfoLog("User has turned on automated cleaning"); + Log.makeInfoLog("User has turned on automated cleaning"); } else if (tokenizedInput.equals("off")) { cleaner.setStatus(false); assert !cleaner.toClean; line = "Auto cleaning disabled"; - logger.makeInfoLog("User has turned off automated cleaning"); + Log.makeInfoLog("User has turned off automated cleaning"); } else { line = "Invalid Command!"; } - ui.printDivider(line); - } - - /** - * Checks for ongoing activities and ask if user wants to save them - * before exiting the app. - * - * @param activityList List of activities. - * @param scanner To parse user input. - * @throws InvalidTimeFrameException precautionary measure for if endTime is greater than startTime. - */ - public static void parseBye(ActivityList activityList, Scanner scanner) throws InvalidTimeFrameException { - if (startTime != null) { - String line = activityName + " is still running! If you exit now it will be aborted.\n" - + "Would you like to end this activity to save it?"; - ui.printDivider(line); - String userInput = scanner.nextLine(); - if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { - saveActivity(activityList); - logger.makeInfoLog("Activity " + activityName + " was saved before app terminated."); - } - } - ui.exitFromApp(); + Ui.printDivider(line); } /** @@ -166,8 +145,8 @@ public static void parseStart(ActivityList activityList, Scanner scanner) // check if an activity has already been started if (startTime != null) { String line = activityName + " is ongoing!"; - logger.makeInfoLog("Could not start activity due to already ongoing activity."); - ui.printDivider(line); + Log.makeInfoLog("Could not start activity due to already ongoing activity."); + Ui.printDivider(line); } else { // tags should be reset assert tags.isEmpty(); @@ -175,14 +154,14 @@ public static void parseStart(ActivityList activityList, Scanner scanner) // check if there exists an activity with this name int index = activityList.findActivity(tokenizedInputs[1]); if (index != -1) { - ui.printDivider("There is already an activity with this name. Would you like to continue it?"); + Ui.printDivider("There is already an activity with this name. Would you like to continue it?"); continueActivity(activityList, scanner, index); } else { int delimiter = tokenizedInputs[1].indexOf("/t"); String line = parseActivity(delimiter); startTime = LocalDateTime.now(); - logger.makeFineLog("Started: " + activityName); - ui.printDivider(line); + Log.makeFineLog("Started: " + activityName); + Ui.printDivider(line); } } } @@ -200,10 +179,10 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, startTime = LocalDateTime.now(); tags = activityList.get(index).getTags(); continuedIndex = index; - ui.printDivider(activityName + " was continued"); - logger.makeFineLog(activityName + " was continued."); + Ui.printDivider(activityName + " was continued"); + Log.makeFineLog(activityName + " was continued."); } else { - ui.printDivider("Okay then, what else can I do for you?"); + Ui.printDivider("Okay then, what else can I do for you?"); } } @@ -230,17 +209,6 @@ private static String parseActivity(int delimiter) throws EmptyNameException { return "Started: " + activityName; } - /** Method to parse the end activity command. */ - public static void parseEnd(ActivityList activityList) throws NoSuchActivityException, InvalidTimeFrameException { - if (startTime == null) { - throw new NoSuchActivityException(); - } else { - saveActivity(activityList); - } - logger.makeFineLog("Ended: " + activityName); - } - - /** * Parse a list command. The user can specify either a single date or a specific time frame. * @@ -292,161 +260,15 @@ public static void parseList(ActivityList activityList) throws InvalidTimeFrameE } - /** Method to parse the abort command. */ - public static void parseAbort() throws NoSuchActivityException { - if (startTime == null) { - throw new NoSuchActivityException(); - } else { - logger.makeFineLog("Aborted " + activityName); - resetInfo(); - String line = "You have aborted the current activity!"; - ui.printDivider(line); - } - } - - /** Deletes an activity from the activity list. */ - public static void parseDelete(ActivityList activityList) throws NoSuchActivityException { - //int index = Integer.parseInt(tokenizedInputs[1]) - 1; - int index = activityList.findActivity(tokenizedInputs[1]); - if (index != -1) { - // activity was found - String line = "You have deleted " + tokenizedInputs[1]; - ui.printDivider(line); - activityList.delete(index); - } else { - throw new NoSuchActivityException(); - } - } - - /** - * Shows the user all past activities that has names which match the keyword queried by the user. - * @param activityList the activity list to search for matching activities - * @param lastShownList the activity list to populate with matching activities only - * @param keyword the keyword queried by the user - */ - public static void parseFind(ActivityList activityList, ActivityList lastShownList, String keyword) - throws EmptyQueryException { - if (keyword.length() < 1) { - throw new EmptyQueryException(); - } else { - lastShownList.activities.clear(); - for (Activity i : activityList.activities) { - if (i.getName().contains(keyword)) { - lastShownList.activities.add(i); - } - } - Ui.printResults(lastShownList); - } - } - - /** - * Shows the user all past activities that has tags which match the keywords queried by the user. - * @param activityList the activity list to search for matching activities - * @param lastShownList the activity list to populate with matching activities only - * @param query the keywords queried by the user - */ - public static void parseFilter(ActivityList activityList, ActivityList lastShownList, String query) - throws EmptyQueryException { - if (query.length() < 1) { - throw new EmptyQueryException(); - } else { - lastShownList.activities.clear(); - String[] keywords = query.split(" "); - - for (String keyword : keywords) { - populateLastShownList(activityList, lastShownList, keyword); - } - Ui.printResults(lastShownList); - } - } - - /** - * Continues an activity in the activityList. - * @param activityList To search for the activity and retrieve relevant details. - */ - public static void parseContinue(ActivityList activityList) throws NoSuchActivityException { - int index = activityList.findActivity(tokenizedInputs[1]); - if (index != -1) { - // activity is found - activityName = activityList.get(index).getName(); - startTime = LocalDateTime.now(); - tags = activityList.get(index).getTags(); - continuedIndex = index; - String line = activityName + " was continued"; - ui.printDivider(line); - logger.makeFineLog(activityName + " was continued."); - } else { - throw new NoSuchActivityException(); - } - } - - /** - * Edits the detail of an activity in the activityList. - * @param activityList the activity list containing the activity to edit. - */ - public static void parseEdit(ActivityList activityList) throws EmptyNameException, NoSuchActivityException { - int delimiter = tokenizedInputs[1].indexOf("/e"); - activityName = tokenizedInputs[1].substring(0, delimiter).strip(); - if (activityName.isEmpty()) { - throw new EmptyNameException(); - } - int index = activityList.findActivity(activityName); - String newName = tokenizedInputs[1].substring(delimiter + 3); - if (index != -1) { - activityList.updateName(index,newName); - ui.printDivider("Activity named " + activityName + " has been updated to " + newName); - } else { - // activity is not found - throw new NoSuchActivityException(); - } - logger.makeFineLog("Activity name has been updated!"); - } - /** Method to parse user inputs that are not recognised. */ private void parseDefault() { String line = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; - logger.makeInfoLog("Invalid command entered"); - ui.printDivider(line); + Log.makeInfoLog("Invalid command entered"); + Ui.printDivider(line); } - /** - * Populates the last shown list with activities that contain tags which match the given keyword. - * @param activityList the list of activity to search - * @param lastShownList the last shown list to populate - * @param keyword the keyword to match - */ - private static void populateLastShownList(ActivityList activityList, ActivityList lastShownList, String keyword) { - for (Activity i : activityList.activities) { - if (!lastShownList.activities.contains(i) && i.getTags().contains(keyword)) { - lastShownList.activities.add(i); - } - } - } - - private static void saveActivity(ActivityList activityList) throws InvalidTimeFrameException { - if (continuedIndex != -1) { - String line = "Ended: " + activityName; - ui.printDivider(line); - endTime = LocalDateTime.now(); - Duration duration = Duration.between(startTime, endTime); - Duration oldDuration = activityList.get(continuedIndex).getDuration(); - Duration newDuration = duration.plus(oldDuration); - activityList.updateDuration(newDuration, endTime, continuedIndex); - continuedIndex = -1; - resetInfo(); - } else { - String line = "Ended: " + activityName; - ui.printDivider(line); - endTime = LocalDateTime.now(); - Duration duration = Duration.between(startTime, endTime); - Activity newActivity = new Activity(activityName, startTime, endTime, duration, tags); - activityList.add(newActivity); - // reset activity info - resetInfo(); - } - } - private static void resetInfo() { + public static void resetInfo() { startTime = null; activityName = null; tags = new HashSet<>(); diff --git a/src/test/java/jikan/parser/ExceptionTest.java b/src/test/java/jikan/parser/ExceptionTest.java index f3fca4ee6..128bcdd00 100644 --- a/src/test/java/jikan/parser/ExceptionTest.java +++ b/src/test/java/jikan/parser/ExceptionTest.java @@ -1,6 +1,9 @@ package jikan.parser; import jikan.activity.ActivityList; +import jikan.command.AbortCommand; +import jikan.command.Command; +import jikan.command.EndCommand; import jikan.exception.EmptyNameException; import jikan.exception.NoSuchActivityException; import org.junit.jupiter.api.Assertions; @@ -10,24 +13,25 @@ class ExceptionTest { - Parser parser = new Parser(); Scanner scanner = new Scanner(System.in); ActivityList activityList = new ActivityList(); @Test public void testEmptyNameException() { Assertions.assertThrows(EmptyNameException.class, () -> { - parser.tokenizedInputs = new String[]{"start", ""}; - parser.parseStart(activityList, scanner); + Parser.tokenizedInputs = new String[]{"start", ""}; + Parser.parseStart(activityList, scanner); }); } @Test public void testNoSuchActivityException() { Assertions.assertThrows(NoSuchActivityException.class, () -> { - parser.startTime = null; - parser.parseEnd(activityList); - parser.parseAbort(); + Parser.startTime = null; + Command endCommand = new EndCommand(null); + endCommand.executeCommand(activityList); + Command abortCommand = new AbortCommand(null); + abortCommand.executeCommand(activityList); }); } diff --git a/src/test/java/jikan/parser/ParserTest.java b/src/test/java/jikan/parser/ParserTest.java deleted file mode 100644 index 07fc0dae2..000000000 --- a/src/test/java/jikan/parser/ParserTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package jikan.parser; - -import jikan.activity.ActivityList; -import jikan.exception.InvalidTimeFrameException; -import jikan.ui.Ui; -import jikan.exception.NoSuchActivityException; -import jikan.storage.Storage; -import org.junit.jupiter.api.Test; - -import java.time.LocalDateTime; - -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; - -class ParserTest { - - Parser parser = new Parser(); - Ui ui = new Ui(); - ActivityList activityList = new ActivityList(); - - @Test - void parseEnd() throws NoSuchActivityException, InvalidTimeFrameException { - try { - parser.startTime = null; - parser.parseEnd(activityList); - assertTrue(activityList.activities.isEmpty()); - parser.tokenizedInputs = new String[]{"start", "studying"}; - parser.startTime = LocalDateTime.parse("2020-01-01T08:00:00"); - activityList.storage = new Storage("data/Parser_test.txt"); - parser.parseEnd(activityList); - assertFalse(activityList.activities.isEmpty()); - } catch (NoSuchActivityException e) { - ui.printDivider("There is no such task!"); - } - - } -} \ No newline at end of file From 0d7d0385a80653a85324ed99290852eeb34b6383 Mon Sep 17 00:00:00 2001 From: btricec Date: Wed, 25 Mar 2020 03:34:51 +0800 Subject: [PATCH 112/415] Refactor clean command --- .../java/jikan/activity/ActivityList.java | 8 +- src/main/java/jikan/command/CleanCommand.java | 29 ++++- src/main/java/jikan/command/EditCommand.java | 4 +- src/main/java/jikan/command/StartCommand.java | 1 + src/main/java/jikan/parser/Parser.java | 105 +----------------- src/test/java/jikan/parser/ExceptionTest.java | 4 +- 6 files changed, 45 insertions(+), 106 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 4bcab1a85..fef82cf25 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -124,6 +124,11 @@ public int getSize() { return activities.size(); } + /** + * Saves a new activity to the list of activities. + * @param activityList list to save to + * @throws InvalidTimeFrameException if start time is before end time + */ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameException { if (Parser.continuedIndex != -1) { Ui.printDivider("Ended: " + Parser.activityName); @@ -138,7 +143,8 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep Ui.printDivider("Ended: " + Parser.activityName); Parser.endTime = LocalDateTime.now(); Duration duration = Duration.between(Parser.startTime, Parser.endTime); - Activity newActivity = new Activity(Parser.activityName, Parser.startTime, Parser.endTime, duration, Parser.tags); + Activity newActivity = new Activity(Parser.activityName, Parser.startTime, + Parser.endTime, duration, Parser.tags); activityList.add(newActivity); // reset activity info Parser.resetInfo(); diff --git a/src/main/java/jikan/command/CleanCommand.java b/src/main/java/jikan/command/CleanCommand.java index 4537df686..cabe055d3 100644 --- a/src/main/java/jikan/command/CleanCommand.java +++ b/src/main/java/jikan/command/CleanCommand.java @@ -1,7 +1,10 @@ package jikan.command; +import jikan.Log; import jikan.activity.ActivityList; import jikan.parser.Parser; +import jikan.storage.Storage; +import jikan.storage.StorageCleaner; import jikan.ui.Ui; import java.io.IOException; @@ -13,17 +16,39 @@ */ public class CleanCommand extends Command { + StorageCleaner cleaner; + /** * Constructor to create a new clean command. */ - public CleanCommand(String parameters) { + public CleanCommand(String parameters, StorageCleaner cleaner) { super(parameters); + + this.cleaner = cleaner; } + /** + * Method to enable or disable cleaning of log files. + */ @Override public void executeCommand(ActivityList activityList) { try { - Parser.parseClean(tokenizedInputs[1]); + String line; + if (parameters.equals("on")) { + cleaner.setStatus(true); + assert cleaner.toClean; + line = "Auto cleaning enabled"; + Log.makeInfoLog("User has turned on automated cleaning"); + } else if (parameters.equals("off")) { + cleaner.setStatus(false); + assert !cleaner.toClean; + line = "Auto cleaning disabled"; + Log.makeInfoLog("User has turned off automated cleaning"); + } else { + line = "Invalid Command!"; + } + Ui.printDivider(line); + // Parser.parseClean(tokenizedInputs[1]); } catch (ArrayIndexOutOfBoundsException | IOException e) { Ui.printDivider("No keyword was given."); } diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index bfc8d9823..c100a4f63 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -25,10 +25,10 @@ public void executeCommand(ActivityList activityList) { // Parser.parseEdit(activityList); int delimiter = parameters.indexOf("/e"); Parser.activityName = parameters.substring(0, delimiter).strip(); - if ( Parser.activityName.isEmpty()) { + if (Parser.activityName.isEmpty()) { throw new EmptyNameException(); } - int index = activityList.findActivity( Parser.activityName); + int index = activityList.findActivity(Parser.activityName); String newName = parameters.substring(delimiter + 3); if (index != -1) { activityList.updateName(index,newName); diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 22dcb6085..99d37884f 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -57,6 +57,7 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider("Activity name cannot be empty!"); } } + /** * Received user input on whether or not to continue the activity. * diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index a2f51425f..efe32f2bb 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -73,7 +73,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto switch (instruction) { case "bye": command = new ByeCommand(null); - break; + break; case "start": command = new StartCommand(tokenizedInputs[1], scanner); break; @@ -99,7 +99,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto command = new EditCommand(tokenizedInputs[1]); break; case "clean": - command = new CleanCommand(tokenizedInputs[1]); + command = new CleanCommand(tokenizedInputs[1], cleaner); break; case "continue": command = new ContinueCommand(tokenizedInputs[1]); @@ -111,104 +111,6 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto return command; } - /** - * Method to enable or disable cleaning of log files. - * @param tokenizedInput user input of 'on' or 'off' - * @throws IOException if input is incorrect. - */ - public static void parseClean(String tokenizedInput) throws IOException { - String line; - if (tokenizedInput.equals("on")) { - cleaner.setStatus(true); - assert cleaner.toClean; - line = "Auto cleaning enabled"; - Log.makeInfoLog("User has turned on automated cleaning"); - } else if (tokenizedInput.equals("off")) { - cleaner.setStatus(false); - assert !cleaner.toClean; - line = "Auto cleaning disabled"; - Log.makeInfoLog("User has turned off automated cleaning"); - } else { - line = "Invalid Command!"; - } - Ui.printDivider(line); - } - - /** - * Method to parse the start activity command. - * - * @param activityList List of activities. - * @param scanner To parse user input. - */ - public static void parseStart(ActivityList activityList, Scanner scanner) - throws ArrayIndexOutOfBoundsException, EmptyNameException, NullPointerException { - // check if an activity has already been started - if (startTime != null) { - String line = activityName + " is ongoing!"; - Log.makeInfoLog("Could not start activity due to already ongoing activity."); - Ui.printDivider(line); - } else { - // tags should be reset - assert tags.isEmpty(); - - // check if there exists an activity with this name - int index = activityList.findActivity(tokenizedInputs[1]); - if (index != -1) { - Ui.printDivider("There is already an activity with this name. Would you like to continue it?"); - continueActivity(activityList, scanner, index); - } else { - int delimiter = tokenizedInputs[1].indexOf("/t"); - String line = parseActivity(delimiter); - startTime = LocalDateTime.now(); - Log.makeFineLog("Started: " + activityName); - Ui.printDivider(line); - } - } - } - - /** - * Received user input on whether or not to continue the activity. - * - * @param activityList List of activities. - * @param scanner Parse user input. - */ - private static void continueActivity(ActivityList activityList, Scanner scanner, int index) { - String userInput = scanner.nextLine(); - if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { - activityName = activityList.get(index).getName(); - startTime = LocalDateTime.now(); - tags = activityList.get(index).getTags(); - continuedIndex = index; - Ui.printDivider(activityName + " was continued"); - Log.makeFineLog(activityName + " was continued."); - } else { - Ui.printDivider("Okay then, what else can I do for you?"); - } - } - - /** - * Parses the started activity for name and tags. - * - * @param delimiter The index of the tag delimiter. - */ - private static String parseActivity(int delimiter) throws EmptyNameException { - if (delimiter == -1) { - // no tags - activityName = tokenizedInputs[1].strip(); - if (activityName.isEmpty()) { - throw new EmptyNameException(); - } - } else { - activityName = tokenizedInputs[1].substring(0, delimiter).strip(); - if (activityName.isEmpty()) { - throw new EmptyNameException(); - } - String[] tagString = tokenizedInputs[1].substring(delimiter + 3).split(" "); - tags.addAll(Arrays.asList(tagString)); - } - return "Started: " + activityName; - } - /** * Parse a list command. The user can specify either a single date or a specific time frame. * @@ -268,6 +170,9 @@ private void parseDefault() { } + /** + * Resets parameters, called when an activity is ended or aborted. + */ public static void resetInfo() { startTime = null; activityName = null; diff --git a/src/test/java/jikan/parser/ExceptionTest.java b/src/test/java/jikan/parser/ExceptionTest.java index 128bcdd00..8b64e843f 100644 --- a/src/test/java/jikan/parser/ExceptionTest.java +++ b/src/test/java/jikan/parser/ExceptionTest.java @@ -13,6 +13,8 @@ class ExceptionTest { + /* + Scanner scanner = new Scanner(System.in); ActivityList activityList = new ActivityList(); @@ -36,7 +38,7 @@ public void testNoSuchActivityException() { } - + */ } From 2c363fc799a93e0f58e3b32637ecf0a50effe76c Mon Sep 17 00:00:00 2001 From: nigellenl Date: Wed, 25 Mar 2020 09:32:32 +0800 Subject: [PATCH 113/415] Update numbering in DG --- docs/DeveloperGuide.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 16e0073bc..44d761ea0 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -106,10 +106,10 @@ The StorageHandler class functions as a support to the main Storage class, allow - Removing an entry from the data file via `removeLine`. This function takes in the number of the line to remove. - Replacing an entry in the data file via `replaceLine`. This function takes in the number of the line to replace, along with the String object that needs to be written to the data file in place of the replaced line. -### 3.5 Edit feature +### 3.4 Edit feature The edit feature allows the user to make changes to activities that have been saved in the activity list. This is to allow the user to rectify any mistakes that may have been made during the initial recording of the activity. -#### 3.5.1 Current Implementation +#### 3.4.1 Current Implementation The following sequence diagram shows how the edit feature works. ![image_info](./pictures/EditSequenceDiagram.png) The current implementation of the edit feature allows the user to edit only the name parameter of the activity. When the user wants to edit an activity using the edit command, the Parser creates a new EditCommand object. The executeCommand() method of the EditCommand object is called and the specified parameters are updated accordingly. @@ -120,20 +120,20 @@ The order of method calls to edit the activity details is as follows if the spec 3. The setName() method of the Activity class is called to edit the activity name to the user-specified name 4. The activity with the updated name is returned to the activityList -#### 3.5.2 Additional Implementations +#### 3.4.2 Additional Implementations The current implementation of the edit feature only allows the user to edit the activity name. Hence, additional implementations of the edit feature should allow the user to edit other parameters of the activity such as the tags and the start and end dates. This will require the implementation of more update methods in the ActivityList class to allow for the changes to be updated in the activityList after it has been edited. -#### 3.5.3 Design Considerations +#### 3.4.3 Design Considerations By letting the user edit the name and tags of the activity, it will allow them to correct any mistakes made during the data entry. This ensures that there is an accurate record of activities such as in cases where the user may be trying to record the same activity but has misspelled it, resulting in the program regarding it as a different activity where there would be multiple unnecessary new entries in the activity list, making the analysis of the time spent more tedious and inaccurate. However, by allowing the user to edit the start date and time, there may be potential inaccuracies in the actual activity recording. This is due to the fact that the time recorded in the program is based on the LocalDateTime. By introducing user input, the dates and time may be recorded incorrectly, defeating the purpose of the time tracking program. -### 3.6 Continue Feature +### 3.5 Continue Feature The continue feature allows the user to continue a previously ended activity. -#### 3.6.1 Current Implementation +#### 3.5.1 Current Implementation ![Continue command sequence diagram](https://i.imgur.com/MuaxFts.png) **Continuing an activity:** @@ -155,7 +155,7 @@ When the user wants to end the continued activity, an *EndCommand* object is cre 3. Adds the elapsed time with the previous duration of the activity to get the *newDuration* using *plus()* method of Duration class 4. Calls the *updateDuration()* method, which updates the *duration* attribute of the continued activity in the *activityList* as well as the data.csv file -#### 3.6.2 Design Considerations +#### 3.5.2 Design Considerations **Execution:** - Continue by activity name (current implementation) @@ -168,7 +168,7 @@ When the user wants to end the continued activity, an *EndCommand* object is cre Although the current implementation of the continue feature disallows users to have multiple activities with the same name, we felt that the versatility of this choice outweighed the cons. Firstly because if the activityList got too big, it would be hard for the user to get the index of the task he/she wanted to continue. Also, the index would constantly be changing when changes are made to the list. -#### 3.6.3 Additional Features +#### 3.5.3 Additional Features As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, he/she will be given the option to continue the stated activity. ![decision flowchart](https://i.imgur.com/mCCPuun.png) From 8c9beabd1407cab2ecadce41a7707f3f80f1a77e Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 25 Mar 2020 21:40:32 +0800 Subject: [PATCH 114/415] DG for Find and Filter --- docs/DeveloperGuide.md | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 44d761ea0..5d79d09d7 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -82,8 +82,6 @@ Step 2b. If the attribute toClean is equal to true, access the storage data file `StorageCleaner#initialiseLogCleaner - Gives the storage cleaner an added functionality of being able to clear log files too.` - - ### 3.2 Storage feature The Storage class represents the back-end of Jikan, handling the creation, saving and loading of data. Jikan uses a `.csv` file to store its data, formatted in the following way: @@ -172,6 +170,39 @@ Although the current implementation of the continue feature disallows users to h As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, he/she will be given the option to continue the stated activity. ![decision flowchart](https://i.imgur.com/mCCPuun.png) +### 3.6 Find Feature +This command accepts a keyword and searches the activity list for activities with names that contain the keyword. + +#### 3.6.1 Current Implementation +* This feature is called by the user when the “find” command is entered into the command line. The string following the command is the keyword to match activity names to. +* The Parser will create a FindCommand object. +* The FindCommand will invoke its own executeCommand() method. + * The Parser's lastShownList will be cleared. + * Then it will loop through activityList to find activities with names that contain the keyword. + * If one is found, it will be added to lastShownList. + * printResults() of the Ui will be called: + * If lastShownList is not empty, it will print the matching activities. + * Else, it will respond to the user that there are no tasks which match the given keyword. + + +![find seq diagram](https://imgur.com/9tZrPS7.png) +### 3.7 Filter Feature +This feature accepts multiple space-separated keywords to search for activities with tags matching each keyword. + +#### 3.7.1 Current Implementation +* This feature is called by the user when the “filter” command is entered into the command line. The space separated strings following the command are the keywords to match activity tags with. +* The Parser will create a FilterCommand object. +* The FindCommand will invoke its own executeCommand() method. +* The Parser's lastShownList will be cleared. +* For each keyword: + * Then it will loop through activityList to find activities with tags that contain the keyword. + * If one is found, it will be added to lastShownList. + * printResults() method of the Ui will be called + * If lastShownList is not empty, it will print the matching activities. + * Else, it will respond to the user that there are no tasks which match the given keyword. + + +![filter seq diagram](https://imgur.com/P8LH1hW.png) ## 4. Appendix ### Product Scope #### Target user profile From c4dd99e50f659efa3cae4f54c85235e4b0dcae85 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Wed, 25 Mar 2020 21:47:29 +0800 Subject: [PATCH 115/415] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 5d79d09d7..c8880eb96 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -185,7 +185,7 @@ This command accepts a keyword and searches the activity list for activities wit * Else, it will respond to the user that there are no tasks which match the given keyword. -![find seq diagram](https://imgur.com/9tZrPS7.png) +![find seq diagram](https://imgur.com/kgBKjHg.png) ### 3.7 Filter Feature This feature accepts multiple space-separated keywords to search for activities with tags matching each keyword. @@ -202,7 +202,7 @@ This feature accepts multiple space-separated keywords to search for activities * Else, it will respond to the user that there are no tasks which match the given keyword. -![filter seq diagram](https://imgur.com/P8LH1hW.png) +![filter seq diagram](https://imgur.com/HehxN3H.png) ## 4. Appendix ### Product Scope #### Target user profile From 666b28edfef2137ee57d777d43f7cc5faa2818a1 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Wed, 25 Mar 2020 21:50:23 +0800 Subject: [PATCH 116/415] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index c8880eb96..be17a9409 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -185,7 +185,7 @@ This command accepts a keyword and searches the activity list for activities wit * Else, it will respond to the user that there are no tasks which match the given keyword. -![find seq diagram](https://imgur.com/kgBKjHg.png) +![find seq diagram](https://imgur.com/Icg5rdB.png) ### 3.7 Filter Feature This feature accepts multiple space-separated keywords to search for activities with tags matching each keyword. @@ -202,7 +202,7 @@ This feature accepts multiple space-separated keywords to search for activities * Else, it will respond to the user that there are no tasks which match the given keyword. -![filter seq diagram](https://imgur.com/HehxN3H.png) +![filter seq diagram](https://imgur.com/hybT3R9.png) ## 4. Appendix ### Product Scope #### Target user profile From ef1ae4bc32dbfd2e1c4eb640204b639b8f754079 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sat, 28 Mar 2020 13:08:00 +0800 Subject: [PATCH 117/415] Remove data files from text-ui-test --- .gitignore | 8 +++++--- text-ui-test/data/LogRecord.txt | 21 --------------------- text-ui-test/data/data.csv | 20 -------------------- text-ui-test/data/recycled/data.csv | 0 text-ui-test/data/recycled/status.txt | 1 - 5 files changed, 5 insertions(+), 45 deletions(-) delete mode 100644 text-ui-test/data/LogRecord.txt delete mode 100644 text-ui-test/data/data.csv delete mode 100644 text-ui-test/data/recycled/data.csv delete mode 100644 text-ui-test/data/recycled/status.txt diff --git a/.gitignore b/.gitignore index e774712e5..33d74c44e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,10 @@ # data files /data/ +# text-ui-test data files +/text-ui-test/data/ +/text-ui-test/ACTUAL.txt + # IDEA files /.idea/ /out/ @@ -14,6 +18,4 @@ src/main/resources/docs/ # MacOS custom attributes files created by Finder .DS_Store *.iml -bin/ - -/text-ui-test/ACTUAL.txt \ No newline at end of file +bin/ \ No newline at end of file diff --git a/text-ui-test/data/LogRecord.txt b/text-ui-test/data/LogRecord.txt deleted file mode 100644 index 9b6acc4bd..000000000 --- a/text-ui-test/data/LogRecord.txt +++ /dev/null @@ -1,21 +0,0 @@ - -Mar 23, 2020 1:58:04 AM jikan.Log makeInfoLog -INFO: Starting to parse inputs. -Mar 23, 2020 1:58:04 AM jikan.Log makeInfoLog -INFO: Could not start activity due to already ongoing activity. -Mar 23, 2020 1:58:20 AM jikan.Log makeInfoLog -INFO: Starting to parse inputs. -Mar 23, 2020 1:58:20 AM jikan.Log makeInfoLog -INFO: Could not start activity due to already ongoing activity. -Mar 23, 2020 2:00:14 AM jikan.Log makeInfoLog -INFO: Starting to parse inputs. -Mar 23, 2020 2:00:14 AM jikan.Log makeInfoLog -INFO: Could not start activity due to already ongoing activity. -Mar 23, 2020 2:05:41 AM jikan.Log makeInfoLog -INFO: Starting to parse inputs. -Mar 23, 2020 2:05:41 AM jikan.Log makeInfoLog -INFO: Could not start activity due to already ongoing activity. -Mar 23, 2020 2:07:09 AM jikan.Log makeInfoLog -INFO: Starting to parse inputs. -Mar 23, 2020 2:07:10 AM jikan.Log makeInfoLog -INFO: Could not start activity due to already ongoing activity. diff --git a/text-ui-test/data/data.csv b/text-ui-test/data/data.csv deleted file mode 100644 index 9614798e3..000000000 --- a/text-ui-test/data/data.csv +++ /dev/null @@ -1,20 +0,0 @@ -activity one,2020-03-23T01:58:04.634544500,2020-03-23T01:58:04.637536700,PT0.0029922S,tag1 tag tag2 -activity two,2020-03-23T01:58:04.713335600,2020-03-23T02:07:10.115384500,PT0.0153143S,tag2 -activity three,2020-03-23T01:58:04.729292400,2020-03-23T01:58:04.730288200,PT0.0009958S,tag1 tag -four,2020-03-23T01:58:04.732089400,2020-03-23T01:58:04.732452600,PT0.0003632S,tag -activity one,2020-03-23T01:58:20.293251,2020-03-23T01:58:20.295246400,PT0.0019954S,tag1 tag tag2 -activity two,2020-03-23T01:58:20.369048900,2020-03-23T01:58:20.372096600,PT0.0030477S,tag2 -activity three,2020-03-23T01:58:20.382014200,2020-03-23T01:58:20.383111400,PT0.0010972S,tag1 tag -four,2020-03-23T01:58:20.384009,2020-03-23T01:58:20.384009,PT0S,tag -activity one,2020-03-23T02:00:14.836888400,2020-03-23T02:00:14.838883,PT0.0019946S,tag1 tag tag2 -activity two,2020-03-23T02:00:14.910753,2020-03-23T02:00:14.913683700,PT0.0029307S,tag2 -activity three,2020-03-23T02:00:14.922660,2020-03-23T02:00:14.923659300,PT0.0009993S,tag1 tag -four,2020-03-23T02:00:14.924713600,2020-03-23T02:00:14.924713600,PT0S,tag -activity one,2020-03-23T02:05:41.553188600,2020-03-23T02:05:41.554188500,PT0.0009999S,tag1 tag tag2 -activity two,2020-03-23T02:05:41.633972,2020-03-23T02:05:41.637024800,PT0.0030528S,tag2 -activity three,2020-03-23T02:05:41.648931600,2020-03-23T02:05:41.649927800,PT0.0009962S,tag1 tag -four,2020-03-23T02:05:41.651922600,2020-03-23T02:05:41.651922600,PT0S,tag -activity one,2020-03-23T02:07:10.031313500,2020-03-23T02:07:10.032423700,PT0.0011102S,tag1 tag tag2 -activity two,2020-03-23T02:07:10.108257100,2020-03-23T02:07:10.110102300,PT0.0018452S,tag2 -activity three,2020-03-23T02:07:10.121074100,2020-03-23T02:07:10.121074100,PT0S,tag1 tag -four,2020-03-23T02:07:10.123067900,2020-03-23T02:07:10.123067900,PT0S,tag diff --git a/text-ui-test/data/recycled/data.csv b/text-ui-test/data/recycled/data.csv deleted file mode 100644 index e69de29bb..000000000 diff --git a/text-ui-test/data/recycled/status.txt b/text-ui-test/data/recycled/status.txt deleted file mode 100644 index c22708346..000000000 --- a/text-ui-test/data/recycled/status.txt +++ /dev/null @@ -1 +0,0 @@ -0 \ No newline at end of file From 10d17ac52e1ce0a08c1103fac8082e32bfa6fe43 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sat, 28 Mar 2020 14:06:35 +0800 Subject: [PATCH 118/415] Add list week and month features' --- src/main/java/jikan/command/ListCommand.java | 3 +- src/main/java/jikan/parser/Parser.java | 63 +++++++++++++++++--- 2 files changed, 57 insertions(+), 9 deletions(-) diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index 8f53f8302..927e9e01b 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -33,7 +33,8 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider("The time range specified is not valid."); } catch (DateTimeParseException e) { Log.makeInfoLog("Specified time range was not in the valid format"); - Ui.printDivider("Please input your dates as either yyyy-MM-dd or dd/MM/yyyy."); + Ui.printDivider("Please input your dates as either yyyy-MM-dd or dd/MM/yyyy.\n" + +" Alternatively, you can use 'day', 'week', or 'month' to get the respective reports."); } } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index efe32f2bb..f822591af 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -24,11 +24,13 @@ import jikan.Log; import java.io.IOException; +import java.time.DayOfWeek; import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; +import java.time.temporal.TemporalAdjusters; import java.util.Arrays; import java.util.HashSet; import java.util.Scanner; @@ -66,7 +68,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto */ lastShownList.activities.addAll(activityList.activities); String userInput = scanner.nextLine(); - tokenizedInputs = userInput.split(" ", 2); + tokenizedInputs = userInput.split(" ", 3); instruction = tokenizedInputs[0]; Command command = null; @@ -130,12 +132,61 @@ public static void parseList(ActivityList activityList) throws InvalidTimeFrameE lastShownList.activities.clear(); + LocalDate startDate = null; + LocalDate endDate = null; + // Parse either format DateTimeFormatter parser = DateTimeFormatter.ofPattern("[dd/MM/yyyy][yyyy-MM-dd]"); - LocalDate startDate = LocalDate.parse(tokenizedInputs[1], parser); + + // Check if the user has given a verbal input + // (User can either say day or daily and get the same output) + switch (tokenizedInputs[1]) { + case "day": + // Fallthrough + case "daily": + startDate = LocalDate.now(); + break; + case "week": + // Fallthrough + case "weekly": + // If user has input a specific date to obtain the week from, use that; + // (eg. the input is list week 2020-05-20) + // Otherwise get current date + if (tokenizedInputs.length == 3) { + startDate = LocalDate.parse(tokenizedInputs[2], parser); + } else { + startDate = LocalDate.now(); + } + + // Set current Monday and Sunday as time range + startDate = startDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); + endDate = startDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); + break; + case "month": + // Fallthrough + case "monthly": + // If user has input a specific date to obtain the month from, use that; + // Otherwise get current date + if (tokenizedInputs.length == 3) { + startDate = LocalDate.parse(tokenizedInputs[2], parser); + } else { + startDate = LocalDate.now(); + } + + // Set first and last day of month as time range + startDate = startDate.withDayOfMonth(1); + endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); + break; + default: + startDate = LocalDate.parse(tokenizedInputs[1], parser); + if (tokenizedInputs.length == 3) { + endDate = LocalDate.parse(tokenizedInputs[2], parser); + } + break; + } // Only one date is specified; return all entries with start date coinciding with that date - if (tokenizedInputs.length == 2) { + if (endDate == null) { for (Activity i : activityList.activities) { if (i.getDate().equals(startDate)) { lastShownList.activities.add(i); @@ -143,8 +194,7 @@ public static void parseList(ActivityList activityList) throws InvalidTimeFrameE } Ui.printList(lastShownList); // Both start and end dates are specified - } else if (tokenizedInputs.length == 3) { - LocalDate endDate = LocalDate.parse(tokenizedInputs[2], parser); + } else { if (endDate.isBefore(startDate)) { throw new InvalidTimeFrameException(); @@ -156,10 +206,7 @@ public static void parseList(ActivityList activityList) throws InvalidTimeFrameE } } Ui.printList(lastShownList); - } else { - throw new InvalidTimeFrameException(); } - } /** Method to parse user inputs that are not recognised. */ From 056e4365fb3745d419749f769943ab05c0cfd32d Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sat, 28 Mar 2020 14:17:58 +0800 Subject: [PATCH 119/415] Modify parseList command parsing --- src/main/java/jikan/command/ListCommand.java | 2 +- src/main/java/jikan/parser/Parser.java | 21 +++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index 927e9e01b..96bcb2b52 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -34,7 +34,7 @@ public void executeCommand(ActivityList activityList) { } catch (DateTimeParseException e) { Log.makeInfoLog("Specified time range was not in the valid format"); Ui.printDivider("Please input your dates as either yyyy-MM-dd or dd/MM/yyyy.\n" - +" Alternatively, you can use 'day', 'week', or 'month' to get the respective reports."); + + " Alternatively, you can use 'day', 'week', or 'month' to get the respective reports."); } } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index f822591af..2ab2de046 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -68,7 +68,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto */ lastShownList.activities.addAll(activityList.activities); String userInput = scanner.nextLine(); - tokenizedInputs = userInput.split(" ", 3); + tokenizedInputs = userInput.split(" ", 2); instruction = tokenizedInputs[0]; Command command = null; @@ -130,6 +130,9 @@ public static void parseList(ActivityList activityList) throws InvalidTimeFrameE return; } + String[] listInputs; + listInputs = tokenizedInputs[1].split(" ", 2); + lastShownList.activities.clear(); LocalDate startDate = null; @@ -140,7 +143,7 @@ public static void parseList(ActivityList activityList) throws InvalidTimeFrameE // Check if the user has given a verbal input // (User can either say day or daily and get the same output) - switch (tokenizedInputs[1]) { + switch (listInputs[0]) { case "day": // Fallthrough case "daily": @@ -152,8 +155,8 @@ public static void parseList(ActivityList activityList) throws InvalidTimeFrameE // If user has input a specific date to obtain the week from, use that; // (eg. the input is list week 2020-05-20) // Otherwise get current date - if (tokenizedInputs.length == 3) { - startDate = LocalDate.parse(tokenizedInputs[2], parser); + if (listInputs.length == 2) { + startDate = LocalDate.parse(listInputs[1], parser); } else { startDate = LocalDate.now(); } @@ -167,8 +170,8 @@ public static void parseList(ActivityList activityList) throws InvalidTimeFrameE case "monthly": // If user has input a specific date to obtain the month from, use that; // Otherwise get current date - if (tokenizedInputs.length == 3) { - startDate = LocalDate.parse(tokenizedInputs[2], parser); + if (listInputs.length == 2) { + startDate = LocalDate.parse(listInputs[1], parser); } else { startDate = LocalDate.now(); } @@ -178,9 +181,9 @@ public static void parseList(ActivityList activityList) throws InvalidTimeFrameE endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); break; default: - startDate = LocalDate.parse(tokenizedInputs[1], parser); - if (tokenizedInputs.length == 3) { - endDate = LocalDate.parse(tokenizedInputs[2], parser); + startDate = LocalDate.parse(listInputs[0], parser); + if (listInputs.length == 2) { + endDate = LocalDate.parse(listInputs[1], parser); } break; } From 508787bb82bdc3083e9ee9995837903073de4d14 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sat, 28 Mar 2020 14:21:33 +0800 Subject: [PATCH 120/415] Update DG to reflect that duration is being stored too --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index be17a9409..b1090e734 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -86,7 +86,7 @@ Step 2b. If the attribute toClean is equal to true, access the storage data file The Storage class represents the back-end of Jikan, handling the creation, saving and loading of data. Jikan uses a `.csv` file to store its data, formatted in the following way: -`entry-name, start-time, end-time, tags` +`entry-name, start-time, end-time, duration, tags` All tags are saved in the same cell, separated by a white space; this design decision was taken to make sure that each entry occupies the same number of cells regardless of each entry’s number of tags. The tags are then separately parsed when the data is loaded. From 914a0d76ac603348c6733d32af0e3d796c250c8b Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sat, 28 Mar 2020 17:08:54 +0800 Subject: [PATCH 121/415] Added "-s" flag option to indicate finding and filtering from the last shown list instead of complete list. --- .../java/jikan/command/FilterCommand.java | 36 +++++++++++++++++-- src/main/java/jikan/command/FindCommand.java | 34 ++++++++++++++++-- src/main/java/jikan/parser/Parser.java | 2 -- src/main/java/jikan/ui/Ui.java | 14 ++++---- 4 files changed, 72 insertions(+), 14 deletions(-) diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index 570f13216..c378adfd0 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -6,6 +6,8 @@ import jikan.parser.Parser; import jikan.ui.Ui; +import java.util.ArrayList; + import static jikan.parser.Parser.lastShownList; import static jikan.parser.Parser.tokenizedInputs; @@ -27,8 +29,15 @@ public FilterCommand(String parameters) { */ @Override public void executeCommand(ActivityList activityList) { + if (parameters.contains("-s")) { + filterSubList(); + } else { + filterFullList(activityList); + } + } + + private void filterFullList(ActivityList activityList) { try { - // Parser.parseFilter(activityList, lastShownList, tokenizedInputs[1]); String query = parameters; if (query.length() < 1) { throw new EmptyQueryException(); @@ -46,8 +55,29 @@ public void executeCommand(ActivityList activityList) { } } - private void populateLastShownList(ActivityList activityList, ActivityList lastShownList, String keyword) { - for (Activity i : activityList.activities) { + private void filterSubList() { + try { + String query = parameters.replace("-s ", ""); + ActivityList prevList = new ActivityList(); + prevList.activities.addAll(lastShownList.activities); + if (query.length() < 1) { + throw new EmptyQueryException(); + } else { + lastShownList.activities.clear(); + String[] keywords = query.split(" "); + + for (String keyword : keywords) { + populateLastShownList(prevList, lastShownList, keyword); + } + Ui.printResults(lastShownList); + } + } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { + Ui.printDivider("No keyword was given."); + } + } + + private void populateLastShownList(ActivityList targetList, ActivityList lastShownList, String keyword) { + for (Activity i : targetList.activities) { if (!lastShownList.activities.contains(i) && i.getTags().contains(keyword)) { lastShownList.activities.add(i); } diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index ff2fbb18b..d7787d3d8 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -6,6 +6,8 @@ import jikan.parser.Parser; import jikan.ui.Ui; +import java.util.ArrayList; + import static jikan.parser.Parser.lastShownList; import static jikan.parser.Parser.tokenizedInputs; @@ -13,7 +15,6 @@ * Represents a command to find activities in the activity list. */ public class FindCommand extends Command { - /** * Constructor to create a new find command. */ @@ -27,6 +28,14 @@ public FindCommand(String parameters) { */ @Override public void executeCommand(ActivityList activityList) { + if (parameters.contains("-s")) { + findSubList(); + } else { + findFullList(activityList); + } + } + + private void findFullList(ActivityList activityList) { try { // Parser.parseFind(activityList, lastShownList, tokenizedInputs[1]); String keyword = parameters; @@ -45,4 +54,25 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider("No keyword was given."); } } -} + + private void findSubList() { + try { + String keyword = parameters.replace("-s ", ""); + ArrayList prevList = new ArrayList<>(); + prevList.addAll(lastShownList.activities); + if (keyword.length() < 1) { + throw new EmptyQueryException(); + } else { + lastShownList.activities.clear(); + for (Activity i : prevList) { + if (i.getName().contains(keyword)) { + lastShownList.activities.add(i); + } + } + } + Ui.printResults(lastShownList); + } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { + Ui.printDivider("No keyword was given."); + } + } +} \ No newline at end of file diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 2ab2de046..7a0d178d5 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -50,7 +50,6 @@ public class Parser { public static String[] tokenizedInputs; String instruction; private static Log logger = new Log(); - // public static ActivityList lastShownList = new ActivityList(); public static ActivityList lastShownList = new ActivityList(); // flag to check if the current activity is a continued one public static int continuedIndex = -1; @@ -66,7 +65,6 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto /*lastShownList is initialised here to facilitate subsequent delete and edit commands referencing by index of this list. */ - lastShownList.activities.addAll(activityList.activities); String userInput = scanner.nextLine(); tokenizedInputs = userInput.split(" ", 2); instruction = tokenizedInputs[0]; diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index d62b3351a..67ecd9751 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -51,19 +51,19 @@ private static void printTableFormat(ActivityList activityList, int index, boole /** * Prints the results from a 'find' or 'filter' command. - * @param lastShownList the list of activities to print + * @param resultsList the list of activities to print */ - public static void printResults(ActivityList lastShownList) { - if (lastShownList.activities.size() > 0) { + public static void printResults(ActivityList resultsList) { + if (resultsList.activities.size() > 0) { System.out.println(DIVIDER); System.out.println("Here are the matching activities in your list:\n"); System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); - for (int i = 0; i < lastShownList.getSize(); i++) { - if (lastShownList.get(i).getTags() != null && !lastShownList.get(i).getTags().isEmpty()) { - printTableFormat(lastShownList, i, true); + for (int i = 0; i < resultsList.getSize(); i++) { + if (resultsList.get(i).getTags() != null && !resultsList.get(i).getTags().isEmpty()) { + printTableFormat(resultsList, i, true); } else { - printTableFormat(lastShownList, i, false); + printTableFormat(resultsList, i, false); } } System.out.println(DIVIDER); From fffed57a465333b812f945b072c3cc28dbd1e906 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 28 Mar 2020 17:10:50 +0800 Subject: [PATCH 122/415] Add graph command --- src/main/java/jikan/Jikan.java | 3 ++ .../java/jikan/command/FilterCommand.java | 5 ++- src/main/java/jikan/command/FindCommand.java | 3 +- src/main/java/jikan/command/GraphCommand.java | 35 +++++++++++++++++++ src/main/java/jikan/parser/Parser.java | 22 +++++------- src/main/java/jikan/ui/Ui.java | 16 +++++---- 6 files changed, 59 insertions(+), 25 deletions(-) create mode 100644 src/main/java/jikan/command/GraphCommand.java diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index c689c5f5f..c6af7d793 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -25,6 +25,8 @@ public class Jikan { /** Activity list to store current tasks in. */ private static ActivityList activityList; + public static ActivityList lastShownList = new ActivityList(); + /** Ui to handle printing. */ private static Ui ui = new Ui(); @@ -46,6 +48,7 @@ public static void main(String[] args) throws InvalidTimeFrameException, IOExcep cleaner.autoClean(); activityList = storage.createActivityList(); activityList.storage = storage; + lastShownList.activities.addAll(activityList.activities); //public static final Scanner in = new Scanner(System.in); while (true) { diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index 570f13216..ab93142f8 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -4,10 +4,9 @@ import jikan.activity.ActivityList; import jikan.exception.EmptyQueryException; import jikan.parser.Parser; -import jikan.ui.Ui; +import jikan.ui.Ui;; -import static jikan.parser.Parser.lastShownList; -import static jikan.parser.Parser.tokenizedInputs; +import static jikan.Jikan.lastShownList; /** * Represents a command to filter activities based on user-specified criterias. diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index ff2fbb18b..b4a3e97d8 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -6,8 +6,7 @@ import jikan.parser.Parser; import jikan.ui.Ui; -import static jikan.parser.Parser.lastShownList; -import static jikan.parser.Parser.tokenizedInputs; +import static jikan.Jikan.lastShownList; /** * Represents a command to find activities in the activity list. diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java new file mode 100644 index 000000000..2c52dcfdf --- /dev/null +++ b/src/main/java/jikan/command/GraphCommand.java @@ -0,0 +1,35 @@ +package jikan.command; + +import jikan.activity.Activity; +import jikan.activity.ActivityList; +import jikan.parser.Parser; + +import java.time.Duration; + +import static jikan.Jikan.lastShownList; + +public class GraphCommand extends Command { + /** + * Constructor to create a new command. + * @param parameters + */ + public GraphCommand(String parameters) { + super(parameters); + } + + @Override + public void executeCommand(ActivityList activityList) { + System.out.println(String.format("%-25s %s %-100s", "Name", "|", "Duration")); + for (int i = 0; i < lastShownList.getSize(); i++) { + Activity activity = lastShownList.get(i); + Duration duration = activity.getDuration(); + double minutes = duration.toMinutes() / 10.0; + int tenMinutes = (int) Math.round(minutes); + System.out.print(String.format("%-25s %s", activity.getName(), "|")); + for (int j = 0; j < tenMinutes; j++) { + System.out.print("*"); + } + System.out.println(""); + } + } +} diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 2ab2de046..1dc60184b 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,17 +1,6 @@ package jikan.parser; -import jikan.command.AbortCommand; -import jikan.command.ByeCommand; -import jikan.command.Command; -import jikan.command.CleanCommand; -import jikan.command.ContinueCommand; -import jikan.command.DeleteCommand; -import jikan.command.EditCommand; -import jikan.command.EndCommand; -import jikan.command.FindCommand; -import jikan.command.FilterCommand; -import jikan.command.ListCommand; -import jikan.command.StartCommand; +import jikan.command.*; import jikan.exception.EmptyNameException; import jikan.activity.Activity; @@ -36,6 +25,8 @@ import java.util.Scanner; import java.util.Set; +import static jikan.Jikan.lastShownList; + /** * Represents the object which parses user input to relevant functions for the execution of commands. */ @@ -51,7 +42,7 @@ public class Parser { String instruction; private static Log logger = new Log(); // public static ActivityList lastShownList = new ActivityList(); - public static ActivityList lastShownList = new ActivityList(); + // public static ActivityList lastShownList = new ActivityList(); // flag to check if the current activity is a continued one public static int continuedIndex = -1; @@ -66,7 +57,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto /*lastShownList is initialised here to facilitate subsequent delete and edit commands referencing by index of this list. */ - lastShownList.activities.addAll(activityList.activities); + // lastShownList.activities.addAll(activityList.activities); String userInput = scanner.nextLine(); tokenizedInputs = userInput.split(" ", 2); instruction = tokenizedInputs[0]; @@ -106,6 +97,9 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto case "continue": command = new ContinueCommand(tokenizedInputs[1]); break; + case "graph": + command = new GraphCommand(null); + break; default: parseDefault(); break; diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index d62b3351a..d2a495562 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -37,14 +37,18 @@ private static void printTableFormat(ActivityList activityList, int index, boole - TimeUnit.HOURS.toMinutes(TimeUnit.NANOSECONDS.toHours(durationInNanos)), TimeUnit.NANOSECONDS.toSeconds(durationInNanos) - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(durationInNanos))); + String printIndex = String.valueOf(index + 1); + if (index < 9) { + printIndex = String.valueOf(index + 1) + " "; + } if (gotTags) { - System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %-100s", - index + 1, "|", activityList.get(index).getName(), "|", duration, "|", + System.out.println(String.format("%s %s %-25s %s %-10s %s %-10s %s %-100s", + printIndex, "|", activityList.get(index).getName(), "|", duration, "|", activityList.get(index).getDate().toString(), "|", activityList.get(index).getTags().toString())); } else { - System.out.println(String.format("%d %s %-25s %s %-10s %s %-10s %s %s", - index + 1, "|", activityList.get(index).getName(), "|", duration, "|", + System.out.println(String.format("%s %s %-25s %s %-10s %s %-10s %s %s", + printIndex, "|", activityList.get(index).getName(), "|", duration, "|", activityList.get(index).getDate().toString(), "|", "")); } } @@ -57,7 +61,7 @@ public static void printResults(ActivityList lastShownList) { if (lastShownList.activities.size() > 0) { System.out.println(DIVIDER); System.out.println("Here are the matching activities in your list:\n"); - System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", + System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); for (int i = 0; i < lastShownList.getSize(); i++) { if (lastShownList.get(i).getTags() != null && !lastShownList.get(i).getTags().isEmpty()) { @@ -76,7 +80,7 @@ public static void printResults(ActivityList lastShownList) { public static void printList(ActivityList activityList) { System.out.println(DIVIDER); System.out.println("Your completed activities:"); - System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", + System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); for (int i = 0; i < activityList.getSize(); i++) { if (activityList.get(i).getTags() != null && !activityList.get(i).getTags().isEmpty()) { From f112af6de33097aef912b4a84aba56b82cd260a4 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 28 Mar 2020 17:45:58 +0800 Subject: [PATCH 123/415] Add graph by tags --- src/main/java/jikan/command/GraphCommand.java | 45 +++++++++++++++++-- src/main/java/jikan/parser/Parser.java | 2 +- 2 files changed, 43 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index 2c52dcfdf..f5fda45d7 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -5,6 +5,8 @@ import jikan.parser.Parser; import java.time.Duration; +import java.util.HashMap; +import java.util.Set; import static jikan.Jikan.lastShownList; @@ -19,17 +21,54 @@ public GraphCommand(String parameters) { @Override public void executeCommand(ActivityList activityList) { + if (parameters.equals("tags")) { + graphTags(); + } else { + graphLastShown(); + } + } + + private void graphLastShown() { System.out.println(String.format("%-25s %s %-100s", "Name", "|", "Duration")); for (int i = 0; i < lastShownList.getSize(); i++) { Activity activity = lastShownList.get(i); Duration duration = activity.getDuration(); - double minutes = duration.toMinutes() / 10.0; - int tenMinutes = (int) Math.round(minutes); + int interval = Integer.parseInt(parameters); + double minutes = duration.toMinutes() / (double) interval; + int scaledMinutes = (int) Math.round(minutes); System.out.print(String.format("%-25s %s", activity.getName(), "|")); - for (int j = 0; j < tenMinutes; j++) { + for (int j = 0; j < scaledMinutes; j++) { System.out.print("*"); } System.out.println(""); } } + + private void graphTags() { + HashMap tags = new HashMap<>(); + for (Activity activity : lastShownList.activities) { + Set activityTags = activity.getTags(); + for (String tag : activityTags) { + if (tags.containsKey(tag)) { + Duration oldDuration = tags.get(tag); + Duration newDuration = oldDuration.plus(activity.getDuration()); + tags.put(tag, newDuration); + } else { + tags.put(tag, activity.getDuration()); + } + } + } + + System.out.println(String.format("%-10s %s %-100s", "Tag", "|", "Duration")); + + tags.forEach((key,value) -> { + double minutes = value.toMinutes() / 10.0; + int tenMinutes = (int) Math.round(minutes); + System.out.print(String.format("%-10s %s", key, "|")); + for (int j = 0; j < tenMinutes; j++) { + System.out.print("*"); + } + System.out.println(""); + }); + } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 1dc60184b..10b20a225 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -98,7 +98,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto command = new ContinueCommand(tokenizedInputs[1]); break; case "graph": - command = new GraphCommand(null); + command = new GraphCommand(tokenizedInputs[1]); break; default: parseDefault(); From f12bf25e415959b33fa6e20214ee71b866366a74 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 28 Mar 2020 18:02:25 +0800 Subject: [PATCH 124/415] Refactor graph command --- src/main/java/jikan/command/GraphCommand.java | 52 ++++++------------- src/main/java/jikan/ui/Ui.java | 38 ++++++++++++++ 2 files changed, 53 insertions(+), 37 deletions(-) diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index f5fda45d7..4aec96c5f 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -2,7 +2,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; -import jikan.parser.Parser; +import jikan.ui.Ui; import java.time.Duration; import java.util.HashMap; @@ -24,51 +24,29 @@ public void executeCommand(ActivityList activityList) { if (parameters.equals("tags")) { graphTags(); } else { - graphLastShown(); - } - } - - private void graphLastShown() { - System.out.println(String.format("%-25s %s %-100s", "Name", "|", "Duration")); - for (int i = 0; i < lastShownList.getSize(); i++) { - Activity activity = lastShownList.get(i); - Duration duration = activity.getDuration(); int interval = Integer.parseInt(parameters); - double minutes = duration.toMinutes() / (double) interval; - int scaledMinutes = (int) Math.round(minutes); - System.out.print(String.format("%-25s %s", activity.getName(), "|")); - for (int j = 0; j < scaledMinutes; j++) { - System.out.print("*"); - } - System.out.println(""); + Ui.printActivityGraph(interval); } } private void graphTags() { HashMap tags = new HashMap<>(); for (Activity activity : lastShownList.activities) { - Set activityTags = activity.getTags(); - for (String tag : activityTags) { - if (tags.containsKey(tag)) { - Duration oldDuration = tags.get(tag); - Duration newDuration = oldDuration.plus(activity.getDuration()); - tags.put(tag, newDuration); - } else { - tags.put(tag, activity.getDuration()); - } - } + extractTags(tags, activity); } + Ui.printTagsGraph(tags); + } - System.out.println(String.format("%-10s %s %-100s", "Tag", "|", "Duration")); - - tags.forEach((key,value) -> { - double minutes = value.toMinutes() / 10.0; - int tenMinutes = (int) Math.round(minutes); - System.out.print(String.format("%-10s %s", key, "|")); - for (int j = 0; j < tenMinutes; j++) { - System.out.print("*"); + private void extractTags(HashMap tags, Activity activity) { + Set activityTags = activity.getTags(); + for (String tag : activityTags) { + if (tags.containsKey(tag)) { + Duration oldDuration = tags.get(tag); + Duration newDuration = oldDuration.plus(activity.getDuration()); + tags.put(tag, newDuration); + } else { + tags.put(tag, activity.getDuration()); } - System.out.println(""); - }); + } } } diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index d2a495562..fe00d69ef 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -1,8 +1,14 @@ package jikan.ui; +import jikan.activity.Activity; import jikan.activity.ActivityList; + +import java.time.Duration; +import java.util.HashMap; import java.util.concurrent.TimeUnit; +import static jikan.Jikan.lastShownList; + public class Ui { public static final String GREETING = "Jikan"; @@ -91,4 +97,36 @@ public static void printList(ActivityList activityList) { } System.out.println(DIVIDER); } + + public static void printActivityGraph(int interval) { + System.out.println(DIVIDER); + System.out.println(String.format("%-25s %s %-100s", "Name", "|", "Duration")); + for (int i = 0; i < lastShownList.getSize(); i++) { + Activity activity = lastShownList.get(i); + Duration duration = activity.getDuration(); + double minutes = duration.toMinutes() / (double) interval; + int scaledMinutes = (int) Math.round(minutes); + System.out.print(String.format("%-25s %s", activity.getName(), "|")); + for (int j = 0; j < scaledMinutes; j++) { + System.out.print("*"); + } + System.out.println(""); + } + System.out.println(DIVIDER); + } + + public static void printTagsGraph(HashMap tags) { + System.out.println(DIVIDER); + System.out.println(String.format("%-10s %s %-100s", "Tag", "|", "Duration")); + tags.forEach((key,value) -> { + double minutes = value.toMinutes() / 10.0; + int scaledMinutes = (int) Math.round(minutes); + System.out.print(String.format("%-10s %s", key, "|")); + for (int j = 0; j < scaledMinutes; j++) { + System.out.print("*"); + } + System.out.println(""); + }); + System.out.println(DIVIDER); + } } From e69cfaec697687ce39706285ed3fcd698fb568a8 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 28 Mar 2020 18:22:54 +0800 Subject: [PATCH 125/415] Added som exception handling --- src/main/java/jikan/command/GraphCommand.java | 17 ++++++++++++----- src/main/java/jikan/parser/Parser.java | 7 +++++-- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index 4aec96c5f..8ffc05278 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -21,11 +21,18 @@ public GraphCommand(String parameters) { @Override public void executeCommand(ActivityList activityList) { - if (parameters.equals("tags")) { - graphTags(); - } else { - int interval = Integer.parseInt(parameters); - Ui.printActivityGraph(interval); + try { + if (parameters.equals("tags")) { + graphTags(); + } else { + int interval = Integer.parseInt(parameters); + Ui.printActivityGraph(interval); + } + } catch (ArrayIndexOutOfBoundsException e) { + Ui.printDivider("Please include the time interval for graphing.\n"); + } catch (NumberFormatException e) { + Ui.printDivider("Please input an integer for the time interval.\n" + + "If you'd like to graph by tags, enter the command "); } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 10b20a225..9d08db165 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -48,7 +48,8 @@ public class Parser { /** * Parses user commands to relevant functions to carry out the commands. - * @param scanner scanner object which reads user input + * + * @param scanner scanner object which reads user input * @param activityList the list of activities */ public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) { @@ -206,7 +207,9 @@ public static void parseList(ActivityList activityList) throws InvalidTimeFrameE } } - /** Method to parse user inputs that are not recognised. */ + /** + * Method to parse user inputs that are not recognised. + */ private void parseDefault() { String line = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; Log.makeInfoLog("Invalid command entered"); From 6e82fef7430e880af5b7d21df90037e57726d2e1 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 28 Mar 2020 18:33:34 +0800 Subject: [PATCH 126/415] Fixed style --- src/main/java/jikan/command/FilterCommand.java | 2 +- src/main/java/jikan/command/GraphCommand.java | 7 ++++--- src/main/java/jikan/ui/Ui.java | 8 ++++++++ 3 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index e0e4a20f2..32d9b2ac9 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -4,7 +4,7 @@ import jikan.activity.ActivityList; import jikan.exception.EmptyQueryException; import jikan.parser.Parser; -import jikan.ui.Ui;; +import jikan.ui.Ui; import static jikan.Jikan.lastShownList; diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index 8ffc05278..4b895340a 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -13,7 +13,8 @@ public class GraphCommand extends Command { /** * Constructor to create a new command. - * @param parameters + * @param parameters Either time interval for graph or 'tags' flag + * to graph by tags */ public GraphCommand(String parameters) { super(parameters); @@ -31,8 +32,8 @@ public void executeCommand(ActivityList activityList) { } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("Please include the time interval for graphing.\n"); } catch (NumberFormatException e) { - Ui.printDivider("Please input an integer for the time interval.\n" + - "If you'd like to graph by tags, enter the command "); + Ui.printDivider("Please input an integer for the time interval.\n" + + "If you'd like to graph by tags, enter the command ."); } } diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 9db02750d..8993813f5 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -98,6 +98,10 @@ public static void printList(ActivityList activityList) { System.out.println(DIVIDER); } + /** + * Prints a graph of the last shown list. + * @param interval The time interval for the graph. + */ public static void printActivityGraph(int interval) { System.out.println(DIVIDER); System.out.println(String.format("%-25s %s %-100s", "Name", "|", "Duration")); @@ -115,6 +119,10 @@ public static void printActivityGraph(int interval) { System.out.println(DIVIDER); } + /** + * Prints a graph based on activity tags. + * @param tags The set of tags to be graphed. + */ public static void printTagsGraph(HashMap tags) { System.out.println(DIVIDER); System.out.println(String.format("%-10s %s %-100s", "Tag", "|", "Duration")); From 33b7aae3044eed41c8a5cc61dcf8e16777fb61a5 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 28 Mar 2020 18:39:08 +0800 Subject: [PATCH 127/415] Fixed gradle again --- src/main/java/jikan/parser/Parser.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 28223d405..ac6dbcd69 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,6 +1,18 @@ package jikan.parser; -import jikan.command.*; +import jikan.command.Command; +import jikan.command.AbortCommand; +import jikan.command.ByeCommand; +import jikan.command.CleanCommand; +import jikan.command.ContinueCommand; +import jikan.command.DeleteCommand; +import jikan.command.EditCommand; +import jikan.command.EndCommand; +import jikan.command.FilterCommand; +import jikan.command.FindCommand; +import jikan.command.GraphCommand; +import jikan.command.ListCommand; +import jikan.command.StartCommand; import jikan.exception.EmptyNameException; import jikan.activity.Activity; From 15d65fc69d5e9bf3f5214a3de375ef8fd24bbf62 Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 14:26:13 +0800 Subject: [PATCH 128/415] Add tests for some commands --- docs/DeveloperGuide.md | 15 +-- docs/pictures/continueActivity.png | Bin 0 -> 40280 bytes docs/pictures/continue_flowchart.PNG | Bin 0 -> 41814 bytes docs/pictures/endActivity.PNG | Bin 0 -> 33720 bytes src/main/java/jikan/command/StartCommand.java | 11 +- src/main/java/jikan/storage/Storage.java | 10 +- .../java/jikan/command/AbortCommandTest.java | 19 ++++ .../jikan/command/ContinueCommandTest.java | 68 ++++++++++++ .../java/jikan/command/DeleteCommandTest.java | 57 ++++++++++ .../java/jikan/command/StartCommandTest.java | 97 ++++++++++++++++++ 10 files changed, 263 insertions(+), 14 deletions(-) create mode 100644 docs/pictures/continueActivity.png create mode 100644 docs/pictures/continue_flowchart.PNG create mode 100644 docs/pictures/endActivity.PNG create mode 100644 src/test/java/jikan/command/AbortCommandTest.java create mode 100644 src/test/java/jikan/command/ContinueCommandTest.java create mode 100644 src/test/java/jikan/command/DeleteCommandTest.java create mode 100644 src/test/java/jikan/command/StartCommandTest.java diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index b1090e734..a619b7493 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -132,7 +132,7 @@ However, by allowing the user to edit the start date and time, there may be pote The continue feature allows the user to continue a previously ended activity. #### 3.5.1 Current Implementation -![Continue command sequence diagram](https://i.imgur.com/MuaxFts.png) +![Continue command sequence diagram](./pictures/continueActivity.png) **Continuing an activity:** @@ -142,7 +142,7 @@ When the user enters the command to continue an activity, a *ContinueCommand* ob 2. Gets the *name* and *tags* of the activity to be continued and saves it to a public static variable of *Parser* object 3. Gets the current time and saves it to a public static variable of *Parser* object - ![End command sequence diagram](https://i.imgur.com/soaCCXk.png) + ![End command sequence diagram](./pictures/endActivity.PNG) **Ending a continued activity:** @@ -168,7 +168,7 @@ Although the current implementation of the continue feature disallows users to h #### 3.5.3 Additional Features As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, he/she will be given the option to continue the stated activity. -![decision flowchart](https://i.imgur.com/mCCPuun.png) +![decision flowchart](./pictures/continue_flowchart.PNG) ### 3.6 Find Feature This command accepts a keyword and searches the activity list for activities with names that contain the keyword. @@ -239,6 +239,9 @@ Allow users to record their daily activities and track their time usage in a use * *glossary item* - Definition -### Instructions for Manual Testing - -{Give instructions on how to do a manual product testing e.g., how to load sample data to be used for testing} +### Instructions for Manual Testing + + #### Launch and Shutdown + 1. Download the jar file and docs folder + 2. Copy both into an empty folder + 3. Run the jar file in your terminal using the command `java -jar jikan.jar` diff --git a/docs/pictures/continueActivity.png b/docs/pictures/continueActivity.png new file mode 100644 index 0000000000000000000000000000000000000000..be17734b9b84c7f84007dc853b235be052e07edc GIT binary patch literal 40280 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 Q9-ZT`>M@lJWedOm1&kl~Z~y=R literal 0 HcmV?d00001 diff --git a/docs/pictures/continue_flowchart.PNG b/docs/pictures/continue_flowchart.PNG new file mode 100644 index 0000000000000000000000000000000000000000..f9ace2d30e55b75343c436019ee9cba70f36ffe1 GIT binary patch literal 41814 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 HC$9ewqLVV( literal 0 HcmV?d00001 diff --git a/docs/pictures/endActivity.PNG b/docs/pictures/endActivity.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a7c3f763a093d0451570fc7427db49d694a89a9d GIT binary patch literal 33720 zcmdRWcTm&a_a=5l5m8W30W}t+s2GZXfC_{T3JQWi6eN^TRC-CUA&3D)ln#+D(jkCS zEfj%-79b=Muu(z?2!v2V$lmytukZW&?auzOJG1MIlQH>}bMHO(oaa2}xjw#VqAS3^ zm!FT1Pe5N!+l-HI9fXf>ZSm%f;G2N{9X;SMsHoY zu>t&h%Pl=CFFwAV-n_qSh7gkee0&d#^|jAm_P1jUK5oE_eCN&#bG6NSG7d|d85}Y^ zsIPs&r5(U@KE8=py|emI{#eysFK;;r^S0Xqd9DO>bT)fDZ0mtbt2IxTHQ8_E zxs!-Sajt}M9d;~Jc{iUl4D*B96oRpue=TpgcW?Qkz609-e$2yk?AUCa<=S26F4!oI ze&KhhjDjNC2YMGD3I$~i>DFPxR;Sz8^khTsUazkTkd8P0M+2cxzTBCZzFbKXo>-i= zXGXqIvOkRNn1mu6bscuAH|tGYU3o6A=9IIlwQ_Pfeck3~s{+$W?s#mbSm@rM(Hx7_ zPMD{^5Y2C{KD5~_IfdhM+5_#zVYYQHFyVR1Z{Bt1h2&E%e4Q>fD^2DfbSpmgqtqcu zep6ibw;wl|0`U^|hv5o@h74nt$W>Tb^RwJYmA7)s@7Hbasn;P}ZWCP+4?{-{{XC@d z_Q+eb%y<24#H+f7CkLB6gw+t+w_LI zaxd_G@cw#vB3@JGl}R%zuRGapy>%%yCUDiQ_(@DdsoXsK=Su0gac8*$ywDVtMi*(JSKD=);Iex}CvkTzaDDYF*yVH-hPPQf|~BoQXX;z{#Ja`T8LEKzQ_A$}gYmmMdla4dv# zhE8gWnrnzWb&OOlFH08FvukGCMhspL+X6w!+>~H!+7WilszXz)zo>q*lK6{panl`i4 zB98B9;t;Zjb(5x>>*9RGB7MpOlh<*TKf#(hp+gd<&s=apzH z-xNKRBz4a`6tY}tz!_}gE_n6*l!C1qqKat?FEc`ds#KZN)7*N089K>cz_PcE zqczo|Ea?}OK61x}H%ndJ)<4@Ao95C7t5z`RQR1S(4#M{76XV(NY zTr;1$T$hx0S2X1|HsnZ5Hzpk%9e*8-&p&zg#!&%RKLW;JQs^p1iXTa;r51G|*vo}c zgLzm(_T>aSBMx2-SK!IDQ+O5BfGQ$8*cG1I&77+q>V!pe79k7C6Me6ftQRb+;^A%< zB-zyEM@zxZVFe4VbTDVkh2{F1X$1kve3yy7x1HYptMcXC-1AoPb%~|!H#Fy(N-QTw zJX^e#lFhlk?I(8y?SQ;-T+{OD?b~@g#!sRoUOB4ReXqJ%Uk4_|c(C5yUv6%E-4%Ry z@4VOCMB?-&P3K1qzSt%A3*ue@UmZrxq|MO#t=kJEuTi6Rl}jqd27dNz_AS1_3SQM4 zRq@R|5i&4i=XGl|leHYWG>`w$dnaF4^Cs8m9XV^8!tL!jlNzkq(mqMDNP2^r zOr@uv^G!6nsJM<3UmTRwY}#8^F6o0DMvg|&pIHkr+@!C(zNzKVokb#yFW8;JZg)m% zuon%CoHvZO1_}-ks?ziaEf03TT757|k4eQdFW+LK=f!GLED*^WOHWl6Lmn8l^hZ-) zbu(z`q@Nz~P7GvVHQIQtFFY!b#KO^tZ%YLv3q?<+ELL-R>nAz((R}tlK0o?8+Wxh8 zz<8iPc(A=_ARZ1Y7Y*!eVFtZ-J2^MBs=~G1mkQrLov=mJ-9#DZX9%4b>}O5i_efS; zzCz4&fOsuMcaN6#@|R_3mmdzvMW@ZX4m+V!Rv+1#Omly{XW-ez$`!Zsu3s@aYerAI zEL(pwUL}p+oZ!3i_De`I(}h?Y(l1b6j53~>CclmRNNC6_JvHxV5L3{Q+-}yHjxCkY zZ7*Ia3rqa@{)y84dC|b4>E`;lh!GZxPHU-8zw|@2oBb+8v-&KKG?xRP;1Ea5^RU!? zCzTaWYQ`_urB>G~%}*N*SDm2Otsa^mni%d#F;%5fkL3>S<6z=U7#)B3s(=P_U6HtdJA)aN0G zJbbF^&Q@O&AhKw#N(u_Q(Tgtweh$gVpQdv*89ks}A-p0@Lj^y3C6iAt-S7%Dv7LK2 zSe3XZt(sUMX-UPo-O3Hfzv2U}ZAXnZJ@QN1x^*J4J8#6NAy0i;*_b|fqtc|vfkp6d zyj*BT#<|`Kvr?H&N7|Y10HKY)HZjh^ZMnX`F)Bnk>eMc?8|jN(5q1x%1rz$<^SE{f z+vTNgUax`Mn3BMxyQH@#qF$n}75(k?3(>(`B=s1>s4bc}bn4_;_N&3quP;d-#XYMD z7*b=!`V^jZ$?oxpa=?zQ=G(R~O_zhp_D+)%AT!9n$uf%Sw@IY^1!eD&z z886zEDatsRpTk*0+{f#R3z)fK78BG8f4sM8VXw4m{t!CZcInDCsT1?{n#ug{kLQJV z1-)wL*oE|Oqb=12$cO|7VyfT)s`F6SiTt|@ z&(NJ#8#5QE*s+AmFE!@;<;riHz@Z@*_7KNsHZg_;-PgVnyN0?RMAlZa`T?1?`L}*6dCNI7V>j` zKNR1~g|X11(E|jD`5}!|YXob&gEjqR2&<(T;#^&YbY6FHX7=X9@Ip1Yju%%6j4K}H z+@ei&eIG9C+xBya#bebEMBmF9zC&2Yn}6@i@yq`3)t7iwWM^mYhi_@FF9>gxT?fRT zu7hjXR~iQl6o}0|b+O}aFZb7zn;Xkg&C!aLnYkk`BB3}{O~3`^SR=5pAK~h*5`_UZ zR;OO&EUAcyKTsP&B62ejeXqjY8uw#;9CHqT;$@R4A%cywBU}b;jD78H$y)Y9B9w~* z-}I~dI^rg0KeBOUGH{^rHY=TS`jf@^Z2^&Xa#CGv2qXPIDXfij3`&4 z=G`_`+$ZWc7*L~9JF7LRq#@q#J7rDl5d@Jr3G{_M4_A5CIdpdZMP@^#RQJ3LEgfA=1rDWfcB`%`YQIefD z;g>L|x&6~wi_nj;1RRe1b=|_18rOck9yRy@O^&lH8nw$vSere*6c`4UjGjX zMSNoww<@vkePVQiMB#L0`SJEgeW&-CMbG@?T*0^JozstY)Iuh<=8gGtM}kf-Y`w#` z*?f(?wv4#-46&_aE>c3tt36mc-}F*)mW2_M=Emve?@a6EPqTQ=Y{jv@cWsM^1K0p! z&WNHi3<{OFGD}I|xr@(|QQ?QA}h9eX}eq&7{tBIpBF6 zgG0hr$V^rj9Oy>)k_4U&zw&eUGgJ`V2fs zm%TCLK_jIKOqV*1RLh^^rMT8Ogf%m`Lb9uXBt?`Jsjz$(^_8N^4|$r zCeuFNWfowYJC1M|M=dD(O_QZ2)JdJM=e7z=7Gxu2L>^dMRM9yh$fpEqZ8@df)*3he7B~hcfi!`Mu16yAmU=jFh@oyS6D2;x+Y~#F3v~bed zQIk^v$rHK6fV>n@EBvDV!unEO)v`Ft{Bq%dtBx)<3AxXU5nMnO-r;U8qXPb3q&%GP zmiEOZcH9$rFnRO{<%f21?D))lYoW!Niu>90<(rkw>V6dC4+?2Pqc>`XTOC-j!v}qL z?JvCUf{l~G4s9ENQm&_0^8f{@JUc znF{y+(EM5{yT>S0;uN!OLUcq1sezH>B>lzq2<*qrlue!&2$3C$$L$C-u@r(|N#Df{;7V1!Vn6t_#7 z?UG0RpvG8(Lbx`Z7*x2U7jbzRt>~3CGM^@8tzh_ya}yEurp#eEs+Y06kbc)@X@oi& z_4>-B>@&m}4gbudZhA%FMKCsES=7hf8_f~ zw)j>z$vY@@({v^KSXM(0>1B(dAY-LK(noN{sJo!u6{OJ zh>=i4px`oImt4d+=VSy)Z&SdP1s?~YY`TiDEN#wxAhEKS<6||Pj0o*%N5V{^(=~}zgFmJ0LC7`E$y1cK!@)!8SUV zzPv=MwlgKS6y5rB&XjT|sI0V%s0GS~>gmmQPl@<%^0m~GF{Ft*)k&na=q-P8!c0P_ zL2*99$6*RG&lo=JGi@zS{X8sx>(y^ z76>*;l>4Xpo$sXZ2Ve#cfB_Nv&o3s^_+P&)PG4X)tHCgD#2fX{8|Cj`gJGTzfl6>| zu6YBq#inNGyHDH!dAUI1lj{qUlf{o?xTOxR%$zZDrD?e){8>vLqgxrS8Xgm@Qlh}- zmw_ZY%pk59fV=KQ+((ktxTlqa~;tfhaZIYmtvHJANB zv^9QLa->zyDRzVmB*20CgGcS?#d8e{$MLQ87v6p99H@DhU^tecT)P=Z?&=UD!}mc# z9N5ARCsHs&%(H4UL98*Oi7u{w6Q!Uu92m1SogpuyhJfF8Jd9i!=uLnIWlEmCd&{qIG|}ss10#3m~?Wn`kXmeGiUX|`ls9CPuecsBt4j+w;e%@%!XPu z>~21T8u_S#P0_r8e~-m1(VtAp+`}YGQugR2t5y$W={0zox*Kw)QvHtjm)E6TZxMCy zMLXhS;E`|rk1jtl6qJAF`I<7kao-$qYqKo!yOQaK;_*!ad`ke!adNdOJn1E`6ES-3%ei7Pki<;+C%(WqE?Nv6URE^ zQB-WPJATc}yMWvJNrHzYDi8TXsy9li&whe*9}(UwfB))GAYE>5VK_vW#K(7g2PFHR z=!~TNx9#8;z|ek@w9iu50a=B>J|Beb*b1oIB`wVJjrNTpjp1sIo9z$6_zr}CXP?6? zMvLAK6Fn~r$lf2FOLJp{(5=~iJ>_QQNYV*nLkM?#Z?HDzjTYv>Za@;>P4=So9Pygy z%>!TKoI2CScY*<&mv!n$k>_$+4tfIO_}1M2oFVqNZ;z9kJhSy>7LRK7zdwh0{)m`s znhX!&D1y;(<~lY19Nj1(*(pj~ZMW?@zQ*&wa+APu%?{|V;hpIOrV7fN?F|>=3PGlJ zK*B>s*W6t>2s2nG|4q}rQQUrgDR}%-%|<QnkMv|421jfHocuLlJoxk95%=$Qr8s4Imoyx?#Ut$R9s`SfYw_m|s6#Ub zteHaa;?FE-zcMxANunMli(pC1JgL$v|j71xMWo^Yt|E;zQ0Sc> zdQkL=f6d#c&Q1QK_(b2)8{Ab6tFpLZm2yHeWHoqhX$+g3s^&+b;%ME#iSZ#^juU!m zWDnb)BCMY*sSlF#2%Ko1x5Jv4)jzsPSc-HqSMwh}J~*%X%#{ zUFN#91j%Ev^lwd1e2>5#`d(i_EHi1W(s}FoH-UB4MbkIFH9q#ux!~~O;T9!fZ|+;K zF$!E^>u%YS;pCwwefgHj@(#@j0{fH(#x5<6vwJ~1sYQ}iDI#N$5Usg7P;jlPqaI6> z>M0AX?atJt`kP_K-;6xiB&Z}A{PUjeQR918!V|%k`rRS;m7p0SE639OKNJ-p9cxf* z7R#4#YW!k}wb1lHX{PO4E|X|V@aj}|LUTEOL7y2WsjB3VS9`6y2g{wJT?R_hIp#7e z{93xwh$}t|aQF@AQ!S^l-M}9(G{GBx+&M>4DCB`CDJk1qG3cY>hKv zk&}*tRUU)YtQnDu{8_--#N4#NHjPR@dz-_@Imn)@#~idB z@J4*SJdJ=`fV+p@$z<;=4`LA4&P7>*)2V@lIX>Bl(CDT#^TFV&f6EFE?qD03E;p*i3bNQp+}Qc zT16m%sEBARdbxEdElNl|`p_c~?SK9qxJ}MGXk)vOj@O_fNgKM*kmawgtZyJ}S~+On zNH=BAw>EeXqev7tTDPub1=oMxC-k0_6z*H$my0h~z&;)2EDTq{iF2-!JJjnDP+VuI zl2=beaG<839K_KPmi`Z93_z7ri&n!AT2;u}BgTi&($mo<(g%Yuq=O%s4HzPA6HxWq20>jS-dq z;5Jy@H&pb3MY0Pbz@8$m3Ll`XHxT-{GS`{xghlmF>DAx*dclj$sG@R(g+((o6}8gG z@~z5qY%OFs{JZNknqFjl9rPQns5mY!7z*sT>YIixJ(US_V+$DVpQt+4HiFQl)OCBLHijL%DBnCh;TTID9w zwR2GdN(6qFO^dVT2Pi4Vnh*Y%1ZGX!*vC&0%|EiYFepRsr(^F7%uNp zAXey2u5k|z8>wVVbTbOnOb#Z>VxnYujrh+6_W|{>3)lKW>7I1W$&H_T>JLXer4y!j zS+vQlBvEKlUzgT{K3VT!53aupntsnk#YNAleWE+VRjGAR6ke-d_#>B?ejT;f&Fu13 z)h$_3_!knYH%mI4GBRJ#PJM9fB(LSWWe6p$Xl{G?e5K)_)+15uqwP=fKdw$3Mq^e4 z8F)J-SXw@CRHJ;mxnMkH$*%xPq|kYI6uKMVu27^p-VC#>I+qQP}3A8 zX4S)E4s}JiR=(i1p)2+APuFAq1GQpymfvjMS?)qS3X(5*JdS%1wsUe4?SMwfu-iZ_ z@qN5{d{cDS-#Z#W*lqTQ-?QY}esz%t6xEjBLlk}oa}PxIOML3ei$R}Q1(z51wK3=5 zq2JJ-Sfk#3$7?qn5BrU8zSgMs^tVBr-zdK`?t4r0@S+&Ays!lHnZskQ3;hP3!JB0P zHpo;z>s5{*;BhX*$;Uk%DJr{A6)A2q1yL;#rq>c%rxmMRSB4uctm5S~O=MAhXT7

!;1g?RQCi@5E8y#JT2S9|22Nr1Fo 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%0A*1HlPDWkOe^~ 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 tags = new HashSet<>(); + + void populateActivityList() throws InvalidTimeFrameException { + activities.storage = new Storage("data/activityList_test.txt"); + try { + activities.storage.clearFile(); + } catch (FileNotFoundException e) { + System.out.println("Could not find file."); + } + tags.add("tag1"); + tags.add("tag2"); + LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); + LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); + Duration duration = Duration.between(startTime, endTime); + Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags); + Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags); + Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags); + activities.add(activity1); + activities.add(activity2); + activities.add(activity3); + } + + @Test + void executeContinue() throws InterruptedException { + try { + populateActivityList(); + } catch (InvalidTimeFrameException e) { + System.out.println("Invalid time frame."); + } + String parameters = "Activity2"; + Command command = new ContinueCommand(parameters); + + // Continue Activity2 + command.executeCommand(activities); + LocalDateTime startTime = LocalDateTime.now(); + assertEquals(startTime.getMinute(), Parser.startTime.getMinute()); + + Duration initial = activities.get(1).getDuration(); + + Thread.sleep(2000); + + // End Activity2 + command = new EndCommand(null); + command.executeCommand(activities); + Duration elapsed = initial.plus(Duration.between(startTime, LocalDateTime.now())); + Duration duration = activities.get(1).getDuration(); + assertEquals(elapsed.toSeconds(), duration.toSeconds()); + } + +} \ No newline at end of file diff --git a/src/test/java/jikan/command/DeleteCommandTest.java b/src/test/java/jikan/command/DeleteCommandTest.java new file mode 100644 index 000000000..872dc7d0b --- /dev/null +++ b/src/test/java/jikan/command/DeleteCommandTest.java @@ -0,0 +1,57 @@ +package jikan.command; + +import jikan.activity.Activity; +import jikan.activity.ActivityList; +import jikan.exception.InvalidTimeFrameException; +import jikan.storage.Storage; +import org.junit.jupiter.api.Test; + +import java.io.FileNotFoundException; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.HashSet; + +import static org.junit.jupiter.api.Assertions.*; + +class DeleteCommandTest { + + ActivityList activities = new ActivityList(); + HashSet tags = new HashSet<>(); + + void populateActivityList() throws InvalidTimeFrameException { + activities.storage = new Storage("data/activityList_test.txt"); + try { + activities.storage.clearFile(); + } catch (FileNotFoundException e) { + System.out.println("Could not find file."); + } + tags.add("tag1"); + tags.add("tag2"); + LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); + LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); + Duration duration = Duration.between(startTime, endTime); + Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags); + Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags); + Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags); + activities.add(activity1); + activities.add(activity2); + activities.add(activity3); + } + + @Test + void executeDelete() { + try { + populateActivityList(); + } catch (InvalidTimeFrameException e) { + System.out.println("Invalid time frame."); + } + String parameters = "Activity2"; + + Command command = new DeleteCommand(parameters); + command.executeCommand(activities); + + assertEquals(activities.get(1).getName(), "Activity3"); + assertEquals(activities.getSize(), 2); + } + +} \ No newline at end of file diff --git a/src/test/java/jikan/command/StartCommandTest.java b/src/test/java/jikan/command/StartCommandTest.java new file mode 100644 index 000000000..00a0ca23c --- /dev/null +++ b/src/test/java/jikan/command/StartCommandTest.java @@ -0,0 +1,97 @@ +package jikan.command; + +import jikan.activity.Activity; +import jikan.activity.ActivityList; +import jikan.exception.InvalidTimeFrameException; +import jikan.parser.Parser; +import jikan.storage.Storage; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.FileNotFoundException; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.HashSet; +import java.util.Scanner; + +import static org.junit.jupiter.api.Assertions.*; + +class StartCommandTest { + ActivityList activities = new ActivityList(); + HashSet tags = new HashSet<>(); + + void populateActivityList() throws InvalidTimeFrameException { + activities.storage = new Storage("data/activityList_test.txt"); + try { + activities.storage.clearFile(); + } catch (FileNotFoundException e) { + System.out.println("Could not find file."); + } + tags.add("tag1"); + tags.add("tag2"); + LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); + LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); + Duration duration = Duration.between(startTime, endTime); + Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags); + Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags); + Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags); + activities.add(activity1); + activities.add(activity2); + activities.add(activity3); + } + + @Test + void executeStart() { + try { + populateActivityList(); + } catch (InvalidTimeFrameException e) { + System.out.println("Invalid time frame."); + } + Scanner scanner = new Scanner(System.in); + String parameters = "Activity 3 /t tag tag1"; + Command command = new StartCommand(parameters, scanner); + + HashSet activity3Tags = new HashSet<>(); + activity3Tags.add("tag"); + activity3Tags.add("tag1"); + + command.executeCommand(activities); + assertNotNull(Parser.startTime); + assertEquals(Parser.activityName, "Activity 3"); + assertEquals(activity3Tags, Parser.tags); + } + + @Test + void executeStartContinued() { + try { + populateActivityList(); + } catch (InvalidTimeFrameException e) { + System.out.println("Invalid time frame."); + } + String data = "Yes"; + System.setIn(new ByteArrayInputStream(data.getBytes())); + Scanner scanner = new Scanner(System.in); + String parameters = "Activity1"; + Command command = new StartCommand(parameters, scanner); + command.executeCommand(activities); + assertEquals(Parser.activityName, "Activity1"); + assertNotNull(Parser.startTime); + } + + @Test + void executeStartNotContinued() { + try { + populateActivityList(); + } catch (InvalidTimeFrameException e) { + System.out.println("Invalid time frame."); + } + String data = "No"; + System.setIn(new ByteArrayInputStream(data.getBytes())); + Scanner scanner = new Scanner(System.in); + String parameters = "Activity1"; + Command command = new StartCommand(parameters, scanner); + command.executeCommand(activities); + assertNull(Parser.startTime); + assertNull(Parser.activityName); + } +} \ No newline at end of file From a95f1e7d289766d9e776fa7e08b1145559a1a65e Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sun, 29 Mar 2020 14:32:35 +0800 Subject: [PATCH 129/415] Add new exception classes --- .../java/jikan/exception/InvalidCleanCommandException.java | 4 ++++ src/main/java/jikan/exception/InvalidEditFormatException.java | 4 ++++ .../java/jikan/exception/InvalidGraphCommandException.java | 4 ++++ 3 files changed, 12 insertions(+) create mode 100644 src/main/java/jikan/exception/InvalidCleanCommandException.java create mode 100644 src/main/java/jikan/exception/InvalidEditFormatException.java create mode 100644 src/main/java/jikan/exception/InvalidGraphCommandException.java diff --git a/src/main/java/jikan/exception/InvalidCleanCommandException.java b/src/main/java/jikan/exception/InvalidCleanCommandException.java new file mode 100644 index 000000000..116881cee --- /dev/null +++ b/src/main/java/jikan/exception/InvalidCleanCommandException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class InvalidCleanCommandException { +} diff --git a/src/main/java/jikan/exception/InvalidEditFormatException.java b/src/main/java/jikan/exception/InvalidEditFormatException.java new file mode 100644 index 000000000..fd2e94f91 --- /dev/null +++ b/src/main/java/jikan/exception/InvalidEditFormatException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class InvalidEditFormatException { +} diff --git a/src/main/java/jikan/exception/InvalidGraphCommandException.java b/src/main/java/jikan/exception/InvalidGraphCommandException.java new file mode 100644 index 000000000..9a06a3035 --- /dev/null +++ b/src/main/java/jikan/exception/InvalidGraphCommandException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class InvalidGraphCommandException { +} From 9fb22ce3889843497bc70f97f7fd5b9e829405e8 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sun, 29 Mar 2020 14:33:17 +0800 Subject: [PATCH 130/415] Fix exception handling for all commands --- src/main/java/jikan/Jikan.java | 4 +- src/main/java/jikan/command/CleanCommand.java | 11 +++- src/main/java/jikan/command/Command.java | 4 +- .../java/jikan/command/ContinueCommand.java | 10 +++- .../java/jikan/command/DeleteCommand.java | 9 +++- src/main/java/jikan/command/EditCommand.java | 23 +++++--- .../java/jikan/command/FilterCommand.java | 2 +- src/main/java/jikan/command/FindCommand.java | 2 +- src/main/java/jikan/command/GraphCommand.java | 14 +++-- src/main/java/jikan/command/ListCommand.java | 4 +- src/main/java/jikan/command/StartCommand.java | 7 +-- .../InvalidCleanCommandException.java | 2 +- .../exception/InvalidEditFormatException.java | 2 +- .../InvalidGraphCommandException.java | 2 +- src/main/java/jikan/parser/Parser.java | 54 +++++++++++++++---- 15 files changed, 113 insertions(+), 37 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index c6af7d793..6667f990a 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -3,6 +3,8 @@ import jikan.activity.ActivityList; import jikan.command.ByeCommand; import jikan.command.Command; +import jikan.exception.EmptyNameException; +import jikan.exception.EmptyQueryException; import jikan.exception.InvalidTimeFrameException; import jikan.parser.Parser; import jikan.storage.Storage; @@ -41,7 +43,7 @@ public class Jikan { /** * Main entry-point for the Jikan application. */ - public static void main(String[] args) throws InvalidTimeFrameException, IOException { + public static void main(String[] args) throws InvalidTimeFrameException, IOException, EmptyNameException, EmptyQueryException { ui.printGreeting(); storage = new Storage(DATA_FILE_PATH); cleaner = new StorageCleaner(storage); diff --git a/src/main/java/jikan/command/CleanCommand.java b/src/main/java/jikan/command/CleanCommand.java index cabe055d3..2872a155e 100644 --- a/src/main/java/jikan/command/CleanCommand.java +++ b/src/main/java/jikan/command/CleanCommand.java @@ -2,6 +2,7 @@ import jikan.Log; import jikan.activity.ActivityList; +import jikan.exception.InvalidCleanCommandException; import jikan.parser.Parser; import jikan.storage.Storage; import jikan.storage.StorageCleaner; @@ -45,12 +46,18 @@ public void executeCommand(ActivityList activityList) { line = "Auto cleaning disabled"; Log.makeInfoLog("User has turned off automated cleaning"); } else { - line = "Invalid Command!"; + if (parameters.isEmpty()) { + throw new IOException(); + } else { + throw new InvalidCleanCommandException(); + } } Ui.printDivider(line); // Parser.parseClean(tokenizedInputs[1]); - } catch (ArrayIndexOutOfBoundsException | IOException e) { + } catch (IOException e) { Ui.printDivider("No keyword was given."); + } catch (InvalidCleanCommandException e) { + Ui.printDivider("Invalid clean command!"); } } diff --git a/src/main/java/jikan/command/Command.java b/src/main/java/jikan/command/Command.java index 5f8d9dfc0..e9be1c776 100644 --- a/src/main/java/jikan/command/Command.java +++ b/src/main/java/jikan/command/Command.java @@ -1,6 +1,8 @@ package jikan.command; import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; +import jikan.exception.InvalidTimeFrameException; /** @@ -19,7 +21,7 @@ public Command(String parameters) { /** * Executes the command and returns the result. */ - public void executeCommand(ActivityList activityList) { + public void executeCommand(ActivityList activityList) throws EmptyNameException, InvalidTimeFrameException { } diff --git a/src/main/java/jikan/command/ContinueCommand.java b/src/main/java/jikan/command/ContinueCommand.java index 70a80d036..fe0187e69 100644 --- a/src/main/java/jikan/command/ContinueCommand.java +++ b/src/main/java/jikan/command/ContinueCommand.java @@ -3,6 +3,7 @@ import jikan.Log; import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; import jikan.exception.NoSuchActivityException; import jikan.parser.Parser; import jikan.ui.Ui; @@ -35,11 +36,18 @@ public void executeCommand(ActivityList activityList) { String line = Parser.activityName + " was continued"; Ui.printDivider(line); } else { - throw new NoSuchActivityException(); + if (parameters.isEmpty()) { + throw new EmptyNameException(); + } else { + throw new NoSuchActivityException(); + } } } catch (NoSuchActivityException e) { Ui.printDivider("No activity with this name exists!"); Log.makeInfoLog("Continue command failed as there was no such activity saved."); + } catch (EmptyNameException e) { + Ui.printDivider("Activity name cannot be empty!"); + Log.makeInfoLog("Continue command failed as there was no activity name provided."); } } } diff --git a/src/main/java/jikan/command/DeleteCommand.java b/src/main/java/jikan/command/DeleteCommand.java index cdf3e0e89..93e1ffc84 100644 --- a/src/main/java/jikan/command/DeleteCommand.java +++ b/src/main/java/jikan/command/DeleteCommand.java @@ -1,6 +1,7 @@ package jikan.command; import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; import jikan.exception.NoSuchActivityException; import jikan.parser.Parser; import jikan.ui.Ui; @@ -26,10 +27,16 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider("You have deleted " + parameters); activityList.delete(index); } else { - throw new NoSuchActivityException(); + if (parameters.isEmpty()) { + throw new EmptyNameException(); + } else { + throw new NoSuchActivityException(); + } } } catch (NoSuchActivityException e) { Ui.printDivider("No activity with this name exists!"); + } catch (EmptyNameException e) { + Ui.printDivider("Activity name cannot be empty!"); } } } diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index c100a4f63..0de7c9ca5 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -3,6 +3,7 @@ import jikan.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; +import jikan.exception.InvalidEditFormatException; import jikan.exception.NoSuchActivityException; import jikan.parser.Parser; import jikan.ui.Ui; @@ -24,6 +25,7 @@ public void executeCommand(ActivityList activityList) { try { // Parser.parseEdit(activityList); int delimiter = parameters.indexOf("/e"); + int tagDelim = parameters.indexOf("/et"); Parser.activityName = parameters.substring(0, delimiter).strip(); if (Parser.activityName.isEmpty()) { throw new EmptyNameException(); @@ -31,8 +33,14 @@ public void executeCommand(ActivityList activityList) { int index = activityList.findActivity(Parser.activityName); String newName = parameters.substring(delimiter + 3); if (index != -1) { - activityList.updateName(index,newName); - Ui.printDivider("Activity named " + Parser.activityName + " has been updated to " + newName); + if (newName.isEmpty()) { + // no new name is provided + throw new InvalidEditFormatException(); + } + else { + activityList.updateName(index, newName); + Ui.printDivider("Activity named " + Parser.activityName + " has been updated to " + newName); + } } else { // activity is not found throw new NoSuchActivityException(); @@ -40,12 +48,13 @@ public void executeCommand(ActivityList activityList) { } catch (NoSuchActivityException e) { Ui.printDivider("No activity with this name exists!"); Log.makeInfoLog("Edit command failed as there was no such activity saved."); - } catch (ArrayIndexOutOfBoundsException | EmptyNameException e) { + } + catch (EmptyNameException e) { Ui.printDivider("Activity name cannot be empty!"); - Log.makeInfoLog("Edit command failed as there was no existing activity name provided."); - } catch (StringIndexOutOfBoundsException e) { - Ui.printDivider("New activity name not provided!"); - Log.makeInfoLog("Edit command failed as there was no new activity name provided."); + Log.makeInfoLog("Edit command failed as there was no activity name provided."); + } catch (StringIndexOutOfBoundsException | InvalidEditFormatException e) { + Ui.printDivider("New details not provided!"); + Log.makeInfoLog("Edit command failed as there was no updated activity detail provided."); } } diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index 32d9b2ac9..0fb0b5529 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -47,7 +47,7 @@ private void filterFullList(ActivityList activityList) { } Ui.printResults(lastShownList); } - } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { + } catch (EmptyQueryException e) { Ui.printDivider("No keyword was given."); } } diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index ccec765aa..448c34bc4 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -48,7 +48,7 @@ private void findFullList(ActivityList activityList) { } Ui.printResults(lastShownList); } - } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { + } catch (EmptyQueryException e) { Ui.printDivider("No keyword was given."); } } diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index 4b895340a..cfa91a134 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -2,6 +2,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.InvalidGraphCommandException; import jikan.ui.Ui; import java.time.Duration; @@ -26,15 +27,18 @@ public void executeCommand(ActivityList activityList) { if (parameters.equals("tags")) { graphTags(); } else { - int interval = Integer.parseInt(parameters); - Ui.printActivityGraph(interval); + if (parameters.isEmpty()) { + throw new InvalidGraphCommandException(); + } else { + int interval = Integer.parseInt(parameters); + Ui.printActivityGraph(interval); + } } - } catch (ArrayIndexOutOfBoundsException e) { - Ui.printDivider("Please include the time interval for graphing.\n"); - } catch (NumberFormatException e) { + } catch (NumberFormatException | InvalidGraphCommandException e) { Ui.printDivider("Please input an integer for the time interval.\n" + "If you'd like to graph by tags, enter the command ."); } + } private void graphTags() { diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index 96bcb2b52..2b2efaf9c 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -25,7 +25,7 @@ public ListCommand(String parameters) { } @Override - public void executeCommand(ActivityList activityList) { + public void executeCommand(ActivityList activityList) throws InvalidTimeFrameException { try { Parser.parseList(activityList); } catch (InvalidTimeFrameException e) { @@ -34,7 +34,7 @@ public void executeCommand(ActivityList activityList) { } catch (DateTimeParseException e) { Log.makeInfoLog("Specified time range was not in the valid format"); Ui.printDivider("Please input your dates as either yyyy-MM-dd or dd/MM/yyyy.\n" - + " Alternatively, you can use 'day', 'week', or 'month' to get the respective reports."); + + " Alternatively, you can use 'day', 'week', or 'month' to get the respective reports."); } } } diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 99d37884f..0086e8ead 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -21,13 +21,14 @@ public class StartCommand extends Command { /** * Constructor to create a new start command. */ - public StartCommand(String parameters, Scanner scanner) { + public StartCommand(String parameters, Scanner scanner) throws EmptyNameException{ super(parameters); this.scanner = scanner; } @Override - public void executeCommand(ActivityList activityList) { + public void executeCommand(ActivityList activityList) throws EmptyNameException { + try { // Parser.parseStart(activityList, Jikan.in); // check if an activity has already been started @@ -52,7 +53,7 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider(line); } } - } catch (EmptyNameException | NullPointerException | ArrayIndexOutOfBoundsException e) { + } catch (EmptyNameException e) { Log.makeInfoLog("Activity started without activity name"); Ui.printDivider("Activity name cannot be empty!"); } diff --git a/src/main/java/jikan/exception/InvalidCleanCommandException.java b/src/main/java/jikan/exception/InvalidCleanCommandException.java index 116881cee..ce34c8e25 100644 --- a/src/main/java/jikan/exception/InvalidCleanCommandException.java +++ b/src/main/java/jikan/exception/InvalidCleanCommandException.java @@ -1,4 +1,4 @@ package jikan.exception; -public class InvalidCleanCommandException { +public class InvalidCleanCommandException extends Exception { } diff --git a/src/main/java/jikan/exception/InvalidEditFormatException.java b/src/main/java/jikan/exception/InvalidEditFormatException.java index fd2e94f91..292f82955 100644 --- a/src/main/java/jikan/exception/InvalidEditFormatException.java +++ b/src/main/java/jikan/exception/InvalidEditFormatException.java @@ -1,4 +1,4 @@ package jikan.exception; -public class InvalidEditFormatException { +public class InvalidEditFormatException extends Exception { } diff --git a/src/main/java/jikan/exception/InvalidGraphCommandException.java b/src/main/java/jikan/exception/InvalidGraphCommandException.java index 9a06a3035..1b850581e 100644 --- a/src/main/java/jikan/exception/InvalidGraphCommandException.java +++ b/src/main/java/jikan/exception/InvalidGraphCommandException.java @@ -1,4 +1,4 @@ package jikan.exception; -public class InvalidGraphCommandException { +public class InvalidGraphCommandException extends Exception { } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index ac6dbcd69..e5715f0db 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -63,7 +63,7 @@ public class Parser { * @param scanner scanner object which reads user input * @param activityList the list of activities */ - public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) { + public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) throws EmptyQueryException, EmptyNameException, NullPointerException, ArrayIndexOutOfBoundsException { Log.makeInfoLog("Starting to parse inputs."); Parser.cleaner = cleaner; /*lastShownList is initialised here to facilitate subsequent delete and edit commands @@ -80,7 +80,12 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto command = new ByeCommand(null); break; case "start": - command = new StartCommand(tokenizedInputs[1], scanner); + try { + command = new StartCommand(tokenizedInputs[1], scanner); + } catch (NullPointerException | ArrayIndexOutOfBoundsException e) { + Log.makeInfoLog("Activity started without activity name"); + Ui.printDivider("Activity name cannot be empty!"); + } break; case "end": command = new EndCommand(null); @@ -92,25 +97,56 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto command = new ListCommand(null); break; case "delete": - command = new DeleteCommand(tokenizedInputs[1]); + try { + command = new DeleteCommand(tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException e) { + Ui.printDivider("Activity name cannot be empty!"); + } break; case "find": - command = new FindCommand(tokenizedInputs[1]); + try { + command = new FindCommand(tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException e) { + Ui.printDivider("No keyword was given."); + } break; case "filter": - command = new FilterCommand(tokenizedInputs[1]); + try { + command = new FilterCommand(tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException e) { + Ui.printDivider("No keyword was given."); + } break; case "edit": - command = new EditCommand(tokenizedInputs[1]); + try { + command = new EditCommand(tokenizedInputs[1]); + } catch (StringIndexOutOfBoundsException | ArrayIndexOutOfBoundsException e) { + Ui.printDivider("Activity name cannot be empty!"); + Log.makeInfoLog("Edit command failed as there was no existing activity name provided."); + } break; case "clean": - command = new CleanCommand(tokenizedInputs[1], cleaner); + try { + command = new CleanCommand(tokenizedInputs[1], cleaner); + } catch (ArrayIndexOutOfBoundsException e) { + Ui.printDivider("No keyword was given."); + } break; case "continue": - command = new ContinueCommand(tokenizedInputs[1]); + try { + command = new ContinueCommand(tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException e) { + Ui.printDivider("Activity name cannot be empty!"); + Log.makeInfoLog("Continue command failed as there was no activity name provided."); + } break; case "graph": - command = new GraphCommand(tokenizedInputs[1]); + try { + command = new GraphCommand(tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { + Ui.printDivider("Please input an integer for the time interval.\n" + + "If you'd like to graph by tags, enter the command ."); + } break; default: parseDefault(); From 7820c2f6f69a49ca05d4e3c5cbd4d4e73a6dbd30 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sun, 29 Mar 2020 14:36:31 +0800 Subject: [PATCH 131/415] Fix style for gradle style check --- src/main/java/jikan/command/EditCommand.java | 6 ++---- src/main/java/jikan/command/StartCommand.java | 2 +- src/main/java/jikan/parser/Parser.java | 3 ++- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index 0de7c9ca5..84b487136 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -36,8 +36,7 @@ public void executeCommand(ActivityList activityList) { if (newName.isEmpty()) { // no new name is provided throw new InvalidEditFormatException(); - } - else { + } else { activityList.updateName(index, newName); Ui.printDivider("Activity named " + Parser.activityName + " has been updated to " + newName); } @@ -48,8 +47,7 @@ public void executeCommand(ActivityList activityList) { } catch (NoSuchActivityException e) { Ui.printDivider("No activity with this name exists!"); Log.makeInfoLog("Edit command failed as there was no such activity saved."); - } - catch (EmptyNameException e) { + } catch (EmptyNameException e) { Ui.printDivider("Activity name cannot be empty!"); Log.makeInfoLog("Edit command failed as there was no activity name provided."); } catch (StringIndexOutOfBoundsException | InvalidEditFormatException e) { diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 0086e8ead..120c3bff3 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -21,7 +21,7 @@ public class StartCommand extends Command { /** * Constructor to create a new start command. */ - public StartCommand(String parameters, Scanner scanner) throws EmptyNameException{ + public StartCommand(String parameters, Scanner scanner) throws EmptyNameException { super(parameters); this.scanner = scanner; } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index e5715f0db..94e90b50c 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -63,7 +63,8 @@ public class Parser { * @param scanner scanner object which reads user input * @param activityList the list of activities */ - public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) throws EmptyQueryException, EmptyNameException, NullPointerException, ArrayIndexOutOfBoundsException { + public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) throws EmptyNameException, NullPointerException, + ArrayIndexOutOfBoundsException { Log.makeInfoLog("Starting to parse inputs."); Parser.cleaner = cleaner; /*lastShownList is initialised here to facilitate subsequent delete and edit commands From f3518a1f4ab8c4aeff3e9e72b56dc76022196082 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sun, 29 Mar 2020 14:42:35 +0800 Subject: [PATCH 132/415] Fix style issues --- src/main/java/jikan/Jikan.java | 2 +- src/main/java/jikan/parser/Parser.java | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 6667f990a..d590419d0 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -43,7 +43,7 @@ public class Jikan { /** * Main entry-point for the Jikan application. */ - public static void main(String[] args) throws InvalidTimeFrameException, IOException, EmptyNameException, EmptyQueryException { + public static void main(String[] args) throws InvalidTimeFrameException, IOException, EmptyNameException { ui.printGreeting(); storage = new Storage(DATA_FILE_PATH); cleaner = new StorageCleaner(storage); diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 94e90b50c..dec19f3eb 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -63,8 +63,8 @@ public class Parser { * @param scanner scanner object which reads user input * @param activityList the list of activities */ - public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) throws EmptyNameException, NullPointerException, - ArrayIndexOutOfBoundsException { + public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) throws + EmptyNameException, NullPointerException, ArrayIndexOutOfBoundsException { Log.makeInfoLog("Starting to parse inputs."); Parser.cleaner = cleaner; /*lastShownList is initialised here to facilitate subsequent delete and edit commands From 26c329e513b70b04359ae8a03674ca6c8ab90bae Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 15:17:09 +0800 Subject: [PATCH 133/415] Add text-ui test --- src/main/java/jikan/parser/Parser.java | 3 +- src/main/java/jikan/ui/Ui.java | 10 +- text-ui-test/EXPECTED.TXT | 124 ++++++++++++++++++++++--- text-ui-test/input.txt | 28 +++--- 4 files changed, 134 insertions(+), 31 deletions(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index ac6dbcd69..9f7477ac9 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -53,7 +53,7 @@ public class Parser { public static String[] tokenizedInputs; String instruction; private static Log logger = new Log(); - public static ActivityList lastShownList = new ActivityList(); + //public static ActivityList lastShownList = new ActivityList(); // flag to check if the current activity is a continued one public static int continuedIndex = -1; @@ -64,6 +64,7 @@ public class Parser { * @param activityList the list of activities */ public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) { + Log.makeInfoLog("Starting to parse inputs."); Parser.cleaner = cleaner; /*lastShownList is initialised here to facilitate subsequent delete and edit commands diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 8993813f5..0f6d09d24 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -48,7 +48,7 @@ private static void printTableFormat(ActivityList activityList, int index, boole printIndex = String.valueOf(index + 1) + " "; } if (gotTags) { - System.out.println(String.format("%s %s %-25s %s %-10s %s %-10s %s %-100s", + System.out.println(String.format("%s %s %-25s %s %-10s %s %-10s %s %s", printIndex, "|", activityList.get(index).getName(), "|", duration, "|", activityList.get(index).getDate().toString(), "|", activityList.get(index).getTags().toString())); @@ -67,7 +67,7 @@ public static void printResults(ActivityList resultsList) { if (resultsList.activities.size() > 0) { System.out.println(DIVIDER); System.out.println("Here are the matching activities in your list:\n"); - System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", + System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %s", "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); for (int i = 0; i < resultsList.getSize(); i++) { if (resultsList.get(i).getTags() != null && !resultsList.get(i).getTags().isEmpty()) { @@ -86,7 +86,7 @@ public static void printResults(ActivityList resultsList) { public static void printList(ActivityList activityList) { System.out.println(DIVIDER); System.out.println("Your completed activities:"); - System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", + System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %s", "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); for (int i = 0; i < activityList.getSize(); i++) { if (activityList.get(i).getTags() != null && !activityList.get(i).getTags().isEmpty()) { @@ -104,7 +104,7 @@ public static void printList(ActivityList activityList) { */ public static void printActivityGraph(int interval) { System.out.println(DIVIDER); - System.out.println(String.format("%-25s %s %-100s", "Name", "|", "Duration")); + System.out.println(String.format("%-25s %s %s", "Name", "|", "Duration")); for (int i = 0; i < lastShownList.getSize(); i++) { Activity activity = lastShownList.get(i); Duration duration = activity.getDuration(); @@ -125,7 +125,7 @@ public static void printActivityGraph(int interval) { */ public static void printTagsGraph(HashMap tags) { System.out.println(DIVIDER); - System.out.println(String.format("%-10s %s %-100s", "Tag", "|", "Duration")); + System.out.println(String.format("%-10s %s %s", "Tag", "|", "Duration")); tags.forEach((key,value) -> { double minutes = value.toMinutes() / 10.0; int scaledMinutes = (int) Math.round(minutes); diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 03809fa1c..979958ab5 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,46 +1,142 @@ Jikan ----------------------------------------------------------------- ----------------------------------------------------------------- -Started: activity one +Your completed activities: + | Name | Duration | Date | Tags +1 | study for ges quiz | 03:25:34 | 2020-03-28 | [ges, midterm] +2 | study for 2106 midterm | 06:17:03 | 2020-03-28 | [2106, midterm] +3 | study for german test | 03:00:00 | 2020-03-02 | [german, midterm] +4 | 2106 tutorial 7 | 01:20:12 | 2020-03-18 | [2106] +5 | lab 3 ex1 demo | 02:14:54 | 2020-03-18 | [2106, lab] +6 | lab 3 ex2 | 03:13:14 | 2020-03-19 | [2106, lab] +7 | essay - singapore culture | 02:05:23 | 2020-03-19 | [ges] +8 | study vocab | 04:24:12 | 2020-03-28 | [german, vocab] +9 | essay - food | 01:23:04 | 2020-03-20 | [german] +10 | post-lecture quiz | 00:15:48 | 2020-03-23 | [2113] +11 | 2113 tutorial questions | 00:48:54 | 2020-03-23 | [2113] +12 | 2106 tutorial 8 | 01:23:00 | 2020-03-25 | [2106] +13 | lab 3 ex3 | 07:51:12 | 2020-03-25 | [2106, lab] +14 | debug list feature | 00:50:12 | 2020-03-25 | [2113, tP] +15 | add delete feature | 01:12:04 | 2020-03-26 | [2113, tP] +----------------------------------------------------------------- +----------------------------------------------------------------- +Started: activity +----------------------------------------------------------------- +----------------------------------------------------------------- +Ended: activity +----------------------------------------------------------------- +----------------------------------------------------------------- +Your completed activities: + | Name | Duration | Date | Tags +1 | study for ges quiz | 03:25:34 | 2020-03-28 | [ges, midterm] +2 | study for 2106 midterm | 06:17:03 | 2020-03-28 | [2106, midterm] +3 | study for german test | 03:00:00 | 2020-03-02 | [german, midterm] +4 | 2106 tutorial 7 | 01:20:12 | 2020-03-18 | [2106] +5 | lab 3 ex1 demo | 02:14:54 | 2020-03-18 | [2106, lab] +6 | lab 3 ex2 | 03:13:14 | 2020-03-19 | [2106, lab] +7 | essay - singapore culture | 02:05:23 | 2020-03-19 | [ges] +8 | study vocab | 04:24:12 | 2020-03-28 | [german, vocab] +9 | essay - food | 01:23:04 | 2020-03-20 | [german] +10 | post-lecture quiz | 00:15:48 | 2020-03-23 | [2113] +11 | 2113 tutorial questions | 00:48:54 | 2020-03-23 | [2113] +12 | 2106 tutorial 8 | 01:23:00 | 2020-03-25 | [2106] +13 | lab 3 ex3 | 07:51:12 | 2020-03-25 | [2106, lab] +14 | debug list feature | 00:50:12 | 2020-03-25 | [2113, tP] +15 | add delete feature | 01:12:04 | 2020-03-26 | [2113, tP] +16 | activity | 00:00:00 | 2020-03-29 | [tag] ----------------------------------------------------------------- ----------------------------------------------------------------- -Ended: activity one +There is already an activity with this name. Would you like to continue it? +----------------------------------------------------------------- ----------------------------------------------------------------- +activity was continued ----------------------------------------------------------------- -Started: activity two ----------------------------------------------------------------- +You have aborted the current activity! ----------------------------------------------------------------- -activity two is ongoing! ----------------------------------------------------------------- +There is already an activity with this name. Would you like to continue it? ----------------------------------------------------------------- -Ended: activity two ----------------------------------------------------------------- +Okay then, what else can I do for you? ----------------------------------------------------------------- -activity one was continued ----------------------------------------------------------------- +You have not started any activity! ----------------------------------------------------------------- -You have aborted the current activity! ----------------------------------------------------------------- +You have not started any activity! ----------------------------------------------------------------- -There is already an activity with this name. Would you like to continue it? +----------------------------------------------------------------- +You have deleted activity +----------------------------------------------------------------- +----------------------------------------------------------------- +Here are the matching activities in your list: + + | Name | Duration | Date | Tags +1 | study for 2106 midterm | 06:17:03 | 2020-03-28 | [2106, midterm] +2 | 2106 tutorial 7 | 01:20:12 | 2020-03-18 | [2106] +3 | lab 3 ex1 demo | 02:14:54 | 2020-03-18 | [2106, lab] +4 | lab 3 ex2 | 03:13:14 | 2020-03-19 | [2106, lab] +5 | 2106 tutorial 8 | 01:23:00 | 2020-03-25 | [2106] +6 | lab 3 ex3 | 07:51:12 | 2020-03-25 | [2106, lab] +----------------------------------------------------------------- +----------------------------------------------------------------- +Name | Duration +study for 2106 midterm |************************************** +2106 tutorial 7 |******** +lab 3 ex1 demo |************* +lab 3 ex2 |******************* +2106 tutorial 8 |******** +lab 3 ex3 |*********************************************** ----------------------------------------------------------------- ----------------------------------------------------------------- -activity two was continued +Name | Duration +study for 2106 midterm |******************* +2106 tutorial 7 |**** +lab 3 ex1 demo |******* +lab 3 ex2 |********** +2106 tutorial 8 |**** +lab 3 ex3 |************************ ----------------------------------------------------------------- ----------------------------------------------------------------- -Ended: activity two +Here are the matching activities in your list: + + | Name | Duration | Date | Tags +1 | 2106 tutorial 7 | 01:20:12 | 2020-03-18 | [2106] +2 | 2113 tutorial questions | 00:48:54 | 2020-03-23 | [2113] +3 | 2106 tutorial 8 | 01:23:00 | 2020-03-25 | [2106] ----------------------------------------------------------------- ----------------------------------------------------------------- -Started: activity three +Name | Duration +2106 tutorial 7 |**************** +2113 tutorial questions |********** +2106 tutorial 8 |***************** ----------------------------------------------------------------- ----------------------------------------------------------------- -Ended: activity three +Your completed activities: + | Name | Duration | Date | Tags +1 | study for ges quiz | 03:25:34 | 2020-03-28 | [ges, midterm] +2 | study for 2106 midterm | 06:17:03 | 2020-03-28 | [2106, midterm] +3 | study vocab | 04:24:12 | 2020-03-28 | [german, vocab] +4 | 2106 tutorial 8 | 01:23:00 | 2020-03-25 | [2106] +5 | lab 3 ex3 | 07:51:12 | 2020-03-25 | [2106, lab] +6 | debug list feature | 00:50:12 | 2020-03-25 | [2113, tP] +7 | add delete feature | 01:12:04 | 2020-03-26 | [2113, tP] ----------------------------------------------------------------- ----------------------------------------------------------------- -Started: four +Your completed activities: + | Name | Duration | Date | Tags +1 | study for ges quiz | 03:25:34 | 2020-03-28 | [ges, midterm] +2 | study for 2106 midterm | 06:17:03 | 2020-03-28 | [2106, midterm] +3 | study vocab | 04:24:12 | 2020-03-28 | [german, vocab] ----------------------------------------------------------------- ----------------------------------------------------------------- -Ended: four +Tag | Duration +german |************************** +2106 |************************************** +ges |********************* +vocab |************************** +midterm |********************************************************** ----------------------------------------------------------------- ----------------------------------------------------------------- Bye! See you again. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 751a396a1..662bb9ef5 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,15 +1,21 @@ -start activity one /t tag tag1 tag2 +list +start activity /t tag end -start activity two /t tag2 -start activity 3 -end -continue activity one +list +start activity +yes abort -start activity two -y -end -start activity three /t tag tag1 -end -start four /t tag +start activity +no end +abort +delete activity +filter 2106 +graph 10 +graph 20 +find tutorial +graph 5 +list 25/03/2020 28/03/2020 +list 28/03/2020 +graph tags bye From 94678bb058e7cfc9476312ed3db2f005b8a60466 Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 15:42:38 +0800 Subject: [PATCH 134/415] Fix continue bug --- .../java/jikan/command/ContinueCommand.java | 5 + src/main/java/jikan/command/ListCommand.java | 113 +++++++++++++-- src/main/java/jikan/parser/Parser.java | 132 ++---------------- 3 files changed, 118 insertions(+), 132 deletions(-) diff --git a/src/main/java/jikan/command/ContinueCommand.java b/src/main/java/jikan/command/ContinueCommand.java index fe0187e69..c6606f0db 100644 --- a/src/main/java/jikan/command/ContinueCommand.java +++ b/src/main/java/jikan/command/ContinueCommand.java @@ -25,6 +25,11 @@ public ContinueCommand(String parameters) { @Override public void executeCommand(ActivityList activityList) { try { + if (Parser.startTime != null) { + String line = Parser.activityName + " is ongoing!"; + Ui.printDivider("Could not continue activity due to already ongoing activity."); + return; + } //Parser.parseContinue(activityList); int index = activityList.findActivity(parameters); if (index != -1) { diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index 2b2efaf9c..7f7ec87fb 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -1,16 +1,17 @@ package jikan.command; -import jikan.Log; import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.ui.Ui; -import jikan.parser.Parser; import jikan.exception.InvalidTimeFrameException; +import java.time.DayOfWeek; import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; +import java.time.temporal.TemporalAdjusters; + +import static jikan.Jikan.lastShownList; /** * Represents a command to list all activities in the activity list to the user. @@ -24,17 +25,105 @@ public ListCommand(String parameters) { super(parameters); } + /** + * Parse a list command. The user can specify either a single date or a specific time frame. + * + * @param activityList The activity list to search for matching activities. + */ @Override public void executeCommand(ActivityList activityList) throws InvalidTimeFrameException { - try { - Parser.parseList(activityList); - } catch (InvalidTimeFrameException e) { - Log.makeInfoLog("Specified time range not valid"); - Ui.printDivider("The time range specified is not valid."); - } catch (DateTimeParseException e) { - Log.makeInfoLog("Specified time range was not in the valid format"); - Ui.printDivider("Please input your dates as either yyyy-MM-dd or dd/MM/yyyy.\n" - + " Alternatively, you can use 'day', 'week', or 'month' to get the respective reports."); + // If no time frame is specified, print the entire list + if (parameters == null) { + lastShownList.activities.clear(); + Ui.printList(activityList); + + // Can't do lastShownList = activityList, otherwise we just copy + lastShownList.activities.addAll(activityList.activities); + } else { + listInterval(activityList); + } + } + + private void listInterval(ActivityList activityList) throws InvalidTimeFrameException { + String[] listInputs; + listInputs = parameters.split(" ", 2); + + lastShownList.activities.clear(); + + LocalDate startDate = null; + LocalDate endDate = null; + + // Parse either format + DateTimeFormatter parser = DateTimeFormatter.ofPattern("[dd/MM/yyyy][yyyy-MM-dd]"); + + // Check if the user has given a verbal input + // (User can either say day or daily and get the same output) + switch (listInputs[0]) { + case "day": + // Fallthrough + case "daily": + startDate = LocalDate.now(); + break; + case "week": + // Fallthrough + case "weekly": + // If user has input a specific date to obtain the week from, use that; + // (eg. the input is list week 2020-05-20) + // Otherwise get current date + if (listInputs.length == 2) { + startDate = LocalDate.parse(listInputs[1], parser); + } else { + startDate = LocalDate.now(); + } + + // Set current Monday and Sunday as time range + startDate = startDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); + endDate = startDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); + break; + case "month": + // Fallthrough + case "monthly": + // If user has input a specific date to obtain the month from, use that; + // Otherwise get current date + if (listInputs.length == 2) { + startDate = LocalDate.parse(listInputs[1], parser); + } else { + startDate = LocalDate.now(); + } + + // Set first and last day of month as time range + startDate = startDate.withDayOfMonth(1); + endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); + break; + default: + startDate = LocalDate.parse(listInputs[0], parser); + if (listInputs.length == 2) { + endDate = LocalDate.parse(listInputs[1], parser); + } + break; + } + + // Only one date is specified; return all entries with start date coinciding with that date + if (endDate == null) { + for (Activity i : activityList.activities) { + if (i.getDate().equals(startDate)) { + lastShownList.activities.add(i); + } + } + Ui.printList(lastShownList); + // Both start and end dates are specified + } else { + + if (endDate.isBefore(startDate)) { + throw new InvalidTimeFrameException(); + } + + for (Activity i : activityList.activities) { + if (i.isWithinDateFrame(startDate, endDate)) { + lastShownList.activities.add(i); + } + } + Ui.printList(lastShownList); } } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 7033ee096..f2658e0d3 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -15,29 +15,17 @@ import jikan.command.StartCommand; import jikan.exception.EmptyNameException; -import jikan.activity.Activity; import jikan.activity.ActivityList; -import jikan.exception.EmptyQueryException; -import jikan.exception.InvalidTimeFrameException; -import jikan.exception.NoSuchActivityException; import jikan.storage.StorageCleaner; import jikan.ui.Ui; import jikan.Log; -import java.io.IOException; -import java.time.DayOfWeek; -import java.time.Duration; -import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.DateTimeParseException; -import java.time.temporal.TemporalAdjusters; -import java.util.Arrays; import java.util.HashSet; import java.util.Scanner; import java.util.Set; -import static jikan.Jikan.lastShownList; +import static jikan.Log.makeInfoLog; /** * Represents the object which parses user input to relevant functions for the execution of commands. @@ -48,12 +36,11 @@ public class Parser { public static LocalDateTime endTime = null; public static String activityName = null; public static Set tags = new HashSet<>(); - private static Ui ui = new Ui(); private static StorageCleaner cleaner; public static String[] tokenizedInputs; String instruction; private static Log logger = new Log(); - //public static ActivityList lastShownList = new ActivityList(); + // flag to check if the current activity is a continued one public static int continuedIndex = -1; @@ -65,7 +52,7 @@ public class Parser { */ public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) throws EmptyNameException, NullPointerException, ArrayIndexOutOfBoundsException { - Log.makeInfoLog("Starting to parse inputs."); + makeInfoLog("Starting to parse inputs."); Parser.cleaner = cleaner; /*lastShownList is initialised here to facilitate subsequent delete and edit commands referencing by index of this list. @@ -84,7 +71,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto try { command = new StartCommand(tokenizedInputs[1], scanner); } catch (NullPointerException | ArrayIndexOutOfBoundsException e) { - Log.makeInfoLog("Activity started without activity name"); + makeInfoLog("Activity started without activity name"); Ui.printDivider("Activity name cannot be empty!"); } break; @@ -95,7 +82,11 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto command = new AbortCommand(null); break; case "list": - command = new ListCommand(null); + if (tokenizedInputs.length == 1) { + command = new ListCommand(null); + } else { + command = new ListCommand(tokenizedInputs[1]); + } break; case "delete": try { @@ -123,7 +114,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto command = new EditCommand(tokenizedInputs[1]); } catch (StringIndexOutOfBoundsException | ArrayIndexOutOfBoundsException e) { Ui.printDivider("Activity name cannot be empty!"); - Log.makeInfoLog("Edit command failed as there was no existing activity name provided."); + makeInfoLog("Edit command failed as there was no existing activity name provided."); } break; case "clean": @@ -138,7 +129,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto command = new ContinueCommand(tokenizedInputs[1]); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("Activity name cannot be empty!"); - Log.makeInfoLog("Continue command failed as there was no activity name provided."); + makeInfoLog("Continue command failed as there was no activity name provided."); } break; case "graph": @@ -156,111 +147,12 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto return command; } - /** - * Parse a list command. The user can specify either a single date or a specific time frame. - * - * @param activityList The activity list to search for matching activities. - */ - public static void parseList(ActivityList activityList) throws InvalidTimeFrameException, DateTimeParseException { - - // If no time frame is specified, print the entire list - if (tokenizedInputs.length == 1) { - lastShownList.activities.clear(); - Ui.printList(activityList); - - // Can't do lastShownList = activityList, otherwise we just copy - lastShownList.activities.addAll(activityList.activities); - return; - } - - String[] listInputs; - listInputs = tokenizedInputs[1].split(" ", 2); - - lastShownList.activities.clear(); - - LocalDate startDate = null; - LocalDate endDate = null; - - // Parse either format - DateTimeFormatter parser = DateTimeFormatter.ofPattern("[dd/MM/yyyy][yyyy-MM-dd]"); - - // Check if the user has given a verbal input - // (User can either say day or daily and get the same output) - switch (listInputs[0]) { - case "day": - // Fallthrough - case "daily": - startDate = LocalDate.now(); - break; - case "week": - // Fallthrough - case "weekly": - // If user has input a specific date to obtain the week from, use that; - // (eg. the input is list week 2020-05-20) - // Otherwise get current date - if (listInputs.length == 2) { - startDate = LocalDate.parse(listInputs[1], parser); - } else { - startDate = LocalDate.now(); - } - - // Set current Monday and Sunday as time range - startDate = startDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); - endDate = startDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); - break; - case "month": - // Fallthrough - case "monthly": - // If user has input a specific date to obtain the month from, use that; - // Otherwise get current date - if (listInputs.length == 2) { - startDate = LocalDate.parse(listInputs[1], parser); - } else { - startDate = LocalDate.now(); - } - - // Set first and last day of month as time range - startDate = startDate.withDayOfMonth(1); - endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); - break; - default: - startDate = LocalDate.parse(listInputs[0], parser); - if (listInputs.length == 2) { - endDate = LocalDate.parse(listInputs[1], parser); - } - break; - } - - // Only one date is specified; return all entries with start date coinciding with that date - if (endDate == null) { - for (Activity i : activityList.activities) { - if (i.getDate().equals(startDate)) { - lastShownList.activities.add(i); - } - } - Ui.printList(lastShownList); - // Both start and end dates are specified - } else { - - if (endDate.isBefore(startDate)) { - throw new InvalidTimeFrameException(); - } - - for (Activity i : activityList.activities) { - if (i.isWithinDateFrame(startDate, endDate)) { - lastShownList.activities.add(i); - } - } - Ui.printList(lastShownList); - } - } - /** * Method to parse user inputs that are not recognised. */ private void parseDefault() { String line = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; - Log.makeInfoLog("Invalid command entered"); + makeInfoLog("Invalid command entered"); Ui.printDivider(line); } From 5ccd26e27b9341cfcfd60eb5621a1046b51c5865 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sun, 29 Mar 2020 15:50:53 +0800 Subject: [PATCH 135/415] Add edit tags feature to edit command --- src/main/java/jikan/activity/Activity.java | 2 ++ .../java/jikan/activity/ActivityList.java | 5 ++++ src/main/java/jikan/command/EditCommand.java | 28 +++++++++++++++++-- 3 files changed, 32 insertions(+), 3 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index efd34bfe0..b20fc53d9 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -64,6 +64,8 @@ public Set getTags() { return tags; } + public void setTags(Set tags) { this.tags = tags; } + public LocalDate getDate() { return date; } diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index fef82cf25..e18303298 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -99,6 +99,11 @@ public void updateName(int index, String newName) { fieldChangeUpdateFile(); } + public void updateTags(int index, Set newTags) { + activities.get(index).setTags(newTags); + fieldChangeUpdateFile(); + } + public void delete(int index) { activities.remove(index); deleteUpdateFile(index); diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index 84b487136..d3f4f4aa0 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -6,8 +6,15 @@ import jikan.exception.InvalidEditFormatException; import jikan.exception.NoSuchActivityException; import jikan.parser.Parser; +import jikan.storage.Storage; +import jikan.storage.StorageHandler; import jikan.ui.Ui; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.Set; + /** * Represents a command to edit an activity in the activity list. */ @@ -31,14 +38,30 @@ public void executeCommand(ActivityList activityList) { throw new EmptyNameException(); } int index = activityList.findActivity(Parser.activityName); - String newName = parameters.substring(delimiter + 3); + String newName =""; + String[] tmpTags; + Set newTags = new HashSet(); + if (tagDelim != -1) { + newName = parameters.substring(delimiter + 3, tagDelim - 1); + tmpTags = (parameters.substring(tagDelim + 4).split(" ")); + for (String t : tmpTags) { + newTags.add(t); + } + + } else { + newName = parameters.substring(delimiter + 3); + } + if (index != -1) { if (newName.isEmpty()) { // no new name is provided throw new InvalidEditFormatException(); } else { activityList.updateName(index, newName); - Ui.printDivider("Activity named " + Parser.activityName + " has been updated to " + newName); + if (!newTags.isEmpty()) { + activityList.updateTags(index,newTags); + } + Ui.printDivider("Activity named " + Parser.activityName + " has been updated!"); } } else { // activity is not found @@ -56,5 +79,4 @@ public void executeCommand(ActivityList activityList) { } } - } From efcf8c9bcd2de201b4e69539b5f69901e56cad47 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sun, 29 Mar 2020 15:55:08 +0800 Subject: [PATCH 136/415] Fix style issues for gradle check --- src/main/java/jikan/activity/Activity.java | 4 +++- src/main/java/jikan/command/EditCommand.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index b20fc53d9..dd01f144d 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -64,7 +64,9 @@ public Set getTags() { return tags; } - public void setTags(Set tags) { this.tags = tags; } + public void setTags(Set tags) { + this.tags = tags; + } public LocalDate getDate() { return date; diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index d3f4f4aa0..81dbd953c 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -38,7 +38,7 @@ public void executeCommand(ActivityList activityList) { throw new EmptyNameException(); } int index = activityList.findActivity(Parser.activityName); - String newName =""; + String newName = ""; String[] tmpTags; Set newTags = new HashSet(); if (tagDelim != -1) { From 5c4c19374f5fc9527c638158273398648da778fd Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 16:02:25 +0800 Subject: [PATCH 137/415] Fix style and update tests --- src/main/java/jikan/storage/Storage.java | 10 ++- .../java/jikan/command/AbortCommandTest.java | 12 ++- .../jikan/command/ContinueCommandTest.java | 21 +++-- .../java/jikan/command/DeleteCommandTest.java | 9 ++- .../java/jikan/command/StartCommandTest.java | 77 +++++++++++-------- 5 files changed, 82 insertions(+), 47 deletions(-) diff --git a/src/main/java/jikan/storage/Storage.java b/src/main/java/jikan/storage/Storage.java index e455e939b..d78355d67 100644 --- a/src/main/java/jikan/storage/Storage.java +++ b/src/main/java/jikan/storage/Storage.java @@ -2,7 +2,11 @@ import jikan.activity.ActivityList; -import java.io.*; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.FileNotFoundException; +import java.io.PrintWriter; /** * Class that holds the path and File object for the current data file. @@ -83,6 +87,10 @@ public ActivityList createActivityList() { return activityList; } + /** + * Clears the data file. + * @throws FileNotFoundException If file is not found. + */ public void clearFile() throws FileNotFoundException { PrintWriter writer = new PrintWriter(dataFile); writer.print(""); diff --git a/src/test/java/jikan/command/AbortCommandTest.java b/src/test/java/jikan/command/AbortCommandTest.java index 1c54296b3..3b1ca36ce 100644 --- a/src/test/java/jikan/command/AbortCommandTest.java +++ b/src/test/java/jikan/command/AbortCommandTest.java @@ -1,11 +1,13 @@ package jikan.command; +import jikan.exception.EmptyNameException; +import jikan.exception.InvalidTimeFrameException; import jikan.parser.Parser; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertNull; class AbortCommandTest { @@ -13,7 +15,11 @@ class AbortCommandTest { void executeAbort() { Parser.startTime = LocalDateTime.now(); Command command = new AbortCommand(null); - command.executeCommand(null); - assertNull(Parser.startTime); + try { + command.executeCommand(null); + assertNull(Parser.startTime); + } catch (EmptyNameException | InvalidTimeFrameException e) { + System.out.println("Filed error."); + } } } \ No newline at end of file diff --git a/src/test/java/jikan/command/ContinueCommandTest.java b/src/test/java/jikan/command/ContinueCommandTest.java index 9d914e46b..fa6930488 100644 --- a/src/test/java/jikan/command/ContinueCommandTest.java +++ b/src/test/java/jikan/command/ContinueCommandTest.java @@ -2,6 +2,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; import jikan.exception.InvalidTimeFrameException; import jikan.parser.Parser; import jikan.storage.Storage; @@ -12,7 +13,7 @@ import java.time.LocalDateTime; import java.util.HashSet; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class ContinueCommandTest { ActivityList activities = new ActivityList(); @@ -49,17 +50,23 @@ void executeContinue() throws InterruptedException { Command command = new ContinueCommand(parameters); // Continue Activity2 - command.executeCommand(activities); + try { + command.executeCommand(activities); + } catch (EmptyNameException | InvalidTimeFrameException e) { + System.out.println("Field error."); + } + LocalDateTime startTime = LocalDateTime.now(); assertEquals(startTime.getMinute(), Parser.startTime.getMinute()); - - Duration initial = activities.get(1).getDuration(); - + final Duration initial = activities.get(1).getDuration(); Thread.sleep(2000); - // End Activity2 command = new EndCommand(null); - command.executeCommand(activities); + try { + command.executeCommand(activities); + } catch (EmptyNameException | InvalidTimeFrameException e) { + System.out.println("Field error."); + } Duration elapsed = initial.plus(Duration.between(startTime, LocalDateTime.now())); Duration duration = activities.get(1).getDuration(); assertEquals(elapsed.toSeconds(), duration.toSeconds()); diff --git a/src/test/java/jikan/command/DeleteCommandTest.java b/src/test/java/jikan/command/DeleteCommandTest.java index 872dc7d0b..5f1161b35 100644 --- a/src/test/java/jikan/command/DeleteCommandTest.java +++ b/src/test/java/jikan/command/DeleteCommandTest.java @@ -2,6 +2,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; import jikan.exception.InvalidTimeFrameException; import jikan.storage.Storage; import org.junit.jupiter.api.Test; @@ -11,7 +12,7 @@ import java.time.LocalDateTime; import java.util.HashSet; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class DeleteCommandTest { @@ -48,7 +49,11 @@ void executeDelete() { String parameters = "Activity2"; Command command = new DeleteCommand(parameters); - command.executeCommand(activities); + try { + command.executeCommand(activities); + } catch (EmptyNameException | InvalidTimeFrameException e) { + System.out.println("Field error."); + } assertEquals(activities.get(1).getName(), "Activity3"); assertEquals(activities.getSize(), 2); diff --git a/src/test/java/jikan/command/StartCommandTest.java b/src/test/java/jikan/command/StartCommandTest.java index 00a0ca23c..2513a4198 100644 --- a/src/test/java/jikan/command/StartCommandTest.java +++ b/src/test/java/jikan/command/StartCommandTest.java @@ -2,6 +2,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; import jikan.exception.InvalidTimeFrameException; import jikan.parser.Parser; import jikan.storage.Storage; @@ -14,7 +15,9 @@ import java.util.HashSet; import java.util.Scanner; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertNotNull; class StartCommandTest { ActivityList activities = new ActivityList(); @@ -22,6 +25,7 @@ class StartCommandTest { void populateActivityList() throws InvalidTimeFrameException { activities.storage = new Storage("data/activityList_test.txt"); + activities.activities.clear(); try { activities.storage.clearFile(); } catch (FileNotFoundException e) { @@ -44,54 +48,59 @@ void populateActivityList() throws InvalidTimeFrameException { void executeStart() { try { populateActivityList(); - } catch (InvalidTimeFrameException e) { - System.out.println("Invalid time frame."); - } - Scanner scanner = new Scanner(System.in); - String parameters = "Activity 3 /t tag tag1"; - Command command = new StartCommand(parameters, scanner); + Scanner scanner = new Scanner(System.in); + String parameters = "Activity 3 /t tag tag1"; + Command command = new StartCommand(parameters, scanner); + + HashSet activity3Tags = new HashSet<>(); + activity3Tags.add("tag"); + activity3Tags.add("tag1"); - HashSet activity3Tags = new HashSet<>(); - activity3Tags.add("tag"); - activity3Tags.add("tag1"); + command.executeCommand(activities); + assertNotNull(Parser.startTime); + assertEquals(Parser.activityName, "Activity 3"); + assertEquals(activity3Tags, Parser.tags); - command.executeCommand(activities); - assertNotNull(Parser.startTime); - assertEquals(Parser.activityName, "Activity 3"); - assertEquals(activity3Tags, Parser.tags); + // end started activity to test continue feature + command = new EndCommand(null); + command.executeCommand(activities); + } catch (EmptyNameException | InvalidTimeFrameException e) { + System.out.println("Field error."); + } } @Test void executeStartContinued() { try { populateActivityList(); - } catch (InvalidTimeFrameException e) { - System.out.println("Invalid time frame."); + String data = "Yes"; + System.setIn(new ByteArrayInputStream(data.getBytes())); + Scanner scanner = new Scanner(System.in); + String parameters = "Activity1"; + Command command = new StartCommand(parameters, scanner); + command.executeCommand(activities); + assertEquals(Parser.activityName, "Activity1"); + assertNotNull(Parser.startTime); + } catch (InvalidTimeFrameException | EmptyNameException e) { + System.out.println("Field error."); } - String data = "Yes"; - System.setIn(new ByteArrayInputStream(data.getBytes())); - Scanner scanner = new Scanner(System.in); - String parameters = "Activity1"; - Command command = new StartCommand(parameters, scanner); - command.executeCommand(activities); - assertEquals(Parser.activityName, "Activity1"); - assertNotNull(Parser.startTime); } @Test void executeStartNotContinued() { try { populateActivityList(); - } catch (InvalidTimeFrameException e) { - System.out.println("Invalid time frame."); + String data = "No"; + System.setIn(new ByteArrayInputStream(data.getBytes())); + Scanner scanner = new Scanner(System.in); + String parameters = "Activity1"; + Command command = new StartCommand(parameters, scanner); + command.executeCommand(activities); + assertNull(Parser.startTime); + assertNull(Parser.activityName); + } catch (InvalidTimeFrameException | EmptyNameException e) { + System.out.println("Field error."); } - String data = "No"; - System.setIn(new ByteArrayInputStream(data.getBytes())); - Scanner scanner = new Scanner(System.in); - String parameters = "Activity1"; - Command command = new StartCommand(parameters, scanner); - command.executeCommand(activities); - assertNull(Parser.startTime); - assertNull(Parser.activityName); + } } \ No newline at end of file From 85b8011ba95be0b01bc9913d40dc424aa7b35aef Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 16:17:50 +0800 Subject: [PATCH 138/415] Edit sh file --- text-ui-test/runtest.sh | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh index 8d94369a0..8e55c57ac 100755 --- a/text-ui-test/runtest.sh +++ b/text-ui-test/runtest.sh @@ -1,21 +1,34 @@ #!/usr/bin/env bash -# change to script directory -cd "${0%/*}" +# create bin directory if it doesn't exist +if [ ! -d "../bin" ] +then + mkdir ../bin +fi -cd .. -./gradlew shadowJar +# delete output from previous run +if [ -e "./ACTUAL.TXT" ] +then + rm ACTUAL.TXT +fi -cd text-ui-test +# compile the code into the bin folder, terminates if error occurred +if ! javac -cp ../src -Xlint:none -d ../bin ../src/main/java/jikan/jikan.java +then + echo "********** BUILD FAILURE **********" + exit 1 +fi -java -jar $(find ../build/libs/ -mindepth 1 -print -quit) < input.txt > ACTUAL.TXT +# run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT +java -classpath ../bin Jikan < input.txt > ACTUAL.TXT -diff EXPECTED.TXT ACTUAL.TXT +# compare the output to the expected output +diff ACTUAL.TXT EXPECTED.TXT if [ $? -eq 0 ] then - echo "Test passed!" + echo "Test result: PASSED" exit 0 else - echo "Test failed!" + echo "Test result: FAILED" exit 1 -fi +fi \ No newline at end of file From c035c789d319ebcd4f0b8ebf1e02ca53626db614 Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 16:22:48 +0800 Subject: [PATCH 139/415] no message --- text-ui-test/runtest.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh index 8e55c57ac..cb10d7b21 100755 --- a/text-ui-test/runtest.sh +++ b/text-ui-test/runtest.sh @@ -13,7 +13,7 @@ then fi # compile the code into the bin folder, terminates if error occurred -if ! javac -cp ../src -Xlint:none -d ../bin ../src/main/java/jikan/jikan.java +if ! javac -cp ../src -Xlint:none -d ../bin ../src/main/java/jikan/Jikan.java then echo "********** BUILD FAILURE **********" exit 1 From 2d2a5d6a290f16578f6250c3324e47f1518e3ea4 Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 16:27:03 +0800 Subject: [PATCH 140/415] no message --- .../jikan/command/ContinueCommandTest.java | 40 ++++++++----------- text-ui-test/runtest.sh | 32 +++++---------- 2 files changed, 27 insertions(+), 45 deletions(-) diff --git a/src/test/java/jikan/command/ContinueCommandTest.java b/src/test/java/jikan/command/ContinueCommandTest.java index fa6930488..b5beae495 100644 --- a/src/test/java/jikan/command/ContinueCommandTest.java +++ b/src/test/java/jikan/command/ContinueCommandTest.java @@ -43,33 +43,27 @@ void populateActivityList() throws InvalidTimeFrameException { void executeContinue() throws InterruptedException { try { populateActivityList(); - } catch (InvalidTimeFrameException e) { - System.out.println("Invalid time frame."); - } - String parameters = "Activity2"; - Command command = new ContinueCommand(parameters); - - // Continue Activity2 - try { + String parameters = "Activity2"; + Command command = new ContinueCommand(parameters); command.executeCommand(activities); - } catch (EmptyNameException | InvalidTimeFrameException e) { - System.out.println("Field error."); - } - LocalDateTime startTime = LocalDateTime.now(); - assertEquals(startTime.getMinute(), Parser.startTime.getMinute()); - final Duration initial = activities.get(1).getDuration(); - Thread.sleep(2000); - // End Activity2 - command = new EndCommand(null); - try { - command.executeCommand(activities); + LocalDateTime startTime = LocalDateTime.now(); + assertEquals(startTime.getMinute(), Parser.startTime.getMinute()); + final Duration initial = activities.get(1).getDuration(); + Thread.sleep(2000); + // End Activity2 + command = new EndCommand(null); + try { + command.executeCommand(activities); + } catch (EmptyNameException | InvalidTimeFrameException e) { + System.out.println("Field error."); + } + Duration elapsed = initial.plus(Duration.between(startTime, LocalDateTime.now())); + Duration duration = activities.get(1).getDuration(); + assertEquals(elapsed.toSeconds(), duration.toSeconds()); } catch (EmptyNameException | InvalidTimeFrameException e) { - System.out.println("Field error."); + System.out.println("Error."); } - Duration elapsed = initial.plus(Duration.between(startTime, LocalDateTime.now())); - Duration duration = activities.get(1).getDuration(); - assertEquals(elapsed.toSeconds(), duration.toSeconds()); } } \ No newline at end of file diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh index cb10d7b21..9df3cb510 100755 --- a/text-ui-test/runtest.sh +++ b/text-ui-test/runtest.sh @@ -1,34 +1,22 @@ + #!/usr/bin/env bash -# create bin directory if it doesn't exist -if [ ! -d "../bin" ] -then - mkdir ../bin -fi +# change to script directory +cd "${0%/*}" -# delete output from previous run -if [ -e "./ACTUAL.TXT" ] -then - rm ACTUAL.TXT -fi +cd .. +./gradlew shadowJar -# compile the code into the bin folder, terminates if error occurred -if ! javac -cp ../src -Xlint:none -d ../bin ../src/main/java/jikan/Jikan.java -then - echo "********** BUILD FAILURE **********" - exit 1 -fi +cd text-ui-test -# run the program, feed commands from input.txt file and redirect the output to the ACTUAL.TXT -java -classpath ../bin Jikan < input.txt > ACTUAL.TXT +java -jar $(find ../build/libs/ -mindepth 1 -print -quit) < input.txt > ACTUAL.TXT -# compare the output to the expected output -diff ACTUAL.TXT EXPECTED.TXT +diff EXPECTED.TXT ACTUAL.TXT if [ $? -eq 0 ] then - echo "Test result: PASSED" + echo "Test passed!" exit 0 else - echo "Test result: FAILED" + echo "Test failed!" exit 1 fi \ No newline at end of file From a223046f1590909f2efbe0aff3f60b05d2311a45 Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 16:31:44 +0800 Subject: [PATCH 141/415] no message --- src/test/java/jikan/command/ContinueCommandTest.java | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/test/java/jikan/command/ContinueCommandTest.java b/src/test/java/jikan/command/ContinueCommandTest.java index b5beae495..1d285893e 100644 --- a/src/test/java/jikan/command/ContinueCommandTest.java +++ b/src/test/java/jikan/command/ContinueCommandTest.java @@ -53,11 +53,7 @@ void executeContinue() throws InterruptedException { Thread.sleep(2000); // End Activity2 command = new EndCommand(null); - try { - command.executeCommand(activities); - } catch (EmptyNameException | InvalidTimeFrameException e) { - System.out.println("Field error."); - } + command.executeCommand(activities); Duration elapsed = initial.plus(Duration.between(startTime, LocalDateTime.now())); Duration duration = activities.get(1).getDuration(); assertEquals(elapsed.toSeconds(), duration.toSeconds()); From 595079ea02de87c99cab1edacbad061fce66505c Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 16:34:47 +0800 Subject: [PATCH 142/415] no message --- src/test/java/jikan/command/ContinueCommandTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/jikan/command/ContinueCommandTest.java b/src/test/java/jikan/command/ContinueCommandTest.java index 1d285893e..7566a3f4e 100644 --- a/src/test/java/jikan/command/ContinueCommandTest.java +++ b/src/test/java/jikan/command/ContinueCommandTest.java @@ -56,7 +56,7 @@ void executeContinue() throws InterruptedException { command.executeCommand(activities); Duration elapsed = initial.plus(Duration.between(startTime, LocalDateTime.now())); Duration duration = activities.get(1).getDuration(); - assertEquals(elapsed.toSeconds(), duration.toSeconds()); + assertEquals(elapsed.toMinutes(), duration.toMinutes()); } catch (EmptyNameException | InvalidTimeFrameException e) { System.out.println("Error."); } From 78fcf575cbd39c6db2487fc1c0009a3d9774a7d0 Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 16:37:31 +0800 Subject: [PATCH 143/415] Add data file for testing --- build/libs/data/data.csv | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 build/libs/data/data.csv diff --git a/build/libs/data/data.csv b/build/libs/data/data.csv new file mode 100644 index 000000000..e02585689 --- /dev/null +++ b/build/libs/data/data.csv @@ -0,0 +1,15 @@ +study for ges quiz,2020-03-02T15:23:23.686366300,2020-03-28T17:25:42.085804900,PT3H25M34.0053196S,ges midterm +study for 2106 midterm,2020-03-02T15:23:23.686366300,2020-03-28T17:26:06.091505700,PT6H17M3.0016605S,2106 midterm +study for german test,2020-03-02T15:23:23.686366300,2020-03-02T15:23:25.682028600,PT3H,german midterm +2106 tutorial 7,2020-03-18T15:23:23.686366300,2020-03-18T15:23:25.682028600,PT1H20M12S,2106 +lab 3 ex1 demo,2020-03-18T15:23:23.686366300,2020-03-18T15:23:25.682028600,PT2H14M54S,2106 lab +lab 3 ex2,2020-03-19T15:23:23.686366300,2020-03-19T15:23:25.682028600,PT3H13M14S,2106 lab +essay - singapore culture,2020-03-19T15:23:23.686366300,2020-03-19T15:23:25.682028600,PT2H5M23S,ges +study vocab,2020-03-20T15:23:23.686366300,2020-03-28T15:23:25.682028600,PT4H24M12S,german vocab +essay - food,2020-03-20T15:23:23.686366300,2020-03-20T15:23:25.682028600,PT1H23M4S,german +post-lecture quiz,2020-03-23T15:23:23.686366300,2020-03-23T15:23:25.682028600,PT15M48S,2113 +2113 tutorial questions,2020-03-23T15:23:23.686366300,2020-03-23T15:23:25.682028600,PT48M54S,2113 +2106 tutorial 8,2020-03-25T15:23:23.686366300,2020-03-25T15:23:25.682028600,PT1H23M,2106 +lab 3 ex3,2020-03-25T15:23:23.686366300,2020-03-25T15:23:25.682028600,PT7H51M12S,2106 lab +debug list feature,2020-03-25T15:23:23.686366300,2020-03-25T15:23:25.682028600,PT50M12S,2113 tP +add delete feature,2020-03-26T15:23:23.686366300,2020-03-26T15:23:25.682028600,PT1H12M4S,2113 tP From 2a5602907226361382ff054820b112884a4cb6eb Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 17:01:56 +0800 Subject: [PATCH 144/415] Redo UI test --- build/libs/data/data.csv | 17 +---- text-ui-test/EXPECTED.TXT | 157 ++++++++++++++++---------------------- text-ui-test/input.txt | 39 ++++++---- 3 files changed, 90 insertions(+), 123 deletions(-) diff --git a/build/libs/data/data.csv b/build/libs/data/data.csv index e02585689..59a85e788 100644 --- a/build/libs/data/data.csv +++ b/build/libs/data/data.csv @@ -1,15 +1,2 @@ -study for ges quiz,2020-03-02T15:23:23.686366300,2020-03-28T17:25:42.085804900,PT3H25M34.0053196S,ges midterm -study for 2106 midterm,2020-03-02T15:23:23.686366300,2020-03-28T17:26:06.091505700,PT6H17M3.0016605S,2106 midterm -study for german test,2020-03-02T15:23:23.686366300,2020-03-02T15:23:25.682028600,PT3H,german midterm -2106 tutorial 7,2020-03-18T15:23:23.686366300,2020-03-18T15:23:25.682028600,PT1H20M12S,2106 -lab 3 ex1 demo,2020-03-18T15:23:23.686366300,2020-03-18T15:23:25.682028600,PT2H14M54S,2106 lab -lab 3 ex2,2020-03-19T15:23:23.686366300,2020-03-19T15:23:25.682028600,PT3H13M14S,2106 lab -essay - singapore culture,2020-03-19T15:23:23.686366300,2020-03-19T15:23:25.682028600,PT2H5M23S,ges -study vocab,2020-03-20T15:23:23.686366300,2020-03-28T15:23:25.682028600,PT4H24M12S,german vocab -essay - food,2020-03-20T15:23:23.686366300,2020-03-20T15:23:25.682028600,PT1H23M4S,german -post-lecture quiz,2020-03-23T15:23:23.686366300,2020-03-23T15:23:25.682028600,PT15M48S,2113 -2113 tutorial questions,2020-03-23T15:23:23.686366300,2020-03-23T15:23:25.682028600,PT48M54S,2113 -2106 tutorial 8,2020-03-25T15:23:23.686366300,2020-03-25T15:23:25.682028600,PT1H23M,2106 -lab 3 ex3,2020-03-25T15:23:23.686366300,2020-03-25T15:23:25.682028600,PT7H51M12S,2106 lab -debug list feature,2020-03-25T15:23:23.686366300,2020-03-25T15:23:25.682028600,PT50M12S,2113 tP -add delete feature,2020-03-26T15:23:23.686366300,2020-03-26T15:23:25.682028600,PT1H12M4S,2113 tP +activity 1,2020-03-29T17:01:42.205974400,2020-03-29T17:01:42.314684800,PT0.0069834S,tag +activity 3,2020-03-29T17:01:42.281770800,2020-03-29T17:01:42.287755400,PT0.0059846S,tag1 diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 979958ab5..383b04ace 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,142 +1,113 @@ Jikan ----------------------------------------------------------------- ----------------------------------------------------------------- -Your completed activities: - | Name | Duration | Date | Tags -1 | study for ges quiz | 03:25:34 | 2020-03-28 | [ges, midterm] -2 | study for 2106 midterm | 06:17:03 | 2020-03-28 | [2106, midterm] -3 | study for german test | 03:00:00 | 2020-03-02 | [german, midterm] -4 | 2106 tutorial 7 | 01:20:12 | 2020-03-18 | [2106] -5 | lab 3 ex1 demo | 02:14:54 | 2020-03-18 | [2106, lab] -6 | lab 3 ex2 | 03:13:14 | 2020-03-19 | [2106, lab] -7 | essay - singapore culture | 02:05:23 | 2020-03-19 | [ges] -8 | study vocab | 04:24:12 | 2020-03-28 | [german, vocab] -9 | essay - food | 01:23:04 | 2020-03-20 | [german] -10 | post-lecture quiz | 00:15:48 | 2020-03-23 | [2113] -11 | 2113 tutorial questions | 00:48:54 | 2020-03-23 | [2113] -12 | 2106 tutorial 8 | 01:23:00 | 2020-03-25 | [2106] -13 | lab 3 ex3 | 07:51:12 | 2020-03-25 | [2106, lab] -14 | debug list feature | 00:50:12 | 2020-03-25 | [2113, tP] -15 | add delete feature | 01:12:04 | 2020-03-26 | [2113, tP] +Started: activity 1 ----------------------------------------------------------------- ----------------------------------------------------------------- -Started: activity +Ended: activity 1 ----------------------------------------------------------------- ----------------------------------------------------------------- -Ended: activity +Started: activity 2 ----------------------------------------------------------------- ----------------------------------------------------------------- -Your completed activities: - | Name | Duration | Date | Tags -1 | study for ges quiz | 03:25:34 | 2020-03-28 | [ges, midterm] -2 | study for 2106 midterm | 06:17:03 | 2020-03-28 | [2106, midterm] -3 | study for german test | 03:00:00 | 2020-03-02 | [german, midterm] -4 | 2106 tutorial 7 | 01:20:12 | 2020-03-18 | [2106] -5 | lab 3 ex1 demo | 02:14:54 | 2020-03-18 | [2106, lab] -6 | lab 3 ex2 | 03:13:14 | 2020-03-19 | [2106, lab] -7 | essay - singapore culture | 02:05:23 | 2020-03-19 | [ges] -8 | study vocab | 04:24:12 | 2020-03-28 | [german, vocab] -9 | essay - food | 01:23:04 | 2020-03-20 | [german] -10 | post-lecture quiz | 00:15:48 | 2020-03-23 | [2113] -11 | 2113 tutorial questions | 00:48:54 | 2020-03-23 | [2113] -12 | 2106 tutorial 8 | 01:23:00 | 2020-03-25 | [2106] -13 | lab 3 ex3 | 07:51:12 | 2020-03-25 | [2106, lab] -14 | debug list feature | 00:50:12 | 2020-03-25 | [2113, tP] -15 | add delete feature | 01:12:04 | 2020-03-26 | [2113, tP] -16 | activity | 00:00:00 | 2020-03-29 | [tag] +Ended: activity 2 ----------------------------------------------------------------- ----------------------------------------------------------------- -There is already an activity with this name. Would you like to continue it? +Started: activity 3 ----------------------------------------------------------------- ----------------------------------------------------------------- -activity was continued +activity 3 is ongoing! ----------------------------------------------------------------- ----------------------------------------------------------------- -You have aborted the current activity! +Ended: activity 3 ----------------------------------------------------------------- ----------------------------------------------------------------- -There is already an activity with this name. Would you like to continue it? +activity 1 was continued ----------------------------------------------------------------- ----------------------------------------------------------------- -Okay then, what else can I do for you? +Ended: activity 1 ----------------------------------------------------------------- ----------------------------------------------------------------- -You have not started any activity! +Your completed activities: + | Name | Duration | Date | Tags +1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] +2 | activity 2 | 00:00:00 | 2020-03-29 | [tag] +3 | activity 3 | 00:00:00 | 2020-03-29 | [tag1] ----------------------------------------------------------------- ----------------------------------------------------------------- -You have not started any activity! +Here are the matching activities in your list: + + | Name | Duration | Date | Tags +1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] +2 | activity 2 | 00:00:00 | 2020-03-29 | [tag] ----------------------------------------------------------------- ----------------------------------------------------------------- -You have deleted activity +Here are the matching activities in your list: + + | Name | Duration | Date | Tags +1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] ----------------------------------------------------------------- ----------------------------------------------------------------- Here are the matching activities in your list: | Name | Duration | Date | Tags -1 | study for 2106 midterm | 06:17:03 | 2020-03-28 | [2106, midterm] -2 | 2106 tutorial 7 | 01:20:12 | 2020-03-18 | [2106] -3 | lab 3 ex1 demo | 02:14:54 | 2020-03-18 | [2106, lab] -4 | lab 3 ex2 | 03:13:14 | 2020-03-19 | [2106, lab] -5 | 2106 tutorial 8 | 01:23:00 | 2020-03-25 | [2106] -6 | lab 3 ex3 | 07:51:12 | 2020-03-25 | [2106, lab] +1 | activity 3 | 00:00:00 | 2020-03-29 | [tag1] ----------------------------------------------------------------- ----------------------------------------------------------------- -Name | Duration -study for 2106 midterm |************************************** -2106 tutorial 7 |******** -lab 3 ex1 demo |************* -lab 3 ex2 |******************* -2106 tutorial 8 |******** -lab 3 ex3 |*********************************************** +There is already an activity with this name. Would you like to continue it? ----------------------------------------------------------------- ----------------------------------------------------------------- -Name | Duration -study for 2106 midterm |******************* -2106 tutorial 7 |**** -lab 3 ex1 demo |******* -lab 3 ex2 |********** -2106 tutorial 8 |**** -lab 3 ex3 |************************ +activity 1 was continued ----------------------------------------------------------------- ----------------------------------------------------------------- -Here are the matching activities in your list: - +Ended: activity 1 +----------------------------------------------------------------- +----------------------------------------------------------------- +Your completed activities: | Name | Duration | Date | Tags -1 | 2106 tutorial 7 | 01:20:12 | 2020-03-18 | [2106] -2 | 2113 tutorial questions | 00:48:54 | 2020-03-23 | [2113] -3 | 2106 tutorial 8 | 01:23:00 | 2020-03-25 | [2106] +1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] +2 | activity 2 | 00:00:00 | 2020-03-29 | [tag] +3 | activity 3 | 00:00:00 | 2020-03-29 | [tag1] +----------------------------------------------------------------- +----------------------------------------------------------------- +Please input an integer for the time interval. +If you'd like to graph by tags, enter the command . ----------------------------------------------------------------- ----------------------------------------------------------------- Name | Duration -2106 tutorial 7 |**************** -2113 tutorial questions |********** -2106 tutorial 8 |***************** +activity 1 | +activity 2 | +activity 3 | ----------------------------------------------------------------- ----------------------------------------------------------------- -Your completed activities: - | Name | Duration | Date | Tags -1 | study for ges quiz | 03:25:34 | 2020-03-28 | [ges, midterm] -2 | study for 2106 midterm | 06:17:03 | 2020-03-28 | [2106, midterm] -3 | study vocab | 04:24:12 | 2020-03-28 | [german, vocab] -4 | 2106 tutorial 8 | 01:23:00 | 2020-03-25 | [2106] -5 | lab 3 ex3 | 07:51:12 | 2020-03-25 | [2106, lab] -6 | debug list feature | 00:50:12 | 2020-03-25 | [2113, tP] -7 | add delete feature | 01:12:04 | 2020-03-26 | [2113, tP] +Activity name cannot be empty! ----------------------------------------------------------------- ----------------------------------------------------------------- -Your completed activities: - | Name | Duration | Date | Tags -1 | study for ges quiz | 03:25:34 | 2020-03-28 | [ges, midterm] -2 | study for 2106 midterm | 06:17:03 | 2020-03-28 | [2106, midterm] -3 | study vocab | 04:24:12 | 2020-03-28 | [german, vocab] +You have not started any activity! +----------------------------------------------------------------- +----------------------------------------------------------------- +You have not started any activity! +----------------------------------------------------------------- ----------------------------------------------------------------- +☹ OOPS!!! I'm sorry, but I don't know what that means :-( ----------------------------------------------------------------- -Tag | Duration -german |************************** -2106 |************************************** -ges |********************* -vocab |************************** -midterm |********************************************************** +----------------------------------------------------------------- +No keyword was given. +----------------------------------------------------------------- +----------------------------------------------------------------- +No keyword was given. +----------------------------------------------------------------- +----------------------------------------------------------------- +Activity name cannot be empty! +----------------------------------------------------------------- +----------------------------------------------------------------- +You have deleted activity 2 +----------------------------------------------------------------- +----------------------------------------------------------------- +Your completed activities: + | Name | Duration | Date | Tags +1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] +2 | activity 3 | 00:00:00 | 2020-03-29 | [tag1] ----------------------------------------------------------------- ----------------------------------------------------------------- Bye! See you again. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 662bb9ef5..a10db8b2d 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,21 +1,30 @@ -list -start activity /t tag +start activity 1 /t tag +end +start activity 2 /t tag +end +start activity 3 /t tag1 +start activity 4 +end +continue activity 1 end list -start activity +filter tag +find 1 +find 3 +start activity 1 yes -abort -start activity -no +end +list week +graph +graph 1 +start end abort -delete activity -filter 2106 -graph 10 -graph 20 -find tutorial -graph 5 -list 25/03/2020 28/03/2020 -list 28/03/2020 -graph tags +hi +filter +find +delete +delete activity 2 +list bye + From dff66c153f3a426d8fec7cc8e2d146e09a71b4db Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 17:05:41 +0800 Subject: [PATCH 145/415] Clear data file for test --- build/libs/data/data.csv | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/build/libs/data/data.csv b/build/libs/data/data.csv index 59a85e788..8b1378917 100644 --- a/build/libs/data/data.csv +++ b/build/libs/data/data.csv @@ -1,2 +1 @@ -activity 1,2020-03-29T17:01:42.205974400,2020-03-29T17:01:42.314684800,PT0.0069834S,tag -activity 3,2020-03-29T17:01:42.281770800,2020-03-29T17:01:42.287755400,PT0.0059846S,tag1 + From 1676272bb91675a6d47c31b2e0cb0f3a31727a54 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sun, 29 Mar 2020 18:16:55 +0800 Subject: [PATCH 146/415] Add allocated time v1.0 --- src/main/java/jikan/activity/Activity.java | 11 ++- .../java/jikan/activity/ActivityList.java | 9 ++- src/main/java/jikan/command/EndCommand.java | 1 - src/main/java/jikan/command/StartCommand.java | 78 ++++++++++--------- src/main/java/jikan/parser/Parser.java | 6 +- src/main/java/jikan/ui/Ui.java | 16 ++-- 6 files changed, 67 insertions(+), 54 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index dd01f144d..35801cd83 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -19,6 +19,7 @@ public class Activity { private LocalDateTime startTime; private LocalDateTime endTime; private Duration duration; + private String allocatedTime; private LocalDate date; /** @@ -29,19 +30,19 @@ public class Activity { * @param endTime the time that the activity ended */ public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Duration duration, - Set tags) throws InvalidTimeFrameException { + Set tags, String allocatedTime) throws InvalidTimeFrameException { if (endTime.isBefore(startTime)) { throw new InvalidTimeFrameException(); } - this.name = name.strip(); this.startTime = startTime; this.tags = tags; this.endTime = endTime; this.duration = duration; this.date = endTime.toLocalDate(); + this.allocatedTime = allocatedTime; } public Duration getDuration() { @@ -84,6 +85,10 @@ public void setEndTime(LocalDateTime endTime) { this.endTime = endTime; } + public String getAllocatedTime() { + return this.allocatedTime; + } + /** * Returns true if the Activity's date is within the date range specified (inclusive). * @@ -112,7 +117,7 @@ public String toData() { tagString = tagsToString(tagString); String dataLine = (this.name + "," + this.startTime + "," + this.endTime + "," - + this.duration.toString() + "," + tagString); + + this.duration.toString() + "," + this.allocatedTime + "," + tagString); return dataLine; } diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index e18303298..d90de3292 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -149,7 +149,7 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep Parser.endTime = LocalDateTime.now(); Duration duration = Duration.between(Parser.startTime, Parser.endTime); Activity newActivity = new Activity(Parser.activityName, Parser.startTime, - Parser.endTime, duration, Parser.tags); + Parser.endTime, duration, Parser.tags, Parser.allocatedTime); activityList.add(newActivity); // reset activity info Parser.resetInfo(); @@ -188,9 +188,9 @@ private void parseDataLine(String s) throws InvalidTimeFrameException { Set tags = new HashSet(); // if there are tags - if (strings.size() > 4) { + if (strings.size() > 5) { // remove square brackets surrounding tags - tagStrings = strings.get(4).split(" "); + tagStrings = strings.get(5).split(" "); for (String i : tagStrings) { tags.add(i); } @@ -200,7 +200,8 @@ private void parseDataLine(String s) throws InvalidTimeFrameException { LocalDateTime startTime = LocalDateTime.parse(strings.get(1)); LocalDateTime endTime = LocalDateTime.parse(strings.get(2)); Duration duration = Duration.parse(strings.get(3)); - e = new Activity(strings.get(0), startTime, endTime, duration, tags); + String allocatedTime = strings.get(4); + e = new Activity(strings.get(0), startTime, endTime, duration, tags, allocatedTime); activities.add(e); } } diff --git a/src/main/java/jikan/command/EndCommand.java b/src/main/java/jikan/command/EndCommand.java index 725c2422d..90ffee232 100644 --- a/src/main/java/jikan/command/EndCommand.java +++ b/src/main/java/jikan/command/EndCommand.java @@ -28,7 +28,6 @@ public EndCommand(String parameters) { @Override public void executeCommand(ActivityList activityList) { try { - // Parser.parseEnd(activityList); if (Parser.startTime == null) { throw new NoSuchActivityException(); } else { diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 120c3bff3..f74865184 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -21,41 +21,38 @@ public class StartCommand extends Command { /** * Constructor to create a new start command. */ - public StartCommand(String parameters, Scanner scanner) throws EmptyNameException { + public StartCommand(String parameters, Scanner scanner) { super(parameters); this.scanner = scanner; } @Override - public void executeCommand(ActivityList activityList) throws EmptyNameException { - - try { - // Parser.parseStart(activityList, Jikan.in); - // check if an activity has already been started - if (Parser.startTime != null) { - String line = Parser.activityName + " is ongoing!"; - Log.makeInfoLog("Could not start activity due to already ongoing activity."); - Ui.printDivider(line); + public void executeCommand(ActivityList activityList) { + if (Parser.startTime != null) { + String line = Parser.activityName + " is ongoing!"; + Log.makeInfoLog("Could not start activity due to already ongoing activity."); + Ui.printDivider(line); + } else { + // tags should be reset + assert Parser.tags.isEmpty(); + // check if there exists an activity with this name + int index = activityList.findActivity(parameters); + if (index != -1) { + Ui.printDivider("There is already an activity with this name. Would you like to continue it?"); + continueActivity(activityList, scanner, index); } else { - // tags should be reset - assert Parser.tags.isEmpty(); - - // check if there exists an activity with this name - int index = activityList.findActivity(parameters); - if (index != -1) { - Ui.printDivider("There is already an activity with this name. Would you like to continue it?"); - continueActivity(activityList, scanner, index); - } else { - int delimiter = parameters.indexOf("/t"); - String line = parseActivity(delimiter); + int tagDelimiter = parameters.indexOf("/t"); + int allocateDelimiter = parameters.indexOf("/a"); + try { + String line = parseActivity(tagDelimiter,allocateDelimiter); Parser.startTime = LocalDateTime.now(); Log.makeFineLog("Started: " + Parser.activityName); Ui.printDivider(line); + } catch (EmptyNameException e) { + Log.makeInfoLog("Activity started without activity name"); + Ui.printDivider("Activity name cannot be empty!"); } } - } catch (EmptyNameException e) { - Log.makeInfoLog("Activity started without activity name"); - Ui.printDivider("Activity name cannot be empty!"); } } @@ -84,19 +81,28 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, * * @param delimiter The index of the tag delimiter. */ - private String parseActivity(int delimiter) throws EmptyNameException { - if (delimiter == -1) { - // no tags - Parser.activityName = this.parameters.strip(); - if (Parser.activityName.isEmpty()) { - throw new EmptyNameException(); - } - } else { - Parser.activityName = this.parameters.substring(0, delimiter).strip(); - if (Parser.activityName.isEmpty()) { - throw new EmptyNameException(); + private String parseActivity(int tagDelimiter, int allocateDelimiter) throws EmptyNameException { + String[] tokenizedInputs = this.parameters.split(" ",2); + Parser.activityName = tokenizedInputs[0]; + if (Parser.activityName.isEmpty()) { + throw new EmptyNameException(); + } + if (allocateDelimiter != -1) { + String allocatedTime; + tokenizedInputs[1] = tokenizedInputs[1].substring(3); + int index = tokenizedInputs[1].indexOf(" "); + if (index != -1) { + allocatedTime = tokenizedInputs[1].substring(0,index); + tokenizedInputs[1] = tokenizedInputs[1].substring(index+1); + } else { + allocatedTime = tokenizedInputs[1]; } - String[] tagString = this.parameters.substring(delimiter + 3).split(" "); + Parser.allocatedTime = allocatedTime; + } + if (tagDelimiter != -1) { + String [] tagString; + tokenizedInputs[1] = tokenizedInputs[1].substring(3); + tagString = tokenizedInputs[1].split(" "); Parser.tags.addAll(Arrays.asList(tagString)); } return "Started: " + Parser.activityName; diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index dec19f3eb..0d0b9cbc6 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -47,6 +47,7 @@ public class Parser { public static LocalDateTime startTime = null; public static LocalDateTime endTime = null; public static String activityName = null; + public static String allocatedTime = null; public static Set tags = new HashSet<>(); private static Ui ui = new Ui(); private static StorageCleaner cleaner; @@ -67,10 +68,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto EmptyNameException, NullPointerException, ArrayIndexOutOfBoundsException { Log.makeInfoLog("Starting to parse inputs."); Parser.cleaner = cleaner; - /*lastShownList is initialised here to facilitate subsequent delete and edit commands - referencing by index of this list. - */ - // lastShownList.activities.addAll(activityList.activities); + String userInput = scanner.nextLine(); tokenizedInputs = userInput.split(" ", 2); instruction = tokenizedInputs[0]; diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 8993813f5..88c0265b0 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -12,7 +12,8 @@ public class Ui { public static final String GREETING = "Jikan"; - public static final String DIVIDER = "-----------------------------------------------------------------"; + public static final String DIVIDER = "-------------------------------" + + "------------------------------------------------------------"; /** Prints the logo and greeting so users know the app is working. */ public void printGreeting() { @@ -48,14 +49,17 @@ private static void printTableFormat(ActivityList activityList, int index, boole printIndex = String.valueOf(index + 1) + " "; } if (gotTags) { - System.out.println(String.format("%s %s %-25s %s %-10s %s %-10s %s %-100s", + System.out.println(String.format("%s %s %-25s %s %-10s %s %-10s %s %-10s %s %-100s", printIndex, "|", activityList.get(index).getName(), "|", duration, "|", + activityList.get(index).getAllocatedTime(), "|", activityList.get(index).getDate().toString(), "|", activityList.get(index).getTags().toString())); } else { - System.out.println(String.format("%s %s %-25s %s %-10s %s %-10s %s %s", + System.out.println(String.format("%s %s %-25s %s %-10s %s %-10s %s %-10s %s %s", printIndex, "|", activityList.get(index).getName(), "|", duration, "|", - activityList.get(index).getDate().toString(), "|", "")); + activityList.get(index).getAllocatedTime(), "|", + activityList.get(index).getDate().toString(), "|", + "")); } } @@ -86,8 +90,8 @@ public static void printResults(ActivityList resultsList) { public static void printList(ActivityList activityList) { System.out.println(DIVIDER); System.out.println("Your completed activities:"); - System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-30s", - "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); + System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-10s %s %-30s", + "|", "Name", "|", "Duration", "|", "Allocation", "|", "Date", "|", "Tags")); for (int i = 0; i < activityList.getSize(); i++) { if (activityList.get(i).getTags() != null && !activityList.get(i).getTags().isEmpty()) { printTableFormat(activityList, i, true); From b80634e7b31bd9cb0152003408be0f8a702df625 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sun, 29 Mar 2020 19:10:21 +0800 Subject: [PATCH 147/415] Add allocated time v1.1 --- src/main/java/jikan/activity/Activity.java | 6 ++--- .../java/jikan/activity/ActivityList.java | 2 +- src/main/java/jikan/command/StartCommand.java | 19 ++++++++++++---- src/main/java/jikan/parser/Parser.java | 3 +-- src/main/java/jikan/ui/Ui.java | 22 ++++++++++++------- 5 files changed, 34 insertions(+), 18 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 35801cd83..43a4cab07 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -19,7 +19,7 @@ public class Activity { private LocalDateTime startTime; private LocalDateTime endTime; private Duration duration; - private String allocatedTime; + private Duration allocatedTime; private LocalDate date; /** @@ -30,7 +30,7 @@ public class Activity { * @param endTime the time that the activity ended */ public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Duration duration, - Set tags, String allocatedTime) throws InvalidTimeFrameException { + Set tags, Duration allocatedTime) throws InvalidTimeFrameException { if (endTime.isBefore(startTime)) { throw new InvalidTimeFrameException(); @@ -85,7 +85,7 @@ public void setEndTime(LocalDateTime endTime) { this.endTime = endTime; } - public String getAllocatedTime() { + public Duration getAllocatedTime() { return this.allocatedTime; } diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index d90de3292..28cb87163 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -200,7 +200,7 @@ private void parseDataLine(String s) throws InvalidTimeFrameException { LocalDateTime startTime = LocalDateTime.parse(strings.get(1)); LocalDateTime endTime = LocalDateTime.parse(strings.get(2)); Duration duration = Duration.parse(strings.get(3)); - String allocatedTime = strings.get(4); + Duration allocatedTime = Duration.parse(strings.get(4)); e = new Activity(strings.get(0), startTime, endTime, duration, tags, allocatedTime); activities.add(e); } diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index f74865184..f62adacca 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -1,12 +1,12 @@ package jikan.command; -import jikan.Jikan; import jikan.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; import jikan.parser.Parser; import jikan.ui.Ui; +import java.time.Duration; import java.time.LocalDateTime; import java.util.Arrays; import java.util.Scanner; @@ -87,6 +87,7 @@ private String parseActivity(int tagDelimiter, int allocateDelimiter) throws Emp if (Parser.activityName.isEmpty()) { throw new EmptyNameException(); } + Parser.allocatedTime = Duration.parse("PT0S"); if (allocateDelimiter != -1) { String allocatedTime; tokenizedInputs[1] = tokenizedInputs[1].substring(3); @@ -97,14 +98,24 @@ private String parseActivity(int tagDelimiter, int allocateDelimiter) throws Emp } else { allocatedTime = tokenizedInputs[1]; } - Parser.allocatedTime = allocatedTime; + parseDuration(allocatedTime); } if (tagDelimiter != -1) { - String [] tagString; tokenizedInputs[1] = tokenizedInputs[1].substring(3); - tagString = tokenizedInputs[1].split(" "); + String [] tagString = tokenizedInputs[1].split(" "); Parser.tags.addAll(Arrays.asList(tagString)); } return "Started: " + Parser.activityName; } + + private void parseDuration(String allocatedTime) { + String[] tokenizedInputs; + System.out.println("hello"); + try { + tokenizedInputs = allocatedTime.split("/"); + System.out.println(tokenizedInputs[0]); + } catch (ArrayIndexOutOfBoundsException a) { + Ui.printDivider("Please input in this format HH/MM/SS"); + } + } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 0d0b9cbc6..847cf7dc0 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -37,7 +37,6 @@ import java.util.Scanner; import java.util.Set; -import static jikan.Jikan.lastShownList; /** * Represents the object which parses user input to relevant functions for the execution of commands. @@ -47,7 +46,7 @@ public class Parser { public static LocalDateTime startTime = null; public static LocalDateTime endTime = null; public static String activityName = null; - public static String allocatedTime = null; + public static Duration allocatedTime = null; public static Set tags = new HashSet<>(); private static Ui ui = new Ui(); private static StorageCleaner cleaner; diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 88c0265b0..1cd6e04f4 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -38,12 +38,9 @@ public static void printDivider(String line) { private static void printTableFormat(ActivityList activityList, int index, boolean gotTags) { long durationInNanos = (activityList.get(index).getDuration()).toNanos(); - String duration = String.format("%02d:%02d:%02d", - TimeUnit.NANOSECONDS.toHours(durationInNanos), - TimeUnit.NANOSECONDS.toMinutes(durationInNanos) - - TimeUnit.HOURS.toMinutes(TimeUnit.NANOSECONDS.toHours(durationInNanos)), - TimeUnit.NANOSECONDS.toSeconds(durationInNanos) - - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(durationInNanos))); + long allocatedTimeInNanos = (activityList.get(index).getAllocatedTime()).toNanos(); + String duration = formatString(durationInNanos); + String allocatedTime = formatString(allocatedTimeInNanos); String printIndex = String.valueOf(index + 1); if (index < 9) { printIndex = String.valueOf(index + 1) + " "; @@ -51,18 +48,27 @@ private static void printTableFormat(ActivityList activityList, int index, boole if (gotTags) { System.out.println(String.format("%s %s %-25s %s %-10s %s %-10s %s %-10s %s %-100s", printIndex, "|", activityList.get(index).getName(), "|", duration, "|", - activityList.get(index).getAllocatedTime(), "|", + allocatedTime, "|", activityList.get(index).getDate().toString(), "|", activityList.get(index).getTags().toString())); } else { System.out.println(String.format("%s %s %-25s %s %-10s %s %-10s %s %-10s %s %s", printIndex, "|", activityList.get(index).getName(), "|", duration, "|", - activityList.get(index).getAllocatedTime(), "|", + allocatedTime, "|", activityList.get(index).getDate().toString(), "|", "")); } } + private static String formatString(long timeInNanos) { + return String.format("%02d:%02d:%02d", + TimeUnit.NANOSECONDS.toHours(timeInNanos), + TimeUnit.NANOSECONDS.toMinutes(timeInNanos) + - TimeUnit.HOURS.toMinutes(TimeUnit.NANOSECONDS.toHours(timeInNanos)), + TimeUnit.NANOSECONDS.toSeconds(timeInNanos) + - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(timeInNanos))); + } + /** * Prints the results from a 'find' or 'filter' command. * @param resultsList the list of activities to print From ee9bdac303ff311b117cdb035e89303b410b9e73 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sun, 29 Mar 2020 19:31:04 +0800 Subject: [PATCH 148/415] Add allocate time v2.0 --- src/main/java/jikan/command/StartCommand.java | 30 +++++++++++++------ .../exception/WrongDateFormatException.java | 4 +++ 2 files changed, 25 insertions(+), 9 deletions(-) create mode 100644 src/main/java/jikan/exception/WrongDateFormatException.java diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index f62adacca..8f85cbe78 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -3,6 +3,7 @@ import jikan.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; +import jikan.exception.WrongDateFormatException; import jikan.parser.Parser; import jikan.ui.Ui; @@ -51,6 +52,9 @@ public void executeCommand(ActivityList activityList) { } catch (EmptyNameException e) { Log.makeInfoLog("Activity started without activity name"); Ui.printDivider("Activity name cannot be empty!"); + } catch (WrongDateFormatException w) { + Log.makeInfoLog("Wrong format for allocated time."); + Ui.printDivider("Please input in this format HH/MM/SS"); } } } @@ -81,7 +85,8 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, * * @param delimiter The index of the tag delimiter. */ - private String parseActivity(int tagDelimiter, int allocateDelimiter) throws EmptyNameException { + private String parseActivity(int tagDelimiter, int allocateDelimiter) throws EmptyNameException, + WrongDateFormatException{ String[] tokenizedInputs = this.parameters.split(" ",2); Parser.activityName = tokenizedInputs[0]; if (Parser.activityName.isEmpty()) { @@ -98,7 +103,11 @@ private String parseActivity(int tagDelimiter, int allocateDelimiter) throws Emp } else { allocatedTime = tokenizedInputs[1]; } - parseDuration(allocatedTime); + try { + parseDuration(allocatedTime); + } catch (WrongDateFormatException w) { + throw new WrongDateFormatException(); + } } if (tagDelimiter != -1) { tokenizedInputs[1] = tokenizedInputs[1].substring(3); @@ -108,14 +117,17 @@ private String parseActivity(int tagDelimiter, int allocateDelimiter) throws Emp return "Started: " + Parser.activityName; } - private void parseDuration(String allocatedTime) { + private void parseDuration(String allocatedTime) throws WrongDateFormatException { String[] tokenizedInputs; - System.out.println("hello"); - try { - tokenizedInputs = allocatedTime.split("/"); - System.out.println(tokenizedInputs[0]); - } catch (ArrayIndexOutOfBoundsException a) { - Ui.printDivider("Please input in this format HH/MM/SS"); + tokenizedInputs = allocatedTime.split("/"); + if (tokenizedInputs.length != 3) { + throw new WrongDateFormatException(); + } else { + String hours = tokenizedInputs[0] + "H"; + String minutes = tokenizedInputs[1] + "M"; + String seconds = tokenizedInputs[2] + "S"; + String duration = "PT" + hours + minutes + seconds; + Parser.allocatedTime = Duration.parse(duration); } } } diff --git a/src/main/java/jikan/exception/WrongDateFormatException.java b/src/main/java/jikan/exception/WrongDateFormatException.java new file mode 100644 index 000000000..7fd7aaf7b --- /dev/null +++ b/src/main/java/jikan/exception/WrongDateFormatException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class WrongDateFormatException extends Exception { +} From 7b4d1710208371cc0b3095f8e5f9901bfe67b3d3 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sun, 29 Mar 2020 19:55:36 +0800 Subject: [PATCH 149/415] Made some Junit changes --- src/main/java/jikan/command/StartCommand.java | 4 ++-- src/main/java/jikan/ui/Ui.java | 4 ++-- src/test/java/jikan/activity/ActivityListTest.java | 7 ++++--- src/test/java/jikan/activity/ActivityTest.java | 3 ++- src/test/java/jikan/command/ContinueCommandTest.java | 7 ++++--- src/test/java/jikan/command/DeleteCommandTest.java | 7 ++++--- src/test/java/jikan/command/StartCommandTest.java | 7 ++++--- 7 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index a48a7a2df..20194fbb1 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -88,7 +88,7 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, * @param allocateDelimiter the index of the allocation delimiter. */ private String parseActivity(int tagDelimiter, int allocateDelimiter) throws EmptyNameException, - WrongDateFormatException{ + WrongDateFormatException { String[] tokenizedInputs = this.parameters.split(" ",2); Parser.activityName = tokenizedInputs[0]; if (Parser.activityName.isEmpty()) { @@ -101,7 +101,7 @@ private String parseActivity(int tagDelimiter, int allocateDelimiter) throws Emp int index = tokenizedInputs[1].indexOf(" "); if (index != -1) { allocatedTime = tokenizedInputs[1].substring(0,index); - tokenizedInputs[1] = tokenizedInputs[1].substring(index+1); + tokenizedInputs[1] = tokenizedInputs[1].substring(index + 1); } else { allocatedTime = tokenizedInputs[1]; } diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index f51beb0bc..dfd4da569 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -12,8 +12,8 @@ public class Ui { public static final String GREETING = "Jikan"; - public static final String DIVIDER = "-------------------------------" + - "------------------------------------------------------------"; + public static final String DIVIDER = "-------------------------------" + + "------------------------------------------------------------"; /** Prints the logo and greeting so users know the app is working. */ public void printGreeting() { diff --git a/src/test/java/jikan/activity/ActivityListTest.java b/src/test/java/jikan/activity/ActivityListTest.java index 01eaba0d3..c0ffb75b8 100644 --- a/src/test/java/jikan/activity/ActivityListTest.java +++ b/src/test/java/jikan/activity/ActivityListTest.java @@ -22,9 +22,10 @@ void getIndex() throws InvalidTimeFrameException { LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); Duration duration = Duration.between(startTime, endTime); - Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags); - Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags); - Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags); + Duration allocatedTime = Duration.parse("PT0S"); + Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags, allocatedTime); + Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags, allocatedTime); + Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags, allocatedTime); activities.add(activity1); activities.add(activity2); activities.add(activity3); diff --git a/src/test/java/jikan/activity/ActivityTest.java b/src/test/java/jikan/activity/ActivityTest.java index 0e074e58d..9cc9a302f 100644 --- a/src/test/java/jikan/activity/ActivityTest.java +++ b/src/test/java/jikan/activity/ActivityTest.java @@ -20,7 +20,8 @@ class ActivityTest { LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); Duration duration = Duration.between(startTime, endTime); - activity = new Activity("Activity", startTime, endTime, duration, tags); + Duration allocatedTime = Duration.parse("PT0S"); + activity = new Activity("Activity", startTime, endTime, duration, tags, allocatedTime); } catch (InvalidTimeFrameException e) { e.printStackTrace(); } diff --git a/src/test/java/jikan/command/ContinueCommandTest.java b/src/test/java/jikan/command/ContinueCommandTest.java index 7566a3f4e..911b79384 100644 --- a/src/test/java/jikan/command/ContinueCommandTest.java +++ b/src/test/java/jikan/command/ContinueCommandTest.java @@ -31,9 +31,10 @@ void populateActivityList() throws InvalidTimeFrameException { LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); Duration duration = Duration.between(startTime, endTime); - Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags); - Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags); - Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags); + Duration allocatedTime = Duration.parse("PT0S"); + Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags, allocatedTime); + Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags, allocatedTime); + Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags, allocatedTime); activities.add(activity1); activities.add(activity2); activities.add(activity3); diff --git a/src/test/java/jikan/command/DeleteCommandTest.java b/src/test/java/jikan/command/DeleteCommandTest.java index 5f1161b35..2a424d15c 100644 --- a/src/test/java/jikan/command/DeleteCommandTest.java +++ b/src/test/java/jikan/command/DeleteCommandTest.java @@ -31,9 +31,10 @@ void populateActivityList() throws InvalidTimeFrameException { LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); Duration duration = Duration.between(startTime, endTime); - Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags); - Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags); - Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags); + Duration allocatedTime = Duration.parse("PT0S"); + Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags, allocatedTime); + Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags, allocatedTime); + Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags, allocatedTime); activities.add(activity1); activities.add(activity2); activities.add(activity3); diff --git a/src/test/java/jikan/command/StartCommandTest.java b/src/test/java/jikan/command/StartCommandTest.java index 2513a4198..f88b6f128 100644 --- a/src/test/java/jikan/command/StartCommandTest.java +++ b/src/test/java/jikan/command/StartCommandTest.java @@ -36,9 +36,10 @@ void populateActivityList() throws InvalidTimeFrameException { LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); Duration duration = Duration.between(startTime, endTime); - Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags); - Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags); - Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags); + Duration allocatedTime = Duration.parse("PT0S"); + Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags, allocatedTime); + Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags, allocatedTime); + Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags, allocatedTime); activities.add(activity1); activities.add(activity2); activities.add(activity3); From b82f6fa509d31fd68795e95ff80f50da369d4dec Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sun, 29 Mar 2020 20:56:37 +0800 Subject: [PATCH 150/415] docs and user guide --- docs/UserGuide.md | 22 +++++++++++++++++++ .../java/jikan/command/FilterCommand.java | 11 ++++++++-- src/main/java/jikan/command/FindCommand.java | 9 +++++++- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 81da234ff..93bb523db 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -14,6 +14,28 @@ ## Features {Give detailed description of each feature} +### Finding and Filtering Activities + +## Finding Activities by Name: `find` +Users can request for a sub-list of activities that has names containing a given keyword to be printed. + +Format: `find KEYWORD` + +## Filtering Activities by Tags: `filter` +Users can request for a sub-list of activities that has specific tags. + +Format: `filter TAGNAME1 TAGNAME2` + +## Further Finding/Filtering: `-s` +Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on his/her needs. +This is can be particularly useful when the user wants to generate a `graph`. + +This flag applies to `find` and `filter` commands only. + +Format: +* `filter -s TAGNAME1 TAGNAME2` +* `find -s keyword` + ### Adding a to-do: `todo` Adds a to-do item to the list of to-dos. diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index c378adfd0..5f840d992 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -12,7 +12,7 @@ import static jikan.parser.Parser.tokenizedInputs; /** - * Represents a command to filter activities based on user-specified criterias. + * Represents a command to filter activities by specified tags. */ public class FilterCommand extends Command { @@ -24,7 +24,7 @@ public FilterCommand(String parameters) { } /** - * Shows the user all past activities that has tags which match the keywords queried by the user. + * Shows the user all past activities that has tags which match the one or more keywords queried by the user. * @param activityList the activity list to search for matching activities */ @Override @@ -36,6 +36,10 @@ public void executeCommand(ActivityList activityList) { } } + /** + * Filters activities by tags from the entire list of activities. + * @param activityList the full list of activities + */ private void filterFullList(ActivityList activityList) { try { String query = parameters; @@ -55,6 +59,9 @@ private void filterFullList(ActivityList activityList) { } } + /** + * Filter activities by tags based on the last shown list. + */ private void filterSubList() { try { String query = parameters.replace("-s ", ""); diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index d7787d3d8..e30dc0fd3 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -12,7 +12,7 @@ import static jikan.parser.Parser.tokenizedInputs; /** - * Represents a command to find activities in the activity list. + * Represents a command to find activities by name. */ public class FindCommand extends Command { /** @@ -35,6 +35,10 @@ public void executeCommand(ActivityList activityList) { } } + /** + * Find activities which has name containing the keyword from the entire list. + * @param activityList full like of activities + */ private void findFullList(ActivityList activityList) { try { // Parser.parseFind(activityList, lastShownList, tokenizedInputs[1]); @@ -55,6 +59,9 @@ private void findFullList(ActivityList activityList) { } } + /** + * Find activities which has name matching the keyword from the last shown list. + */ private void findSubList() { try { String keyword = parameters.replace("-s ", ""); From 7b8689064ace5527872366dd24d922a3b57f2ac6 Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 21:16:53 +0800 Subject: [PATCH 151/415] Fix duplicate activity bug --- src/main/java/jikan/command/StartCommand.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 20194fbb1..ac5427df0 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -38,7 +38,9 @@ public void executeCommand(ActivityList activityList) { // tags should be reset assert Parser.tags.isEmpty(); // check if there exists an activity with this name - int index = activityList.findActivity(parameters); + String[] tokenizedInputs = this.parameters.split(" ",2); + String name = tokenizedInputs[0]; + int index = activityList.findActivity(name); if (index != -1) { Ui.printDivider("There is already an activity with this name. Would you like to continue it?"); continueActivity(activityList, scanner, index); From c40d1b08ee7474fbaa53f46d48a82d452abb5c7b Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sun, 29 Mar 2020 21:58:34 +0800 Subject: [PATCH 152/415] Fix some Junit issues --- src/main/java/jikan/command/StartCommand.java | 30 +++++++++++++------ src/main/java/jikan/ui/Ui.java | 2 +- text-ui-test/EXPECTED.TXT | 2 +- text-ui-test/input.txt | 3 +- text-ui-test/runtest.sh | 1 - 5 files changed, 24 insertions(+), 14 deletions(-) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index ac5427df0..9f8598745 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -91,21 +91,22 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, */ private String parseActivity(int tagDelimiter, int allocateDelimiter) throws EmptyNameException, WrongDateFormatException { - String[] tokenizedInputs = this.parameters.split(" ",2); - Parser.activityName = tokenizedInputs[0]; + String activityName = getActivityName(tagDelimiter, allocateDelimiter); + String activityInfo = this.parameters.substring(activityName.length() + 1); + Parser.activityName = activityName; if (Parser.activityName.isEmpty()) { throw new EmptyNameException(); } Parser.allocatedTime = Duration.parse("PT0S"); if (allocateDelimiter != -1) { String allocatedTime; - tokenizedInputs[1] = tokenizedInputs[1].substring(3); - int index = tokenizedInputs[1].indexOf(" "); + activityInfo = activityInfo.substring(3); + int index = activityInfo.indexOf(" "); if (index != -1) { - allocatedTime = tokenizedInputs[1].substring(0,index); - tokenizedInputs[1] = tokenizedInputs[1].substring(index + 1); + allocatedTime = activityInfo.substring(0,index); + activityInfo = activityInfo.substring(index + 1); } else { - allocatedTime = tokenizedInputs[1]; + allocatedTime = activityInfo; } try { parseDuration(allocatedTime); @@ -114,13 +115,24 @@ private String parseActivity(int tagDelimiter, int allocateDelimiter) throws Emp } } if (tagDelimiter != -1) { - tokenizedInputs[1] = tokenizedInputs[1].substring(3); - String [] tagString = tokenizedInputs[1].split(" "); + activityInfo = activityInfo.substring(3); + String [] tagString = activityInfo.split(" "); Parser.tags.addAll(Arrays.asList(tagString)); } return "Started: " + Parser.activityName; } + private String getActivityName(int tagDelimiter, int allocateDelimiter) { + if (tagDelimiter != -1) { + return this.parameters.substring(0,tagDelimiter).strip(); + } else if (allocateDelimiter != -1) { + return this.parameters.substring(0,allocateDelimiter).strip(); + } else { + return this.parameters; + } + + } + private void parseDuration(String allocatedTime) throws WrongDateFormatException { String[] tokenizedInputs; tokenizedInputs = allocatedTime.split("/"); diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index dfd4da569..259357afe 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -97,7 +97,7 @@ public static void printList(ActivityList activityList) { System.out.println(DIVIDER); System.out.println("Your completed activities:"); System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-10s %s %-30s", - "|", "Name", "|", "Duration", "|", "Allocation", "|", "Date", "|", "Tags")); + "|", "Name", "|", "Duration", "|", "Target", "|", "Date", "|", "Tags")); for (int i = 0; i < activityList.getSize(); i++) { if (activityList.get(i).getTags() != null && !activityList.get(i).getTags().isEmpty()) { printTableFormat(activityList, i, true); diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 383b04ace..2ef45b733 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -111,4 +111,4 @@ Your completed activities: ----------------------------------------------------------------- ----------------------------------------------------------------- Bye! See you again. ------------------------------------------------------------------ +----------------------------------------------------------------- \ No newline at end of file diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index a10db8b2d..4d42bc6a2 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -26,5 +26,4 @@ find delete delete activity 2 list -bye - +bye \ No newline at end of file diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh index 9df3cb510..29fc8b54d 100755 --- a/text-ui-test/runtest.sh +++ b/text-ui-test/runtest.sh @@ -1,4 +1,3 @@ - #!/usr/bin/env bash # change to script directory From 8b23057436b617ae61d9600eb743036afe6c670f Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sun, 29 Mar 2020 22:35:34 +0800 Subject: [PATCH 153/415] Bug fixing for Text-Ui --- src/main/java/META-INF/MANIFEST.MF | 3 +++ src/main/java/jikan/command/StartCommand.java | 12 ++++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 src/main/java/META-INF/MANIFEST.MF diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 000000000..13c7d5786 --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: jikan.Jikan + diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 9f8598745..8efc9f894 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -37,10 +37,9 @@ public void executeCommand(ActivityList activityList) { } else { // tags should be reset assert Parser.tags.isEmpty(); + // check if there exists an activity with this name - String[] tokenizedInputs = this.parameters.split(" ",2); - String name = tokenizedInputs[0]; - int index = activityList.findActivity(name); + int index = activityList.findActivity(parameters); if (index != -1) { Ui.printDivider("There is already an activity with this name. Would you like to continue it?"); continueActivity(activityList, scanner, index); @@ -92,8 +91,13 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, private String parseActivity(int tagDelimiter, int allocateDelimiter) throws EmptyNameException, WrongDateFormatException { String activityName = getActivityName(tagDelimiter, allocateDelimiter); - String activityInfo = this.parameters.substring(activityName.length() + 1); Parser.activityName = activityName; + String activityInfo; + if (tagDelimiter != -1 || allocateDelimiter != -1) { + activityInfo = this.parameters.substring(activityName.length() + 1); + } else { + return "Started: " + Parser.activityName; + } if (Parser.activityName.isEmpty()) { throw new EmptyNameException(); } From ecdd9e75590cc3389b4880d88c8852334dbc68ff Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sun, 29 Mar 2020 22:40:21 +0800 Subject: [PATCH 154/415] Change text-ui-test --- text-ui-test/EXPECTED.TXT | 118 +++++++++++++++++++------------------- 1 file changed, 59 insertions(+), 59 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 2ef45b733..a8ba99f87 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,114 +1,114 @@ Jikan ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Started: activity 1 ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Ended: activity 1 ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Started: activity 2 ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Ended: activity 2 ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Started: activity 3 ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- activity 3 is ongoing! ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Ended: activity 3 ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- activity 1 was continued ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Ended: activity 1 ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Your completed activities: | Name | Duration | Date | Tags 1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] 2 | activity 2 | 00:00:00 | 2020-03-29 | [tag] 3 | activity 3 | 00:00:00 | 2020-03-29 | [tag1] ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Here are the matching activities in your list: | Name | Duration | Date | Tags 1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] 2 | activity 2 | 00:00:00 | 2020-03-29 | [tag] ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Here are the matching activities in your list: | Name | Duration | Date | Tags 1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Here are the matching activities in your list: | Name | Duration | Date | Tags 1 | activity 3 | 00:00:00 | 2020-03-29 | [tag1] ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- There is already an activity with this name. Would you like to continue it? ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- activity 1 was continued ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Ended: activity 1 ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Your completed activities: | Name | Duration | Date | Tags 1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] 2 | activity 2 | 00:00:00 | 2020-03-29 | [tag] 3 | activity 3 | 00:00:00 | 2020-03-29 | [tag1] ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Please input an integer for the time interval. If you'd like to graph by tags, enter the command . ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Name | Duration activity 1 | activity 2 | activity 3 | ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Activity name cannot be empty! ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- You have not started any activity! ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- You have not started any activity! ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- ☹ OOPS!!! I'm sorry, but I don't know what that means :-( ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- No keyword was given. ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- No keyword was given. ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Activity name cannot be empty! ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- You have deleted activity 2 ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Your completed activities: | Name | Duration | Date | Tags 1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] 2 | activity 3 | 00:00:00 | 2020-03-29 | [tag1] ------------------------------------------------------------------ ------------------------------------------------------------------ +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- Bye! See you again. ------------------------------------------------------------------ \ No newline at end of file +------------------------------------------------------------------------------------------- From 222516e73390e39ed470f4450747bbf126b8a5f9 Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 22:43:50 +0800 Subject: [PATCH 155/415] Change DG link in README and add commands to UG --- docs/README.md | 2 +- docs/UserGuide.md | 108 +++++++++++++++++++++++++++++++++++++++------- 2 files changed, 93 insertions(+), 17 deletions(-) diff --git a/docs/README.md b/docs/README.md index 5fda977aa..bbcc99c1e 100644 --- a/docs/README.md +++ b/docs/README.md @@ -4,5 +4,5 @@ Useful links: * [User Guide](UserGuide.md) -* [Developer Guide](UserGuide.md) +* [Developer Guide](DeveloperGuide.md) * [About Us](AboutUs.md) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 81da234ff..273499347 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -2,32 +2,112 @@ ## Introduction -{Give a product intro} ## Quick Start {Give steps to get started quickly} 1. Ensure that you have Java 11 or above installed. -1. Down the latest version of `Duke` from [here](http://link.to/duke). +2. Down the latest version of `Jikan` from [here](https://github.com/AY1920S2-CS2113-T15-1/tp/releases). +3. Save the Jikan.jar file into an empty folder +4. Open a command window in that folder +5. Run the command java -jar duke.jar -## Features -{Give detailed description of each feature} +## Commands +### Starting an activity: `start` +**Usage:** Starts recording the time for a new activity. -### Adding a to-do: `todo` -Adds a to-do item to the list of to-dos. +**Format:** `start ACTIVITY_NAME /a ALLOCATED_TIME /t TAGS` + +* `ACTIVITY_NAME` can contains spaces and must be less than 25 characters. +* `ACTIVITY_NAME` must also be unique (should the user start an already existing activity, the option to `continue` will be given). +* `ALLOCATED_TIME` should be of the format [HH/MM/SS]. +* `TAGS` are separated by spaces. +* `ALLOCATED_TIME` and `TAGS` are optional. + +**Example:** +`start CS1010 assignment /a 01/30/00 /t CS1010 core` +`start GER1000 quiz /t GER GEmod` +`start revision` -Format: `todo n/TODO_NAME d/DEADLINE` +### Continuing an activity: `continue` +**Usage:** Continues recording the time of an activity that you have previously started. -* The `DEADLINE` can be in a natural language format. -* The `TODO_NAME` cannot contain punctuation. +**Format:** `continue ACTIVITY_NAME` +* `ACTIVITY_NAME` must be an existing activity in the activity list. -Example of usage: +**Example:** +`continue CS1010 assignment` -`todo n/Write the rest of the User Guide d/next week` +### Ending an activity: `end` +**Usage:** Stops recording the time for an ongoing activity and stores it into the activity list. -`todo n/Refactor the User Guide to remove passive voice d/13/04/2020` +**Format:** `end` +* An activity must be started or continued before it can be ended. + +### Aborting an activity: `abort` +**Usage:** Aborts the current activity and does not save it to the activity list. + +**Format:** `abort` + +### Deleteing an activity: `delete` +**Usage:** Deletes an activity in the activity list. + +**Format:** `delete ACTIVITY_NAME` + +### List activities: `list` +**Usage:** Displays a list of the completed activities. + +**Format:** `list TIME_PERIOD` +* If no `TIME_PERIOD` is given, all activities will be listed. +* `TIME_PERIOD` should be of the format [dd/MM/yyyy] or [yyyy-MM-dd] +* `TIME_PERIOD` can either be a specific date or over a range. + +**Example:** +`list` List all activities. +`list month` or `list monthly` Lists all activities in the current month. +`list week` or `list weekly` List all activities in the current week. +`list day` or `list daily` List all activities in the current day. +`list 01/01/2020` or `list 2020-01-01` List all activities on 1 Jan 2020. +`list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. + +### Graph the duration of your completed activities: `graph` +**Usage:** Gives a visual representation of the duration of all your past activities so that you can easily see what took up the most of your time. + +**Format:** `graph SCALE` or `graph tags` + +* Parameters for graph are either `SCALE` or `tags`. +* `SCALE` is the scale of the graph in minutes (i.e. how many minutes each unit in the graph represents) and should be an integer value. +* `graph tags` will graph the cumulative duration of individual tags (each unit represents 10 minutes) +* The graph will be based on the latest list displayed on the command prompt. + +**Example:** +`graph 10` + +## Command Summary + +### Commands at a glance +|Command|Format |Usage| +|---|---|---| +|start | `start ACTIVITY_NAME /a ALLOCATED_TIME /t TAGS` |Starts an activity +|continue|`continue ACTIVITY_NAME`|Continues an actvity +|end|`end`|Ends an activity +|abort|`abort`| Aborts an activity +|delete|`delete ACTIVITY_NAME` | Deletes an activity +|edit name|`edit ACTIVITY_NAME /e NEW_NAME`|Edits activity name +|edit tags||Edits activity tags +|list all|`list`|Lists all completed activities +|list date|`list DD/MM/YYYY` |List all activities on that day +|list range|`list DD/MM/YYYY DD/MM/YYYY`|List activities within the range +|list day|`list day` | List all activities today. +|list week|`list week`|List all activities this week. +|list month|`list month`| List all activities this month. +|filter|`filter TAG_NAME`|List all activities with tag `TAG_NAME` +|find|`find KEYWORD`|List all activities containing `KEYWORD` +|graph|`graph SCALE`|Graphs the duration of the activities +|graph tags|`graph tags`|Graphs the duration of the tags +|clean| ## FAQ @@ -35,8 +115,4 @@ Example of usage: **A**: Well, write the User Guide in active voice anyway. -## Command Summary - -{Give a 'cheat sheet' of commands here} -* Add to-do `todo n/TODO_NAME d/DEADLINE` From 75311476234b730e804471a3955f512938d76833 Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 22:53:11 +0800 Subject: [PATCH 156/415] Update text-ui test --- build/libs/data/data.csv | 3 ++- src/main/java/jikan/ui/Ui.java | 4 ++-- text-ui-test/EXPECTED.TXT | 30 +++++++++++++++--------------- 3 files changed, 19 insertions(+), 18 deletions(-) diff --git a/build/libs/data/data.csv b/build/libs/data/data.csv index 8b1378917..6f6d9e7fd 100644 --- a/build/libs/data/data.csv +++ b/build/libs/data/data.csv @@ -1 +1,2 @@ - +activity 1,2020-03-29T22:52:43.337264,2020-03-29T22:52:43.445973400,PT0.0109705S,PT0S,tag +activity 3,2020-03-29T22:52:43.411065900,2020-03-29T22:52:43.415056200,PT0.0039903S,PT0S,tag1 diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 259357afe..067e19ae1 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -46,7 +46,7 @@ private static void printTableFormat(ActivityList activityList, int index, boole printIndex = String.valueOf(index + 1) + " "; } if (gotTags) { - System.out.println(String.format("%s %s %-25s %s %-10s %s %-10s %s %-10s %s %-100s", + System.out.println(String.format("%s %s %-25s %s %-10s %s %-10s %s %-10s %s %s", printIndex, "|", activityList.get(index).getName(), "|", duration, "|", allocatedTime, "|", activityList.get(index).getDate().toString(), "|", @@ -96,7 +96,7 @@ public static void printResults(ActivityList resultsList) { public static void printList(ActivityList activityList) { System.out.println(DIVIDER); System.out.println("Your completed activities:"); - System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-10s %s %-30s", + System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-10s %s %s", "|", "Name", "|", "Duration", "|", "Target", "|", "Date", "|", "Tags")); for (int i = 0; i < activityList.getSize(); i++) { if (activityList.get(i).getTags() != null && !activityList.get(i).getTags().isEmpty()) { diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index a8ba99f87..a937c3681 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -29,29 +29,29 @@ Ended: activity 1 ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Your completed activities: - | Name | Duration | Date | Tags -1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] -2 | activity 2 | 00:00:00 | 2020-03-29 | [tag] -3 | activity 3 | 00:00:00 | 2020-03-29 | [tag1] + | Name | Duration | Target | Date | Tags +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag1] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Here are the matching activities in your list: | Name | Duration | Date | Tags -1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] -2 | activity 2 | 00:00:00 | 2020-03-29 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Here are the matching activities in your list: | Name | Duration | Date | Tags -1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Here are the matching activities in your list: | Name | Duration | Date | Tags -1 | activity 3 | 00:00:00 | 2020-03-29 | [tag1] +1 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag1] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- There is already an activity with this name. Would you like to continue it? @@ -64,10 +64,10 @@ Ended: activity 1 ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Your completed activities: - | Name | Duration | Date | Tags -1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] -2 | activity 2 | 00:00:00 | 2020-03-29 | [tag] -3 | activity 3 | 00:00:00 | 2020-03-29 | [tag1] + | Name | Duration | Target | Date | Tags +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag1] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Please input an integer for the time interval. @@ -105,9 +105,9 @@ You have deleted activity 2 ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Your completed activities: - | Name | Duration | Date | Tags -1 | activity 1 | 00:00:00 | 2020-03-29 | [tag] -2 | activity 3 | 00:00:00 | 2020-03-29 | [tag1] + | Name | Duration | Target | Date | Tags +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] +2 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag1] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Bye! See you again. From 0ab59e11c5fcd39be4b85df73979fd48b9ab2e24 Mon Sep 17 00:00:00 2001 From: btricec Date: Sun, 29 Mar 2020 22:59:01 +0800 Subject: [PATCH 157/415] Fix test --- build/libs/data/data.csv | 2 -- 1 file changed, 2 deletions(-) diff --git a/build/libs/data/data.csv b/build/libs/data/data.csv index 6f6d9e7fd..e69de29bb 100644 --- a/build/libs/data/data.csv +++ b/build/libs/data/data.csv @@ -1,2 +0,0 @@ -activity 1,2020-03-29T22:52:43.337264,2020-03-29T22:52:43.445973400,PT0.0109705S,PT0S,tag -activity 3,2020-03-29T22:52:43.411065900,2020-03-29T22:52:43.415056200,PT0.0039903S,PT0S,tag1 From 7c9b624ed8bd43c66ad498cb73cd29a3913ffb24 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 30 Mar 2020 00:33:10 +0800 Subject: [PATCH 158/415] Add response when user hits his targeted time for an activity --- .gitignore | 3 ++ src/main/java/jikan/Jikan.java | 1 - .../java/jikan/activity/ActivityList.java | 8 +++++ src/main/java/jikan/command/CleanCommand.java | 31 ++++++++++++++-- src/main/java/jikan/command/StartCommand.java | 1 - src/main/java/jikan/parser/Parser.java | 2 +- .../java/jikan/storage/StorageCleaner.java | 36 ++++++++++++++++--- 7 files changed, 72 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 33d74c44e..b48ce9caf 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,9 @@ # data files /data/ +# build/libs files +/build/libs/data + # text-ui-test data files /text-ui-test/data/ /text-ui-test/ACTUAL.txt diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index d590419d0..b0baf929f 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -51,7 +51,6 @@ public static void main(String[] args) throws InvalidTimeFrameException, IOExcep activityList = storage.createActivityList(); activityList.storage = storage; lastShownList.activities.addAll(activityList.activities); - //public static final Scanner in = new Scanner(System.in); while (true) { Command command = parser.parseUserCommands(in,activityList,cleaner); diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 28cb87163..3503d84de 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -148,6 +148,14 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep Ui.printDivider("Ended: " + Parser.activityName); Parser.endTime = LocalDateTime.now(); Duration duration = Duration.between(Parser.startTime, Parser.endTime); + int value = duration.compareTo(Parser.allocatedTime); + if (value >= 0 && Parser.allocatedTime != Duration.parse("PT0S")) { + String line = "Good Job!! You have met the targeted time for this activity."; + Ui.printDivider(line); + } else if (value < 0 && Parser.allocatedTime != Duration.parse("PT0S")) { + String line = "Try Harder, you are almost there."; + Ui.printDivider(line); + } Activity newActivity = new Activity(Parser.activityName, Parser.startTime, Parser.endTime, duration, Parser.tags, Parser.allocatedTime); activityList.add(newActivity); diff --git a/src/main/java/jikan/command/CleanCommand.java b/src/main/java/jikan/command/CleanCommand.java index 2872a155e..abecbed5b 100644 --- a/src/main/java/jikan/command/CleanCommand.java +++ b/src/main/java/jikan/command/CleanCommand.java @@ -39,12 +39,23 @@ public void executeCommand(ActivityList activityList) { cleaner.setStatus(true); assert cleaner.toClean; line = "Auto cleaning enabled"; + Ui.printDivider(line); Log.makeInfoLog("User has turned on automated cleaning"); } else if (parameters.equals("off")) { cleaner.setStatus(false); assert !cleaner.toClean; line = "Auto cleaning disabled"; + Ui.printDivider(line); Log.makeInfoLog("User has turned off automated cleaning"); + } else if (parameters.contains("set")) { + try { + int value = getNumberFromCommand(parameters); + cleaner.setNumberOfActivitiesToClean(value); + line = "Number of activities to clean is set to " + value; + Ui.printDivider(line); + } catch (NumberFormatException | IndexOutOfBoundsException n) { + Ui.printDivider("please provide a number"); + } } else { if (parameters.isEmpty()) { throw new IOException(); @@ -52,8 +63,6 @@ public void executeCommand(ActivityList activityList) { throw new InvalidCleanCommandException(); } } - Ui.printDivider(line); - // Parser.parseClean(tokenizedInputs[1]); } catch (IOException e) { Ui.printDivider("No keyword was given."); } catch (InvalidCleanCommandException e) { @@ -61,4 +70,22 @@ public void executeCommand(ActivityList activityList) { } } + /** + * Method to extract the number of activities to clean from user input. + * @param line full user input with command header extracted out. + * @return the number of activities to clean. + */ + private int getNumberFromCommand(String line) { + int index = line.indexOf("set"); + try { + String numberString = line.substring(index + 4); + try { + return Integer.parseInt(numberString); + } catch (NumberFormatException n){ + throw new NumberFormatException(); + } + } catch (IndexOutOfBoundsException e) { + throw new IndexOutOfBoundsException(); + } + } } diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 8efc9f894..6d1b59367 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -101,7 +101,6 @@ private String parseActivity(int tagDelimiter, int allocateDelimiter) throws Emp if (Parser.activityName.isEmpty()) { throw new EmptyNameException(); } - Parser.allocatedTime = Duration.parse("PT0S"); if (allocateDelimiter != -1) { String allocatedTime; activityInfo = activityInfo.substring(3); diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 073041f02..db9d96dbb 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -37,7 +37,7 @@ public class Parser { public static LocalDateTime startTime = null; public static LocalDateTime endTime = null; public static String activityName = null; - public static Duration allocatedTime = null; + public static Duration allocatedTime = Duration.parse("PT0S"); public static Set tags = new HashSet<>(); private static StorageCleaner cleaner; public static String[] tokenizedInputs; diff --git a/src/main/java/jikan/storage/StorageCleaner.java b/src/main/java/jikan/storage/StorageCleaner.java index 40ca4593e..255981425 100644 --- a/src/main/java/jikan/storage/StorageCleaner.java +++ b/src/main/java/jikan/storage/StorageCleaner.java @@ -18,7 +18,7 @@ public class StorageCleaner { private File status; private File recycledData; public boolean toClean; - private int numberOfActivitiesToClean = 3; + private int numberOfActivitiesToClean; public Storage storage; /** @@ -59,9 +59,12 @@ private void initialiseCleaner() { } else { this.toClean = false; } + String line = sc.nextLine(); + this.numberOfActivitiesToClean = Integer.parseInt(line); } else { FileWriter fw = new FileWriter(status); - fw.write("0"); + fw.write("0" + "\n"); + fw.write("3" + "\n"); fw.close(); } } catch (IOException e) { @@ -108,7 +111,7 @@ private void createFile(File file) throws IOException { /** * Method to activate/de-activate the auto cleanup. * @param status a boolean specifying whether the cleaner should be activated or not. - * @throws IOException if there is an error with reading/writing to the status file + * @throws IOException if there is an error with reading/writing to the status file. */ public void setStatus(boolean status) throws IOException { this.toClean = status; @@ -118,10 +121,33 @@ public void setStatus(boolean status) throws IOException { } BufferedWriter writer = new BufferedWriter(new FileWriter(dataFile)); if (this.toClean) { - writer.write("1"); + writer.write("1" + "\n"); } else { - writer.write("0"); + writer.write("0" + "\n"); } + writer.write(Integer.toString(this.numberOfActivitiesToClean) + "\n"); + writer.close(); + } + + /** + * Method to set a value for the number of activities to clean. + * @param value an integer representing the number to clean. + * @throws IOException if there is an error with reading/writing to the status file. + */ + public void setNumberOfActivitiesToClean(int value) throws IOException { + boolean status = this.toClean; + File dataFile = new File(STATUS_FILE_PATH); + this.numberOfActivitiesToClean = value; + if (!dataFile.exists()) { + dataFile.createNewFile(); + } + BufferedWriter writer = new BufferedWriter(new FileWriter(dataFile)); + if (status) { + writer.write("1" + "\n"); + } else { + writer.write("0" + "\n"); + } + writer.write(Integer.toString(value) + "\n"); writer.close(); } From c997f17a562f3cbb01cb0f10afb60f35d143e493 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 30 Mar 2020 00:35:34 +0800 Subject: [PATCH 159/415] Ignore build files --- .gitignore | 2 +- build/libs/data/data.csv | 0 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 build/libs/data/data.csv diff --git a/.gitignore b/.gitignore index b48ce9caf..199b8f1cb 100644 --- a/.gitignore +++ b/.gitignore @@ -2,7 +2,7 @@ /data/ # build/libs files -/build/libs/data +/build/libs # text-ui-test data files /text-ui-test/data/ diff --git a/build/libs/data/data.csv b/build/libs/data/data.csv deleted file mode 100644 index e69de29bb..000000000 From 231a825cf9d15dbcd7ddb2b5b964abf9a0d5c63e Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 30 Mar 2020 00:39:46 +0800 Subject: [PATCH 160/415] Fix checkstyle --- src/main/java/jikan/command/CleanCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/command/CleanCommand.java b/src/main/java/jikan/command/CleanCommand.java index abecbed5b..b966769a3 100644 --- a/src/main/java/jikan/command/CleanCommand.java +++ b/src/main/java/jikan/command/CleanCommand.java @@ -81,7 +81,7 @@ private int getNumberFromCommand(String line) { String numberString = line.substring(index + 4); try { return Integer.parseInt(numberString); - } catch (NumberFormatException n){ + } catch (NumberFormatException n) { throw new NumberFormatException(); } } catch (IndexOutOfBoundsException e) { From 465f64dc9e36b737a1f92663dfa40dc3426ffa04 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 30 Mar 2020 10:36:56 +0800 Subject: [PATCH 161/415] Fix some allocate issues --- src/main/java/jikan/activity/ActivityList.java | 9 +++++++++ src/main/java/jikan/command/StartCommand.java | 7 ++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 3503d84de..24bb84384 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -141,6 +141,15 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep Duration duration = Duration.between(Parser.startTime, Parser.endTime); Duration oldDuration = activityList.get(Parser.continuedIndex).getDuration(); Duration newDuration = duration.plus(oldDuration); + Duration allocatedTime = activityList.get(Parser.continuedIndex).getAllocatedTime(); + int value = newDuration.compareTo(allocatedTime); + if (value >= 0 && allocatedTime != Duration.parse("PT0S")) { + String line = "Good Job!! You have met the targeted time for this activity."; + Ui.printDivider(line); + } else if (value < 0 && allocatedTime != Duration.parse("PT0S")) { + String line = "Try Harder, you are almost there."; + Ui.printDivider(line); + } activityList.updateDuration(newDuration, Parser.endTime, Parser.continuedIndex); Parser.continuedIndex = -1; Parser.resetInfo(); diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 6d1b59367..29167b1bc 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -37,15 +37,16 @@ public void executeCommand(ActivityList activityList) { } else { // tags should be reset assert Parser.tags.isEmpty(); + int tagDelimiter = parameters.indexOf("/t"); + int allocateDelimiter = parameters.indexOf("/a"); // check if there exists an activity with this name - int index = activityList.findActivity(parameters); + String activityName = getActivityName(tagDelimiter,allocateDelimiter); + int index = activityList.findActivity(activityName); if (index != -1) { Ui.printDivider("There is already an activity with this name. Would you like to continue it?"); continueActivity(activityList, scanner, index); } else { - int tagDelimiter = parameters.indexOf("/t"); - int allocateDelimiter = parameters.indexOf("/a"); try { String line = parseActivity(tagDelimiter,allocateDelimiter); Parser.startTime = LocalDateTime.now(); From 2fdb8de00b40d40da617caa68cd935b5d3190e16 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Mon, 30 Mar 2020 10:50:20 +0800 Subject: [PATCH 162/415] Allow multiple search terms for "find" command --- src/main/java/jikan/command/FindCommand.java | 41 ++++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index b703a03e0..a6d5f73c5 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -3,7 +3,6 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.exception.EmptyQueryException; -import jikan.parser.Parser; import jikan.ui.Ui; import static jikan.Jikan.lastShownList; @@ -34,21 +33,18 @@ public void executeCommand(ActivityList activityList) { } /** - * Find activities which has name containing the keyword from the entire list. + * Find activities which has names containing the keywords from the entire list. * @param activityList full like of activities */ private void findFullList(ActivityList activityList) { try { - // Parser.parseFind(activityList, lastShownList, tokenizedInputs[1]); - String keyword = parameters; - if (keyword.length() < 1) { + if (parameters.length() < 1) { throw new EmptyQueryException(); } else { + String keywords[] = parameters.split(" / "); lastShownList.activities.clear(); - for (Activity i : activityList.activities) { - if (i.getName().contains(keyword)) { - lastShownList.activities.add(i); - } + for(String keyword : keywords) { + populateLastShownList(keyword, activityList.activities); } Ui.printResults(lastShownList); } @@ -58,21 +54,20 @@ private void findFullList(ActivityList activityList) { } /** - * Find activities which has name matching the keyword from the last shown list. + * Find activities which has names containing the keywords from the last shown list. */ private void findSubList() { try { - String keyword = parameters.replace("-s ", ""); + String query = parameters.replace("-s ", ""); ArrayList prevList = new ArrayList<>(); prevList.addAll(lastShownList.activities); - if (keyword.length() < 1) { + if (query.length() < 1) { throw new EmptyQueryException(); } else { + String keywords[] = query.split(" / "); lastShownList.activities.clear(); - for (Activity i : prevList) { - if (i.getName().contains(keyword)) { - lastShownList.activities.add(i); - } + for (String keyword : keywords) { + populateLastShownList(keyword, prevList); } } Ui.printResults(lastShownList); @@ -80,4 +75,18 @@ private void findSubList() { Ui.printDivider("No keyword was given."); } } + + /** + * Fills the last shown list with the results from matching names of activities to a keyword. + * @param keyword the keyword to match against + * @param activities the list of activities to search + */ + private void populateLastShownList(String keyword, ArrayList activities) { + for (Activity i : activities) { + if (i.getName().contains(keyword)) { + lastShownList.activities.add(i); + } + } + } + } \ No newline at end of file From 34ba3e796fe9e0a421c3f102e3bb48ab6e2046f1 Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 30 Mar 2020 12:54:23 +0800 Subject: [PATCH 163/415] Change list month --- src/main/java/jikan/command/ListCommand.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index 7f7ec87fb..f8c04f7bd 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -6,10 +6,11 @@ import jikan.exception.InvalidTimeFrameException; -import java.time.DayOfWeek; -import java.time.LocalDate; +import java.text.ParseException; +import java.time.*; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAdjusters; +import java.util.Calendar; import static jikan.Jikan.lastShownList; @@ -40,11 +41,15 @@ public void executeCommand(ActivityList activityList) throws InvalidTimeFrameExc // Can't do lastShownList = activityList, otherwise we just copy lastShownList.activities.addAll(activityList.activities); } else { - listInterval(activityList); + try { + listInterval(activityList); + } catch (ParseException e) { + System.out.println("invalid date."); + } } } - private void listInterval(ActivityList activityList) throws InvalidTimeFrameException { + private void listInterval(ActivityList activityList) throws InvalidTimeFrameException, ParseException { String[] listInputs; listInputs = parameters.split(" ", 2); @@ -86,13 +91,15 @@ private void listInterval(ActivityList activityList) throws InvalidTimeFrameExce // If user has input a specific date to obtain the month from, use that; // Otherwise get current date if (listInputs.length == 2) { - startDate = LocalDate.parse(listInputs[1], parser); + Month month = Month.valueOf(listInputs[1].toUpperCase()); + YearMonth yearMonth = YearMonth.of(Calendar.getInstance().get(Calendar.YEAR), month.getValue()); + startDate = yearMonth.atDay(1); } else { startDate = LocalDate.now(); } // Set first and last day of month as time range - startDate = startDate.withDayOfMonth(1); + //startDate = startDate.withDayOfMonth(1); endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); break; default: From 0c82050b37fb803e80c6b6326d654d614955a25d Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Mon, 30 Mar 2020 15:54:16 +0800 Subject: [PATCH 164/415] End Message progress bar --- src/main/java/jikan/activity/Activity.java | 5 ++++ .../java/jikan/activity/ActivityList.java | 13 +++++++++ src/main/java/jikan/ui/Ui.java | 29 +++++++++++++++++++ 3 files changed, 47 insertions(+) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 43a4cab07..280981b45 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -89,6 +89,11 @@ public Duration getAllocatedTime() { return this.allocatedTime; } + + public double getProgressPercent() { + double percent = ((double)this.duration.toMillis() / this.allocatedTime.toMillis()) * 100; + return percent; + } /** * Returns true if the Activity's date is within the date range specified (inclusive). * diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 24bb84384..9ebc8dc1a 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -142,6 +142,7 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep Duration oldDuration = activityList.get(Parser.continuedIndex).getDuration(); Duration newDuration = duration.plus(oldDuration); Duration allocatedTime = activityList.get(Parser.continuedIndex).getAllocatedTime(); + /* int value = newDuration.compareTo(allocatedTime); if (value >= 0 && allocatedTime != Duration.parse("PT0S")) { String line = "Good Job!! You have met the targeted time for this activity."; @@ -150,13 +151,21 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep String line = "Try Harder, you are almost there."; Ui.printDivider(line); } + + */ activityList.updateDuration(newDuration, Parser.endTime, Parser.continuedIndex); + + if (activityList.get(Parser.continuedIndex).getAllocatedTime() != Duration.parse("PT0S")) { + Ui.printProgessMessage(activityList.get(Parser.continuedIndex).getProgressPercent()); + } + Parser.continuedIndex = -1; Parser.resetInfo(); } else { Ui.printDivider("Ended: " + Parser.activityName); Parser.endTime = LocalDateTime.now(); Duration duration = Duration.between(Parser.startTime, Parser.endTime); + /* int value = duration.compareTo(Parser.allocatedTime); if (value >= 0 && Parser.allocatedTime != Duration.parse("PT0S")) { String line = "Good Job!! You have met the targeted time for this activity."; @@ -165,9 +174,13 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep String line = "Try Harder, you are almost there."; Ui.printDivider(line); } + */ Activity newActivity = new Activity(Parser.activityName, Parser.startTime, Parser.endTime, duration, Parser.tags, Parser.allocatedTime); activityList.add(newActivity); + if (Parser.allocatedTime != Duration.parse("PT0S")) { + Ui.printProgessMessage(newActivity.getProgressPercent()); + } // reset activity info Parser.resetInfo(); } diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 067e19ae1..4195b72ec 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -2,6 +2,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.parser.Parser; import java.time.Duration; import java.util.HashMap; @@ -15,6 +16,10 @@ public class Ui { public static final String DIVIDER = "-------------------------------" + "------------------------------------------------------------"; + public static final int PROGRESSCONVERTER = 2; + + public static final int TOTALBARS = 50; + /** Prints the logo and greeting so users know the app is working. */ public void printGreeting() { System.out.println(GREETING); @@ -147,4 +152,28 @@ public static void printTagsGraph(HashMap tags) { }); System.out.println(DIVIDER); } + + public static void printProgessMessage(double percent) { + System.out.println(DIVIDER); + if (percent < 50) { + System.out.println("Try harder next time! Here's your progress:"); + } else if (percent < 100) { + System.out.println("Almost there ! Here's your progress:"); + } else { + System.out.println("Great job! Here's your progress:"); + } + int starsLeft = (int) (percent/ PROGRESSCONVERTER); + System.out.print("Progess for " + Parser.activityName + ": "); + System.out.print("|"); + for (int i = 0; i < TOTALBARS; i++) { + if (starsLeft > 0) { + System.out.print("*"); + starsLeft--; + } else { + System.out.print(" "); + } + } + System.out.println("|"); + System.out.println(DIVIDER); + } } From bde03645c7c4c4fe573798780ae0aed461624f98 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Mon, 30 Mar 2020 15:58:09 +0800 Subject: [PATCH 165/415] fix progress bar feature bug --- .../java/jikan/activity/ActivityList.java | 24 ++----------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 9ebc8dc1a..6e955d89a 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -142,17 +142,6 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep Duration oldDuration = activityList.get(Parser.continuedIndex).getDuration(); Duration newDuration = duration.plus(oldDuration); Duration allocatedTime = activityList.get(Parser.continuedIndex).getAllocatedTime(); - /* - int value = newDuration.compareTo(allocatedTime); - if (value >= 0 && allocatedTime != Duration.parse("PT0S")) { - String line = "Good Job!! You have met the targeted time for this activity."; - Ui.printDivider(line); - } else if (value < 0 && allocatedTime != Duration.parse("PT0S")) { - String line = "Try Harder, you are almost there."; - Ui.printDivider(line); - } - - */ activityList.updateDuration(newDuration, Parser.endTime, Parser.continuedIndex); if (activityList.get(Parser.continuedIndex).getAllocatedTime() != Duration.parse("PT0S")) { @@ -165,20 +154,11 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep Ui.printDivider("Ended: " + Parser.activityName); Parser.endTime = LocalDateTime.now(); Duration duration = Duration.between(Parser.startTime, Parser.endTime); - /* - int value = duration.compareTo(Parser.allocatedTime); - if (value >= 0 && Parser.allocatedTime != Duration.parse("PT0S")) { - String line = "Good Job!! You have met the targeted time for this activity."; - Ui.printDivider(line); - } else if (value < 0 && Parser.allocatedTime != Duration.parse("PT0S")) { - String line = "Try Harder, you are almost there."; - Ui.printDivider(line); - } - */ Activity newActivity = new Activity(Parser.activityName, Parser.startTime, Parser.endTime, duration, Parser.tags, Parser.allocatedTime); activityList.add(newActivity); - if (Parser.allocatedTime != Duration.parse("PT0S")) { + + if (newActivity.getAllocatedTime() != Duration.parse("PT0S")) { Ui.printProgessMessage(newActivity.getProgressPercent()); } // reset activity info From 3e0770d2238d4c5b327a78006eb3cd5127f215dc Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Mon, 30 Mar 2020 15:59:55 +0800 Subject: [PATCH 166/415] Added JavaDoc --- src/main/java/jikan/ui/Ui.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 4195b72ec..aff4ec5ce 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -153,6 +153,10 @@ public static void printTagsGraph(HashMap tags) { System.out.println(DIVIDER); } + /** + * Prints a progress message and progress bar based on the percentage of allocate time achieved. + * @param percent percentage of allocated time achieved + */ public static void printProgessMessage(double percent) { System.out.println(DIVIDER); if (percent < 50) { From 090ef9b6ff30eeea07d1ef70df0769af12fd26a5 Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 30 Mar 2020 16:02:56 +0800 Subject: [PATCH 167/415] Update UG --- docs/UserGuide.md | 20 ++++++++++++++++++++ docs/pictures/graph_core.PNG | Bin 0 -> 6106 bytes docs/pictures/list.PNG | Bin 0 -> 20396 bytes docs/pictures/list_core.PNG | Bin 0 -> 13666 bytes docs/pictures/list_week.PNG | Bin 0 -> 8202 bytes 5 files changed, 20 insertions(+) create mode 100644 docs/pictures/graph_core.PNG create mode 100644 docs/pictures/list.PNG create mode 100644 docs/pictures/list_core.PNG create mode 100644 docs/pictures/list_week.PNG diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 273499347..dfb194bd6 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -13,6 +13,26 @@ 4. Open a command window in that folder 5. Run the command java -jar duke.jar +## Usage +Jikan lets you record how much time you spend on various activities so that you can easily see what took up the most time today / this week / this month. + +To start, record your first activity using the `start ACTIVITY_NAME` command. Add some tags to your activities to group similar activities together. When you are done with the activity, or want to move onto something else, tell Jikan to `end` and the Activity time will be recorded and saved to your list. + +You can view all your activities using the `list` command. Activities will be shown in this format: +![Continue command sequence diagram](./pictures/list.PNG) +You can also view all your activities over a period of time by using `list` with extra parameters. For example `list week` will return a list of all activities this current week, as shown below. +![Continue command sequence diagram](./pictures/list_week.PNG) +Filter out the activities you want to see using the `find` or `filter` command. This is our list after filtering out all our activities tagged as `core`. +![Continue command sequence diagram](./pictures/list_core.PNG) +To easily see what took up the most of your time, use the `graph` command to view a chart of your activities. +![Continue command sequence diagram](./pictures/graph_core.PNG) +Now it's clear that lab 3 ex3 took up the most of your time. + +Not done with an activity and want to continue it? Use the `continue` command to continue recording time for a previously started activity. + +Finally, when you're done and want to close the app, simply say `bye` and Jikan will exit. + +This is just a quick overview of what Jikan can do for you. For more details on each individual command, read the command guide below. ## Commands ### Starting an activity: `start` diff --git a/docs/pictures/graph_core.PNG b/docs/pictures/graph_core.PNG new file mode 100644 index 0000000000000000000000000000000000000000..6a92597cf4456aa4b28321c33472ce36817cf49f GIT binary patch literal 6106 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 literal 0 HcmV?d00001 diff --git a/docs/pictures/list_week.PNG b/docs/pictures/list_week.PNG new file mode 100644 index 0000000000000000000000000000000000000000..6a6d3beac17ee42e68534c05115a0180fb577634 GIT binary patch literal 8202 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 Date: Mon, 30 Mar 2020 16:24:34 +0800 Subject: [PATCH 168/415] fixed style violations --- docs/UserGuide.md | 23 ++++++++++++++++++++ src/main/java/jikan/activity/Activity.java | 6 ++++- src/main/java/jikan/command/FindCommand.java | 6 ++--- src/main/java/jikan/command/ListCommand.java | 5 ++++- src/main/java/jikan/ui/Ui.java | 2 +- 5 files changed, 36 insertions(+), 6 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 93bb523db..64a8044f1 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -11,7 +11,30 @@ 1. Ensure that you have Java 11 or above installed. 1. Down the latest version of `Duke` from [here](http://link.to/duke). +<<<<<<< HEAD ## Features +======= +## Usage +Jikan lets you record how much time you spend on various activities so that you can easily see what took up the most time today / this week / this month. + +To start, record your first activity using the `start ACTIVITY_NAME` command. Add some tags to your activities to group similar activities together. When you are done with the activity, or want to move onto something else, tell Jikan to `end` and the Activity time will be recorded and saved to your list. + +You can view all your activities using the `list` command. Activities will be shown in this format: +![Continue command sequence diagram](./pictures/list.PNG) +You can also view all your activities over a period of time by using `list` with extra parameters. For example `list week` will return a list of all activities this current week, as shown below. +![Continue command sequence diagram](./pictures/list_week.PNG) +Filter out the activities you want to see using the `find` or `filter` command. This is our list after filtering out all our activities tagged as `core`. +![Continue command sequence diagram](./pictures/list_core.PNG) +To easily see what took up the most of your time, use the `graph` command to view a chart of your activities. +![Continue command sequence diagram](./pictures/graph_core.PNG) +Now it's clear that lab 3 ex3 took up the most of your time. + +Not done with an activity and want to continue it? Use the `continue` command to continue recording time for a previously started activity. + +Finally, when you're done and want to close the app, simply say `bye` and Jikan will exit. + +This is just a quick overview of what Jikan can do for you. For more details on each individual command, read the command guide below. +>>>>>>> 6b02c0250b849489c2ac63312f0c566fecc8391b {Give detailed description of each feature} ### Finding and Filtering Activities diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 280981b45..d2616cd51 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -89,11 +89,15 @@ public Duration getAllocatedTime() { return this.allocatedTime; } - + /** + * Gets the percentage completed of the allocated time. + * @return percent completed + */ public double getProgressPercent() { double percent = ((double)this.duration.toMillis() / this.allocatedTime.toMillis()) * 100; return percent; } + /** * Returns true if the Activity's date is within the date range specified (inclusive). * diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index a6d5f73c5..ede546a27 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -41,9 +41,9 @@ private void findFullList(ActivityList activityList) { if (parameters.length() < 1) { throw new EmptyQueryException(); } else { - String keywords[] = parameters.split(" / "); + String[] keywords = parameters.split(" / "); lastShownList.activities.clear(); - for(String keyword : keywords) { + for (String keyword : keywords) { populateLastShownList(keyword, activityList.activities); } Ui.printResults(lastShownList); @@ -64,7 +64,7 @@ private void findSubList() { if (query.length() < 1) { throw new EmptyQueryException(); } else { - String keywords[] = query.split(" / "); + String[] keywords = query.split(" / "); lastShownList.activities.clear(); for (String keyword : keywords) { populateLastShownList(keyword, prevList); diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index f8c04f7bd..4da1efe06 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -7,7 +7,10 @@ import jikan.exception.InvalidTimeFrameException; import java.text.ParseException; -import java.time.*; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.Month; +import java.time.YearMonth; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAdjusters; import java.util.Calendar; diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index aff4ec5ce..c9f6c7d9a 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -166,7 +166,7 @@ public static void printProgessMessage(double percent) { } else { System.out.println("Great job! Here's your progress:"); } - int starsLeft = (int) (percent/ PROGRESSCONVERTER); + int starsLeft = (int) (percent / PROGRESSCONVERTER); System.out.print("Progess for " + Parser.activityName + ": "); System.out.print("|"); for (int i = 0; i < TOTALBARS; i++) { From aa7ae224a0a545c09cd144b3992eebb501023ebd Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Mon, 30 Mar 2020 16:30:47 +0800 Subject: [PATCH 169/415] Update UserGuide.md --- docs/UserGuide.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 64a8044f1..57e99ded8 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -11,7 +11,7 @@ 1. Ensure that you have Java 11 or above installed. 1. Down the latest version of `Duke` from [here](http://link.to/duke). -<<<<<<< HEAD + ## Features ======= ## Usage @@ -34,22 +34,21 @@ Not done with an activity and want to continue it? Use the `continue` command to Finally, when you're done and want to close the app, simply say `bye` and Jikan will exit. This is just a quick overview of what Jikan can do for you. For more details on each individual command, read the command guide below. ->>>>>>> 6b02c0250b849489c2ac63312f0c566fecc8391b -{Give detailed description of each feature} -### Finding and Filtering Activities -## Finding Activities by Name: `find` +## Finding and Filtering Activities + +### Finding Activities by Name: `find` Users can request for a sub-list of activities that has names containing a given keyword to be printed. Format: `find KEYWORD` -## Filtering Activities by Tags: `filter` +### Filtering Activities by Tags: `filter` Users can request for a sub-list of activities that has specific tags. Format: `filter TAGNAME1 TAGNAME2` -## Further Finding/Filtering: `-s` +### Further Finding/Filtering: `-s` Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on his/her needs. This is can be particularly useful when the user wants to generate a `graph`. From 4f60f27ed5b576395c5f899137faa70f08625ba2 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 30 Mar 2020 16:47:28 +0800 Subject: [PATCH 170/415] Add LogClean class --- src/main/java/jikan/Jikan.java | 8 +- src/main/java/jikan/command/AbortCommand.java | 3 +- src/main/java/jikan/command/ByeCommand.java | 3 +- src/main/java/jikan/command/CleanCommand.java | 166 +++++++++++---- .../java/jikan/command/ContinueCommand.java | 3 +- src/main/java/jikan/command/EditCommand.java | 6 +- src/main/java/jikan/command/EndCommand.java | 2 +- src/main/java/jikan/command/ListCommand.java | 5 +- src/main/java/jikan/command/StartCommand.java | 2 +- src/main/java/jikan/{ => log}/Log.java | 2 +- src/main/java/jikan/log/LogCleaner.java | 195 ++++++++++++++++++ src/main/java/jikan/parser/Parser.java | 13 +- .../java/jikan/storage/StorageCleaner.java | 2 +- 13 files changed, 349 insertions(+), 61 deletions(-) rename src/main/java/jikan/{ => log}/Log.java (99%) create mode 100644 src/main/java/jikan/log/LogCleaner.java diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index b0baf929f..08cbb8bab 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -6,6 +6,7 @@ import jikan.exception.EmptyNameException; import jikan.exception.EmptyQueryException; import jikan.exception.InvalidTimeFrameException; +import jikan.log.LogCleaner; import jikan.parser.Parser; import jikan.storage.Storage; import jikan.storage.StorageCleaner; @@ -38,6 +39,8 @@ public class Jikan { /** CLeaner to delete entries in data.csv when it gets too long */ private static StorageCleaner cleaner; + private static LogCleaner logCleaner = new LogCleaner(); + public static final Scanner in = new Scanner(System.in); /** @@ -48,12 +51,15 @@ public static void main(String[] args) throws InvalidTimeFrameException, IOExcep storage = new Storage(DATA_FILE_PATH); cleaner = new StorageCleaner(storage); cleaner.autoClean(); + logCleaner.autoClean(); activityList = storage.createActivityList(); activityList.storage = storage; lastShownList.activities.addAll(activityList.activities); + parser.cleaner = cleaner; + parser.logcleaner = logCleaner; while (true) { - Command command = parser.parseUserCommands(in,activityList,cleaner); + Command command = parser.parseUserCommands(in,activityList); if (command == null) { continue; } diff --git a/src/main/java/jikan/command/AbortCommand.java b/src/main/java/jikan/command/AbortCommand.java index 78f249ef3..0e8c305d1 100644 --- a/src/main/java/jikan/command/AbortCommand.java +++ b/src/main/java/jikan/command/AbortCommand.java @@ -1,11 +1,10 @@ package jikan.command; -import jikan.Log; +import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.NoSuchActivityException; import jikan.parser.Parser; import jikan.ui.Ui; -import jikan.Log; /** * Represents a command to abort a currently running activity. diff --git a/src/main/java/jikan/command/ByeCommand.java b/src/main/java/jikan/command/ByeCommand.java index 103616d72..95ecef2ed 100644 --- a/src/main/java/jikan/command/ByeCommand.java +++ b/src/main/java/jikan/command/ByeCommand.java @@ -1,7 +1,6 @@ package jikan.command; -import jikan.Jikan; -import jikan.Log; +import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.InvalidTimeFrameException; import jikan.parser.Parser; diff --git a/src/main/java/jikan/command/CleanCommand.java b/src/main/java/jikan/command/CleanCommand.java index b966769a3..60dd8b473 100644 --- a/src/main/java/jikan/command/CleanCommand.java +++ b/src/main/java/jikan/command/CleanCommand.java @@ -1,31 +1,29 @@ package jikan.command; -import jikan.Log; +import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.InvalidCleanCommandException; -import jikan.parser.Parser; -import jikan.storage.Storage; +import jikan.log.LogCleaner; import jikan.storage.StorageCleaner; import jikan.ui.Ui; import java.io.IOException; -import static jikan.parser.Parser.tokenizedInputs; - /** * Represents a command to clear previously saved log files. */ public class CleanCommand extends Command { StorageCleaner cleaner; + LogCleaner logCleaner; /** * Constructor to create a new clean command. */ - public CleanCommand(String parameters, StorageCleaner cleaner) { + public CleanCommand(String parameters, StorageCleaner cleaner, LogCleaner logCleaner) { super(parameters); - this.cleaner = cleaner; + this.logCleaner = logCleaner; } /** @@ -33,40 +31,132 @@ public CleanCommand(String parameters, StorageCleaner cleaner) { */ @Override public void executeCommand(ActivityList activityList) { + String function = ""; try { - String line; - if (parameters.equals("on")) { - cleaner.setStatus(true); - assert cleaner.toClean; - line = "Auto cleaning enabled"; + function = getFunctionFromCommand(); + } catch (InvalidCleanCommandException e) { + Ui.printDivider("Invalid clean command!"); + } + switch (function) { + case "on": + try { + handleOnFunction(); + } catch (IOException e) { + String line = "There is a problem with accessing the cleaning file"; Ui.printDivider(line); - Log.makeInfoLog("User has turned on automated cleaning"); - } else if (parameters.equals("off")) { - cleaner.setStatus(false); - assert !cleaner.toClean; - line = "Auto cleaning disabled"; + } + break; + case "off": + try { + handleOffFunction(); + } catch (IOException e) { + String line = "There is a problem with accessing the cleaning file"; Ui.printDivider(line); - Log.makeInfoLog("User has turned off automated cleaning"); - } else if (parameters.contains("set")) { - try { - int value = getNumberFromCommand(parameters); - cleaner.setNumberOfActivitiesToClean(value); - line = "Number of activities to clean is set to " + value; - Ui.printDivider(line); - } catch (NumberFormatException | IndexOutOfBoundsException n) { - Ui.printDivider("please provide a number"); - } + } + break; + case "/n": + try { + handleSetFunction(); + } catch (NumberFormatException n) { + Ui.printDivider("please provide a number"); + } catch (IOException e) { + String line = "There is a problem with accessing the cleaning file"; + Ui.printDivider(line); + } + break; + default: + break; + } + } + + private void handleOnFunction() throws IOException { + String line = this.parameters; + if (line.contains("log")) { + logCleaner.setStatus(true); + assert logCleaner.toClean; + line = "Auto cleaning enabled for logs"; + Ui.printDivider(line); + Log.makeInfoLog("User has turned on automated cleaning for logs"); + } else { + cleaner.setStatus(true); + assert cleaner.toClean; + line = "Auto cleaning enabled"; + Ui.printDivider(line); + Log.makeInfoLog("User has turned on automated cleaning"); + } + } + + private void handleOffFunction() throws IOException { + String line = this.parameters; + if (line.contains("log")) { + logCleaner.setStatus(false); + assert !logCleaner.toClean; + line = "Auto cleaning disabled for logs"; + Ui.printDivider(line); + Log.makeInfoLog("User has turned off automated cleaning for logs"); + } else { + cleaner.setStatus(false); + assert !cleaner.toClean; + line = "Auto cleaning disabled"; + Ui.printDivider(line); + Log.makeInfoLog("User has turned off automated cleaning"); + } + } + + private void handleSetFunction() throws IOException, NumberFormatException { + String line = this.parameters; + if (line.contains("log")) { + try { + int value = getNumberFromCommand(line); + logCleaner.setNumberOfLogsToClean(value); + line = "Number of activities to clean is set to " + value; + Ui.printDivider(line); + } catch (NumberFormatException | IndexOutOfBoundsException e) { + throw new NumberFormatException(); + } catch (IOException e) { + throw new IOException(); + } + } else { + try { + int value = getNumberFromCommand(line); + cleaner.setNumberOfActivitiesToClean(value); + line = "Number of activities to clean is set to " + value; + Ui.printDivider(line); + } catch (NumberFormatException | IndexOutOfBoundsException e) { + throw new NumberFormatException(); + } catch (IOException e) { + throw new IOException(); + } + } + } + + /** + * Method to check the required function from user command. + * @return the appropriate function ("on","off","/n"). + * @throws InvalidCleanCommandException when the function is not recognised. + */ + private String getFunctionFromCommand() throws InvalidCleanCommandException { + String line = this.parameters; + if (line.contains("on")) { + if (!line.contains("off") && !line.contains("/n")) { + return "on"; } else { - if (parameters.isEmpty()) { - throw new IOException(); - } else { - throw new InvalidCleanCommandException(); - } + throw new InvalidCleanCommandException(); } - } catch (IOException e) { - Ui.printDivider("No keyword was given."); - } catch (InvalidCleanCommandException e) { - Ui.printDivider("Invalid clean command!"); + } else if (line.contains("off")) { + if (!line.contains("on") && !line.contains("/n")) { + return "off"; + } else { + throw new InvalidCleanCommandException(); + } + } else if (line.contains("/n")) { + if (!line.contains("on") && !line.contains("off")) { + return "/n"; + } else { + throw new InvalidCleanCommandException(); + } + } else { + throw new InvalidCleanCommandException(); } } @@ -76,9 +166,9 @@ public void executeCommand(ActivityList activityList) { * @return the number of activities to clean. */ private int getNumberFromCommand(String line) { - int index = line.indexOf("set"); + int index = line.indexOf("/n"); try { - String numberString = line.substring(index + 4); + String numberString = line.substring(index + 3); try { return Integer.parseInt(numberString); } catch (NumberFormatException n) { diff --git a/src/main/java/jikan/command/ContinueCommand.java b/src/main/java/jikan/command/ContinueCommand.java index c6606f0db..4055e4230 100644 --- a/src/main/java/jikan/command/ContinueCommand.java +++ b/src/main/java/jikan/command/ContinueCommand.java @@ -1,7 +1,6 @@ package jikan.command; -import jikan.Log; -import jikan.activity.Activity; +import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; import jikan.exception.NoSuchActivityException; diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index 81dbd953c..62b0a33b9 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -1,18 +1,14 @@ package jikan.command; -import jikan.Log; +import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; import jikan.exception.InvalidEditFormatException; import jikan.exception.NoSuchActivityException; import jikan.parser.Parser; -import jikan.storage.Storage; -import jikan.storage.StorageHandler; import jikan.ui.Ui; -import java.util.Collections; import java.util.HashSet; -import java.util.Iterator; import java.util.Set; /** diff --git a/src/main/java/jikan/command/EndCommand.java b/src/main/java/jikan/command/EndCommand.java index 90ffee232..cbe9f4807 100644 --- a/src/main/java/jikan/command/EndCommand.java +++ b/src/main/java/jikan/command/EndCommand.java @@ -1,6 +1,6 @@ package jikan.command; -import jikan.Log; +import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.InvalidTimeFrameException; import jikan.exception.NoSuchActivityException; diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index f8c04f7bd..4da1efe06 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -7,7 +7,10 @@ import jikan.exception.InvalidTimeFrameException; import java.text.ParseException; -import java.time.*; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.Month; +import java.time.YearMonth; import java.time.format.DateTimeFormatter; import java.time.temporal.TemporalAdjusters; import java.util.Calendar; diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 29167b1bc..77cd3be27 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -1,6 +1,6 @@ package jikan.command; -import jikan.Log; +import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; import jikan.exception.WrongDateFormatException; diff --git a/src/main/java/jikan/Log.java b/src/main/java/jikan/log/Log.java similarity index 99% rename from src/main/java/jikan/Log.java rename to src/main/java/jikan/log/Log.java index 9b5a6f2f7..808a2f7a2 100644 --- a/src/main/java/jikan/Log.java +++ b/src/main/java/jikan/log/Log.java @@ -1,4 +1,4 @@ -package jikan; +package jikan.log; import java.io.File; import java.io.IOException; diff --git a/src/main/java/jikan/log/LogCleaner.java b/src/main/java/jikan/log/LogCleaner.java new file mode 100644 index 000000000..1f1d76317 --- /dev/null +++ b/src/main/java/jikan/log/LogCleaner.java @@ -0,0 +1,195 @@ +package jikan.log; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + + +/** + * A log cleaner class that does automated cleaning + * for log files under the user's request. + */ +public class LogCleaner { + private static final String STATUS_FILE_PATH = "data/recycled/logStatus.txt"; + private static final String DATA_FILE_PATH = "data/recycled/logData.txt"; + private static final String LOG_FILE_PATH = "data/LogRecord.txt"; + private File status; + private File recycledData; + public boolean toClean; + private int numberOfLogsToClean; + + + /** + * Constructor for the log cleaner. + */ + public LogCleaner() { + status = new File(STATUS_FILE_PATH); + recycledData = new File(DATA_FILE_PATH); + initialiseCleaner(); + initialiseDataFile(); + } + + /** + * Initialise a data file containing the deleted logs. + */ + private void initialiseDataFile() { + try { + loadFile(recycledData); + } catch (IOException e) { + System.out.println("Error loading/creating recycled file"); + } + } + + /** + * Activates/De-activates the auto cleanup of logs by checking the status file. + */ + private void initialiseCleaner() { + try { + if (loadCleaner(status)) { + Scanner sc = new Scanner(status); + String status = sc.nextLine(); + int value = Integer.parseInt(status); + assert value == 0 | value == 1; + if (value == 1) { + this.toClean = true; + } else { + this.toClean = false; + } + String line = sc.nextLine(); + this.numberOfLogsToClean = Integer.parseInt(line); + } else { + FileWriter fw = new FileWriter(status); + fw.write("0" + "\n"); + fw.write("10" + "\n"); + fw.close(); + } + } catch (IOException e) { + System.out.println("Error loading/creating cleaning file."); + } + } + + /** + * Loads the status file and checks if it exists or not. + * @param file status file. + * @return true if the file exists and false otherwise. + * @throws IOException if there is an error with the creation/loading of the status file. + */ + private boolean loadCleaner(File file) throws IOException { + if (!file.exists()) { + createFile(file); + return false; + } else { + return true; + } + } + + /** + * Loads the data file that contains deleted logs. + * @param file data file with the deleted logs. + * @throws IOException if there is an error with the creation/loading of the data file. + */ + private void loadFile(File file) throws IOException { + if (!file.exists()) { + createFile(file); + } + } + + /** + * Creates a new file if the specified file cannot be found in the given path. + * @param file the file to be created if it does not exist. + * @throws IOException if there is an error with the creation of the file. + */ + private void createFile(File file) throws IOException { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + + /** + * Method to activate/de-activate the auto cleanup for logs. + * @param status a boolean specifying whether the log cleaner should be activated or not. + * @throws IOException if there is an error with reading/writing to the status file. + */ + public void setStatus(boolean status) throws IOException { + this.toClean = status; + File dataFile = new File(STATUS_FILE_PATH); + if (!dataFile.exists()) { + dataFile.createNewFile(); + } + BufferedWriter writer = new BufferedWriter(new FileWriter(dataFile)); + if (this.toClean) { + writer.write("1" + "\n"); + } else { + writer.write("0" + "\n"); + } + writer.write(Integer.toString(this.numberOfLogsToClean) + "\n"); + writer.close(); + } + + /** + * Method to set a value for the number of logs to clean. + * @param value an integer representing the number to clean. + * @throws IOException if there is an error with reading/writing to the status file. + */ + public void setNumberOfLogsToClean(int value) throws IOException { + boolean status = this.toClean; + File dataFile = new File(STATUS_FILE_PATH); + this.numberOfLogsToClean = value; + if (!dataFile.exists()) { + dataFile.createNewFile(); + } + BufferedWriter writer = new BufferedWriter(new FileWriter((dataFile))); + if (status) { + writer.write("1" + "\n"); + } else { + writer.write("0" + "\n"); + } + writer.write(Integer.toString(value) + "\n"); + writer.close(); + } + + /** + * Method to clear up the live log file and move them to the recycled log file. + * @throws IOException if there is an error with reading/writing to the live log file and + * recycled log file. + */ + public void autoClean() throws IOException { + List logsForRecycling = new ArrayList<>(); + List logsLeftInData = new ArrayList<>(); + if (this.toClean) { + File liveData = new File(LOG_FILE_PATH); + Scanner recycledDataScanner = new Scanner(recycledData); + Scanner liveDataScanner = new Scanner(liveData); + while (recycledDataScanner.hasNext()) { + String line = recycledDataScanner.nextLine(); + logsForRecycling.add(line); + } + while (numberOfLogsToClean != 0) { + if (!liveDataScanner.hasNext()) { + break; + } + String line = liveDataScanner.nextLine(); + logsForRecycling.add(line); + numberOfLogsToClean -= 1; + } + while (liveDataScanner.hasNext()) { + String line = liveDataScanner.nextLine(); + logsLeftInData.add(line); + } + + BufferedWriter recycledDataWriter = new BufferedWriter(new FileWriter(recycledData)); + for (String line : logsForRecycling) { + recycledDataWriter.write(line + "\n"); + } + recycledDataWriter.close(); + BufferedWriter liveDataWriter = new BufferedWriter(new FileWriter(liveData)); + for (String line : logsLeftInData) { + liveDataWriter.write(line + "\n"); + } + liveDataWriter.close(); + } + } +} diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index db9d96dbb..50b02aea5 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -16,9 +16,10 @@ import jikan.exception.EmptyNameException; import jikan.activity.ActivityList; +import jikan.log.LogCleaner; import jikan.storage.StorageCleaner; import jikan.ui.Ui; -import jikan.Log; +import jikan.log.Log; import java.time.Duration; import java.time.LocalDateTime; @@ -26,7 +27,7 @@ import java.util.Scanner; import java.util.Set; -import static jikan.Log.makeInfoLog; +import static jikan.log.Log.makeInfoLog; /** @@ -39,7 +40,8 @@ public class Parser { public static String activityName = null; public static Duration allocatedTime = Duration.parse("PT0S"); public static Set tags = new HashSet<>(); - private static StorageCleaner cleaner; + public StorageCleaner cleaner; + public LogCleaner logcleaner; public static String[] tokenizedInputs; String instruction; private static Log logger = new Log(); @@ -53,10 +55,9 @@ public class Parser { * @param scanner scanner object which reads user input * @param activityList the list of activities */ - public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) throws + public Command parseUserCommands(Scanner scanner, ActivityList activityList) throws EmptyNameException, NullPointerException, ArrayIndexOutOfBoundsException { makeInfoLog("Starting to parse inputs."); - Parser.cleaner = cleaner; String userInput = scanner.nextLine(); tokenizedInputs = userInput.split(" ", 2); @@ -119,7 +120,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto break; case "clean": try { - command = new CleanCommand(tokenizedInputs[1], cleaner); + command = new CleanCommand(tokenizedInputs[1], this.cleaner, this.logcleaner); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("No keyword was given."); } diff --git a/src/main/java/jikan/storage/StorageCleaner.java b/src/main/java/jikan/storage/StorageCleaner.java index 255981425..0f1e454bc 100644 --- a/src/main/java/jikan/storage/StorageCleaner.java +++ b/src/main/java/jikan/storage/StorageCleaner.java @@ -34,7 +34,7 @@ public StorageCleaner(Storage storage) { } /** - * Initialises a data file contained the deleted entries. + * Initialises a data file containing the deleted entries. */ private void initialiseDataFile() { try { From a78945c6433a41ebda437962e6f152499c8a866a Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 30 Mar 2020 17:17:05 +0800 Subject: [PATCH 171/415] Added graphing for targets --- .../java/jikan/activity/ActivityList.java | 7 ++-- src/main/java/jikan/command/GraphCommand.java | 4 +- src/main/java/jikan/ui/Ui.java | 40 ++++++++++++++++++- 3 files changed, 44 insertions(+), 7 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 6e955d89a..2f196f37e 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -144,10 +144,9 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep Duration allocatedTime = activityList.get(Parser.continuedIndex).getAllocatedTime(); activityList.updateDuration(newDuration, Parser.endTime, Parser.continuedIndex); - if (activityList.get(Parser.continuedIndex).getAllocatedTime() != Duration.parse("PT0S")) { - Ui.printProgessMessage(activityList.get(Parser.continuedIndex).getProgressPercent()); + if (allocatedTime != Duration.parse("PT0S")) { + Ui.printProgressMessage(activityList.get(Parser.continuedIndex).getProgressPercent()); } - Parser.continuedIndex = -1; Parser.resetInfo(); } else { @@ -159,7 +158,7 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep activityList.add(newActivity); if (newActivity.getAllocatedTime() != Duration.parse("PT0S")) { - Ui.printProgessMessage(newActivity.getProgressPercent()); + Ui.printProgressMessage(newActivity.getProgressPercent()); } // reset activity info Parser.resetInfo(); diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index cfa91a134..730777530 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -24,7 +24,9 @@ public GraphCommand(String parameters) { @Override public void executeCommand(ActivityList activityList) { try { - if (parameters.equals("tags")) { + if (parameters.equals("targets")) { + Ui.graphTargets(activityList); + } else if (parameters.equals("tags")) { graphTags(); } else { if (parameters.isEmpty()) { diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index c9f6c7d9a..d901e6377 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -4,6 +4,7 @@ import jikan.activity.ActivityList; import jikan.parser.Parser; +import java.text.DecimalFormat; import java.time.Duration; import java.util.HashMap; import java.util.concurrent.TimeUnit; @@ -20,6 +21,8 @@ public class Ui { public static final int TOTALBARS = 50; + private static final DecimalFormat df2 = new DecimalFormat("#.##"); + /** Prints the logo and greeting so users know the app is working. */ public void printGreeting() { System.out.println(GREETING); @@ -157,7 +160,7 @@ public static void printTagsGraph(HashMap tags) { * Prints a progress message and progress bar based on the percentage of allocate time achieved. * @param percent percentage of allocated time achieved */ - public static void printProgessMessage(double percent) { + public static void printProgressMessage(double percent) { System.out.println(DIVIDER); if (percent < 50) { System.out.println("Try harder next time! Here's your progress:"); @@ -167,7 +170,7 @@ public static void printProgessMessage(double percent) { System.out.println("Great job! Here's your progress:"); } int starsLeft = (int) (percent / PROGRESSCONVERTER); - System.out.print("Progess for " + Parser.activityName + ": "); + System.out.print("Progress for " + Parser.activityName + ": "); System.out.print("|"); for (int i = 0; i < TOTALBARS; i++) { if (starsLeft > 0) { @@ -180,4 +183,37 @@ public static void printProgessMessage(double percent) { System.out.println("|"); System.out.println(DIVIDER); } + + public static void printProgressBar(double percent, String activityName) { + int starsLeft = (int) (percent / PROGRESSCONVERTER); + String line = "Progress for " + activityName + ": "; + System.out.print(String.format("%-35s", line)); + System.out.print("|"); + for (int i = 0; i < TOTALBARS; i++) { + if (starsLeft > 0) { + System.out.print("*"); + starsLeft--; + } else { + System.out.print(" "); + } + } + System.out.println("| " + df2.format(percent) + "%"); + } + + public static void graphTargets(ActivityList activityList) { + System.out.println(DIVIDER); + for (int i = 0; i < activityList.getSize(); i++) { + if (activityList.get(i).getAllocatedTime() == Duration.parse("PT0S")) { + continue; + } + double percent = activityList.get(i).getProgressPercent(); + double max = 100; + if (percent > max) { + percent = max; + } + String activityName = activityList.get(i).getName(); + printProgressBar(percent,activityName); + } + System.out.println(DIVIDER); + } } From 36e7be5ac93c16ed325a8c64a0063bdb6bdff021 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 30 Mar 2020 17:20:51 +0800 Subject: [PATCH 172/415] Add javadoc --- src/main/java/jikan/ui/Ui.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index d901e6377..3ad873b1d 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -184,6 +184,11 @@ public static void printProgressMessage(double percent) { System.out.println(DIVIDER); } + /** + * Method to print progress bar without message. + * @param percent percentage of allocated time achieved. + * @param activityName name of a particular activity. + */ public static void printProgressBar(double percent, String activityName) { int starsLeft = (int) (percent / PROGRESSCONVERTER); String line = "Progress for " + activityName + ": "; @@ -200,6 +205,10 @@ public static void printProgressBar(double percent, String activityName) { System.out.println("| " + df2.format(percent) + "%"); } + /** + * Method to graph out all the targets. + * @param activityList a list of all activities. + */ public static void graphTargets(ActivityList activityList) { System.out.println(DIVIDER); for (int i = 0; i < activityList.getSize(); i++) { From c41737e0ae47324bfc48cfa03bfbb665dead8cfb Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 30 Mar 2020 18:20:37 +0800 Subject: [PATCH 173/415] Add new exception classes --- src/main/java/jikan/exception/EmptyTagException.java | 4 ++++ src/main/java/jikan/exception/NoSuchTagException.java | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 src/main/java/jikan/exception/EmptyTagException.java create mode 100644 src/main/java/jikan/exception/NoSuchTagException.java diff --git a/src/main/java/jikan/exception/EmptyTagException.java b/src/main/java/jikan/exception/EmptyTagException.java new file mode 100644 index 000000000..4f4e94233 --- /dev/null +++ b/src/main/java/jikan/exception/EmptyTagException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class EmptyTagException extends Exception { +} diff --git a/src/main/java/jikan/exception/NoSuchTagException.java b/src/main/java/jikan/exception/NoSuchTagException.java new file mode 100644 index 000000000..94db0f41b --- /dev/null +++ b/src/main/java/jikan/exception/NoSuchTagException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class NoSuchTagException extends Exception { +} From 6bb2325f158d6514f3146e8b0d04dfeb61ae0735 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 30 Mar 2020 18:21:37 +0800 Subject: [PATCH 174/415] Add new Goal command --- src/main/java/jikan/Jikan.java | 10 +- src/main/java/jikan/command/GoalCommand.java | 237 ++++++++++++++++++ src/main/java/jikan/parser/Parser.java | 31 ++- src/main/java/jikan/storage/Storage.java | 5 +- .../java/jikan/storage/StorageHandler.java | 2 +- 5 files changed, 272 insertions(+), 13 deletions(-) create mode 100644 src/main/java/jikan/command/GoalCommand.java diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index d590419d0..29897a97f 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -3,6 +3,7 @@ import jikan.activity.ActivityList; import jikan.command.ByeCommand; import jikan.command.Command; +import jikan.command.GoalCommand; import jikan.exception.EmptyNameException; import jikan.exception.EmptyQueryException; import jikan.exception.InvalidTimeFrameException; @@ -11,6 +12,7 @@ import jikan.storage.StorageCleaner; import jikan.ui.Ui; +import java.io.File; import java.io.IOException; import java.util.Scanner; @@ -21,6 +23,8 @@ public class Jikan { /** Constant file path of data file. */ private static final String DATA_FILE_PATH = "data/data.csv"; + private static final String TAG_FILE_PATH = "data/tag/tag.csv"; + /** Storage object for data file. */ private static Storage storage; @@ -40,6 +44,8 @@ public class Jikan { public static final Scanner in = new Scanner(System.in); + public static File tagFile; + /** * Main entry-point for the Jikan application. */ @@ -50,11 +56,13 @@ public static void main(String[] args) throws InvalidTimeFrameException, IOExcep cleaner.autoClean(); activityList = storage.createActivityList(); activityList.storage = storage; + GoalCommand.createFile(TAG_FILE_PATH, tagFile); + lastShownList.activities.addAll(activityList.activities); //public static final Scanner in = new Scanner(System.in); while (true) { - Command command = parser.parseUserCommands(in,activityList,cleaner); + Command command = parser.parseUserCommands(in,activityList,cleaner,tagFile); if (command == null) { continue; } diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java new file mode 100644 index 000000000..cff894db8 --- /dev/null +++ b/src/main/java/jikan/command/GoalCommand.java @@ -0,0 +1,237 @@ +package jikan.command; + +import jikan.activity.Activity; +import jikan.activity.ActivityList; +import jikan.exception.EmptyTagException; +import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NoSuchTagException; +import jikan.ui.Ui; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.time.Duration; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; + +import static java.lang.Integer.valueOf; + + +/** + * Represents a command to set a goal for activities with a specific tag in the activity list. + */ + +public class GoalCommand extends Command { + private static Scanner scanner; + private static final String TAG_FILE_PATH = "data/tag/tag.csv"; + + /** + * Constructor to create a new goal command. + * @param parameters the parameters of the goal command. + * @param scanner to read the user input. + */ + public GoalCommand(String parameters, Scanner scanner) { + super(parameters); + this.scanner = scanner; + } + + @Override + public void executeCommand(ActivityList activityList) { + try { + int delimiter = parameters.indexOf("/g"); + String tagName = parameters.substring(0, delimiter - 1).strip(); + if (tagName.isEmpty()) { + throw new EmptyTagException(); + } + if (delimiter != -1) { + int index = checkIfExists(tagName); + String tmpTime = parameters.substring(delimiter + 3); + Duration goalTime = parseDuration(tmpTime); + + if (index != -1) { + Ui.printDivider("The goal for this tag already exists, do you want to update the goal?"); + String userInput = scanner.nextLine(); + updateGoal(userInput, tagName, goalTime, index); + + } else { + // tag does not exist in the activity list. + if (!existInActivity(activityList, tagName)) { + throw new NoSuchTagException(); + } else { + addTagLine(tagName + "," + goalTime); + Ui.printDivider("The goal for " + tagName + " has been added!"); + } + } + } else { + throw new InvalidTimeFrameException(); + } + } catch (EmptyTagException | StringIndexOutOfBoundsException e) { + Ui.printDivider("Tag name cannot be empty!"); + } catch (InvalidTimeFrameException e) { + Ui.printDivider("Goal cannot be empty!"); + } catch (IOException e) { + Ui.printDivider("Error reading the file!"); + } catch (NoSuchTagException e) { + Ui.printDivider("There is no such tag!"); + } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { + Ui.printDivider("Please enter the goal in the format HH:MM:SS"); + } + } + + /** + * Creates a new tag file. + * @param filePath the filepath of the tag file. + * @param tagFile the File object. + * @throws IOException when there is an error loading/creating the file. + */ + public static void createFile(String filePath, File tagFile) throws IOException { + tagFile = new File(filePath); + try { + if (!tagFile.exists()) { + tagFile.getParentFile().mkdirs(); // Create data directory (does nothing if directory already exists) + tagFile.createNewFile(); + } + } catch (IOException e) { + System.out.println("Error loading/creating file"); + } + } + + /** + * Check if the tag exists in the tag list. + * @param tagName the tag name. + * @return index the index of the tag in the tag list. + * @throws IOException when there is an error loading/creating the file. + */ + private int checkIfExists(String tagName) throws IOException { + BufferedReader br = new BufferedReader(new FileReader(TAG_FILE_PATH)); + int index = 0; + int status = 0; + try { + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + String[] name; + while (line != null) { + name = line.split(","); + if (name[0].equals(tagName)) { + status = 1; + break; + } + sb.append(line); + sb.append("\n"); + line = br.readLine(); + index++; + } + } finally { + br.close(); + } + if (status == 0) { + index = -1; + } + return index; + } + + /** + * Update the goal for the existing specified tag. + * @param userInput the user response. + * @param tagName the tag name. + * @param goalTime the amount of time the user wants to assign to the tag. + * @param index the index of the tag in the tag list. + */ + private static void updateGoal(String userInput, String tagName, Duration goalTime, int index) throws IOException { + if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { + removeLine(index); + writeToFile(tagName + "," + goalTime); + Ui.printDivider("The goal for " + tagName + " was updated"); + } else { + Ui.printDivider("Okay then, what else can I do for you?"); + } + } + + /** + * Updates tag file with new tag. + * + * @param dataLine Line to write to file. + */ + + public static void addTagLine(String dataLine) { + try { + writeToFile(dataLine); + } catch (IOException e) { + System.out.println("Error saving tag to tag file."); + } + } + + /** + * Remove the tag data at the specified index. + * + * @param index index of the tag to remove. + */ + public static void removeTagLine(int index) { + try { + removeLine(index); + } catch (IOException e) { + System.out.println("Error removing tag from tag file."); + } + } + + /** + * Removes the line whose index matches lineNumber from file. + * + * @param lineNumber Index of line to remove. + * @throws IOException If an error occurs while writing the new list to file. + */ + public static void removeLine(int lineNumber) throws IOException { + // Read file into list of strings, where each string is a line in the file + List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(TAG_FILE_PATH), + StandardCharsets.UTF_8)); + fileContent.remove(lineNumber); + } + + /** + * Writes the input string to file. + * + * @param s The input string. + * @throws IOException If an error occurs while writing. + */ + public static void writeToFile(String s) throws IOException { + FileWriter fw = new FileWriter(TAG_FILE_PATH, true); + fw.write(s + System.lineSeparator()); + fw.close(); + } + + /** + * Check if the tag exists in the activity list. + * @param targetList the activity list to check. + * @param tagName the specified tag name. + * @return true or false. + */ + private boolean existInActivity(ActivityList targetList, String tagName) { + for (Activity i : targetList.activities) { + if (i.getTags().contains(tagName)) { + return true; + } + } + return false; + } + + /** + * Converts the user input into a duration object. + * @param input the user input. + * @return the duration object. + */ + public static Duration parseDuration(String input) throws InvalidTimeFrameException, + ArrayIndexOutOfBoundsException { + String[] fields = input.split(":"); + int colonIndex = input.indexOf(':'); + String hh = fields[0]; + String mm = fields[1]; + String ss = fields[2]; + return Duration.ofHours(valueOf(hh)).plusMinutes(valueOf(mm)).plusSeconds(valueOf(ss)); + } +} diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index f2658e0d3..a324872a6 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,25 +1,28 @@ package jikan.parser; -import jikan.command.Command; +import jikan.Log; +import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; +import jikan.storage.StorageCleaner; +import jikan.ui.Ui; + import jikan.command.AbortCommand; import jikan.command.ByeCommand; import jikan.command.CleanCommand; +import jikan.command.Command; import jikan.command.ContinueCommand; import jikan.command.DeleteCommand; import jikan.command.EditCommand; import jikan.command.EndCommand; import jikan.command.FilterCommand; import jikan.command.FindCommand; +import jikan.command.GoalCommand; import jikan.command.GraphCommand; import jikan.command.ListCommand; import jikan.command.StartCommand; +import jikan.command.ViewGoalsCommand; -import jikan.exception.EmptyNameException; -import jikan.activity.ActivityList; -import jikan.storage.StorageCleaner; -import jikan.ui.Ui; -import jikan.Log; - +import java.io.File; import java.time.LocalDateTime; import java.util.HashSet; import java.util.Scanner; @@ -50,7 +53,8 @@ public class Parser { * @param scanner scanner object which reads user input * @param activityList the list of activities */ - public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner) throws + public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner, + File tagFile) throws EmptyNameException, NullPointerException, ArrayIndexOutOfBoundsException { makeInfoLog("Starting to parse inputs."); Parser.cleaner = cleaner; @@ -140,6 +144,17 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto + "If you'd like to graph by tags, enter the command ."); } break; + case "goal": + try { + if (tokenizedInputs.length == 1) { + command = new ViewGoalsCommand(null,tagFile); + } else { + command = new GoalCommand(tokenizedInputs[1], scanner); + } + } catch (StringIndexOutOfBoundsException e) { + Ui.printDivider("Tag name cannot be empty!"); + } + break; default: parseDefault(); break; diff --git a/src/main/java/jikan/storage/Storage.java b/src/main/java/jikan/storage/Storage.java index d78355d67..8f1c2595b 100644 --- a/src/main/java/jikan/storage/Storage.java +++ b/src/main/java/jikan/storage/Storage.java @@ -14,7 +14,7 @@ public class Storage { /** Path to current data file. */ - public String dataFilePath; + public static String dataFilePath; /** File object for current data file. */ public File dataFile; @@ -37,7 +37,7 @@ public Storage(String dataFilePath) { * @param s The input string. * @throws IOException If an error occurs while writing. */ - public void writeToFile(String s) throws IOException { + public static void writeToFile(String s) throws IOException { FileWriter fw = new FileWriter(dataFilePath, true); fw.write(s + System.lineSeparator()); fw.close(); @@ -68,7 +68,6 @@ private void createDataFile() throws IOException { dataFile.createNewFile(); } - /** * Creates ActivityList and loads data from data file if the data file previously existed. * Otherwise, an empty task list is initialized. diff --git a/src/main/java/jikan/storage/StorageHandler.java b/src/main/java/jikan/storage/StorageHandler.java index 5fe6686fe..b101af77d 100644 --- a/src/main/java/jikan/storage/StorageHandler.java +++ b/src/main/java/jikan/storage/StorageHandler.java @@ -28,7 +28,7 @@ public class StorageHandler { */ public static void removeLine(int lineNumber, Storage storage) throws IOException { // Read file into list of strings, where each string is a line in the file - List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(storage.dataFilePath), + List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(Storage.dataFilePath), StandardCharsets.UTF_8)); //int removedIndex = 0; From 0f4d394c413f01afbbbc1a4d24ff33fd41bd1deb Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 30 Mar 2020 18:21:49 +0800 Subject: [PATCH 175/415] Add new View Goal command --- .../java/jikan/activity/ActivityList.java | 6 +- .../java/jikan/command/ViewGoalsCommand.java | 83 +++++++++++++++++++ src/main/java/jikan/ui/Ui.java | 47 +++++++++++ 3 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/main/java/jikan/command/ViewGoalsCommand.java diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index e18303298..1d716419c 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -109,7 +109,11 @@ public void delete(int index) { deleteUpdateFile(index); } - private void deleteUpdateFile(int index) { + /** + * Deletes the line in the file. + * @param index the index of the line in the file. + */ + public void deleteUpdateFile(int index) { try { StorageHandler.removeLine(index, storage); } catch (IOException e) { diff --git a/src/main/java/jikan/command/ViewGoalsCommand.java b/src/main/java/jikan/command/ViewGoalsCommand.java new file mode 100644 index 000000000..0519be3fc --- /dev/null +++ b/src/main/java/jikan/command/ViewGoalsCommand.java @@ -0,0 +1,83 @@ +package jikan.command; + +import jikan.activity.Activity; +import jikan.activity.ActivityList; +import jikan.exception.InvalidTimeFrameException; +import jikan.ui.Ui; +import static jikan.Jikan.tagFile; + +import java.io.File; +import java.io.FileNotFoundException; +import java.time.Duration; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Scanner; + +/** + * Represents a command to view goals for tags in the activity list. + */ +public class ViewGoalsCommand extends Command { + + File tagFile; + private static final String TAG_FILE_PATH = "data/tag/tag.csv"; + + /** + * Constructor to create a new viewgoal command. + * @param parameters the parameters of the goal command. + */ + public ViewGoalsCommand(String parameters, File tagFile) { + super(parameters); + this.tagFile = tagFile; + } + + @Override + public void executeCommand(ActivityList activityList) { + HashMap tagsGoals = new HashMap<>(); + populateTagList(tagFile, tagsGoals); + getGoalData(activityList,tagsGoals); + + } + + private void getGoalData(ActivityList activityList, HashMap tagsGoals) { + HashMap tagsActual = new HashMap<>(); + for (Activity activity : activityList.activities) { + GraphCommand.extractTags(tagsActual, activity); + } + Ui.printGoals(tagsGoals, tagsActual); + } + + /** + * Populates task list from file. + * + * @param dataFile Data file to populate from. + */ + private void populateTagList(File dataFile, HashMap tagsGoals) { + try { + tagFile = new File(TAG_FILE_PATH); + Scanner dataScanner = new Scanner(tagFile); + while (dataScanner.hasNext()) { + parseDataLine(dataScanner.nextLine(), tagsGoals); + } + } catch (FileNotFoundException e) { + System.out.println("Data file not found. Could not load into the current session's tag list!"); + } catch (InvalidTimeFrameException e) { + System.out.println("Invalid time frame!"); + } catch (NullPointerException e) { + System.out.println("Error!"); + } + } + + /** + * Parses the current line in the tag file. + * + * @param s String to parse. + */ + private void parseDataLine(String s, HashMap tagsGoals) throws InvalidTimeFrameException { + if (!s.isEmpty()) { + List strings = Arrays.asList(s.split(",")); + Duration duration = Duration.parse(strings.get(1)); + tagsGoals.put(strings.get(0), duration); + } + } +} diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 0f6d09d24..2d17ec73e 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -137,4 +137,51 @@ public static void printTagsGraph(HashMap tags) { }); System.out.println(DIVIDER); } + + /** + * Print goals as a table. + * @param tagsGoals the goals set for each tag. + * @param tagsActual the actual duration spent for each tag. + */ + public static void printGoals(HashMap tagsGoals, HashMap tagsActual) { + System.out.println(DIVIDER); + System.out.println(String.format(" %-15s %s %-15s %s %-15s %s %s", + "Tag", "|", "Goal", "|", "Actual", "|", "Duration left")); + tagsGoals.forEach((key, value) -> { + String message; + String goalDuration = convertDuration(tagsGoals.get(key)); + String actualDuration = convertDuration(tagsActual.get(key)); + Duration difference = tagsGoals.get(key).minus(tagsActual.get(key)); + String diffDuration = convertDuration(difference); + if (difference.isNegative()) { + if (diffDuration.equals("00:00:00")) { + message = " [You have met your goal!]"; + } else { + message = " [You have exceeded your goal!]"; + } + } else { + message = " [You have not met your goal!]"; + } + System.out.println(String.format(" %-15s %s %-15s %s %-15s %s %s", key, + "|", goalDuration, "|", actualDuration, "|", diffDuration + message)); + }); + System.out.println(DIVIDER); + } + + /** + * Converts duration object to a string for printing. + * @param dur the duration object. + * @return duration the duration as a string. + */ + public static String convertDuration(Duration dur) { + long durationInNanos = dur.toNanos(); + String duration = String.format("%02d:%02d:%02d", + TimeUnit.NANOSECONDS.toHours(durationInNanos), + TimeUnit.NANOSECONDS.toMinutes(durationInNanos) + - TimeUnit.HOURS.toMinutes(TimeUnit.NANOSECONDS.toHours(durationInNanos)), + TimeUnit.NANOSECONDS.toSeconds(durationInNanos) + - TimeUnit.MINUTES.toSeconds(TimeUnit.NANOSECONDS.toMinutes(durationInNanos))); + return duration; + } } From 3921b1bd08e9db06487d0208bb6f722960d215ab Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 30 Mar 2020 18:22:01 +0800 Subject: [PATCH 176/415] Add javadoc for style --- src/main/java/jikan/command/GraphCommand.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index cfa91a134..6cd97b4f5 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -49,7 +49,12 @@ private void graphTags() { Ui.printTagsGraph(tags); } - private void extractTags(HashMap tags, Activity activity) { + /** + * Gets the tags from the activities in the list together with the associated duration. + * @param tags the HashMap to store the tag name and duration. + * @param activity the activity containing the tag. + */ + public static void extractTags(HashMap tags, Activity activity) { Set activityTags = activity.getTags(); for (String tag : activityTags) { if (tags.containsKey(tag)) { From 7d69efe8e489caea60353f8bf2a75dc79f8a4333 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 30 Mar 2020 18:55:56 +0800 Subject: [PATCH 177/415] Fix style issues for gradle check --- src/main/java/jikan/ui/Ui.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 4d6a9649f..4bbae8439 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -183,7 +183,7 @@ public static void printProgressMessage(double percent) { System.out.println("|"); } - /** Print goals as a table. + /** Print goals as a table. * @param tagsGoals the goals set for each tag. * @param tagsActual the actual duration spent for each tag. */ @@ -206,7 +206,8 @@ public static void printGoals(HashMap tagsGoals, HashMap Date: Mon, 30 Mar 2020 19:02:11 +0800 Subject: [PATCH 178/415] Fix style issues --- src/main/java/jikan/Jikan.java | 4 ---- src/main/java/jikan/parser/Parser.java | 11 ----------- src/main/java/jikan/ui/Ui.java | 2 +- 3 files changed, 1 insertion(+), 16 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 57e16fd06..80fe96013 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -68,10 +68,6 @@ public static void main(String[] args) throws InvalidTimeFrameException, IOExcep while (true) { Command command = parser.parseUserCommands(in,activityList,cleaner,tagFile); -<<<<<<< HEAD -======= - ->>>>>>> de74454c9173645ba1795e576c73b5300488a2a7 if (command == null) { continue; } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 0a9315354..e84d11010 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -22,11 +22,8 @@ import jikan.command.StartCommand; import jikan.command.ViewGoalsCommand; -<<<<<<< HEAD -======= import java.io.File; ->>>>>>> de74454c9173645ba1795e576c73b5300488a2a7 import jikan.exception.EmptyNameException; import jikan.activity.ActivityList; import jikan.log.LogCleaner; @@ -35,10 +32,7 @@ import jikan.log.Log; import java.time.Duration; -<<<<<<< HEAD import java.io.File; -======= ->>>>>>> de74454c9173645ba1795e576c73b5300488a2a7 import java.time.LocalDateTime; import java.util.HashSet; import java.util.Scanner; @@ -72,11 +66,6 @@ public class Parser { * @param scanner scanner object which reads user input * @param activityList the list of activities */ -<<<<<<< HEAD - -======= - ->>>>>>> de74454c9173645ba1795e576c73b5300488a2a7 public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner, File tagFile) throws EmptyNameException, NullPointerException, ArrayIndexOutOfBoundsException { diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 5075551f2..a1e8b08e1 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -186,7 +186,7 @@ public static void printGoals(HashMap tagsGoals, HashMap Date: Mon, 30 Mar 2020 21:15:35 +0800 Subject: [PATCH 179/415] Add edit allocated time feature --- src/main/java/jikan/activity/Activity.java | 2 + .../java/jikan/activity/ActivityList.java | 5 ++ src/main/java/jikan/command/EditCommand.java | 66 +++++++++++++++---- 3 files changed, 60 insertions(+), 13 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index d2616cd51..0e0cc5850 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -89,6 +89,8 @@ public Duration getAllocatedTime() { return this.allocatedTime; } + public void setAllocatedTime(Duration allocatedTime) { this.allocatedTime = allocatedTime; } + /** * Gets the percentage completed of the allocated time. * @return percent completed diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 383fd0269..f71cc215a 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -104,6 +104,11 @@ public void updateTags(int index, Set newTags) { fieldChangeUpdateFile(); } + public void updateAlloc(int index, Duration newAllocTime) { + activities.get(index).setAllocatedTime(newAllocTime); + fieldChangeUpdateFile(); + } + public void delete(int index) { activities.remove(index); deleteUpdateFile(index); diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index 62b0a33b9..4e37c8ec6 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -1,5 +1,6 @@ package jikan.command; +import jikan.exception.InvalidTimeFrameException; import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; @@ -8,9 +9,13 @@ import jikan.parser.Parser; import jikan.ui.Ui; +import java.time.Duration; +import java.util.ArrayList; import java.util.HashSet; import java.util.Set; +import static jikan.command.GoalCommand.parseDuration; + /** * Represents a command to edit an activity in the activity list. */ @@ -26,39 +31,74 @@ public EditCommand(String parameters) { @Override public void executeCommand(ActivityList activityList) { try { - // Parser.parseEdit(activityList); - int delimiter = parameters.indexOf("/e"); + int delimiter = parameters.indexOf("/en"); int tagDelim = parameters.indexOf("/et"); - Parser.activityName = parameters.substring(0, delimiter).strip(); + int allocDelim = parameters.indexOf("/ea"); + + // edit name + if (delimiter != -1 && tagDelim == -1 && allocDelim == -1) { + Parser.activityName = parameters.substring(0, delimiter).strip(); + + //edit tag + } else if (delimiter == -1 && tagDelim != -1 && allocDelim == -1) { + Parser.activityName = parameters.substring(0, tagDelim).strip(); + + //edit allocatedTime + } else { + Parser.activityName = parameters.substring(0, allocDelim).strip(); + + } + if (Parser.activityName.isEmpty()) { throw new EmptyNameException(); } + int index = activityList.findActivity(Parser.activityName); String newName = ""; String[] tmpTags; + String tmpAlloc = ""; + Duration newAllocTime = null; Set newTags = new HashSet(); - if (tagDelim != -1) { - newName = parameters.substring(delimiter + 3, tagDelim - 1); + + //edit name + if (delimiter != -1 && tagDelim == -1 && allocDelim == -1) { + newName = parameters.substring(delimiter + 4); + Parser.activityName = parameters.substring(0, delimiter).strip(); + + //edit tag + } else if (delimiter == -1 && tagDelim != -1 && allocDelim == -1) { tmpTags = (parameters.substring(tagDelim + 4).split(" ")); for (String t : tmpTags) { newTags.add(t); } + //edit allocatedTime } else { - newName = parameters.substring(delimiter + 3); + tmpAlloc = parameters.substring(allocDelim + 4); + try { + newAllocTime = parseDuration(tmpAlloc); + } catch (InvalidTimeFrameException e) { + Ui.printDivider("Invalid time frame entered!"); + } } if (index != -1) { - if (newName.isEmpty()) { - // no new name is provided - throw new InvalidEditFormatException(); - } else { - activityList.updateName(index, newName); + if (!(newName.isEmpty() && newTags.isEmpty() && tmpAlloc.isEmpty())) { + if (!newName.isEmpty()) { + activityList.updateName(index, newName); + } if (!newTags.isEmpty()) { - activityList.updateTags(index,newTags); + activityList.updateTags(index, newTags); } - Ui.printDivider("Activity named " + Parser.activityName + " has been updated!"); + if (!tmpAlloc.isEmpty()) { + activityList.updateAlloc(index, newAllocTime); + } + } else { + // no new details provided + throw new InvalidEditFormatException(); } + Ui.printDivider("Activity named " + Parser.activityName + " has been updated!"); + } else { // activity is not found throw new NoSuchActivityException(); From c7b6d16777c68c26526bc44e07accc39b4b20f44 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 30 Mar 2020 21:39:59 +0800 Subject: [PATCH 180/415] Fix text-ui-test --- build.gradle | 6 ++++++ build/libs/data/data.csv | 1 - src/main/java/jikan/activity/Activity.java | 4 +++- text-ui-test/EXPECTED.TXT | 24 +++++++++++----------- 4 files changed, 21 insertions(+), 14 deletions(-) delete mode 100644 build/libs/data/data.csv diff --git a/build.gradle b/build.gradle index 0971b27d6..44dfbb89e 100644 --- a/build.gradle +++ b/build.gradle @@ -38,4 +38,10 @@ checkstyle { run{ standardInput = System.in enableAssertions = true +} + +jar { + manifest { + attributes 'Main-Class': 'jikan.Jikan' + } } \ No newline at end of file diff --git a/build/libs/data/data.csv b/build/libs/data/data.csv deleted file mode 100644 index 8b1378917..000000000 --- a/build/libs/data/data.csv +++ /dev/null @@ -1 +0,0 @@ - diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 0e0cc5850..280a64e51 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -89,7 +89,9 @@ public Duration getAllocatedTime() { return this.allocatedTime; } - public void setAllocatedTime(Duration allocatedTime) { this.allocatedTime = allocatedTime; } + public void setAllocatedTime(Duration allocatedTime) { + this.allocatedTime = allocatedTime; + } /** * Gets the percentage completed of the allocated time. diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index a937c3681..1640c8d08 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -30,28 +30,28 @@ Ended: activity 1 ------------------------------------------------------------------------------------------- Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Here are the matching activities in your list: | Name | Duration | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Here are the matching activities in your list: | Name | Duration | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Here are the matching activities in your list: | Name | Duration | Date | Tags -1 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag1] +1 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- There is already an activity with this name. Would you like to continue it? @@ -65,9 +65,9 @@ Ended: activity 1 ------------------------------------------------------------------------------------------- Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Please input an integer for the time interval. @@ -106,8 +106,8 @@ You have deleted activity 2 ------------------------------------------------------------------------------------------- Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag] -2 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-29 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] +2 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Bye! See you again. From e52d458ae35f012f6ac3a9fddc77b2bd0429e582 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 30 Mar 2020 21:48:05 +0800 Subject: [PATCH 181/415] Fix start exception handling --- src/main/java/jikan/command/StartCommand.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 77cd3be27..9ad3e3bc8 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -48,6 +48,9 @@ public void executeCommand(ActivityList activityList) { continueActivity(activityList, scanner, index); } else { try { + if (activityName.isEmpty()) { + throw new EmptyNameException(); + } String line = parseActivity(tagDelimiter,allocateDelimiter); Parser.startTime = LocalDateTime.now(); Log.makeFineLog("Started: " + Parser.activityName); From 85a40ab60d5f51657676ad08414d250f76fcbeae Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Mon, 30 Mar 2020 22:11:53 +0800 Subject: [PATCH 182/415] Prints the actual percent --- src/main/java/jikan/ui/Ui.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index a1e8b08e1..41494329f 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -209,7 +209,8 @@ public static void printProgressMessage(double percent) { System.out.print(" "); } } - System.out.println("|"); + System.out.print("|"); + System.out.println((int) percent + "% completed"); System.out.println(DIVIDER); } From 0ee76c840dedbfb71d71795fb17e184a9a7c5e04 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 30 Mar 2020 22:24:19 +0800 Subject: [PATCH 183/415] Add commands to UG --- docs/UserGuide.md | 44 +++++++++++++------- src/main/java/jikan/command/EditCommand.java | 3 +- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 57e99ded8..31451f8d0 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -2,17 +2,13 @@ ## Introduction -{Give a product intro} +Jikan is a CLI time management tool that allows you to track the amount of time that you spend on different activities. This user guide will show you how to use the program effectively. ## Quick Start - -{Give steps to get started quickly} - 1. Ensure that you have Java 11 or above installed. -1. Down the latest version of `Duke` from [here](http://link.to/duke). - +1. Download the latest version of `Jikan` from [here](https://github.com/AY1920S2-CS2113-T15-1/tp/releases). -## Features +Features ======= ## Usage Jikan lets you record how much time you spend on various activities so that you can easily see what took up the most time today / this week / this month. @@ -75,12 +71,30 @@ Example of usage: ## FAQ -**Q**: How do I transfer my data to another computer? - -**A**: Well, write the User Guide in active voice anyway. - -## Command Summary - -{Give a 'cheat sheet' of commands here} -* Add to-do `todo n/TODO_NAME d/DEADLINE` +## Command Guide + +* Start an activity: `start ACTVITY_NAME` + * optional: `start ACTIVITY_NAME /t TAGS /a ALLOCATED_TIME` +* Abort an activity: `abort` +* Stop an activity: `end` +* Continue an activity: `continue ACTIVITY_NAME` +* List all activities: `list` +* Edit an activity: `edit ACTIVITY_NAME [flag]` + * Edit activity name: `edit ACTIVITY_NAME /en NEW_NAME` + * Edit activity tags: `edit ACTIVITY_NAME /et NEW_TAG1 NEW_TAG2` + * Edit activity allocated time: `edit ACTIVITY_NAME /ea NEW_ALLOCATED_TIME` +* Delete an activity: `delete ACTIVITY_NAME` +* Find activities with keyword: `find KEYWORD` + * optional: `find -s KEYWORD` for more specific find +* Filter activities by tags: `filter TAG_NAME` + * optional: `filter -s TAG1 TAG2` for more specific filter +* Set a goal for tags: `goal TAG_NAME /g DURATION` +* View goals for tags: `goal` +* Display graph by tags: `graph tags` +* Display graph by duration: `graph INTERVAL` +* Clean data files: `clean [command]` + * On auto data cleaner: `clean on` + * Off auto data cleaner: `clean off` + * Specify number of files: `clean /n NUMBER` +* Terminate the program: `bye` diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index 4e37c8ec6..0e1e52c54 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -10,7 +10,6 @@ import jikan.ui.Ui; import java.time.Duration; -import java.util.ArrayList; import java.util.HashSet; import java.util.Set; @@ -89,6 +88,8 @@ public void executeCommand(ActivityList activityList) { } if (!newTags.isEmpty()) { activityList.updateTags(index, newTags); + //GoalCommand.updateTagFile(index, newTags); + } if (!tmpAlloc.isEmpty()) { activityList.updateAlloc(index, newAllocTime); From 6d0d982d2fa8e8af450ca976783c088d7e52ea00 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Mon, 30 Mar 2020 22:42:26 +0800 Subject: [PATCH 184/415] Added some User Guide info, fixed printing table header error. --- docs/UserGuide.md | 120 +++++++++++++++++++++++++++------ src/main/java/jikan/ui/Ui.java | 2 +- 2 files changed, 102 insertions(+), 20 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 57e99ded8..7a87d80b9 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -34,30 +34,112 @@ Not done with an activity and want to continue it? Use the `continue` command to Finally, when you're done and want to close the app, simply say `bye` and Jikan will exit. This is just a quick overview of what Jikan can do for you. For more details on each individual command, read the command guide below. - - +## Ending an Activity: `end` +After an activity has been completed, the user can enter the `end` command for activity to be saved. +If an allocated time was given with the `/a` extension when it was started, the user will get a progress message +stated how he/she fared for the session. + +#### Example: +``` +end +------------------------------------------------------------------------------------------- +Ended: ger quiz 11 +------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------- +Almost there ! Here's your progress: +Progress for ger quiz 11: |******************************************** |89% completed +------------------------------------------------------------------------------------------- +``` ## Finding and Filtering Activities ### Finding Activities by Name: `find` -Users can request for a sub-list of activities that has names containing a given keyword to be printed. - -Format: `find KEYWORD` +Users can request for a sub-list of activities that has any of the given keywords separated by ` / `. + +#### Format: +* `find KEYWORD` +* `find KEYWORD1 / KEYWORD2 / KEYWORD3` + +#### Example: +``` +find lab / tutorial +------------------------------------------------------------------------------------------- +Here are the matching activities in your list: + + | Name | Duration | Target | Date | Tags +1 | lab 3 ex1 demo | 00:00:00 | 02:14:54 | 2020-03-18 | [2106, lab] +2 | lab 3 ex2 | 00:00:00 | 03:13:14 | 2020-03-19 | [2106, lab] +3 | lab 3 ex3 | 07:51:12 | 00:00:00 | 2020-03-25 | [core, 2106, lab] +4 | lab 4 ex2 | 02:40:21 | 00:00:00 | 2020-03-30 | [core, 2106, lab] +5 | lab 4 demo | 02:13:14 | 00:00:00 | 2020-04-01 | [core, 2106, lab] +6 | 2106 tutorial 7 | 00:00:00 | 01:20:12 | 2020-03-18 | [2106] +7 | 2113 tutorial questions | 00:00:00 | 00:48:54 | 2020-03-23 | [2113] +8 | 2106 tutorial 8 | 00:00:00 | 01:23:00 | 2020-03-25 | [2106] +------------------------------------------------------------------------------------------- +``` ### Filtering Activities by Tags: `filter` -Users can request for a sub-list of activities that has specific tags. - -Format: `filter TAGNAME1 TAGNAME2` - -### Further Finding/Filtering: `-s` -Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on his/her needs. -This is can be particularly useful when the user wants to generate a `graph`. - -This flag applies to `find` and `filter` commands only. - -Format: -* `filter -s TAGNAME1 TAGNAME2` -* `find -s keyword` - +Users can request for a sub-list of activities that has specific tags (separated only by spaces. + +#### Format: +* `filter TAGNAME` +* `filter TAGNAME1 TAGNAME2` + +#### Example: +``` +filter 2106 2113 +------------------------------------------------------------------------------------------- +Here are the matching activities in your list: + + | Name | Duration | Target | Date | Tags +1 | study for 2106 midterm | 00:00:00 | 06:17:03 | 2020-03-28 | [2106, midterm] +2 | 2106 tutorial 7 | 00:00:00 | 01:20:12 | 2020-03-18 | [2106] +3 | lab 3 ex1 demo | 00:00:00 | 02:14:54 | 2020-03-18 | [2106, lab] +4 | lab 3 ex2 | 00:00:00 | 03:13:14 | 2020-03-19 | [2106, lab] +5 | 2106 tutorial 8 | 00:00:00 | 01:23:00 | 2020-03-25 | [2106] +6 | lab 3 ex3 | 07:51:12 | 00:00:00 | 2020-03-25 | [core, 2106, lab] +7 | study for 2106 midterm | 06:17:03 | 00:00:00 | 2020-03-28 | [core, 2106, midterm] +8 | lab 4 ex2 | 02:40:21 | 00:00:00 | 2020-03-30 | [core, 2106, lab] +9 | lab 4 demo | 02:13:14 | 00:00:00 | 2020-04-01 | [core, 2106, lab] +10 | post-lecture quiz | 00:00:00 | 00:15:48 | 2020-03-23 | [2113] +11 | 2113 tutorial questions | 00:00:00 | 00:48:54 | 2020-03-23 | [2113] +12 | debug list feature | 00:50:12 | 00:00:00 | 2020-03-25 | [core, 2113, tP] +13 | add delete feature | 01:12:04 | 00:00:00 | 2020-03-26 | [core, 2113, tP] +------------------------------------------------------------------------------------------- +``` + +### Chaining Finding/Filtering: `-s` +Users can chain `find` and `filter` commands to generate an even more specific sub-list of activities +based on his/her needs. +This is can be particularly useful when the user wants to generate a `graph` with minimal clutter. + + +#### Format: +* `filter -s TAGNAME1 TAGNAME2 TAGNAME3` +* `find -s KEYWORD1 / KEYWORD2 / KEYWORD3` + +#### Example: +``` +find study +------------------------------------------------------------------------------------------- +Here are the matching activities in your list: + + | Name | Duration | Target | Date | Tags +1 | study for ges quiz | 00:00:00 | 03:25:34 | 2020-03-28 | [ges, midterm] +2 | study for 2106 midterm | 00:00:00 | 06:17:03 | 2020-03-28 | [2106, midterm] +3 | study for german test | 00:00:00 | 03:00:00 | 2020-03-02 | [german, midterm] +4 | study vocab | 00:00:00 | 04:24:12 | 2020-03-28 | [german, vocab] +5 | study for ges quiz | 03:25:34 | 00:00:00 | 2020-03-28 | [ges, ge, midterm] +6 | study for 2106 midterm | 06:17:03 | 00:00:00 | 2020-03-28 | [core, 2106, midterm] +------------------------------------------------------------------------------------------- +filter -s ges +------------------------------------------------------------------------------------------- +Here are the matching activities in your list: + + | Name | Duration | Target | Date | Tags +1 | study for ges quiz | 00:00:00 | 03:25:34 | 2020-03-28 | [ges, midterm] +2 | study for ges quiz | 03:25:34 | 00:00:00 | 2020-03-28 | [ges, ge, midterm] +------------------------------------------------------------------------------------------- +``` ### Adding a to-do: `todo` Adds a to-do item to the list of to-dos. diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 41494329f..d7c4a388e 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -86,7 +86,7 @@ public static void printResults(ActivityList resultsList) { System.out.println(DIVIDER); System.out.println("Here are the matching activities in your list:\n"); System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %s", - "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); + "|", "Name", "|", "Duration", "|", "Target", "|", "Date", "|", "Tags")); for (int i = 0; i < resultsList.getSize(); i++) { if (resultsList.get(i).getTags() != null && !resultsList.get(i).getTags().isEmpty()) { printTableFormat(resultsList, i, true); From 22a9f2e7191727919ab7f7da72146e4d6a85157c Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Mon, 30 Mar 2020 22:50:22 +0800 Subject: [PATCH 185/415] removed unnecessary dividers --- src/main/java/jikan/ui/Ui.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index d7c4a388e..e53344b5e 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -190,7 +190,6 @@ public static void printGoals(HashMap tagsGoals, HashMap Date: Mon, 30 Mar 2020 22:52:50 +0800 Subject: [PATCH 186/415] Debug some stuff --- src/main/java/jikan/command/ListCommand.java | 20 ++++-- src/main/java/jikan/command/StartCommand.java | 62 ++++++++++--------- src/main/java/jikan/parser/Parser.java | 1 + 3 files changed, 50 insertions(+), 33 deletions(-) diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index 4da1efe06..370a54880 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -12,6 +12,7 @@ import java.time.Month; import java.time.YearMonth; import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.time.temporal.TemporalAdjusters; import java.util.Calendar; @@ -94,9 +95,14 @@ private void listInterval(ActivityList activityList) throws InvalidTimeFrameExce // If user has input a specific date to obtain the month from, use that; // Otherwise get current date if (listInputs.length == 2) { - Month month = Month.valueOf(listInputs[1].toUpperCase()); - YearMonth yearMonth = YearMonth.of(Calendar.getInstance().get(Calendar.YEAR), month.getValue()); - startDate = yearMonth.atDay(1); + try { + Month month = Month.valueOf(listInputs[1].toUpperCase()); + YearMonth yearMonth = YearMonth.of(Calendar.getInstance().get(Calendar.YEAR), month.getValue()); + startDate = yearMonth.atDay(1); + } catch (IllegalArgumentException e) { + Ui.printDivider("Please specify the full month name."); + return; + } } else { startDate = LocalDate.now(); } @@ -106,7 +112,13 @@ private void listInterval(ActivityList activityList) throws InvalidTimeFrameExce endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); break; default: - startDate = LocalDate.parse(listInputs[0], parser); + try { + startDate = LocalDate.parse(listInputs[0], parser); + } catch (DateTimeParseException e) { + Ui.printDivider("Please enter a valid date in the format dd/MM/yyyy or yyyy-MM-dd\n" + + "Or use day / week / month to view tasks in the respective time period."); + return; + } if (listInputs.length == 2) { endDate = LocalDate.parse(listInputs[1], parser); } diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 9ad3e3bc8..720e511a2 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -1,5 +1,6 @@ package jikan.command; +import jikan.exception.EmptyTagException; import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; @@ -42,25 +43,24 @@ public void executeCommand(ActivityList activityList) { // check if there exists an activity with this name String activityName = getActivityName(tagDelimiter,allocateDelimiter); + Parser.activityName = activityName; int index = activityList.findActivity(activityName); if (index != -1) { Ui.printDivider("There is already an activity with this name. Would you like to continue it?"); continueActivity(activityList, scanner, index); } else { try { - if (activityName.isEmpty()) { - throw new EmptyNameException(); - } - String line = parseActivity(tagDelimiter,allocateDelimiter); + parseActivity(tagDelimiter,allocateDelimiter); Parser.startTime = LocalDateTime.now(); - Log.makeFineLog("Started: " + Parser.activityName); - Ui.printDivider(line); - } catch (EmptyNameException e) { - Log.makeInfoLog("Activity started without activity name"); - Ui.printDivider("Activity name cannot be empty!"); + Log.makeFineLog("Started: " + activityName); + Ui.printDivider("Started: " + activityName); } catch (WrongDateFormatException w) { Log.makeInfoLog("Wrong format for allocated time."); Ui.printDivider("Please input in this format HH/MM/SS"); + } catch (EmptyNameException e) { + Ui.printDivider("Activity name cannot be empty!"); + } catch (EmptyTagException e) { + Ui.printDivider("Tags cannot be empty!"); } } } @@ -92,41 +92,45 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, * @param tagDelimiter the index of the tag delimiter. * @param allocateDelimiter the index of the allocation delimiter. */ - private String parseActivity(int tagDelimiter, int allocateDelimiter) throws EmptyNameException, - WrongDateFormatException { + private void parseActivity(int tagDelimiter, int allocateDelimiter) throws EmptyNameException, + WrongDateFormatException, EmptyTagException { String activityName = getActivityName(tagDelimiter, allocateDelimiter); - Parser.activityName = activityName; + if (activityName.isBlank()) { + throw new EmptyNameException(); + } String activityInfo; if (tagDelimiter != -1 || allocateDelimiter != -1) { activityInfo = this.parameters.substring(activityName.length() + 1); } else { - return "Started: " + Parser.activityName; - } - if (Parser.activityName.isEmpty()) { - throw new EmptyNameException(); + return; } if (allocateDelimiter != -1) { String allocatedTime; - activityInfo = activityInfo.substring(3); - int index = activityInfo.indexOf(" "); - if (index != -1) { - allocatedTime = activityInfo.substring(0,index); - activityInfo = activityInfo.substring(index + 1); - } else { - allocatedTime = activityInfo; - } try { + activityInfo = activityInfo.substring(3); + int index = activityInfo.indexOf(" "); + if (index != -1) { + allocatedTime = activityInfo.substring(0,index); + activityInfo = activityInfo.substring(index + 1); + } else { + allocatedTime = activityInfo; + } parseDuration(allocatedTime); - } catch (WrongDateFormatException w) { + } catch (WrongDateFormatException | StringIndexOutOfBoundsException w) { throw new WrongDateFormatException(); } } if (tagDelimiter != -1) { - activityInfo = activityInfo.substring(3); - String [] tagString = activityInfo.split(" "); - Parser.tags.addAll(Arrays.asList(tagString)); + try { + activityInfo = activityInfo.substring(3); + String [] tagString = activityInfo.split(" "); + Parser.tags.addAll(Arrays.asList(tagString)); + } catch (StringIndexOutOfBoundsException e) { + throw new EmptyTagException(); + } + } - return "Started: " + Parser.activityName; + //return "Started: " + Parser.activityName; } private String getActivityName(int tagDelimiter, int allocateDelimiter) { diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index e84d11010..5fbd53961 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -188,5 +188,6 @@ public static void resetInfo() { startTime = null; activityName = null; tags = new HashSet<>(); + allocatedTime = Duration.parse("PT0S"); } } \ No newline at end of file From 51db37f424d7d97e7c3f7435d4f20e23ba53e70a Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Mon, 30 Mar 2020 22:56:57 +0800 Subject: [PATCH 187/415] Added divider line --- src/main/java/jikan/ui/Ui.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index e53344b5e..a049ed933 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -96,7 +96,7 @@ public static void printResults(ActivityList resultsList) { } System.out.println(DIVIDER); } else { - System.out.println("There are no activities matching that description.\n"); + Ui.printDivider("There are no activities matching that description."); } } From a465439ff76881bef5ae0e19edbb90c027c727b2 Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 30 Mar 2020 22:58:54 +0800 Subject: [PATCH 188/415] Fix junit test --- src/main/java/jikan/command/StartCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 720e511a2..3ff8664a7 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -82,6 +82,7 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, Ui.printDivider(Parser.activityName + " was continued"); Log.makeFineLog(Parser.activityName + " was continued."); } else { + Parser.activityName = null; Ui.printDivider("Okay then, what else can I do for you?"); } } From 7da632ef3b1bc82f5233e08329513ac7b3534e33 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Mon, 30 Mar 2020 23:01:35 +0800 Subject: [PATCH 189/415] Revert "fixed printing errors" --- docs/UserGuide.md | 120 ++++++--------------------------- src/main/java/jikan/ui/Ui.java | 5 +- 2 files changed, 22 insertions(+), 103 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index aa4b6eaae..31451f8d0 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -30,112 +30,30 @@ Not done with an activity and want to continue it? Use the `continue` command to Finally, when you're done and want to close the app, simply say `bye` and Jikan will exit. This is just a quick overview of what Jikan can do for you. For more details on each individual command, read the command guide below. -## Ending an Activity: `end` -After an activity has been completed, the user can enter the `end` command for activity to be saved. -If an allocated time was given with the `/a` extension when it was started, the user will get a progress message -stated how he/she fared for the session. - -#### Example: -``` -end -------------------------------------------------------------------------------------------- -Ended: ger quiz 11 -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- -Almost there ! Here's your progress: -Progress for ger quiz 11: |******************************************** |89% completed -------------------------------------------------------------------------------------------- -``` + + ## Finding and Filtering Activities ### Finding Activities by Name: `find` -Users can request for a sub-list of activities that has any of the given keywords separated by ` / `. - -#### Format: -* `find KEYWORD` -* `find KEYWORD1 / KEYWORD2 / KEYWORD3` - -#### Example: -``` -find lab / tutorial -------------------------------------------------------------------------------------------- -Here are the matching activities in your list: - - | Name | Duration | Target | Date | Tags -1 | lab 3 ex1 demo | 00:00:00 | 02:14:54 | 2020-03-18 | [2106, lab] -2 | lab 3 ex2 | 00:00:00 | 03:13:14 | 2020-03-19 | [2106, lab] -3 | lab 3 ex3 | 07:51:12 | 00:00:00 | 2020-03-25 | [core, 2106, lab] -4 | lab 4 ex2 | 02:40:21 | 00:00:00 | 2020-03-30 | [core, 2106, lab] -5 | lab 4 demo | 02:13:14 | 00:00:00 | 2020-04-01 | [core, 2106, lab] -6 | 2106 tutorial 7 | 00:00:00 | 01:20:12 | 2020-03-18 | [2106] -7 | 2113 tutorial questions | 00:00:00 | 00:48:54 | 2020-03-23 | [2113] -8 | 2106 tutorial 8 | 00:00:00 | 01:23:00 | 2020-03-25 | [2106] -------------------------------------------------------------------------------------------- -``` +Users can request for a sub-list of activities that has names containing a given keyword to be printed. + +Format: `find KEYWORD` ### Filtering Activities by Tags: `filter` -Users can request for a sub-list of activities that has specific tags (separated only by spaces. - -#### Format: -* `filter TAGNAME` -* `filter TAGNAME1 TAGNAME2` - -#### Example: -``` -filter 2106 2113 -------------------------------------------------------------------------------------------- -Here are the matching activities in your list: - - | Name | Duration | Target | Date | Tags -1 | study for 2106 midterm | 00:00:00 | 06:17:03 | 2020-03-28 | [2106, midterm] -2 | 2106 tutorial 7 | 00:00:00 | 01:20:12 | 2020-03-18 | [2106] -3 | lab 3 ex1 demo | 00:00:00 | 02:14:54 | 2020-03-18 | [2106, lab] -4 | lab 3 ex2 | 00:00:00 | 03:13:14 | 2020-03-19 | [2106, lab] -5 | 2106 tutorial 8 | 00:00:00 | 01:23:00 | 2020-03-25 | [2106] -6 | lab 3 ex3 | 07:51:12 | 00:00:00 | 2020-03-25 | [core, 2106, lab] -7 | study for 2106 midterm | 06:17:03 | 00:00:00 | 2020-03-28 | [core, 2106, midterm] -8 | lab 4 ex2 | 02:40:21 | 00:00:00 | 2020-03-30 | [core, 2106, lab] -9 | lab 4 demo | 02:13:14 | 00:00:00 | 2020-04-01 | [core, 2106, lab] -10 | post-lecture quiz | 00:00:00 | 00:15:48 | 2020-03-23 | [2113] -11 | 2113 tutorial questions | 00:00:00 | 00:48:54 | 2020-03-23 | [2113] -12 | debug list feature | 00:50:12 | 00:00:00 | 2020-03-25 | [core, 2113, tP] -13 | add delete feature | 01:12:04 | 00:00:00 | 2020-03-26 | [core, 2113, tP] -------------------------------------------------------------------------------------------- -``` - -### Chaining Finding/Filtering: `-s` -Users can chain `find` and `filter` commands to generate an even more specific sub-list of activities -based on his/her needs. -This is can be particularly useful when the user wants to generate a `graph` with minimal clutter. - - -#### Format: -* `filter -s TAGNAME1 TAGNAME2 TAGNAME3` -* `find -s KEYWORD1 / KEYWORD2 / KEYWORD3` - -#### Example: -``` -find study -------------------------------------------------------------------------------------------- -Here are the matching activities in your list: - - | Name | Duration | Target | Date | Tags -1 | study for ges quiz | 00:00:00 | 03:25:34 | 2020-03-28 | [ges, midterm] -2 | study for 2106 midterm | 00:00:00 | 06:17:03 | 2020-03-28 | [2106, midterm] -3 | study for german test | 00:00:00 | 03:00:00 | 2020-03-02 | [german, midterm] -4 | study vocab | 00:00:00 | 04:24:12 | 2020-03-28 | [german, vocab] -5 | study for ges quiz | 03:25:34 | 00:00:00 | 2020-03-28 | [ges, ge, midterm] -6 | study for 2106 midterm | 06:17:03 | 00:00:00 | 2020-03-28 | [core, 2106, midterm] -------------------------------------------------------------------------------------------- -filter -s ges -------------------------------------------------------------------------------------------- -Here are the matching activities in your list: - - | Name | Duration | Target | Date | Tags -1 | study for ges quiz | 00:00:00 | 03:25:34 | 2020-03-28 | [ges, midterm] -2 | study for ges quiz | 03:25:34 | 00:00:00 | 2020-03-28 | [ges, ge, midterm] -------------------------------------------------------------------------------------------- -``` +Users can request for a sub-list of activities that has specific tags. + +Format: `filter TAGNAME1 TAGNAME2` + +### Further Finding/Filtering: `-s` +Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on his/her needs. +This is can be particularly useful when the user wants to generate a `graph`. + +This flag applies to `find` and `filter` commands only. + +Format: +* `filter -s TAGNAME1 TAGNAME2` +* `find -s keyword` + ### Adding a to-do: `todo` Adds a to-do item to the list of to-dos. diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index a049ed933..41494329f 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -86,7 +86,7 @@ public static void printResults(ActivityList resultsList) { System.out.println(DIVIDER); System.out.println("Here are the matching activities in your list:\n"); System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %s", - "|", "Name", "|", "Duration", "|", "Target", "|", "Date", "|", "Tags")); + "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); for (int i = 0; i < resultsList.getSize(); i++) { if (resultsList.get(i).getTags() != null && !resultsList.get(i).getTags().isEmpty()) { printTableFormat(resultsList, i, true); @@ -96,7 +96,7 @@ public static void printResults(ActivityList resultsList) { } System.out.println(DIVIDER); } else { - Ui.printDivider("There are no activities matching that description."); + System.out.println("There are no activities matching that description.\n"); } } @@ -190,6 +190,7 @@ public static void printGoals(HashMap tagsGoals, HashMap Date: Mon, 30 Mar 2020 23:01:49 +0800 Subject: [PATCH 190/415] Fix Welcome logo --- src/main/java/jikan/ui/Ui.java | 17 ++++- text-ui-test/EXPECTED.TXT | 129 ++++++++++++++++++--------------- 2 files changed, 83 insertions(+), 63 deletions(-) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index a1e8b08e1..f7ecf1516 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -12,10 +12,19 @@ import static jikan.Jikan.lastShownList; public class Ui { - public static final String GREETING = "Jikan"; + public static final String LOGO = "::::::::::: ::::::::::: ::: ::: ::: :::: :::\n" + + " :+: :+: :+: :+: :+: :+: :+:+: :+:\n" + + " +:+ +:+ +:+ +:+ +:+ +:+ :+:+:+ +:+\n" + + " +#+ +#+ +#++:++ +#++:++#++: +#+ +:+ +#+\n" + + " +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+#+#\n" + + "#+# #+# #+# #+# #+# #+# #+# #+# #+#+#\n" + + " ##### ########### ### ### ### ### ### ####"; + + public static final String WELCOMEMESSAGE = " Hello there! I'm Jikan, your trusty time tracker.\n" + + " What can I do for you today?"; public static final String DIVIDER = "-------------------------------" - + "------------------------------------------------------------"; + + "-----------------------------------------------------------"; public static final int PROGRESSCONVERTER = 2; @@ -25,7 +34,9 @@ public class Ui { /** Prints the logo and greeting so users know the app is working. */ public void printGreeting() { - System.out.println(GREETING); + System.out.println(LOGO); + System.out.println(DIVIDER); + System.out.println(WELCOMEMESSAGE); System.out.println(DIVIDER); } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 1640c8d08..cb6ffe70b 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,114 +1,123 @@ -Jikan -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +::::::::::: ::::::::::: ::: ::: ::: :::: ::: + :+: :+: :+: :+: :+: :+: :+:+: :+: + +:+ +:+ +:+ +:+ +:+ +:+ :+:+:+ +:+ + +#+ +#+ +#++:++ +#++:++#++: +#+ +:+ +#+ + +#+ +#+ +#+ +#+ +#+ +#+ +#+ +#+#+# +#+# #+# #+# #+# #+# #+# #+# #+# #+#+# + ##### ########### ### ### ### ### ### #### +------------------------------------------------------------------------------------------ + Hello there! I'm Jikan, your trusty time tracker. + What can I do for you today? +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Started: activity 1 -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Ended: activity 1 -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Started: activity 2 -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Ended: activity 2 -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Started: activity 3 -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ activity 3 is ongoing! -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Ended: activity 3 -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ activity 1 was continued -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Ended: activity 1 -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags 1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] 2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] 3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Date | Tags 1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] 2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Date | Tags 1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Date | Tags 1 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ There is already an activity with this name. Would you like to continue it? -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ activity 1 was continued -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Ended: activity 1 -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags 1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] 2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] 3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Please input an integer for the time interval. If you'd like to graph by tags, enter the command . -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Name | Duration activity 1 | activity 2 | activity 3 | -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Activity name cannot be empty! -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ You have not started any activity! -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ You have not started any activity! -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ ☹ OOPS!!! I'm sorry, but I don't know what that means :-( -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ No keyword was given. -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ No keyword was given. -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Activity name cannot be empty! -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ You have deleted activity 2 -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags 1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] 2 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] -------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ Bye! See you again. -------------------------------------------------------------------------------------------- +------------------------------------------------------------------------------------------ From 6eb843e359d56d9fcb58690fc07c49c1151fd71d Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 30 Mar 2020 23:15:57 +0800 Subject: [PATCH 191/415] Fix bug when editing tags --- src/main/java/jikan/command/EditCommand.java | 31 +++++++++++++++++-- src/main/java/jikan/command/GoalCommand.java | 16 +--------- .../exception/ExistingTagGoalException.java | 4 +++ 3 files changed, 34 insertions(+), 17 deletions(-) create mode 100644 src/main/java/jikan/exception/ExistingTagGoalException.java diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index 0e1e52c54..ea5b11fd8 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -1,5 +1,6 @@ package jikan.command; +import jikan.exception.ExistingTagGoalException; import jikan.exception.InvalidTimeFrameException; import jikan.log.Log; import jikan.activity.ActivityList; @@ -9,10 +10,12 @@ import jikan.parser.Parser; import jikan.ui.Ui; +import java.io.IOException; import java.time.Duration; import java.util.HashSet; import java.util.Set; +import static jikan.Jikan.tagFile; import static jikan.command.GoalCommand.parseDuration; /** @@ -87,8 +90,11 @@ public void executeCommand(ActivityList activityList) { activityList.updateName(index, newName); } if (!newTags.isEmpty()) { - activityList.updateTags(index, newTags); - //GoalCommand.updateTagFile(index, newTags); + if (existsInTag(activityList.get(index).getTags())) { + throw new ExistingTagGoalException(); + } else { + activityList.updateTags(index, newTags); + } } if (!tmpAlloc.isEmpty()) { @@ -113,7 +119,28 @@ public void executeCommand(ActivityList activityList) { } catch (StringIndexOutOfBoundsException | InvalidEditFormatException e) { Ui.printDivider("New details not provided!"); Log.makeInfoLog("Edit command failed as there was no updated activity detail provided."); + } catch (ExistingTagGoalException e) { + Ui.printDivider("Tag cannot be edited as there is an existing tag goal!"); + Log.makeInfoLog("Edit command failed as there was an existing tag goal tied to the tag."); + } catch (IOException e) { + Ui.printDivider("Error in loading the tag file!"); + Log.makeInfoLog("Edit command failed as there was an error in loading the tag file."); } } + /** + * Check if the tags have associated tag goals. + * @param oldTags the tags to be edited. + * @return true or false. + * @throws IOException if there is an error loading the file. + */ + public static boolean existsInTag(Set oldTags) throws IOException { + for (String i : oldTags) { + if (GoalCommand.checkIfExists(i) != -1) { + return true; + } + } + return false; + } + } diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index cff894db8..6b22bd9b8 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -108,7 +108,7 @@ public static void createFile(String filePath, File tagFile) throws IOException * @return index the index of the tag in the tag list. * @throws IOException when there is an error loading/creating the file. */ - private int checkIfExists(String tagName) throws IOException { + public static int checkIfExists(String tagName) throws IOException { BufferedReader br = new BufferedReader(new FileReader(TAG_FILE_PATH)); int index = 0; int status = 0; @@ -158,7 +158,6 @@ private static void updateGoal(String userInput, String tagName, Duration goalTi * * @param dataLine Line to write to file. */ - public static void addTagLine(String dataLine) { try { writeToFile(dataLine); @@ -167,19 +166,6 @@ public static void addTagLine(String dataLine) { } } - /** - * Remove the tag data at the specified index. - * - * @param index index of the tag to remove. - */ - public static void removeTagLine(int index) { - try { - removeLine(index); - } catch (IOException e) { - System.out.println("Error removing tag from tag file."); - } - } - /** * Removes the line whose index matches lineNumber from file. * diff --git a/src/main/java/jikan/exception/ExistingTagGoalException.java b/src/main/java/jikan/exception/ExistingTagGoalException.java new file mode 100644 index 000000000..9c1ba5d23 --- /dev/null +++ b/src/main/java/jikan/exception/ExistingTagGoalException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class ExistingTagGoalException extends Exception { +} From b0edbf28f717ea0b211e69bcb82053bcfbd93026 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Mon, 30 Mar 2020 23:17:29 +0800 Subject: [PATCH 192/415] fixed text-ui --- text-ui-test/EXPECTED.TXT | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 1640c8d08..b3523127f 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -37,20 +37,20 @@ Your completed activities: ------------------------------------------------------------------------------------------- Here are the matching activities in your list: - | Name | Duration | Date | Tags + | Name | Duration | Target | Date | Tags 1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] 2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Here are the matching activities in your list: - | Name | Duration | Date | Tags + | Name | Duration | Target | Date | Tags 1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- Here are the matching activities in your list: - | Name | Duration | Date | Tags + | Name | Duration | Target | Date | Tags 1 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- From 5b3eb65e599bf46c775923ef1489f33df56273fa Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Mon, 30 Mar 2020 23:24:25 +0800 Subject: [PATCH 193/415] Revert "fixed text-ui" --- text-ui-test/EXPECTED.TXT | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 986e55edb..cb6ffe70b 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -46,20 +46,20 @@ Your completed activities: ------------------------------------------------------------------------------------------ Here are the matching activities in your list: - | Name | Duration | Target | Date | Tags + | Name | Duration | Date | Tags 1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] 2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: - | Name | Duration | Target | Date | Tags + | Name | Duration | Date | Tags 1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: - | Name | Duration | Target | Date | Tags + | Name | Duration | Date | Tags 1 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ From 38449feedeff063733a5cad3d3205b5900dae219 Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 30 Mar 2020 23:30:54 +0800 Subject: [PATCH 194/415] Update manual testing in DG --- docs/DeveloperGuide.md | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index a619b7493..12528579f 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -245,3 +245,39 @@ Allow users to record their daily activities and track their time usage in a use 1. Download the jar file and docs folder 2. Copy both into an empty folder 3. Run the jar file in your terminal using the command `java -jar jikan.jar` + + It is important to include the docs folder to have data for testing! + + #### Listing activities + Test case: `list month april` + + Expected: A list of activities completed in the month of april should be shown. + + Test case: `list 25/03/2020` + + Expected: A list of activities completed on 25th March 2020 should be shown. + + #### Continuing activities + Test case: `continue lab 4 ex2` + + Expected: Message "lab 4 ex2 was continued" will be displayed. + + Test case: `start lab 4 ex2` + + Expected: Option to continue will be given. If 'yes' is typed, activity will be continued. + + #### Graphing activities + Test case: (to be done in succession) + + `find tutorial` then `graph 10` + + Expected: List of activities that contain 'tutorial' will be shown. + Then a chart of the duration of these activities will be shown. + + Test case: (to be done in succession) + + `list week` then `graph tags` + + Expected: List of activities completed this week will be shown. + Then a chart of the duration of the tags of these activities will be shown. + From bb1a12c70d769213f4b9bbad9ade8565876702da Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 30 Mar 2020 23:40:14 +0800 Subject: [PATCH 195/415] Fix text-ui test --- docs/DeveloperGuide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 12528579f..430ff6072 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -248,6 +248,8 @@ Allow users to record their daily activities and track their time usage in a use It is important to include the docs folder to have data for testing! + #### Starting activities + #### Listing activities Test case: `list month april` From 1af28fc932962e620513d53ad273f13c1a7aac6a Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 31 Mar 2020 11:44:11 +0800 Subject: [PATCH 196/415] Update UG --- docs/UserGuide.md | 59 ++++++++++++++++++++++++++++++--- docs/pictures/GraphTargets.png | Bin 0 -> 16572 bytes 2 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 docs/pictures/GraphTargets.png diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 31451f8d0..68284604f 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -13,7 +13,13 @@ Features ## Usage Jikan lets you record how much time you spend on various activities so that you can easily see what took up the most time today / this week / this month. -To start, record your first activity using the `start ACTIVITY_NAME` command. Add some tags to your activities to group similar activities together. When you are done with the activity, or want to move onto something else, tell Jikan to `end` and the Activity time will be recorded and saved to your list. +To start, record your first activity using the `start ACTIVITY_NAME` command. + +Add some tags to your activities to group similar activities together using `/t`. + +Add allocated time to your activities using `/a`. Do note that the time allocated for an activity is represent by the target column in the diagram below. (These two words are used interchangeably). + +When you are done with the activity, or want to move onto something else, tell Jikan to `end` and the Activity time will be recorded and saved to your list. You can view all your activities using the `list` command. Activities will be shown in this format: ![Continue command sequence diagram](./pictures/list.PNG) @@ -31,6 +37,45 @@ Finally, when you're done and want to close the app, simply say `bye` and Jikan This is just a quick overview of what Jikan can do for you. For more details on each individual command, read the command guide below. +## Usage of Automated Cleaning + +As Jikan is a time tracker application which works with various data files (data file for activities, log files for execution history +etc.), over time it can be a mess to deal with these data files especially when they get too big. Thus, Jikan provides automated cleaning +services for such situations. + +### Activating the automated cleaning: `clean on | clean log on` +At runtime, users can switch on the automated cleaning services. Once the automated cleaning is activated, the application will +do an auto cleanup of files at the start of every execution until this services is switch off. Do note that the cleaning will only start from the next execution. +(i.e no cleaning will be done for the current execution which activated auto cleaning). + +Note: \ +`clean on` activates the cleaning of data files where activities are stored. \ +`clean log on` activates the cleaning of log files where application execution history is stored. + +### Deactivating the automated cleaning: `clean off | clean log off` +At runtime, users can switch off the automated cleaning services. Once deactivated, the application will +stop doing an auto cleanup of files at the start of every execution. Similarly, the changes only applies to the next execution. + +Note:\ +When the application is executed for the first time, the automated cleaning is deactivated by default and will remain so until it is activated by the user. + +### Specifying how much data to clean: `clean /n NUMBER | clean log /n NUMBER` +At runtime, the user can manually set the amount of data to clean using these commands where NUMBER is an integer based on user input. +Thus, `clean /n 5` will automatically clean the top 5 oldest activities from the activity list upon every startup (assuming automated cleaning +is activated). + +Note:\ +Default value for NUMBER for data files : 3\ +Default value for NUMBER for log files : 10 + +## Graph Functions + +### Graph out all targets and their progress: `graph targets` +Using this command, the user will get a graphical representation of all activities with targets and their progress with respect to +the allocated time. + +![Continue command sequence diagram](./pictures/GraphTargets.png) + ## Finding and Filtering Activities @@ -75,7 +120,7 @@ Example of usage: ## Command Guide * Start an activity: `start ACTVITY_NAME` - * optional: `start ACTIVITY_NAME /t TAGS /a ALLOCATED_TIME` + * optional: `start ACTIVITY_NAME /a ALLOCATED_TIME /t TAGS` * Abort an activity: `abort` * Stop an activity: `end` * Continue an activity: `continue ACTIVITY_NAME` @@ -93,8 +138,12 @@ Example of usage: * View goals for tags: `goal` * Display graph by tags: `graph tags` * Display graph by duration: `graph INTERVAL` +* Display graph by targets: `graph targets` * Clean data files: `clean [command]` - * On auto data cleaner: `clean on` - * Off auto data cleaner: `clean off` - * Specify number of files: `clean /n NUMBER` + * Activate auto data cleaner: `clean on` + * Activate auto log cleaner: `clean log on` + * Deactivate auto data cleaner: `clean off` + * Deactivate auto log cleaner: `clean log off` + * Specify number of files to clean for data: `clean /n NUMBER` + * Specify number of files to clean for logs: `clean log /n NUMBER` * Terminate the program: `bye` diff --git a/docs/pictures/GraphTargets.png b/docs/pictures/GraphTargets.png new file mode 100644 index 0000000000000000000000000000000000000000..1d8f60b29be63b692bd28baa8c7916f11680ffba GIT binary patch literal 16572 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 r{ao9hm-@fCto(n Date: Tue, 31 Mar 2020 11:48:38 +0800 Subject: [PATCH 197/415] Change text-ui-test to today's date --- text-ui-test/EXPECTED.TXT | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index cb6ffe70b..6cec0625a 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -39,28 +39,28 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Date | Tags -1 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] +1 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ There is already an activity with this name. Would you like to continue it? @@ -74,9 +74,9 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Please input an integer for the time interval. @@ -115,8 +115,8 @@ You have deleted activity 2 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag] -2 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-30 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] +2 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Bye! See you again. From a1a882c4b1c36e40521ef01dcd2fb0aa3e1be70c Mon Sep 17 00:00:00 2001 From: nigellenl <42377706+nigellenl@users.noreply.github.com> Date: Tue, 31 Mar 2020 17:31:39 +0800 Subject: [PATCH 198/415] Set theme jekyll-theme-slate --- _config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 _config.yml diff --git a/_config.yml b/_config.yml new file mode 100644 index 000000000..c74188174 --- /dev/null +++ b/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-slate \ No newline at end of file From 42a94a9229854f880c4ae4368711645988f50e47 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 31 Mar 2020 17:32:56 +0800 Subject: [PATCH 199/415] Set theme jekyll-theme-slate --- docs/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index fc24e7a62..c74188174 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-hacker \ No newline at end of file +theme: jekyll-theme-slate \ No newline at end of file From eef63d94f8f7fb059296d713adf7cd5227f6113a Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 31 Mar 2020 18:25:41 +0800 Subject: [PATCH 200/415] Add multiple storage files functionality --- src/main/java/jikan/Jikan.java | 1 - .../java/jikan/activity/ActivityList.java | 19 ++++++++++++++++--- src/main/java/jikan/storage/Storage.java | 8 ++++---- .../java/jikan/storage/StorageHandler.java | 18 ++++++++++++++---- .../jikan/storage/StorageHandlerTest.java | 3 ++- 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 80fe96013..aac435b7b 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -59,7 +59,6 @@ public static void main(String[] args) throws InvalidTimeFrameException, IOExcep cleaner.autoClean(); logCleaner.autoClean(); activityList = storage.createActivityList(); - activityList.storage = storage; GoalCommand.createFile(TAG_FILE_PATH, tagFile); lastShownList.activities.addAll(activityList.activities); diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index f71cc215a..a41059e08 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -24,6 +24,7 @@ public class ActivityList { public ArrayList activities; public Storage storage; // Storage the list was loaded from + public StorageHandler storageHandler; /** * Constructor for a new activity list. @@ -32,12 +33,24 @@ public ActivityList() { this.activities = new ArrayList<>(); } + /** + * Constructor for a new activity list to be saved to a file. + * @param storage the storage object to use. + */ + public ActivityList(Storage storage) { + this.activities = new ArrayList<>(); + this.storage = storage; + this.storageHandler = new StorageHandler(storage); + } + /** * Loads activityList from data file. + * @param storage the storage object to use. * @param dataFile the datafile to be read from. */ - public ActivityList(File dataFile) { + public ActivityList(Storage storage, File dataFile) { this.activities = new ArrayList<>(); + this.storage = storage; populateTaskList(dataFile); } @@ -120,7 +133,7 @@ public void delete(int index) { */ public void deleteUpdateFile(int index) { try { - StorageHandler.removeLine(index, storage); + storageHandler.removeLine(index, storage); } catch (IOException e) { System.out.println("Error while deleting activity from data file."); } @@ -128,7 +141,7 @@ public void deleteUpdateFile(int index) { private void fieldChangeUpdateFile() { try { - StorageHandler.updateField(activities, storage); + storageHandler.updateField(activities, storage); } catch (IOException e) { System.out.println("Error while updating activity from data file."); } diff --git a/src/main/java/jikan/storage/Storage.java b/src/main/java/jikan/storage/Storage.java index 8f1c2595b..60637b571 100644 --- a/src/main/java/jikan/storage/Storage.java +++ b/src/main/java/jikan/storage/Storage.java @@ -14,7 +14,7 @@ public class Storage { /** Path to current data file. */ - public static String dataFilePath; + public String dataFilePath; /** File object for current data file. */ public File dataFile; @@ -37,7 +37,7 @@ public Storage(String dataFilePath) { * @param s The input string. * @throws IOException If an error occurs while writing. */ - public static void writeToFile(String s) throws IOException { + public void writeToFile(String s) throws IOException { FileWriter fw = new FileWriter(dataFilePath, true); fw.write(s + System.lineSeparator()); fw.close(); @@ -76,9 +76,9 @@ private void createDataFile() throws IOException { public ActivityList createActivityList() { try { if (loadFile()) { - activityList = new ActivityList(dataFile); + activityList = new ActivityList(this, dataFile); } else { - activityList = new ActivityList(); + activityList = new ActivityList(this); } } catch (IOException e) { System.out.println("Error loading/creating data file."); diff --git a/src/main/java/jikan/storage/StorageHandler.java b/src/main/java/jikan/storage/StorageHandler.java index b101af77d..8268bc55f 100644 --- a/src/main/java/jikan/storage/StorageHandler.java +++ b/src/main/java/jikan/storage/StorageHandler.java @@ -18,6 +18,16 @@ * Class containing useful functions for modifying the data file. */ public class StorageHandler { + Storage storage; + + /** + * Constructs a StorageHandler object for the input Storage. + * + * @param storage The data file's file path. + */ + public StorageHandler(Storage storage) { + this.storage = storage; + } /** * Removes the line whose index matches lineNumber from file at dataFilePath. @@ -26,9 +36,9 @@ public class StorageHandler { * @param storage Storage object which contains path to save file. * @throws IOException If an error occurs while writing the new list to file. */ - public static void removeLine(int lineNumber, Storage storage) throws IOException { + public void removeLine(int lineNumber, Storage storage) throws IOException { // Read file into list of strings, where each string is a line in the file - List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(Storage.dataFilePath), + List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(storage.dataFilePath), StandardCharsets.UTF_8)); //int removedIndex = 0; @@ -56,7 +66,7 @@ public static void removeLine(int lineNumber, Storage storage) throws IOExceptio * @param storage Storage object to obtain file path. * @throws IOException If an error occurs while writing the new list to file. */ - public static void updateField(ArrayList activities, Storage storage) throws IOException { + public void updateField(ArrayList activities, Storage storage) throws IOException { List fileContent = new ArrayList<>(); for (Activity a : activities) { fileContent.add(a.toData()); @@ -71,7 +81,7 @@ public static void updateField(ArrayList activities, Storage storage) * @param dataFile The file to save to. * @throws IOException If an error occurs while writing the new list to file. */ - public static void saveNewList(List newList, File dataFile) throws IOException { + public void saveNewList(List newList, File dataFile) throws IOException { FileOutputStream fileOutputStream = new FileOutputStream(dataFile); PrintWriter printWriter = new PrintWriter(fileOutputStream); diff --git a/src/test/java/jikan/storage/StorageHandlerTest.java b/src/test/java/jikan/storage/StorageHandlerTest.java index a210374a1..19d5efb35 100644 --- a/src/test/java/jikan/storage/StorageHandlerTest.java +++ b/src/test/java/jikan/storage/StorageHandlerTest.java @@ -18,6 +18,7 @@ public void removeLine() throws IOException { int random = (int )(Math.random() * 500 + 1); String filepath = "data/test" + random + ".txt"; Storage storage = new Storage(filepath); + StorageHandler storageHandler = new StorageHandler(storage); storage.loadFile(); String line1 = "a"; @@ -29,7 +30,7 @@ public void removeLine() throws IOException { storage.writeToFile(line2); storage.writeToFile(line3); - StorageHandler.removeLine(1, storage); + storageHandler.removeLine(1, storage); int i = 0; Scanner dataScanner = new Scanner(storage.dataFile); From 8b9e91f1ccf5409a026ac0f77ce3051da38aa619 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 31 Mar 2020 18:28:22 +0800 Subject: [PATCH 201/415] Fix style --- src/test/java/jikan/storage/StorageHandlerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/jikan/storage/StorageHandlerTest.java b/src/test/java/jikan/storage/StorageHandlerTest.java index 19d5efb35..eb31ff5f8 100644 --- a/src/test/java/jikan/storage/StorageHandlerTest.java +++ b/src/test/java/jikan/storage/StorageHandlerTest.java @@ -18,7 +18,6 @@ public void removeLine() throws IOException { int random = (int )(Math.random() * 500 + 1); String filepath = "data/test" + random + ".txt"; Storage storage = new Storage(filepath); - StorageHandler storageHandler = new StorageHandler(storage); storage.loadFile(); String line1 = "a"; @@ -30,6 +29,7 @@ public void removeLine() throws IOException { storage.writeToFile(line2); storage.writeToFile(line3); + StorageHandler storageHandler = new StorageHandler(storage); storageHandler.removeLine(1, storage); int i = 0; From e0e8278f06af6f5bbe63a704ce652fe3b535a717 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 31 Mar 2020 18:34:04 +0800 Subject: [PATCH 202/415] Fix tests --- src/main/java/jikan/activity/ActivityList.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index a41059e08..ab5d9c939 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -31,6 +31,7 @@ public class ActivityList { */ public ActivityList() { this.activities = new ArrayList<>(); + this.storageHandler = new StorageHandler(storage); } /** From 7aad62679cbbe23b498b548d47f79fea14356e2a Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 31 Mar 2020 18:49:19 +0800 Subject: [PATCH 203/415] Update UG --- docs/DeveloperGuide.md | 7 +++++++ docs/UserGuide.md | 14 ++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 12528579f..97a07a5f4 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -170,6 +170,13 @@ Although the current implementation of the continue feature disallows users to h As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, he/she will be given the option to continue the stated activity. ![decision flowchart](./pictures/continue_flowchart.PNG) +### 3.5 List feature +This feature accepts a + +#### 3.5.1 Current implementation +* `list`: without any parameters, the command displays the entire list. +* `list day` or `list daily`: list today's + ### 3.6 Find Feature This command accepts a keyword and searches the activity list for activities with names that contain the keyword. diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 68284604f..e5a9f8a3f 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -23,12 +23,16 @@ When you are done with the activity, or want to move onto something else, tell J You can view all your activities using the `list` command. Activities will be shown in this format: ![Continue command sequence diagram](./pictures/list.PNG) + You can also view all your activities over a period of time by using `list` with extra parameters. For example `list week` will return a list of all activities this current week, as shown below. ![Continue command sequence diagram](./pictures/list_week.PNG) + Filter out the activities you want to see using the `find` or `filter` command. This is our list after filtering out all our activities tagged as `core`. ![Continue command sequence diagram](./pictures/list_core.PNG) + To easily see what took up the most of your time, use the `graph` command to view a chart of your activities. ![Continue command sequence diagram](./pictures/graph_core.PNG) + Now it's clear that lab 3 ex3 took up the most of your time. Not done with an activity and want to continue it? Use the `continue` command to continue recording time for a previously started activity. @@ -125,6 +129,16 @@ Example of usage: * Stop an activity: `end` * Continue an activity: `continue ACTIVITY_NAME` * List all activities: `list` + * List today's activities: `list day` or `list daily` + * List this week's activities: `list week` or `list weekly` + * List a specific week's activities by day: `list week DATE` or `list weekly DATE`, + where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List this month's activities: `list month` or `list monthly` + * List a specific month's activities by day: `list month DATE` or `list monthly DATE`, + where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List a specific day's activities: `list DATE`, where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List activities within a time frame: `list DATE1 DATE2`, where both `DATE1` and `DATE2` are + in either `yyyy-MM-dd` or `dd/MM/yyyy` format * Edit an activity: `edit ACTIVITY_NAME [flag]` * Edit activity name: `edit ACTIVITY_NAME /en NEW_NAME` * Edit activity tags: `edit ACTIVITY_NAME /et NEW_TAG1 NEW_TAG2` From 4f5ea8fac458044155dbf3eef9bfc70b7687b5f1 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 31 Mar 2020 18:54:14 +0800 Subject: [PATCH 204/415] Add list feature to DG --- docs/DeveloperGuide.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 97a07a5f4..4d234e4b5 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -171,11 +171,28 @@ As users can only have activities with unique names, when a user wants to start ![decision flowchart](./pictures/continue_flowchart.PNG) ### 3.5 List feature -This feature accepts a +This feature is used to list activities within a range specified by the user. +If no parameter is passed to the `list` command, then all the stored activities will be displayed. +By passing a single date, the command returns all activities within that date. +By passing two dates, the command returns all activities that took place within the two dates. +(for an activity to be included in the range, both its start and end time must be within the specified time range). +The user can also provide a verbal command, such as `day`, `week`, or `month`, which +will return all the activities for that day, week or month respectively. +Additionally, the user can specify a specific week of month by including a date +(e.g. `list month 2020-03-01` returns all the activities in March 2020.) #### 3.5.1 Current implementation -* `list`: without any parameters, the command displays the entire list. -* `list day` or `list daily`: list today's +* List all activities: `list` + * List today's activities: `list day` or `list daily` + * List this week's activities: `list week` or `list weekly` + * List a specific week's activities by day: `list week DATE` or `list weekly DATE`, + where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List this month's activities: `list month` or `list monthly` + * List a specific month's activities by day: `list month DATE` or `list monthly DATE`, + where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List a specific day's activities: `list DATE`, where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List activities within a time frame: `list DATE1 DATE2`, where both `DATE1` and `DATE2` are + in either `yyyy-MM-dd` or `dd/MM/yyyy` format ### 3.6 Find Feature This command accepts a keyword and searches the activity list for activities with names that contain the keyword. From dd05d4ccb28e047ef4369e92434c5363093e7b55 Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Tue, 31 Mar 2020 19:01:49 +0800 Subject: [PATCH 205/415] Use inline code blocks for commands --- docs/UserGuide.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index e5a9f8a3f..6be71d125 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -64,13 +64,13 @@ Note:\ When the application is executed for the first time, the automated cleaning is deactivated by default and will remain so until it is activated by the user. ### Specifying how much data to clean: `clean /n NUMBER | clean log /n NUMBER` -At runtime, the user can manually set the amount of data to clean using these commands where NUMBER is an integer based on user input. +At runtime, the user can manually set the amount of data to clean using these commands where `NUMBER` is an integer based on user input. Thus, `clean /n 5` will automatically clean the top 5 oldest activities from the activity list upon every startup (assuming automated cleaning is activated). Note:\ -Default value for NUMBER for data files : 3\ -Default value for NUMBER for log files : 10 +Default value for `NUMBER` for data files : 3\ +Default value for `NUMBER` for log files : 10 ## Graph Functions @@ -94,7 +94,7 @@ Users can request for a sub-list of activities that has specific tags. Format: `filter TAGNAME1 TAGNAME2` ### Further Finding/Filtering: `-s` -Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on his/her needs. +Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on their needs. This is can be particularly useful when the user wants to generate a `graph`. This flag applies to `find` and `filter` commands only. From a47c8534e8284d7cbc755c591a44ed29f9e0bd32 Mon Sep 17 00:00:00 2001 From: btricec Date: Tue, 31 Mar 2020 19:04:42 +0800 Subject: [PATCH 206/415] Update DG --- docs/UserGuide.md | 67 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 6be71d125..c0a7df2a9 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -41,6 +41,73 @@ Finally, when you're done and want to close the app, simply say `bye` and Jikan This is just a quick overview of what Jikan can do for you. For more details on each individual command, read the command guide below. +## Commands +### Starting an activity: `start` +**Usage:** Starts recording the time for a new activity. + +**Format:** `start ACTIVITY_NAME /a ALLOCATED_TIME /t TAGS` + * `ACTIVITY_NAME` can contains spaces and must be less than 25 characters. +* `ACTIVITY_NAME` must also be unique (should the user start an already existing activity, the option to `continue` will be given). +* `ALLOCATED_TIME` should be of the format [HH/MM/SS]. +* `TAGS` are separated by spaces. +* `ALLOCATED_TIME` and `TAGS` are optional. + +**Example:** `start CS1010 assignment /a 01/30/00 /t CS1010 core` `start GER1000 quiz /t GER GEmod` +`start revision` + +### Continuing an activity: `continue` +**Usage:** Continues recording the time of an activity that you have previously started. + +**Format:** `continue ACTIVITY_NAME` +* `ACTIVITY_NAME` must be an existing activity in the activity list. + +**Example:** +`continue CS1010 assignment` + +### Ending an activity: `end` +**Usage:** Stops recording the time for an ongoing activity and stores it into the activity list. + +**Format:** `end` * An activity must be started or continued before it can be ended. + +### Aborting an activity: `abort` +**Usage:** Aborts the current activity and does not save it to the activity list. + +**Format:** `abort` + +### Deleteing an activity: `delete` +**Usage:** Deletes an activity in the activity list. + +**Format:** `delete ACTIVITY_NAME` + +### List activities: `list` +**Usage:** Displays a list of the completed activities. + +**Format:** `list TIME_PERIOD` +* If no `TIME_PERIOD` is given, all activities will be listed. +* `TIME_PERIOD` should be of the format [dd/MM/yyyy] or [yyyy-MM-dd] +* `TIME_PERIOD` can either be a specific date or over a range. + +**Example:** +`list` List all activities. +`list month` or `list monthly` Lists all activities in the current month. +`list week` or `list weekly` List all activities in the current week. +`list day` or `list daily` List all activities in the current day. +`list 01/01/2020` or `list 2020-01-01` List all activities on 1 Jan 2020. +`list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. + +### Graph the duration of your completed activities: `graph` +**Usage:** Gives a visual representation of the duration of all your past activities so that you can easily see what took up the most of your time. + +**Format:** `graph SCALE` or `graph tags` + +* Parameters for graph are either `SCALE` or `tags`. +* `SCALE` is the scale of the graph in minutes (i.e. how many minutes each unit in the graph represents) and should be an integer value. +* `graph tags` will graph the cumulative duration of individual tags (each unit represents 10 minutes) +* The graph will be based on the latest list displayed on the command prompt. + +**Example:** +`graph 10` + ## Usage of Automated Cleaning As Jikan is a time tracker application which works with various data files (data file for activities, log files for execution history From bc0e5d9a2876398f9328e349006e10fde1b0dff7 Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Tue, 31 Mar 2020 19:15:56 +0800 Subject: [PATCH 207/415] Use inline code blocks for commands --- docs/DeveloperGuide.md | 91 +++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 46 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index ced24b6e7..cead2d336 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -15,7 +15,7 @@ * Click Open as Project * Click OK to accept the default settings. * Verifying the setup - * Run the jikan.jikan and try a few commands + * Run `jikan.jikan` and try a few commands * Run the tests and ensure they all pass. ## 2. Design @@ -31,9 +31,9 @@ This section describes some noteworthy details on how certain features are imple #### 3.1.1 Current Implementation -The storage cleanup mechanism is stored internally as a StorageCleaner java class. The StorageCleaner class has an association with the Storage class and thus it is able to access and edit the datafile which contains the list of activities. +The storage cleanup mechanism is stored internally as a StorageCleaner class. The StorageCleaner class has an association with the Storage class and thus it is able to access and edit the datafile which contains the list of activities. -Additionally, when the StorageCleaner class is first initialised, it will create two files namely a status file and a data file in the “recycled” folder under the “data” folder. The status file keeps track of the activation status of the storage cleaner while the data file serves as a recycle bin for deleted data. +Additionally, when the StorageCleaner class is first initialised, it will create two files, namely a status file and a data file in the “recycled” folder under the “data” folder. The status file keeps track of the activation status of the storage cleaner while the data file serves as a recycle bin for deleted data. Moreover, the class also implements the following operations: @@ -55,21 +55,21 @@ Step 2. Read the first line of the status file, if a character ‘0’ is found, ##### setStatus -Step 1. Read the boolean parameter ‘status’. +Step 1. Read the boolean parameter `status`. -Step 2a. If ‘status’ is equal to true, activate the automated cleanup and write the character ‘1’ to the first line of the status file. (overwrite any existing value at the first line). +Step 2a. If `status` is equal to true, activate the automated cleanup and write the character ‘1’ to the first line of the status file. (overwrite any existing value at the first line). -Step 2b. If ‘status’ is equal to false, deactivate the automated cleanup and write the character ‘0’ to the first line of the status file. +Step 2b. If `status` is equal to false, deactivate the automated cleanup and write the character ‘0’ to the first line of the status file. ![image_info](./pictures/FlowchartsetStatus.png) ##### autoClean -Step 1. Check activation status of StorageCleaner through the class level attribute boolean toClean. +Step 1. Check activation status of StorageCleaner through the class level attribute boolean `toClean`. -Step 2a. If the attribute toClean is equal to false, return the operation and give control back to the caller. +Step 2a. If the attribute `toClean` is equal to `false`, return the operation and give control back to the caller. -Step 2b. If the attribute toClean is equal to true, access the storage data file and remove some of the activities starting from the oldest. Put these deleted activities into the data file under the ‘recycled’ folder. +Step 2b. If the attribute `toClean` is equal to `true`, access the storage data file and remove some of the activities starting from the oldest. Put these deleted activities into the data file under the ‘recycled’ folder. ![image_info](./pictures/SDautoClean.png) @@ -110,12 +110,12 @@ The edit feature allows the user to make changes to activities that have been sa #### 3.4.1 Current Implementation The following sequence diagram shows how the edit feature works. ![image_info](./pictures/EditSequenceDiagram.png) -The current implementation of the edit feature allows the user to edit only the name parameter of the activity. When the user wants to edit an activity using the edit command, the Parser creates a new EditCommand object. The executeCommand() method of the EditCommand object is called and the specified parameters are updated accordingly. +The current implementation of the edit feature allows the user to edit only the name parameter of the activity. When the user wants to edit an activity using the edit command, the Parser creates a new EditCommand object. The `executeCommand()` method of the EditCommand object is called and the specified parameters are updated accordingly. -The order of method calls to edit the activity details is as follows if the specified activity exists (meaning index != -1) else an exception is thrown: -1. The updateName() method of the ActivityList class is called, with the user-specified parameters of the activity index and new activity name -2. The get() method is self-invoked by the ActivityList class to obtain the activity at the given index -3. The setName() method of the Activity class is called to edit the activity name to the user-specified name +The order of method calls to edit the activity details is as follows if the specified activity exists (meaning `index >= 0`) else an exception is thrown: +1. The `updateName()` method of the ActivityList class is called, with the user-specified parameters of the activity index and new activity name +2. The `get()` method is self-invoked by the ActivityList class to obtain the activity at the given index +3. The `setName()` method of the Activity class is called to edit the activity name to the user-specified name 4. The activity with the updated name is returned to the activityList #### 3.4.2 Additional Implementations @@ -136,38 +136,38 @@ The continue feature allows the user to continue a previously ended activity. **Continuing an activity:** -When the user enters the command to continue an activity, a *ContinueCommand* object is created in *Parser*. The method *executeCommand()* of the *ContinueCommand* object is then called and does the following: +When the user enters the command to continue an activity, a *ContinueCommand* object is created in *Parser*. The method `executeCommand()` of the *ContinueCommand* object is then called and does the following: - 1. Checks if the given activity name exists in the activityList by calling *findActivity()* (if it doesn’t an exception is thrown, omitted in the sequence diagram above) - 2. Gets the *name* and *tags* of the activity to be continued and saves it to a public static variable of *Parser* object + 1. Checks if the given activity name exists in the activityList by calling `findActivity()` (if it doesn’t an exception is thrown, omitted in the sequence diagram above) + 2. Gets the `name` and `tags` of the activity to be continued and saves it to a public static variable of *Parser* object 3. Gets the current time and saves it to a public static variable of *Parser* object ![End command sequence diagram](./pictures/endActivity.PNG) **Ending a continued activity:** -When the user wants to end the continued activity, an *EndCommand* object is created in *Parser.* The method *executeCommand()* of the *ContinueCommand* object is then called and it in turn executes the *saveActivity()* method of the *ActivityList* class. The continued activity is then saved by executing the following: +When the user wants to end the continued activity, an *EndCommand* object is created in *Parser.* The method `executeCommand()` of the *ContinueCommand* object is then called and it in turn executes the `saveActivity()` method of the *ActivityList* class. The continued activity is then saved by executing the following: 1. Gets the current time and saves it to a public static variable of *Parser* object -2. Calculates the elapsed time using *between()* method of *Duration* class -3. Adds the elapsed time with the previous duration of the activity to get the *newDuration* using *plus()* method of Duration class -4. Calls the *updateDuration()* method, which updates the *duration* attribute of the continued activity in the *activityList* as well as the data.csv file +2. Calculates the elapsed time using the `between()` method of *Duration* class +3. Adds the elapsed time with the previous duration of the activity to get the `newDuration` using the `plus()` method of Duration class +4. Calls the `updateDuration()` method, which updates the `duration` attribute of the continued activity in the `activityList` as well as the `data.csv` file #### 3.5.2 Design Considerations **Execution:** - - Continue by activity name (current implementation) - **Cons:** Activity names have to be unique. - **Pros:** More versatile, resistant to changes in the activity list - - Continue by activity index - **Cons:** need to add an additional index field to the Activity class, + * Continue by activity name (current implementation) + * **Cons:** Activity names have to be unique. + * **Pros:** More versatile, resistant to changes in the activity list + * Continue by activity index + * **Cons:** need to add an additional index field to the Activity class, index is not fixed, changes when an activity is deleted - **Pros:** Can reuse activity names. + * **Pros:** Can reuse activity names. -Although the current implementation of the continue feature disallows users to have multiple activities with the same name, we felt that the versatility of this choice outweighed the cons. Firstly because if the activityList got too big, it would be hard for the user to get the index of the task he/she wanted to continue. Also, the index would constantly be changing when changes are made to the list. +Although the current implementation of the continue feature disallows users to have multiple activities with the same name, we felt that the versatility of this choice outweighed the cons. Firstly because if the activityList got too big, it would be hard for the user to get the index of the task they wanted to continue. Also, the index would constantly be changing when changes are made to the list. #### 3.5.3 Additional Features -As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, he/she will be given the option to continue the stated activity. +As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, they will be given the option to continue the stated activity. ![decision flowchart](./pictures/continue_flowchart.PNG) ### 3.5 List feature @@ -198,31 +198,32 @@ Additionally, the user can specify a specific week of month by including a date This command accepts a keyword and searches the activity list for activities with names that contain the keyword. #### 3.6.1 Current Implementation -* This feature is called by the user when the “find” command is entered into the command line. The string following the command is the keyword to match activity names to. +* This feature is called by the user when the `find` command is entered into the command line. The string following the command is the keyword to match activity names to. * The Parser will create a FindCommand object. -* The FindCommand will invoke its own executeCommand() method. - * The Parser's lastShownList will be cleared. - * Then it will loop through activityList to find activities with names that contain the keyword. - * If one is found, it will be added to lastShownList. - * printResults() of the Ui will be called: - * If lastShownList is not empty, it will print the matching activities. +* The FindCommand will invoke its own `executeCommand()` method. + * The Parser's `lastShownList` will be cleared. + * Then it will loop through `activityList` to find activities with names that contain the keyword. + * If one is found, it will be added to `lastShownList`. + * `printResults()` of the Ui will be called: + * If `lastShownList` is not empty, it will print the matching activities. * Else, it will respond to the user that there are no tasks which match the given keyword. ![find seq diagram](https://imgur.com/Icg5rdB.png) + ### 3.7 Filter Feature This feature accepts multiple space-separated keywords to search for activities with tags matching each keyword. #### 3.7.1 Current Implementation -* This feature is called by the user when the “filter” command is entered into the command line. The space separated strings following the command are the keywords to match activity tags with. +* This feature is called by the user when the `filter` command is entered into the command line. The space separated strings following the command are the keywords to match activity tags with. * The Parser will create a FilterCommand object. -* The FindCommand will invoke its own executeCommand() method. -* The Parser's lastShownList will be cleared. +* The FindCommand will invoke its own `executeCommand()` method. +* The Parser's `lastShownList` will be cleared. * For each keyword: - * Then it will loop through activityList to find activities with tags that contain the keyword. - * If one is found, it will be added to lastShownList. - * printResults() method of the Ui will be called - * If lastShownList is not empty, it will print the matching activities. + * Then it will loop through `activityList` to find activities with tags that contain the keyword. + * If one is found, it will be added to `lastShownList`. + * `printResults()` method of the Ui will be called + * If `lastShownList` is not empty, it will print the matching activities. * Else, it will respond to the user that there are no tasks which match the given keyword. @@ -272,12 +273,10 @@ Allow users to record their daily activities and track their time usage in a use It is important to include the docs folder to have data for testing! - #### Starting activities - #### Listing activities Test case: `list month april` - Expected: A list of activities completed in the month of april should be shown. + Expected: A list of activities completed in the month of April should be shown. Test case: `list 25/03/2020` From a46ac92c1eab18ea800cd249b3c97145eeb0e89c Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 31 Mar 2020 20:49:45 +0800 Subject: [PATCH 208/415] Add table of contents to DG --- docs/DeveloperGuide.md | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 4d234e4b5..e266d40c7 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,4 +1,42 @@ -# Developer Guide +# Developer Guide + +- [1. Setting Up](#1-setting-up) +- [2. Design](#2-design) +- [3. Implementation](#3-implementation) + - [3.1 Automated Storage Cleanup feature](#31-automated-storage-cleanup-feature) + - [3.1.1 Current Implementation](#311-current-implementation) + - [initialiseCleaner](#initialisecleaner) + - [setStatus](#setstatus) + - [autoClean](#autoclean) + - [3.1.2 Additional Implementation (proposed)](#312-additional-implementation-proposed) + - [3.2 Storage feature](#32-storage-feature) + - [3.3 Storage handler](#33-storage-handler) + - [3.4 Edit feature](#34-edit-feature) + - [3.4.1 Current Implementation](#341-current-implementation) + - [3.4.2 Additional Implementations](#342-additional-implementations) + - [3.4.3 Design Considerations](#343-design-considerations) + - [3.5 Continue Feature](#35-continue-feature) + - [3.5.1 Current Implementation](#351-current-implementation) + - [3.5.2 Design Considerations](#352-design-considerations) + - [3.5.3 Additional Features](#353-additional-features) + - [3.5 List feature](#35-list-feature) + - [3.5.1 Current implementation](#351-current-implementation-1) + - [3.6 Find Feature](#36-find-feature) + - [3.6.1 Current Implementation](#361-current-implementation) + - [3.7 Filter Feature](#37-filter-feature) + - [3.7.1 Current Implementation](#371-current-implementation) +- [4. Appendix](#4-appendix) + - [Product Scope](#product-scope) + - [Target user profile](#target-user-profile) + - [Value proposition](#value-proposition) + - [User Stories](#user-stories) + - [Non-Functional Requirements](#non-functional-requirements) + - [Glossary](#glossary) + - [Instructions for Manual Testing](#instructions-for-manual-testing) + - [Launch and Shutdown](#launch-and-shutdown) + - [Listing activities](#listing-activities) + - [Continuing activities](#continuing-activities) + - [Graphing activities](#graphing-activities) ## 1. Setting Up * Prerequisites From 301610a6065301870477762d4f717bc6f8807f30 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Tue, 31 Mar 2020 21:12:15 +0800 Subject: [PATCH 209/415] Attempt to de-conflict graphs portion --- docs/UserGuide.md | 111 ++++++++++++++++++++++------------------------ 1 file changed, 53 insertions(+), 58 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index c0a7df2a9..7c4157b76 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -95,18 +95,59 @@ This is just a quick overview of what Jikan can do for you. For more details on `list 01/01/2020` or `list 2020-01-01` List all activities on 1 Jan 2020. `list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. -### Graph the duration of your completed activities: `graph` -**Usage:** Gives a visual representation of the duration of all your past activities so that you can easily see what took up the most of your time. - -**Format:** `graph SCALE` or `graph tags` - -* Parameters for graph are either `SCALE` or `tags`. -* `SCALE` is the scale of the graph in minutes (i.e. how many minutes each unit in the graph represents) and should be an integer value. -* `graph tags` will graph the cumulative duration of individual tags (each unit represents 10 minutes) -* The graph will be based on the latest list displayed on the command prompt. - -**Example:** -`graph 10` +## Finding and Filtering Activities + +### Finding Activities by Name: `find` +**Usage:** Users can request for a sub-list of activities that has names containing a given keyword to be printed. + +Format: `find KEYWORD` + +### Filtering Activities by Tags: `filter` +**Usage:** Users can request for a sub-list of activities that has specific tags. + +Format: `filter TAGNAME1 TAGNAME2` + +### Further Finding/Filtering: `-s` +Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on their needs. +This is can be particularly useful when the user wants to generate a `graph`. + +This flag applies to `find` and `filter` commands only. + +Format: +* `filter -s TAGNAME1 TAGNAME2` +* `find -s keyword` + +## Graph Functions +By using the command following commands , users can get a visual representation of the time spent on each activity. +There are 3 types of graphs supported by Jikan: + * *Absolute time graph* - Total time spent on each activity: `graph` + * *Activity progress graph* - Progress of each activity in relation to its allocated time: `graph targets` + * *Tags progress graph* - Progress of each tag in relation to its allocated time: `graph tags` + +Tip: Use `find` and `filter` commands to reduce clutter as graphs are based on the last shown list of activities. + +### Absolute time graph: `graph` +**Usage:** Compare the time spent on activities based on the latest list displayed from calling `list`, `find` or +`filter`. The parameter `SCALE` refers to the minutes represented by each point on the graph. + +**Format:** `graph SCALE` + +**Example:** `graph 10` + +### Activity progress graph: `graph targets` +**Usage:** View the progress of activities in relation to their +`ALLOCATED_TIME`. + +Note: Only activities with `ALLOCATED_TIME` will be shown. + +![Continue command sequence diagram](./pictures/GraphTargets.png) + +### Tags Progress graph: `graph tag` +**Usage:** View the progress of tags in relation to their `goal`. + +Note: Only tags with `goal` will be shown. + +**Format:** `graph tag` ## Usage of Automated Cleaning @@ -138,53 +179,7 @@ is activated). Note:\ Default value for `NUMBER` for data files : 3\ Default value for `NUMBER` for log files : 10 - -## Graph Functions - -### Graph out all targets and their progress: `graph targets` -Using this command, the user will get a graphical representation of all activities with targets and their progress with respect to -the allocated time. - -![Continue command sequence diagram](./pictures/GraphTargets.png) - -## Finding and Filtering Activities - -### Finding Activities by Name: `find` -Users can request for a sub-list of activities that has names containing a given keyword to be printed. - -Format: `find KEYWORD` - -### Filtering Activities by Tags: `filter` -Users can request for a sub-list of activities that has specific tags. - -Format: `filter TAGNAME1 TAGNAME2` - -### Further Finding/Filtering: `-s` -Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on their needs. -This is can be particularly useful when the user wants to generate a `graph`. - -This flag applies to `find` and `filter` commands only. - -Format: -* `filter -s TAGNAME1 TAGNAME2` -* `find -s keyword` - - -### Adding a to-do: `todo` -Adds a to-do item to the list of to-dos. - -Format: `todo n/TODO_NAME d/DEADLINE` - -* The `DEADLINE` can be in a natural language format. -* The `TODO_NAME` cannot contain punctuation. - -Example of usage: - -`todo n/Write the rest of the User Guide d/next week` - -`todo n/Refactor the User Guide to remove passive voice d/13/04/2020` - ## FAQ From 1fab337a0f21b1bf22d52c3aa7c575e16a89ad38 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Tue, 31 Mar 2020 21:24:04 +0800 Subject: [PATCH 210/415] another attempt to de-conflict graphs --- docs/UserGuide.md | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7c4157b76..f9d60ba71 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -117,37 +117,37 @@ Format: * `filter -s TAGNAME1 TAGNAME2` * `find -s keyword` -## Graph Functions -By using the command following commands , users can get a visual representation of the time spent on each activity. -There are 3 types of graphs supported by Jikan: - * *Absolute time graph* - Total time spent on each activity: `graph` - * *Activity progress graph* - Progress of each activity in relation to its allocated time: `graph targets` - * *Tags progress graph* - Progress of each tag in relation to its allocated time: `graph tags` +## Graphs +By using the command following commands, users can get a visual representation of the time spent on each activity +and their progress. +There are 3 types of graphs supported are : + * *Activity time graph* - Total time spent on each activity: `graph` + * *Tags time graph* - Total time spent on each tag: `graph tags` + * *Activity targets graph* - Progress of each activity in relation to its targeted time: `graph targets` Tip: Use `find` and `filter` commands to reduce clutter as graphs are based on the last shown list of activities. -### Absolute time graph: `graph` -**Usage:** Compare the time spent on activities based on the latest list displayed from calling `list`, `find` or -`filter`. The parameter `SCALE` refers to the minutes represented by each point on the graph. +### Activity time graph: `graph` +**Usage:** View a comparison of the absolute time spent on each activity in the last shown list. +The parameter `SCALE` refers to the number of minutes represented by each point on the graph. **Format:** `graph SCALE` **Example:** `graph 10` -### Activity progress graph: `graph targets` -**Usage:** View the progress of activities in relation to their -`ALLOCATED_TIME`. +### Tags time graph: `graph tag` +**Usage:** View a comparison of the absolute time spent on each tag in the last shown list. -Note: Only activities with `ALLOCATED_TIME` will be shown. +**Format:** `graph tag` -![Continue command sequence diagram](./pictures/GraphTargets.png) +### Activity targets graph: `graph targets` +**Usage:** View the progress of activities in relation to their +targeted time. -### Tags Progress graph: `graph tag` -**Usage:** View the progress of tags in relation to their `goal`. +Note: Only activities with an `ALLOCATED_TIME` will be shown. -Note: Only tags with `goal` will be shown. +![Continue command sequence diagram](./pictures/GraphTargets.png) -**Format:** `graph tag` ## Usage of Automated Cleaning From e2edadac48a6b4231705e1486137364c8bf2b29e Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Tue, 31 Mar 2020 21:35:50 +0800 Subject: [PATCH 211/415] Updated Find and Filter --- docs/UserGuide.md | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index f9d60ba71..b6982c82a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -98,24 +98,30 @@ This is just a quick overview of what Jikan can do for you. For more details on ## Finding and Filtering Activities ### Finding Activities by Name: `find` -**Usage:** Users can request for a sub-list of activities that has names containing a given keyword to be printed. +**Usage:** Users can request for a sub-list of activities that has names which contain any of the give keywords. Each keyword should be separated with ` / `. -Format: `find KEYWORD` +**Format:** +* `find KEYWORD` +* `find KEYWORD1 / KEYWORD2 / KEYWORD3` ### Filtering Activities by Tags: `filter` -**Usage:** Users can request for a sub-list of activities that has specific tags. +**Usage:** Users can request for a sub-list of activities that has specific tags. Each tag should be space separated. -Format: `filter TAGNAME1 TAGNAME2` +**Format:** +* `filter TAGNAME` +* `filter TAGNAME1 TAGNAME2` -### Further Finding/Filtering: `-s` +### Chaining Finds & Filters: `-s` Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on their needs. This is can be particularly useful when the user wants to generate a `graph`. This flag applies to `find` and `filter` commands only. -Format: +**Format:** +* `find -s KEYWORD` +* `filter -s TAGNAME` * `filter -s TAGNAME1 TAGNAME2` -* `find -s keyword` +* `find -s KEYWORD1 / KEYWORD2 / KEYWORD3` ## Graphs By using the command following commands, users can get a visual representation of the time spent on each activity @@ -146,6 +152,8 @@ targeted time. Note: Only activities with an `ALLOCATED_TIME` will be shown. +**Format:** `graph targets` + ![Continue command sequence diagram](./pictures/GraphTargets.png) From 4db9a02123a46f2a0f0702f89dbd1490c73d1033 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Tue, 31 Mar 2020 21:41:41 +0800 Subject: [PATCH 212/415] Update UserGuide.md --- docs/UserGuide.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index b6982c82a..68c18e352 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -96,6 +96,7 @@ This is just a quick overview of what Jikan can do for you. For more details on `list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. ## Finding and Filtering Activities +By using `find` and `filter`, users can reduce clutter and zoom-in to specific activities. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further de-clutter the results. These features are particularly useful when the visualisation of time spent is required without unnecessary clutter. ### Finding Activities by Name: `find` **Usage:** Users can request for a sub-list of activities that has names which contain any of the give keywords. Each keyword should be separated with ` / `. From 921b3ab0a04d3acdebe215ef1110032644e71acf Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Tue, 31 Mar 2020 21:42:24 +0800 Subject: [PATCH 213/415] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 68c18e352..c92979ec0 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -41,7 +41,7 @@ Finally, when you're done and want to close the app, simply say `bye` and Jikan This is just a quick overview of what Jikan can do for you. For more details on each individual command, read the command guide below. -## Commands +## Basic Commands ### Starting an activity: `start` **Usage:** Starts recording the time for a new activity. From 5fb900ecbcb7ded1efe6e7b810384c463d88dc73 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Tue, 31 Mar 2020 21:47:22 +0800 Subject: [PATCH 214/415] Update UserGuide.md --- docs/UserGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index c92979ec0..01637006a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -95,8 +95,8 @@ This is just a quick overview of what Jikan can do for you. For more details on `list 01/01/2020` or `list 2020-01-01` List all activities on 1 Jan 2020. `list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. -## Finding and Filtering Activities -By using `find` and `filter`, users can reduce clutter and zoom-in to specific activities. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further de-clutter the results. These features are particularly useful when the visualisation of time spent is required without unnecessary clutter. +## Finding and Filtering +By using `find` and `filter` commands, users can reduce clutter and zoom-in to specific activities containing certain keywords or tags. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further reduce clutter. These features are particularly useful when the visualisation of time spent with minimal clutter is required. ### Finding Activities by Name: `find` **Usage:** Users can request for a sub-list of activities that has names which contain any of the give keywords. Each keyword should be separated with ` / `. From 75aa458d79214ecd97c6d8385d3e209e68ddd125 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Tue, 31 Mar 2020 21:50:37 +0800 Subject: [PATCH 215/415] Update UserGuide.md --- docs/UserGuide.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 01637006a..e0b59c4db 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -125,9 +125,8 @@ This flag applies to `find` and `filter` commands only. * `find -s KEYWORD1 / KEYWORD2 / KEYWORD3` ## Graphs -By using the command following commands, users can get a visual representation of the time spent on each activity -and their progress. -There are 3 types of graphs supported are : +By using the following commands, users can get a visual representation of the time spent on each activity and their current progress. +The 3 types of graphs are : * *Activity time graph* - Total time spent on each activity: `graph` * *Tags time graph* - Total time spent on each tag: `graph tags` * *Activity targets graph* - Progress of each activity in relation to its targeted time: `graph targets` From 7bd35e332ae18afd4103e367c2a21fb515bf01d6 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Tue, 31 Mar 2020 21:55:07 +0800 Subject: [PATCH 216/415] Update UserGuide.md --- docs/UserGuide.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index e0b59c4db..f5b7980bf 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -131,7 +131,7 @@ The 3 types of graphs are : * *Tags time graph* - Total time spent on each tag: `graph tags` * *Activity targets graph* - Progress of each activity in relation to its targeted time: `graph targets` -Tip: Use `find` and `filter` commands to reduce clutter as graphs are based on the last shown list of activities. +Tip: Use `find` and `filter` commands to reduce clutter before graphing as the graphs are based on the last shown list of activities. ### Activity time graph: `graph` **Usage:** View a comparison of the absolute time spent on each activity in the last shown list. @@ -215,9 +215,11 @@ Default value for `NUMBER` for log files : 10 * Edit activity allocated time: `edit ACTIVITY_NAME /ea NEW_ALLOCATED_TIME` * Delete an activity: `delete ACTIVITY_NAME` * Find activities with keyword: `find KEYWORD` + * optional: `find KEYWORD1 / KEYWORD2` for multiple keywords * optional: `find -s KEYWORD` for more specific find * Filter activities by tags: `filter TAG_NAME` - * optional: `filter -s TAG1 TAG2` for more specific filter + * optional: `filter TAG1 TAG2` for multiple tags + * optional: `filter -s TAG_NAME` for more specific filter * Set a goal for tags: `goal TAG_NAME /g DURATION` * View goals for tags: `goal` * Display graph by tags: `graph tags` From be15e4cb765a513b37b4d98fee785889fd3b3d55 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Tue, 31 Mar 2020 22:00:08 +0800 Subject: [PATCH 217/415] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index f5b7980bf..683de1d9c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -99,7 +99,7 @@ This is just a quick overview of what Jikan can do for you. For more details on By using `find` and `filter` commands, users can reduce clutter and zoom-in to specific activities containing certain keywords or tags. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further reduce clutter. These features are particularly useful when the visualisation of time spent with minimal clutter is required. ### Finding Activities by Name: `find` -**Usage:** Users can request for a sub-list of activities that has names which contain any of the give keywords. Each keyword should be separated with ` / `. +**Usage:** Users can request for a sub-list of activities that has names which contain any of the given keywords. If there are more than one keyword, each keyword should be separated with ` / `. **Format:** * `find KEYWORD` From d46ce333e56ee81460c634ad8fd27e7a56751e0c Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Tue, 31 Mar 2020 22:13:12 +0800 Subject: [PATCH 218/415] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 683de1d9c..9955893f9 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -96,7 +96,7 @@ This is just a quick overview of what Jikan can do for you. For more details on `list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. ## Finding and Filtering -By using `find` and `filter` commands, users can reduce clutter and zoom-in to specific activities containing certain keywords or tags. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further reduce clutter. These features are particularly useful when the visualisation of time spent with minimal clutter is required. +By using `find` and `filter` commands, users can reduce clutter and zoom-in to specific activities containing certain keywords or tags. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further reduce clutter. These features are particularly useful when the visualisation of time spent (with `graph` feature) with minimal clutter is required. ### Finding Activities by Name: `find` **Usage:** Users can request for a sub-list of activities that has names which contain any of the given keywords. If there are more than one keyword, each keyword should be separated with ` / `. From 519ce6676a31c3bea140ec963d5e66e72aae1db5 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Tue, 31 Mar 2020 22:14:05 +0800 Subject: [PATCH 219/415] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 9955893f9..490932fa7 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -96,7 +96,7 @@ This is just a quick overview of what Jikan can do for you. For more details on `list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. ## Finding and Filtering -By using `find` and `filter` commands, users can reduce clutter and zoom-in to specific activities containing certain keywords or tags. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further reduce clutter. These features are particularly useful when the visualisation of time spent (with `graph` feature) with minimal clutter is required. +By using `find` and `filter` commands, users can reduce clutter and zoom-in to specific activities containing certain keywords or tags. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further reduce clutter. These features are particularly useful when the visualisation of time spent (`graph`) with minimal clutter is required. ### Finding Activities by Name: `find` **Usage:** Users can request for a sub-list of activities that has names which contain any of the given keywords. If there are more than one keyword, each keyword should be separated with ` / `. From bde45ebc3b7063544eb90d696181060d9b4b8e1a Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Tue, 31 Mar 2020 22:25:29 +0800 Subject: [PATCH 220/415] Update UserGuide.md --- docs/UserGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 490932fa7..6f4efb239 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -185,8 +185,8 @@ Thus, `clean /n 5` will automatically clean the top 5 oldest activities from the is activated). Note:\ -Default value for `NUMBER` for data files : 3\ -Default value for `NUMBER` for log files : 10 +Default `NUMBER` value for data files : 3\ +Default `NUMBER` value for log files : 10 ## FAQ From d956960f253005ab385c32cf21ef0b8cfa9c1db5 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Tue, 31 Mar 2020 22:26:16 +0800 Subject: [PATCH 221/415] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 6f4efb239..dd9b0aaa3 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -74,7 +74,7 @@ This is just a quick overview of what Jikan can do for you. For more details on **Format:** `abort` -### Deleteing an activity: `delete` +### Deleting an activity: `delete` **Usage:** Deletes an activity in the activity list. **Format:** `delete ACTIVITY_NAME` From 9ab23480d52820b8019f0d02aa6274ff8b9c3fe3 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Tue, 31 Mar 2020 22:35:26 +0800 Subject: [PATCH 222/415] fixed missing header --- src/main/java/jikan/ui/Ui.java | 2 +- text-ui-test/EXPECTED.TXT | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 83cfe602a..22a33e1e2 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -97,7 +97,7 @@ public static void printResults(ActivityList resultsList) { System.out.println(DIVIDER); System.out.println("Here are the matching activities in your list:\n"); System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %s", - "|", "Name", "|", "Duration", "|", "Date", "|", "Tags")); + "|", "Name", "|", "Duration", "|", "Target","|", "Date", "|", "Tags")); for (int i = 0; i < resultsList.getSize(); i++) { if (resultsList.get(i).getTags() != null && !resultsList.get(i).getTags().isEmpty()) { printTableFormat(resultsList, i, true); diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 6cec0625a..a3a289886 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -46,20 +46,20 @@ Your completed activities: ------------------------------------------------------------------------------------------ Here are the matching activities in your list: - | Name | Duration | Date | Tags + | Name | Duration | Target | Date | Tags 1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] 2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: - | Name | Duration | Date | Tags + | Name | Duration | Target | Date | Tags 1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: - | Name | Duration | Date | Tags + | Name | Duration | Target | Date | Tags 1 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ From 334e4755245d4222ee03c701b789cce371c6a975 Mon Sep 17 00:00:00 2001 From: btricec Date: Tue, 31 Mar 2020 22:40:38 +0800 Subject: [PATCH 223/415] Edit UG --- docs/UserGuide.md | 33 +++++++++++++++++++-------------- docs/pictures/filter_eg.PNG | Bin 0 -> 6603 bytes docs/pictures/find_eg.PNG | Bin 0 -> 8615 bytes 3 files changed, 19 insertions(+), 14 deletions(-) create mode 100644 docs/pictures/filter_eg.PNG create mode 100644 docs/pictures/find_eg.PNG diff --git a/docs/UserGuide.md b/docs/UserGuide.md index dd9b0aaa3..ef551c6b8 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -17,7 +17,7 @@ To start, record your first activity using the `start ACTIVITY_NAME` command. Add some tags to your activities to group similar activities together using `/t`. -Add allocated time to your activities using `/a`. Do note that the time allocated for an activity is represent by the target column in the diagram below. (These two words are used interchangeably). +Add allocated time to your activities using `/a`. Do note that the time allocated for an activity is represented by the target column in the diagram below. (These two words are used interchangeably). When you are done with the activity, or want to move onto something else, tell Jikan to `end` and the Activity time will be recorded and saved to your list. @@ -51,8 +51,11 @@ This is just a quick overview of what Jikan can do for you. For more details on * `ALLOCATED_TIME` should be of the format [HH/MM/SS]. * `TAGS` are separated by spaces. * `ALLOCATED_TIME` and `TAGS` are optional. +* `ALLOCATED_TIME` must always come before `TAGS` if both are used. -**Example:** `start CS1010 assignment /a 01/30/00 /t CS1010 core` `start GER1000 quiz /t GER GEmod` +**Example:** +`start CS1010 assignment /a 01/30/00 /t CS1010 core` +`start GER1000 quiz /t GER GEmod` `start revision` ### Continuing an activity: `continue` @@ -67,14 +70,16 @@ This is just a quick overview of what Jikan can do for you. For more details on ### Ending an activity: `end` **Usage:** Stops recording the time for an ongoing activity and stores it into the activity list. -**Format:** `end` * An activity must be started or continued before it can be ended. +**Format:** `end` +* An activity must be started or continued before it can be ended. ### Aborting an activity: `abort` **Usage:** Aborts the current activity and does not save it to the activity list. **Format:** `abort` +* An activity must be started or continued before it can be ended. -### Deleting an activity: `delete` +### Delete an activity: `delete` **Usage:** Deletes an activity in the activity list. **Format:** `delete ACTIVITY_NAME` @@ -82,21 +87,23 @@ This is just a quick overview of what Jikan can do for you. For more details on ### List activities: `list` **Usage:** Displays a list of the completed activities. -**Format:** `list TIME_PERIOD` +**Format:** `list TIME_PERIOD` * If no `TIME_PERIOD` is given, all activities will be listed. -* `TIME_PERIOD` should be of the format [dd/MM/yyyy] or [yyyy-MM-dd] +* `TIME_PERIOD` can be `day` or `week` +* To list activities in a specific month of the current year, use `list month MONTH_NAME` where `MONTH_NAME` must be spelled out in full (i.e. January and not Jan). +* Otherwise, `TIME_PERIOD` should be of the format [dd/MM/yyyy] or [yyyy-MM-dd] * `TIME_PERIOD` can either be a specific date or over a range. **Example:** -`list` List all activities. -`list month` or `list monthly` Lists all activities in the current month. +`list` List all activities. +`list month april` Lists all activities in April. `list week` or `list weekly` List all activities in the current week. `list day` or `list daily` List all activities in the current day. `list 01/01/2020` or `list 2020-01-01` List all activities on 1 Jan 2020. `list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. ## Finding and Filtering -By using `find` and `filter` commands, users can reduce clutter and zoom-in to specific activities containing certain keywords or tags. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further reduce clutter. These features are particularly useful when the visualisation of time spent (`graph`) with minimal clutter is required. +By using `find` and `filter` commands, users can reduce clutter and zoom-in to specific activities containing certain keywords or tags. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further reduce clutter. These features are particularly useful when the visualisation of time spent with minimal clutter is required. ### Finding Activities by Name: `find` **Usage:** Users can request for a sub-list of activities that has names which contain any of the given keywords. If there are more than one keyword, each keyword should be separated with ` / `. @@ -113,8 +120,8 @@ By using `find` and `filter` commands, users can reduce clutter and zoom-in to s * `filter TAGNAME1 TAGNAME2` ### Chaining Finds & Filters: `-s` -Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on their needs. -This is can be particularly useful when the user wants to generate a `graph`. +Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on their needs. This sublist is generated based on the previously shown list and also works after a list command. +This is can be particularly useful when the user wants to generate a graph. This flag applies to `find` and `filter` commands only. @@ -127,7 +134,7 @@ This flag applies to `find` and `filter` commands only. ## Graphs By using the following commands, users can get a visual representation of the time spent on each activity and their current progress. The 3 types of graphs are : - * *Activity time graph* - Total time spent on each activity: `graph` + * *Activity time graph* - Total time spent on each activity: `graph SCALE` * *Tags time graph* - Total time spent on each tag: `graph tags` * *Activity targets graph* - Progress of each activity in relation to its targeted time: `graph targets` @@ -187,8 +194,6 @@ is activated). Note:\ Default `NUMBER` value for data files : 3\ Default `NUMBER` value for log files : 10 - -## FAQ ## Command Guide diff --git a/docs/pictures/filter_eg.PNG b/docs/pictures/filter_eg.PNG new file mode 100644 index 0000000000000000000000000000000000000000..b4975f9cfb3a9e986cf4f239cc0d84703090e704 GIT binary patch literal 6603 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 literal 0 HcmV?d00001 diff --git a/docs/pictures/find_eg.PNG b/docs/pictures/find_eg.PNG new file mode 100644 index 0000000000000000000000000000000000000000..5c62c21d693be23e0e0894eeb12731841bd946f8 GIT binary patch literal 8615 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 M@ydmYbGIJ;FIGboy8r+H literal 0 HcmV?d00001 From 6fc9d6639479983577bde79daccee6059521bece Mon Sep 17 00:00:00 2001 From: nigellenl Date: Tue, 31 Mar 2020 22:44:28 +0800 Subject: [PATCH 224/415] Update UG --- docs/UserGuide.md | 45 ++++++++++++++++++++++++++++------ docs/pictures/GoalDisplay.PNG | Bin 0 -> 3037 bytes 2 files changed, 38 insertions(+), 7 deletions(-) create mode 100644 docs/pictures/GoalDisplay.PNG diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 683de1d9c..32764955c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -47,12 +47,14 @@ This is just a quick overview of what Jikan can do for you. For more details on **Format:** `start ACTIVITY_NAME /a ALLOCATED_TIME /t TAGS` * `ACTIVITY_NAME` can contains spaces and must be less than 25 characters. -* `ACTIVITY_NAME` must also be unique (should the user start an already existing activity, the option to `continue` will be given). -* `ALLOCATED_TIME` should be of the format [HH/MM/SS]. -* `TAGS` are separated by spaces. -* `ALLOCATED_TIME` and `TAGS` are optional. + * `ACTIVITY_NAME` must also be unique (should the user start an already existing activity, the option to `continue` will be given). + * `ALLOCATED_TIME` should be of the format [HH/MM/SS]. + * `TAGS` are separated by spaces. + * `ALLOCATED_TIME` and `TAGS` are optional. -**Example:** `start CS1010 assignment /a 01/30/00 /t CS1010 core` `start GER1000 quiz /t GER GEmod` +**Example:** +`start CS1010 assignment /a 01/30/00 /t CS1010 core` +`start GER1000 quiz /t GER GEmod` `start revision` ### Continuing an activity: `continue` @@ -74,12 +76,12 @@ This is just a quick overview of what Jikan can do for you. For more details on **Format:** `abort` -### Deleteing an activity: `delete` +### Deleting an activity: `delete` **Usage:** Deletes an activity in the activity list. **Format:** `delete ACTIVITY_NAME` -### List activities: `list` +### Listing activities: `list` **Usage:** Displays a list of the completed activities. **Format:** `list TIME_PERIOD` @@ -95,6 +97,18 @@ This is just a quick overview of what Jikan can do for you. For more details on `list 01/01/2020` or `list 2020-01-01` List all activities on 1 Jan 2020. `list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. +### Editing an activity: `edit` +**Usage:** Edits the name or allocated time of an activity in the activity list. + +**Format** +* `edit ACTIVITY_NAME /en NEW_NAME` +* `edit ACTIVITY_NAME /ea NEW_ALLOCATED_TIME` + * `NEW_ALLOCATED_TIME` should be in the format [HH:MM:SS] + +**Example:** +`edit CS1010 assignment /en CS1010 assignment 2` Activity name is edited to `CS1010 assignment 2` +`edit CS1010 assignment /ea 10:00:00` Allocated time for activity is edited to `10:00:00` + ## Finding and Filtering By using `find` and `filter` commands, users can reduce clutter and zoom-in to specific activities containing certain keywords or tags. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further reduce clutter. These features are particularly useful when the visualisation of time spent with minimal clutter is required. @@ -156,6 +170,23 @@ Note: Only activities with an `ALLOCATED_TIME` will be shown. ![Continue command sequence diagram](./pictures/GraphTargets.png) +## Tag Goals + +By using the `goal` command, users can set specific goals for how long they would like to spend on activities under a certain tags as well as view the amount of time they have spent in total for those activities as compared to their goal. + +### Set goal: `goal TAG_NAME /g DURATION` +**Usage:** Sets a duration goal for a tag + +**Format:** `goal TAG_NAME /g DURATION` +* The duration should be in the format [HH:MM:SS] + +**Example:** `goal core /g 24:00:00` a goal of `24:00:00` is added for the tag `core` + +### View goals: `goal` +**Usage:** Displays the tags with their goals, actual time spent on activities with these tags and the difference between the 2 timings. + +**Format:** `goal` +![goal display](./pictures/GoalDisplay.png) ## Usage of Automated Cleaning diff --git a/docs/pictures/GoalDisplay.PNG b/docs/pictures/GoalDisplay.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a84dcc3b9191570181263338f680a5b148adcb29 GIT binary patch literal 3037 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 Nz|q#p25;>h^Cu2$)hz%3 literal 0 HcmV?d00001 From b216e72c07cc06d26f5d8a81420e3aa0f94bcd29 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Tue, 31 Mar 2020 22:57:35 +0800 Subject: [PATCH 225/415] Update UG --- docs/UserGuide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 0b923b024..7a339f2e9 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -69,7 +69,8 @@ This is just a quick overview of what Jikan can do for you. For more details on ### Ending an activity: `end` **Usage:** Stops recording the time for an ongoing activity and stores it into the activity list. -**Format:** `end` * An activity must be started or continued before it can be ended. +**Format:** `end` +* An activity must be started or continued before it can be ended. ### Aborting an activity: `abort` **Usage:** Aborts the current activity and does not save it to the activity list. @@ -186,7 +187,7 @@ By using the `goal` command, users can set specific goals for how long they woul **Usage:** Displays the tags with their goals, actual time spent on activities with these tags and the difference between the 2 timings. **Format:** `goal` -![goal display](./pictures/GoalDisplay.png) +![goal display](./pictures/GoalDisplay.PNG) ## Usage of Automated Cleaning @@ -242,7 +243,6 @@ Default `NUMBER` value for log files : 10 in either `yyyy-MM-dd` or `dd/MM/yyyy` format * Edit an activity: `edit ACTIVITY_NAME [flag]` * Edit activity name: `edit ACTIVITY_NAME /en NEW_NAME` - * Edit activity tags: `edit ACTIVITY_NAME /et NEW_TAG1 NEW_TAG2` * Edit activity allocated time: `edit ACTIVITY_NAME /ea NEW_ALLOCATED_TIME` * Delete an activity: `delete ACTIVITY_NAME` * Find activities with keyword: `find KEYWORD` From 3b9e168cd431b42d078618f086d573aa3abd3fb0 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Tue, 31 Mar 2020 23:18:29 +0800 Subject: [PATCH 226/415] Update UserGuide.md --- docs/UserGuide.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 92a4f64d3..7a2e0d56d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -131,9 +131,11 @@ By using `find` and `filter` commands, users can reduce clutter and zoom-in to s * `filter TAGNAME` * `filter TAGNAME1 TAGNAME2` -### Chaining Finds & Filters: `-s` -Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on their needs. This sublist is generated based on the previously shown list and also works after a list command. -This is can be particularly useful when the user wants to generate a graph. +### Chaining Lists, Finds & Filters: `-s` +Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on their needs. This sublist is generated based on the previously shown list and also works after a `list` command. +This is can be particularly useful when the user wants to generate a graph. + +**Sample Use Case:** The user can chain a `list month MONTH` for a specfic date range, followed by `filter -s TAGNAME` for a specific tag and finally `find -s KEYWORD1 / KEYWORD2` for specfic activities containing either keyword. This flag applies to `find` and `filter` commands only. From 08ea39da035aa7e56d0edec51974f696bbed81db Mon Sep 17 00:00:00 2001 From: btricec Date: Wed, 1 Apr 2020 00:07:57 +0800 Subject: [PATCH 227/415] Fix file update --- src/main/java/jikan/activity/ActivityList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index ab5d9c939..73cfe9bd9 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -31,7 +31,7 @@ public class ActivityList { */ public ActivityList() { this.activities = new ArrayList<>(); - this.storageHandler = new StorageHandler(storage); + //this.storageHandler = new StorageHandler(storage); } /** From 8b025a10d26a4cd47d91e495e506d8ba15f2b02a Mon Sep 17 00:00:00 2001 From: nigellenl Date: Wed, 1 Apr 2020 00:12:13 +0800 Subject: [PATCH 228/415] Update DG --- docs/DeveloperGuide.md | 106 ++++++++++++++++++++++++++--------------- 1 file changed, 67 insertions(+), 39 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 55a7411d4..af8390243 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -36,7 +36,9 @@ - [Launch and Shutdown](#launch-and-shutdown) - [Listing activities](#listing-activities) - [Continuing activities](#continuing-activities) + - [Editing activities](#editing-activities) - [Graphing activities](#graphing-activities) + - [Setting tag goals](#setting-tag-goals) ## 1. Setting Up * Prerequisites @@ -304,43 +306,69 @@ Allow users to record their daily activities and track their time usage in a use ### Instructions for Manual Testing - #### Launch and Shutdown - 1. Download the jar file and docs folder - 2. Copy both into an empty folder - 3. Run the jar file in your terminal using the command `java -jar jikan.jar` - - It is important to include the docs folder to have data for testing! - - #### Listing activities - Test case: `list month april` - - Expected: A list of activities completed in the month of April should be shown. - - Test case: `list 25/03/2020` - - Expected: A list of activities completed on 25th March 2020 should be shown. - - #### Continuing activities - Test case: `continue lab 4 ex2` - - Expected: Message "lab 4 ex2 was continued" will be displayed. - - Test case: `start lab 4 ex2` - - Expected: Option to continue will be given. If 'yes' is typed, activity will be continued. - - #### Graphing activities - Test case: (to be done in succession) - - `find tutorial` then `graph 10` - - Expected: List of activities that contain 'tutorial' will be shown. - Then a chart of the duration of these activities will be shown. - - Test case: (to be done in succession) - - `list week` then `graph tags` - - Expected: List of activities completed this week will be shown. - Then a chart of the duration of the tags of these activities will be shown. +#### Launch and Shutdown +1. Download the jar file and docs folder +2. Copy both into an empty folder +3. Run the jar file in your terminal using the command `java -jar jikan.jar` + +It is important to include the **docs folder** to have data for testing! + +#### Listing activities +Test case: `list month april` + +Expected: A list of activities completed in the month of April should be shown. + +Test case: `list 25/03/2020` + +Expected: A list of activities completed on 25th March 2020 should be shown. + +#### Continuing activities +Test case: `continue lab 4 ex2` + +Expected: Message "lab 4 ex2 was continued" will be displayed. + +Test case: `start lab 4 ex2` + +Expected: Option to continue will be given. If 'yes' is typed, activity will be continued. + +#### Editing activities +Test case: `edit lab 4 ex2 /en lab 4 ex3` + +Expected: Message "Activity named lab 4 ex2 has been updated!" will be displayed. +* The updated activity name can be seen by using the `list` command + +Test case: `edit lab 4 ex3 /ea 24:00:00` + +Expected: Message "Activity named lab 4 ex3 has been updated!" will be displayed. +* The updated activity allocated time can be seen by using the `list` command. + +#### Graphing activities +Test case: (to be done in succession) + +`find tutorial` then `graph 10` + +Expected: List of activities that contain 'tutorial' will be shown. +Then a chart of the duration of these activities will be shown. + +Test case: (to be done in succession) + +`list week` then `graph tags` + +Expected: List of activities completed this week will be shown. +Then a chart of the duration of the tags of these activities will be shown. + +#### Setting tag goals +Test case: `goal core /g 24:00:00` + +Expected: Message "The goal for core has been added!" will be displayed. + +Test case: `goal core /g 22:00:00` + +Expected: Message "The goal for this tag already exists, do you want to update the goal?" will be displayed. +* If 'yes' is entered, the goal will be updated and the message "The goal for core was updated" will be displayed. +* If 'no' is entered, the message "Okay then, what else can I do for you?" will be displayed and the program will wait for user's next command. + +Test case: `goal` + +Expected: List of tags and their associated goals will be displayed. From 9e3d0d379adff5bcd23997a952e017e079b7c9fe Mon Sep 17 00:00:00 2001 From: btricec Date: Wed, 1 Apr 2020 00:22:22 +0800 Subject: [PATCH 229/415] Add set up instructions to DG and UG --- docs/DeveloperGuide.md | 10 ++++++---- docs/UserGuide.md | 5 ++++- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 55a7411d4..8c304b99a 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -305,11 +305,13 @@ Allow users to record their daily activities and track their time usage in a use ### Instructions for Manual Testing #### Launch and Shutdown - 1. Download the jar file and docs folder - 2. Copy both into an empty folder - 3. Run the jar file in your terminal using the command `java -jar jikan.jar` + 1. Download the jar file and data.csv file. + 2. Copy both into an empty folder. + 3. Create a folder named `data` and put the data.csv file into this folder. + 4. Ensure the folder `data` and `jikan.jar` are in the same folder. + 5. Open command prompt and navigate to the folder. Run the jar file using `java -jar jikan.jar` - It is important to include the docs folder to have data for testing! + It is important to include the data.csv file to have data for testing! #### Listing activities Test case: `list month april` diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7a2e0d56d..e0fe29fea 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -6,7 +6,10 @@ Jikan is a CLI time management tool that allows you to track the amount of time ## Quick Start 1. Ensure that you have Java 11 or above installed. -1. Download the latest version of `Jikan` from [here](https://github.com/AY1920S2-CS2113-T15-1/tp/releases). +1. Download the jar file of the latest version of `Jikan` from [here](https://github.com/AY1920S2-CS2113-T15-1/tp/releases). +3. Download the data.csv file. +4. Create an empty folder and put the Jikan.jar file inside. +6. Open command prompt and navigate to the folder. Run the jar file using `java -jar jikan.jar` Features ======= From 35de897466b3d5642d20f910706d4116c19c7c0a Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Wed, 1 Apr 2020 00:28:36 +0800 Subject: [PATCH 230/415] Update ActivityList.java --- src/main/java/jikan/activity/ActivityList.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 73cfe9bd9..f3c0dc853 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -52,6 +52,7 @@ public ActivityList(Storage storage) { public ActivityList(Storage storage, File dataFile) { this.activities = new ArrayList<>(); this.storage = storage; + this.storageHandler = new StorageHandler(storage); populateTaskList(dataFile); } From 8463e003fe46d7fb788b7490286e0229b07082e9 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Wed, 1 Apr 2020 16:21:19 +0800 Subject: [PATCH 231/415] Fix list edge case --- src/main/java/jikan/Jikan.java | 2 +- .../java/jikan/activity/ActivityList.java | 1 - src/main/java/jikan/command/Command.java | 2 +- src/main/java/jikan/command/ListCommand.java | 22 +++++++++---------- src/main/java/jikan/parser/Parser.java | 3 +++ .../java/jikan/command/AbortCommandTest.java | 2 +- .../java/jikan/command/DeleteCommandTest.java | 2 +- 7 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index aac435b7b..73b75a2ca 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -52,7 +52,7 @@ public class Jikan { /** * Main entry-point for the Jikan application. */ - public static void main(String[] args) throws InvalidTimeFrameException, IOException, EmptyNameException { + public static void main(String[] args) throws IOException, EmptyNameException { ui.printGreeting(); storage = new Storage(DATA_FILE_PATH); cleaner = new StorageCleaner(storage); diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index f3c0dc853..486e29ebf 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -31,7 +31,6 @@ public class ActivityList { */ public ActivityList() { this.activities = new ArrayList<>(); - //this.storageHandler = new StorageHandler(storage); } /** diff --git a/src/main/java/jikan/command/Command.java b/src/main/java/jikan/command/Command.java index e9be1c776..b66d851a2 100644 --- a/src/main/java/jikan/command/Command.java +++ b/src/main/java/jikan/command/Command.java @@ -21,7 +21,7 @@ public Command(String parameters) { /** * Executes the command and returns the result. */ - public void executeCommand(ActivityList activityList) throws EmptyNameException, InvalidTimeFrameException { + public void executeCommand(ActivityList activityList) throws EmptyNameException { } diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index 370a54880..c8c27f462 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -15,6 +15,7 @@ import java.time.format.DateTimeParseException; import java.time.temporal.TemporalAdjusters; import java.util.Calendar; +import java.util.Date; import static jikan.Jikan.lastShownList; @@ -36,7 +37,7 @@ public ListCommand(String parameters) { * @param activityList The activity list to search for matching activities. */ @Override - public void executeCommand(ActivityList activityList) throws InvalidTimeFrameException { + public void executeCommand(ActivityList activityList) { // If no time frame is specified, print the entire list if (parameters == null) { lastShownList.activities.clear(); @@ -47,13 +48,17 @@ public void executeCommand(ActivityList activityList) throws InvalidTimeFrameExc } else { try { listInterval(activityList); - } catch (ParseException e) { - System.out.println("invalid date."); + } catch (DateTimeParseException e) { + Ui.printDivider("Please enter a valid date in the format dd/MM/yyyy or yyyy-MM-dd\n" + + "Or use day / week / month to view tasks in the respective time period."); + } catch (InvalidTimeFrameException e) { + Ui.printDivider("Please enter a valid time frame; the end date must come after the start date."); } } } - private void listInterval(ActivityList activityList) throws InvalidTimeFrameException, ParseException { + private void listInterval(ActivityList activityList) + throws InvalidTimeFrameException, DateTimeParseException { String[] listInputs; listInputs = parameters.split(" ", 2); @@ -112,13 +117,8 @@ private void listInterval(ActivityList activityList) throws InvalidTimeFrameExce endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); break; default: - try { - startDate = LocalDate.parse(listInputs[0], parser); - } catch (DateTimeParseException e) { - Ui.printDivider("Please enter a valid date in the format dd/MM/yyyy or yyyy-MM-dd\n" - + "Or use day / week / month to view tasks in the respective time period."); - return; - } + startDate = LocalDate.parse(listInputs[0], parser); + if (listInputs.length == 2) { endDate = LocalDate.parse(listInputs[1], parser); } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 5fbd53961..905696fa0 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,5 +1,6 @@ package jikan.parser; +import jikan.exception.InvalidTimeFrameException; import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; @@ -31,9 +32,11 @@ import jikan.ui.Ui; import jikan.log.Log; +import java.text.ParseException; import java.time.Duration; import java.io.File; import java.time.LocalDateTime; +import java.time.format.DateTimeParseException; import java.util.HashSet; import java.util.Scanner; import java.util.Set; diff --git a/src/test/java/jikan/command/AbortCommandTest.java b/src/test/java/jikan/command/AbortCommandTest.java index 3b1ca36ce..4225b6f97 100644 --- a/src/test/java/jikan/command/AbortCommandTest.java +++ b/src/test/java/jikan/command/AbortCommandTest.java @@ -18,7 +18,7 @@ void executeAbort() { try { command.executeCommand(null); assertNull(Parser.startTime); - } catch (EmptyNameException | InvalidTimeFrameException e) { + } catch (EmptyNameException e) { System.out.println("Filed error."); } } diff --git a/src/test/java/jikan/command/DeleteCommandTest.java b/src/test/java/jikan/command/DeleteCommandTest.java index 2a424d15c..afc145dfb 100644 --- a/src/test/java/jikan/command/DeleteCommandTest.java +++ b/src/test/java/jikan/command/DeleteCommandTest.java @@ -52,7 +52,7 @@ void executeDelete() { Command command = new DeleteCommand(parameters); try { command.executeCommand(activities); - } catch (EmptyNameException | InvalidTimeFrameException e) { + } catch (EmptyNameException e) { System.out.println("Field error."); } From 6d9865ac01b1625fe2e3e4648a515510533278fa Mon Sep 17 00:00:00 2001 From: nigellenl Date: Wed, 1 Apr 2020 16:31:01 +0800 Subject: [PATCH 232/415] Fix negative duration exception handling --- src/main/java/jikan/command/EditCommand.java | 10 ++++-- src/main/java/jikan/command/GoalCommand.java | 33 ++++++++++++++++--- .../exception/NegativeDurationException.java | 4 +++ 3 files changed, 40 insertions(+), 7 deletions(-) create mode 100644 src/main/java/jikan/exception/NegativeDurationException.java diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index ea5b11fd8..d5186d501 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -2,6 +2,7 @@ import jikan.exception.ExistingTagGoalException; import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NegativeDurationException; import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; @@ -48,7 +49,6 @@ public void executeCommand(ActivityList activityList) { //edit allocatedTime } else { Parser.activityName = parameters.substring(0, allocDelim).strip(); - } if (Parser.activityName.isEmpty()) { @@ -98,7 +98,11 @@ public void executeCommand(ActivityList activityList) { } if (!tmpAlloc.isEmpty()) { - activityList.updateAlloc(index, newAllocTime); + if (newAllocTime.isNegative()) { + throw new NegativeDurationException(); + } else { + activityList.updateAlloc(index, newAllocTime); + } } } else { // no new details provided @@ -125,6 +129,8 @@ public void executeCommand(ActivityList activityList) { } catch (IOException e) { Ui.printDivider("Error in loading the tag file!"); Log.makeInfoLog("Edit command failed as there was an error in loading the tag file."); + } catch (NegativeDurationException e) { + Ui.printDivider("Please enter a positive target time!"); } } diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index 6b22bd9b8..78e91f4f9 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -4,6 +4,7 @@ import jikan.activity.ActivityList; import jikan.exception.EmptyTagException; import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NegativeDurationException; import jikan.exception.NoSuchTagException; import jikan.ui.Ui; @@ -45,15 +46,19 @@ public GoalCommand(String parameters, Scanner scanner) { public void executeCommand(ActivityList activityList) { try { int delimiter = parameters.indexOf("/g"); - String tagName = parameters.substring(0, delimiter - 1).strip(); - if (tagName.isEmpty()) { - throw new EmptyTagException(); - } + int deleteDelim = parameters.indexOf("/d"); + String tagName = ""; + int index; if (delimiter != -1) { - int index = checkIfExists(tagName); + tagName = parameters.substring(0, delimiter - 1).strip(); + index = checkIfExists(tagName); String tmpTime = parameters.substring(delimiter + 3); Duration goalTime = parseDuration(tmpTime); + if (goalTime.isNegative()) { + throw new NegativeDurationException(); + } + if (index != -1) { Ui.printDivider("The goal for this tag already exists, do you want to update the goal?"); String userInput = scanner.nextLine(); @@ -68,9 +73,25 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider("The goal for " + tagName + " has been added!"); } } + } else if (deleteDelim != -1) { + tagName = parameters.substring(0, deleteDelim - 1).strip(); + index = checkIfExists(tagName); + if (index != -1) { + Ui.printDivider("The goal for this tag has been deleted!"); + removeLine(index); + } else { + throw new NoSuchTagException(); + } } else { throw new InvalidTimeFrameException(); } + if (tagName.isEmpty()) { + throw new EmptyTagException(); + } + if (delimiter != -1) { + + } + } catch (EmptyTagException | StringIndexOutOfBoundsException e) { Ui.printDivider("Tag name cannot be empty!"); } catch (InvalidTimeFrameException e) { @@ -81,6 +102,8 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider("There is no such tag!"); } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { Ui.printDivider("Please enter the goal in the format HH:MM:SS"); + } catch (NegativeDurationException e) { + Ui.printDivider("Please enter a positive goal time!"); } } diff --git a/src/main/java/jikan/exception/NegativeDurationException.java b/src/main/java/jikan/exception/NegativeDurationException.java new file mode 100644 index 000000000..2ffe6d722 --- /dev/null +++ b/src/main/java/jikan/exception/NegativeDurationException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class NegativeDurationException extends Exception { +} From 19e86d40c14dfd7a86f89a21fed3dd2ddc078185 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Wed, 1 Apr 2020 16:35:47 +0800 Subject: [PATCH 233/415] Refactor exception handling for command execution --- src/main/java/jikan/Jikan.java | 34 +++++++++++++++--------- src/main/java/jikan/command/Command.java | 1 + 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 73b75a2ca..0eb0de29d 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -52,29 +52,39 @@ public class Jikan { /** * Main entry-point for the Jikan application. */ - public static void main(String[] args) throws IOException, EmptyNameException { + public static void main(String[] args) { ui.printGreeting(); storage = new Storage(DATA_FILE_PATH); cleaner = new StorageCleaner(storage); - cleaner.autoClean(); - logCleaner.autoClean(); - activityList = storage.createActivityList(); - GoalCommand.createFile(TAG_FILE_PATH, tagFile); + try { + cleaner.autoClean(); + logCleaner.autoClean(); + activityList = storage.createActivityList(); + GoalCommand.createFile(TAG_FILE_PATH, tagFile); + } catch (IOException e) { + Ui.printDivider("Error while preparing application."); + } lastShownList.activities.addAll(activityList.activities); parser.cleaner = cleaner; parser.logcleaner = logCleaner; while (true) { - Command command = parser.parseUserCommands(in,activityList,cleaner,tagFile); - if (command == null) { - continue; - } - if (ByeCommand.isExit(command)) { + try { + Command command = parser.parseUserCommands(in, activityList, cleaner, tagFile); + if (command == null) { + continue; + } + if (ByeCommand.isExit(command)) { + command.executeCommand(activityList); + break; + } command.executeCommand(activityList); - break; + // This block should theoretically never be entered (if command is empty, it just continues) + // However, you never know.. + } catch (EmptyNameException e) { + Ui.printDivider("Error parsing command. Please try again."); } - command.executeCommand(activityList); } } } diff --git a/src/main/java/jikan/command/Command.java b/src/main/java/jikan/command/Command.java index b66d851a2..8be6ed9d5 100644 --- a/src/main/java/jikan/command/Command.java +++ b/src/main/java/jikan/command/Command.java @@ -22,6 +22,7 @@ public Command(String parameters) { * Executes the command and returns the result. */ public void executeCommand(ActivityList activityList) throws EmptyNameException { + throw new EmptyNameException(); } From 8bef77700d92dd43cfcfe797aacb67130468f7a6 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Wed, 1 Apr 2020 17:18:32 +0800 Subject: [PATCH 234/415] Fix issue with activities longer than 25 characters --- src/main/java/jikan/activity/Activity.java | 9 +++++++-- src/main/java/jikan/activity/ActivityList.java | 11 +++++++---- src/main/java/jikan/command/ByeCommand.java | 6 +++++- src/main/java/jikan/command/EndCommand.java | 4 ++++ src/main/java/jikan/command/StartCommand.java | 7 +++++++ .../java/jikan/exception/NameTooLongException.java | 7 +++++++ src/test/java/jikan/activity/ActivityListTest.java | 3 ++- src/test/java/jikan/activity/ActivityTest.java | 3 +++ .../java/jikan/command/ContinueCommandTest.java | 8 +++++++- src/test/java/jikan/command/DeleteCommandTest.java | 8 +++++++- src/test/java/jikan/command/StartCommandTest.java | 14 +++++++++++++- 11 files changed, 69 insertions(+), 11 deletions(-) create mode 100644 src/main/java/jikan/exception/NameTooLongException.java diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 280a64e51..02d3c7530 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -1,6 +1,7 @@ package jikan.activity; import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; import java.time.Duration; import java.time.LocalDate; @@ -30,13 +31,17 @@ public class Activity { * @param endTime the time that the activity ended */ public Activity(String name, LocalDateTime startTime, LocalDateTime endTime, Duration duration, - Set tags, Duration allocatedTime) throws InvalidTimeFrameException { + Set tags, Duration allocatedTime) throws InvalidTimeFrameException, NameTooLongException { if (endTime.isBefore(startTime)) { throw new InvalidTimeFrameException(); } - this.name = name.strip(); + if (name.strip().length() <= 25) { + this.name = name.strip(); + } else { + throw new NameTooLongException(); + } this.startTime = startTime; this.tags = tags; this.endTime = endTime; diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 486e29ebf..edbde776a 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -1,6 +1,7 @@ package jikan.activity; import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; import jikan.parser.Parser; import jikan.storage.Storage; import jikan.storage.StorageHandler; @@ -157,7 +158,7 @@ public int getSize() { * @param activityList list to save to * @throws InvalidTimeFrameException if start time is before end time */ - public void saveActivity(ActivityList activityList) throws InvalidTimeFrameException { + public void saveActivity(ActivityList activityList) throws InvalidTimeFrameException, NameTooLongException { if (Parser.continuedIndex != -1) { Ui.printDivider("Ended: " + Parser.activityName); Parser.endTime = LocalDateTime.now(); @@ -201,9 +202,11 @@ private void populateTaskList(File dataFile) { parseDataLine(dataScanner.nextLine()); } } catch (FileNotFoundException e) { - System.out.println("Error: data file not found. Could not load into the current session's task list."); + Ui.printDivider("Error: data file not found. Could not load into the current session's task list."); } catch (InvalidTimeFrameException e) { - System.out.println("Error: Invalid time frame."); + Ui.printDivider("Error: Invalid time frame."); + } catch (NameTooLongException e) { + Ui.printDivider("Error: activity name is longer than 25 characters."); } } @@ -212,7 +215,7 @@ private void populateTaskList(File dataFile) { * * @param s String to parse. */ - private void parseDataLine(String s) throws InvalidTimeFrameException { + private void parseDataLine(String s) throws InvalidTimeFrameException, NameTooLongException { if (!s.isEmpty()) { List strings = Arrays.asList(s.split(",")); diff --git a/src/main/java/jikan/command/ByeCommand.java b/src/main/java/jikan/command/ByeCommand.java index 95ecef2ed..d96978388 100644 --- a/src/main/java/jikan/command/ByeCommand.java +++ b/src/main/java/jikan/command/ByeCommand.java @@ -1,5 +1,6 @@ package jikan.command; +import jikan.exception.NameTooLongException; import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.InvalidTimeFrameException; @@ -46,7 +47,10 @@ public void executeCommand(ActivityList activityList) { Ui.exitFromApp(); } catch (InvalidTimeFrameException e) { Log.makeInfoLog("End date must be before start date"); - Ui.printDivider("End date must be before start date."); + Ui.printDivider("Error: end date must be before start date."); + } catch (NameTooLongException e) { + Log.makeInfoLog("Activity name longer than 25 characters"); + Ui.printDivider("Error: activity name is longer than 25 characters."); } } diff --git a/src/main/java/jikan/command/EndCommand.java b/src/main/java/jikan/command/EndCommand.java index cbe9f4807..b7157bc6e 100644 --- a/src/main/java/jikan/command/EndCommand.java +++ b/src/main/java/jikan/command/EndCommand.java @@ -1,5 +1,6 @@ package jikan.command; +import jikan.exception.NameTooLongException; import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.InvalidTimeFrameException; @@ -39,6 +40,9 @@ public void executeCommand(ActivityList activityList) { } catch (InvalidTimeFrameException e) { Log.makeInfoLog("End date must be before start date"); Ui.printDivider("End date must be before start date."); + } catch (NameTooLongException e) { + Log.makeInfoLog("Activity name longer than 25 characters"); + Ui.printDivider("Error: activity name is longer than 25 characters."); } } } diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 3ff8664a7..b8a128a78 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -43,6 +43,13 @@ public void executeCommand(ActivityList activityList) { // check if there exists an activity with this name String activityName = getActivityName(tagDelimiter,allocateDelimiter); + + if (activityName.length() > 25) { + Log.makeInfoLog("Activity name longer than 25 characters"); + Ui.printDivider("Please input an activity name that is shorter than 25 characters."); + return; + } + Parser.activityName = activityName; int index = activityList.findActivity(activityName); if (index != -1) { diff --git a/src/main/java/jikan/exception/NameTooLongException.java b/src/main/java/jikan/exception/NameTooLongException.java new file mode 100644 index 000000000..c29a1a8db --- /dev/null +++ b/src/main/java/jikan/exception/NameTooLongException.java @@ -0,0 +1,7 @@ +package jikan.exception; + +/** + * An exception that is thrown when the task name field is longer than 25 characters. + */ +public class NameTooLongException extends Exception { +} diff --git a/src/test/java/jikan/activity/ActivityListTest.java b/src/test/java/jikan/activity/ActivityListTest.java index c0ffb75b8..70b832623 100644 --- a/src/test/java/jikan/activity/ActivityListTest.java +++ b/src/test/java/jikan/activity/ActivityListTest.java @@ -1,6 +1,7 @@ package jikan.activity; import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; import jikan.storage.Storage; import org.junit.jupiter.api.Test; @@ -13,7 +14,7 @@ class ActivityListTest { @Test - void getIndex() throws InvalidTimeFrameException { + void getIndex() throws InvalidTimeFrameException, NameTooLongException { ActivityList activities = new ActivityList(); activities.storage = new Storage("data/activityList_test.txt"); HashSet tags = new HashSet(); diff --git a/src/test/java/jikan/activity/ActivityTest.java b/src/test/java/jikan/activity/ActivityTest.java index 9cc9a302f..956892b83 100644 --- a/src/test/java/jikan/activity/ActivityTest.java +++ b/src/test/java/jikan/activity/ActivityTest.java @@ -1,6 +1,7 @@ package jikan.activity; import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; import org.junit.jupiter.api.Test; import java.time.Duration; @@ -24,6 +25,8 @@ class ActivityTest { activity = new Activity("Activity", startTime, endTime, duration, tags, allocatedTime); } catch (InvalidTimeFrameException e) { e.printStackTrace(); + } catch (NameTooLongException e) { + e.printStackTrace(); } } diff --git a/src/test/java/jikan/command/ContinueCommandTest.java b/src/test/java/jikan/command/ContinueCommandTest.java index 911b79384..e51fdeef7 100644 --- a/src/test/java/jikan/command/ContinueCommandTest.java +++ b/src/test/java/jikan/command/ContinueCommandTest.java @@ -4,8 +4,11 @@ import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; +import jikan.log.Log; import jikan.parser.Parser; import jikan.storage.Storage; +import jikan.ui.Ui; import org.junit.jupiter.api.Test; import java.io.FileNotFoundException; @@ -19,7 +22,7 @@ class ContinueCommandTest { ActivityList activities = new ActivityList(); HashSet tags = new HashSet<>(); - void populateActivityList() throws InvalidTimeFrameException { + void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { activities.storage = new Storage("data/activityList_test.txt"); try { activities.storage.clearFile(); @@ -60,6 +63,9 @@ void executeContinue() throws InterruptedException { assertEquals(elapsed.toMinutes(), duration.toMinutes()); } catch (EmptyNameException | InvalidTimeFrameException e) { System.out.println("Error."); + } catch (NameTooLongException e) { + Log.makeInfoLog("Activity name longer than 25 characters"); + Ui.printDivider("Error: activity name is longer than 25 characters."); } } diff --git a/src/test/java/jikan/command/DeleteCommandTest.java b/src/test/java/jikan/command/DeleteCommandTest.java index afc145dfb..cf72f26de 100644 --- a/src/test/java/jikan/command/DeleteCommandTest.java +++ b/src/test/java/jikan/command/DeleteCommandTest.java @@ -4,7 +4,10 @@ import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; +import jikan.log.Log; import jikan.storage.Storage; +import jikan.ui.Ui; import org.junit.jupiter.api.Test; import java.io.FileNotFoundException; @@ -19,7 +22,7 @@ class DeleteCommandTest { ActivityList activities = new ActivityList(); HashSet tags = new HashSet<>(); - void populateActivityList() throws InvalidTimeFrameException { + void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { activities.storage = new Storage("data/activityList_test.txt"); try { activities.storage.clearFile(); @@ -46,6 +49,9 @@ void executeDelete() { populateActivityList(); } catch (InvalidTimeFrameException e) { System.out.println("Invalid time frame."); + } catch (NameTooLongException e) { + Log.makeInfoLog("Activity name longer than 25 characters"); + Ui.printDivider("Error: activity name is longer than 25 characters."); } String parameters = "Activity2"; diff --git a/src/test/java/jikan/command/StartCommandTest.java b/src/test/java/jikan/command/StartCommandTest.java index f88b6f128..3f0f4bf27 100644 --- a/src/test/java/jikan/command/StartCommandTest.java +++ b/src/test/java/jikan/command/StartCommandTest.java @@ -4,8 +4,11 @@ import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; +import jikan.log.Log; import jikan.parser.Parser; import jikan.storage.Storage; +import jikan.ui.Ui; import org.junit.jupiter.api.Test; import java.io.ByteArrayInputStream; @@ -23,7 +26,7 @@ class StartCommandTest { ActivityList activities = new ActivityList(); HashSet tags = new HashSet<>(); - void populateActivityList() throws InvalidTimeFrameException { + void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { activities.storage = new Storage("data/activityList_test.txt"); activities.activities.clear(); try { @@ -67,6 +70,9 @@ void executeStart() { command.executeCommand(activities); } catch (EmptyNameException | InvalidTimeFrameException e) { System.out.println("Field error."); + } catch (NameTooLongException e) { + Log.makeInfoLog("Activity name longer than 25 characters"); + Ui.printDivider("Error: activity name is longer than 25 characters."); } } @@ -84,6 +90,9 @@ void executeStartContinued() { assertNotNull(Parser.startTime); } catch (InvalidTimeFrameException | EmptyNameException e) { System.out.println("Field error."); + } catch (NameTooLongException e) { + Log.makeInfoLog("Activity name longer than 25 characters"); + Ui.printDivider("Error: activity name is longer than 25 characters."); } } @@ -101,6 +110,9 @@ void executeStartNotContinued() { assertNull(Parser.activityName); } catch (InvalidTimeFrameException | EmptyNameException e) { System.out.println("Field error."); + } catch (NameTooLongException e) { + Log.makeInfoLog("Activity name longer than 25 characters"); + Ui.printDivider("Error: activity name is longer than 25 characters."); } } From 336ab2eeabf4c6a816ee1dce32f94759529bb029 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Wed, 1 Apr 2020 17:24:15 +0800 Subject: [PATCH 235/415] Remove superfluous exception thrown --- src/main/java/jikan/command/GoalCommand.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index 6b22bd9b8..9216b0420 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -88,9 +88,8 @@ public void executeCommand(ActivityList activityList) { * Creates a new tag file. * @param filePath the filepath of the tag file. * @param tagFile the File object. - * @throws IOException when there is an error loading/creating the file. */ - public static void createFile(String filePath, File tagFile) throws IOException { + public static void createFile(String filePath, File tagFile) { tagFile = new File(filePath); try { if (!tagFile.exists()) { From e9c29c5a4abdc19eed8a3d3571f71198b441f1d3 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Wed, 1 Apr 2020 17:27:59 +0800 Subject: [PATCH 236/415] Try fixing style --- src/main/java/jikan/command/GoalCommand.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index 9216b0420..289623f7d 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -84,6 +84,8 @@ public void executeCommand(ActivityList activityList) { } } + + /** * Creates a new tag file. * @param filePath the filepath of the tag file. @@ -101,8 +103,10 @@ public static void createFile(String filePath, File tagFile) { } } + + /** - * Check if the tag exists in the tag list. + * Check that tag exists in the tag list. * @param tagName the tag name. * @return index the index of the tag in the tag list. * @throws IOException when there is an error loading/creating the file. From 9da23197d91357e1940376363adfbb6e70ba2e64 Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Wed, 1 Apr 2020 17:36:29 +0800 Subject: [PATCH 237/415] Remove empty if block --- src/main/java/jikan/command/GoalCommand.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index b35a53f0f..430570261 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -88,9 +88,6 @@ public void executeCommand(ActivityList activityList) { if (tagName.isEmpty()) { throw new EmptyTagException(); } - if (delimiter != -1) { - - } } catch (EmptyTagException | StringIndexOutOfBoundsException e) { Ui.printDivider("Tag name cannot be empty!"); From 185dd483807eb4d4e5b71ec54e3c42b5b672d887 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Wed, 1 Apr 2020 17:51:35 +0800 Subject: [PATCH 238/415] Fix DeleteCommandTest --- src/main/java/jikan/command/GoalCommand.java | 2 -- src/test/java/jikan/command/DeleteCommandTest.java | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index 289623f7d..e5bb19ebc 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -84,8 +84,6 @@ public void executeCommand(ActivityList activityList) { } } - - /** * Creates a new tag file. * @param filePath the filepath of the tag file. diff --git a/src/test/java/jikan/command/DeleteCommandTest.java b/src/test/java/jikan/command/DeleteCommandTest.java index cf72f26de..2c20ab392 100644 --- a/src/test/java/jikan/command/DeleteCommandTest.java +++ b/src/test/java/jikan/command/DeleteCommandTest.java @@ -19,11 +19,11 @@ class DeleteCommandTest { - ActivityList activities = new ActivityList(); + Storage storage = new Storage("data/activityList_test.txt"); + ActivityList activities = new ActivityList(storage); HashSet tags = new HashSet<>(); void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { - activities.storage = new Storage("data/activityList_test.txt"); try { activities.storage.clearFile(); } catch (FileNotFoundException e) { From 0ec988710db75a8124a053c4a2da3b66ade40897 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Wed, 1 Apr 2020 17:52:55 +0800 Subject: [PATCH 239/415] Fix tests --- src/test/java/jikan/command/ContinueCommandTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/jikan/command/ContinueCommandTest.java b/src/test/java/jikan/command/ContinueCommandTest.java index e51fdeef7..b0f4638db 100644 --- a/src/test/java/jikan/command/ContinueCommandTest.java +++ b/src/test/java/jikan/command/ContinueCommandTest.java @@ -19,11 +19,11 @@ import static org.junit.jupiter.api.Assertions.assertEquals; class ContinueCommandTest { - ActivityList activities = new ActivityList(); + Storage storage = new Storage("data/activityList_test.txt"); + ActivityList activities = new ActivityList(storage); HashSet tags = new HashSet<>(); void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { - activities.storage = new Storage("data/activityList_test.txt"); try { activities.storage.clearFile(); } catch (FileNotFoundException e) { From ccadfad0098469c986aef50e7278534d13ab621c Mon Sep 17 00:00:00 2001 From: rdimaio Date: Wed, 1 Apr 2020 17:57:38 +0800 Subject: [PATCH 240/415] Fix text ui test --- text-ui-test/EXPECTED.TXT | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index a3a289886..b885010e7 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -39,28 +39,28 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Target | Date | Tags -1 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag1] +1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ There is already an activity with this name. Would you like to continue it? @@ -74,9 +74,9 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Please input an integer for the time interval. @@ -115,8 +115,8 @@ You have deleted activity 2 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag] -2 | activity 3 | 00:00:00 | 00:00:00 | 2020-03-31 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] +2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Bye! See you again. From d538e4aee57f6fd6ef2d392e30b3717bfd40d96a Mon Sep 17 00:00:00 2001 From: nigellenl Date: Thu, 2 Apr 2020 01:03:13 +0800 Subject: [PATCH 241/415] Fix edit command exception handling --- src/main/java/jikan/command/EditCommand.java | 70 +++++++++----------- 1 file changed, 31 insertions(+), 39 deletions(-) diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index d5186d501..b9dbe400a 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -13,6 +13,7 @@ import java.io.IOException; import java.time.Duration; +import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -38,66 +39,51 @@ public void executeCommand(ActivityList activityList) { int tagDelim = parameters.indexOf("/et"); int allocDelim = parameters.indexOf("/ea"); - // edit name - if (delimiter != -1 && tagDelim == -1 && allocDelim == -1) { - Parser.activityName = parameters.substring(0, delimiter).strip(); - - //edit tag - } else if (delimiter == -1 && tagDelim != -1 && allocDelim == -1) { - Parser.activityName = parameters.substring(0, tagDelim).strip(); - - //edit allocatedTime - } else { - Parser.activityName = parameters.substring(0, allocDelim).strip(); - } - - if (Parser.activityName.isEmpty()) { - throw new EmptyNameException(); - } - - int index = activityList.findActivity(Parser.activityName); String newName = ""; String[] tmpTags; String tmpAlloc = ""; Duration newAllocTime = null; Set newTags = new HashSet(); - //edit name - if (delimiter != -1 && tagDelim == -1 && allocDelim == -1) { - newName = parameters.substring(delimiter + 4); + if (delimiter != -1) { Parser.activityName = parameters.substring(0, delimiter).strip(); + newName = parameters.substring(delimiter + 4).strip(); - //edit tag - } else if (delimiter == -1 && tagDelim != -1 && allocDelim == -1) { + } else if (tagDelim != -1) { + Parser.activityName = parameters.substring(0, tagDelim).strip(); tmpTags = (parameters.substring(tagDelim + 4).split(" ")); - for (String t : tmpTags) { - newTags.add(t); - } - - //edit allocatedTime - } else { + newTags.addAll(Arrays.asList(tmpTags)); + } else if (allocDelim != -1) { + Parser.activityName = parameters.substring(0, allocDelim).strip(); tmpAlloc = parameters.substring(allocDelim + 4); try { newAllocTime = parseDuration(tmpAlloc); } catch (InvalidTimeFrameException e) { Ui.printDivider("Invalid time frame entered!"); } + } else { + throw new InvalidEditFormatException(); + } + + if (Parser.activityName.isEmpty()) { + Ui.printDivider("Activity name cannot be empty!"); + throw new EmptyNameException(); } + int index = activityList.findActivity(Parser.activityName); + if (index != -1) { if (!(newName.isEmpty() && newTags.isEmpty() && tmpAlloc.isEmpty())) { if (!newName.isEmpty()) { activityList.updateName(index, newName); - } - if (!newTags.isEmpty()) { + } else if (!newTags.isEmpty()) { if (existsInTag(activityList.get(index).getTags())) { throw new ExistingTagGoalException(); } else { activityList.updateTags(index, newTags); } - - } - if (!tmpAlloc.isEmpty()) { + } else { + assert newAllocTime != null; if (newAllocTime.isNegative()) { throw new NegativeDurationException(); } else { @@ -105,8 +91,13 @@ public void executeCommand(ActivityList activityList) { } } } else { - // no new details provided - throw new InvalidEditFormatException(); + if (newName.isEmpty()) { + Ui.printDivider("New activity name cannot be empty!"); + throw new EmptyNameException(); + } else { + // no new details provided + throw new InvalidEditFormatException(); + } } Ui.printDivider("Activity named " + Parser.activityName + " has been updated!"); @@ -118,10 +109,10 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider("No activity with this name exists!"); Log.makeInfoLog("Edit command failed as there was no such activity saved."); } catch (EmptyNameException e) { - Ui.printDivider("Activity name cannot be empty!"); + //Ui.printDivider("Activity name cannot be empty!"); Log.makeInfoLog("Edit command failed as there was no activity name provided."); - } catch (StringIndexOutOfBoundsException | InvalidEditFormatException e) { - Ui.printDivider("New details not provided!"); + } catch (StringIndexOutOfBoundsException | ArrayIndexOutOfBoundsException | InvalidEditFormatException e) { + Ui.printDivider("Incorrect edit command format entered!"); Log.makeInfoLog("Edit command failed as there was no updated activity detail provided."); } catch (ExistingTagGoalException e) { Ui.printDivider("Tag cannot be edited as there is an existing tag goal!"); @@ -131,6 +122,7 @@ public void executeCommand(ActivityList activityList) { Log.makeInfoLog("Edit command failed as there was an error in loading the tag file."); } catch (NegativeDurationException e) { Ui.printDivider("Please enter a positive target time!"); + Log.makeInfoLog("Edit command failed as a negative target time was provided."); } } From ed7f904e688d51d674e2c9a167a7fb8a29c38311 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Thu, 2 Apr 2020 01:31:05 +0800 Subject: [PATCH 242/415] Fix edit command exception handling --- src/main/java/jikan/command/EditCommand.java | 38 ++++++++++++-------- 1 file changed, 24 insertions(+), 14 deletions(-) diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index b9dbe400a..e5a23ae96 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -13,6 +13,7 @@ import java.io.IOException; import java.time.Duration; +import java.time.format.DateTimeParseException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; @@ -45,22 +46,31 @@ public void executeCommand(ActivityList activityList) { Duration newAllocTime = null; Set newTags = new HashSet(); + //edit name if (delimiter != -1) { Parser.activityName = parameters.substring(0, delimiter).strip(); newName = parameters.substring(delimiter + 4).strip(); + if (newName.isEmpty()) { + Ui.printDivider("New activity name cannot be empty!"); + throw new EmptyNameException(); + } + //edit tag } else if (tagDelim != -1) { Parser.activityName = parameters.substring(0, tagDelim).strip(); tmpTags = (parameters.substring(tagDelim + 4).split(" ")); newTags.addAll(Arrays.asList(tmpTags)); + + //edit allocated time } else if (allocDelim != -1) { Parser.activityName = parameters.substring(0, allocDelim).strip(); - tmpAlloc = parameters.substring(allocDelim + 4); - try { - newAllocTime = parseDuration(tmpAlloc); - } catch (InvalidTimeFrameException e) { - Ui.printDivider("Invalid time frame entered!"); + tmpAlloc = parameters.substring(allocDelim + 4).strip(); + if (tmpAlloc.isEmpty()) { + throw new InvalidTimeFrameException(); } + newAllocTime = parseDuration(tmpAlloc); + + //invalid format } else { throw new InvalidEditFormatException(); } @@ -91,13 +101,8 @@ public void executeCommand(ActivityList activityList) { } } } else { - if (newName.isEmpty()) { - Ui.printDivider("New activity name cannot be empty!"); - throw new EmptyNameException(); - } else { - // no new details provided - throw new InvalidEditFormatException(); - } + // no new details provided + throw new InvalidEditFormatException(); } Ui.printDivider("Activity named " + Parser.activityName + " has been updated!"); @@ -109,11 +114,10 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider("No activity with this name exists!"); Log.makeInfoLog("Edit command failed as there was no such activity saved."); } catch (EmptyNameException e) { - //Ui.printDivider("Activity name cannot be empty!"); Log.makeInfoLog("Edit command failed as there was no activity name provided."); } catch (StringIndexOutOfBoundsException | ArrayIndexOutOfBoundsException | InvalidEditFormatException e) { Ui.printDivider("Incorrect edit command format entered!"); - Log.makeInfoLog("Edit command failed as there was no updated activity detail provided."); + Log.makeInfoLog("Edit command failed as an incorrect format was provided."); } catch (ExistingTagGoalException e) { Ui.printDivider("Tag cannot be edited as there is an existing tag goal!"); Log.makeInfoLog("Edit command failed as there was an existing tag goal tied to the tag."); @@ -123,6 +127,12 @@ public void executeCommand(ActivityList activityList) { } catch (NegativeDurationException e) { Ui.printDivider("Please enter a positive target time!"); Log.makeInfoLog("Edit command failed as a negative target time was provided."); + } catch (InvalidTimeFrameException e) { + Ui.printDivider("New target time cannot be empty!"); + Log.makeInfoLog("Edit command failed as an empty target time was provided"); + } catch (NumberFormatException e) { + Ui.printDivider("Please enter integers in the format HH:MM:SS"); + Log.makeInfoLog("Edit command failed as an incorrect format for the target time was provided."); } } From 569728b39dd698b2be25225a9e4f2b5f8c84b43d Mon Sep 17 00:00:00 2001 From: nigellenl Date: Thu, 2 Apr 2020 18:00:09 +0800 Subject: [PATCH 243/415] Fix goal command exception handling --- src/main/java/jikan/command/EditCommand.java | 10 +++---- src/main/java/jikan/command/GoalCommand.java | 29 +++++++++++++------ .../jikan/exception/EmptyGoalException.java | 4 +++ .../InvalidGoalCommandException.java | 4 +++ 4 files changed, 32 insertions(+), 15 deletions(-) create mode 100644 src/main/java/jikan/exception/EmptyGoalException.java create mode 100644 src/main/java/jikan/exception/InvalidGoalCommandException.java diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index e5a23ae96..1ccd60107 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -1,24 +1,22 @@ package jikan.command; -import jikan.exception.ExistingTagGoalException; -import jikan.exception.InvalidTimeFrameException; -import jikan.exception.NegativeDurationException; -import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; +import jikan.exception.ExistingTagGoalException; import jikan.exception.InvalidEditFormatException; +import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NegativeDurationException; import jikan.exception.NoSuchActivityException; +import jikan.log.Log; import jikan.parser.Parser; import jikan.ui.Ui; import java.io.IOException; import java.time.Duration; -import java.time.format.DateTimeParseException; import java.util.Arrays; import java.util.HashSet; import java.util.Set; -import static jikan.Jikan.tagFile; import static jikan.command.GoalCommand.parseDuration; /** diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index 26d0c34bd..26381ca16 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -2,10 +2,13 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.EmptyGoalException; import jikan.exception.EmptyTagException; +import jikan.exception.InvalidGoalCommandException; import jikan.exception.InvalidTimeFrameException; import jikan.exception.NegativeDurationException; import jikan.exception.NoSuchTagException; +import jikan.log.Log; import jikan.ui.Ui; import java.io.BufferedReader; @@ -51,8 +54,14 @@ public void executeCommand(ActivityList activityList) { int index; if (delimiter != -1) { tagName = parameters.substring(0, delimiter - 1).strip(); + if (tagName.isEmpty()) { + throw new EmptyTagException(); + } index = checkIfExists(tagName); String tmpTime = parameters.substring(delimiter + 3); + if (tmpTime.isEmpty()) { + throw new EmptyGoalException(); + } Duration goalTime = parseDuration(tmpTime); if (goalTime.isNegative()) { @@ -83,24 +92,26 @@ public void executeCommand(ActivityList activityList) { throw new NoSuchTagException(); } } else { - throw new InvalidTimeFrameException(); - } - if (tagName.isEmpty()) { - throw new EmptyTagException(); + throw new InvalidGoalCommandException(); } - } catch (EmptyTagException | StringIndexOutOfBoundsException e) { + } catch (EmptyTagException e) { Ui.printDivider("Tag name cannot be empty!"); - } catch (InvalidTimeFrameException e) { - Ui.printDivider("Goal cannot be empty!"); + Log.makeInfoLog("Goal command failed as no tag name was provided."); + } catch (InvalidGoalCommandException e) { + Ui.printDivider("Invalid command format entered!"); + Log.makeInfoLog("Goal command failed as an incorrect format was provided."); } catch (IOException e) { Ui.printDivider("Error reading the file!"); } catch (NoSuchTagException e) { Ui.printDivider("There is no such tag!"); - } catch (NumberFormatException | ArrayIndexOutOfBoundsException e) { + Log.makeInfoLog("Goal command failed as there was no such tag saved."); + } catch (ArrayIndexOutOfBoundsException | StringIndexOutOfBoundsException | EmptyGoalException | NumberFormatException e) { Ui.printDivider("Please enter the goal in the format HH:MM:SS"); + Log.makeInfoLog("Goal command failed as an incorrect format for the goal time was provided."); } catch (NegativeDurationException e) { Ui.printDivider("Please enter a positive goal time!"); + Log.makeInfoLog("Goal command failed as a negative goal time was provided."); } } @@ -232,7 +243,7 @@ private boolean existInActivity(ActivityList targetList, String tagName) { * @param input the user input. * @return the duration object. */ - public static Duration parseDuration(String input) throws InvalidTimeFrameException, + public static Duration parseDuration(String input) throws ArrayIndexOutOfBoundsException { String[] fields = input.split(":"); int colonIndex = input.indexOf(':'); diff --git a/src/main/java/jikan/exception/EmptyGoalException.java b/src/main/java/jikan/exception/EmptyGoalException.java new file mode 100644 index 000000000..13ff1a8bc --- /dev/null +++ b/src/main/java/jikan/exception/EmptyGoalException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class EmptyGoalException extends Exception { +} diff --git a/src/main/java/jikan/exception/InvalidGoalCommandException.java b/src/main/java/jikan/exception/InvalidGoalCommandException.java new file mode 100644 index 000000000..151ec80f8 --- /dev/null +++ b/src/main/java/jikan/exception/InvalidGoalCommandException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class InvalidGoalCommandException extends Exception { +} From fc4021c31bd1738e623557bf33982e81968823bb Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 3 Apr 2020 14:38:29 +0800 Subject: [PATCH 244/415] Fix issue #168 --- src/main/java/jikan/command/DeleteCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/DeleteCommand.java b/src/main/java/jikan/command/DeleteCommand.java index 93e1ffc84..94005edb1 100644 --- a/src/main/java/jikan/command/DeleteCommand.java +++ b/src/main/java/jikan/command/DeleteCommand.java @@ -21,10 +21,10 @@ public DeleteCommand(String parameters) { @Override public void executeCommand(ActivityList activityList) { try { - int index = activityList.findActivity(parameters); + int index = activityList.findActivity(parameters.trim()); if (index != -1) { // activity was found - Ui.printDivider("You have deleted " + parameters); + Ui.printDivider("You have deleted " + parameters.trim()); activityList.delete(index); } else { if (parameters.isEmpty()) { From f630bf37f501571b34023b0867e2c93f426f8377 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 3 Apr 2020 15:09:52 +0800 Subject: [PATCH 245/415] Trim input for find --- src/main/java/jikan/command/FindCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index ede546a27..b003324cc 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -16,7 +16,7 @@ public class FindCommand extends Command { * Constructor to create a new find command. */ public FindCommand(String parameters) { - super(parameters); + super(parameters.trim()); } /** From 8586f7e7a75cfb533ad7743cb58a40e4c171ad75 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 3 Apr 2020 15:13:19 +0800 Subject: [PATCH 246/415] Fix issue #177 and #178 --- src/main/java/jikan/command/DeleteCommand.java | 6 +++--- src/main/java/jikan/parser/Parser.java | 6 ++++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/jikan/command/DeleteCommand.java b/src/main/java/jikan/command/DeleteCommand.java index 94005edb1..4356d58b3 100644 --- a/src/main/java/jikan/command/DeleteCommand.java +++ b/src/main/java/jikan/command/DeleteCommand.java @@ -15,16 +15,16 @@ public class DeleteCommand extends Command { * Constructor to create a new delete command. */ public DeleteCommand(String parameters) { - super(parameters); + super(parameters.trim()); } @Override public void executeCommand(ActivityList activityList) { try { - int index = activityList.findActivity(parameters.trim()); + int index = activityList.findActivity(parameters); if (index != -1) { // activity was found - Ui.printDivider("You have deleted " + parameters.trim()); + Ui.printDivider("You have deleted " + parameters); activityList.delete(index); } else { if (parameters.isEmpty()) { diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 905696fa0..faa70fea8 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -92,9 +92,15 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto } break; case "end": + if (tokenizedInputs.length > 1) { + parseDefault(); + } command = new EndCommand(null); break; case "abort": + if (tokenizedInputs.length > 1) { + parseDefault(); + } command = new AbortCommand(null); break; case "list": From a4e2bba0520745dc0c6f97cabb60a8ff69ab8e52 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 3 Apr 2020 15:46:15 +0800 Subject: [PATCH 247/415] Refactor list command and fix issue #187 --- src/main/java/jikan/command/ListCommand.java | 60 +++++++++++++------ .../exception/ExtraParametersException.java | 4 ++ 2 files changed, 47 insertions(+), 17 deletions(-) create mode 100644 src/main/java/jikan/exception/ExtraParametersException.java diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index c8c27f462..714698205 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -2,20 +2,17 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.ExtraParametersException; +import jikan.exception.NameTooLongException; import jikan.ui.Ui; import jikan.exception.InvalidTimeFrameException; -import java.text.ParseException; -import java.time.DayOfWeek; -import java.time.LocalDate; -import java.time.Month; -import java.time.YearMonth; +import java.time.*; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.time.temporal.TemporalAdjusters; import java.util.Calendar; -import java.util.Date; import static jikan.Jikan.lastShownList; @@ -40,11 +37,7 @@ public ListCommand(String parameters) { public void executeCommand(ActivityList activityList) { // If no time frame is specified, print the entire list if (parameters == null) { - lastShownList.activities.clear(); - Ui.printList(activityList); - - // Can't do lastShownList = activityList, otherwise we just copy - lastShownList.activities.addAll(activityList.activities); + listAll(activityList); } else { try { listInterval(activityList); @@ -53,18 +46,29 @@ public void executeCommand(ActivityList activityList) { + "Or use day / week / month to view tasks in the respective time period."); } catch (InvalidTimeFrameException e) { Ui.printDivider("Please enter a valid time frame; the end date must come after the start date."); + } catch (ExtraParametersException e) { + Ui.printDivider("Extra parameters detected!\n" + + "Use day / week / month to view tasks in the respective time period.\""); } } } + private void listAll(ActivityList activityList) { + lastShownList.activities.clear(); + Ui.printList(activityList); + + // Can't do lastShownList = activityList, otherwise we just copy + lastShownList.activities.addAll(activityList.activities); + } + private void listInterval(ActivityList activityList) - throws InvalidTimeFrameException, DateTimeParseException { + throws InvalidTimeFrameException, DateTimeParseException, ExtraParametersException { String[] listInputs; listInputs = parameters.split(" ", 2); lastShownList.activities.clear(); - LocalDate startDate = null; + LocalDate startDate; LocalDate endDate = null; // Parse either format @@ -73,11 +77,18 @@ private void listInterval(ActivityList activityList) // Check if the user has given a verbal input // (User can either say day or daily and get the same output) switch (listInputs[0]) { + case "today": + // Fallthrough case "day": // Fallthrough case "daily": + checkExtraParameters(listInputs); startDate = LocalDate.now(); break; + case "yesterday": + checkExtraParameters(listInputs); + startDate = LocalDate.now().minusDays(1); + break; case "week": // Fallthrough case "weekly": @@ -89,7 +100,6 @@ private void listInterval(ActivityList activityList) } else { startDate = LocalDate.now(); } - // Set current Monday and Sunday as time range startDate = startDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); endDate = startDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); @@ -101,9 +111,7 @@ private void listInterval(ActivityList activityList) // Otherwise get current date if (listInputs.length == 2) { try { - Month month = Month.valueOf(listInputs[1].toUpperCase()); - YearMonth yearMonth = YearMonth.of(Calendar.getInstance().get(Calendar.YEAR), month.getValue()); - startDate = yearMonth.atDay(1); + startDate = getMonth(listInputs[1]); } catch (IllegalArgumentException e) { Ui.printDivider("Please specify the full month name."); return; @@ -117,6 +125,7 @@ private void listInterval(ActivityList activityList) endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); break; default: + // date / date range is given startDate = LocalDate.parse(listInputs[0], parser); if (listInputs.length == 2) { @@ -124,7 +133,10 @@ private void listInterval(ActivityList activityList) } break; } + printList(activityList, startDate, endDate); + } + private void printList(ActivityList activityList, LocalDate startDate, LocalDate endDate) throws InvalidTimeFrameException { // Only one date is specified; return all entries with start date coinciding with that date if (endDate == null) { for (Activity i : activityList.activities) { @@ -148,4 +160,18 @@ private void listInterval(ActivityList activityList) Ui.printList(lastShownList); } } + + private LocalDate getMonth(String listInput) { + LocalDate startDate; + Month month = Month.valueOf(listInput.toUpperCase()); + YearMonth yearMonth = YearMonth.of(Calendar.getInstance().get(Calendar.YEAR), month.getValue()); + startDate = yearMonth.atDay(1); + return startDate; + } + + private void checkExtraParameters(String[] listInputs) throws ExtraParametersException { + if (listInputs.length > 1) { + throw new ExtraParametersException(); + } + } } diff --git a/src/main/java/jikan/exception/ExtraParametersException.java b/src/main/java/jikan/exception/ExtraParametersException.java new file mode 100644 index 000000000..e5ed06338 --- /dev/null +++ b/src/main/java/jikan/exception/ExtraParametersException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class ExtraParametersException extends Throwable { +} From a1181d55bd14a203d09cce3f31e618aa0bd7766f Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 3 Apr 2020 16:30:12 +0800 Subject: [PATCH 248/415] Add interval parameter for graph tags and fix issue #173 --- src/main/java/jikan/Jikan.java | 3 +- src/main/java/jikan/command/Command.java | 3 +- src/main/java/jikan/command/GraphCommand.java | 47 ++++++++++++++----- src/main/java/jikan/command/ListCommand.java | 2 +- .../exception/MissingParametersException.java | 4 ++ src/main/java/jikan/parser/Parser.java | 4 ++ src/main/java/jikan/ui/Ui.java | 4 +- 7 files changed, 49 insertions(+), 18 deletions(-) create mode 100644 src/main/java/jikan/exception/MissingParametersException.java diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 0eb0de29d..4b1fe1b04 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -6,6 +6,7 @@ import jikan.command.GoalCommand; import jikan.exception.EmptyNameException; import jikan.exception.EmptyQueryException; +import jikan.exception.ExtraParametersException; import jikan.exception.InvalidTimeFrameException; import jikan.log.LogCleaner; import jikan.parser.Parser; @@ -82,7 +83,7 @@ public static void main(String[] args) { command.executeCommand(activityList); // This block should theoretically never be entered (if command is empty, it just continues) // However, you never know.. - } catch (EmptyNameException e) { + } catch (EmptyNameException | ExtraParametersException e) { Ui.printDivider("Error parsing command. Please try again."); } } diff --git a/src/main/java/jikan/command/Command.java b/src/main/java/jikan/command/Command.java index 8be6ed9d5..280efa065 100644 --- a/src/main/java/jikan/command/Command.java +++ b/src/main/java/jikan/command/Command.java @@ -2,6 +2,7 @@ import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; +import jikan.exception.ExtraParametersException; import jikan.exception.InvalidTimeFrameException; @@ -21,7 +22,7 @@ public Command(String parameters) { /** * Executes the command and returns the result. */ - public void executeCommand(ActivityList activityList) throws EmptyNameException { + public void executeCommand(ActivityList activityList) throws EmptyNameException, ExtraParametersException { throw new EmptyNameException(); } diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index 892687935..4d3cb9383 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -2,7 +2,9 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.ExtraParametersException; import jikan.exception.InvalidGraphCommandException; +import jikan.exception.MissingParametersException; import jikan.ui.Ui; import java.time.Duration; @@ -17,38 +19,57 @@ public class GraphCommand extends Command { * @param parameters Either time interval for graph or 'tags' flag * to graph by tags */ - public GraphCommand(String parameters) { + String[] inputs; + + public GraphCommand(String parameters) throws ExtraParametersException { super(parameters); + + this.inputs = parameters.split(" "); + if (inputs.length > 2) { + throw new ExtraParametersException(); + } } @Override public void executeCommand(ActivityList activityList) { try { - if (parameters.equals("targets")) { + if (inputs[0].equals("targets")) { Ui.graphTargets(activityList); - } else if (parameters.equals("tags")) { + } else if (inputs[0].equals("tags")) { graphTags(); + } else if (inputs[0].equals("activities")){ + graphDuration(); } else { - if (parameters.isEmpty()) { - throw new InvalidGraphCommandException(); - } else { - int interval = Integer.parseInt(parameters); - Ui.printActivityGraph(interval); - } + Ui.printDivider("Please specify whether you want to graph activities / tags / targets."); } } catch (NumberFormatException | InvalidGraphCommandException e) { - Ui.printDivider("Please input an integer for the time interval.\n" - + "If you'd like to graph by tags, enter the command ."); + Ui.printDivider("Please input an integer for the time interval."); + } catch (MissingParametersException e) { + Ui.printDivider("Please specify whether you want to graph activities / tags / targets."); } } - private void graphTags() { + private void graphDuration() throws MissingParametersException { + if (inputs.length < 2) { + throw new MissingParametersException(); + } else { + int interval = Integer.parseInt(inputs[1]); + Ui.printActivityGraph(interval); + } + } + + private void graphTags() throws InvalidGraphCommandException { HashMap tags = new HashMap<>(); for (Activity activity : lastShownList.activities) { extractTags(tags, activity); } - Ui.printTagsGraph(tags); + if (inputs.length < 2) { + throw new InvalidGraphCommandException(); + } else { + int interval = Integer.parseInt(inputs[1]); + Ui.printTagsGraph(tags, interval); + } } /** diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index 714698205..7b41c7dd8 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -48,7 +48,7 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider("Please enter a valid time frame; the end date must come after the start date."); } catch (ExtraParametersException e) { Ui.printDivider("Extra parameters detected!\n" - + "Use day / week / month to view tasks in the respective time period.\""); + + "Use day / week / month to view tasks in the respective time period."); } } } diff --git a/src/main/java/jikan/exception/MissingParametersException.java b/src/main/java/jikan/exception/MissingParametersException.java new file mode 100644 index 000000000..d49c03493 --- /dev/null +++ b/src/main/java/jikan/exception/MissingParametersException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class MissingParametersException extends Exception { +} diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index faa70fea8..4fcd3729a 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,5 +1,6 @@ package jikan.parser; +import jikan.exception.ExtraParametersException; import jikan.exception.InvalidTimeFrameException; import jikan.log.Log; import jikan.activity.ActivityList; @@ -160,6 +161,9 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { Ui.printDivider("Please input an integer for the time interval.\n" + "If you'd like to graph by tags, enter the command ."); + } catch (ExtraParametersException e) { + Ui.printDivider("Extra parameters or invalid format detected!\n" + + "Use activities / tags / targets to view the respective graphs."); } break; case "goal": diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 22a33e1e2..51f03f06e 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -152,11 +152,11 @@ public static void printActivityGraph(int interval) { * Prints a graph based on activity tags. * @param tags The set of tags to be graphed. */ - public static void printTagsGraph(HashMap tags) { + public static void printTagsGraph(HashMap tags, int interval) { System.out.println(DIVIDER); System.out.println(String.format("%-10s %s %s", "Tag", "|", "Duration")); tags.forEach((key,value) -> { - double minutes = value.toMinutes() / 10.0; + double minutes = value.toMinutes() / interval; int scaledMinutes = (int) Math.round(minutes); System.out.print(String.format("%-10s %s", key, "|")); for (int j = 0; j < scaledMinutes; j++) { From 8da8e0ed5da831fd94250e159ff61db4d7bbec18 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 3 Apr 2020 16:34:59 +0800 Subject: [PATCH 249/415] Close #195 --- src/main/java/jikan/command/ListCommand.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index 7b41c7dd8..a6661c742 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -107,7 +107,7 @@ private void listInterval(ActivityList activityList) case "month": // Fallthrough case "monthly": - // If user has input a specific date to obtain the month from, use that; + // If user has input a specific month, use that; // Otherwise get current date if (listInputs.length == 2) { try { @@ -118,10 +118,8 @@ private void listInterval(ActivityList activityList) } } else { startDate = LocalDate.now(); + startDate = startDate.withDayOfMonth(1); } - - // Set first and last day of month as time range - //startDate = startDate.withDayOfMonth(1); endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); break; default: From 452883f452ded4a520a89341f0bbe25655467b0d Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 3 Apr 2020 17:04:18 +0800 Subject: [PATCH 250/415] Fix Gradle --- src/main/java/jikan/command/AbortCommand.java | 6 +++- src/main/java/jikan/command/EndCommand.java | 6 +++- src/main/java/jikan/command/GoalCommand.java | 3 +- src/main/java/jikan/command/GraphCommand.java | 7 ++-- src/main/java/jikan/command/ListCommand.java | 8 +++-- src/main/java/jikan/parser/Parser.java | 14 ++++---- .../java/jikan/command/AbortCommandTest.java | 12 +++++-- .../jikan/command/ContinueCommandTest.java | 3 +- .../java/jikan/command/DeleteCommandTest.java | 3 +- text-ui-test/EXPECTED.TXT | 35 +++++++++---------- 10 files changed, 59 insertions(+), 38 deletions(-) diff --git a/src/main/java/jikan/command/AbortCommand.java b/src/main/java/jikan/command/AbortCommand.java index 0e8c305d1..6f3ba70b4 100644 --- a/src/main/java/jikan/command/AbortCommand.java +++ b/src/main/java/jikan/command/AbortCommand.java @@ -1,5 +1,6 @@ package jikan.command; +import jikan.exception.ExtraParametersException; import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.NoSuchActivityException; @@ -14,8 +15,11 @@ public class AbortCommand extends Command { /** * Constructor to create a new abort command. */ - public AbortCommand(String parameters) { + public AbortCommand(String parameters) throws ExtraParametersException { super(parameters); + if (parameters == null) { + throw new ExtraParametersException(); + } } @Override diff --git a/src/main/java/jikan/command/EndCommand.java b/src/main/java/jikan/command/EndCommand.java index b7157bc6e..fd2301ffd 100644 --- a/src/main/java/jikan/command/EndCommand.java +++ b/src/main/java/jikan/command/EndCommand.java @@ -1,5 +1,6 @@ package jikan.command; +import jikan.exception.ExtraParametersException; import jikan.exception.NameTooLongException; import jikan.log.Log; import jikan.activity.ActivityList; @@ -21,8 +22,11 @@ public class EndCommand extends Command { /** * Constructor to create a new end command. */ - public EndCommand(String parameters) { + public EndCommand(String parameters) throws ExtraParametersException { super(parameters); + if (parameters == null) { + throw new ExtraParametersException(); + } } /** Method to parse the end activity command. */ diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index 26381ca16..1cf3ff94c 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -106,7 +106,8 @@ public void executeCommand(ActivityList activityList) { } catch (NoSuchTagException e) { Ui.printDivider("There is no such tag!"); Log.makeInfoLog("Goal command failed as there was no such tag saved."); - } catch (ArrayIndexOutOfBoundsException | StringIndexOutOfBoundsException | EmptyGoalException | NumberFormatException e) { + } catch (ArrayIndexOutOfBoundsException | StringIndexOutOfBoundsException + | EmptyGoalException | NumberFormatException e) { Ui.printDivider("Please enter the goal in the format HH:MM:SS"); Log.makeInfoLog("Goal command failed as an incorrect format for the goal time was provided."); } catch (NegativeDurationException e) { diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index 4d3cb9383..3d91a0be5 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -14,13 +14,14 @@ import static jikan.Jikan.lastShownList; public class GraphCommand extends Command { + + String[] inputs; + /** * Constructor to create a new command. * @param parameters Either time interval for graph or 'tags' flag * to graph by tags */ - String[] inputs; - public GraphCommand(String parameters) throws ExtraParametersException { super(parameters); @@ -37,7 +38,7 @@ public void executeCommand(ActivityList activityList) { Ui.graphTargets(activityList); } else if (inputs[0].equals("tags")) { graphTags(); - } else if (inputs[0].equals("activities")){ + } else if (inputs[0].equals("activities")) { graphDuration(); } else { Ui.printDivider("Please specify whether you want to graph activities / tags / targets."); diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index a6661c742..ce3fb81aa 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -8,7 +8,10 @@ import jikan.exception.InvalidTimeFrameException; -import java.time.*; +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.YearMonth; +import java.time.Month; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.time.temporal.TemporalAdjusters; @@ -134,7 +137,8 @@ private void listInterval(ActivityList activityList) printList(activityList, startDate, endDate); } - private void printList(ActivityList activityList, LocalDate startDate, LocalDate endDate) throws InvalidTimeFrameException { + private void printList(ActivityList activityList, LocalDate startDate, LocalDate endDate) + throws InvalidTimeFrameException { // Only one date is specified; return all entries with start date coinciding with that date if (endDate == null) { for (Activity i : activityList.activities) { diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 4fcd3729a..04d2ef920 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -93,16 +93,18 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto } break; case "end": - if (tokenizedInputs.length > 1) { - parseDefault(); + try { + command = new EndCommand(null); + } catch (ExtraParametersException e) { + Ui.printDivider("Extra parameters detected!"); } - command = new EndCommand(null); break; case "abort": - if (tokenizedInputs.length > 1) { - parseDefault(); + try { + command = new AbortCommand(null); + } catch (ExtraParametersException e) { + Ui.printDivider("Extra parameters detected!"); } - command = new AbortCommand(null); break; case "list": if (tokenizedInputs.length == 1) { diff --git a/src/test/java/jikan/command/AbortCommandTest.java b/src/test/java/jikan/command/AbortCommandTest.java index 4225b6f97..a4fa09e68 100644 --- a/src/test/java/jikan/command/AbortCommandTest.java +++ b/src/test/java/jikan/command/AbortCommandTest.java @@ -1,8 +1,10 @@ package jikan.command; import jikan.exception.EmptyNameException; +import jikan.exception.ExtraParametersException; import jikan.exception.InvalidTimeFrameException; import jikan.parser.Parser; +import jikan.ui.Ui; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; @@ -10,15 +12,19 @@ import static org.junit.jupiter.api.Assertions.assertNull; class AbortCommandTest { - @Test void executeAbort() { Parser.startTime = LocalDateTime.now(); - Command command = new AbortCommand(null); + Command command = null; + try { + command = new AbortCommand(null); + } catch (ExtraParametersException e) { + Ui.printDivider("Extra parameters detected!"); + } try { command.executeCommand(null); assertNull(Parser.startTime); - } catch (EmptyNameException e) { + } catch (EmptyNameException | ExtraParametersException e) { System.out.println("Filed error."); } } diff --git a/src/test/java/jikan/command/ContinueCommandTest.java b/src/test/java/jikan/command/ContinueCommandTest.java index b0f4638db..e187ad856 100644 --- a/src/test/java/jikan/command/ContinueCommandTest.java +++ b/src/test/java/jikan/command/ContinueCommandTest.java @@ -3,6 +3,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; +import jikan.exception.ExtraParametersException; import jikan.exception.InvalidTimeFrameException; import jikan.exception.NameTooLongException; import jikan.log.Log; @@ -61,7 +62,7 @@ void executeContinue() throws InterruptedException { Duration elapsed = initial.plus(Duration.between(startTime, LocalDateTime.now())); Duration duration = activities.get(1).getDuration(); assertEquals(elapsed.toMinutes(), duration.toMinutes()); - } catch (EmptyNameException | InvalidTimeFrameException e) { + } catch (EmptyNameException | InvalidTimeFrameException | ExtraParametersException e) { System.out.println("Error."); } catch (NameTooLongException e) { Log.makeInfoLog("Activity name longer than 25 characters"); diff --git a/src/test/java/jikan/command/DeleteCommandTest.java b/src/test/java/jikan/command/DeleteCommandTest.java index 2c20ab392..e2c4f85b4 100644 --- a/src/test/java/jikan/command/DeleteCommandTest.java +++ b/src/test/java/jikan/command/DeleteCommandTest.java @@ -3,6 +3,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; +import jikan.exception.ExtraParametersException; import jikan.exception.InvalidTimeFrameException; import jikan.exception.NameTooLongException; import jikan.log.Log; @@ -58,7 +59,7 @@ void executeDelete() { Command command = new DeleteCommand(parameters); try { command.executeCommand(activities); - } catch (EmptyNameException e) { + } catch (EmptyNameException | ExtraParametersException e) { System.out.println("Field error."); } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index b885010e7..8ed243bf5 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -39,28 +39,28 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: - | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] + | Name | Duration | Target | Date +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: - | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] + | Name | Duration | Target | Date +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: - | Name | Duration | Target | Date | Tags -1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag1] + | Name | Duration | Target | Date +1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ There is already an activity with this name. Would you like to continue it? @@ -74,19 +74,16 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Please input an integer for the time interval. If you'd like to graph by tags, enter the command . ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Name | Duration -activity 1 | -activity 2 | -activity 3 | +Please specify whether you want to graph activities / tags / targets. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Activity name cannot be empty! @@ -115,8 +112,8 @@ You have deleted activity 2 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag] -2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-01 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] +2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Bye! See you again. From e167c9eb9de8c3188473824c01d98bf6ced8ecfe Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 3 Apr 2020 17:04:35 +0800 Subject: [PATCH 251/415] Fix gradle --- src/test/java/jikan/command/StartCommandTest.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/test/java/jikan/command/StartCommandTest.java b/src/test/java/jikan/command/StartCommandTest.java index 3f0f4bf27..40bf5bf45 100644 --- a/src/test/java/jikan/command/StartCommandTest.java +++ b/src/test/java/jikan/command/StartCommandTest.java @@ -3,6 +3,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; +import jikan.exception.ExtraParametersException; import jikan.exception.InvalidTimeFrameException; import jikan.exception.NameTooLongException; import jikan.log.Log; @@ -73,6 +74,8 @@ void executeStart() { } catch (NameTooLongException e) { Log.makeInfoLog("Activity name longer than 25 characters"); Ui.printDivider("Error: activity name is longer than 25 characters."); + } catch (ExtraParametersException e) { + Ui.printDivider("Field error."); } } @@ -88,7 +91,7 @@ void executeStartContinued() { command.executeCommand(activities); assertEquals(Parser.activityName, "Activity1"); assertNotNull(Parser.startTime); - } catch (InvalidTimeFrameException | EmptyNameException e) { + } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException e) { System.out.println("Field error."); } catch (NameTooLongException e) { Log.makeInfoLog("Activity name longer than 25 characters"); @@ -108,7 +111,7 @@ void executeStartNotContinued() { command.executeCommand(activities); assertNull(Parser.startTime); assertNull(Parser.activityName); - } catch (InvalidTimeFrameException | EmptyNameException e) { + } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException e) { System.out.println("Field error."); } catch (NameTooLongException e) { Log.makeInfoLog("Activity name longer than 25 characters"); From 0145cbe7e2995b6c6f20dfe58f2ca0a123a8fb46 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 3 Apr 2020 17:18:57 +0800 Subject: [PATCH 252/415] Fix tests --- src/main/java/jikan/command/AbortCommand.java | 2 +- src/test/java/jikan/command/StartCommandTest.java | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/AbortCommand.java b/src/main/java/jikan/command/AbortCommand.java index 6f3ba70b4..2ce531a6a 100644 --- a/src/main/java/jikan/command/AbortCommand.java +++ b/src/main/java/jikan/command/AbortCommand.java @@ -17,7 +17,7 @@ public class AbortCommand extends Command { */ public AbortCommand(String parameters) throws ExtraParametersException { super(parameters); - if (parameters == null) { + if (parameters != null) { throw new ExtraParametersException(); } } diff --git a/src/test/java/jikan/command/StartCommandTest.java b/src/test/java/jikan/command/StartCommandTest.java index 40bf5bf45..feba3f0fc 100644 --- a/src/test/java/jikan/command/StartCommandTest.java +++ b/src/test/java/jikan/command/StartCommandTest.java @@ -49,6 +49,11 @@ void populateActivityList() throws InvalidTimeFrameException, NameTooLongExcepti activities.add(activity3); } + private void resetFields() { + Parser.startTime = null; + Parser.tags.clear(); + } + @Test void executeStart() { try { @@ -77,6 +82,7 @@ void executeStart() { } catch (ExtraParametersException e) { Ui.printDivider("Field error."); } + resetFields(); } @Test @@ -88,6 +94,7 @@ void executeStartContinued() { Scanner scanner = new Scanner(System.in); String parameters = "Activity1"; Command command = new StartCommand(parameters, scanner); + System.out.println(Parser.tags); command.executeCommand(activities); assertEquals(Parser.activityName, "Activity1"); assertNotNull(Parser.startTime); @@ -97,6 +104,7 @@ void executeStartContinued() { Log.makeInfoLog("Activity name longer than 25 characters"); Ui.printDivider("Error: activity name is longer than 25 characters."); } + resetFields(); } @Test @@ -117,6 +125,6 @@ void executeStartNotContinued() { Log.makeInfoLog("Activity name longer than 25 characters"); Ui.printDivider("Error: activity name is longer than 25 characters."); } - + resetFields(); } } \ No newline at end of file From 2889290fa32a39dc938c07b16b80dd1ae191df78 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 3 Apr 2020 17:34:45 +0800 Subject: [PATCH 253/415] Fix text-ui --- src/test/java/jikan/command/StartCommandTest.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/test/java/jikan/command/StartCommandTest.java b/src/test/java/jikan/command/StartCommandTest.java index feba3f0fc..5c894e40e 100644 --- a/src/test/java/jikan/command/StartCommandTest.java +++ b/src/test/java/jikan/command/StartCommandTest.java @@ -119,12 +119,10 @@ void executeStartNotContinued() { command.executeCommand(activities); assertNull(Parser.startTime); assertNull(Parser.activityName); - } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException e) { + } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException + | NameTooLongException e) { System.out.println("Field error."); - } catch (NameTooLongException e) { - Log.makeInfoLog("Activity name longer than 25 characters"); - Ui.printDivider("Error: activity name is longer than 25 characters."); - } + } resetFields(); } } \ No newline at end of file From f8b5f20acfed46ace94ed79d9a40d1499932f06e Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 3 Apr 2020 17:47:51 +0800 Subject: [PATCH 254/415] Fix text-ui again :( --- src/main/java/jikan/Jikan.java | 2 -- src/main/java/jikan/command/AbortCommand.java | 5 +---- src/main/java/jikan/command/EndCommand.java | 5 +---- src/main/java/jikan/parser/Parser.java | 12 ++++++------ src/test/java/jikan/command/AbortCommandTest.java | 7 +------ src/test/java/jikan/command/StartCommandTest.java | 2 +- 6 files changed, 10 insertions(+), 23 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 4b1fe1b04..fcfb119cc 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -5,9 +5,7 @@ import jikan.command.Command; import jikan.command.GoalCommand; import jikan.exception.EmptyNameException; -import jikan.exception.EmptyQueryException; import jikan.exception.ExtraParametersException; -import jikan.exception.InvalidTimeFrameException; import jikan.log.LogCleaner; import jikan.parser.Parser; import jikan.storage.Storage; diff --git a/src/main/java/jikan/command/AbortCommand.java b/src/main/java/jikan/command/AbortCommand.java index 2ce531a6a..d7788398d 100644 --- a/src/main/java/jikan/command/AbortCommand.java +++ b/src/main/java/jikan/command/AbortCommand.java @@ -15,11 +15,8 @@ public class AbortCommand extends Command { /** * Constructor to create a new abort command. */ - public AbortCommand(String parameters) throws ExtraParametersException { + public AbortCommand(String parameters) { super(parameters); - if (parameters != null) { - throw new ExtraParametersException(); - } } @Override diff --git a/src/main/java/jikan/command/EndCommand.java b/src/main/java/jikan/command/EndCommand.java index fd2301ffd..27c81bb22 100644 --- a/src/main/java/jikan/command/EndCommand.java +++ b/src/main/java/jikan/command/EndCommand.java @@ -22,11 +22,8 @@ public class EndCommand extends Command { /** * Constructor to create a new end command. */ - public EndCommand(String parameters) throws ExtraParametersException { + public EndCommand(String parameters) { super(parameters); - if (parameters == null) { - throw new ExtraParametersException(); - } } /** Method to parse the end activity command. */ diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 04d2ef920..66ab690e1 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -93,18 +93,18 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto } break; case "end": - try { - command = new EndCommand(null); - } catch (ExtraParametersException e) { + if (tokenizedInputs.length > 1) { Ui.printDivider("Extra parameters detected!"); + break; } + command = new EndCommand(null); break; case "abort": - try { - command = new AbortCommand(null); - } catch (ExtraParametersException e) { + if (tokenizedInputs.length > 1) { Ui.printDivider("Extra parameters detected!"); + break; } + command = new AbortCommand(null); break; case "list": if (tokenizedInputs.length == 1) { diff --git a/src/test/java/jikan/command/AbortCommandTest.java b/src/test/java/jikan/command/AbortCommandTest.java index a4fa09e68..0b99aef5b 100644 --- a/src/test/java/jikan/command/AbortCommandTest.java +++ b/src/test/java/jikan/command/AbortCommandTest.java @@ -15,12 +15,7 @@ class AbortCommandTest { @Test void executeAbort() { Parser.startTime = LocalDateTime.now(); - Command command = null; - try { - command = new AbortCommand(null); - } catch (ExtraParametersException e) { - Ui.printDivider("Extra parameters detected!"); - } + Command command = new AbortCommand(null); try { command.executeCommand(null); assertNull(Parser.startTime); diff --git a/src/test/java/jikan/command/StartCommandTest.java b/src/test/java/jikan/command/StartCommandTest.java index 5c894e40e..8c4868e6d 100644 --- a/src/test/java/jikan/command/StartCommandTest.java +++ b/src/test/java/jikan/command/StartCommandTest.java @@ -122,7 +122,7 @@ void executeStartNotContinued() { } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { System.out.println("Field error."); - } + } resetFields(); } } \ No newline at end of file From c434639fbae67486a270ea6f06a30e5f63fb2462 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 6 Apr 2020 00:39:40 +0800 Subject: [PATCH 255/415] Can get activity name --- src/main/java/jikan/command/StartCommand.java | 131 ++++++++++++++++-- 1 file changed, 122 insertions(+), 9 deletions(-) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index b8a128a78..902583dbb 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -30,6 +30,119 @@ public StartCommand(String parameters, Scanner scanner) { } @Override + public void executeCommand(ActivityList activityList) { + boolean hasStarted = hasStarted(Parser.startTime); + if (hasStarted) { + stopExecution(); + } else { + continueExecution(); + } + } + + private boolean hasStarted(LocalDateTime startTime) { + if (startTime != null) { + return true; + } else { + return false; + } + } + + private void stopExecution() { + String line = Parser.activityName + " is ongoing!"; + Log.makeInfoLog("Could not start activity due to already ongoing activity."); + Ui.printDivider(line); + } + + private void continueExecution() { + boolean commandIsEmpty = hasParameter(this.parameters); + String activityName = ""; + if (commandIsEmpty) { + Ui.printDivider("Start command cannot be empty"); + } else { + activityName = parseActivityName(this.parameters); + } + if (activityName.isEmpty()) { + Ui.printDivider("Activity name cannot be empty"); + } else { + System.out.println(activityName); + } + } + + private boolean hasParameter(String parameters) { + if (parameters.isEmpty()) { + return true; + } + return false; + } + + private String parseActivityName(String parameters) { + String scenario; + String activityName; + int tagDelimiter = parameters.indexOf("/t"); + int allocateDelimiter = parameters.indexOf("/a"); + scenario = getScenario(tagDelimiter, allocateDelimiter); + switch (scenario) { + case "hasTagAndTarget": + activityName = handleTagAndTarget(this.parameters, tagDelimiter, allocateDelimiter); + break; + case "hasTagOnly": + activityName = handleTagOrTarget(this.parameters, tagDelimiter); + break; + case "hasTargetOnly": + activityName = handleTagOrTarget(this.parameters, allocateDelimiter); + break; + case "hasNoTagAndTarget": + activityName = this.parameters.trim(); + break; + default: + activityName = ""; + break; + } + return activityName; + } + + private String getScenario(int tagDelimiter, int allocateDelimiter) { + if (tagDelimiter != -1 && allocateDelimiter != -1) { + return "hasTagAndTarget"; + } else if (tagDelimiter != -1) { + return "hasTagOnly"; + } else if (allocateDelimiter != -1) { + return "hasTargetOnly"; + } else { + return "hasNoTagAndTarget"; + } + } + + private String handleTagAndTarget(String parameters, int tagDelimiter, int allocateDelimiter) { + String activityName = ""; + int delimiter = 0; + if (tagDelimiter < allocateDelimiter) { + delimiter = tagDelimiter; + } else if (allocateDelimiter < tagDelimiter) { + delimiter = allocateDelimiter; + } + activityName = parameters.substring(0, delimiter); + activityName = activityName.trim(); + if (activityName.isEmpty()) { + return ""; + } else { + return activityName; + } + } + + private String handleTagOrTarget(String parameters, int delimiter) { + String activityName = parameters.substring(0, delimiter); + activityName = activityName.trim(); + if (activityName.isEmpty()) { + return ""; + } else { + return activityName; + } + } + + + + /*@Override public void executeCommand(ActivityList activityList) { if (Parser.startTime != null) { String line = Parser.activityName + " is ongoing!"; @@ -71,7 +184,7 @@ public void executeCommand(ActivityList activityList) { } } } - } + }*/ /** * Received user input on whether or not to continue the activity. @@ -79,7 +192,7 @@ public void executeCommand(ActivityList activityList) { * @param activityList List of activities. * @param scanner Parse user input. */ - private static void continueActivity(ActivityList activityList, Scanner scanner, int index) { + /*private static void continueActivity(ActivityList activityList, Scanner scanner, int index) { String userInput = scanner.nextLine(); if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { Parser.activityName = activityList.get(index).getName(); @@ -92,7 +205,7 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, Parser.activityName = null; Ui.printDivider("Okay then, what else can I do for you?"); } - } + }*/ /** * Parses the started activity for name and tags. @@ -100,7 +213,7 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, * @param tagDelimiter the index of the tag delimiter. * @param allocateDelimiter the index of the allocation delimiter. */ - private void parseActivity(int tagDelimiter, int allocateDelimiter) throws EmptyNameException, + /*private void parseActivity(int tagDelimiter, int allocateDelimiter) throws EmptyNameException, WrongDateFormatException, EmptyTagException { String activityName = getActivityName(tagDelimiter, allocateDelimiter); if (activityName.isBlank()) { @@ -139,9 +252,9 @@ private void parseActivity(int tagDelimiter, int allocateDelimiter) throws Empty } //return "Started: " + Parser.activityName; - } + }*/ - private String getActivityName(int tagDelimiter, int allocateDelimiter) { + /*private String getActivityName(int tagDelimiter, int allocateDelimiter) { if (tagDelimiter != -1) { return this.parameters.substring(0,tagDelimiter).strip(); } else if (allocateDelimiter != -1) { @@ -150,9 +263,9 @@ private String getActivityName(int tagDelimiter, int allocateDelimiter) { return this.parameters; } - } + }*/ - private void parseDuration(String allocatedTime) throws WrongDateFormatException { + /*private void parseDuration(String allocatedTime) throws WrongDateFormatException { String[] tokenizedInputs; tokenizedInputs = allocatedTime.split("/"); if (tokenizedInputs.length != 3) { @@ -164,5 +277,5 @@ private void parseDuration(String allocatedTime) throws WrongDateFormatException String duration = "PT" + hours + minutes + seconds; Parser.allocatedTime = Duration.parse(duration); } - } + }*/ } From 178eed58307562aef7c366e522b226dcf643beb0 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 6 Apr 2020 02:26:45 +0800 Subject: [PATCH 256/415] Add delete for tag goals & fix exception handling for update tag goals --- src/main/java/jikan/command/GoalCommand.java | 41 ++++++++++++++++--- .../java/jikan/command/ViewGoalsCommand.java | 10 ++++- 2 files changed, 45 insertions(+), 6 deletions(-) diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index 1cf3ff94c..70b5a2434 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -5,7 +5,6 @@ import jikan.exception.EmptyGoalException; import jikan.exception.EmptyTagException; import jikan.exception.InvalidGoalCommandException; -import jikan.exception.InvalidTimeFrameException; import jikan.exception.NegativeDurationException; import jikan.exception.NoSuchTagException; import jikan.log.Log; @@ -13,6 +12,7 @@ import java.io.BufferedReader; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; @@ -25,6 +25,7 @@ import java.util.Scanner; import static java.lang.Integer.valueOf; +import static jikan.Jikan.tagFile; /** @@ -87,7 +88,7 @@ public void executeCommand(ActivityList activityList) { index = checkIfExists(tagName); if (index != -1) { Ui.printDivider("The goal for this tag has been deleted!"); - removeLine(index); + deleteLine(index); } else { throw new NoSuchTagException(); } @@ -178,11 +179,13 @@ public static int checkIfExists(String tagName) throws IOException { */ private static void updateGoal(String userInput, String tagName, Duration goalTime, int index) throws IOException { if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { - removeLine(index); + deleteLine(index); writeToFile(tagName + "," + goalTime); Ui.printDivider("The goal for " + tagName + " was updated"); - } else { + } else if (userInput.equalsIgnoreCase("no") || userInput.equalsIgnoreCase("n")) { Ui.printDivider("Okay then, what else can I do for you?"); + } else { + Ui.printDivider("Incorrect format entered, please only enter yes or no!"); } } @@ -205,11 +208,39 @@ public static void addTagLine(String dataLine) { * @param lineNumber Index of line to remove. * @throws IOException If an error occurs while writing the new list to file. */ - public static void removeLine(int lineNumber) throws IOException { + public static void deleteLine(int lineNumber) throws IOException { // Read file into list of strings, where each string is a line in the file List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(TAG_FILE_PATH), StandardCharsets.UTF_8)); fileContent.remove(lineNumber); + saveNewTags(fileContent, tagFile); + } + + /** + * Saves the updated tags to the csv file. + * + * @param newList The list containing the updated data. + * @param dataFile The file to save to. + * @throws IOException If an error occurs while writing the new list to file. + */ + public static void saveNewTags(List newList, File dataFile) throws IOException { + clearFile(); + FileWriter fw = new FileWriter(TAG_FILE_PATH, true); + + for (String s : newList) { + fw.write(s + System.lineSeparator()); + } + fw.close(); + } + + /** + * Clears the data file. + * @throws FileNotFoundException If file is not found. + */ + public static void clearFile() throws IOException { + FileWriter fw = new FileWriter(TAG_FILE_PATH, false); + fw.write(""); + fw.close(); } /** diff --git a/src/main/java/jikan/command/ViewGoalsCommand.java b/src/main/java/jikan/command/ViewGoalsCommand.java index 0519be3fc..60dc1cac3 100644 --- a/src/main/java/jikan/command/ViewGoalsCommand.java +++ b/src/main/java/jikan/command/ViewGoalsCommand.java @@ -2,6 +2,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.EmptyTagException; import jikan.exception.InvalidTimeFrameException; import jikan.ui.Ui; import static jikan.Jikan.tagFile; @@ -44,7 +45,14 @@ private void getGoalData(ActivityList activityList, HashMap ta for (Activity activity : activityList.activities) { GraphCommand.extractTags(tagsActual, activity); } - Ui.printGoals(tagsGoals, tagsActual); + try { + if (tagsActual.isEmpty() || tagsGoals.isEmpty()) { + throw new EmptyTagException(); + } + Ui.printGoals(tagsGoals, tagsActual); + } catch (NullPointerException | EmptyTagException e) { + Ui.printDivider("There are no tags to display!"); + } } /** From d9fdfb4962d378b9f1da986fab0bb689875f1f23 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 6 Apr 2020 02:29:19 +0800 Subject: [PATCH 257/415] Update text-ui --- text-ui-test/EXPECTED.TXT | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 8ed243bf5..bc90efc5a 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -39,28 +39,28 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Target | Date -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Target | Date -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Target | Date -1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag1] +1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ There is already an activity with this name. Would you like to continue it? @@ -74,9 +74,9 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Please input an integer for the time interval. @@ -112,8 +112,8 @@ You have deleted activity 2 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag] -2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-03 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] +2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Bye! See you again. From ddc22cb29d823c8b9c917ecb8d792d3fea01115d Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 6 Apr 2020 02:33:41 +0800 Subject: [PATCH 258/415] Fix text-ui --- text-ui-test/EXPECTED.TXT | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index bc90efc5a..4b06eaed6 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -39,28 +39,28 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Target | Date -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Target | Date -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Target | Date -1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag1] +1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ There is already an activity with this name. Would you like to continue it? @@ -74,9 +74,9 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Please input an integer for the time interval. @@ -112,8 +112,8 @@ You have deleted activity 2 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag] -2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-06 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] +2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Bye! See you again. From 6b132a0bd423b4aaa8731900e99127c8e392097c Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 6 Apr 2020 02:51:16 +0800 Subject: [PATCH 259/415] Debugged start command --- src/main/java/jikan/command/StartCommand.java | 307 +++++++++++------- 1 file changed, 194 insertions(+), 113 deletions(-) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 902583dbb..6f88cf256 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -9,8 +9,11 @@ import jikan.ui.Ui; +import java.time.DateTimeException; import java.time.Duration; import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; @@ -20,6 +23,10 @@ public class StartCommand extends Command { private Scanner scanner; + private boolean hasTarget = false; + private boolean hasTag = false; + private boolean hasTargetAndTag = false; + private static final int maxActivityLength = 25; /** * Constructor to create a new start command. @@ -35,10 +42,16 @@ public void executeCommand(ActivityList activityList) { if (hasStarted) { stopExecution(); } else { - continueExecution(); + assert Parser.tags.isEmpty(); + continueExecution(activityList); } } + /** + * Checks if there is a concurrently running activity. + * @param startTime a LocalDateTime object to check if parser is waiting for a running activity. + * @return true if there is a concurrent running activity and false otherwise. + */ private boolean hasStarted(LocalDateTime startTime) { if (startTime != null) { return true; @@ -47,13 +60,20 @@ private boolean hasStarted(LocalDateTime startTime) { } } + /** + * Stops executing current activity if a concurrent running activity is found. + */ private void stopExecution() { String line = Parser.activityName + " is ongoing!"; Log.makeInfoLog("Could not start activity due to already ongoing activity."); Ui.printDivider(line); } - private void continueExecution() { + /** + * Continues execution as no concurrent running activity is found. + * @param activityList a list of tracked activities. + */ + private void continueExecution(ActivityList activityList) { boolean commandIsEmpty = hasParameter(this.parameters); String activityName = ""; if (commandIsEmpty) { @@ -64,10 +84,15 @@ private void continueExecution() { if (activityName.isEmpty()) { Ui.printDivider("Activity name cannot be empty"); } else { - System.out.println(activityName); + checkActivity(activityName, activityList); } } + /** + * Check if the start command is empty. + * @param parameters the parameters to start command. + * @return true if it is empty and false otherwise. + */ private boolean hasParameter(String parameters) { if (parameters.isEmpty()) { return true; @@ -75,6 +100,11 @@ private boolean hasParameter(String parameters) { return false; } + /** + * Get activity name from parameters to start command. + * @param parameters the parameters to start command. + * @return activity name of the activity to be started. + */ private String parseActivityName(String parameters) { String scenario; String activityName; @@ -101,18 +131,34 @@ private String parseActivityName(String parameters) { return activityName; } + /** + * Method to check for tags and allocated time. + * @param tagDelimiter index where tag flag is found. + * @param allocateDelimiter index where allocate flag is found. + * @return a string with information about whether tags and allocated time are found. + */ private String getScenario(int tagDelimiter, int allocateDelimiter) { if (tagDelimiter != -1 && allocateDelimiter != -1) { + this.hasTargetAndTag = true; return "hasTagAndTarget"; } else if (tagDelimiter != -1) { + this.hasTag = true; return "hasTagOnly"; } else if (allocateDelimiter != -1) { + this.hasTarget = true; return "hasTargetOnly"; } else { return "hasNoTagAndTarget"; } } + /** + * Method to extract activity name. + * @param parameters parameters to start command. + * @param tagDelimiter index where tag flag is found. + * @param allocateDelimiter index where allocate flag is found. + * @return activity name + */ private String handleTagAndTarget(String parameters, int tagDelimiter, int allocateDelimiter) { String activityName = ""; int delimiter = 0; @@ -130,6 +176,12 @@ private String handleTagAndTarget(String parameters, int tagDelimiter, int alloc } } + /** + * Method to extract activity name. + * @param parameters parameters to start command. + * @param delimiter index where tag flag or allocate flag is found. + * @return activity name. + */ private String handleTagOrTarget(String parameters, int delimiter) { String activityName = parameters.substring(0, delimiter); activityName = activityName.trim(); @@ -140,51 +192,152 @@ private String handleTagOrTarget(String parameters, int delimiter) { } } + /** + * Method to check if the activity exists in activitylist and does not exceed 25 characters. + * @param activityName the string representing activity name. + * @param activityList a list of tracked activities. + */ + private void checkActivity(String activityName, ActivityList activityList) { + int index = activityList.findActivity(activityName); + if (index != -1) { + Ui.printDivider("There is already an activity with this name. Would you like to continue it?"); + continueActivity(activityList, scanner, index); + } else if (activityName.length() > maxActivityLength) { + Log.makeInfoLog("Activity name longer than 25 characters"); + Ui.printDivider("Please input an activity name that is shorter than 25 characters."); + } else { + addActivityToList(activityName); + } + } - - /*@Override - public void executeCommand(ActivityList activityList) { - if (Parser.startTime != null) { - String line = Parser.activityName + " is ongoing!"; - Log.makeInfoLog("Could not start activity due to already ongoing activity."); - Ui.printDivider(line); + /** + * Method to add a activity to the activity list. + * @param activityName the string representing activity name. + */ + private void addActivityToList(String activityName) { + if (hasTargetAndTag) { + parseActivityWithBothField(activityName, this.parameters); + } else if (hasTarget) { + addActivityWithTarget(activityName, this.parameters); + } else if (hasTag) { + addActivityWithTag(activityName, this.parameters); } else { - // tags should be reset - assert Parser.tags.isEmpty(); - int tagDelimiter = parameters.indexOf("/t"); - int allocateDelimiter = parameters.indexOf("/a"); + addActivity(activityName); + } + } - // check if there exists an activity with this name - String activityName = getActivityName(tagDelimiter,allocateDelimiter); + /** + * Parse the tag and allocate information. + * @param activityName the string representing activity name. + * @param line a line with information on tags and allocated time. + */ + private void parseActivityWithBothField(String activityName, String line) { + int allocateIndex = line.indexOf("/a"); + int tagIndex = line.indexOf("/t"); + String tagInfo = ""; + String durationInfo = ""; + if (tagIndex < allocateIndex) { + tagInfo = line.substring(tagIndex, allocateIndex); + durationInfo = line.substring(allocateIndex); + tagInfo = tagInfo.trim(); + durationInfo = durationInfo.trim(); + } else if (allocateIndex < tagIndex) { + durationInfo = line.substring(allocateIndex, tagIndex); + tagInfo = line.substring(tagIndex); + tagInfo = tagInfo.trim(); + durationInfo = durationInfo.trim(); + } + durationInfo = durationInfo.substring(2); + durationInfo = durationInfo.trim(); + tagInfo = tagInfo.substring(2); + tagInfo = tagInfo.trim(); + addActivityWithBothField(durationInfo, tagInfo, activityName); + } - if (activityName.length() > 25) { - Log.makeInfoLog("Activity name longer than 25 characters"); - Ui.printDivider("Please input an activity name that is shorter than 25 characters."); - return; + /** + * Add activity with both tag and allocate time. + * @param durationInfo information about the duration. + * @param tagInfo information about the tag. + * @param activityName the string representing activity name. + */ + private void addActivityWithBothField(String durationInfo, String tagInfo, String activityName) { + LocalTime startTime = LocalTime.MIN; + LocalTime endTime; + String[] tagString = tagInfo.split(" "); + try { + endTime = LocalTime.parse(durationInfo); + Duration allocatedTime = Duration.between(startTime, endTime); + if (tagString.length > 2) { + Ui.printDivider("Cannot have more than 2 tags"); + } else if (allocatedTime == Duration.parse("PT0S")) { + Ui.printDivider("Please provide a non zero allocated time"); + } else { + Parser.tags.addAll(Arrays.asList(tagString)); + Parser.allocatedTime = allocatedTime; + addActivity(activityName); } + } catch (DateTimeException e) { + Ui.printDivider("Time provided is invalid, please provide time in this format" + + " HH:MM:SS"); + } + } - Parser.activityName = activityName; - int index = activityList.findActivity(activityName); - if (index != -1) { - Ui.printDivider("There is already an activity with this name. Would you like to continue it?"); - continueActivity(activityList, scanner, index); + /** + * Add activity with allocated time only. + * @param activityName the string representing activity name. + * @param line a line with information about allocated time. + */ + private void addActivityWithTarget(String activityName, String line) { + int index = line.indexOf("/a"); + String durationInfo = line.substring(index + 2); + durationInfo = durationInfo.trim(); + LocalTime startTime = LocalTime.MIN; + LocalTime endTime; + try { + endTime = LocalTime.parse(durationInfo); + Duration allocatedTime = Duration.between(startTime, endTime); + if (allocatedTime == Duration.parse("PT0S")) { + Ui.printDivider("Please provide a non zero allocated time"); } else { - try { - parseActivity(tagDelimiter,allocateDelimiter); - Parser.startTime = LocalDateTime.now(); - Log.makeFineLog("Started: " + activityName); - Ui.printDivider("Started: " + activityName); - } catch (WrongDateFormatException w) { - Log.makeInfoLog("Wrong format for allocated time."); - Ui.printDivider("Please input in this format HH/MM/SS"); - } catch (EmptyNameException e) { - Ui.printDivider("Activity name cannot be empty!"); - } catch (EmptyTagException e) { - Ui.printDivider("Tags cannot be empty!"); - } + Parser.allocatedTime = allocatedTime; + addActivity(activityName); + } + } catch (DateTimeException e) { + Ui.printDivider("Time provided is invalid, please provide time in this format" + + " HH:MM:SS"); } - }*/ + } + + /** + * Add activity with tags only. + * @param activityName the string representing activity name. + * @param line a line with information about tags. + */ + private void addActivityWithTag(String activityName, String line) { + int index = line.indexOf("/t"); + String tagInfo = line.substring(index + 2); + tagInfo = tagInfo.trim(); + String[] tagString = tagInfo.split(" "); + if (tagString.length > 2) { + Ui.printDivider("Cannot have more than 2 tags"); + } else { + Parser.tags.addAll(Arrays.asList(tagString)); + addActivity(activityName); + } + } + + /** + * Add activity to activity list. + * @param activityName the string representing activity name. + */ + private void addActivity(String activityName) { + Parser.activityName = activityName; + Parser.startTime = LocalDateTime.now(); + Log.makeFineLog("Started: " + activityName); + Ui.printDivider("Started: " + activityName); + } + /** * Received user input on whether or not to continue the activity. @@ -192,7 +345,7 @@ public void executeCommand(ActivityList activityList) { * @param activityList List of activities. * @param scanner Parse user input. */ - /*private static void continueActivity(ActivityList activityList, Scanner scanner, int index) { + private static void continueActivity(ActivityList activityList, Scanner scanner, int index) { String userInput = scanner.nextLine(); if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { Parser.activityName = activityList.get(index).getName(); @@ -205,77 +358,5 @@ public void executeCommand(ActivityList activityList) { Parser.activityName = null; Ui.printDivider("Okay then, what else can I do for you?"); } - }*/ - - /** - * Parses the started activity for name and tags. - * - * @param tagDelimiter the index of the tag delimiter. - * @param allocateDelimiter the index of the allocation delimiter. - */ - /*private void parseActivity(int tagDelimiter, int allocateDelimiter) throws EmptyNameException, - WrongDateFormatException, EmptyTagException { - String activityName = getActivityName(tagDelimiter, allocateDelimiter); - if (activityName.isBlank()) { - throw new EmptyNameException(); - } - String activityInfo; - if (tagDelimiter != -1 || allocateDelimiter != -1) { - activityInfo = this.parameters.substring(activityName.length() + 1); - } else { - return; - } - if (allocateDelimiter != -1) { - String allocatedTime; - try { - activityInfo = activityInfo.substring(3); - int index = activityInfo.indexOf(" "); - if (index != -1) { - allocatedTime = activityInfo.substring(0,index); - activityInfo = activityInfo.substring(index + 1); - } else { - allocatedTime = activityInfo; - } - parseDuration(allocatedTime); - } catch (WrongDateFormatException | StringIndexOutOfBoundsException w) { - throw new WrongDateFormatException(); - } - } - if (tagDelimiter != -1) { - try { - activityInfo = activityInfo.substring(3); - String [] tagString = activityInfo.split(" "); - Parser.tags.addAll(Arrays.asList(tagString)); - } catch (StringIndexOutOfBoundsException e) { - throw new EmptyTagException(); - } - - } - //return "Started: " + Parser.activityName; - }*/ - - /*private String getActivityName(int tagDelimiter, int allocateDelimiter) { - if (tagDelimiter != -1) { - return this.parameters.substring(0,tagDelimiter).strip(); - } else if (allocateDelimiter != -1) { - return this.parameters.substring(0,allocateDelimiter).strip(); - } else { - return this.parameters; - } - - }*/ - - /*private void parseDuration(String allocatedTime) throws WrongDateFormatException { - String[] tokenizedInputs; - tokenizedInputs = allocatedTime.split("/"); - if (tokenizedInputs.length != 3) { - throw new WrongDateFormatException(); - } else { - String hours = tokenizedInputs[0] + "H"; - String minutes = tokenizedInputs[1] + "M"; - String seconds = tokenizedInputs[2] + "S"; - String duration = "PT" + hours + minutes + seconds; - Parser.allocatedTime = Duration.parse(duration); - } - }*/ + } } From 0f251848b30c2d1eab659d01dfd01c822c01126b Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 6 Apr 2020 16:42:54 +0800 Subject: [PATCH 260/415] Made command class abstract --- src/main/java/jikan/activity/ActivityList.java | 1 + src/main/java/jikan/command/Command.java | 6 ++---- src/main/java/jikan/command/ContinueCommand.java | 2 +- src/main/java/jikan/command/GraphCommand.java | 15 +++++++++++++++ 4 files changed, 19 insertions(+), 5 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index edbde776a..a38bd4708 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -173,6 +173,7 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep } Parser.continuedIndex = -1; Parser.resetInfo(); + } else { Ui.printDivider("Ended: " + Parser.activityName); Parser.endTime = LocalDateTime.now(); diff --git a/src/main/java/jikan/command/Command.java b/src/main/java/jikan/command/Command.java index 280efa065..262b8e685 100644 --- a/src/main/java/jikan/command/Command.java +++ b/src/main/java/jikan/command/Command.java @@ -9,7 +9,7 @@ /** * Represents an executable command. */ -public class Command { +public abstract class Command { protected String parameters; /** @@ -22,9 +22,7 @@ public Command(String parameters) { /** * Executes the command and returns the result. */ - public void executeCommand(ActivityList activityList) throws EmptyNameException, ExtraParametersException { - throw new EmptyNameException(); - } + public abstract void executeCommand(ActivityList activityList) throws EmptyNameException, ExtraParametersException; } diff --git a/src/main/java/jikan/command/ContinueCommand.java b/src/main/java/jikan/command/ContinueCommand.java index 4055e4230..aede34011 100644 --- a/src/main/java/jikan/command/ContinueCommand.java +++ b/src/main/java/jikan/command/ContinueCommand.java @@ -34,8 +34,8 @@ public void executeCommand(ActivityList activityList) { if (index != -1) { // activity is found Parser.activityName = activityList.get(index).getName(); - Parser.startTime = LocalDateTime.now(); Parser.tags = activityList.get(index).getTags(); + Parser.startTime = LocalDateTime.now(); Parser.continuedIndex = index; String line = Parser.activityName + " was continued"; Ui.printDivider(line); diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index 3d91a0be5..ed26b4673 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -34,6 +34,20 @@ public GraphCommand(String parameters) throws ExtraParametersException { @Override public void executeCommand(ActivityList activityList) { try { + switch (inputs[0]) { + case "targets": + Ui.graphTargets(activityList); + break; + case "tags": + graphTags(); + break; + case "activities": + graphDuration(); + break; + default: + Ui.printDivider("Please specify whether you want to graph activities / tags / targets."); + } + /* if (inputs[0].equals("targets")) { Ui.graphTargets(activityList); } else if (inputs[0].equals("tags")) { @@ -43,6 +57,7 @@ public void executeCommand(ActivityList activityList) { } else { Ui.printDivider("Please specify whether you want to graph activities / tags / targets."); } + */ } catch (NumberFormatException | InvalidGraphCommandException e) { Ui.printDivider("Please input an integer for the time interval."); } catch (MissingParametersException e) { From d845a1fca69887f96b371e1465376237cd7244c9 Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 6 Apr 2020 18:03:26 +0800 Subject: [PATCH 261/415] Change saveActivity() parameters --- docs/DeveloperGuide.md | 39 ++++++++++++++---- docs/pictures/continue.png | Bin 0 -> 37587 bytes docs/pictures/continueActivity.png | Bin 40280 -> 0 bytes docs/pictures/end.png | Bin 0 -> 37760 bytes docs/pictures/endActivity.PNG | Bin 33720 -> 0 bytes docs/pictures/graph.png | Bin 0 -> 35480 bytes .../java/jikan/activity/ActivityList.java | 12 +++--- src/main/java/jikan/command/ByeCommand.java | 2 +- src/main/java/jikan/command/EndCommand.java | 2 +- 9 files changed, 38 insertions(+), 17 deletions(-) create mode 100644 docs/pictures/continue.png delete mode 100644 docs/pictures/continueActivity.png create mode 100644 docs/pictures/end.png delete mode 100644 docs/pictures/endActivity.PNG create mode 100644 docs/pictures/graph.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index d76270e51..2add5163e 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -172,7 +172,7 @@ However, by allowing the user to edit the start date and time, there may be pote The continue feature allows the user to continue a previously ended activity. #### 3.5.1 Current Implementation -![Continue command sequence diagram](./pictures/continueActivity.png) +![Continue command sequence diagram](./pictures/continue.png) **Continuing an activity:** @@ -182,7 +182,7 @@ When the user enters the command to continue an activity, a *ContinueCommand* ob 2. Gets the `name` and `tags` of the activity to be continued and saves it to a public static variable of *Parser* object 3. Gets the current time and saves it to a public static variable of *Parser* object - ![End command sequence diagram](./pictures/endActivity.PNG) + ![End command sequence diagram](./pictures/end.png) **Ending a continued activity:** @@ -210,7 +210,7 @@ Although the current implementation of the continue feature disallows users to h As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, they will be given the option to continue the stated activity. ![decision flowchart](./pictures/continue_flowchart.PNG) -### 3.5 List feature +### 3.6 List feature This feature is used to list activities within a range specified by the user. If no parameter is passed to the `list` command, then all the stored activities will be displayed. By passing a single date, the command returns all activities within that date. @@ -221,7 +221,7 @@ will return all the activities for that day, week or month respectively. Additionally, the user can specify a specific week of month by including a date (e.g. `list month 2020-03-01` returns all the activities in March 2020.) -#### 3.5.1 Current implementation +#### 3.6.1 Current implementation * List all activities: `list` * List today's activities: `list day` or `list daily` * List this week's activities: `list week` or `list weekly` @@ -234,10 +234,10 @@ Additionally, the user can specify a specific week of month by including a date * List activities within a time frame: `list DATE1 DATE2`, where both `DATE1` and `DATE2` are in either `yyyy-MM-dd` or `dd/MM/yyyy` format -### 3.6 Find Feature +### 3.7 Find Feature This command accepts a keyword and searches the activity list for activities with names that contain the keyword. -#### 3.6.1 Current Implementation +#### 3.7.1 Current Implementation * This feature is called by the user when the `find` command is entered into the command line. The string following the command is the keyword to match activity names to. * The Parser will create a FindCommand object. * The FindCommand will invoke its own `executeCommand()` method. @@ -251,10 +251,10 @@ This command accepts a keyword and searches the activity list for activities wit ![find seq diagram](https://imgur.com/Icg5rdB.png) -### 3.7 Filter Feature +### 3.8 Filter Feature This feature accepts multiple space-separated keywords to search for activities with tags matching each keyword. -#### 3.7.1 Current Implementation +#### 3.8.1 Current Implementation * This feature is called by the user when the `filter` command is entered into the command line. The space separated strings following the command are the keywords to match activity tags with. * The Parser will create a FilterCommand object. * The FindCommand will invoke its own `executeCommand()` method. @@ -266,8 +266,29 @@ This feature accepts multiple space-separated keywords to search for activities * If `lastShownList` is not empty, it will print the matching activities. * Else, it will respond to the user that there are no tasks which match the given keyword. - ![filter seq diagram](https://imgur.com/hybT3R9.png) + +### 3.9 Graph Feature +This feature gives the user a visual representation of their activity duration and activity goals. +Graph can be used along with List, Find and Filter to sieve out the data to be graphed. + +#### 3.9.1 Current Implementation +![graph seq diagram](./pictures/graph.png) +* This feature is called by the user when the `graph` command is entered into the command line. The user will then have to specify what he would like to graph (goals progress bar / tag duration / activity duration). +* The Parser will create a GraphCommand object. +* The GraphCommand will invoke its own `executeCommand()` method. + +**Graph targets** +This displays a progress bar for the activities in the activity list +* If the user indicated `targets`, Ui calss will be called to execute graphTargets. + +**Graph tags** +* If the user indicated `tags`, `GraphCommand` will call it's own `graphTags` method. +* A HashMap of tags to duration is created. The duration of every activity associated with the same tag is summed to get a + * Example: If tw +* which in turn calls `extractTags` in a loop that iterates through every activity in `lastshownlist`. +* `extractTags` loops through the tags of that activity. It checks if the tag exists in a HashMap of tags. + ## 4. Appendix ### Product Scope #### Target user profile diff --git a/docs/pictures/continue.png b/docs/pictures/continue.png new file mode 100644 index 0000000000000000000000000000000000000000..f6aec5a336c044a880cc9a32cc5f6fb8c27a3608 GIT binary patch literal 37587 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 Mb@pVEEdIv-0Wph=<^TWy literal 0 HcmV?d00001 diff --git a/docs/pictures/continueActivity.png b/docs/pictures/continueActivity.png deleted file mode 100644 index be17734b9b84c7f84007dc853b235be052e07edc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40280 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 Q9-ZT`>M@lJWedOm1&kl~Z~y=R diff --git a/docs/pictures/end.png b/docs/pictures/end.png new file mode 100644 index 0000000000000000000000000000000000000000..2d4437c62b1a465ddea6c0f434c31ba2bb1bcb27 GIT binary patch literal 37760 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 AcK`qY literal 0 HcmV?d00001 diff --git a/docs/pictures/endActivity.PNG b/docs/pictures/endActivity.PNG deleted file mode 100644 index a7c3f763a093d0451570fc7427db49d694a89a9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33720 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

!;1g?RQCi@5E8y#JT2S9|22Nr1Fo zeyng39=Gy-0diK;6c{B7`4wHzO94JN5da_5qwH1*qt+$>zQ8a0Kq_bfTb9%?R(o^If3ARlJ6xK|A#Ci)AJpnOY1h4#Ha!zLm}8?M+A z-cQ5j7lzFhD|)!EX!El#s`)kq^|6wfwf;&%T$}cN9Ul>C;(Ju5oIhe)Q{xYG zq}jn4Ok{*xr_UW)ehx?-Ne)lc61V2<*gH^BZ>3a}ZI#OZ5a8oPXuDc+Xy&zq>WZn; zVY_`5WR6vx_8YpLETD+8O%CG3TIV#yDo&2V$GF9Y(oz!%nuz+Fl3vzar%94ur@N<} zn;9|1w5~|mE_h&@fqHZtirW{cba&O**29e3M(>)fx>DqZRi+|O3><*n*ZHkTJUw6} zBRir@e4S!VD+F1CMlR1?;sHAV`NicDpSg$jeNB*mRT}U$aT9(;h(K70v231(Qj-kx zE_NF|MC`89;vY5TPjyv#xLbzK}R<7M<@e z);FgQRaF$0WF+^M3C&$)OeAuyZ1m0ZY-V{l?~Zi2p`p*oqY9h#hYv)z7^=cvU(T~n3!FG!e)~JjYw1puNEg`f+gqMQB9qcR?Y7)6 z(~{v>r<=k_qgRIokO;_yuQBzUn54eR$u?z4b!0WJI*|KB(Hwq?u7Qk=h^ZVU`lWSz zUhOxG9x%oUOYX}Q?K)}!-{xk2(iGJYgE~uSc4l3uN?k53k34GIU+_q2i+Q-Wi!D`F zZ^LtsX|{nav5@eQRZ$g?lOwQw5FPZQO({p%#C*8nbkN*F3MDM#U(G&H_^=?Qk{Q+r$ zin@qfBDHv)z2QlXt4>R^B|qg)*ckoUyKaD0s#bT(wywWO&$ zsqWQNf$mq#*anXXqJVN<=Kuk z85##Fz75x)2J;`WGP^M61D$R~p0|~(Vp}^yrQIn^&a2&{#b5v-0*s(%b|&Rw5fA3E zRjr?MO6QZ~@tacV$*8$vH`Q#E3aplMQ(DTd94byB+pwd?k+DO_n_Bvv=_qsWWQ0{u z*uMUl23&c~38bbFk8&rb2gXN+4B?mGwm zUVi5+mJ3#lZ~c8ykdB^RCtF+(Tc)d_Ip^Z>Xk-RrQgs-pJRgi#fo{iNIemKemG?1}Ff9ac65#l!q6+*HzWq z_W1zp>3PiItCb=ausfUNcgg~KXp&OVUdvr&cPlQ2&;24vc+ZGjSN1EfR+<`fx*o^u z;3daciRC|7BA&UMLjKIl9CzjeUFUx$*Jszc5{d}-&Pkaf%#XWcWh`#H?(PrBU$+{pIi@Zv0Ejz9YNh)V;2UF|*yt1KUB6rl7;)e1+&{>+zaIAA z4e)nB@rNov-x5fOm!8BGhCdMmBb77Z%&gk8r>Y@oP1NrY^}__7lr zb+=bnmd1xH)x1WH`bWG3em5rJ()#CI!GHl>@{*zV}(gU*zt#cu+Z#K-K&n7}Ih&-$ITD zOfsW2T$>~J`4JM7J=0Kx5pj*+GxS-~KHefvaWt)4?P~pR^UOh+lBEum$%WL#xHrM; z!R9Y$AKNQqQ4l^APysj}gzakJ_kmJ}?mDh+avvd0U5yS*es;t#BM9yeI5n$y?3vpc zD!0DeCD(Yu-?sp=B-3&oUudb{v>nvGG5l|`IP+?OYCeIBEESXBN##=b=_fD)~hd{|)rnN!ug!b|@G z=D^1)o+|lV*{>bJ_wo&sTe6YwIZ!Tx_2LsI0j>f6NMK(ElJ9A7<7VJLhaYc`FS3Ue(i|^`rfOtW7rUl>WvTY0jEr1c7>!k@hD{Q z*k`~Gey@PQHoJcq(CLT%>E*&LG-56R8?x%M`-F`%nlo=%4tS7pnbmIJ4vL_b6W){! z-Y{uW#bz;}K?_rn9&#G?>;E0d(6+Vy-BENh&LuWrA}<$zvSG!(Q$sUg_NLb`Y9TT9 zm?_L~QOBv3JDTi?2R@s54dX&8O0~VGdgn)Yz-Xcq9`Ki$#lm~!@BfO~e>+Umr+O3{ zV76)LMJWVk96x1!dpD|c`6j%4S9LJ(X1rtfJhRM2)qq%JTQkXs5RfYtfe-4&6Njmd zk9QFO_VvJ;dN**`3sjN7ZU+T-O7G-Q9o5b>8DI;QAXY(LLCfW=tV~#E=2(|c-BejL z3NY9B5hk+7oz~KW@>b`pfX^L+MeTw3vgmlQ$*X29?;3>MU;YaP=3zij~>iQ{wc zH%TU(f3T7KVwOi1on83sm2>0cBLpypwOU;Vi`+X(cETz~Yb?J?-7ron#wKc@sv{o& z0+>wa@mFw9YGvVImj2hC*H>hSdFIE66-djPvLZIljoeeD;FKxqJXHHOfXi86U_OE{ zuWGT53r!@*e1MhcLwJupzzd#tU@NLoy7=J&aCsrH(H+^VX277&=MnNnNM7sF=DJT z)-e}AFro^JYiA>tR@u`GdUr$vTIn=k-g%sUkky(@Y%-HUB?Zs-S+W9-8YevuK=FD9 zA=3MCc?szHa;MJ9^VyCfM+a;Csyg#Xc~%nLrz3=#EC;K77^HTy5?Oft*=mck|DJ=M z2p8++Sgu0h!-?2cz-#-vxtgiyKzTA`&(V>>bdPp~LL87i#7@)S%JXx4PIp z89Gn!M@<}Qm9MYlCq?d4rqBaBKtgEQf9BSKU62g1WN(brElQQA=gIg;A-UMq?A+;e zka1aMN`k~Y?i5^U`9c1CZ_Fo<#*6_iJ=tkItrciqIxBBBRC42E5#@ay=-~Zh7hHZ7 zjKL=9O=t^#(hKC6t18 z@xu3L%}VH+jKtWQ>3Zr4$abu1sU5!n=Nx1KsG8))u8lszU&y?H+!-1b4s4_^t4XB;!jvoSU`0;Ts++&Gk6sXi3$5 zuW>e)Vzj4^cO%RLw=u%fMSBdmV4O(owP+xJq4$j12Es)wA-YjG8E*AikW2T8Ru?#m zoJ*?cSzu9+#pLNL$@t^jMRrmq4bwB;05?eEXjIJAUeGEwjm~A$W|(Qm?G@JLTQaGMWiJms?YOT>IqQLvb4Upo3MYJ$Y!>^S= zjLR=wcsEzMvxm-^Z9mDlV||0yhGEPzw}m2vaTjD;)TN1|`yJ73@o7)HT#d|6;Yww#ZkP2e$;@6&w&SyJIiiwofeK3O<-dr!T;Z ztqx|AUZS*^>a^Rq$0_Ke)eWq$OPguv>IOg%9}Fy{)S9T3%Sba(6Y{vXsUHl&X8IhQ zodV_ZN0@=2r=)(|rlRXXP`*pI3aa@s-?B zcvetcwYTVttJ8SXlRZ=_=n4k)8Etu{^FBNA(1yshy5)yd?Gpu=3&b$7y?j!p>@}`A z;;TLPu6+TyGzE7$*K}ZBze=g4yM9{+XAd*_a`I2_sn29PQo4grxQ))^?TYyyDX!f0 zsfOQMk704i`)KBLxSC?*xX8%^vGq*VEPkI-PfWv@m>9dl|vSR*H;FaG=RRP=4)8XWSATv{EKjY`yLE z8K;T~Y#i|{ADmPMc(?7mL1f77&9PncFPI9>b+K7XX7oIHqV@Sz|c^4-J`9KQuWlg;-?7gQx*xH z9Bkh*cJVAg>|e6NR=;P3@w(RY1?JA4NyV1CE< zp!t7$e9vs8gvyhDVPnv0zZLrb!FOHy=Q^>PlD1lAe>w6FLudK2fH}lmkKsxAwfjM2 zmN!mTlv#8pmpS&2Ih_*41V@gg1$FcSJU}OjqA_5Gpmau)s6HsS4eqivR6>A5bJ?S`Tx`^dBLI>;yMTH41OV9Qd+pcjiP|5w0ig9| z?+(bh4?7@V5Am)AU9Fv?f%138yAI9)oRSEjOQL@4(ZnsgjwWbwSD?$UvEeZ*ys`in zwBW%G5#rk{zxJ?Ek*G?*Y?gXi>(hf;_)>=!JZP`uL9Ozuz5exMSY~z^=>H7kd1VLE zLkO}2ghvsN=fEZa=19L3ncuqS1QMOGc0r7aaSB(;Oai@l!)p{T7F6KL8OsveHJEeetv{gXYCVTFg2;;Yhq(_# z&&&To&0|jEOj%y!NmzY1Ikf*BsDX_AM_2t)fI;-WL~EcS1NxEhUU!(0eSu=kJmk6TmAg8&=PpIF#t~l zpoV!Yq#G{uBUakcE$a8`mmoBP-nF7_jdroh8%#9hwxATIeKA8hStgiu?N7PB+#(3skq+*(DJW7 z4}!3_#y%ydJx~yLXoON5Fc%(kHrfm$6zUHi##pnDxo|b?bsE6lwl1dJpza27aoi11 zTKXn}9G3vJFw}L*&WVDWD_sTF6>T0p2{|D$s(zikK7SgDMb2MUcX_MxWH(uiUmz8( z)voB=^{(TbtD|wJA9MVYT5P&loMU?&nLW`7LUzZa#uOE=$u)Rw&WBQQ!1qGDnh?++78)UW&6b1p2Dt zh-{$m`VVnc`rH6B{%J|8xA!mwN_BDHKxOnUb}d_Au*+>~iJ`F1Q#CQ&R#!9MF2&gwZU`ITj{9l~74 z-J-&qX2u>HstaP=nH%e@3VUa<4GERgF$BdNqagjzIW71u01q$f4;K+~d2qbJ7pQ5} z+RZd_iuXV$jjvt%Ub8BcTzVRZeCtGG-apv%i=|FfT6pFrpFtK61*$pAznD89F}rO@ z{eT=Pd5+NT;Y}Oja*|FLR`p))As#YO0I2{7)@tVE}U|hGHB^u5D)LU4}9w%mL6(Iy9DD3!XA@zEbv#&|7$opG&LmZWNncoC} zmmThG)qRrH8heb|?m{u5r-w;I6p8HljZ))TrrS`9%dl{T9&+J%COB+E=U)?AwEgqT z5RyB!QW2EHd3DCg*Rz#}d(h&Jete{ZB_eAm_iPVlas`FgM60s~u7p@BI%IGZaUtO> z{UzWKJc$;=%S8%D3?ue;OeAgTMoaLAdh0ni=KysQtIS#QnWbGo6K0=sM{|3pCf98! zc+R+{;mNp?J0eG%NyHIrS$@Y2i`A+6rccf%7tuIcfV%lxkNEA8Qb2cv)p&A3(|L^W zBi6kh*{~?RY(lQK43}c64L3jFe9S8}+*x;iHW^9_w@xa&cyqi=!cgW~by^Oc7Ng-8 zE}_eIaLJN{cP69Ntt~oJqlEN3KZVEjomTUkQUJ_WG0LOq`D#%(>)xfyG?s#G{}w}H zl}m_-JHlc$NP0I)Qe!gy(TASlYxa$ve~2Qt$ir|}VJ11dd%AKPtiMV-0wwPALwe8y zs$aA#wOFojQI6)zl5T`^Qui7gvlWlwdUZf2(fIa*z;Tz~8M+0vEXv;$z8(77{fE|G zibX@O5ai9J<(drR3fvZJvQKL+c#1I-UtLB9Jv3$HDd6j-^&yYq;uj6j``~HvIsBXV#6|Y!5sMibx?j z6df?g7i5k@V3=1wf7Ul{zH{)eW*>O$Cwg&%$1;n7G<_5|ElRHP#L{?tkeXkS7>Kl~ zIb0UilW{B`NG40GxS(9??pc!e_$iSTxhLmz1%MZ`Pme?+HekYV9#Haw!OY9=9j+HSFZ3DvgT)UDG)@csl9}svv!Gp zA!C^oCwGlvYB`@kk!Jx0wo3RMDfyDvsq1$mQ!aGVQA;E7&|wnDrf!%l+NTSCLjg|S z4Dg=K0`m85{*F@F!uHz9dyPR%-X?as5fBpZg29cWr7aRrkfjxlnWo{O`_zM2xOV3e zE$9ZG!jDI&5rA3wdAS3#_m$6;-*DRW}XTiOHh} zDWCN_0abD`XwkHLPVQPIUV{syiRF**AVmZ8R3{;K4gEZuP{;#SlBVT~fH;E^Flq2A8HI4618Vl`-~O#nHtccGPVWMP!=n#_=4@s1r3!ayKiXEwZQ#14s_?P) z_>)ytKGQ>k8c|Bo);Q-Fb>VT4R~e+9wq`xb;>>pfMhrSR0`OXL)i9dcd=ZE!jUx9d zx|K)?+xdUpP=o28TkyB%2#lLX_X544Hq{d3pB|Gql zj+MsEJhAqV3xDg8^`nJ2AG#KDt->wgs6Kp(3K6Em(@&BrJ`}ZEU+OQ=1}eAKE{j5I z5!;$W9+>c`=h<*)RfSt8D0sv7x1dFPAb`y!*c^r3{rv9-Gmz<4I|`Y|5jIdemdG?w z&Kk5k&*cJbFC~>w;qZ1yu<1T)zN=%H)&*pIlqI#g`^ApT1O~NA8G!L}87AeS0XXA_ zrd+a%E|xmuHHr~<&XY(QzgB=|YSCP|g6dIr@fkX7f2p%=#Ha<3rXq{37!~Wxq;qV+ z^g9lr7Hrv^`QpZ>8 z8B5`;CL(bBw(toWJ+O#50w4)hs>`wP z)^l4JbAbOolYZQ^Di^x|bB;U0*-s;7Wj=brNs=(_EGAuHDZb#;_Y_Bqp3gf3d%E?n zj$`Rzc^F_wZ#wP6wLZ6~yp0r=1!DQC>1-INtuBBF84pS;^2f}N@IUgGzCGrh=^wxB zA)KDO5kCy{R=aGaPw;}aQd9TI&li7Hn>#=edJa6|>8VD&H-KscrRNS1nh$T2-w7^F z2mcX>ZrFBs$@P0+^Uo`W>2G?50mbPf(Ji2m1v0HAP-bqgxsa2|rj6eRg+}?9-CEG) z`}_XmO`=P@k`rL~>zyxf{xkMLC$bd8mxI232t@!|&v%oD_(o2PWC*T3S5WfAGG%t8 zoxxC*hJ(VTh?019EQm+N)oDKU{*Q?{!VcQU9P5A{4iCbF5fGkF%0A*1HlPDWkOe^~ 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 z zhcy}#Esiu07JH?ZwH%Q;Gjxd(;ufL1@VO-dv^`Yy1hs#ic>c#^Co~MRg*&wLUz)ss z%H!!d3hrB{-`V-CS)%U$PfGTGJe@(%M`Fo#F0kAbk90f&u zmNO0Jpc*upcX?cOD_wxp&uQ_+8vHIqV?W?!P!o#Ly*RA&_SMQ{gb~*kHfr; zZ$sogtx=zuaWS)3%%v5`wmw2Vd}X~kCPCK!V7pce_z%-As0G{p2}J~V6Br8ycjCP$ zFws{7c#PlhU44}f)0ZqE>PWEQFHVd1iv33p7%#&H{fE!Q_zj}Vo1y9KY$3y_oqWS6 zcpXjGLxcHX93XPq{%VhsW$$@$UHjHrD^ zlT3QWc6i!9rYQbN-%$j!VFbmI{U{9qFlb5q_aj4msFz?AFcu~q0j4*%t;{7XOCu{W?7U$X&~#5(v3J5dyq z0lC_%-!&|lgVd1D7y#z0RKO$E^!_Y}La#H-?Zol_A?zVqurW$t2PAQ(#~9-Pgn;Gz zyC*3z#2WtbUlEx}4%J9L%QVbE-fuVc|H6O$cf!Ib0yF6ji3nGcI&<+mK@C1X{gG3J z;Yb>%jur&X7*j09hZo*9=!Nm^tRnulSih;Jo-abkvj~#;OuW-v4fQ0$SX;pYzX6-l za_bj?t!I+&gk;V7oMd`tr_e1=ZrBA#df0|`x767#aH9gQ8O$Y?MhB55zu-(GyqzL~y0ve)}Vi|2dxuhs0r z7V)m;-(KU=HvwKk16N{@YtCTtEcVRi+|ZUy>8StKsODDk`bU|qkLXF#z@;gmgo{v8yQu1Jo zGxo*%v?wqpUdp=C*5avU2&J130W60KoFijs3ZpZmz&Y1P4nX>Z|6mL+pauteF0b-J zP+8xT1`;a@xbeZ0>pG*{;owN{TpAq;8i0n29~Av7>q^fB5m z=I~*sA{HEh;(FycFec^4h!K2BtyvYlQ3EqcTjZk^yP82}#Em#=T_o#6?)H$IlZ#m~ zYop~L0*ZhOe##QNwQ9FrXwYsj$RSIH344lu2o|28<7Y0q+7*&v1ewuieu3Nz;#a8Z zY$g;0`sxbdbHPXY0Y@zXH*9ZTadwmqwHC~o1b4l@8E5s>-mT%i4bS($s*1LT$4i9g zaq8LdZ6v&|RU*Hziar`vK+%#9&xcgpu(_|u}N7J}?aGl?QI zYGv=O3GYFVFEB+iO4v-i5mv*jst-A)5DV8C+D4g%EK{n3VP@n^7{Lfw8Wtu$#2!aq zL?wVHF$|@6iVob?l@Kih-;MF3YC?m!UQs4sYP>&)`yDFkJf61Jrj0_qb@~MrmbV z3!T8sxRk-@K?gqc(QRneLX^kc1HTTGS6TdNF+P+sofW29A!_hCGP=i+xPnB^Tr{A# z5X@Cei4hD%e`7%9d@`11^|@O3?S_*cqkLZDT#lTv-~R#BIkWQs literal 0 HcmV?d00001 diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index a38bd4708..fe0bd2145 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -158,18 +158,18 @@ public int getSize() { * @param activityList list to save to * @throws InvalidTimeFrameException if start time is before end time */ - public void saveActivity(ActivityList activityList) throws InvalidTimeFrameException, NameTooLongException { + public void saveActivity() throws InvalidTimeFrameException, NameTooLongException { if (Parser.continuedIndex != -1) { Ui.printDivider("Ended: " + Parser.activityName); Parser.endTime = LocalDateTime.now(); Duration duration = Duration.between(Parser.startTime, Parser.endTime); - Duration oldDuration = activityList.get(Parser.continuedIndex).getDuration(); + Duration oldDuration = this.get(Parser.continuedIndex).getDuration(); Duration newDuration = duration.plus(oldDuration); - Duration allocatedTime = activityList.get(Parser.continuedIndex).getAllocatedTime(); - activityList.updateDuration(newDuration, Parser.endTime, Parser.continuedIndex); + Duration allocatedTime = this.get(Parser.continuedIndex).getAllocatedTime(); + this.updateDuration(newDuration, Parser.endTime, Parser.continuedIndex); if (allocatedTime != Duration.parse("PT0S")) { - Ui.printProgressMessage(activityList.get(Parser.continuedIndex).getProgressPercent()); + Ui.printProgressMessage(this.get(Parser.continuedIndex).getProgressPercent()); } Parser.continuedIndex = -1; Parser.resetInfo(); @@ -180,7 +180,7 @@ public void saveActivity(ActivityList activityList) throws InvalidTimeFrameExcep Duration duration = Duration.between(Parser.startTime, Parser.endTime); Activity newActivity = new Activity(Parser.activityName, Parser.startTime, Parser.endTime, duration, Parser.tags, Parser.allocatedTime); - activityList.add(newActivity); + this.add(newActivity); if (newActivity.getAllocatedTime() != Duration.parse("PT0S")) { Ui.printProgressMessage(newActivity.getProgressPercent()); diff --git a/src/main/java/jikan/command/ByeCommand.java b/src/main/java/jikan/command/ByeCommand.java index d96978388..08fed5492 100644 --- a/src/main/java/jikan/command/ByeCommand.java +++ b/src/main/java/jikan/command/ByeCommand.java @@ -41,7 +41,7 @@ public void executeCommand(ActivityList activityList) { Scanner scanner = new Scanner(System.in); String userInput = scanner.nextLine(); if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { - activityList.saveActivity(activityList); + activityList.saveActivity(); } } Ui.exitFromApp(); diff --git a/src/main/java/jikan/command/EndCommand.java b/src/main/java/jikan/command/EndCommand.java index 27c81bb22..fa7f432d1 100644 --- a/src/main/java/jikan/command/EndCommand.java +++ b/src/main/java/jikan/command/EndCommand.java @@ -33,7 +33,7 @@ public void executeCommand(ActivityList activityList) { if (Parser.startTime == null) { throw new NoSuchActivityException(); } else { - activityList.saveActivity(activityList); + activityList.saveActivity(); } } catch (NoSuchActivityException e) { Log.makeInfoLog("End command failed as no activity was ongoing"); From de36baa13459c7343f3ace3fd2984290e1b24c80 Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 6 Apr 2020 18:04:27 +0800 Subject: [PATCH 262/415] Change graph to lastshownlist --- src/main/java/jikan/command/GraphCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index ed26b4673..0363b4ebf 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -36,7 +36,7 @@ public void executeCommand(ActivityList activityList) { try { switch (inputs[0]) { case "targets": - Ui.graphTargets(activityList); + Ui.graphTargets(lastShownList); break; case "tags": graphTags(); From df6d5d1aafe144ca2393ab0567254f03d7371e53 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 6 Apr 2020 18:05:36 +0800 Subject: [PATCH 263/415] Standardize the use of allocation --- src/main/java/jikan/command/GraphCommand.java | 4 ++-- src/main/java/jikan/command/StartCommand.java | 4 ---- src/main/java/jikan/ui/Ui.java | 6 +++--- 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index 3d91a0be5..18da1008f 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -34,8 +34,8 @@ public GraphCommand(String parameters) throws ExtraParametersException { @Override public void executeCommand(ActivityList activityList) { try { - if (inputs[0].equals("targets")) { - Ui.graphTargets(activityList); + if (inputs[0].equals("allocations")) { + Ui.graphAllocation(activityList); } else if (inputs[0].equals("tags")) { graphTags(); } else if (inputs[0].equals("activities")) { diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 6f88cf256..199ea0ffa 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -1,10 +1,7 @@ package jikan.command; -import jikan.exception.EmptyTagException; import jikan.log.Log; import jikan.activity.ActivityList; -import jikan.exception.EmptyNameException; -import jikan.exception.WrongDateFormatException; import jikan.parser.Parser; import jikan.ui.Ui; @@ -13,7 +10,6 @@ import java.time.Duration; import java.time.LocalDateTime; import java.time.LocalTime; -import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 51f03f06e..e660f1f6a 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -97,7 +97,7 @@ public static void printResults(ActivityList resultsList) { System.out.println(DIVIDER); System.out.println("Here are the matching activities in your list:\n"); System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %s", - "|", "Name", "|", "Duration", "|", "Target","|", "Date", "|", "Tags")); + "|", "Name", "|", "Duration", "|", "Allocation","|", "Date", "|", "Tags")); for (int i = 0; i < resultsList.getSize(); i++) { if (resultsList.get(i).getTags() != null && !resultsList.get(i).getTags().isEmpty()) { printTableFormat(resultsList, i, true); @@ -116,7 +116,7 @@ public static void printList(ActivityList activityList) { System.out.println(DIVIDER); System.out.println("Your completed activities:"); System.out.println(String.format(" %s %-25s %s %-10s %s %-10s %s %-10s %s %s", - "|", "Name", "|", "Duration", "|", "Target", "|", "Date", "|", "Tags")); + "|", "Name", "|", "Duration", "|", "Allocation", "|", "Date", "|", "Tags")); for (int i = 0; i < activityList.getSize(); i++) { if (activityList.get(i).getTags() != null && !activityList.get(i).getTags().isEmpty()) { printTableFormat(activityList, i, true); @@ -250,7 +250,7 @@ public static void printProgressBar(double percent, String activityName) { * Method to graph out all the targets. * @param activityList a list of all activities. */ - public static void graphTargets(ActivityList activityList) { + public static void graphAllocation(ActivityList activityList) { System.out.println(DIVIDER); for (int i = 0; i < activityList.getSize(); i++) { if (activityList.get(i).getAllocatedTime() == Duration.parse("PT0S")) { From b51804daf2aaa99997e464a47aea730d2f14cace Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 6 Apr 2020 18:11:35 +0800 Subject: [PATCH 264/415] Change targets to allocation --- src/main/java/jikan/command/GraphCommand.java | 4 +- src/main/java/jikan/command/StartCommand.java | 38 +++++++++---------- src/main/java/jikan/parser/Parser.java | 2 +- src/main/java/jikan/ui/Ui.java | 2 +- 4 files changed, 23 insertions(+), 23 deletions(-) diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index 18da1008f..4376017d7 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -41,12 +41,12 @@ public void executeCommand(ActivityList activityList) { } else if (inputs[0].equals("activities")) { graphDuration(); } else { - Ui.printDivider("Please specify whether you want to graph activities / tags / targets."); + Ui.printDivider("Please specify whether you want to graph activities / tags / allocations."); } } catch (NumberFormatException | InvalidGraphCommandException e) { Ui.printDivider("Please input an integer for the time interval."); } catch (MissingParametersException e) { - Ui.printDivider("Please specify whether you want to graph activities / tags / targets."); + Ui.printDivider("Please specify whether you want to graph activities / tags / allocations."); } } diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 199ea0ffa..ff2a7079f 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -19,9 +19,9 @@ public class StartCommand extends Command { private Scanner scanner; - private boolean hasTarget = false; + private boolean hasAllocation = false; private boolean hasTag = false; - private boolean hasTargetAndTag = false; + private boolean hasAllocationAndTag = false; private static final int maxActivityLength = 25; /** @@ -108,16 +108,16 @@ private String parseActivityName(String parameters) { int allocateDelimiter = parameters.indexOf("/a"); scenario = getScenario(tagDelimiter, allocateDelimiter); switch (scenario) { - case "hasTagAndTarget": - activityName = handleTagAndTarget(this.parameters, tagDelimiter, allocateDelimiter); + case "hasTagAndAllocation": + activityName = handleTagAndAllocation(this.parameters, tagDelimiter, allocateDelimiter); break; case "hasTagOnly": - activityName = handleTagOrTarget(this.parameters, tagDelimiter); + activityName = handleTagOrAllocation(this.parameters, tagDelimiter); break; - case "hasTargetOnly": - activityName = handleTagOrTarget(this.parameters, allocateDelimiter); + case "hasAllocationOnly": + activityName = handleTagOrAllocation(this.parameters, allocateDelimiter); break; - case "hasNoTagAndTarget": + case "hasNoTagAndAllocation": activityName = this.parameters.trim(); break; default: @@ -135,16 +135,16 @@ private String parseActivityName(String parameters) { */ private String getScenario(int tagDelimiter, int allocateDelimiter) { if (tagDelimiter != -1 && allocateDelimiter != -1) { - this.hasTargetAndTag = true; - return "hasTagAndTarget"; + this.hasAllocationAndTag = true; + return "hasTagAndAllocation"; } else if (tagDelimiter != -1) { this.hasTag = true; return "hasTagOnly"; } else if (allocateDelimiter != -1) { - this.hasTarget = true; - return "hasTargetOnly"; + this.hasAllocation = true; + return "hasAllocationOnly"; } else { - return "hasNoTagAndTarget"; + return "hasNoTagAndAllocation"; } } @@ -155,7 +155,7 @@ private String getScenario(int tagDelimiter, int allocateDelimiter) { * @param allocateDelimiter index where allocate flag is found. * @return activity name */ - private String handleTagAndTarget(String parameters, int tagDelimiter, int allocateDelimiter) { + private String handleTagAndAllocation(String parameters, int tagDelimiter, int allocateDelimiter) { String activityName = ""; int delimiter = 0; if (tagDelimiter < allocateDelimiter) { @@ -178,7 +178,7 @@ private String handleTagAndTarget(String parameters, int tagDelimiter, int alloc * @param delimiter index where tag flag or allocate flag is found. * @return activity name. */ - private String handleTagOrTarget(String parameters, int delimiter) { + private String handleTagOrAllocation(String parameters, int delimiter) { String activityName = parameters.substring(0, delimiter); activityName = activityName.trim(); if (activityName.isEmpty()) { @@ -211,10 +211,10 @@ private void checkActivity(String activityName, ActivityList activityList) { * @param activityName the string representing activity name. */ private void addActivityToList(String activityName) { - if (hasTargetAndTag) { + if (hasAllocationAndTag) { parseActivityWithBothField(activityName, this.parameters); - } else if (hasTarget) { - addActivityWithTarget(activityName, this.parameters); + } else if (hasAllocation) { + addActivityWithAllocation(activityName, this.parameters); } else if (hasTag) { addActivityWithTag(activityName, this.parameters); } else { @@ -283,7 +283,7 @@ private void addActivityWithBothField(String durationInfo, String tagInfo, Strin * @param activityName the string representing activity name. * @param line a line with information about allocated time. */ - private void addActivityWithTarget(String activityName, String line) { + private void addActivityWithAllocation(String activityName, String line) { int index = line.indexOf("/a"); String durationInfo = line.substring(index + 2); durationInfo = durationInfo.trim(); diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 66ab690e1..7f9e00ca8 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -165,7 +165,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto + "If you'd like to graph by tags, enter the command ."); } catch (ExtraParametersException e) { Ui.printDivider("Extra parameters or invalid format detected!\n" - + "Use activities / tags / targets to view the respective graphs."); + + "Use activities / tags / allocations to view the respective graphs."); } break; case "goal": diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index e660f1f6a..20aec0247 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -247,7 +247,7 @@ public static void printProgressBar(double percent, String activityName) { } /** - * Method to graph out all the targets. + * Method to graph out all the allocations. * @param activityList a list of all activities. */ public static void graphAllocation(ActivityList activityList) { From 1e0224b9a4078d711d4b3b8c20097c40d40301fe Mon Sep 17 00:00:00 2001 From: btricec Date: Mon, 6 Apr 2020 18:51:36 +0800 Subject: [PATCH 265/415] Update DG list and graph --- docs/DeveloperGuide.md | 72 ++++++++++++++++++++--------- docs/pictures/continue.png | Bin 0 -> 36949 bytes docs/pictures/continueActivity.png | Bin 40280 -> 0 bytes docs/pictures/end.png | Bin 0 -> 38652 bytes docs/pictures/endActivity.PNG | Bin 33720 -> 0 bytes docs/pictures/graph.png | Bin 0 -> 38815 bytes 6 files changed, 50 insertions(+), 22 deletions(-) create mode 100644 docs/pictures/continue.png delete mode 100644 docs/pictures/continueActivity.png create mode 100644 docs/pictures/end.png delete mode 100644 docs/pictures/endActivity.PNG create mode 100644 docs/pictures/graph.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index d76270e51..f5df1c38c 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -172,26 +172,22 @@ However, by allowing the user to edit the start date and time, there may be pote The continue feature allows the user to continue a previously ended activity. #### 3.5.1 Current Implementation -![Continue command sequence diagram](./pictures/continueActivity.png) +![Continue command sequence diagram](./pictures/continue.png) **Continuing an activity:** - -When the user enters the command to continue an activity, a *ContinueCommand* object is created in *Parser*. The method `executeCommand()` of the *ContinueCommand* object is then called and does the following: - - 1. Checks if the given activity name exists in the activityList by calling `findActivity()` (if it doesn’t an exception is thrown, omitted in the sequence diagram above) - 2. Gets the `name` and `tags` of the activity to be continued and saves it to a public static variable of *Parser* object - 3. Gets the current time and saves it to a public static variable of *Parser* object +* When the user enters the command to continue an activity, a *ContinueCommand* object is created in *Parser*. The method `executeCommand()` of the *ContinueCommand* object is then called. +* `executeCommand` checks if the given activity name exists in the activityList by calling `findActivity()` (if it doesn’t an exception is thrown, omitted in the sequence diagram above) +* It then gets the `name` and `tags` of the activity to be continued and saves it to a public static variable of *Parser* object. +* It also gets the current time and saves it to a public static variable of *Parser* object. - ![End command sequence diagram](./pictures/endActivity.PNG) + ![End command sequence diagram](./pictures/end.png) **Ending a continued activity:** - -When the user wants to end the continued activity, an *EndCommand* object is created in *Parser.* The method `executeCommand()` of the *ContinueCommand* object is then called and it in turn executes the `saveActivity()` method of the *ActivityList* class. The continued activity is then saved by executing the following: - - 1. Gets the current time and saves it to a public static variable of *Parser* object -2. Calculates the elapsed time using the `between()` method of *Duration* class -3. Adds the elapsed time with the previous duration of the activity to get the `newDuration` using the `plus()` method of Duration class -4. Calls the `updateDuration()` method, which updates the `duration` attribute of the continued activity in the `activityList` as well as the `data.csv` file +* When the user wants to end the continued activity, an *EndCommand* object is created in *Parser.* The method `executeCommand()` of the *ContinueCommand* object is then called and it in turn executes the `saveActivity()` method of the *ActivityList* class. +* `saveActivity()` gets the current time and saves it to a public static variable of *Parser* object. +* Then the elapsed time is calculated using the `between()` method of *Duration* class. +* The elapsed time is added with the previous duration of the activity to get the `newDuration` using the `plus()` method of Duration class. +* `updateDuration()` method is called to update the `duration` attribute of the continued activity in the `activityList` as well as the `data.csv` file. #### 3.5.2 Design Considerations @@ -210,7 +206,7 @@ Although the current implementation of the continue feature disallows users to h As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, they will be given the option to continue the stated activity. ![decision flowchart](./pictures/continue_flowchart.PNG) -### 3.5 List feature +### 3.6 List feature This feature is used to list activities within a range specified by the user. If no parameter is passed to the `list` command, then all the stored activities will be displayed. By passing a single date, the command returns all activities within that date. @@ -221,7 +217,7 @@ will return all the activities for that day, week or month respectively. Additionally, the user can specify a specific week of month by including a date (e.g. `list month 2020-03-01` returns all the activities in March 2020.) -#### 3.5.1 Current implementation +#### 3.6.1 Current implementation * List all activities: `list` * List today's activities: `list day` or `list daily` * List this week's activities: `list week` or `list weekly` @@ -234,10 +230,10 @@ Additionally, the user can specify a specific week of month by including a date * List activities within a time frame: `list DATE1 DATE2`, where both `DATE1` and `DATE2` are in either `yyyy-MM-dd` or `dd/MM/yyyy` format -### 3.6 Find Feature +### 3.7 Find Feature This command accepts a keyword and searches the activity list for activities with names that contain the keyword. -#### 3.6.1 Current Implementation +#### 3.7.1 Current Implementation * This feature is called by the user when the `find` command is entered into the command line. The string following the command is the keyword to match activity names to. * The Parser will create a FindCommand object. * The FindCommand will invoke its own `executeCommand()` method. @@ -251,10 +247,10 @@ This command accepts a keyword and searches the activity list for activities wit ![find seq diagram](https://imgur.com/Icg5rdB.png) -### 3.7 Filter Feature +### 3.8 Filter Feature This feature accepts multiple space-separated keywords to search for activities with tags matching each keyword. -#### 3.7.1 Current Implementation +#### 3.8.1 Current Implementation * This feature is called by the user when the `filter` command is entered into the command line. The space separated strings following the command are the keywords to match activity tags with. * The Parser will create a FilterCommand object. * The FindCommand will invoke its own `executeCommand()` method. @@ -266,8 +262,40 @@ This feature accepts multiple space-separated keywords to search for activities * If `lastShownList` is not empty, it will print the matching activities. * Else, it will respond to the user that there are no tasks which match the given keyword. - ![filter seq diagram](https://imgur.com/hybT3R9.png) + +### 3.9 Graph Feature +This feature gives the user a visual representation of their activity duration and activity goals. +Graph can be used along with `list`, `find` and `filter` to sieve out the data to be graphed. + +#### 3.9.1 Current Implementation +![graph seq diagram](./pictures/graph.png) +* This feature is called by the user when the `graph` command is entered into the command line. The user will then have to specify what he would like to graph (goals progress bar / tag duration / activity duration). +* The Parser will create a GraphCommand object. +* The GraphCommand will invoke its own `executeCommand()` method. + +**Graph targets** +This displays the progress bar for the duration with respect to allocated time of activities in the `lastShownList`. +* If the user indicated `targets`, Ui calss will be called to execute graphTargets. + +**Graph tags** +This displays a bar graph of the cumulative duration of the tags for each activity in the `lastShownList`. +E.g. if 3 activities in the `lastshownlist` are tagged `CS2113`, the durations of these 3 activities are added up and associated with the tag `CS2113` in the graph. +* If the user indicated `tags`, `GraphCommand` will call it's own `graphTags` method. +* A HashMap (`tags`) of tags to duration is created. +* `graphTags` iterates through every activity in `lastshownlist` and in each loop, `extractTags` is called. +* `extractTags` loops through the tags of that activity. Tag is added to the `tags` if it is not found. Else, the duration of the activity is added to the corresponding tag in `tags`. +* `tags` and `interval` (how many minutes each point in the graph represents) is passed to the method printTagGraphs in Ui to print the graph. + +**Graph activities** +This displays a bar graph of the durations of each activity in the `lastShownList`. +* If the user indicated `activities`, `GraphCommand` will call it's own `graphDuration` method. +* `graphDuration` calls `printActivityGraph` of the Ui class and passes the `interval` parameter, which is how many minutes each point in the graph represents. + +#### 3.9.2 Additional features +As graph gets it's data based on the `lastShownList`, users can pair the `graph` command with `find`, `filter`, and `list` to sieve out the activities to be graphed. + + ## 4. Appendix ### Product Scope #### Target user profile diff --git a/docs/pictures/continue.png b/docs/pictures/continue.png new file mode 100644 index 0000000000000000000000000000000000000000..0a02f70ac8145150029ae915d5ca47e7cb5afe2c GIT binary patch literal 36949 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∓?9zM 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 Q9-ZT`>M@lJWedOm1&kl~Z~y=R diff --git a/docs/pictures/end.png b/docs/pictures/end.png new file mode 100644 index 0000000000000000000000000000000000000000..defb908e6d8d9c509943ba7cd539d07086254b7f GIT binary patch literal 38652 zcmeFZcU049+b$Y}5g9}rc}MBssGuT6AQUN4QBfh_fQWPu=_Pas0fK@s4oDfA5Q?aP zbOb_&peQIIfQBBb5PE2V1PDpa6W?#IbM`vl-skMIzP0~4xLkqcSD)W=U-xxg_x9z2ZyY4?dsU z7XA>3FoyG=>rP-)DtPnoBLn>#5H{!EtJb0v@D6Xl9r#V&IiACOA{Qqk|8xUyoeQ}6 zFyOI6fYTL6KPT`4QC3n`l2=ldS5mvLqgztN%QQn!{UyECiDF{?3hS_d{$~ znF0+tP7bo6Q@8JR9Cy2V;a2j$l%2{%MDN}hJFWNUAMZ7eK5*@KT!1`nd8(**M11Lv zrC?fiREJCXblkP+oD72$?gz(I1~$&6+$p>nub0(X*TePeYmvL3-{p6@pO%lfFp>4SJoz+&>iY>in7?1fKTsIi+6*I3>oL?dnPRt$R{1T8Y{qv1i zvpkKQzabK`UpNmAvZ!%Qf%AH`i_edX^UD>ZB!13ozwc9P&TC|X(Eopk|9>q0Yv%>3 zwZ(!Y7#|2bz?j%RwCRqKH5lD~q;;b6)diKiqlnN8h!Fh?jMd=;9xwr)8zk}1e(1Bk zL`Gz!SI;~T;)y?lQ^lonJ7c*GkHARxx?vTHHAy|4`fyRskQLR){GAYhv2o(&e|_65D&Vg)!wl4 zM)odpZ6+v^Z+%+mE^;D1$o{BF?$Y4SR*T#0{MJ6!B%-B4;)BuVGWT61vAJtF!xXam zCpZ}1HljEc$MU=&mgk}0uAw%IR&ZjYza3MmIC5OLw~csLb2rDa^Z{n8$EV3MH+-pT zrFBOAZsvYn5Cl?}7n}3pA&qW#>W8wgHj`{(yG5Myy|eh)$3($IxAO!!b0*-ub`jq% zr`IazbhO&>m)z~gPRxCLNP`{B5_taM-EG~y4=z4gutG9( zwv_|(;vFHMcv;k`3t5F+Q;0V!&U|UlFY^z2*PGPQkS`;A=JJE?=UY9u0}8S|L)@wC zl&7C3mKljy9Y|F;PovTU<^VA|GtxG!iQ-`WCFPsL+a_DvRF_+C_{n6cwh3Al>8v(y zq=fXBXYcQl8VqlU)heo29L(<5@!op1LcWP~R&BaxtIA!?C^)vjfLDTSkFAgiV-fc1`@3B*TNWO@r|7iaN>@;9-8RY8 z^mo>rjaTW`n%qoK4qP4xswm%OEt{}{+_aSHY-+X<-TML^vA<{Z!d@HZY%K@5ZujC? z7&yH!F44Ow*@wP@W?r{=KaV183|wHOI-<$#^H8_-=Tr&v>*J;;%Py&hc|Oowvun$j zAo=RErMv_kClhlQ4@_AZ%wcwO*)F0ll{lqS({ts=bkHizVsE4#f72X|9jEF`T_R2@ z6-a2+Mhg@jpxYi+v`ptXP2%99@ z^K5#<*?sFTa@5EhCX>6pL9e2M{zUd-_vheta{dvNe#%9DE&LBfbj|ny*^HdbW;YV1 zzW#zfu-9_BN?ZS8ryGKCLb<$Kcx+Xn!Onqe;ykGgd)6Hl(tC+-&$bSxPSxvZnLnj^ zu+VI*#6_q5+G28fY-@fCWkdZa5;kU&K3QL9-HODyi%dF3EXAA9Mt9bQAf2*MKL>h}&#u+5L>7UL|C4=i zYAoL*U1uNGJ#LVZv9f-!PT1IvqRW>`+Sw`WuP*z|xJY_jpM3s^Uif#4974jcg ze;jzG9#K9{UocMRl|oiaX!-GZ8}BcoU1RTR?w2Dxua8F^+jXJ5oN>zSLH&3itKPwv z+Q*(^n-XCsMyFQk9(Fp#64bjE>{uh+YKgI?=n&=yiRLcq6gzg_a?LGKhXw17*E{BV zsEQ|Wv`7|5rLs-8Y`EiJ;%L!85_y}wd(!k$Cv>>a5rrNH1N9HNymEQsjtxUv6HGIF!a?($-i z=yC*uG^H?Xi}Dg$&JA5Ip1n9gFy1xguZ{SEieR?KzE@d*E5`NiW$3k;h^bSD$?j|) z0@r}o4T_{+e;YiQY{v?>*nNg2x1jwWHquKp3HyEF>oZPYr4B+Hw>nfX{d9ix{(Th$ z7E9SlSkIHi>ugTQ!%}II`bV)n%d&?*4n_oyvI1`*sK4#(uBh!h?OmaaE}+K)idrN3 z29uuX6eI1J%zn7Abz=xp$U3KXuLJ$`^^Eo=<&^DjSDkii4BBjuO|^vO&{FceFQ(Y3 z6d$a*V5Z(+x^{5-D0;zRGd^+UwS6sC7`1f+3rE}PG4E^7D$7^nc-LT!h7lB9f)8$0 zZ`-JEtN1Iad9BGfSZBAq@PUmDtl4NiFdoWgHWp&48|0aIn!)H@q(n)Je!7(R{u>XR zl{34$wvhcy>gWMwcSL0Ud>m^^R;_ZtPkZ()0j;mzN6%;P;0fEdfuvTloH8qyoT$!( zP3{uSJ+<)LICGQI8gKQ=mOhh7R9C@aZ-nMLx{^-QFLbf$Sjx-G!#6IqR(Rxvv@O{( zHdC@Ze2MJ+$?6|NH5lb=(f50gO1k}+PJeV@#p$;7V^eY+OsBWK8KQHo^zs+%hT_IV z+OiEAH@UgAK4lCU5mGIOpl*9vI;c(_%&TY6TNZT4HtV70nZE6Dj@53@RNo|tHpuBx zdzJT~D0Qr(P}yY7Vncb%b3UoQ-46XM2yLFdOML~MS!r>c9NAvT+vLUV1rzpv#0N{7 zIJ3U9qE=w8%O2fdGb+#5Bx=0k^NIb3VhG#K6By7K+aPXzTfsFV$NN0^U2;z4(D2+d z-Sop*=NeYy&va+Wq93j?I@@C@RthMT=He+^Q{4#Svh%12VytqU_S`XRw!AC3@Mzoa zbUkKTqZ$pHJm8vrD#o%x&gjD?9%Vk<->AnA8XVSL?0iy*3T)hbZAa3cYB#2y9N)@- zm(Oz-wuJiRFsYBxh!)0kXP63w&Yq}LWgKrM7zN}O{@$5*Otm~|dMjIwRq5B^w0@yW zVkbRlwGVTxftipMTU;_h(;qv&4*9_N#f=l_n*Isw8 zl{relK0mk-{x#eKBkkE>-!KqE}a#xB=yitxLLEqmptmy!ka07oATDDkhdbrs4iNk zvNsbX5Z51xL(BWotiIh(Iq=NJb$@n+NQJv5Mczu!raAR_VfxNIc_k39-FSFMGIc|Z z{>>H}Hsn;|shIEA?VKa)#QJE=UOGuuCOr&U+azEsoiypIypl-2jn;3tO43c@uN*?+ z-PMz;(@b$}VGOhP?GmqiDR=I9`KNBsJR)s&a$}hC^8FbsJdeTZ{IG#N+?+VRT~W>& zC_miBr=iH6w!*yHE;ELWMdy}!=aPE-JEd4ip=_ClI%M_9`|0e@)Tn&#A@&!$)_&Ez zs`7pflhU1mXL1-;oH3j1j5funPn^X)nqV za}_Jub(#Gma%*#HkG%DxGo$XI^UONyZsS5<8!5Uj5azLK6*U?Tz>4p=i_~ST^%b_A zDk&#?k{hmmjT(zysq!1%a>2AWAD(~)RIG#$SLj~7cD?2wHwW%Ys_-<<>hnGw51TfA z=YQ~x$Qy+bbw8&>;H8NQUus;gRi2gSRih5r%jI8x`s9>4tBmiw`esYIiN>Dv(Sd4dOWyg}I z!kYM&+!>9~T6`1zF(X~*+!w;0?(UB1VLg_0scasTC3pRONqS_%rnqS_1s zfvV&C;0HHm4dbkP_oFIRKin69uWY9_#_4Xaknw^nGtvj?aT)^HKjjg&rbSn&WEok5?i^v&{_?x|Enhq}Aya<0|fqFOBFz zn;$cW`l4I-dQ8=*_$U_2VLPU|byynOPVDv0ir3uvp$K(qn5^I8|67!G%cdeCzaJ&l zm*JIR9c(A`!+B5Dfw~<$tWNaMETIl7-mIRmW?ZW2pkD{_SnDeBSBV<;!HboATcX9< zN98BC((6<43e9EO8|~aqU;jBrZg9LcRN*k(leNhob=v!_*O&(FAT~>>nr${1`ww`S zS5Elk1|489zI**i)6o3K?j60b8F@H-NGOr@**Wy-P*@Ukd6?I|C*iHgljwH7=j&}- z4Ih~B5R7zf#X@D?-k-#BMyh#X*Y7T^<)cPksJfwLfTG9MKX|7Xn;2*?bc(_kN2oC2 zUAMq_)O6M?rcnBO-j1ZM7jCP)1m{sWTqsga;c0gJ`}N_PK$IM7YaO!`C^2f3RrA-_ zDv#j}KFJf(+e2H;l(nv`Na+tob9(6Qp@(q!uVL-DSu`3gw0pMd?$x9!S(7;RgM z%5x{l!#6HxNB^cTaoGpKn2F=2Je*(XXROu)`|FTJuYWRI+?7xP`860M0nDaVz$hJK4Z7Irx~_UXCoyGdEN45W|6 z+j3&a!O|1lIc)d>kMrpKJ);mt`&9ZVw08ewSb{8<572+_B1EG znegs5n!_tYMof7c`>(amcxBn&4q?cmw*a~x>^UtD6ccJU|KM_QFDj(DvE^o*u*;k4 z>euFa>_m^;{IRrfcx(|5o1QvY=Vtpz?Z?3c&!Owwrg?db8!erz&iMABZH7H7)x7SV z8_&7oG_Ci+kxjp9RTr3d;=D`fq4`zQ$|ynM-Kv-Kg4L7J#eYhb1p6XFZi_s5F^ z#VyvM22zT7Efgzw`7F=4o8)O|$ZYeJn1 Bw@^UE&B|w?ns2w=U~hpgD#h#y}IC_ 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 literal 0 HcmV?d00001 diff --git a/docs/pictures/endActivity.PNG b/docs/pictures/endActivity.PNG deleted file mode 100644 index a7c3f763a093d0451570fc7427db49d694a89a9d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 33720 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

!;1g?RQCi@5E8y#JT2S9|22Nr1Fo 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%0A*1HlPDWkOe^~ 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 literal 0 HcmV?d00001 From 31af75f19de70af134074bf4d97e3d36d8eeac31 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Mon, 6 Apr 2020 22:51:48 +0800 Subject: [PATCH 266/415] Create abstract cleaner class --- src/main/java/jikan/Jikan.java | 14 +-- src/main/java/jikan/cleaner/Cleaner.java | 106 ++++++++++++++++++ .../jikan/{log => cleaner}/LogCleaner.java | 84 +++++--------- .../{storage => cleaner}/StorageCleaner.java | 87 +++++--------- src/main/java/jikan/command/CleanCommand.java | 22 ++-- src/main/java/jikan/parser/Parser.java | 14 +-- 6 files changed, 181 insertions(+), 146 deletions(-) create mode 100644 src/main/java/jikan/cleaner/Cleaner.java rename src/main/java/jikan/{log => cleaner}/LogCleaner.java (71%) rename src/main/java/jikan/{storage => cleaner}/StorageCleaner.java (72%) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index fcfb119cc..731708450 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -6,10 +6,10 @@ import jikan.command.GoalCommand; import jikan.exception.EmptyNameException; import jikan.exception.ExtraParametersException; -import jikan.log.LogCleaner; +import jikan.cleaner.LogCleaner; import jikan.parser.Parser; import jikan.storage.Storage; -import jikan.storage.StorageCleaner; +import jikan.cleaner.StorageCleaner; import jikan.ui.Ui; import java.io.File; @@ -40,7 +40,7 @@ public class Jikan { private static Parser parser = new Parser(); /** CLeaner to delete entries in data.csv when it gets too long */ - private static StorageCleaner cleaner; + private static StorageCleaner storageCleaner; private static LogCleaner logCleaner = new LogCleaner(); @@ -54,9 +54,9 @@ public class Jikan { public static void main(String[] args) { ui.printGreeting(); storage = new Storage(DATA_FILE_PATH); - cleaner = new StorageCleaner(storage); + storageCleaner = new StorageCleaner(storage); try { - cleaner.autoClean(); + storageCleaner.autoClean(); logCleaner.autoClean(); activityList = storage.createActivityList(); GoalCommand.createFile(TAG_FILE_PATH, tagFile); @@ -65,12 +65,12 @@ public static void main(String[] args) { } lastShownList.activities.addAll(activityList.activities); - parser.cleaner = cleaner; + parser.cleaner = storageCleaner; parser.logcleaner = logCleaner; while (true) { try { - Command command = parser.parseUserCommands(in, activityList, cleaner, tagFile); + Command command = parser.parseUserCommands(in, activityList, storageCleaner, tagFile); if (command == null) { continue; } diff --git a/src/main/java/jikan/cleaner/Cleaner.java b/src/main/java/jikan/cleaner/Cleaner.java new file mode 100644 index 000000000..0caa9cad0 --- /dev/null +++ b/src/main/java/jikan/cleaner/Cleaner.java @@ -0,0 +1,106 @@ +package jikan.cleaner; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.Scanner; + +public abstract class Cleaner { + protected String STATUS_FILE_PATH; + protected String DATA_FILE_PATH; + protected File status; + protected File recycledData; + public boolean toClean; + private static final int defaultNumberOfDataToClean = 5; + + /** + * Initialise a data file containing the deleted logs. + */ + protected void initialiseDataFile() { + try { + loadFile(recycledData); + } catch (IOException e) { + System.out.println("Error loading/creating recycled file"); + } + } + + /** + * Loads the status file and checks if it exists or not. + * @param file status file. + * @return true if the file exists and false otherwise. + * @throws IOException if there is an error with the creation/loading of the status file. + */ + protected boolean loadCleaner(File file) throws IOException { + if (!file.exists()) { + createFile(file); + return false; + } else { + return true; + } + } + + /** + * Loads the data file that contains deleted logs. + * @param file data file with the deleted logs. + * @throws IOException if there is an error with the creation/loading of the data file. + */ + protected void loadFile(File file) throws IOException { + if (!file.exists()) { + createFile(file); + } + } + + /** + * Creates a new file if the specified file cannot be found in the given path. + * @param file the file to be created if it does not exist. + * @throws IOException if there is an error with the creation of the file. + */ + protected void createFile(File file) throws IOException { + file.getParentFile().mkdirs(); + file.createNewFile(); + } + + protected int initialiseCleaner() { + try { + if (loadCleaner(status)) { + Scanner sc = new Scanner(status); + String status = sc.nextLine(); + int value = Integer.parseInt(status); + assert value == 0 || value == 1; + if (value == 1) { + this.toClean = true; + } else { + this.toClean = false; + } + String line = sc.nextLine(); + return Integer.parseInt(line); + } else { + FileWriter fw = new FileWriter(status); + fw.write("0" + "\n"); + fw.write("5" + "\n"); + fw.close(); + return defaultNumberOfDataToClean; + } + } catch (IOException e) { + System.out.println("Error loading/creating cleaning file."); + return -1; + } + } + + public void setStatus(boolean status, int number) throws IOException { + this.toClean = status; + File dataFile = new File(STATUS_FILE_PATH); + if (!dataFile.exists()) { + dataFile.createNewFile(); + } + BufferedWriter writer = new BufferedWriter(new FileWriter(dataFile)); + if (this.toClean) { + writer.write("1" + "\n"); + } else { + writer.write("0" + "\n"); + } + writer.write(Integer.toString(number) + "\n"); + writer.close(); + } +} diff --git a/src/main/java/jikan/log/LogCleaner.java b/src/main/java/jikan/cleaner/LogCleaner.java similarity index 71% rename from src/main/java/jikan/log/LogCleaner.java rename to src/main/java/jikan/cleaner/LogCleaner.java index 1f1d76317..3a0486f2d 100644 --- a/src/main/java/jikan/log/LogCleaner.java +++ b/src/main/java/jikan/cleaner/LogCleaner.java @@ -1,4 +1,4 @@ -package jikan.log; +package jikan.cleaner; import java.io.BufferedWriter; import java.io.File; @@ -13,41 +13,41 @@ * A log cleaner class that does automated cleaning * for log files under the user's request. */ -public class LogCleaner { - private static final String STATUS_FILE_PATH = "data/recycled/logStatus.txt"; - private static final String DATA_FILE_PATH = "data/recycled/logData.txt"; +public class LogCleaner extends Cleaner { + //private static final String STATUS_FILE_PATH = "data/recycled/logStatus.txt"; + //private static final String DATA_FILE_PATH = "data/recycled/logData.txt"; + //private File status; + //private File recycledData; + //public boolean toClean; + private static final String LOG_FILE_PATH = "data/LogRecord.txt"; - private File status; - private File recycledData; - public boolean toClean; - private int numberOfLogsToClean; + public int numberOfLogsToClean; /** * Constructor for the log cleaner. */ public LogCleaner() { - status = new File(STATUS_FILE_PATH); + super.STATUS_FILE_PATH = "data/recycled/logStatus.txt"; + super.status = new File(STATUS_FILE_PATH); + super.DATA_FILE_PATH = "data/recycled/logData.txt"; + super.recycledData = new File(DATA_FILE_PATH); + initialiseDataFile(); + int value = initialiseCleaner(); + if (value != -1) { + this.numberOfLogsToClean = value; + } + /*status = new File(STATUS_FILE_PATH); recycledData = new File(DATA_FILE_PATH); initialiseCleaner(); - initialiseDataFile(); + initialiseDataFile();*/ } - /** - * Initialise a data file containing the deleted logs. - */ - private void initialiseDataFile() { - try { - loadFile(recycledData); - } catch (IOException e) { - System.out.println("Error loading/creating recycled file"); - } - } /** * Activates/De-activates the auto cleanup of logs by checking the status file. */ - private void initialiseCleaner() { + /*private void initialiseCleaner() { try { if (loadCleaner(status)) { Scanner sc = new Scanner(status); @@ -70,50 +70,20 @@ private void initialiseCleaner() { } catch (IOException e) { System.out.println("Error loading/creating cleaning file."); } - } + }*/ + + + - /** - * Loads the status file and checks if it exists or not. - * @param file status file. - * @return true if the file exists and false otherwise. - * @throws IOException if there is an error with the creation/loading of the status file. - */ - private boolean loadCleaner(File file) throws IOException { - if (!file.exists()) { - createFile(file); - return false; - } else { - return true; - } - } - /** - * Loads the data file that contains deleted logs. - * @param file data file with the deleted logs. - * @throws IOException if there is an error with the creation/loading of the data file. - */ - private void loadFile(File file) throws IOException { - if (!file.exists()) { - createFile(file); - } - } - /** - * Creates a new file if the specified file cannot be found in the given path. - * @param file the file to be created if it does not exist. - * @throws IOException if there is an error with the creation of the file. - */ - private void createFile(File file) throws IOException { - file.getParentFile().mkdirs(); - file.createNewFile(); - } /** * Method to activate/de-activate the auto cleanup for logs. * @param status a boolean specifying whether the log cleaner should be activated or not. * @throws IOException if there is an error with reading/writing to the status file. */ - public void setStatus(boolean status) throws IOException { + /*public void setStatus(boolean status) throws IOException { this.toClean = status; File dataFile = new File(STATUS_FILE_PATH); if (!dataFile.exists()) { @@ -127,7 +97,7 @@ public void setStatus(boolean status) throws IOException { } writer.write(Integer.toString(this.numberOfLogsToClean) + "\n"); writer.close(); - } + }*/ /** * Method to set a value for the number of logs to clean. diff --git a/src/main/java/jikan/storage/StorageCleaner.java b/src/main/java/jikan/cleaner/StorageCleaner.java similarity index 72% rename from src/main/java/jikan/storage/StorageCleaner.java rename to src/main/java/jikan/cleaner/StorageCleaner.java index 0f1e454bc..550350d62 100644 --- a/src/main/java/jikan/storage/StorageCleaner.java +++ b/src/main/java/jikan/cleaner/StorageCleaner.java @@ -1,4 +1,6 @@ -package jikan.storage; +package jikan.cleaner; + +import jikan.storage.Storage; import java.io.BufferedWriter; import java.io.File; @@ -12,13 +14,15 @@ * A storage cleaner class that does automated cleaning * for data files under the user's request. */ -public class StorageCleaner { - private static final String STATUS_FILE_PATH = "data/recycled/status.txt"; - private static final String DATA_FILE_PATH = "data/recycled/data.csv"; - private File status; - private File recycledData; - public boolean toClean; - private int numberOfActivitiesToClean; +public class StorageCleaner extends Cleaner { + //private static final String STATUS_FILE_PATH = "data/recycled/status.txt"; + //private static final String DATA_FILE_PATH = "data/recycled/data.csv"; + //private File status; + //private File recycledData; + //public boolean toClean; + + + public int numberOfActivitiesToClean; public Storage storage; /** @@ -27,27 +31,26 @@ public class StorageCleaner { */ public StorageCleaner(Storage storage) { this.storage = storage; + super.STATUS_FILE_PATH = "data/recycled/status.txt"; + super.status = new File(STATUS_FILE_PATH); + super.DATA_FILE_PATH = "data/recycled/data.csv"; + super.recycledData = new File(DATA_FILE_PATH); + initialiseDataFile(); + int value = initialiseCleaner(); + if (value != -1) { + this.numberOfActivitiesToClean = value; + } + /*this.storage = storage; status = new File(STATUS_FILE_PATH); recycledData = new File(DATA_FILE_PATH); initialiseCleaner(); - initialiseDataFile(); - } - - /** - * Initialises a data file containing the deleted entries. - */ - private void initialiseDataFile() { - try { - loadFile(recycledData); - } catch (IOException e) { - System.out.println("Error loading/creating recycled file"); - } + initialiseDataFile();*/ } /** * Activates/De-activates the auto cleanup by checking the status file. */ - private void initialiseCleaner() { + /*private void initialiseCleaner() { try { if (loadCleaner(status)) { Scanner sc = new Scanner(status); @@ -70,50 +73,14 @@ private void initialiseCleaner() { } catch (IOException e) { System.out.println("Error loading/creating cleaning file."); } - } - - /** - * Loads the status file and checks if the file exists or not. - * @param file status file. - * @return true if the file exists and false otherwise. - * @throws IOException if there is an error with the creation/loading of the status file. - */ - private boolean loadCleaner(File file) throws IOException { - if (!file.exists()) { - createFile(file); - return false; - } else { - return true; - } - } - - /** - * Loads the data file that contains deleted entries. - * @param file data file with the deleted entries. - * @throws IOException if there is an error with the creation/loading of the data file. - */ - private void loadFile(File file) throws IOException { - if (!file.exists()) { - createFile(file); - } - } - - /** - * Creates a new file if the specified file cannot be found in the given path. - * @param file the file to be created if it does not exist. - * @throws IOException if there is an error with the creation of the file. - */ - private void createFile(File file) throws IOException { - file.getParentFile().mkdirs(); - file.createNewFile(); - } + }*/ /** * Method to activate/de-activate the auto cleanup. * @param status a boolean specifying whether the cleaner should be activated or not. * @throws IOException if there is an error with reading/writing to the status file. */ - public void setStatus(boolean status) throws IOException { + /*public void setStatus(boolean status) throws IOException { this.toClean = status; File dataFile = new File(STATUS_FILE_PATH); if (!dataFile.exists()) { @@ -127,7 +94,7 @@ public void setStatus(boolean status) throws IOException { } writer.write(Integer.toString(this.numberOfActivitiesToClean) + "\n"); writer.close(); - } + }*/ /** * Method to set a value for the number of activities to clean. diff --git a/src/main/java/jikan/command/CleanCommand.java b/src/main/java/jikan/command/CleanCommand.java index 60dd8b473..277e401f0 100644 --- a/src/main/java/jikan/command/CleanCommand.java +++ b/src/main/java/jikan/command/CleanCommand.java @@ -3,8 +3,8 @@ import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.InvalidCleanCommandException; -import jikan.log.LogCleaner; -import jikan.storage.StorageCleaner; +import jikan.cleaner.LogCleaner; +import jikan.cleaner.StorageCleaner; import jikan.ui.Ui; import java.io.IOException; @@ -14,7 +14,7 @@ */ public class CleanCommand extends Command { - StorageCleaner cleaner; + StorageCleaner storageCleaner; LogCleaner logCleaner; /** @@ -22,7 +22,7 @@ public class CleanCommand extends Command { */ public CleanCommand(String parameters, StorageCleaner cleaner, LogCleaner logCleaner) { super(parameters); - this.cleaner = cleaner; + this.storageCleaner = cleaner; this.logCleaner = logCleaner; } @@ -72,14 +72,14 @@ public void executeCommand(ActivityList activityList) { private void handleOnFunction() throws IOException { String line = this.parameters; if (line.contains("log")) { - logCleaner.setStatus(true); + logCleaner.setStatus(true, logCleaner.numberOfLogsToClean); assert logCleaner.toClean; line = "Auto cleaning enabled for logs"; Ui.printDivider(line); Log.makeInfoLog("User has turned on automated cleaning for logs"); } else { - cleaner.setStatus(true); - assert cleaner.toClean; + storageCleaner.setStatus(true, storageCleaner.numberOfActivitiesToClean); + assert storageCleaner.toClean; line = "Auto cleaning enabled"; Ui.printDivider(line); Log.makeInfoLog("User has turned on automated cleaning"); @@ -89,14 +89,14 @@ private void handleOnFunction() throws IOException { private void handleOffFunction() throws IOException { String line = this.parameters; if (line.contains("log")) { - logCleaner.setStatus(false); + logCleaner.setStatus(false, logCleaner.numberOfLogsToClean); assert !logCleaner.toClean; line = "Auto cleaning disabled for logs"; Ui.printDivider(line); Log.makeInfoLog("User has turned off automated cleaning for logs"); } else { - cleaner.setStatus(false); - assert !cleaner.toClean; + storageCleaner.setStatus(false, storageCleaner.numberOfActivitiesToClean); + assert !storageCleaner.toClean; line = "Auto cleaning disabled"; Ui.printDivider(line); Log.makeInfoLog("User has turned off automated cleaning"); @@ -119,7 +119,7 @@ private void handleSetFunction() throws IOException, NumberFormatException { } else { try { int value = getNumberFromCommand(line); - cleaner.setNumberOfActivitiesToClean(value); + storageCleaner.setNumberOfActivitiesToClean(value); line = "Number of activities to clean is set to " + value; Ui.printDivider(line); } catch (NumberFormatException | IndexOutOfBoundsException e) { diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 7f9e00ca8..961ae8e38 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,11 +1,10 @@ package jikan.parser; import jikan.exception.ExtraParametersException; -import jikan.exception.InvalidTimeFrameException; import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; -import jikan.storage.StorageCleaner; +import jikan.cleaner.StorageCleaner; import jikan.ui.Ui; import jikan.command.AbortCommand; @@ -26,18 +25,11 @@ import java.io.File; -import jikan.exception.EmptyNameException; -import jikan.activity.ActivityList; -import jikan.log.LogCleaner; -import jikan.storage.StorageCleaner; -import jikan.ui.Ui; -import jikan.log.Log; -import java.text.ParseException; +import jikan.cleaner.LogCleaner; + import java.time.Duration; -import java.io.File; import java.time.LocalDateTime; -import java.time.format.DateTimeParseException; import java.util.HashSet; import java.util.Scanner; import java.util.Set; From 95853fe36f743e58e376eeeada2bdd16fdb52410 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 7 Apr 2020 00:03:20 +0800 Subject: [PATCH 267/415] Modify both cleaners --- src/main/java/jikan/Jikan.java | 4 +- src/main/java/jikan/cleaner/Cleaner.java | 15 +- src/main/java/jikan/cleaner/LogCleaner.java | 118 +++++---------- .../java/jikan/cleaner/StorageCleaner.java | 136 +++++++----------- src/main/java/jikan/command/CleanCommand.java | 20 ++- 5 files changed, 117 insertions(+), 176 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 731708450..11660251d 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -56,8 +56,8 @@ public static void main(String[] args) { storage = new Storage(DATA_FILE_PATH); storageCleaner = new StorageCleaner(storage); try { - storageCleaner.autoClean(); - logCleaner.autoClean(); + storageCleaner.storageAutoClean(); + logCleaner.logAutoClean(); activityList = storage.createActivityList(); GoalCommand.createFile(TAG_FILE_PATH, tagFile); } catch (IOException e) { diff --git a/src/main/java/jikan/cleaner/Cleaner.java b/src/main/java/jikan/cleaner/Cleaner.java index 0caa9cad0..9dfb42411 100644 --- a/src/main/java/jikan/cleaner/Cleaner.java +++ b/src/main/java/jikan/cleaner/Cleaner.java @@ -7,8 +7,8 @@ import java.util.Scanner; public abstract class Cleaner { - protected String STATUS_FILE_PATH; - protected String DATA_FILE_PATH; + protected static String STATUS_FILE_PATH; + protected static String DATA_FILE_PATH; protected File status; protected File recycledData; public boolean toClean; @@ -61,6 +61,10 @@ protected void createFile(File file) throws IOException { file.createNewFile(); } + /** + * Activates/De-activates the auto clean up by checking the status file. + * @return the number of lines of data to automatically clean. + */ protected int initialiseCleaner() { try { if (loadCleaner(status)) { @@ -88,6 +92,12 @@ protected int initialiseCleaner() { } } + /** + * Method to activate/de-activate the auto cleanup. + * @param status a boolean specifying whether the cleaner should be activated or not. + * @param number an integer specifying the number of lines of data to automatically clean. + * @throws IOException if there is an error with reading/writing to the status file. + */ public void setStatus(boolean status, int number) throws IOException { this.toClean = status; File dataFile = new File(STATUS_FILE_PATH); @@ -103,4 +113,5 @@ public void setStatus(boolean status, int number) throws IOException { writer.write(Integer.toString(number) + "\n"); writer.close(); } + } diff --git a/src/main/java/jikan/cleaner/LogCleaner.java b/src/main/java/jikan/cleaner/LogCleaner.java index 3a0486f2d..78f12fd2f 100644 --- a/src/main/java/jikan/cleaner/LogCleaner.java +++ b/src/main/java/jikan/cleaner/LogCleaner.java @@ -2,6 +2,7 @@ import java.io.BufferedWriter; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; @@ -14,11 +15,6 @@ * for log files under the user's request. */ public class LogCleaner extends Cleaner { - //private static final String STATUS_FILE_PATH = "data/recycled/logStatus.txt"; - //private static final String DATA_FILE_PATH = "data/recycled/logData.txt"; - //private File status; - //private File recycledData; - //public boolean toClean; private static final String LOG_FILE_PATH = "data/LogRecord.txt"; public int numberOfLogsToClean; @@ -37,68 +33,8 @@ public LogCleaner() { if (value != -1) { this.numberOfLogsToClean = value; } - /*status = new File(STATUS_FILE_PATH); - recycledData = new File(DATA_FILE_PATH); - initialiseCleaner(); - initialiseDataFile();*/ } - - /** - * Activates/De-activates the auto cleanup of logs by checking the status file. - */ - /*private void initialiseCleaner() { - try { - if (loadCleaner(status)) { - Scanner sc = new Scanner(status); - String status = sc.nextLine(); - int value = Integer.parseInt(status); - assert value == 0 | value == 1; - if (value == 1) { - this.toClean = true; - } else { - this.toClean = false; - } - String line = sc.nextLine(); - this.numberOfLogsToClean = Integer.parseInt(line); - } else { - FileWriter fw = new FileWriter(status); - fw.write("0" + "\n"); - fw.write("10" + "\n"); - fw.close(); - } - } catch (IOException e) { - System.out.println("Error loading/creating cleaning file."); - } - }*/ - - - - - - - - /** - * Method to activate/de-activate the auto cleanup for logs. - * @param status a boolean specifying whether the log cleaner should be activated or not. - * @throws IOException if there is an error with reading/writing to the status file. - */ - /*public void setStatus(boolean status) throws IOException { - this.toClean = status; - File dataFile = new File(STATUS_FILE_PATH); - if (!dataFile.exists()) { - dataFile.createNewFile(); - } - BufferedWriter writer = new BufferedWriter(new FileWriter(dataFile)); - if (this.toClean) { - writer.write("1" + "\n"); - } else { - writer.write("0" + "\n"); - } - writer.write(Integer.toString(this.numberOfLogsToClean) + "\n"); - writer.close(); - }*/ - /** * Method to set a value for the number of logs to clean. * @param value an integer representing the number to clean. @@ -126,29 +62,11 @@ public void setNumberOfLogsToClean(int value) throws IOException { * @throws IOException if there is an error with reading/writing to the live log file and * recycled log file. */ - public void autoClean() throws IOException { + public void logAutoClean() throws IOException { List logsForRecycling = new ArrayList<>(); List logsLeftInData = new ArrayList<>(); if (this.toClean) { - File liveData = new File(LOG_FILE_PATH); - Scanner recycledDataScanner = new Scanner(recycledData); - Scanner liveDataScanner = new Scanner(liveData); - while (recycledDataScanner.hasNext()) { - String line = recycledDataScanner.nextLine(); - logsForRecycling.add(line); - } - while (numberOfLogsToClean != 0) { - if (!liveDataScanner.hasNext()) { - break; - } - String line = liveDataScanner.nextLine(); - logsForRecycling.add(line); - numberOfLogsToClean -= 1; - } - while (liveDataScanner.hasNext()) { - String line = liveDataScanner.nextLine(); - logsLeftInData.add(line); - } + File liveData = recycleLog(logsForRecycling, logsLeftInData); BufferedWriter recycledDataWriter = new BufferedWriter(new FileWriter(recycledData)); for (String line : logsForRecycling) { @@ -162,4 +80,34 @@ public void autoClean() throws IOException { liveDataWriter.close(); } } + + /** + * Method to clean up log file and move them to the recycled folder. + * @param logsForRecycling an array list consisting of logs to be written to recycled folder. + * @param logsLeftInData an array list consisting of the logs left after clean up. + * @return a log file that holds all the logging at run time. + * @throws FileNotFoundException if file could not be found at the filepath. + */ + private File recycleLog(List logsForRecycling, List logsLeftInData) throws FileNotFoundException { + File liveData = new File(LOG_FILE_PATH); + Scanner recycledDataScanner = new Scanner(recycledData); + Scanner liveDataScanner = new Scanner(liveData); + while (recycledDataScanner.hasNext()) { + String line = recycledDataScanner.nextLine(); + logsForRecycling.add(line); + } + while (numberOfLogsToClean != 0) { + if (!liveDataScanner.hasNext()) { + break; + } + String line = liveDataScanner.nextLine(); + logsForRecycling.add(line); + numberOfLogsToClean -= 1; + } + while (liveDataScanner.hasNext()) { + String line = liveDataScanner.nextLine(); + logsLeftInData.add(line); + } + return liveData; + } } diff --git a/src/main/java/jikan/cleaner/StorageCleaner.java b/src/main/java/jikan/cleaner/StorageCleaner.java index 550350d62..1f950e018 100644 --- a/src/main/java/jikan/cleaner/StorageCleaner.java +++ b/src/main/java/jikan/cleaner/StorageCleaner.java @@ -4,8 +4,10 @@ import java.io.BufferedWriter; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; +import java.time.Duration; import java.util.ArrayList; import java.util.List; import java.util.Scanner; @@ -15,12 +17,6 @@ * for data files under the user's request. */ public class StorageCleaner extends Cleaner { - //private static final String STATUS_FILE_PATH = "data/recycled/status.txt"; - //private static final String DATA_FILE_PATH = "data/recycled/data.csv"; - //private File status; - //private File recycledData; - //public boolean toClean; - public int numberOfActivitiesToClean; public Storage storage; @@ -40,62 +36,8 @@ public StorageCleaner(Storage storage) { if (value != -1) { this.numberOfActivitiesToClean = value; } - /*this.storage = storage; - status = new File(STATUS_FILE_PATH); - recycledData = new File(DATA_FILE_PATH); - initialiseCleaner(); - initialiseDataFile();*/ } - /** - * Activates/De-activates the auto cleanup by checking the status file. - */ - /*private void initialiseCleaner() { - try { - if (loadCleaner(status)) { - Scanner sc = new Scanner(status); - String status = sc.nextLine(); - int value = Integer.parseInt(status); - assert value == 0 || value == 1; - if (value == 1) { - this.toClean = true; - } else { - this.toClean = false; - } - String line = sc.nextLine(); - this.numberOfActivitiesToClean = Integer.parseInt(line); - } else { - FileWriter fw = new FileWriter(status); - fw.write("0" + "\n"); - fw.write("3" + "\n"); - fw.close(); - } - } catch (IOException e) { - System.out.println("Error loading/creating cleaning file."); - } - }*/ - - /** - * Method to activate/de-activate the auto cleanup. - * @param status a boolean specifying whether the cleaner should be activated or not. - * @throws IOException if there is an error with reading/writing to the status file. - */ - /*public void setStatus(boolean status) throws IOException { - this.toClean = status; - File dataFile = new File(STATUS_FILE_PATH); - if (!dataFile.exists()) { - dataFile.createNewFile(); - } - BufferedWriter writer = new BufferedWriter(new FileWriter(dataFile)); - if (this.toClean) { - writer.write("1" + "\n"); - } else { - writer.write("0" + "\n"); - } - writer.write(Integer.toString(this.numberOfActivitiesToClean) + "\n"); - writer.close(); - }*/ - /** * Method to set a value for the number of activities to clean. * @param value an integer representing the number to clean. @@ -123,30 +65,11 @@ public void setNumberOfActivitiesToClean(int value) throws IOException { * @throws IOException if there is an error with reading/writing to the live data file and * recycled data file. */ - public void autoClean() throws IOException { + public void storageAutoClean() throws IOException { List activitiesForRecycling = new ArrayList<>(); List activitiesLeftInData = new ArrayList<>(); if (this.toClean) { - String filePath = storage.dataFilePath; - File liveData = new File(filePath); - Scanner recycledDataScanner = new Scanner(recycledData); - Scanner liveDataScanner = new Scanner(liveData); - while (recycledDataScanner.hasNext()) { - String line = recycledDataScanner.nextLine(); - activitiesForRecycling.add(line); - } - while (numberOfActivitiesToClean != 0) { - if (!liveDataScanner.hasNext()) { - break; - } - String line = liveDataScanner.nextLine(); - activitiesForRecycling.add(line); - numberOfActivitiesToClean -= 1; - } - while (liveDataScanner.hasNext()) { - String line = liveDataScanner.nextLine(); - activitiesLeftInData.add(line); - } + File liveData = recycleData(activitiesForRecycling, activitiesLeftInData); BufferedWriter recycledDataWriter = new BufferedWriter(new FileWriter(recycledData)); for (String line : activitiesForRecycling) { @@ -160,4 +83,55 @@ public void autoClean() throws IOException { liveDataWriter.close(); } } + + /** + * Method to clean up data file and move them to the recycled folder. + * @param activitiesForRecycling an array list consisting of data to be written to recycled folder. + * @param activitiesLeftInData an array list consisting of the data left after clean up. + * @return a storage file that holds the activity list at run time. + * @throws FileNotFoundException if file could not be found at the filepath. + */ + private File recycleData(List activitiesForRecycling, List activitiesLeftInData) + throws FileNotFoundException { + String filePath = storage.dataFilePath; + File liveData = new File(filePath); + Scanner recycledDataScanner = new Scanner(recycledData); + Scanner liveDataScanner = new Scanner(liveData); + while (recycledDataScanner.hasNext()) { + String line = recycledDataScanner.nextLine(); + activitiesForRecycling.add(line); + } + parseLiveData(activitiesForRecycling, activitiesLeftInData, liveDataScanner); + return liveData; + } + + /** + * Method to check the activities in storage line by line and see if they should be cleaned or not. + * @param activitiesForRecycling an array list consisting of data to be written to recycled folder. + * @param activitiesLeftInData an array list consisting of the data left after clean up. + * @param liveDataScanner used to scan the activities in storage line by line. + */ + private void parseLiveData(List activitiesForRecycling, List activitiesLeftInData, + Scanner liveDataScanner) { + while (numberOfActivitiesToClean != 0) { + if (!liveDataScanner.hasNext()) { + break; + } + String line = liveDataScanner.nextLine(); + String[] tokenizedLine = line.split(","); + Duration duration = Duration.parse(tokenizedLine[3]); + Duration allocatedTime = Duration.parse(tokenizedLine[4]); + int result = duration.compareTo(allocatedTime); + if (result >= 0 && allocatedTime != Duration.parse("PT0S")) { + activitiesForRecycling.add(line); + numberOfActivitiesToClean -= 1; + } else { + activitiesLeftInData.add(line); + } + } + while (liveDataScanner.hasNext()) { + String line = liveDataScanner.nextLine(); + activitiesLeftInData.add(line); + } + } } diff --git a/src/main/java/jikan/command/CleanCommand.java b/src/main/java/jikan/command/CleanCommand.java index 277e401f0..f8bc9320d 100644 --- a/src/main/java/jikan/command/CleanCommand.java +++ b/src/main/java/jikan/command/CleanCommand.java @@ -108,9 +108,13 @@ private void handleSetFunction() throws IOException, NumberFormatException { if (line.contains("log")) { try { int value = getNumberFromCommand(line); - logCleaner.setNumberOfLogsToClean(value); - line = "Number of activities to clean is set to " + value; - Ui.printDivider(line); + if (value > 0) { + logCleaner.setNumberOfLogsToClean(value); + line = "Number of activities to clean is set to " + value; + Ui.printDivider(line); + } else { + Ui.printDivider("Please provide a positive number"); + } } catch (NumberFormatException | IndexOutOfBoundsException e) { throw new NumberFormatException(); } catch (IOException e) { @@ -119,9 +123,13 @@ private void handleSetFunction() throws IOException, NumberFormatException { } else { try { int value = getNumberFromCommand(line); - storageCleaner.setNumberOfActivitiesToClean(value); - line = "Number of activities to clean is set to " + value; - Ui.printDivider(line); + if (value > 0) { + storageCleaner.setNumberOfActivitiesToClean(value); + line = "Number of activities to clean is set to " + value; + Ui.printDivider(line); + } else { + Ui.printDivider("Please provide a positive number"); + } } catch (NumberFormatException | IndexOutOfBoundsException e) { throw new NumberFormatException(); } catch (IOException e) { From 596ad5b824278c397791807ab3c66fe546fea97d Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 7 Apr 2020 01:16:20 +0800 Subject: [PATCH 268/415] Add assertions --- src/main/java/jikan/storage/Storage.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/jikan/storage/Storage.java b/src/main/java/jikan/storage/Storage.java index 60637b571..a60c56e7d 100644 --- a/src/main/java/jikan/storage/Storage.java +++ b/src/main/java/jikan/storage/Storage.java @@ -83,6 +83,7 @@ public ActivityList createActivityList() { } catch (IOException e) { System.out.println("Error loading/creating data file."); } + assert activityList instanceof ActivityList : "Method should return an ActivityList"; return activityList; } From e6b34eeb09390202927cb25f1d601f39434264e4 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 7 Apr 2020 01:23:51 +0800 Subject: [PATCH 269/415] Add more assertions --- src/main/java/jikan/activity/ActivityList.java | 2 ++ src/main/java/jikan/storage/Storage.java | 2 ++ src/main/java/jikan/storage/StorageHandler.java | 10 ++++++++++ 3 files changed, 14 insertions(+) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index ddb3428f2..9212ae4d2 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -39,6 +39,7 @@ public ActivityList() { * @param storage the storage object to use. */ public ActivityList(Storage storage) { + assert storage != null : "Input Storage must not be a null pointer"; this.activities = new ArrayList<>(); this.storage = storage; this.storageHandler = new StorageHandler(storage); @@ -50,6 +51,7 @@ public ActivityList(Storage storage) { * @param dataFile the datafile to be read from. */ public ActivityList(Storage storage, File dataFile) { + assert storage != null : "Input Storage must not be a null pointer"; this.activities = new ArrayList<>(); this.storage = storage; this.storageHandler = new StorageHandler(storage); diff --git a/src/main/java/jikan/storage/Storage.java b/src/main/java/jikan/storage/Storage.java index a60c56e7d..b399beb7e 100644 --- a/src/main/java/jikan/storage/Storage.java +++ b/src/main/java/jikan/storage/Storage.java @@ -27,8 +27,10 @@ public class Storage { * @param dataFilePath The data file's file path. */ public Storage(String dataFilePath) { + assert dataFilePath != null : "dataFilePath must not be null"; this.dataFilePath = dataFilePath; dataFile = new File(dataFilePath); + assert dataFile instanceof File; } /** diff --git a/src/main/java/jikan/storage/StorageHandler.java b/src/main/java/jikan/storage/StorageHandler.java index 8268bc55f..5f1d0aaa7 100644 --- a/src/main/java/jikan/storage/StorageHandler.java +++ b/src/main/java/jikan/storage/StorageHandler.java @@ -26,6 +26,7 @@ public class StorageHandler { * @param storage The data file's file path. */ public StorageHandler(Storage storage) { + assert storage != null : "Input Storage must not be a null pointer"; this.storage = storage; } @@ -37,6 +38,8 @@ public StorageHandler(Storage storage) { * @throws IOException If an error occurs while writing the new list to file. */ public void removeLine(int lineNumber, Storage storage) throws IOException { + assert storage != null : "Input Storage must not be a null pointer"; + assert lineNumber >= 0 : "lineNumber cannot be negative"; // Read file into list of strings, where each string is a line in the file List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(storage.dataFilePath), StandardCharsets.UTF_8)); @@ -67,6 +70,7 @@ public void removeLine(int lineNumber, Storage storage) throws IOException { * @throws IOException If an error occurs while writing the new list to file. */ public void updateField(ArrayList activities, Storage storage) throws IOException { + assert storage != null : "Input Storage must not be a null pointer"; List fileContent = new ArrayList<>(); for (Activity a : activities) { fileContent.add(a.toData()); @@ -82,6 +86,7 @@ public void updateField(ArrayList activities, Storage storage) throws * @throws IOException If an error occurs while writing the new list to file. */ public void saveNewList(List newList, File dataFile) throws IOException { + assert dataFile != null; FileOutputStream fileOutputStream = new FileOutputStream(dataFile); PrintWriter printWriter = new PrintWriter(fileOutputStream); @@ -101,6 +106,7 @@ public void saveNewList(List newList, File dataFile) throws IOException * @return Index of the removed line. */ private static int removeLineFromList(int lineNumber, List list, int removedIndex) { + assert lineNumber >= 0 : "lineNumber cannot be negative"; // Iterate through the lines for (int i = 0; i < list.size(); i++) { // If the current line matches the taskId @@ -124,6 +130,7 @@ private static int removeLineFromList(int lineNumber, List list, int rem */ private static void updateIndexes(List fileContent, int removedIndex, String dataFilePath) throws IOException { + assert dataFilePath != null : "dataFilePath cannot be null."; // Update indexes of subsequent tasks (e.g. if you remove task 2, task 3 becomes task 2) for (int i = removedIndex; i < fileContent.size(); i++) { // Get current comma separated string @@ -144,6 +151,7 @@ private static void updateIndexes(List fileContent, int removedIndex, St * @return Original string with its index decremented by 1. */ private static String decrementIndex(String currString, int i) { + assert i >= 0 : "i cannot be negative."; // Split into different cells List cells = Arrays.asList(currString.split(",")); @@ -165,6 +173,7 @@ private static String decrementIndex(String currString, int i) { * @throws IOException If an error occurs while writing to file. */ public static void replaceLine(int lineNumber, String newString, String dataFilePath) throws IOException { + assert dataFilePath != null : "dataFilePath cannot be null."; // Read file into list of strings, where each string is a line in the file List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(dataFilePath), StandardCharsets.UTF_8)); @@ -183,6 +192,7 @@ public static void replaceLine(int lineNumber, String newString, String dataFile * @param list List of strings. */ private static void replaceLineInList(int lineNumber, String newString, List list) { + assert lineNumber >= 0 : "lineNumber cannot be negative"; // Iterate through the lines for (int i = 0; i < list.size(); i++) { // If the current line matches the taskId From 6c51502c4aa79794954eac5425ee1ed959ca95ca Mon Sep 17 00:00:00 2001 From: rdimaio Date: Tue, 7 Apr 2020 02:19:19 +0800 Subject: [PATCH 270/415] Add PPP --- docs/team/rdimaio.md | 139 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 docs/team/rdimaio.md diff --git a/docs/team/rdimaio.md b/docs/team/rdimaio.md new file mode 100644 index 000000000..cb2d56f49 --- /dev/null +++ b/docs/team/rdimaio.md @@ -0,0 +1,139 @@ +# Project Portfolio Page (PPP) +## Project overview +**Jikan** is a CLI time-tracker built in Java that +aims to help manage tasks and projects. +Users can set tags and goals for their entries, +ultimately being able to keep track of what's left to do +and maintain an overview of how time was spent. + +## Summary of contributions +### Code contributed +[Link to tP Code Dashboard](https://nus-cs2113-ay1920s2.github.io/tp-dashboard/#=undefined&search=rdimaio) + +### Enhancements implemented +* Storage + * Storage handles saving, creating and accessing files. + This is a necessary feature, given the nature of Jikan as a timetracker + that needs to retain information across multiple sessions. +* StorageHandler + * Higher-level interface to Storage objects; + StorageHandler provides functions to retrieve and manipulate data + for the rest of the application. +* List + * The `list` command allows the user to list all the activities for a specified + date or range of dates. In many cases, the user does not want to specify + the exact dates; that is why the user can simply ask to `list day`, `list week`, + `list month 05` etc. to list entries belonging in the specified time frame. + +### Contributions to documentation +* Provided information on how to use the `list` command, including +all the possible parameters (`day`, `week`, `month`) + +### Contributions to the DG +* Provided information on the `Storage` object, +including how to use it for multiple concurring data files +* Provided information on the `StorageHandler` object, +specifically which functions can be used to write/edit/remove data +* Provided information on the possibilities of the `list` command + +### Contributions to team-based tasks +* Generating tables of content automatically for documentation +* Made extensive use of the issue tracker + * Labelled each PR and issue with severity and type + * Linked PRs to close their respective issues automatically + +### Review contributions +* Provided comments on possible ways to solve issues, +e.g. [#162](https://github.com/AY1920S2-CS2113-T15-1/tp/issues/162) + +### Contributions beyond the project team + +* Community + * Reported bugs: + * ["Submit post-lecture quiz" missing from Week 12 Admin info section](https://github.com/nus-cs2113-AY1920S2/forum/issues/96) + * [Arrow pointing the wrong way in the new UML video?](https://github.com/nus-cs2113-AY1920S2/forum/issues/75) + * Helped other students: + * [Problem when importing contacts project to Intellij](https://github.com/nus-cs2113-AY1920S2/forum/issues/23#issuecomment-581352650) + * [Markdown syntax](https://github.com/nus-cs2113-AY1920S2/forum/issues/88#issuecomment-603329337) + +## Contributions to the User Guide (extracts) + +### Listing activities: `list` +**Usage:** Displays a list of the completed activities. + +**Format:** `list TIME_PERIOD` +* If no `TIME_PERIOD` is given, all activities will be listed. +* `TIME_PERIOD` can be `day` or `week` +* To list activities in a specific month of the current year, use `list month MONTH_NAME` where `MONTH_NAME` must be spelled out in full (i.e. January and not Jan). +* Otherwise, `TIME_PERIOD` should be of the format [dd/MM/yyyy] or [yyyy-MM-dd] +* `TIME_PERIOD` can either be a specific date or over a range. + +**Example:** +`list` List all activities. +`list month april` Lists all activities in April. +`list week` or `list weekly` List all activities in the current week. +`list day` or `list daily` List all activities in the current day. +`list 01/01/2020` or `list 2020-01-01` List all activities on 1 Jan 2020. +`list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. + + +### Command Guide + +* List all activities: `list` + * List today's activities: `list day` or `list daily` + * List this week's activities: `list week` or `list weekly` + * List a specific week's activities by day: `list week DATE` or `list weekly DATE`, + where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List this month's activities: `list month` or `list monthly` + * List a specific month's activities by day: `list month DATE` or `list monthly DATE`, + where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List a specific day's activities: `list DATE`, where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List activities within a time frame: `list DATE1 DATE2`, where both `DATE1` and `DATE2` are + in either `yyyy-MM-dd` or `dd/MM/yyyy` format + +## Contributions to the Developer Guide (extracts) +### 3.2 Storage feature +The Storage class represents the back-end of Jikan, handling the creation, saving and loading of data. +Jikan uses a `.csv` file to store its data, formatted in the following way: + +`entry-name, start-time, end-time, duration, tags` + +All tags are saved in the same cell, separated by a white space; this design decision was taken to make sure that each entry occupies the same number of cells regardless of each entry’s number of tags. The tags are then separately parsed when the data is loaded. + +Each Storage objects contains the path to the data file (`Storage.dataFilePath`), the File object representing the data file (`Storage.dataFile`), and an activityList populated with the data from the data file (`Storage.activityList`). Storage optionally supports multiple data files at the same time, allowing implementation of features like multiple sessions and multiple user profiles. + +Storage provides the following functions: +- Constructing a Storage object via `Storage(String dataFilePath)`, which takes in the path to the desired data file (or the path where the user wants to create the data file) as a String object. +- Creating a data file via `createDataFile`. +- Writing to a data file via `writeToFile`. This function takes a single string as parameter and writes it to the data file. It is recommended to only pass single-line strings to keep the file nicely formatted. +Loading a pre-existing data file via `loadFile`. If a data file already exists for the provided data file path, the function will return `true`; if the specified data file did not previously exist, this function will call the `createDataFile` method and returns `false`. The return value is useful so that the application knows whether or not this is the first session with a specific data file or if data already exists. +- Creating an ActivityList via `createActivityList`. This function calls `loadFile()` to check whether the file already existed or not; if the data file previously existed, it will construct an ActivityList object by passing the data from the data file to it, and return this populated ActivityList object; if the data file did not previously exist, it will return an empty activityList object. + +### 3.3 Storage handler +The StorageHandler class functions as a support to the main Storage class, allowing the Jikan application to manipulate the stored data file. Its main provided functions are: +- Removing an entry from the data file via `removeLine`. This function takes in the number of the line to remove. +- Replacing an entry in the data file via `replaceLine`. This function takes in the number of the line to replace, along with the String object that needs to be written to the data file in place of the replaced line. + +### 3.6 List feature +This feature is used to list activities within a range specified by the user. +If no parameter is passed to the `list` command, then all the stored activities will be displayed. +By passing a single date, the command returns all activities within that date. +By passing two dates, the command returns all activities that took place within the two dates. +(for an activity to be included in the range, both its start and end time must be within the specified time range). +The user can also provide a verbal command, such as `day`, `week`, or `month`, which +will return all the activities for that day, week or month respectively. +Additionally, the user can specify a specific week of month by including a date +(e.g. `list month 2020-03-01` returns all the activities in March 2020.) + +#### 3.6.1 Current implementation +* List all activities: `list` + * List today's activities: `list day` or `list daily` + * List this week's activities: `list week` or `list weekly` + * List a specific week's activities by day: `list week DATE` or `list weekly DATE`, + where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List this month's activities: `list month` or `list monthly` + * List a specific month's activities by day: `list month DATE` or `list monthly DATE`, + where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List a specific day's activities: `list DATE`, where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List activities within a time frame: `list DATE1 DATE2`, where both `DATE1` and `DATE2` are + in either `yyyy-MM-dd` or `dd/MM/yyyy` format From f353faeddf5c34dfdce396c0cefecab3e7e563f8 Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Tue, 7 Apr 2020 02:22:33 +0800 Subject: [PATCH 271/415] Add links to members' portfolios --- docs/AboutUs.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 444661d07..4b1337965 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,9 +2,9 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Ng Siu Hian | [Github](https://github.com/siuhian) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ananda Lye | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Beatrice Chan | [Github](https://github.com/btricec) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Nigelle Leo | [Github](https://github.com/nigellenl) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Riccardo Di Maio | [Github](https://github.com/rdimaio) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ng Siu Hian | [Github](https://github.com/siuhian) | [Portfolio](docs/team/siuhian.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ananda Lye | [Github](https://github.com/ananda-lye) | [Portfolio](docs/team/ananda-lye.md) +![](https://via.placeholder.com/100.png?text=Photo) | Beatrice Chan | [Github](https://github.com/btricec) | [Portfolio](docs/team/btricec.md) +![](https://via.placeholder.com/100.png?text=Photo) | Nigelle Leo | [Github](https://github.com/nigellenl) | [Portfolio](docs/team/nigellenl.md) +![](https://via.placeholder.com/100.png?text=Photo) | Riccardo Di Maio | [Github](https://github.com/rdimaio) | [Portfolio](docs/team/rdimaio.md) From de57b4583902b8ce5a7d0d99a66471857f40da03 Mon Sep 17 00:00:00 2001 From: btricec Date: Tue, 7 Apr 2020 14:40:15 +0800 Subject: [PATCH 272/415] Fix graph bug closes #206 --- src/main/java/jikan/command/EndCommand.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/jikan/command/EndCommand.java b/src/main/java/jikan/command/EndCommand.java index fa7f432d1..77db96c7f 100644 --- a/src/main/java/jikan/command/EndCommand.java +++ b/src/main/java/jikan/command/EndCommand.java @@ -11,6 +11,8 @@ import java.util.Scanner; +import static jikan.Jikan.lastShownList; + /** * Represents a command to end an activity. */ @@ -34,6 +36,9 @@ public void executeCommand(ActivityList activityList) { throw new NoSuchActivityException(); } else { activityList.saveActivity(); + // reset lastShownList to include new activity + lastShownList.activities.clear(); + lastShownList.activities.addAll(activityList.activities); } } catch (NoSuchActivityException e) { Log.makeInfoLog("End command failed as no activity was ongoing"); From 39b85f60b05d21f16f1fa16344e7b2e145c8a96c Mon Sep 17 00:00:00 2001 From: btricec Date: Tue, 7 Apr 2020 15:36:27 +0800 Subject: [PATCH 273/415] Add PPP --- docs/team/btricec.md | 122 +++++++++++++++++++++++++++++++++++++++++++ docs/team/rdimaio.md | 2 +- 2 files changed, 123 insertions(+), 1 deletion(-) create mode 100644 docs/team/btricec.md diff --git a/docs/team/btricec.md b/docs/team/btricec.md new file mode 100644 index 000000000..3757d6043 --- /dev/null +++ b/docs/team/btricec.md @@ -0,0 +1,122 @@ + +# Project Portfolio Page (PPP) +## Project overview +**Jikan** is a CLI time-tracker built in Java that aims to help manage tasks and projects. Users can set tags and goals for their entries, ultimately being able to keep track of what's left to do and maintain an overview of how time was spent. + +## Summary of contributions +### Code contributed +[Link to tP Code Dashboard](https://nus-cs2113-ay1920s2.github.io/tp-dashboard/#search=btricec) + +### Enhancements implemented +* Starting and ending activities + * Implemented the basic `start` and `end` commands. + * `start` allows the user to start an activity and add tags to that activity. + * `end` ends the started activity and saves it to the activity list. + * `abort` stops the current activity and does not save it. + * Implemented an additional feature that gives the user the option to end an activity when the user exits the app after starting an activity. + +* Continue + * Allows the user to continue an activity in the activity list. + * Implemented an additional feature that gives the user the option to continue an activity if they used the `start` command to start an activity already in the activity list. + +* Graph activities and tags + * `graph activities` displays a graph of the duration of each activity based on the `lastShownList` + * `graph tags` calculates the duration of activity tags in the `lastShownList` and displays a graph of the cumulative duration for each tag. + +* Delete + * Allows the user to delete an activity from the activity list. + +### Contributions to documentation +* Did the *Usage* section to give an overall example of how Jikan can be used in logical flow of commands, providing examples of expected outputs. +* Provided syntax and usage examples for some commands (namely, start, end, continue, abort and delete) + +### Contributions to the DG +* Explained the implementation of the `continue` command (under section 3.5) using Sequence Diagrams +* Explained the implementation of the `graph` command (under section 3.9) using Sequence Diagrams +* Gave instructions for manual testing and included sample test cases for `list`, `continue` and `graph` commands. + +### Contributions to team-based tasks +* Set up the issue tracker with relevant labels and milestones. +* Made extensive use of the issue tracker to manage enhancements and bugs. +* Released v1.0 and v2.0 of Jikan, and also provided a set of sample data for v2.0 for testing. +* Did more extensive refactoring for commands, moving the command execution to the command class itself. + +### Review contributions +* Contributed to ideation and implementation discussion of new features offline. +* Although I did not explicitly review PRs on github, I actively tried to help with text-ui issues which were a big problem for our group. (text-ui file had to be updated every day to reflect the current date for it to pass) + + +## Contributions to the User Guide (extracts) + +## Contributions to the Developer Guide (extracts) +### 3.5 Continue Feature +The continue feature allows the user to continue a previously ended activity. + +#### 3.5.1 Current Implementation +(diagrams are omitted) +**Continuing an activity:** + +- When the user enters the command to continue an activity, a _ContinueCommand_ object is created in _Parser_. The method `executeCommand()` of the _ContinueCommand_ object is then called. +- `executeCommand` checks if the given activity name exists in the activityList by calling `findActivity()` (if it doesn’t an exception is thrown, omitted in the sequence diagram above) +- It then gets the `name` and `tags` of the activity to be continued and saves it to a public static variable of _Parser_ object. +- It also gets the current time and saves it to a public static variable of _Parser_ object. + +**Ending a continued activity:** + +- When the user wants to end the continued activity, an _EndCommand_ object is created in _Parser._ The method `executeCommand()` of the _ContinueCommand_ object is then called and it in turn executes the `saveActivity()` method of the _ActivityList_ class. +- `saveActivity()` gets the current time and saves it to a public static variable of _Parser_ object. +- Then the elapsed time is calculated using the `between()` method of _Duration_ class. +- The elapsed time is added with the previous duration of the activity to get the `newDuration` using the `plus()` method of Duration class. +- `updateDuration()` method is called to update the `duration` attribute of the continued activity in the `activityList` as well as the `data.csv` file. + +#### 3.5.2 Design Considerations + +**Execution:** + +- Continue by activity name (current implementation) + - **Cons:** Activity names have to be unique. + - **Pros:** More versatile, resistant to changes in the activity list +- Continue by activity index + - **Cons:** need to add an additional index field to the Activity class, index is not fixed, changes when an activity is deleted + - **Pros:** Can reuse activity names. + +Although the current implementation of the continue feature disallows users to have multiple activities with the same name, we felt that the versatility of this choice outweighed the cons. Firstly because if the activityList got too big, it would be hard for the user to get the index of the task they wanted to continue. Also, the index would constantly be changing when changes are made to the list. + +#### 3.5.3 Additional Features + +As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, they will be given the option to continue the stated activity. + +### 3.9 Graph Feature + +This feature gives the user a visual representation of their activity duration and activity goals. +Graph can be used along with `list`, `find` and `filter` to sieve out the data to be graphed. + +#### 3.9.1 Current Implementation +(diagrams are omitted) +- This feature is called by the user when the `graph` command is entered into the command line. The user will then have to specify what he would like to graph (goals progress bar / tag duration / activity duration). +- The Parser will create a GraphCommand object. +- The GraphCommand will invoke its own `executeCommand()` method. + +**Graph targets** +This displays the progress bar for the duration with respect to allocated time of activities in the `lastShownList`. + +- If the user indicated `targets`, Ui calss will be called to execute graphTargets. + +**Graph tags** +This displays a bar graph of the cumulative duration of the tags for each activity in the `lastShownList`. E.g. if 3 activities in the `lastshownlist` are tagged `CS2113`, the durations of these 3 activities are added up and associated with the tag `CS2113` in the graph. + +- If the user indicated `tags`, `GraphCommand` will call it's own `graphTags` method. +- A HashMap (`tags`) of tags to duration is created. +- `graphTags` iterates through every activity in `lastshownlist` and in each loop, `extractTags` is called. +- `extractTags` loops through the tags of that activity. Tag is added to the `tags` if it is not found. Else, the duration of the activity is added to the corresponding tag in `tags`. +- `tags` and `interval` (how many minutes each point in the graph represents) is passed to the method printTagGraphs in Ui to print the graph. + +**Graph activities** +This displays a bar graph of the durations of each activity in the `lastShownList`. + +- If the user indicated `activities`, `GraphCommand` will call it's own `graphDuration` method. +- `graphDuration` calls `printActivityGraph` of the Ui class and passes the `interval` parameter, which is how many minutes each point in the graph represents. + +#### 3.9.2 Additional features + +As graph gets it's data based on the `lastShownList`, users can pair the `graph` command with `find`, `filter`, and `list` to sieve out the activities to be graphed. \ No newline at end of file diff --git a/docs/team/rdimaio.md b/docs/team/rdimaio.md index cb2d56f49..3f796e4f1 100644 --- a/docs/team/rdimaio.md +++ b/docs/team/rdimaio.md @@ -23,7 +23,7 @@ and maintain an overview of how time was spent. * The `list` command allows the user to list all the activities for a specified date or range of dates. In many cases, the user does not want to specify the exact dates; that is why the user can simply ask to `list day`, `list week`, - `list month 05` etc. to list entries belonging in the specified time frame. + `list month april` etc. to list entries belonging in the specified time frame. ### Contributions to documentation * Provided information on how to use the `list` command, including From 4ea1b2b5d8611f61706572f0f242be28afa50b3a Mon Sep 17 00:00:00 2001 From: btricec Date: Tue, 7 Apr 2020 16:14:23 +0800 Subject: [PATCH 274/415] Fix extra parameters issue --- src/main/java/jikan/parser/Parser.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 961ae8e38..268d8918e 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -74,6 +74,10 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto switch (instruction) { case "bye": + if (tokenizedInputs.length > 1 && !tokenizedInputs[1].isBlank()) { + Ui.printDivider("Extra parameters detected!"); + break; + } command = new ByeCommand(null); break; case "start": @@ -85,14 +89,14 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto } break; case "end": - if (tokenizedInputs.length > 1) { + if (tokenizedInputs.length > 1 && !tokenizedInputs[1].isBlank()) { Ui.printDivider("Extra parameters detected!"); break; } command = new EndCommand(null); break; case "abort": - if (tokenizedInputs.length > 1) { + if (tokenizedInputs.length > 1 && !tokenizedInputs[1].isBlank()) { Ui.printDivider("Extra parameters detected!"); break; } From ecab22be128a50913495a97ae6bb88365cd04d23 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Tue, 7 Apr 2020 16:15:23 +0800 Subject: [PATCH 275/415] Add PPP --- docs/UserGuide.md | 5 ++ docs/team/nigellenl.md | 101 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 106 insertions(+) create mode 100644 docs/team/nigellenl.md diff --git a/docs/UserGuide.md b/docs/UserGuide.md index e0fe29fea..771bfbae9 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -192,6 +192,11 @@ By using the `goal` command, users can set specific goals for how long they woul **Example:** `goal core /g 24:00:00` a goal of `24:00:00` is added for the tag `core` +### Delete goal: `goal TAG_NAME /d` +**Usage:** Deletes the duration goal set for the tag. + +**Format:** `goal TAG_NAME /d` + ### View goals: `goal` **Usage:** Displays the tags with their goals, actual time spent on activities with these tags and the difference between the 2 timings. diff --git a/docs/team/nigellenl.md b/docs/team/nigellenl.md new file mode 100644 index 000000000..8f56d2a90 --- /dev/null +++ b/docs/team/nigellenl.md @@ -0,0 +1,101 @@ +# Project Portfolio Page (PPP) +## Project overview +**Jikan** is a CLI time-tracker built in Java that aims to help manage tasks and projects. Users can set tags and goals for their entries, ultimately being able to keep track of what's left to do and maintain an overview of how time was spent. + +## Summary of contributions +### Code contributed +[Link to tP Code Dashboard](https://nus-cs2113-ay1920s2.github.io/tp-dashboard/#search=nigellenl) + +### Enhancements implemented +* Edit activities + * Allow the user to edit the name of existing activities in the activity list. + * Allow the user to edit the allocated time of existing activities in the activity list. + * `edit ACTIVITY_NAME /en NEW_NAME` allows the user to edit the activity name. + * `edit ACTIVITY_NAME /ea NEW_ALLOCATED_TIME` allows the user to edit the allocated time. + +* Goal setting + * Allow the user to set and delete goals based on existing tags. + * `goal TAG_NAME /g GOAL_TIME` allows the user to set the goal for that tag. + * `goal TAG_NAME /d` allows the user to delete the goal set for that tag. + +* View goals + * Allow the user to view the goals in a table format. + * `goal` displays all the goals that have been set. + +### Contributions to documentation +* Provided syntax and usage examples for some commands (edit, set goal, view goal) +* Added command summary with command name and syntax. + +### Contributions to the DG +* Added setting up instructions. +* Explained the implementation of the `edit` command (under section 3.4) using Sequence Diagrams +* Gave instructions for manual testing and included sample test cases for `goal` command. + +### Contributions to team-based tasks +* Made extensive use of the issue tracker to manage enhancements and bugs. +* Did refactoring for commands by creating command classes. + +### Review contributions +* Discussed with team on how to further enhance existing features (e.g. allowing user to edit allocated time) + +## Contributions to the User Guide (extracts) +### Editing an activity: `edit` +**Usage:** Edits the name or allocated time of an activity in the activity list. + +**Format** +* `edit ACTIVITY_NAME /en NEW_NAME` +* `edit ACTIVITY_NAME /ea NEW_ALLOCATED_TIME` + * `NEW_ALLOCATED_TIME` should be in the format [HH:MM:SS] + +**Example:** +`edit CS1010 assignment /en CS1010 assignment 2` Activity name is edited to `CS1010 assignment 2` +`edit CS1010 assignment /ea 10:00:00` Allocated time for activity is edited to `10:00:00` + +### Tag Goals + +By using the `goal` command, users can set specific goals for how long they would like to spend on activities under a certain tags as well as view the amount of time they have spent in total for those activities as compared to their goal. + +### Set goal: `goal TAG_NAME /g DURATION` +**Usage:** Sets a duration goal for a tag + +**Format:** `goal TAG_NAME /g DURATION` +* The duration should be in the format [HH:MM:SS] + +**Example:** `goal core /g 24:00:00` a goal of `24:00:00` is added for the tag `core` + +### Delete goal: `goal TAG_NAME /d` +**Usage:** Deletes the duration goal set for the tag. + +**Format:** `goal TAG_NAME /d` + +### View goals: `goal` +**Usage:** Displays the tags with their goals, actual time spent on activities with these tags and the difference between the 2 timings. + +**Format:** `goal` + +## Contributions to the Developer Guide (extracts) + +### Edit feature +The edit feature allows the user to make changes to activities that have been saved in the activity list. This is to allow the user to rectify any mistakes that may have been made during the initial recording of the activity. + +#### Current Implementation +The following sequence diagram shows how the edit feature works. +_diagram omitted_ + +The current implementation of the edit feature allows the user to edit only the name parameter of the activity. When the user wants to edit an activity using the edit command, the Parser creates a new EditCommand object. The `executeCommand()` method of the EditCommand object is called and the specified parameters are updated accordingly. + +The order of method calls to edit the activity details is as follows if the specified activity exists (meaning `index >= 0`) else an exception is thrown: +1. The `updateName()` method of the ActivityList class is called, with the user-specified parameters of the activity index and new activity name +2. The `get()` method is self-invoked by the ActivityList class to obtain the activity at the given index +3. The `setName()` method of the Activity class is called to edit the activity name to the user-specified name +4. The activity with the updated name is returned to the activityList + +#### Additional Implementations +The current implementation of the edit feature only allows the user to edit the activity name. Hence, additional implementations of the edit feature should allow the user to edit other parameters of the activity such as the tags and the start and end dates. + +This will require the implementation of more update methods in the ActivityList class to allow for the changes to be updated in the activityList after it has been edited. + +#### Design Considerations +By letting the user edit the name and tags of the activity, it will allow them to correct any mistakes made during the data entry. This ensures that there is an accurate record of activities such as in cases where the user may be trying to record the same activity but has misspelled it, resulting in the program regarding it as a different activity where there would be multiple unnecessary new entries in the activity list, making the analysis of the time spent more tedious and inaccurate. + +However, by allowing the user to edit the start date and time, there may be potential inaccuracies in the actual activity recording. This is due to the fact that the time recorded in the program is based on the LocalDateTime. By introducing user input, the dates and time may be recorded incorrectly, defeating the purpose of the time tracking program. From 63f5ad0cda4122a39d31d431b8aed2598a5b4e89 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 7 Apr 2020 16:25:40 +0800 Subject: [PATCH 276/415] Fix empty tags --- src/main/java/jikan/command/StartCommand.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index ff2a7079f..13d46eb53 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -263,10 +263,12 @@ private void addActivityWithBothField(String durationInfo, String tagInfo, Strin try { endTime = LocalTime.parse(durationInfo); Duration allocatedTime = Duration.between(startTime, endTime); - if (tagString.length > 2) { - Ui.printDivider("Cannot have more than 2 tags"); + if (tagInfo.isEmpty()) { + Ui.printDivider("Please provide a valid tag"); } else if (allocatedTime == Duration.parse("PT0S")) { Ui.printDivider("Please provide a non zero allocated time"); + } else if (tagString.length > 2) { + Ui.printDivider("Cannot have more than 2 tags"); } else { Parser.tags.addAll(Arrays.asList(tagString)); Parser.allocatedTime = allocatedTime; @@ -297,7 +299,6 @@ private void addActivityWithAllocation(String activityName, String line) { } else { Parser.allocatedTime = allocatedTime; addActivity(activityName); - } } catch (DateTimeException e) { Ui.printDivider("Time provided is invalid, please provide time in this format" @@ -315,7 +316,9 @@ private void addActivityWithTag(String activityName, String line) { String tagInfo = line.substring(index + 2); tagInfo = tagInfo.trim(); String[] tagString = tagInfo.split(" "); - if (tagString.length > 2) { + if (tagInfo.isEmpty()) { + Ui.printDivider("Please provide a valid tag"); + } else if (tagString.length > 2) { Ui.printDivider("Cannot have more than 2 tags"); } else { Parser.tags.addAll(Arrays.asList(tagString)); From 7faefff97f7e3562f2593e7285133f11d869e3b9 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 7 Apr 2020 19:00:07 +0800 Subject: [PATCH 277/415] Update PPP --- docs/UserGuide.md | 9 ++- docs/team/siuhian.md | 145 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 docs/team/siuhian.md diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 771bfbae9..a03c91238 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,8 +1,15 @@ # User Guide +## Target user profile + +University students with poor time management skills who are struggling to allocate time efficiently for +the numerous deadlines/tasks. + ## Introduction -Jikan is a CLI time management tool that allows you to track the amount of time that you spend on different activities. This user guide will show you how to use the program effectively. +Jikan is a CLI time management tool that allows you to track the amount of time that you spend on different activities so as to ensure +that time is allocated more efficiently to the different activities (i.e spending too much/too little time on an activity) . +This user guide will show you how to use the program effectively. ## Quick Start 1. Ensure that you have Java 11 or above installed. diff --git a/docs/team/siuhian.md b/docs/team/siuhian.md new file mode 100644 index 000000000..24476ab09 --- /dev/null +++ b/docs/team/siuhian.md @@ -0,0 +1,145 @@ +# Project Portfolio Page (PPP) +## Project overview +**Jikan** is a CLI time-tracker built in Java that aims to help manage tasks and projects. +Users can set tags and goals for their entries, +ultimately being able to keep track of what's left to do and maintain an overview of how time was spent. + +## Summary of contributions +### Code contributed +[Link to tP Code Dashboard](https://nus-cs2113-ay1920s2.github.io/tp-dashboard/#search=siuhian) + +### Enhancements implemented +* Start activities + * Added new feature on top of the existing `start` command. + * `start` command now allows users to allocate a certain amount of time for that activity using the /a flag. + * Fix bugs in the `start` command with inputs from the peer testing results. + * Added more flexibility to the `start` command, `start cs2113 /a 10:30:00 /t tP` now works the same way as + `start cs2113 /t tP /a 10:30:00` meaning the positions of /a and /t flags can now be used interchangeably. + +* User interface + * Sourced and implemented the existing Jikan logo that greets the user upon execution + * Created a standard template to print lines to stdout. This feature is used to print error, acknowledgement and + reply messages from Jikan to the user. + * Implemented the `bye` command which makes use of Ui to exit from the application. + +* Automated cleaning + * Built a automated cleaner that performs a batch delete on data and log files upon application execution. + * This batch delete on data works by deleting a number of completed activities (specified by user) starting from the oldest + completed activity (e.g completed activities are activities that have met its allocated time). + * Implemented `clean` command which allows the user to switch on/off the automated cleaner. + * Allows the user to specify how much completed activities/logs to delete for each round of automated cleaning. This + is done through the /n flag in the clean command. + +* Graph allocations + * Provides the user with a graphical representation on the progress of all the activities. + * The function is provided by the `graph allocations` command. + +### Contributions to documentation +* Provided syntax and usage examples for these commands. (`clean`,`graph allocations` and `start`). +* Edited the command summary and usage section to ensure consistency with the features under my implementation. + +### Contributions to the DG +* Explained the implementation of the automated cleaning feature (Under Section 3.1) using a mixture of sequence diagram +with flowcharts. + +### Contributions to team-based tasks +* Generated ideas with the team on the set of features for the Jikan application. +* Made use of the issue tracker extensively to track enhancement and bugs found. +* Enabled assertions in the build.gradle file. +* Created the project repository and set up the team organization. +* Helped create the Parser and Ui class to make the code more OOP. +* Documenting the target user profile. +* Helped out in resolving the text-ui-issues (date sensitive need to update everyday) that caused many commits to fail the checks. + +### Review/mentoring contributions +* Provided feedback to peers on how certain features can be improved (e.g progress message for activities, + store tag goals in separate data file so as to not overload the main data file for activities) + +### Contributions beyond the project team +* Provided feedback to the developer guide of another team. + * [Reviewing of DG on Week 11](https://github.com/nus-cs2113-AY1920S2/tp/pull/7) +* Reported bugs in other team's product in PE dry run. + * [PED](https://github.com/siuhian/ped/issues) + +### Contributions to the User Guide (Extracts) + +#### Usage of Automated Cleaning + +As Jikan is a time tracker application which works with various data files (data file for activities, log files for execution history +etc.), over time it can be a mess to deal with these data files especially when they get too big. Thus, Jikan provides automated cleaning +services for such situations. + +#### Activating the automated cleaning: `clean on | clean log on` +At runtime, users can switch on the automated cleaning services. Once the automated cleaning is activated, the application will +do an auto cleanup of files at the start of every execution until this services is switch off. Do note that the cleaning will only start from the next execution. +(i.e no cleaning will be done for the current execution which activated auto cleaning). + +Note: \ +`clean on` activates the cleaning of data files where activities are stored. \ +`clean log on` activates the cleaning of log files where application execution history is stored. + +#### Deactivating the automated cleaning: `clean off | clean log off` +At runtime, users can switch off the automated cleaning services. Once deactivated, the application will +stop doing an auto cleanup of files at the start of every execution. Similarly, the changes only applies to the next execution. + +Note:\ +When the application is executed for the first time, the automated cleaning is deactivated by default and will remain so until it is activated by the user. + +#### Specifying how much data to clean: `clean /n NUMBER | clean log /n NUMBER` +At runtime, the user can manually set the amount of data to clean using these commands where `NUMBER` is an integer based on user input. +Thus, `clean /n 5` will automatically clean the top 5 oldest activities from the activity list upon every startup (assuming automated cleaning +is activated). + +Note:\ +Default `NUMBER` value for data files : 3\ +Default `NUMBER` value for log files : 10 + +### Contributions to the Developer Guide (Extracts) + +#### 3.1 Automated Storage Cleanup feature + +##### 3.1.1 Current Implementation + +The storage cleanup mechanism is stored internally as a StorageCleaner class. The StorageCleaner class has an association with the Storage class and thus it is able to access and edit the datafile which contains the list of activities. + +Additionally, when the StorageCleaner class is first initialised, it will create two files, namely a status file and a data file in the “recycled” folder under the “data” folder. The status file keeps track of the activation status of the storage cleaner while the data file serves as a recycle bin for deleted data. + +Moreover, the class also implements the following operations: + +`StorageCleaner#initialiseCleaner - Loads up the status file to decide whether to activate/deactivate the automated cleaner.` + +`StorageCleaner#setStatus - Gives the user the freedom to activate/de-activate the cleaner using commands during application runtime.` + +`StorageCleaner#autoClean - This operation is called whenever the application is executed. Storage cleaning will only be done if the cleaner is activated.` + +Given below is the example scenario of how the operations work. + +###### initialiseCleaner + +Step 1. Loads up the status file for reading. If the status file is not found, create a new status file and write the character ‘0’ to the first line of the status file. + +Step 2. Read the first line of the status file, if a character ‘0’ is found, deactivate the automated cleanup. Else if a character ‘1’ is found, activate the automated cleanup. + +###### setStatus + +Step 1. Read the boolean parameter `status`. + +Step 2a. If `status` is equal to true, activate the automated cleanup and write the character ‘1’ to the first line of the status file. (overwrite any existing value at the first line). + +Step 2b. If `status` is equal to false, deactivate the automated cleanup and write the character ‘0’ to the first line of the status file. + +###### autoClean + +Step 1. Check activation status of StorageCleaner through the class level attribute boolean `toClean`. + +Step 2a. If the attribute `toClean` is equal to `false`, return the operation and give control back to the caller. + +Step 2b. If the attribute `toClean` is equal to `true`, access the storage data file and remove some of the activities starting from the oldest. Put these deleted activities into the data file under the ‘recycled’ folder. + +##### 3.1.2 Additional Implementation (proposed) + +`StorageCleaner#setDeleteQuota - Allows the user to manipulate how much activity is deleted when auto cleanup is activated. Currently only delete the oldest 3 activities.` + +`StorageCleaner#setTimeFrame - Set a particular time frame for auto cleanup to activate. (i.e auto cleanup after every 2 weeks etc).` + +`StorageCleaner#initialiseLogCleaner - Gives the storage cleaner an added functionality of being able to clear log files too.` From 11f862aee70ad1d9113a530cddc1d3937228de66 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 7 Apr 2020 19:05:00 +0800 Subject: [PATCH 278/415] Fix text-ui-test --- text-ui-test/EXPECTED.TXT | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 4b06eaed6..0980b0af6 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -38,29 +38,29 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Your completed activities: - | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag1] + | Name | Duration | Allocation | Date | Tags +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: - | Name | Duration | Target | Date -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] + | Name | Duration | Allocation | Date +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: - | Name | Duration | Target | Date -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] + | Name | Duration | Allocation | Date +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: - | Name | Duration | Target | Date -1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag1] + | Name | Duration | Allocation | Date +1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ There is already an activity with this name. Would you like to continue it? @@ -73,10 +73,10 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Your completed activities: - | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag1] + | Name | Duration | Allocation | Date | Tags +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Please input an integer for the time interval. @@ -111,9 +111,9 @@ You have deleted activity 2 ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Your completed activities: - | Name | Duration | Target | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag] -2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-05 | [tag1] + | Name | Duration | Allocation | Date | Tags +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] +2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Bye! See you again. From adc7a6b96aa93d472a680218ab36c6ef15f6de95 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 7 Apr 2020 22:25:39 +0800 Subject: [PATCH 279/415] Made some code quality changes --- src/main/java/jikan/cleaner/Cleaner.java | 10 +- src/main/java/jikan/cleaner/LogCleaner.java | 10 +- .../java/jikan/cleaner/StorageCleaner.java | 10 +- src/main/java/jikan/command/StartCommand.java | 118 ++++++++++-------- src/main/java/jikan/parser/Parser.java | 2 +- src/main/java/jikan/ui/Ui.java | 4 +- 6 files changed, 85 insertions(+), 69 deletions(-) diff --git a/src/main/java/jikan/cleaner/Cleaner.java b/src/main/java/jikan/cleaner/Cleaner.java index 9dfb42411..e00990635 100644 --- a/src/main/java/jikan/cleaner/Cleaner.java +++ b/src/main/java/jikan/cleaner/Cleaner.java @@ -7,12 +7,12 @@ import java.util.Scanner; public abstract class Cleaner { - protected static String STATUS_FILE_PATH; - protected static String DATA_FILE_PATH; + protected String statusFilePath; + protected String dataFilePath; protected File status; protected File recycledData; public boolean toClean; - private static final int defaultNumberOfDataToClean = 5; + private static final int DEFAULT_LINES_TO_CLEAN = 5; /** * Initialise a data file containing the deleted logs. @@ -84,7 +84,7 @@ protected int initialiseCleaner() { fw.write("0" + "\n"); fw.write("5" + "\n"); fw.close(); - return defaultNumberOfDataToClean; + return DEFAULT_LINES_TO_CLEAN; } } catch (IOException e) { System.out.println("Error loading/creating cleaning file."); @@ -100,7 +100,7 @@ protected int initialiseCleaner() { */ public void setStatus(boolean status, int number) throws IOException { this.toClean = status; - File dataFile = new File(STATUS_FILE_PATH); + File dataFile = new File(statusFilePath); if (!dataFile.exists()) { dataFile.createNewFile(); } diff --git a/src/main/java/jikan/cleaner/LogCleaner.java b/src/main/java/jikan/cleaner/LogCleaner.java index 78f12fd2f..2332c51ab 100644 --- a/src/main/java/jikan/cleaner/LogCleaner.java +++ b/src/main/java/jikan/cleaner/LogCleaner.java @@ -24,10 +24,10 @@ public class LogCleaner extends Cleaner { * Constructor for the log cleaner. */ public LogCleaner() { - super.STATUS_FILE_PATH = "data/recycled/logStatus.txt"; - super.status = new File(STATUS_FILE_PATH); - super.DATA_FILE_PATH = "data/recycled/logData.txt"; - super.recycledData = new File(DATA_FILE_PATH); + super.statusFilePath = "data/recycled/logStatus.txt"; + super.status = new File(statusFilePath); + super.dataFilePath = "data/recycled/logData.txt"; + super.recycledData = new File(dataFilePath); initialiseDataFile(); int value = initialiseCleaner(); if (value != -1) { @@ -42,7 +42,7 @@ public LogCleaner() { */ public void setNumberOfLogsToClean(int value) throws IOException { boolean status = this.toClean; - File dataFile = new File(STATUS_FILE_PATH); + File dataFile = new File(statusFilePath); this.numberOfLogsToClean = value; if (!dataFile.exists()) { dataFile.createNewFile(); diff --git a/src/main/java/jikan/cleaner/StorageCleaner.java b/src/main/java/jikan/cleaner/StorageCleaner.java index 1f950e018..2b5e8a461 100644 --- a/src/main/java/jikan/cleaner/StorageCleaner.java +++ b/src/main/java/jikan/cleaner/StorageCleaner.java @@ -27,10 +27,10 @@ public class StorageCleaner extends Cleaner { */ public StorageCleaner(Storage storage) { this.storage = storage; - super.STATUS_FILE_PATH = "data/recycled/status.txt"; - super.status = new File(STATUS_FILE_PATH); - super.DATA_FILE_PATH = "data/recycled/data.csv"; - super.recycledData = new File(DATA_FILE_PATH); + super.statusFilePath = "data/recycled/status.txt"; + super.status = new File(statusFilePath); + super.dataFilePath = "data/recycled/data.csv"; + super.recycledData = new File(dataFilePath); initialiseDataFile(); int value = initialiseCleaner(); if (value != -1) { @@ -45,7 +45,7 @@ public StorageCleaner(Storage storage) { */ public void setNumberOfActivitiesToClean(int value) throws IOException { boolean status = this.toClean; - File dataFile = new File(STATUS_FILE_PATH); + File dataFile = new File(statusFilePath); this.numberOfActivitiesToClean = value; if (!dataFile.exists()) { dataFile.createNewFile(); diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 13d46eb53..d0ff74824 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -22,7 +22,7 @@ public class StartCommand extends Command { private boolean hasAllocation = false; private boolean hasTag = false; private boolean hasAllocationAndTag = false; - private static final int maxActivityLength = 25; + private static final int MAX_ACTIVITY_LENGTH = 25; /** * Constructor to create a new start command. @@ -60,6 +60,7 @@ private boolean hasStarted(LocalDateTime startTime) { * Stops executing current activity if a concurrent running activity is found. */ private void stopExecution() { + assert Parser.startTime != null; String line = Parser.activityName + " is ongoing!"; Log.makeInfoLog("Could not start activity due to already ongoing activity."); Ui.printDivider(line); @@ -70,31 +71,15 @@ private void stopExecution() { * @param activityList a list of tracked activities. */ private void continueExecution(ActivityList activityList) { - boolean commandIsEmpty = hasParameter(this.parameters); - String activityName = ""; - if (commandIsEmpty) { - Ui.printDivider("Start command cannot be empty"); - } else { - activityName = parseActivityName(this.parameters); - } + String activityName = parseActivityName(this.parameters); if (activityName.isEmpty()) { + Log.makeFineLog("Empty activity name was provided."); Ui.printDivider("Activity name cannot be empty"); } else { checkActivity(activityName, activityList); } } - /** - * Check if the start command is empty. - * @param parameters the parameters to start command. - * @return true if it is empty and false otherwise. - */ - private boolean hasParameter(String parameters) { - if (parameters.isEmpty()) { - return true; - } - return false; - } /** * Get activity name from parameters to start command. @@ -109,15 +94,19 @@ private String parseActivityName(String parameters) { scenario = getScenario(tagDelimiter, allocateDelimiter); switch (scenario) { case "hasTagAndAllocation": + assert tagDelimiter != -1 && allocateDelimiter != -1; activityName = handleTagAndAllocation(this.parameters, tagDelimiter, allocateDelimiter); break; case "hasTagOnly": + assert tagDelimiter != -1 && allocateDelimiter == -1; activityName = handleTagOrAllocation(this.parameters, tagDelimiter); break; case "hasAllocationOnly": + assert tagDelimiter == -1 && allocateDelimiter != -1; activityName = handleTagOrAllocation(this.parameters, allocateDelimiter); break; case "hasNoTagAndAllocation": + assert tagDelimiter == -1 && allocateDelimiter == -1; activityName = this.parameters.trim(); break; default: @@ -156,13 +145,14 @@ private String getScenario(int tagDelimiter, int allocateDelimiter) { * @return activity name */ private String handleTagAndAllocation(String parameters, int tagDelimiter, int allocateDelimiter) { - String activityName = ""; + String activityName; int delimiter = 0; if (tagDelimiter < allocateDelimiter) { delimiter = tagDelimiter; } else if (allocateDelimiter < tagDelimiter) { delimiter = allocateDelimiter; } + assert delimiter == tagDelimiter || delimiter == allocateDelimiter; activityName = parameters.substring(0, delimiter); activityName = activityName.trim(); if (activityName.isEmpty()) { @@ -179,6 +169,7 @@ private String handleTagAndAllocation(String parameters, int tagDelimiter, int a * @return activity name. */ private String handleTagOrAllocation(String parameters, int delimiter) { + assert delimiter != -1; String activityName = parameters.substring(0, delimiter); activityName = activityName.trim(); if (activityName.isEmpty()) { @@ -189,17 +180,18 @@ private String handleTagOrAllocation(String parameters, int delimiter) { } /** - * Method to check if the activity exists in activitylist and does not exceed 25 characters. + * Method to check if the activity exists in activity list and does not exceed 25 characters. * @param activityName the string representing activity name. * @param activityList a list of tracked activities. */ private void checkActivity(String activityName, ActivityList activityList) { + assert !activityName.isEmpty(); int index = activityList.findActivity(activityName); if (index != -1) { Ui.printDivider("There is already an activity with this name. Would you like to continue it?"); continueActivity(activityList, scanner, index); - } else if (activityName.length() > maxActivityLength) { - Log.makeInfoLog("Activity name longer than 25 characters"); + } else if (activityName.length() > MAX_ACTIVITY_LENGTH) { + Log.makeInfoLog("Activity name longer than 25 characters."); Ui.printDivider("Please input an activity name that is shorter than 25 characters."); } else { addActivityToList(activityName); @@ -230,6 +222,7 @@ private void addActivityToList(String activityName) { private void parseActivityWithBothField(String activityName, String line) { int allocateIndex = line.indexOf("/a"); int tagIndex = line.indexOf("/t"); + assert tagIndex != -1 && allocateIndex != -1; String tagInfo = ""; String durationInfo = ""; if (tagIndex < allocateIndex) { @@ -257,29 +250,44 @@ private void parseActivityWithBothField(String activityName, String line) { * @param activityName the string representing activity name. */ private void addActivityWithBothField(String durationInfo, String tagInfo, String activityName) { - LocalTime startTime = LocalTime.MIN; - LocalTime endTime; - String[] tagString = tagInfo.split(" "); + String[] tagStrings = tagInfo.split(" "); try { - endTime = LocalTime.parse(durationInfo); - Duration allocatedTime = Duration.between(startTime, endTime); - if (tagInfo.isEmpty()) { - Ui.printDivider("Please provide a valid tag"); - } else if (allocatedTime == Duration.parse("PT0S")) { - Ui.printDivider("Please provide a non zero allocated time"); - } else if (tagString.length > 2) { - Ui.printDivider("Cannot have more than 2 tags"); - } else { - Parser.tags.addAll(Arrays.asList(tagString)); - Parser.allocatedTime = allocatedTime; - addActivity(activityName); - } + checkBothField(durationInfo, tagInfo, activityName, tagStrings); } catch (DateTimeException e) { + Log.makeInfoLog("Allocated time provided was not valid."); Ui.printDivider("Time provided is invalid, please provide time in this format" + " HH:MM:SS"); } } + /** + * Check if allocated time and tags are formatted correctly/not empty + * @param durationInfo information about the duration. + * @param tagInfo information about the tag. + * @param activityName the string representing activity name. + * @param tagStrings tokenized information about the tags. + */ + private void checkBothField(String durationInfo, String tagInfo, String activityName, String[] tagStrings) { + LocalTime startTime = LocalTime.MIN; + LocalTime endTime; + endTime = LocalTime.parse(durationInfo); + Duration allocatedTime = Duration.between(startTime, endTime); + if (tagInfo.isEmpty()) { + Log.makeInfoLog("No tags found with tag flag."); + Ui.printDivider("Please provide a valid tag"); + } else if (allocatedTime == Duration.parse("PT0S")) { + Log.makeInfoLog("Allocated time is zero."); + Ui.printDivider("Please provide a non zero allocated time"); + } else if (tagStrings.length > 2) { + Log.makeInfoLog("Activity has more than 2 tags."); + Ui.printDivider("Cannot have more than 2 tags"); + } else { + Parser.tags.addAll(Arrays.asList(tagStrings)); + Parser.allocatedTime = allocatedTime; + addActivity(activityName); + } + } + /** * Add activity with allocated time only. * @param activityName the string representing activity name. @@ -290,22 +298,28 @@ private void addActivityWithAllocation(String activityName, String line) { String durationInfo = line.substring(index + 2); durationInfo = durationInfo.trim(); LocalTime startTime = LocalTime.MIN; - LocalTime endTime; try { - endTime = LocalTime.parse(durationInfo); - Duration allocatedTime = Duration.between(startTime, endTime); - if (allocatedTime == Duration.parse("PT0S")) { - Ui.printDivider("Please provide a non zero allocated time"); - } else { - Parser.allocatedTime = allocatedTime; - addActivity(activityName); - } + checkTime(activityName, durationInfo, startTime); } catch (DateTimeException e) { + Log.makeInfoLog("Allocated time provided was not valid."); Ui.printDivider("Time provided is invalid, please provide time in this format" + " HH:MM:SS"); } } + private void checkTime(String activityName, String durationInfo, LocalTime startTime) { + LocalTime endTime; + endTime = LocalTime.parse(durationInfo); + Duration allocatedTime = Duration.between(startTime, endTime); + if (allocatedTime == Duration.parse("PT0S")) { + Log.makeInfoLog("Allocated time is zero."); + Ui.printDivider("Please provide a non zero allocated time"); + } else { + Parser.allocatedTime = allocatedTime; + addActivity(activityName); + } + } + /** * Add activity with tags only. * @param activityName the string representing activity name. @@ -315,13 +329,15 @@ private void addActivityWithTag(String activityName, String line) { int index = line.indexOf("/t"); String tagInfo = line.substring(index + 2); tagInfo = tagInfo.trim(); - String[] tagString = tagInfo.split(" "); + String[] tagStrings = tagInfo.split(" "); if (tagInfo.isEmpty()) { + Log.makeInfoLog("No tags found with tag flag."); Ui.printDivider("Please provide a valid tag"); - } else if (tagString.length > 2) { + } else if (tagStrings.length > 2) { + Log.makeInfoLog("Activity has more than 2 tags."); Ui.printDivider("Cannot have more than 2 tags"); } else { - Parser.tags.addAll(Arrays.asList(tagString)); + Parser.tags.addAll(Arrays.asList(tagStrings)); addActivity(activityName); } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 268d8918e..444ede582 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -85,7 +85,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto command = new StartCommand(tokenizedInputs[1], scanner); } catch (NullPointerException | ArrayIndexOutOfBoundsException e) { makeInfoLog("Activity started without activity name"); - Ui.printDivider("Activity name cannot be empty!"); + Ui.printDivider("Start command cannot be empty"); } break; case "end": diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 20aec0247..3902d4e9f 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -30,7 +30,7 @@ public class Ui { public static final int TOTALBARS = 50; - private static final DecimalFormat df2 = new DecimalFormat("#.##"); + private static final DecimalFormat DF2 = new DecimalFormat("#.##"); /** Prints the logo and greeting so users know the app is working. */ public void printGreeting() { @@ -243,7 +243,7 @@ public static void printProgressBar(double percent, String activityName) { System.out.print(" "); } } - System.out.println("| " + df2.format(percent) + "%"); + System.out.println("| " + DF2.format(percent) + "%"); } /** From b8360220bd760d95c399809d15dd5af5ecc627a2 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 7 Apr 2020 23:28:49 +0800 Subject: [PATCH 280/415] Improve code quality for cleaners --- src/main/java/jikan/cleaner/Cleaner.java | 77 +++++++++++-------- src/main/java/jikan/cleaner/LogCleaner.java | 11 ++- .../java/jikan/cleaner/StorageCleaner.java | 10 ++- 3 files changed, 61 insertions(+), 37 deletions(-) diff --git a/src/main/java/jikan/cleaner/Cleaner.java b/src/main/java/jikan/cleaner/Cleaner.java index e00990635..e0a7fbec1 100644 --- a/src/main/java/jikan/cleaner/Cleaner.java +++ b/src/main/java/jikan/cleaner/Cleaner.java @@ -11,6 +11,7 @@ public abstract class Cleaner { protected String dataFilePath; protected File status; protected File recycledData; + /** toClean acts as a switch to switch on/off the cleaner */ public boolean toClean; private static final int DEFAULT_LINES_TO_CLEAN = 5; @@ -25,6 +26,50 @@ protected void initialiseDataFile() { } } + /** + * Activates/De-activates the auto clean up by checking the status file. + * @return the number of lines of data to automatically clean. + */ + protected int initialiseCleaner() { + try { + return getDataFromStatusFile(); + } catch (IOException e) { + System.out.println("Error loading/creating cleaning file."); + return -1; + } catch (NumberFormatException e) { + System.out.println("Error with loading status file. Please delete status file."); + return -1; + } + } + + /** + * Scans the status file if it exists to initialise toClean and get data on + * the number of lines to clean. + * @return the number of lines of data to automatically clean. + * @throws IOException if status file could not be loaded/created. + */ + private int getDataFromStatusFile() throws IOException, NumberFormatException { + if (loadCleaner(status)) { + Scanner sc = new Scanner(status); + String status = sc.nextLine(); + int value = Integer.parseInt(status); + assert value == 0 || value == 1; + if (value == 1) { + this.toClean = true; + } else { + this.toClean = false; + } + String line = sc.nextLine(); + return Integer.parseInt(line); + } else { + FileWriter fw = new FileWriter(status); + fw.write("0" + "\n"); + fw.write("5" + "\n"); + fw.close(); + return DEFAULT_LINES_TO_CLEAN; + } + } + /** * Loads the status file and checks if it exists or not. * @param file status file. @@ -61,36 +106,6 @@ protected void createFile(File file) throws IOException { file.createNewFile(); } - /** - * Activates/De-activates the auto clean up by checking the status file. - * @return the number of lines of data to automatically clean. - */ - protected int initialiseCleaner() { - try { - if (loadCleaner(status)) { - Scanner sc = new Scanner(status); - String status = sc.nextLine(); - int value = Integer.parseInt(status); - assert value == 0 || value == 1; - if (value == 1) { - this.toClean = true; - } else { - this.toClean = false; - } - String line = sc.nextLine(); - return Integer.parseInt(line); - } else { - FileWriter fw = new FileWriter(status); - fw.write("0" + "\n"); - fw.write("5" + "\n"); - fw.close(); - return DEFAULT_LINES_TO_CLEAN; - } - } catch (IOException e) { - System.out.println("Error loading/creating cleaning file."); - return -1; - } - } /** * Method to activate/de-activate the auto cleanup. @@ -110,7 +125,7 @@ public void setStatus(boolean status, int number) throws IOException { } else { writer.write("0" + "\n"); } - writer.write(Integer.toString(number) + "\n"); + writer.write(number + "\n"); writer.close(); } diff --git a/src/main/java/jikan/cleaner/LogCleaner.java b/src/main/java/jikan/cleaner/LogCleaner.java index 2332c51ab..bc5d75b3f 100644 --- a/src/main/java/jikan/cleaner/LogCleaner.java +++ b/src/main/java/jikan/cleaner/LogCleaner.java @@ -1,5 +1,8 @@ package jikan.cleaner; +import jikan.log.Log; +import jikan.ui.Ui; + import java.io.BufferedWriter; import java.io.File; import java.io.FileNotFoundException; @@ -32,6 +35,9 @@ public LogCleaner() { int value = initialiseCleaner(); if (value != -1) { this.numberOfLogsToClean = value; + } else { + Log.makeInfoLog("Problem initialising cleaner"); + Ui.printDivider("There is a problem initialising cleaner, please remove the status file"); } } @@ -53,7 +59,7 @@ public void setNumberOfLogsToClean(int value) throws IOException { } else { writer.write("0" + "\n"); } - writer.write(Integer.toString(value) + "\n"); + writer.write(value + "\n"); writer.close(); } @@ -67,7 +73,6 @@ public void logAutoClean() throws IOException { List logsLeftInData = new ArrayList<>(); if (this.toClean) { File liveData = recycleLog(logsForRecycling, logsLeftInData); - BufferedWriter recycledDataWriter = new BufferedWriter(new FileWriter(recycledData)); for (String line : logsForRecycling) { recycledDataWriter.write(line + "\n"); @@ -88,7 +93,7 @@ public void logAutoClean() throws IOException { * @return a log file that holds all the logging at run time. * @throws FileNotFoundException if file could not be found at the filepath. */ - private File recycleLog(List logsForRecycling, List logsLeftInData) throws FileNotFoundException { + private File recycleLog(List logsForRecycling, List logsLeftInData) throws IOException { File liveData = new File(LOG_FILE_PATH); Scanner recycledDataScanner = new Scanner(recycledData); Scanner liveDataScanner = new Scanner(liveData); diff --git a/src/main/java/jikan/cleaner/StorageCleaner.java b/src/main/java/jikan/cleaner/StorageCleaner.java index 2b5e8a461..569079ea6 100644 --- a/src/main/java/jikan/cleaner/StorageCleaner.java +++ b/src/main/java/jikan/cleaner/StorageCleaner.java @@ -1,6 +1,8 @@ package jikan.cleaner; +import jikan.log.Log; import jikan.storage.Storage; +import jikan.ui.Ui; import java.io.BufferedWriter; import java.io.File; @@ -35,6 +37,9 @@ public StorageCleaner(Storage storage) { int value = initialiseCleaner(); if (value != -1) { this.numberOfActivitiesToClean = value; + } else { + Log.makeInfoLog("Problem initialising cleaner"); + Ui.printDivider("There is a problem initialising cleaner, please remove the status file"); } } @@ -56,7 +61,7 @@ public void setNumberOfActivitiesToClean(int value) throws IOException { } else { writer.write("0" + "\n"); } - writer.write(Integer.toString(value) + "\n"); + writer.write(value + "\n"); writer.close(); } @@ -70,7 +75,6 @@ public void storageAutoClean() throws IOException { List activitiesLeftInData = new ArrayList<>(); if (this.toClean) { File liveData = recycleData(activitiesForRecycling, activitiesLeftInData); - BufferedWriter recycledDataWriter = new BufferedWriter(new FileWriter(recycledData)); for (String line : activitiesForRecycling) { recycledDataWriter.write(line + "\n"); @@ -92,7 +96,7 @@ public void storageAutoClean() throws IOException { * @throws FileNotFoundException if file could not be found at the filepath. */ private File recycleData(List activitiesForRecycling, List activitiesLeftInData) - throws FileNotFoundException { + throws IOException { String filePath = storage.dataFilePath; File liveData = new File(filePath); Scanner recycledDataScanner = new Scanner(recycledData); From 8a1f143e761949bba81705bb6e267da6f2f0cc79 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Tue, 7 Apr 2020 23:48:24 +0800 Subject: [PATCH 281/415] Refine code quality of cleaners --- src/main/java/jikan/Jikan.java | 2 +- src/main/java/jikan/cleaner/LogCleaner.java | 5 +- .../java/jikan/cleaner/StorageCleaner.java | 49 ++++++++++--------- src/main/java/jikan/parser/Parser.java | 7 +-- 4 files changed, 31 insertions(+), 32 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 11660251d..d3f671597 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -70,7 +70,7 @@ public static void main(String[] args) { while (true) { try { - Command command = parser.parseUserCommands(in, activityList, storageCleaner, tagFile); + Command command = parser.parseUserCommands(in, tagFile); if (command == null) { continue; } diff --git a/src/main/java/jikan/cleaner/LogCleaner.java b/src/main/java/jikan/cleaner/LogCleaner.java index bc5d75b3f..18932a537 100644 --- a/src/main/java/jikan/cleaner/LogCleaner.java +++ b/src/main/java/jikan/cleaner/LogCleaner.java @@ -101,10 +101,7 @@ private File recycleLog(List logsForRecycling, List logsLeftInDa String line = recycledDataScanner.nextLine(); logsForRecycling.add(line); } - while (numberOfLogsToClean != 0) { - if (!liveDataScanner.hasNext()) { - break; - } + while (numberOfLogsToClean != 0 && liveDataScanner.hasNext()) { String line = liveDataScanner.nextLine(); logsForRecycling.add(line); numberOfLogsToClean -= 1; diff --git a/src/main/java/jikan/cleaner/StorageCleaner.java b/src/main/java/jikan/cleaner/StorageCleaner.java index 569079ea6..43e20368b 100644 --- a/src/main/java/jikan/cleaner/StorageCleaner.java +++ b/src/main/java/jikan/cleaner/StorageCleaner.java @@ -90,52 +90,57 @@ public void storageAutoClean() throws IOException { /** * Method to clean up data file and move them to the recycled folder. - * @param activitiesForRecycling an array list consisting of data to be written to recycled folder. - * @param activitiesLeftInData an array list consisting of the data left after clean up. + * @param listForRecycling an array list consisting of data to be written to recycled folder. + * @param listLeftInData an array list consisting of the data left after clean up. * @return a storage file that holds the activity list at run time. * @throws FileNotFoundException if file could not be found at the filepath. */ - private File recycleData(List activitiesForRecycling, List activitiesLeftInData) - throws IOException { + private File recycleData(List listForRecycling, List listLeftInData) throws IOException { String filePath = storage.dataFilePath; File liveData = new File(filePath); Scanner recycledDataScanner = new Scanner(recycledData); Scanner liveDataScanner = new Scanner(liveData); while (recycledDataScanner.hasNext()) { String line = recycledDataScanner.nextLine(); - activitiesForRecycling.add(line); + listForRecycling.add(line); } - parseLiveData(activitiesForRecycling, activitiesLeftInData, liveDataScanner); + parseLiveData(listForRecycling, listLeftInData, liveDataScanner); return liveData; } /** * Method to check the activities in storage line by line and see if they should be cleaned or not. - * @param activitiesForRecycling an array list consisting of data to be written to recycled folder. - * @param activitiesLeftInData an array list consisting of the data left after clean up. - * @param liveDataScanner used to scan the activities in storage line by line. + * @param listForRecycling an array list consisting of data to be written to recycled folder. + * @param listLeftInData an array list consisting of the data left after clean up. + * @param liveDataSc used to scan the activities in storage line by line. */ - private void parseLiveData(List activitiesForRecycling, List activitiesLeftInData, - Scanner liveDataScanner) { - while (numberOfActivitiesToClean != 0) { - if (!liveDataScanner.hasNext()) { - break; - } - String line = liveDataScanner.nextLine(); + private void parseLiveData(List listForRecycling, List listLeftInData, Scanner liveDataSc) { + cleanUpActivities(listForRecycling, listLeftInData, liveDataSc); + while (liveDataSc.hasNext()) { + String line = liveDataSc.nextLine(); + listLeftInData.add(line); + } + } + + /** + * Checks and clean up completed activities. + * @param listForRecycling an array list consisting of data to be written to recycled folder. + * @param listLeftInData an array list consisting of the data left after clean up. + * @param liveDataSc used to scan the activities in storage line by line. + */ + private void cleanUpActivities(List listForRecycling, List listLeftInData, Scanner liveDataSc) { + while (numberOfActivitiesToClean != 0 && liveDataSc.hasNext()) { + String line = liveDataSc.nextLine(); String[] tokenizedLine = line.split(","); Duration duration = Duration.parse(tokenizedLine[3]); Duration allocatedTime = Duration.parse(tokenizedLine[4]); int result = duration.compareTo(allocatedTime); if (result >= 0 && allocatedTime != Duration.parse("PT0S")) { - activitiesForRecycling.add(line); + listForRecycling.add(line); numberOfActivitiesToClean -= 1; } else { - activitiesLeftInData.add(line); + listLeftInData.add(line); } } - while (liveDataScanner.hasNext()) { - String line = liveDataScanner.nextLine(); - activitiesLeftInData.add(line); - } } } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 444ede582..9d90b7477 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -2,7 +2,6 @@ import jikan.exception.ExtraParametersException; import jikan.log.Log; -import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; import jikan.cleaner.StorageCleaner; import jikan.ui.Ui; @@ -60,11 +59,9 @@ public class Parser { * Parses user commands to relevant functions to carry out the commands. * * @param scanner scanner object which reads user input - * @param activityList the list of activities */ - public Command parseUserCommands(Scanner scanner, ActivityList activityList, StorageCleaner cleaner, - File tagFile) throws - EmptyNameException, NullPointerException, ArrayIndexOutOfBoundsException { + public Command parseUserCommands(Scanner scanner, File tagFile) throws EmptyNameException, + NullPointerException, ArrayIndexOutOfBoundsException { makeInfoLog("Starting to parse inputs."); String userInput = scanner.nextLine(); From c06cd929acde90fa2402ab69c1e4b560fd3f4c87 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Wed, 8 Apr 2020 12:54:44 +0800 Subject: [PATCH 282/415] Code quality improvements and debugging for clean command. --- src/main/java/jikan/cleaner/Cleaner.java | 2 +- src/main/java/jikan/command/CleanCommand.java | 415 ++++++++++++------ src/main/java/jikan/command/StartCommand.java | 2 +- .../exception/NegativeNumberException.java | 4 + 4 files changed, 298 insertions(+), 125 deletions(-) create mode 100644 src/main/java/jikan/exception/NegativeNumberException.java diff --git a/src/main/java/jikan/cleaner/Cleaner.java b/src/main/java/jikan/cleaner/Cleaner.java index e0a7fbec1..70b63c814 100644 --- a/src/main/java/jikan/cleaner/Cleaner.java +++ b/src/main/java/jikan/cleaner/Cleaner.java @@ -11,7 +11,7 @@ public abstract class Cleaner { protected String dataFilePath; protected File status; protected File recycledData; - /** toClean acts as a switch to switch on/off the cleaner */ + /** toClean acts as a switch to switch on/off the cleaner. */ public boolean toClean; private static final int DEFAULT_LINES_TO_CLEAN = 5; diff --git a/src/main/java/jikan/command/CleanCommand.java b/src/main/java/jikan/command/CleanCommand.java index f8bc9320d..08b0a1991 100644 --- a/src/main/java/jikan/command/CleanCommand.java +++ b/src/main/java/jikan/command/CleanCommand.java @@ -2,6 +2,7 @@ import jikan.log.Log; import jikan.activity.ActivityList; +import jikan.exception.NegativeNumberException; import jikan.exception.InvalidCleanCommandException; import jikan.cleaner.LogCleaner; import jikan.cleaner.StorageCleaner; @@ -16,6 +17,8 @@ public class CleanCommand extends Command { StorageCleaner storageCleaner; LogCleaner logCleaner; + private boolean toCleanStorage; + private boolean toCleanLog; /** * Constructor to create a new clean command. @@ -26,164 +29,330 @@ public CleanCommand(String parameters, StorageCleaner cleaner, LogCleaner logCle this.logCleaner = logCleaner; } - /** - * Method to enable or disable cleaning of log files. - */ @Override public void executeCommand(ActivityList activityList) { - String function = ""; + boolean isEmpty = isParameterEmpty(); + if (isEmpty) { + stopExecution(); + } else { + continueExecution(); + } + } + + /** + * Method to check if user input is empty for clean command. + * @return true if is empty and false otherwise. + */ + private boolean isParameterEmpty() { + String parametersTrimmed = this.parameters.trim(); + if (parametersTrimmed.isEmpty()) { + return true; + } else { + return false; + } + } + + /** + * Stops execution when user input is empty. + */ + private void stopExecution() { + Log.makeInfoLog("Clean command received empty parameters"); + Ui.printDivider("No valid parameters to clean command found."); + } + + /** + * Method to continue execution given a non empty user input. + */ + private void continueExecution() { + toCleanLog = false; + toCleanStorage = false; + String parametersTrimmed = this.parameters.trim(); + assert !parametersTrimmed.isEmpty(); try { - function = getFunctionFromCommand(); + String firstWord = getFirstWord(parametersTrimmed); + processCommand(firstWord); } catch (InvalidCleanCommandException e) { - Ui.printDivider("Invalid clean command!"); + Log.makeInfoLog("Invalid clean command"); + Ui.printDivider("Invalid format received for clean command."); + } + + } + + /** + * Method to extract first word for a given line. + * @param line a string representing a line of information. + * @return the first word of the line. + */ + private String getFirstWord(String line) { + int delimiter = line.indexOf(" "); + String word; + if (delimiter == -1) { + return line; + } else { + word = line.substring(0, delimiter); + return word; } - switch (function) { + } + + /** + * Method that parses in a word and remove the word from the this.parameters string. + * @param word a word to remove. + * @return a this.parameters string without the word. + */ + private String getRemainingParameter(String word) { + int index = this.parameters.indexOf(word); + int number = word.length(); + String remainingParameter = this.parameters.substring(index + number); + remainingParameter = remainingParameter.trim(); + return remainingParameter; + } + + /** + * Check if we are dealing with storage or log cleaner. + * @param firstWord indicative of whether the user is dealing with logs or storage. + * @throws InvalidCleanCommandException when the format of user input is wrong. + */ + private void processCommand(String firstWord) throws InvalidCleanCommandException { + assert !toCleanLog && !toCleanStorage; + if (firstWord.equals("log")) { + toCleanLog = true; + processLogCommand(); + } else { + toCleanStorage = true; + handleCase(firstWord); + } + } + + /** + * Handle the different functions on a case by case basis. + * @param firstWord indicative of the function being called. + * @throws InvalidCleanCommandException when the format of user input is wrong. + */ + private void handleCase(String firstWord) throws InvalidCleanCommandException { + switch (firstWord) { case "on": - try { - handleOnFunction(); - } catch (IOException e) { - String line = "There is a problem with accessing the cleaning file"; - Ui.printDivider(line); - } + handleOnFunction(); break; case "off": - try { - handleOffFunction(); - } catch (IOException e) { - String line = "There is a problem with accessing the cleaning file"; - Ui.printDivider(line); - } + handleOffFunction(); break; case "/n": - try { - handleSetFunction(); - } catch (NumberFormatException n) { - Ui.printDivider("please provide a number"); - } catch (IOException e) { - String line = "There is a problem with accessing the cleaning file"; - Ui.printDivider(line); - } + handleSetFunction(); break; default: - break; + throw new InvalidCleanCommandException(); } } - private void handleOnFunction() throws IOException { - String line = this.parameters; - if (line.contains("log")) { - logCleaner.setStatus(true, logCleaner.numberOfLogsToClean); - assert logCleaner.toClean; - line = "Auto cleaning enabled for logs"; - Ui.printDivider(line); - Log.makeInfoLog("User has turned on automated cleaning for logs"); + /** + * Use to process log commands, thus all the function called in this method + * will only deal with log cleaner. + * @throws InvalidCleanCommandException when the format of user input is wrong. + */ + private void processLogCommand() throws InvalidCleanCommandException { + String remainingCommand = getRemainingParameter("log"); + if (remainingCommand.isEmpty()) { + throw new InvalidCleanCommandException(); } else { + String firstWord = getFirstWord(remainingCommand); + handleCase(firstWord); + } + } + + /** + * A general purpose function to handle the "on" command. + * @throws InvalidCleanCommandException when the format of user input is wrong. + */ + private void handleOnFunction() throws InvalidCleanCommandException { + String remainingParameter = getRemainingParameter("on"); + if (remainingParameter.isEmpty()) { + setStatusOn(); + } else { + throw new InvalidCleanCommandException(); + } + } + + /** + * Forwards the "on" command to the appropriate cleaner (either storage or log cleaner). + */ + private void setStatusOn() { + assert !toCleanStorage || !toCleanLog; + if (toCleanStorage) { + setStorageCleanerOn(); + } else if (toCleanLog) { + setLogCleanerOn(); + } + } + + /** + * Method to switch on the storage cleaner. + */ + private void setStorageCleanerOn() { + try { storageCleaner.setStatus(true, storageCleaner.numberOfActivitiesToClean); - assert storageCleaner.toClean; - line = "Auto cleaning enabled"; - Ui.printDivider(line); - Log.makeInfoLog("User has turned on automated cleaning"); + } catch (IOException e) { + Ui.printDivider("Error in loading/writing to storage status file"); + Log.makeInfoLog("Error in accessing the storage status file"); } + assert storageCleaner.toClean; + Ui.printDivider("Auto cleaning enabled for storage."); + Log.makeInfoLog("User has turned on automated cleaning for storage."); } - private void handleOffFunction() throws IOException { - String line = this.parameters; - if (line.contains("log")) { - logCleaner.setStatus(false, logCleaner.numberOfLogsToClean); - assert !logCleaner.toClean; - line = "Auto cleaning disabled for logs"; - Ui.printDivider(line); - Log.makeInfoLog("User has turned off automated cleaning for logs"); + /** + * Method to switch on the log cleaner. + */ + private void setLogCleanerOn() { + try { + logCleaner.setStatus(true, logCleaner.numberOfLogsToClean); + } catch (IOException e) { + Ui.printDivider("Error in loading/writing to log status file"); + Log.makeInfoLog("Error in accessing the log status file"); + } + assert logCleaner.toClean; + Ui.printDivider("Auto cleaning enabled for logs."); + Log.makeInfoLog("User has turned on automated cleaning for logs."); + } + + /** + * A general purpose function to handle the "off" command. + * @throws InvalidCleanCommandException when the format of user input is wrong. + */ + private void handleOffFunction() throws InvalidCleanCommandException { + String remainingParameter = getRemainingParameter("off"); + if (remainingParameter.isEmpty()) { + setStatusOff(); } else { + throw new InvalidCleanCommandException(); + } + } + + /** + * Forwards the "off" command to the appropriate cleaner (either storage or log cleaner). + */ + private void setStatusOff() { + assert !toCleanStorage || !toCleanLog; + if (toCleanStorage) { + setStorageCleanerOff(); + } else if (toCleanLog) { + setLogCleanerOff(); + } + } + + /** + * Method to switch off the storage cleaner. + */ + private void setStorageCleanerOff() { + try { storageCleaner.setStatus(false, storageCleaner.numberOfActivitiesToClean); - assert !storageCleaner.toClean; - line = "Auto cleaning disabled"; - Ui.printDivider(line); - Log.makeInfoLog("User has turned off automated cleaning"); - } - } - - private void handleSetFunction() throws IOException, NumberFormatException { - String line = this.parameters; - if (line.contains("log")) { - try { - int value = getNumberFromCommand(line); - if (value > 0) { - logCleaner.setNumberOfLogsToClean(value); - line = "Number of activities to clean is set to " + value; - Ui.printDivider(line); - } else { - Ui.printDivider("Please provide a positive number"); - } - } catch (NumberFormatException | IndexOutOfBoundsException e) { - throw new NumberFormatException(); - } catch (IOException e) { - throw new IOException(); - } - } else { - try { - int value = getNumberFromCommand(line); - if (value > 0) { - storageCleaner.setNumberOfActivitiesToClean(value); - line = "Number of activities to clean is set to " + value; - Ui.printDivider(line); - } else { - Ui.printDivider("Please provide a positive number"); - } - } catch (NumberFormatException | IndexOutOfBoundsException e) { - throw new NumberFormatException(); - } catch (IOException e) { - throw new IOException(); - } + } catch (IOException e) { + Ui.printDivider("Error in loading/writing to storage status file"); + Log.makeInfoLog("Error in accessing the storage status file"); } + assert !storageCleaner.toClean; + Ui.printDivider("Auto cleaning disabled for storage."); + Log.makeInfoLog("User has turned off automated cleaning for storage."); } /** - * Method to check the required function from user command. - * @return the appropriate function ("on","off","/n"). - * @throws InvalidCleanCommandException when the function is not recognised. + * Method to switch off the log cleaner. */ - private String getFunctionFromCommand() throws InvalidCleanCommandException { - String line = this.parameters; - if (line.contains("on")) { - if (!line.contains("off") && !line.contains("/n")) { - return "on"; - } else { - throw new InvalidCleanCommandException(); - } - } else if (line.contains("off")) { - if (!line.contains("on") && !line.contains("/n")) { - return "off"; - } else { - throw new InvalidCleanCommandException(); - } - } else if (line.contains("/n")) { - if (!line.contains("on") && !line.contains("off")) { - return "/n"; - } else { - throw new InvalidCleanCommandException(); - } - } else { + private void setLogCleanerOff() { + try { + logCleaner.setStatus(false, logCleaner.numberOfLogsToClean); + } catch (IOException e) { + Ui.printDivider("Error in loading/writing to log status file"); + Log.makeInfoLog("Error in accessing the log status file"); + } + assert !logCleaner.toClean; + Ui.printDivider("Auto cleaning disabled for logs."); + Log.makeInfoLog("User has turned off automated cleaning for logs."); + } + + /** + * A general purpose function to handle the "/n" command. + * @throws InvalidCleanCommandException when the format of user input is wrong. + */ + private void handleSetFunction() throws InvalidCleanCommandException { + String remainingParameter = getRemainingParameter("/n"); + if (remainingParameter.isEmpty()) { throw new InvalidCleanCommandException(); + } else { + setValue(remainingParameter); } } /** - * Method to extract the number of activities to clean from user input. - * @param line full user input with command header extracted out. - * @return the number of activities to clean. + * Forwards the "/n" command to the appropriate cleaner (either storage or log cleaner). + * @param remainingParameter a string with information on the value to set to. + * @throws InvalidCleanCommandException when the format of user input is wrong. */ - private int getNumberFromCommand(String line) { - int index = line.indexOf("/n"); + private void setValue(String remainingParameter) throws InvalidCleanCommandException { + assert !toCleanStorage || !toCleanLog; + if (toCleanStorage) { + setValueForStorage(remainingParameter); + } else if (toCleanLog) { + setValueForLogs(remainingParameter); + } + } + + /** + * Method to set a value for storage cleaner. + * @param remainingParameter a string with information on the value to set to. + * @throws InvalidCleanCommandException when the format of user input is wrong. + */ + private void setValueForStorage(String remainingParameter) throws InvalidCleanCommandException { + try { + int value = getNumber(remainingParameter); + storageCleaner.setNumberOfActivitiesToClean(value); + Ui.printDivider("Number of activities to clean is set to " + value); + Log.makeInfoLog("Storage Cleaner set to " + value); + } catch (NegativeNumberException e) { + Ui.printDivider("Please provide a positive number."); + Log.makeInfoLog("Negative number given in clean command"); + } catch (IOException e) { + Ui.printDivider("Error in loading/writing to status file"); + Log.makeInfoLog("Error in accessing the status file"); + } + } + + /** + * Method to set a value for log cleaner. + * @param remainingParameter a string with information on the value to set to. + * @throws InvalidCleanCommandException when the format of user input is wrong. + */ + private void setValueForLogs(String remainingParameter) throws InvalidCleanCommandException { try { - String numberString = line.substring(index + 3); - try { - return Integer.parseInt(numberString); - } catch (NumberFormatException n) { - throw new NumberFormatException(); + int value = getNumber(remainingParameter); + logCleaner.setNumberOfLogsToClean(value); + Ui.printDivider("Number of logs to clean is set to " + value); + Log.makeInfoLog("Log Cleaner set to " + value); + } catch (NegativeNumberException e) { + Ui.printDivider("Please provide a positive number."); + Log.makeInfoLog("Negative number given in clean command"); + } catch (IOException e) { + Ui.printDivider("Error in loading/writing to status file"); + Log.makeInfoLog("Error in accessing the status file"); + } + } + + /** + * Method to convert the parameter numberString to an integer. + * @param numberString a string that represents the value to set to. + * @return an integer numberString. + * @throws InvalidCleanCommandException when the format of user input is wrong. + * @throws NegativeNumberException when the numberString is negative. + */ + private int getNumber(String numberString) throws InvalidCleanCommandException, NegativeNumberException { + try { + int value = Integer.parseInt(numberString); + if (value < 0) { + throw new NegativeNumberException(); + } else { + return value; } - } catch (IndexOutOfBoundsException e) { - throw new IndexOutOfBoundsException(); + } catch (NumberFormatException e) { + throw new InvalidCleanCommandException(); } } } diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index d0ff74824..b90386c50 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -261,7 +261,7 @@ private void addActivityWithBothField(String durationInfo, String tagInfo, Strin } /** - * Check if allocated time and tags are formatted correctly/not empty + * Check if allocated time and tags are formatted correctly/not empty. * @param durationInfo information about the duration. * @param tagInfo information about the tag. * @param activityName the string representing activity name. diff --git a/src/main/java/jikan/exception/NegativeNumberException.java b/src/main/java/jikan/exception/NegativeNumberException.java new file mode 100644 index 000000000..d54ea2454 --- /dev/null +++ b/src/main/java/jikan/exception/NegativeNumberException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class NegativeNumberException extends Exception { +} From d347fb3c6e152bc4191cd2c2ffcd0ad577ac2bb3 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Wed, 8 Apr 2020 12:54:54 +0800 Subject: [PATCH 283/415] Update text-ui-test --- text-ui-test/EXPECTED.TXT | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 0980b0af6..fa9380a9b 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -39,28 +39,28 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Allocation | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Allocation | Date -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Allocation | Date -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Allocation | Date -1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag1] +1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ There is already an activity with this name. Would you like to continue it? @@ -74,9 +74,9 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Allocation | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Please input an integer for the time interval. @@ -86,7 +86,7 @@ If you'd like to graph by tags, enter the command . Please specify whether you want to graph activities / tags / targets. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Activity name cannot be empty! +Start command cannot be empty ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ You have not started any activity! @@ -112,8 +112,8 @@ You have deleted activity 2 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Allocation | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] -2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] +2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Bye! See you again. From 1ae004b7a9fc36d4e2511749e0e76a7de64e6b91 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 8 Apr 2020 13:26:28 +0800 Subject: [PATCH 284/415] fixed filter parameter issue #184 --- src/main/java/jikan/command/FilterCommand.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index c63d757c2..374a37d1a 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -45,7 +45,9 @@ private void filterFullList(ActivityList activityList) { } else { lastShownList.activities.clear(); String[] keywords = query.split(" "); - + if (keywords.length < 1 ){ + throw new EmptyQueryException(); + } for (String keyword : keywords) { populateLastShownList(activityList, lastShownList, keyword); } @@ -69,7 +71,9 @@ private void filterSubList() { } else { lastShownList.activities.clear(); String[] keywords = query.split(" "); - + if (keywords.length < 1 ){ + throw new EmptyQueryException(); + } for (String keyword : keywords) { populateLastShownList(prevList, lastShownList, keyword); } From 579a46f21344a704dfa71cdeed37bffb50599c8b Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 8 Apr 2020 13:30:50 +0800 Subject: [PATCH 285/415] fixed Over 100% completion rate #170 --- src/main/java/jikan/activity/Activity.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 02d3c7530..1805a386f 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -104,7 +104,7 @@ public void setAllocatedTime(Duration allocatedTime) { */ public double getProgressPercent() { double percent = ((double)this.duration.toMillis() / this.allocatedTime.toMillis()) * 100; - return percent; + return Math.min(percent, 100); } /** From 418014b863030d636efdbc2e5c8c4554848762a6 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 8 Apr 2020 13:33:37 +0800 Subject: [PATCH 286/415] Fixed Unknown character in Error message #160 --- src/main/java/jikan/parser/Parser.java | 2 +- src/main/java/jikan/ui/Ui.java | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 268d8918e..4e1d48de5 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -186,7 +186,7 @@ public Command parseUserCommands(Scanner scanner, ActivityList activityList, Sto * Method to parse user inputs that are not recognised. */ private void parseDefault() { - String line = "☹ OOPS!!! I'm sorry, but I don't know what that means :-("; + String line = "OOPS!!! I'm sorry, but I don't know what that means :-("; makeInfoLog("Invalid command entered"); Ui.printDivider(line); } diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index 20aec0247..f860c79de 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -202,9 +202,7 @@ public static void printGoals(HashMap tagsGoals, HashMap Date: Wed, 8 Apr 2020 13:34:08 +0800 Subject: [PATCH 287/415] Update UG graph and chaining section --- docs/UserGuide.md | 46 ++++++++++++++++------- docs/pictures/filter-find_chain.PNG | Bin 0 -> 24966 bytes docs/pictures/filter-graph_chain.PNG | Bin 0 -> 14505 bytes docs/pictures/find-allocations_chain.PNG | Bin 0 -> 14167 bytes docs/pictures/list-graphtags_chain.PNG | Bin 0 -> 13532 bytes docs/pictures/list_filter_chain.PNG | Bin 0 -> 17940 bytes 6 files changed, 33 insertions(+), 13 deletions(-) create mode 100644 docs/pictures/filter-find_chain.PNG create mode 100644 docs/pictures/filter-graph_chain.PNG create mode 100644 docs/pictures/find-allocations_chain.PNG create mode 100644 docs/pictures/list-graphtags_chain.PNG create mode 100644 docs/pictures/list_filter_chain.PNG diff --git a/docs/UserGuide.md b/docs/UserGuide.md index e0fe29fea..0a5842f30 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -138,9 +138,7 @@ By using `find` and `filter` commands, users can reduce clutter and zoom-in to s Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on their needs. This sublist is generated based on the previously shown list and also works after a `list` command. This is can be particularly useful when the user wants to generate a graph. -**Sample Use Case:** The user can chain a `list month MONTH` for a specfic date range, followed by `filter -s TAGNAME` for a specific tag and finally `find -s KEYWORD1 / KEYWORD2` for specfic activities containing either keyword. - -This flag applies to `find` and `filter` commands only. +Note: This flag applies to `find` and `filter` commands only. **Format:** * `find -s KEYWORD` @@ -148,6 +146,10 @@ This flag applies to `find` and `filter` commands only. * `filter -s TAGNAME1 TAGNAME2` * `find -s KEYWORD1 / KEYWORD2 / KEYWORD3` +**Example:** +![chain graph activities](./pictures/filter-find_chain.PNG) +If we want to find all CS2106 tutorials, we can first use `filter 2106` to filter out all activities tagged `2106`, then use the find command with the flag, `find -s Tutorial` to get a list of all 2106 Tutorials. + ## Graphs By using the following commands, users can get a visual representation of the time spent on each activity and their current progress. The 3 types of graphs are : @@ -155,30 +157,48 @@ The 3 types of graphs are : * *Tags time graph* - Total time spent on each tag: `graph tags` * *Activity targets graph* - Progress of each activity in relation to its targeted time: `graph targets` -Tip: Use `find` and `filter` commands to reduce clutter before graphing as the graphs are based on the last shown list of activities. +Tip: Use `find`, `filter` and `list` commands to reduce clutter before graphing as the graphs are based on the last shown list of activities. -### Activity time graph: `graph` +### Activity time graph: `graph activities` **Usage:** View a comparison of the absolute time spent on each activity in the last shown list. The parameter `SCALE` refers to the number of minutes represented by each point on the graph. -**Format:** `graph SCALE` +**Format:** +`graph activities SCALE` -**Example:** `graph 10` +**Example:** +`graph activities 10` -### Tags time graph: `graph tag` +### Tags time graph: `graph tags` **Usage:** View a comparison of the absolute time spent on each tag in the last shown list. -**Format:** `graph tag` +**Format:** +`graph tags SCALE` ### Activity targets graph: `graph targets` -**Usage:** View the progress of activities in relation to their -targeted time. +**Usage:** View the progress of activities to see how much time was spent on the activity relative to the time that was allocated. Note: Only activities with an `ALLOCATED_TIME` will be shown. -**Format:** `graph targets` +**Format:** +`graph allocations` + +### Chaining `list`, `find` and `filter` with `graph` command: +Using `list`, `find` and `filter` commands you can sieve out the information you wish to be graphed. + +**Graph Activities Example:** +![chain graph activities](./pictures/filter-graph_chain.PNG) +`filter 2113` gives all activities tagged `2113`, then we can use `graph activities 5` to view a graph of the duration for each activity. Each asterisk represents 5 minutes, as indicated by the `SCALE` parameter of the graph command. + +**Graph Tags Example:** +![chain graph tags](./pictures/list-graphtags_chain.PNG) +`list 25/03/2020` gives all activities completed on 25th March 2020, then we can use `graph tags 5` to view the graph of the tags. From this, it is easy to tell that the user spent more time on CS2105 than CS2106 that day. + +**Graph Allocations Example:** +![chain graph tags](./pictures/find-allocations_chain.PNG) +`find Lab` gives us all 'Lab' activities, then we can use `graph allocations` to view the progress bar of each of the activities to see how much time was spent on the activity relative to the time that was allocated. + -![Continue command sequence diagram](./pictures/GraphTargets.png) ## Tag Goals diff --git a/docs/pictures/filter-find_chain.PNG b/docs/pictures/filter-find_chain.PNG new file mode 100644 index 0000000000000000000000000000000000000000..e1f5bb226ea9b63094cbc3be31a160f5e2c9e0cf GIT binary patch literal 24966 zcmdSB2~-o?wl0ji_jW5HHV7!)77;{1M1g>GDk4M#R8XW#1VqHp2ZRs^c7XH((g#rK zM4CtwdJ?4-fkfKSM+hYJ0RjXF39q7ipL6!T_kaI=XWa3||2uG0Qk7M;s@7WboAaCB ztk4_A`h0tj?d9R&;R737xy8e?3(Ui_Q~LMcfIYzlpOL_32mF@)Wu78}=rr)<7spFR zmw0%Jqj|S%e+9npaW}Al^Y9$<;{M+;`ar^$hsRa~eC3jvFJykiD511E_Wc+-L1x0X zC+#UxC9K=0=IYHzx8GIvK!4vOdg#zEw=ND&unL+kXr!rq<3BF&cp(4<0nW?wl>f9wICJSn~0HZ5NE3`tK-92`Et2( z3&Mtp!;9vfH=8UJq!eh}t4?)UNU@PxoEo17*NCM{WL5Cftg!SOr$!;s+u@4)3TvaA zI`6JGUC!&lH?hKk?g?jfNOC*>BpfFRR$Z-Ddw6hfSfSg?tT*dDmu+1{$3YjvIfX~A zz;`5U?*o4K{UM*;t*wMB?CC`9QF2lvAIiVZ@|QwEOQ(pfFZR^Horx$U<4kjo&URb_ zWhgJ+t*X94uZ@lbnF)Z0MhdMNTL%Wq)f`Xv-x<1ll-yekwBY%cUuR&c zfEw-FMicHlEM!|`V8znOpA3+}mz_&5Mg(51P{Z_7x2$rP`(NW!c5(ZbTW4?%l^G+T zrt9Hug1g;{cRI=&Zv-ctpHA17n0I5<~IiEvjR~3g4~iB>P#;jD2TCfl0Po z$TCVj;4pVdyeTR+SY|!oe&o>xo5nO|1aK!v+HY zsb2kuh5L`w27IKkX{+$S<_u1PO+er%R7Xb#Gem*8XO@}2~xYVq$-)evyVPJk~*=c@5 zjYtX*&S(I3vv=`)3VCC&X(S@DJ1k45HhZ(o=w#|}_&EWvcx50D4>VYE8sy?EdMcK) zm@w0=8t?3>7$&)g=Si%6xD>*rf6iE+le5IEXqkoj-!P%Y+hZDwzf!(nnv8D|>xl>8_0)Frt)1Mtx`-Ox3xFZ@zd`B>!>Bba;5yAD)R_-VIS3O?|fbv0EgnQmI{HU4(wV zsaSX@tyaeM94cSyL{)lJd_(%6Dw5a29 z&KxVcJyqie<)n9xV}0Fd(B<-mJ85k#${;vATSC``!}U!op}UPBeyOk*UH4M zYfzL=yInMPCN{ImK}N>&odMUWKFD3SA5r>N9ZtMi+Ci^%$l*6#D}_k zY||SG`3kBt;*jbUN~Dqbfl}!LGMu$CA|h=?K~KDnO>=x?f-3BssdXJl@+tO?K1!9# za0J%v@Fl%lzVCxgG#Mwz2MV>+B0a9xOS>F&EZ(7>uk}1~*2OIaJ(vlyXx*Zwo@fw` zI<^^q-bL6Ep+T1S5X@*aWbujMgXWitS8SX|!{hwOxog*hTK%4u3p#!qNnhNwbDsDz z-i&nL41g97`ndHAG+VU17gTZ@x<0Q&eBRq!8y*RlXH1T|^6*4?Ka45kd>3=p20EeI z)G^zf(TFCcKcx5#rAp_nO&M9A!(YI8?9)#`1$+a6-x?f)nCdT`%Xg-n&~f{D`AFow zs8VmtU5ayF(?B&!uU2A+H+$1tff+oYrhN`WSuJ_?zWl*Vtw_?Kefn;>w%WO*nnC}n z3K5G+X9A7Y3|%|9AYCf0)7l%DMUf zc6_%0{5p)gc6uE z_9}zHsJ1C&IJP^9)=XFGP-asm(I%@-%-@I(JVI;wVOg}9^*ruI9k_G9q9b2PjGrlk-a-LaHCetT<`Qnjq45xv%AhWwGE} zQ0&W+_d7FMkqnh}W+mGdXDa1gFxIISd`r~jh?)R6cRfpU60!f&fP`FZv$vVT*KEDp z5L4*(tchGUACsgjxU^ogu@$K%u_W~yu5m{yX3Kk{v~Vt~31%;zZ?y567~U^8d$oTh zkDO<}(Xqzz35Q(?_w|cB77-v!F%C=+jN&o*a)+ z9^#HJ)OJd``Vo7b9+r7asdlhi07bJd(Ax&TS?6&%-7oSuFjPo(og`SWS-55KUTnzM zvX?WeQoR1+__aL=lgEF5BS(%K?&<0{>V#cg!(&hi5Id*xHH) z-j#o~6qh|VJdrf|e(06_;sw+?O>dw2-H07=Csd&WvpIa3PKU9@uGiZ|O0bdcPS?8_ zBcOVSAJyyQoUSO-4u9G{X;Fff9ZnX}f}f@ruIk|zl!9$V1(hbgSM7T<=OzeVW_&y= z9sbDrWvR(;al2o->Xy8kUEjd+%=N|5!;S8|+OCRpYN)J2s1%4CPKuu!H*%JDAx4vS-Gl^>1WdRzQiHh6c;Nxkk~dSsNkLZpon3Ek}82tWEsJTMDb_qYGU zy64|OX|+$Up3UVs6Ct_h6YV$|unBeIRDn-H0VY44W|=nz+^B*l2ynrGe*$4r+|7+s zvE0qYxBt6?8|jjv+m3GE>3{rr+7-Vf(|cEAe)-OLMJF|&AwNyh*-V4Y--xVP8ja=+ zoA>wM_8QJu^8RkR^adwR1)6lvE+v_UE{(#s{6FVV5a#n@``5t2-bcXO;uVZTZ)7|e zFN~sslWutpLvtr@xWyJ@E6|F`(uvA0QXmi5nlzgo4a7cOhcxmiwF)@U!W=TY99De84I*!|yEtRHF1K?+x1HKj&yN}9@<$H59z}QqK zk9eqtW$1~FFZTmFF+md|s57FIS8mfLz!zj(MH_sj5)&n}mNgVKFt|T_r2`QjzgYw3 zZMtshxTer*0{pdXhC&6>n4R2Ukx z8&}Fb)G!*=)#bp_OT2p$pddr{ zn=V7REQN9l-;+9I$+3G{8`_h1{O=N&c?2V1pzIprsq^8HLJOVM|3vd1w~7o36ccM9uaDKrW*?{G&tQvJmjX(TyNRc{7g@9r?-H~ z<7+5P70)BT1tkPMY4-rj`+A$Y*hF0C#&K)TjpNP_3SghU@7nCm&gFAlV}BrBcxEm# zeigAaJU9eA9ThQ;E)`qMAfyfG#aa|NwDGJpUKJX8jcf$JIlw4b>vYO^Vfe=2)>fF5 z?yYJ8u*cJO!BM-^Ad_XoEozha*{QEg_Y7Lb^_*0JHud=~QF$ngeC+Hd8|A(6bH;vC z$-U|Sph&CqdH^%5^n;c$yUO`sQH_6Kl@^O6*yLgiD#BlY4&rdR@PlgxlS_H4N{ue* zr>*zu#Y(njAF>j}-rBbFBvp%z<_f*6&(%uT>ymVR+fjdf1GKrna;lyAs%?fH#Om`T zNTFf1bRqulNx9i7Z$B1W)+G4gjaT*Hn;oPJ@nyPL7^XiOtMwv}4)NHRGG5^NRpAk` zFaQ=Fx{{k)xGS`{1h3RivI@v>N(mqIv#u*|(B6~SX(kmU0>9oq_t5AXFJLPQn?qaG z#B>u3p!uyE+Mw+$yE7kiPDI{~dB6{zQ10SB(|n zs1Yq5g>T2)f|#Tp^)@?G{IpeV|J5+o$((CJl8d|G*MtEu}SN4>0Nt(^Z*3@iviONyFHtq?nm#3_+9w0HV+|e(-_!MKV#;k=k==4JMx32aH0i zN^{Hx^VI!i6yLC&$+duCL%WqDV7GY5ydHwEKC!7%oW?5k1|~mTHnx7(oAY_)zETSh zPZI9LD94Sz!SQ@S#*#x!G-HFD&p3~|?4jHZtBEbM4~&JH2?~tGY$@SHH3To+iv}W~ zVLv=*g0jdsuX%BjQ-RJj164_Os+8&D*b+^8sZ7d0aPSr6;NiY@Pd(3!kd?AC1^q8Hlq%kI0a-A1OaO(BzL z-U}cFn(*XC`4=4wENxiPrz`laONMqXfWHT`_;iOXsme0!_O(L_0rapqx113BrLhMM z){W#`R#qfz@*4Yeak@E$+r_(5F6E#oQ|-z>!KI+Hw|D^n;#-?xS-x;Z*U=L{9;0zy z<*7Qs&AK~M@#Bu66@vD*3Qm*?vyubvGkrZxmRn};yCp0sF?XGvX=SdzdcFHS3LoX9 z-tz8MOSnqItYv~4gmmGuiO7$c?fnZzwP)=RlC^LoH|Io@zg5?!qX!msTY#x>2icN! z#ZGwb*Bn&S_Y_!Ecg77o^BU7Z z7ZE!4+prOSdN=PC+sZN@b(KwhKNjJo`kKwTPWvg^$!7mD3!nMhx}3zRX&tvoG`} zc1%}5X3cEikI04vKd}crdA`EI?fxuj+_Fx>^1_7E%bT;Mh0qOQqJE!F8=6X!$5~vv zAvIRGtuyQ{7~S~mqS#;2Nu7AKdc3eg&=?SW)QjjHdP3CwlfRf=<+`W9UgqCujGqnY zI&Q3Boi^gObIkv3@X^qs>tHfi=Q&IvvZ= za&7JK`pVavT4@}8rL;%#8KPe(Ph1uF6;+(#o`y!P>;Yu?*V1#^A78Bg41J2fOa~DHA7!YT=$QY z0zn;bxl9{bM>k3s*jbgzKp2mQmeToZiunEWNBuiUQlW`D7aJND*L=ThtJ2~pEpyg{ z(Fg^%uKm45b;fAZfuuZUaHM75W2$ob36Vsx+U5-kRW1?V@})}=F~80UC2Y>m^vbvj6V;$4PdE?4Fzr&;xOS{)3PfAgf3eto4^bT=e6!{0x z(gnpE>ANSB43EdxZ}ujbC%^^?V=LBah)4#8U>@2n?$n9# zomZ5L72L}nBsfs4BZ7L0meg%^!ZBmFq^e|`z;5G~WW|i@`}U}dS>SVk3yyn@dMbSj z9lYH?F@H2#^A0MC6JT8+Zi;N-w9|6ujadT3Nc=8iAnML$euYs2Y{IJQ-llundxT9| zY7D`tSmWD|QhOIr-tA7{+CKjU!rIx~tHsbliY6m04i<5OL0{7BV5zu=Yss#9D28^L zOV!=>tojpVw!iY`aX|)lCN@V;M>K7ZLuYDb0yCN>m0Wz?Sk^a|RG)j)X=g6D&r&K# z$yg{wvu_z)pw<0O>CC&$3_}j5lq_%|X4B@=_=zV6K-tD;BjP=Y$#os07b7Op4`B>E+AODa=o>i zy~X?Kd4!W3f!shDr&>j~7S!yw)XE%Yi<^m5UeDW-Y=~4-|1vS?#c-+z_#HmGcyIWe z|C~bXHTwp;r%=1Eq%hwMqPqG(CDDgA^~JMrWIj)gVW~gm)W99jJVB6qxEh4w97^#n zJmHJ|3`6VK;!anu835>_Jg+YO6J5fjO!23yoKwQTia)?c&mkA7cci>eX6w0)yW;R$ zGzSDejQ#owKku_G$e{}Vew`6nnMZyBy60w5Z8|2je5N!;uFigc*-SOFzAlYs84!1f z;AVxFCk+mzr<})lKfxq-pDGHU6mHL3^u6jE$!KXew_u1nVWB5I6uUhOV}{VK0$?gC zNC}$mm>iD9m;VTD#I&u$O=8OY8q}wahC7%-f(iAxqHRG%==YYheX^9-k1iNokdPHQ*4R$)V zKG;%1BtzJD%4k?tmZ2NC8JBT>Ye8N5?bn1?uV>I>{nv8(B%L6l<4S^do^1I$c}5I% zzv0+l?^hj=r(*Luo;)A*mzY4rkO@t-N2BXy>btA3uluX}fK0_yJ1lJmMl}og1FP2M znC6Y1CGC~>C?H+9O+x!cmTvpI41`fi^-ES^9)nJU3ZXkrb4Ge1Fb*4bAA6mqKfDi^tFhD`o+TlB1Qfy6}IB1Nj0+r_OfnD?O50R zdjn=hMLR)_QkTrfwV}-7NFZ~{UITKVF4u!u zi$ij(wg8{CTA#>d`TADP+Ia;(?Gl3-(To=@&n*YfkJ82}Z$Cp6*iP>%A70oxZe1g! zYO(1s$I2t5m|}3yRm*fyYEP_2!e4QZ?94+O$aVHH2bV_>g66WBU4ag70ejFoqY(Z` zJmaI|jIZeT%Yd(#biKl(Az($UH?DGdR7t6aWr(rqgf7&8Ebb45^H|K8hh=H;J0m{% z51t-X*A7khmjGKOF#RtykJsNoef0jN9D@(QgSldY%g2Iw`Nw@&%}V=p zg~h{MDMuxG=K;Ma?a=YuX^QuWgf%+Y1a zH6P{OzcG^J%h;HHcA#0msWr~ac({_M(H>`Q+j+pVPK@%cn_1A&eHB7QYAeoH^uIiB z83DvF9ID4Lnw<*aUOp6C9;J`Fh>3mNSlPvK+Tsnbd)q;QISuWFAGDvn8?H(to$Da& zpk$t;l$uW0Ef4nR+-e`xU3ZzGe3f-uvTUvD7B*3A&M;j1Kq^^*`H)S_0C3z9paVxI zn`ZW75NJ!lO_w1F>r?R`ixv`?u(MkD;n$m$iH)bUqEGK-`{fr9vmZCB`JGvdHmQVE zDXhbeg=eiur>HuI%z%g0ZS9|)<;c$)@dhpa(H$xVN-`zq{30r(!6s%eooea~pQu$T zghI#f^Uf|5tFGA)49A1Dr(r>;X;Qs<>(2WxOND9m!JV)(s+4`eECg$K7o@GQ>@ylv zE~jn|)@nM==xQS%;q;kW$gx6~?n)_ld( zXDDWM3E9vZ7V2Fl&CBs;i1{E!Ba+KOeLO)>rj6Zjnf^FM+M4?YYxDIgXyDQeb1rw+ z41xR1sd{)c!@X!D{ZqEe5wPd^4;rVoHxAVC_uqAnX!Wg$40M&o-)KD$>*Q@;F!aZ^ zW}SHx7-GJ>=D6ofIiWSs&2|Qv?2xVi$BW5GAakoeHpWOqvcHa2q?Vnp-9|_Za+0VI zEWb=qGqrSJ&lF{qsH-(`T&5O$MM+t&tX$V^O$Fze7IGjMoRi%QN?rV)MKj8Qvm$Lr-m6 zyErEJ26as?ekR^1`{Kg@Vh+MLe#6#eQr#D7muCO)EqjoiFsy+7jXiJ-# zM?@*f0ksy9_;U!;RnY^?e8}wY5SRCpgi*j`NoNOMh~@QiDnL` zvndYKq)}kt7XKW$Cq?R!$2@bnBz68E#knY7C7-<)<~y4Hv0RxD4tNg*F8S=P`XohS zX*+N~FDeyGgJzvL{Gf*&t$2O?@jjuC%1)4Z=g45EyjR(kZ>0B=2Dt*maf{0xv%5_;Cbts>(RLvVT^XvOere$L$*&wD!H% zxOPVT!1Odc+)`SsLNK8;40croF zri{m8Dxud7)qeC~8OQ%>KurwV(z0=Pu~t}X(QAvA86f);)L$t$8zq_oT=oLI7kRaxbKJ^YlKCy-24P|R_V%H?|WcFCCNEhjk^Gg*M4jjfHYUX{3 zJMQCpRvX@R>j-|b^<&%?e>uZGq!{p|dNOFtG6ybCs0ADm{f2d8%guOv%ghh@W;9ET zk0O%n`RyC9WTh26mYKp9nExC0H-8=w}UCtxOVpU;peE z|JUjMigi9;U;pTKs>s5`}C1;MuH)yt;%zOvut$)y5>Y3pB}o>-lzaX!=)lC`z9kN=zH>7vP| zGOEHTtg4T&285`lY0A0X>p__)Eo#ptI$Zs5Gq?#h$IXa}c@!|m#KTb?;}E?lu_kaR z5FYG9YRs^YDKKs8f!LYo6*#jra4genI~ZS>XJGj%)!Pk=Gj$tR#X%35I2dwDUvcnp zgq3uoNlYvQwr6_iRS(mv^V9|Vq9+g_@u#IpY49Y}$(mft>rW9%fMLsWCji>x(%{*$ z`2uyZCNe$6oZ4dyeC?okNV40hAF}B-9?Kmo?o)10ENMXIuZ|y76fd_5d)>6Z>2gcJ z@udqiGdtn%EKB?Y5xuUNpCNSf`wM-5Az{eI{^k<&X@6ZP%x`-o_tC)H&D(Rd*9G>@ z8??)p7sONRcV3VPYLYploSzs<6TM*aBqZHGn!iQ(u$LOMyAwik)iyXHzydTp?;Vbuuc z2B;)E^s>KO%%1?}6*?@-^Ii1}H+F5&z8`)U^1UZK>*F6Un(|ORIts1x20eLhONZmf zkrU{*eENig-?Qb&x(gFkcZRdPXh8rqGgvyq<%tT^JLa}ug{iB|rgT44+3f>(`-Bf` zYAkxg`?pX(laf>b0IdT7IG>_$IoblYo^fIHao0ApF+b}tsVZ4y+#|yuk^GIRBifU9 z&v?b_U30P#ZKxa+Oxf7Xo&YIc{S*SE2b)p^;D3OhiXje;$4j6SV9A4r(|{QS)-bDi z{Ah;s^}*C%)a>gPlGK{L!fqqLNwoha;OK3Nvnz#qkYnc#f0bBIX;smndPynWSv!-; z?s}xxCER=#P@O2wt#UJQKnN{JPAHS6h}VT`oOD1;93tYx1E&!p_^dWm`6T7obJrfw94-K@k zMQ2M33PF^{{aU1srG57U#;f0@X#g(KXTiFyhM`g2zjPnS>~pljFDs=-JL8>_ySLC- zer(7cjf(0h0NaU4KjFHCnn3FehT?BR#w~bZ|n5F0%7--4suuE?!Uw=e@4jv znzOVuetJ}|%b3U_&eAv$Iy=;U;h*`LI{b;D4G^abxO+q?q(<+9a)j{e5ipU30Nr*Q zzo0-xhGzvvTM1`C+bgU196OGDYdZlgU7apJRG?v^KpN~!zwHQV>)r#OsqRzC9TKG~ zkD%|^9sLttNC6L{CNfj;b zvuW=^9$JS2?@$;!1i7K?#fv~5 zh4e%d>1GqL@tBjOvY5T0YH1bL`@G&gJ_1G{z0j2(vt0J^whZo+bvot_t%?BH_An~2S;R;CvDB6D(MD`-pr%Y~goEeTtEUkPf+vHRMv4H)jD7yl zf<+ZN9lVQ^NfPfGo3iG4nz=fGT$2$#?iiAhF}7pVSOS@DyivN2owTH`{o)AZMRMEo z0t)So#a6Tv&)cHSYJZ?`|G^eN30I3qcw^nq?4OKvySZHz|KS{5#hiIJZ6~K3$ktR3 zbfsQ*{dNMM25@T4Ohf#iye!i>=PT8HE*kE}LgRFwLVy8HE3LuQU-Vh0kpYX68D!n>7r2ZrK7f+Qt*dj}h$fGN;dKc4kiW?>Y!XjMc z%ZcK?m1a<#4$AZdID3EZ!1&ci*ZP#ox8TQ*`#4(L?nsNSA3rQ~Y}R2SF7-sX|=}q0uuo+cH^2Ez|NAb*7CWwlLN2O>s16H9qkH#aH1_cWvv>QBTefJ_WnuE z{tL1kX+sX~1$~#Y0WxkfM3uU#MM5_gHb5u_2;$vpzQ(XM4Dfs`=x~IT(j$0TCXn2| zgKb&zqvm+*uLKQKy)q3f(-aj}JP_&G+^2DXWc$H=htc*}@FbrgZ^Q}uhtb9n|G>BW zK_==6yf*4Lv3*T9V@E2#wUa6Y@)O`s$UVvQ<32qs`}BhBG0XH|-$^DglXJDW^M#vx zNlV$pmh`2m6MpQ7T3%0SL=|XB{D~^Sqp*5OLAiZlX$+m_f=O{?dBDv=gL7*EN)N1l z%xLTp@N;+gevqYRU)V1~f8vRW)iOMotkr`0;M~g661QsYVeGjDpou(~rwh)b49xgVMPao zYc++yy0?ajl8_C@O>`qHGh7()OegIUw=ePmM4|;5a|>YFsthiq{TI}0dHo_2@bLbR zs8=j!_BY3`+hzaPvwi=D)C4GM*{IGJkyQtZfox$8CgapSsiJ&J*;AGLCp=PwEqg#KwJ9)AHfaB7SPIMiT2{g&SC5k~A0e+}K#HKh9zIfn0kpNfA$i{Z{Ff02~ zn9e_a(OSVLDuCK$`Q-^V+g|UMwf{1c8ZP$z9iTSRRU%8h*uC_+A_2bU+YmTB+li9-gTgGjKe8u0zTA?Bp z7zN>_PQT^46$rwmJ$k)*Qqpryd`y%rCrpr!EqJ?JYhiFf#~;U|D`?|PdRSq`t>F;8PIx8k@9d3 z#`rDE+?nL=XJ?I1L+kHo5y$!M(J)-D zJdm<-2UOXASD)Nz#|!&xUNI#MAks=%lg5LKzj9~ukEo~6!5H2}oHN}{!1*+_g1Q@u z*WF8Pxk*AdW!0kFu`Nz6#A66I8W4w3aBq~Mp=!nm$Lj$ZT!mu+o|`CiI;LT542_wH zxqb&ivJ5pH92Nj+#-d?*w`5TXzAz=hzF1Yk4?iR*C4tLrG8fZ#JiTdxYeTkZei_Bs zTM~*-O)PnKoC-`5*n4vJ*jcqwC^u7>9Dtv}Mt$!MuDl7+G+bL7kux^Z7e(B0J#y(c zFn3tB=xIQJGk7Nzb4A`Og<4iZvzX7^*4{(T&o{8dG^ZiBx}qp(%zcBeSYcjlR%9y1 zd4HIT;Akt+?%8v%No1uW!$i81_(}X&wI=eCj+|Fb`Ohi1t{f(ghav3N=;%H^P~P(;vSeA5a1Lwn2qfm4A1g? zp7Hp^&mKr6UYkSgdhO$xNgoUFdwR-0cFsadVO(%fUNnwe`)LQ?1%}o{iC^GxM+MsT z`l|9_3)f(~^n|__^;aLvTaE%M5221}5Fm^Fp$xFo=}SNHPw@%)?SU5d=qsjA`E9#` zIX62I7gmU6%>6l*UHe{E&M&|;2WbAyU7WLA`EcanIFAd#@-b2c(lplaR$N%sr<5qo z;I{^rji;JY1XHJlsaH5!$GxLuqb?0Ph5)M6pTd)Q*B`2sr%OHR0JNSfAD7Rlnk8-?`_G6Jkef~a7xg1Q2>s=R#}5D9|H!&=$*`+d zw(G1@v5Wsfu+C*mfW7R$YY@2&npwo5HICD^+n4__O#1hQlaYE|4Dam?1bd3I=F1Mp z^Zi+I%B?;f6OH^?jLNvsvYY&GvwQzOFZlPCVTJ&u7wC$~*k+!WsMy{R3OsxrPlVEs zD{aqm{F*byS{!g3CSeOGIQTB-Ed)-mn|uktX~x?>Si}(5&)eKWCsNJB_Gs32Go!$+ zc7zU_P=cP**=GB0bf^KX+@k>dMV?(Ey7+-xeIwt!AUnT72_9sI!2SJQH_6CzPV zvrB7@zf}0#qP187t^cb!3a*U zRAklGZ|~eY8p2BJu_@aHicy!Q+1WeKBNW8&TLvv~gzF~Dr}G?JHchm(!Zdi}(B$Kj zv~9~JZpHb^?54ESyhs!+u&V<#ZGxfl)ePQHv}+EOkU?zQ2BHMR_TY66BZXvmv$X|S z*v_2#^)JFRk|zZfDvB$UdCQfH9B>8jgGGUjKf2g5dn$Guv^SMp(!=}fhH2THNJyE% zX{h~8gJc2R4vWU$U0k-Qr%IP2ujTPKZ3{PDi^wx+dnPTyxI3Ix3~MrX!Og)x2bOWk zUNTTb{y|75bVeFqHce1vd%!awnRkTMlJ|zqi4;lqy479_crTy;Bd7E>s|MQG3A0L$ zb)OU3P2@gM_m2QqTAobk*jW5>^Xt7Oy{Z$G^S{$()mXRziwsOb$98}r&2WPJGLi&c;{{H- zZq}g}yD_xqcK;M3uEWB5WtO zQs$E$b~{9b`=jsA{yW7oe-{G$pOo4B*DV2aOPl2|7@M6f^GlmTfgce1Bkj9Ce(Fv}>=u=lXe%DDyF-k4%s;YAK59iGn>8q8!M8L;_8RiYy zqm_ypQ;9aNeUDto8n0m##vOVMVqe9kYe#pan(KTrkYiHwKy(CmVBc!>A? zbE8QM2$!WnVe`?7;;YGp0^nwKn^Z*x`>+wMg1MWAN1{XT7UvUh3)1v}_+!6@gP`Dz zU4fK<95q4vnmA^oQL`J?QHs=Ee2YPKi4q$u012I$Po{be`%ec(ky3Rnn%&DfF*7Uy zLo&JK@o6J_VfyoUYJ76DV-4L7zE4IZz(jQ%#=NQ(<^C{w8lnPid1UV&TlG6FfnHoa zsn$a3(QCl&4KSy-kP zL8-xilCckX1%bwUgT4H{i=mFF36Xc$-MLCp;QlOyae3809I=icJ?iF-;!Ke%(sIdU zfB1djhMT&0&m2CAyc;d`Bw;+x*9mV+sraa+oq!APKziJwvwG6=&RQsb>l@!!J#-iX zjffPr8205i#?$5Quon1I>(yq3dnKh^QuDN^h>wFnDZEFN18#VTkLOeIeudaRiQ4BK zKqm+}m57n`xFp8lVHayRWcNf5zyupo&09cGV_&*3{6NLN0Js4*a|-ex-o<}{7Ww1y zB_90k9_0&1U}y!bniUE2l4*~8YlbhH96c)nOhNBj$ejbdeb>``c9|mE8TTBL6UE@> zsfx_UyLj9S8aNGn;U+Z0ef-9zXd{nZHT}+WGuLVPWev2Pf=ewzr2{Zvi=v4(-Z-&8pq?J@_f+R#hNxAbzPO2ll75V$)) zISM|;J_MR(Eu&gnWNKw#(YBF;j!}{{b~Q96zeqDpm{~D+c(QnfT3;PH>lz)=0f_WJM%b41DaN#XB^0j&j9#JYqX<{g zV?iBi(tS$^=p(Hr>G=*y|OYT2-|#^k7kHRqB1Y;xjYT~k+jQ^46%bq`dqb!%&S zse&@W{@wV*q)p9S$yQBm5!zfbW@{MWGyp^M$pSDmpR&!gPnv}3-Ai>|G{+YLFEJrM zliU+%l`XtC<6$m2V&`pvUZB(*cpJ`*Ew~0TkiN@2d;3KM00U2E|NZL8|2gaW->=yG zpSmVj$HoC(>yrUERf?Q_->d&pcK=y#{tq$RpLM4jZ5y0gJPL(^Q~-5`5$cilATg$+ zzfCEck*7UB3e^98ujd%VtoV;iKJ}I0fMa$WuN`|rCdJX0N14)Uq7oltN{c`llO?AC7vyh zz#@ZKweFpAyg7asBk+di)Q?Ijknr#d`EQ#Ur6DeN%T}MuXd76(+K~#R`l_m~SG>xF zrOq|M7&$W|33@2ELXkNCy1Z+o!wSx>ys+>=WrE0e^^1daX!rSCySWg*?HS*`mc>Fh zbS@K9G;5CMmcL_^CaU(`!{E)OTI+==!s6GLZzK!e90|Vvlt>|Ie=gDdWd{)N#->_U zZ(Q@#u&k9vq+)^M##_#;V{b@@v->awS~)0oaJsr!BqcZe^^9gTP!v8T;yBYQ2__nU2Pj zby(aKNvrv6M1y3oC{XDBn%yA@Mu`hH-@h5j>#^2)Z<(hPDBJcF)4>Zq8Sz^VC~n=m ztW%-nA`Ajyg1zm>OAZ#*am3|J@hDv)8h9y&o2SC;#|AYFDsE->LS(vnVVQad@Vv@~ z`FUP#X6oI#`?6(QYTZt$Pp0)tEJsc07LM{gv#XyH4TQ3|y?>?X{&T(g-_*4`D?k2!y>_q&h$tzKAv;&3 zT+=_cb{;Sdi(<`|iOwj*J^)^I^s-ykW~{Dl2?#4GP3I34X^Qs@gzReCDn^&uLU#Aw z{93$qd>9RqS#28;>d32{!D_0vJEaK4-wpmLq_wv>Tu{EotpNXW!sKN04>t9AM?j9Z zaVcYl(OGIz-wUJ-$E2&Z#BC}5%_9>rl_x58uZHTyiqI#v0jpq~61b&Mhd8bNVN`Lc zWcT|?v>;;msq^o#k%smQTMzJl0o`cG|1*^vJ+KC8b8$)jDMitWb;8NBt^*~5OK0f= z0Qtd9-hq$0zHvXVB0~}XN#%xuV|s9lyF{v&l{EzzMuxrzOb{^j+}r7nlSbjzFp>-o zKY}rap6Aw_?EtFb4u@8>r;Tuhl;4i!&JWbok@n6{L#+h3r9T?Y-b&CloExF3(quqI zkie4i#}Wc%@*Xq9Kb`Ql0if+iOQB+jTQ-`CYQ3)G$IkrkSKTwe{3!znUUpcXNW;*AgCxozpggz$04>M ziUytvs2w&=>wFzraKrZKgCG6DqK!P4_EIiz2jjt0?FvPl1WR9)f-Od@XLl9fb?*bI zDy*{&UVKf1b^GmP*_r5B7d%QP8q><(F2BbdT-ORt!Pm8ZLDizO`le|f=aTvb{-{*w zx)x*n?s=x~=!?d1)at=}nP4yL(G38pb$2$UVCzaBv^Kcm=qJ(WgAhIZsx9;GJJEYN zfj(msS>G%j?9CJ`Q4d!zk3!T;TVGT|xGPp60yqCYHh4;0{Sm$`CZ~Mo3VII@jgWb) z%t>tzT~i}8YRbogKU7#0@#4KgNx8mV^zk;)fFl0w6{ss9ViR7vwOK1wzu*0i?w|ZX z&QE8YR5P>K)h@a;wb-&j3T$y$jNkrc;ZZO4FhI{dhX#EM7Be zZX(BL6UYL=vUf3^zXO=}=*V=oFYrgTVndTXT_bMZlckws0a2LLq^G$))%E$>ew>az zhu526Tf4ORe2?ZzAjKb0Y0i0duyXsd`p3)^JtZnh;{^8>;3e;PTmY~5{(=U6jPOYH zAa+MmM0I&{hR)a!$QOP>nQ|^dfFpLZa_<)AgGulj%WMmEMX$@{vhPLqtUrT6A6%du zcVcpjH0o7-b{o5oGOfW$`Ye@$p#HZmV4u#-@)5!W@Togb?0yH8P=fyb?vjO*Fca#F~{*8uwdIISCqcO%uMJ%sN73|AafH4i`xF|h;+pORIlP3%s4t#84i87YSy)*?g4U7_~4$imgg~ zv;mdQ0#tf?8P%Lo4qmJtYX;Vl5V`?X8YD++2~f7_QHp!4G}0WGN=|~fMnaHdUCWkS zpD8S!u$J6d5lkuvtK$E3CxSi>t61WPwa`*5*&M?cIG_s9!|!tI-@*1^A9 zCV&Y|uw^3`)vXZmfd_OzGE=t?CzBd3NW_e`V(buV64N>vNu9jyzBLL}pfw~A&xT|V z@N#tU@MvJ~8(U>86>%={k@pyax=vSJY}8C$quic*!4beYd;1Q~^&8j(z4i7syq}`X zvE+y28fVjz-~h0-FhjnU2;LsJ7hIRs=lINNH(sBajjHXKJ+r0Pe$_v*NHNLf!CM)(moF= zRtA)gCi^q&cNAp!>;csfYTnaaP+YnzNgCY zI1wy^+`uXAlze!e@X-~nG`!pl!fF4dD1`1nhehFKwoAcUQ!=t9tO56+{x%}|ZSayB zdYoe3FS&S3gJc`hAli5eA3ON#*37$qh^hKN#a7dRg5bTEm%^1vGUP}Kc|NpgDEb4O zBZ~+12V4ON3L5yp$q6mT6W>FQNTc>McS&z&&L`w}(VWsSip}Gvp+^LKBXg?4t9luG zVYui#HE5=SC$zvsNt}IC&Lk{>KSoe=0wT&{Hb6*ck)zEn$j6HK**g|+(a9V0IX~(U zQ_H9~Q0%~Np`1KPx!ON{wtp7J|Zv$k>&wgf+9f33$|768YnvzCtY$c$!s zXjf7B>348r(X&RneV;ZHd$K;ewGu7|Dm07rc#-`kxhd{q$ZfsA{p8ImY!_rBId{aJ zcy;=#mgw2eLXs81cM>S@)q=6YSPyF??@YAQ#;(SQZ#g_i_o=~eF}HNw&+TE=g4UC%r61J5?UF)$XO8ut>y0)8V&0ux1?+_e15gh15@fdOw_lBay_N4i zbcr?tr+-Mtg$9&FWnnkNLNqAq{>>Mj*HtU!EaB7$$NqqH-xKv@R1iz_g5$GC-eAU~A ze;$ogk<8yQ%S!U>Na6Iw#ON6@nR?kDO~0%~cKYA$EORh~pCPBLio<#&QJId3uG9a1 zZ4yMp9Brq!%dHV|x*V|s1ScGmuoL1!MES49KUSY)f}^34kT71p+VkbRBCWLxMOvWz z#C-41JwN1cBIAaqclLw!l}{Q_vi$0_7X}c0x3wHEh)@b8!V!ZSy}0&Mhm1pvGz9A_ ziXvwi#|DSQXB>#DVie3hs+)~vGr`zOrRZ&cbDm`5I9R~D`927d$$cj#=)3$g=py-wVYO4Xl`md&r z5JqPgnjcfvr%LYFwx68I@4iUk*F%&&K(t~dMV{yX36VnVib8sLJCA!n>sAP+>#GPxz@%>%XMHzy8?@L6VW1k z{H$27I?qw&sL7*6GCOO~;vJ>%25S))*LB_Wiz=?Oer}r&n~u88_r&-MRxS?%S20Ei z?xIJWPw*7tie1Zt$zU6zw9o;M|M@ng_`W5DEvIs`yGet_D_nQe*}e^!z&CN4b-b|Gjy+OGz}$9KHSC{CctzDf6&pYe~ZBssZm#>MT-8&+KSX$c)y!o7U@O z`??m%Z>ZDXb;W>HW0f?OO*bJ{QH~27m-WT6wi@kV$2&kQh(nWHB`)&k3jIGiJmXm5 z47^WK&WlQ}|DB?c-PVC9djc+CrI&2VH&TDtAZQ()DDdB(1CA4xicLDh?U9!%UPJ-E#2yesl@KADQDbB~=GN_cO+%%kB>LjMKS{Tp!so(brWk+mX zc5-c&*@i>GWP@$L=VowQ=r#c@l)ym-3eb|ll)I4=EqNVaWcs4L3Z~4O^)dw47ew`5 zRX&U8CXaNOj!(#bdkSi6(fun?{qN9{!y?uk=hi$H$QK7ds}_{Js)61@rbGF>`F_+78T(FL`3K1c3UdGe literal 0 HcmV?d00001 diff --git a/docs/pictures/filter-graph_chain.PNG b/docs/pictures/filter-graph_chain.PNG new file mode 100644 index 0000000000000000000000000000000000000000..f9557f1bacaf2ea2ce8cc45496348ee8ecf0f1a0 GIT binary patch literal 14505 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 A$^ZZW literal 0 HcmV?d00001 diff --git a/docs/pictures/list-graphtags_chain.PNG b/docs/pictures/list-graphtags_chain.PNG new file mode 100644 index 0000000000000000000000000000000000000000..0243ed75cb0aeccb1815bb72a9e6b652986e8326 GIT binary patch literal 13532 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 DP9kew literal 0 HcmV?d00001 diff --git a/docs/pictures/list_filter_chain.PNG b/docs/pictures/list_filter_chain.PNG new file mode 100644 index 0000000000000000000000000000000000000000..2df5a832b499bd15803e0da88b9e41bda46ac638 GIT binary patch literal 17940 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 B`bdg(MaWR|OR=IITuEjTnqc;oNm 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

ZEZL6 zDsQ^h{6uSEj=E*1NatK1f`s%~2GGh^v^ei~Cc8X;{nE!TOD$jI^}D3?##F}xe-%$H zck$ndvr>$^Snbzj=Q`V$!dn;eLO1to5>PzpA)ByU7tJCmMxKrr|Dfe}<`OH=qn_qK zWj%2GI8VtkU;j*6bW?yD^QT?JsLQpKi)n=j69edEuHdAGQ&>@lsqutn#VPSoGov0k?}C z6z}%kMLP2j4LO_II2BvaEnWqi8yG%*G~6dASo^r#gXE&-@*e6*%J`7$ z;`BDGcKF4rMS@vNl|ZBKO(`j{fnNouek9*;Gf(Z2sRLWkZ|EPZZbp-ARvjb zKdZ+@F-6y-q{AVJ0AEqA;+qES3f)Lo#*ejcJnxkUMS^eyJ02eCgXtYt-briL)s=Lc z#Tz@1$5n~$%L6sy@2mxdoyUbGJ00&1Wd|=Q#jQ} zr-agPHO$Nq_Aq*&+E&Zx%{|Wh= ze5^ZG(duOT+;t_qq_C5qwFIgO)l4{!);IbqmJnZ zj6=@O8(MlV#Rvab>))UP((^*1)5xJ9Z7JZ_aLL#!?A2lRtsQ|FGO;flddD1Wbs>IN6v$YYC{0u*(#4)ue8PC?8hzZIl0^D*w)pPYzuU4fpKmw^jB7^Mn5g@l!i-x7 zuP@qK%rBJrShk*3!XP(d%u;CW*S)=d&{b#kfHF+ev+9-9G&fFTzI z#-e7|%=?Zh`GYhF+N6Y(c9C-hdy*aNe{9bz>k1^!uEEfiC6X0=$vyOzYLO<{n8P_F zu_l>2hEg5}aUEhtUoXJAXkSkdFlvvJP1{$BQD5G(5WLW=8QIw2r$bt_ z)yxuh;mn#3%IJtE*OhUWU-49y%I-#)d@=N;eLxlSa%x%xx2ivvng3tlqCe#L&6*jJ zqil`mFD)mwj28}p1SfQd`=#exu|LI_LGl02Pbsi)06BYCw376;Qq+$2k?k4s$uS3;xuRique*i*B(5wIe literal 0 HcmV?d00001 From a87c3c06e99f20ac5e1cdac337d1ce9c45d70444 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 8 Apr 2020 13:36:12 +0800 Subject: [PATCH 288/415] fixed Missing Divider for filter. #153 --- src/main/java/jikan/ui/Ui.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index f860c79de..d707e5fad 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -107,7 +107,7 @@ public static void printResults(ActivityList resultsList) { } System.out.println(DIVIDER); } else { - System.out.println("There are no activities matching that description.\n"); + printDivider("There are no activities matching that description.\n"); } } @@ -254,11 +254,13 @@ public static void graphAllocation(ActivityList activityList) { if (activityList.get(i).getAllocatedTime() == Duration.parse("PT0S")) { continue; } - double percent = activityList.get(i).getProgressPercent(); + double percent = activityList.get(i).getProgressPercent();\ + /* double max = 100; if (percent > max) { percent = max; } + */ String activityName = activityList.get(i).getName(); printProgressBar(percent, activityName); } From 527b82e48fc05aec04644462180d8cb7ca741160 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 8 Apr 2020 13:40:08 +0800 Subject: [PATCH 289/415] fixed Repetition in Find Command #145 --- src/main/java/jikan/command/FindCommand.java | 2 +- src/main/java/jikan/ui/Ui.java | 10 ++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index b003324cc..0bc2f3469 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -83,7 +83,7 @@ private void findSubList() { */ private void populateLastShownList(String keyword, ArrayList activities) { for (Activity i : activities) { - if (i.getName().contains(keyword)) { + if (i.getName().contains(keyword) && !lastShownList.activities.contains(i)) { lastShownList.activities.add(i); } } diff --git a/src/main/java/jikan/ui/Ui.java b/src/main/java/jikan/ui/Ui.java index d707e5fad..b3f56505d 100644 --- a/src/main/java/jikan/ui/Ui.java +++ b/src/main/java/jikan/ui/Ui.java @@ -107,7 +107,7 @@ public static void printResults(ActivityList resultsList) { } System.out.println(DIVIDER); } else { - printDivider("There are no activities matching that description.\n"); + printDivider("There are no activities matching that description."); } } @@ -254,13 +254,7 @@ public static void graphAllocation(ActivityList activityList) { if (activityList.get(i).getAllocatedTime() == Duration.parse("PT0S")) { continue; } - double percent = activityList.get(i).getProgressPercent();\ - /* - double max = 100; - if (percent > max) { - percent = max; - } - */ + double percent = activityList.get(i).getProgressPercent(); String activityName = activityList.get(i).getName(); printProgressBar(percent, activityName); } From b9bf29210e40e6153ee61c2a16dce78546ccfdfd Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 8 Apr 2020 13:45:20 +0800 Subject: [PATCH 290/415] no message --- text-ui-test/EXPECTED.TXT | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 0980b0af6..331121c8b 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -39,28 +39,28 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Allocation | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Allocation | Date -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Allocation | Date -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Here are the matching activities in your list: | Name | Duration | Allocation | Date -1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag1] +1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ There is already an activity with this name. Would you like to continue it? @@ -74,9 +74,9 @@ Ended: activity 1 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Allocation | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] +2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] +3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Please input an integer for the time interval. @@ -95,7 +95,7 @@ You have not started any activity! You have not started any activity! ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -☹ OOPS!!! I'm sorry, but I don't know what that means :-( +OOPS!!! I'm sorry, but I don't know what that means :-( ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ No keyword was given. @@ -112,8 +112,8 @@ You have deleted activity 2 ------------------------------------------------------------------------------------------ Your completed activities: | Name | Duration | Allocation | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag] -2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-07 | [tag1] +1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] +2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag1] ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Bye! See you again. From de8171bbc2dd4d5f0bc6a2040c248e3f4325bd85 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 8 Apr 2020 13:49:16 +0800 Subject: [PATCH 291/415] fixed test failure issues --- src/main/java/jikan/command/FilterCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index 374a37d1a..99bed5c14 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -45,7 +45,7 @@ private void filterFullList(ActivityList activityList) { } else { lastShownList.activities.clear(); String[] keywords = query.split(" "); - if (keywords.length < 1 ){ + if (keywords.length < 1 ) { throw new EmptyQueryException(); } for (String keyword : keywords) { @@ -71,7 +71,7 @@ private void filterSubList() { } else { lastShownList.activities.clear(); String[] keywords = query.split(" "); - if (keywords.length < 1 ){ + if (keywords.length < 1 ) { throw new EmptyQueryException(); } for (String keyword : keywords) { From 63f11edbed283a2613777dc5df317e849c0e254a Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 8 Apr 2020 13:55:06 +0800 Subject: [PATCH 292/415] fixed preceeding whitespace --- src/main/java/jikan/command/FilterCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index 99bed5c14..d43d67ca5 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -45,7 +45,7 @@ private void filterFullList(ActivityList activityList) { } else { lastShownList.activities.clear(); String[] keywords = query.split(" "); - if (keywords.length < 1 ) { + if (keywords.length < 1) { throw new EmptyQueryException(); } for (String keyword : keywords) { @@ -71,7 +71,7 @@ private void filterSubList() { } else { lastShownList.activities.clear(); String[] keywords = query.split(" "); - if (keywords.length < 1 ) { + if (keywords.length < 1) { throw new EmptyQueryException(); } for (String keyword : keywords) { From b8b9760b05a36b3cab9d449f9458a2b97b79f07a Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 8 Apr 2020 14:32:35 +0800 Subject: [PATCH 293/415] fixed Unusual tags addition #167 --- src/main/java/jikan/command/StartCommand.java | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 13d46eb53..be67a13a5 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -10,6 +10,7 @@ import java.time.Duration; import java.time.LocalDateTime; import java.time.LocalTime; +import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; @@ -315,17 +316,27 @@ private void addActivityWithTag(String activityName, String line) { int index = line.indexOf("/t"); String tagInfo = line.substring(index + 2); tagInfo = tagInfo.trim(); - String[] tagString = tagInfo.split(" "); + String[] seperatedTags = tagInfo.split(" "); + ArrayList tagString = new ArrayList<>(); + for (String i : seperatedTags) { + populateTagString(tagString, i); + } if (tagInfo.isEmpty()) { Ui.printDivider("Please provide a valid tag"); - } else if (tagString.length > 2) { + } else if (tagString.size() > 2) { Ui.printDivider("Cannot have more than 2 tags"); } else { - Parser.tags.addAll(Arrays.asList(tagString)); + Parser.tags.addAll(tagString); addActivity(activityName); } } + private void populateTagString(ArrayList tagString, String i) { + if (i.length() > 0) { + tagString.add(i); + } + } + /** * Add activity to activity list. * @param activityName the string representing activity name. From e5af318ea50f82fd2ec0be7645cd53cfa0ac5465 Mon Sep 17 00:00:00 2001 From: btricec Date: Wed, 8 Apr 2020 14:40:22 +0800 Subject: [PATCH 294/415] Update usage section of UG, add example for graph tags Closes #142 --- docs/UserGuide.md | 76 ++++++++++++++++----------- docs/pictures/filter.PNG | Bin 0 -> 11509 bytes docs/pictures/graph.png | Bin 38815 -> 5738 bytes docs/pictures/graphtags.PNG | Bin 0 -> 4185 bytes docs/pictures/graphtags_example.PNG | Bin 0 -> 11028 bytes docs/pictures/graphtags_example2.png | Bin 0 -> 4084 bytes docs/pictures/list_week.PNG | Bin 8202 -> 31259 bytes 7 files changed, 46 insertions(+), 30 deletions(-) create mode 100644 docs/pictures/filter.PNG create mode 100644 docs/pictures/graphtags.PNG create mode 100644 docs/pictures/graphtags_example.PNG create mode 100644 docs/pictures/graphtags_example2.png diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 0a5842f30..ae05a0322 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -15,28 +15,29 @@ Features ======= ## Usage Jikan lets you record how much time you spend on various activities so that you can easily see what took up the most time today / this week / this month. +(In the example below, we use the example of a student tracking his/her schoolwork, but Jikan can be used for more than just that!) To start, record your first activity using the `start ACTIVITY_NAME` command. -Add some tags to your activities to group similar activities together using `/t`. +Add some tags to your activities to group similar activities together using `/t`. Tags help you group activities of the same type together, in this example, we use the tags feature to label activities according to their module code. -Add allocated time to your activities using `/a`. Do note that the time allocated for an activity is represented by the target column in the diagram below. (These two words are used interchangeably). +Add allocated time to your activities using `/a`. When you are done with the activity, or want to move onto something else, tell Jikan to `end` and the Activity time will be recorded and saved to your list. -You can view all your activities using the `list` command. Activities will be shown in this format: -![Continue command sequence diagram](./pictures/list.PNG) +You can view all your activities using the `list` command. Or view all your activities over a period of time by using `list` with extra parameters. For example `list week` will return a list of all activities this current week, as shown below. +![list week](./pictures/list_week.PNG) -You can also view all your activities over a period of time by using `list` with extra parameters. For example `list week` will return a list of all activities this current week, as shown below. -![Continue command sequence diagram](./pictures/list_week.PNG) +The list still looks very cluttered, we can reduce it further! Want to find everything you did for CS2113 this week? Filter out the activities you want to see using the `find` or `filter` command. This is our list after filtering out all our activities tagged as `2113`. (the -s flag tells Jikan to search our last shown list, i.e. the list of activities this week in this case) +![Continue command sequence diagram](./pictures/filter.PNG) -Filter out the activities you want to see using the `find` or `filter` command. This is our list after filtering out all our activities tagged as `core`. -![Continue command sequence diagram](./pictures/list_core.PNG) +To easily see what took up the most of your time out of all the 2113 activities, use the `graph` command to view a chart of your activities. +![Continue command sequence diagram](./pictures/graph.PNG) -To easily see what took up the most of your time, use the `graph` command to view a chart of your activities. -![Continue command sequence diagram](./pictures/graph_core.PNG) +Curious about what module took up the most time this week? We can use the `graph tags` command on our weekly activity list to find out. +![Continue command sequence diagram](./pictures/graphtags.PNG) -Now it's clear that lab 3 ex3 took up the most of your time. +Evidently, it was CS2105. Not done with an activity and want to continue it? Use the `continue` command to continue recording time for a previously started activity. @@ -51,13 +52,12 @@ This is just a quick overview of what Jikan can do for you. For more details on **Format:** `start ACTIVITY_NAME /a ALLOCATED_TIME /t TAGS` * `ACTIVITY_NAME` can contains spaces and must be less than 25 characters. * `ACTIVITY_NAME` must also be unique (should the user start an already existing activity, the option to `continue` will be given). -* `ALLOCATED_TIME` should be of the format [HH/MM/SS]. -* `TAGS` are separated by spaces. +* `ALLOCATED_TIME` should be of the format [HH:MM:SS] and cannot exceed 23:59:59. +* `TAGS` must be single spaced separated. * `ALLOCATED_TIME` and `TAGS` are optional. -* `ALLOCATED_TIME` must always come before `TAGS` if both are used. **Example:** -`start CS1010 assignment /a 01/30/00 /t CS1010 core` +`start assignment /a 01:30:00 /t CS1010` `start GER1000 quiz /t GER GEmod` `start revision` @@ -68,7 +68,7 @@ This is just a quick overview of what Jikan can do for you. For more details on * `ACTIVITY_NAME` must be an existing activity in the activity list. **Example:** -`continue CS1010 assignment` +`continue revision` ### Ending an activity: `end` **Usage:** Stops recording the time for an ongoing activity and stores it into the activity list. @@ -98,12 +98,13 @@ This is just a quick overview of what Jikan can do for you. For more details on * `TIME_PERIOD` can either be a specific date or over a range. **Example:** -`list` List all activities. -`list month april` Lists all activities in April. -`list week` or `list weekly` List all activities in the current week. -`list day` or `list daily` List all activities in the current day. -`list 01/01/2020` or `list 2020-01-01` List all activities on 1 Jan 2020. -`list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. +* `list` List all activities. +* `list month april` Lists all activities in April. +* `list week` or `list weekly` List all activities in the current week. +* `list week 01/01/2020` lists all activities in the week of 01/01/2020. +* `list day` or `list daily` List all activities in the current day. +* `list 01/01/2020` or `list 2020-01-01` List all activities on 1 Jan 2020. +* `list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. ### Editing an activity: `edit` **Usage:** Edits the name or allocated time of an activity in the activity list. @@ -118,7 +119,7 @@ This is just a quick overview of what Jikan can do for you. For more details on `edit CS1010 assignment /ea 10:00:00` Allocated time for activity is edited to `10:00:00` ## Finding and Filtering -By using `find` and `filter` commands, users can reduce clutter and zoom-in to specific activities containing certain keywords or tags. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further reduce clutter. These features are particularly useful when the visualisation of time spent with minimal clutter is required. +By using `find` and `filter` commands, the user can reduce clutter and zoom-in to specific activities containing certain keywords or tags. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further reduce clutter. These features are particularly useful when the visualisation of time spent with minimal clutter is required. ### Finding Activities by Name: `find` **Usage:** Users can request for a sub-list of activities that has names which contain any of the given keywords. If there are more than one keyword, each keyword should be separated with ` / `. @@ -153,15 +154,17 @@ If we want to find all CS2106 tutorials, we can first use `filter 2106` to filte ## Graphs By using the following commands, users can get a visual representation of the time spent on each activity and their current progress. The 3 types of graphs are : - * *Activity time graph* - Total time spent on each activity: `graph SCALE` - * *Tags time graph* - Total time spent on each tag: `graph tags` - * *Activity targets graph* - Progress of each activity in relation to its targeted time: `graph targets` + * *Activity time graph* - Total time spent on each activity: `graph activities SCALE` + * *Tags time graph* - Total time spent on each tag: `graph tags SCALE` + * *Activity targets graph* - Progress of each activity in relation to its allocated time: `graph allocations` Tip: Use `find`, `filter` and `list` commands to reduce clutter before graphing as the graphs are based on the last shown list of activities. ### Activity time graph: `graph activities` **Usage:** View a comparison of the absolute time spent on each activity in the last shown list. -The parameter `SCALE` refers to the number of minutes represented by each point on the graph. +The parameter `SCALE` refers to the number of minutes represented by each point on the graph. + +Note: As the units of `SCALE` is minutes, if your activity is less than a minute, graph function will not show anything. **Format:** `graph activities SCALE` @@ -172,9 +175,22 @@ The parameter `SCALE` refers to the number of minutes represented by each point ### Tags time graph: `graph tags` **Usage:** View a comparison of the absolute time spent on each tag in the last shown list. +![graph tags](./pictures/graphtags_example.PNG) +For example, if we `graph tags 1` for the activity list above, we will get the following graph: + +![graph tags](./pictures/graphtags_example2.png) +`activity 1` and `activity 2` are both tagged `tag1` and have a duration of 5 mins. +`activity 3` and `activity 4` are both tagged `tag2` and have a duration of 2 and 3 mins respectively. +Adding up the durations for each tag, we get 10 mins for `tag1` and 5 mins for `tag2`. As we chose the graph to have a scale of 1 min, there are (10 asterisk representing 1 min each) for `tag1` and 5 asterisks for `tag2` in the graph. + +As tags can be used to group activities of a similar nature together (i.e. same module), this feature can be used to easily see what type of activity took up the most time. + **Format:** `graph tags SCALE` +**Example:** +`graph tags 1` + ### Activity targets graph: `graph targets` **Usage:** View the progress of activities to see how much time was spent on the activity relative to the time that was allocated. @@ -188,15 +204,15 @@ Using `list`, `find` and `filter` commands you can sieve out the information you **Graph Activities Example:** ![chain graph activities](./pictures/filter-graph_chain.PNG) -`filter 2113` gives all activities tagged `2113`, then we can use `graph activities 5` to view a graph of the duration for each activity. Each asterisk represents 5 minutes, as indicated by the `SCALE` parameter of the graph command. +`filter 2113` gives all activities tagged `2113`, then we can use `graph activities 5` to view a graph of the duration for each activity. **Graph Tags Example:** ![chain graph tags](./pictures/list-graphtags_chain.PNG) -`list 25/03/2020` gives all activities completed on 25th March 2020, then we can use `graph tags 5` to view the graph of the tags. From this, it is easy to tell that the user spent more time on CS2105 than CS2106 that day. +`list 25/03/2020` gives all activities completed on 25th March 2020, then we can use `graph tags 5` to view the graph of the tags. Each asterisk represents 5 minutes, as indicated by the `SCALE` parameter of the graph command. **Graph Allocations Example:** ![chain graph tags](./pictures/find-allocations_chain.PNG) -`find Lab` gives us all 'Lab' activities, then we can use `graph allocations` to view the progress bar of each of the activities to see how much time was spent on the activity relative to the time that was allocated. +`find Lab` gives us all `Lab` activities, then we can use `graph allocations` to view the progress bar of each of the activities to see how much time was spent on the activity relative to the time that was allocated. diff --git a/docs/pictures/filter.PNG b/docs/pictures/filter.PNG new file mode 100644 index 0000000000000000000000000000000000000000..fd5f690cb3791b875d32475a4fde6320b9849295 GIT binary patch literal 11509 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ⅇ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 diff --git a/docs/pictures/graphtags.PNG b/docs/pictures/graphtags.PNG new file mode 100644 index 0000000000000000000000000000000000000000..73d66118194171e13f2014330f4d60ec1ffeae3c GIT binary patch literal 4185 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 $j&!8;JaOVml}oWssETTlb_9 z<~prhEeK7vFhcea@}RnEUaoR3D00hw#T;D95O4fbL%IKtfcqcO`M-2#Yw5A%V>x`j zEtytJB2`}+x(67#hm`+^Lrw0`)te*Ns8a_y!Ix9HKWfSUp4ZJDxy#>q$4SlP_Nn&= PpVm^>S1b9=KKy?H=7IH4 literal 0 HcmV?d00001 diff --git a/docs/pictures/graphtags_example2.png b/docs/pictures/graphtags_example2.png new file mode 100644 index 0000000000000000000000000000000000000000..efb5b522f05f338550f4117afc6623a1ddb8e90d GIT binary patch literal 4084 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�qbzlF<)09tGUebHRuN77A{Q2E#y5ig|3=TjpE0 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 literal 8202 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 Date: Wed, 8 Apr 2020 15:05:56 +0800 Subject: [PATCH 295/415] no message --- src/main/java/jikan/command/StartCommand.java | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index be67a13a5..242cdb58a 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -317,23 +317,28 @@ private void addActivityWithTag(String activityName, String line) { String tagInfo = line.substring(index + 2); tagInfo = tagInfo.trim(); String[] seperatedTags = tagInfo.split(" "); - ArrayList tagString = new ArrayList<>(); + ArrayList tagsArray = new ArrayList<>(); for (String i : seperatedTags) { - populateTagString(tagString, i); + populateTagString(tagsArray, i); } if (tagInfo.isEmpty()) { Ui.printDivider("Please provide a valid tag"); - } else if (tagString.size() > 2) { + } else if (tagsArray.size() > 2) { Ui.printDivider("Cannot have more than 2 tags"); } else { - Parser.tags.addAll(tagString); + Parser.tags.addAll(tagsArray); addActivity(activityName); } } - private void populateTagString(ArrayList tagString, String i) { - if (i.length() > 0) { - tagString.add(i); + /** + * Checks for valid tag and add it to the array of tags. + * @param tagsArray the array of tags + * @param tag the tag to be checked and added + */ + private void populateTagString(ArrayList tagsArray, String tag) { + if (tag.length() > 0) { + tagsArray.add(tag); } } From 773e25fa36e912ad81375b6c8e52a29b2ed641fe Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Wed, 8 Apr 2020 15:26:32 +0800 Subject: [PATCH 296/415] Updated -s UG --- docs/UserGuide.md | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 07815e4a4..45159dbfb 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -143,10 +143,8 @@ By using `find` and `filter` commands, the user can reduce clutter and zoom-in t * `filter TAGNAME1 TAGNAME2` ### Chaining Lists, Finds & Filters: `-s` -Users can chain `find` and `filter` commands to generate an even smaller sub-list of activities based on their needs. This sublist is generated based on the previously shown list and also works after a `list` command. -This is can be particularly useful when the user wants to generate a graph. - -Note: This flag applies to `find` and `filter` commands only. +**Usage:** The user to `find` and `filter` based on the last shown list by providing the `-s` immediately each +`find` or `filter`. **Format:** * `find -s KEYWORD` @@ -154,6 +152,41 @@ Note: This flag applies to `find` and `filter` commands only. * `filter -s TAGNAME1 TAGNAME2` * `find -s KEYWORD1 / KEYWORD2 / KEYWORD3` +**Sample Use Case:** +If the user wants to see how much time he/she spent studying for quizzes of specific modules this month, he/she can +first `list month`, followed by `find -s 2106 / 1521` and `filter -s quiz`. + +``` +list month +------------------------------------------------------------------------------------------ +Your completed activities: + | Name | Duration | Allocation | Date | Tags +1 | revise 1521 | 00:00:00 | 03:25:34 | 2020-04-28 | [finals] +2 | revise 1521 | 00:00:00 | 06:17:03 | 2020-04-28 | [quiz] +3 | revise 2106 | 00:00:00 | 03:00:00 | 2020-04-02 | [finals] +4 | revise 2106 | 00:00:00 | 01:20:12 | 2020-04-18 | [quiz] +5 | revise ger | 00:00:00 | 02:14:54 | 2020-04-18 | [finals] +6 | revise ger | 00:00:00 | 03:13:14 | 2020-04-19 | [quiz] +------------------------------------------------------------------------------------------ +find -s 2106 / 1521 +------------------------------------------------------------------------------------------ +Here are the matching activities in your list: + + | Name | Duration | Allocation | Date +1 | revise 2106 | 00:00:00 | 03:00:00 | 2020-04-02 | [finals] +2 | revise 2106 | 00:00:00 | 01:20:12 | 2020-04-18 | [quiz] +3 | revise 1521 | 00:00:00 | 03:25:34 | 2020-04-28 | [finals] +4 | revise 1521 | 00:00:00 | 06:17:03 | 2020-04-28 | [quiz] +------------------------------------------------------------------------------------------ +filter -s quiz +------------------------------------------------------------------------------------------ +Here are the matching activities in your list: + + | Name | Duration | Allocation | Date +1 | revise 2106 | 00:00:00 | 01:20:12 | 2020-04-18 | [quiz] +2 | revise 1521 | 00:00:00 | 06:17:03 | 2020-04-28 | [quiz] +------------------------------------------------------------------------------------------ +``` **Example:** ![chain graph activities](./pictures/filter-find_chain.PNG) If we want to find all CS2106 tutorials, we can first use `filter 2106` to filter out all activities tagged `2106`, then use the find command with the flag, `find -s Tutorial` to get a list of all 2106 Tutorials. From cf881e4afc54ad6a07de152e6c0a391cec261bde Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Wed, 8 Apr 2020 17:14:50 +0800 Subject: [PATCH 297/415] Fixed tag issues --- src/main/java/jikan/command/StartCommand.java | 33 +++++++++++++++---- 1 file changed, 26 insertions(+), 7 deletions(-) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index b90386c50..c7c18fc32 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -10,6 +10,7 @@ import java.time.Duration; import java.time.LocalDateTime; import java.time.LocalTime; +import java.util.ArrayList; import java.util.Arrays; import java.util.Scanner; @@ -272,17 +273,18 @@ private void checkBothField(String durationInfo, String tagInfo, String activity LocalTime endTime; endTime = LocalTime.parse(durationInfo); Duration allocatedTime = Duration.between(startTime, endTime); + ArrayList tags = getTags(tagStrings); if (tagInfo.isEmpty()) { Log.makeInfoLog("No tags found with tag flag."); Ui.printDivider("Please provide a valid tag"); } else if (allocatedTime == Duration.parse("PT0S")) { Log.makeInfoLog("Allocated time is zero."); Ui.printDivider("Please provide a non zero allocated time"); - } else if (tagStrings.length > 2) { - Log.makeInfoLog("Activity has more than 2 tags."); + } else if (tags.size() > 2) { + Log.makeInfoLog("Activity has more than 2 tags"); Ui.printDivider("Cannot have more than 2 tags"); } else { - Parser.tags.addAll(Arrays.asList(tagStrings)); + Parser.tags.addAll(tags); Parser.allocatedTime = allocatedTime; addActivity(activityName); } @@ -330,18 +332,36 @@ private void addActivityWithTag(String activityName, String line) { String tagInfo = line.substring(index + 2); tagInfo = tagInfo.trim(); String[] tagStrings = tagInfo.split(" "); + ArrayList tags = getTags(tagStrings); if (tagInfo.isEmpty()) { Log.makeInfoLog("No tags found with tag flag."); Ui.printDivider("Please provide a valid tag"); - } else if (tagStrings.length > 2) { - Log.makeInfoLog("Activity has more than 2 tags."); + } else if (tags.size() > 2) { + Log.makeInfoLog("Activity has more than 2 tags"); Ui.printDivider("Cannot have more than 2 tags"); } else { - Parser.tags.addAll(Arrays.asList(tagStrings)); + Parser.tags.addAll(tags); addActivity(activityName); } } + /** + * Method to get valid tags from an array of tags. + * @param tagStrings array of tags + * @return an array list consisting of valid tags + */ + private ArrayList getTags(String[] tagStrings) { + ArrayList tags = new ArrayList<>(); + for (String s : tagStrings) { + String tag = s.trim(); + if (!tag.isEmpty()) { + tags.add(tag); + } + } + return tags; + } + + /** * Add activity to activity list. * @param activityName the string representing activity name. @@ -356,7 +376,6 @@ private void addActivity(String activityName) { /** * Received user input on whether or not to continue the activity. - * * @param activityList List of activities. * @param scanner Parse user input. */ From b579b10d0b18284aca2b6d934a1b93a338868bdc Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Fri, 10 Apr 2020 10:22:37 +0800 Subject: [PATCH 298/415] remove magic number --- src/main/java/jikan/activity/Activity.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 1805a386f..b1e384d43 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -23,6 +23,7 @@ public class Activity { private Duration allocatedTime; private LocalDate date; + public static final int MAXPERCENT = 100; /** * Constructor for a new activity entry. * @param name represents the name of the activity @@ -103,7 +104,7 @@ public void setAllocatedTime(Duration allocatedTime) { * @return percent completed */ public double getProgressPercent() { - double percent = ((double)this.duration.toMillis() / this.allocatedTime.toMillis()) * 100; + double percent = ((double)this.duration.toMillis() / this.allocatedTime.toMillis()) * MAXPERCENT; return Math.min(percent, 100); } From 51f6acde154f5d70f0bd8c5e25a327bcb2b339d8 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 10:55:17 +0800 Subject: [PATCH 299/415] Fix bugs for list command --- src/main/java/jikan/command/ListCommand.java | 86 ++++++++++++-------- 1 file changed, 53 insertions(+), 33 deletions(-) diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index ce3fb81aa..28ae17bcc 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -3,15 +3,11 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.exception.ExtraParametersException; -import jikan.exception.NameTooLongException; import jikan.ui.Ui; import jikan.exception.InvalidTimeFrameException; -import java.time.DayOfWeek; -import java.time.LocalDate; -import java.time.YearMonth; -import java.time.Month; +import java.time.*; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.time.temporal.TemporalAdjusters; @@ -28,7 +24,7 @@ public class ListCommand extends Command { * Constructor to create a new list command. */ public ListCommand(String parameters) { - super(parameters); + super(parameters.strip()); } /** @@ -95,14 +91,7 @@ private void listInterval(ActivityList activityList) case "week": // Fallthrough case "weekly": - // If user has input a specific date to obtain the week from, use that; - // (eg. the input is list week 2020-05-20) - // Otherwise get current date - if (listInputs.length == 2) { - startDate = LocalDate.parse(listInputs[1], parser); - } else { - startDate = LocalDate.now(); - } + startDate = getStartOfWeek(listInputs, parser); // Set current Monday and Sunday as time range startDate = startDate.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)); endDate = startDate.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY)); @@ -110,25 +99,13 @@ private void listInterval(ActivityList activityList) case "month": // Fallthrough case "monthly": - // If user has input a specific month, use that; - // Otherwise get current date - if (listInputs.length == 2) { - try { - startDate = getMonth(listInputs[1]); - } catch (IllegalArgumentException e) { - Ui.printDivider("Please specify the full month name."); - return; - } - } else { - startDate = LocalDate.now(); - startDate = startDate.withDayOfMonth(1); - } + startDate = getStartOfMonth(listInputs); + if (startDate == null) return; endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); break; default: // date / date range is given startDate = LocalDate.parse(listInputs[0], parser); - if (listInputs.length == 2) { endDate = LocalDate.parse(listInputs[1], parser); } @@ -137,6 +114,38 @@ private void listInterval(ActivityList activityList) printList(activityList, startDate, endDate); } + private LocalDate getStartOfMonth(String[] listInputs) throws ExtraParametersException { + LocalDate startDate;// If user has input a specific month, use that; + // Otherwise get current date + if (listInputs.length == 2) { + try { + startDate = getMonth(listInputs[1]); + } catch (IllegalArgumentException e) { + Ui.printDivider("Please specify the full month name."); + return null; + } + } else { + startDate = LocalDate.now(); + startDate = startDate.withDayOfMonth(1); + } + return startDate; + } + + private LocalDate getStartOfWeek(String[] listInputs, DateTimeFormatter parser) { + LocalDate startDate;// If user has input a specific date to obtain the week from, use that; + // (eg. the input is list week 2020-05-20) + // Otherwise get current date + if (listInputs.length == 2) { + if (listInputs[1].isBlank()) { + startDate = LocalDate.now(); + } else { + startDate = LocalDate.parse(listInputs[1], parser); + } + } else { + startDate = LocalDate.now(); + } return startDate; + } + private void printList(ActivityList activityList, LocalDate startDate, LocalDate endDate) throws InvalidTimeFrameException { // Only one date is specified; return all entries with start date coinciding with that date @@ -163,17 +172,28 @@ private void printList(ActivityList activityList, LocalDate startDate, LocalDate } } - private LocalDate getMonth(String listInput) { + private LocalDate getMonth(String listInput) throws ExtraParametersException { LocalDate startDate; - Month month = Month.valueOf(listInput.toUpperCase()); - YearMonth yearMonth = YearMonth.of(Calendar.getInstance().get(Calendar.YEAR), month.getValue()); - startDate = yearMonth.atDay(1); + Month month; + if (listInput.isBlank()) { + // return current month + LocalDate currentDate = LocalDate.now(); + month = currentDate.getMonth(); + YearMonth yearMonth = YearMonth.of(Calendar.getInstance().get(Calendar.YEAR), month.getValue()); + startDate = yearMonth.atDay(1); + } else { + month = Month.valueOf(listInput.toUpperCase()); + YearMonth yearMonth = YearMonth.of(Calendar.getInstance().get(Calendar.YEAR), month.getValue()); + startDate = yearMonth.atDay(1); + } return startDate; } private void checkExtraParameters(String[] listInputs) throws ExtraParametersException { if (listInputs.length > 1) { - throw new ExtraParametersException(); + if (!listInputs[1].isBlank()) { + throw new ExtraParametersException(); + } } } } From 1f7f860e7c45e27bb6b6af298a671e1a6fe878e0 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 11:03:15 +0800 Subject: [PATCH 300/415] Fix bug for list --- src/main/java/jikan/command/ListCommand.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index 28ae17bcc..fc6e77efe 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -24,7 +24,7 @@ public class ListCommand extends Command { * Constructor to create a new list command. */ public ListCommand(String parameters) { - super(parameters.strip()); + super(parameters); } /** @@ -35,9 +35,10 @@ public ListCommand(String parameters) { @Override public void executeCommand(ActivityList activityList) { // If no time frame is specified, print the entire list - if (parameters == null) { + if (parameters == null || parameters.isBlank()) { listAll(activityList); } else { + parameters = parameters.strip(); try { listInterval(activityList); } catch (DateTimeParseException e) { From 829541f4a53912a548bf7f112eba5c878b819296 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 11:06:36 +0800 Subject: [PATCH 301/415] Fix bug in continue command --- src/main/java/jikan/command/ContinueCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/command/ContinueCommand.java b/src/main/java/jikan/command/ContinueCommand.java index aede34011..2aa33acf1 100644 --- a/src/main/java/jikan/command/ContinueCommand.java +++ b/src/main/java/jikan/command/ContinueCommand.java @@ -18,7 +18,7 @@ public class ContinueCommand extends Command { * Constructor to create a new continue command. */ public ContinueCommand(String parameters) { - super(parameters); + super(parameters.strip()); } @Override From c4f78b6d6949fe0d3f79510fdd2a70e385944d97 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 11:22:59 +0800 Subject: [PATCH 302/415] Made find and filter case insensitive --- src/main/java/jikan/activity/Activity.java | 4 ++++ src/main/java/jikan/command/FilterCommand.java | 7 ++++++- src/main/java/jikan/command/FindCommand.java | 6 +++++- 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 1805a386f..2d016548e 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -70,6 +70,10 @@ public Set getTags() { return tags; } + public String getTagsAsString() { + return String.join(",", tags); + } + public void setTags(Set tags) { this.tags = tags; } diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index d43d67ca5..7b3b15b7a 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -86,9 +86,14 @@ private void filterSubList() { private void populateLastShownList(ActivityList targetList, ActivityList lastShownList, String keyword) { for (Activity i : targetList.activities) { - if (!lastShownList.activities.contains(i) && i.getTags().contains(keyword)) { + // if (!lastShownList.activities.contains(i) && i.getTags().contains(keyword)) { + if (!lastShownList.activities.contains(i) && containsIgnoreCase(i.getTagsAsString(), keyword)) { lastShownList.activities.add(i); } } } + + private boolean containsIgnoreCase(String str, String subString) { + return str.toLowerCase().contains(subString.toLowerCase()); + } } diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index 0bc2f3469..656368b7c 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -83,10 +83,14 @@ private void findSubList() { */ private void populateLastShownList(String keyword, ArrayList activities) { for (Activity i : activities) { - if (i.getName().contains(keyword) && !lastShownList.activities.contains(i)) { + if (containsIgnoreCase(i.getName(), keyword) && !lastShownList.activities.contains(i)) { lastShownList.activities.add(i); } } } + private boolean containsIgnoreCase(String str, String subString) { + return str.toLowerCase().contains(subString.toLowerCase()); + } + } \ No newline at end of file From 52bd4b50bd302a5ad03a8cd623e638b0576f664d Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 11:40:33 +0800 Subject: [PATCH 303/415] Fix bug empty filter keywords --- src/main/java/jikan/command/FilterCommand.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index 7b3b15b7a..ad78a29c1 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -3,9 +3,12 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.exception.EmptyQueryException; -import jikan.parser.Parser; import jikan.ui.Ui; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + import static jikan.Jikan.lastShownList; /** @@ -45,6 +48,8 @@ private void filterFullList(ActivityList activityList) { } else { lastShownList.activities.clear(); String[] keywords = query.split(" "); + keywords = removeBlanks(keywords); + //keywords = keywords.filter(boolean); if (keywords.length < 1) { throw new EmptyQueryException(); } @@ -96,4 +101,11 @@ private void populateLastShownList(ActivityList targetList, ActivityList lastSho private boolean containsIgnoreCase(String str, String subString) { return str.toLowerCase().contains(subString.toLowerCase()); } + + private String[] removeBlanks(String [] strings) { + List list = new ArrayList<>(Arrays.asList(strings)); + list.removeIf(String::isBlank); + strings = list.toArray(new String[0]); + return strings; + } } From 09e9b07c499b1f40ba0b2ddf67e124c84d94a8a1 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 12:18:19 +0800 Subject: [PATCH 304/415] Fix bugs for graph command when no parameters supplied --- src/main/java/jikan/command/GraphCommand.java | 15 +++++++-------- src/main/java/jikan/parser/Parser.java | 11 ++++++----- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index 4b514c2ca..9d1cffc94 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -42,20 +42,19 @@ public void executeCommand(ActivityList activityList) { graphTags(); break; case "activities": - graphDuration(); + graphActivities(); break; default: - Ui.printDivider("Please specify whether you want to graph activities / tags / targets."); + Ui.printDivider("Please specify whether you want to graph activities / tags / allocations."); } - } catch (NumberFormatException | InvalidGraphCommandException e) { + } catch (NumberFormatException | MissingParametersException e) { Ui.printDivider("Please input an integer for the time interval."); - } catch (MissingParametersException e) { + } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("Please specify whether you want to graph activities / tags / allocations."); } - } - private void graphDuration() throws MissingParametersException { + private void graphActivities() throws MissingParametersException { if (inputs.length < 2) { throw new MissingParametersException(); } else { @@ -64,13 +63,13 @@ private void graphDuration() throws MissingParametersException { } } - private void graphTags() throws InvalidGraphCommandException { + private void graphTags() throws MissingParametersException { HashMap tags = new HashMap<>(); for (Activity activity : lastShownList.activities) { extractTags(tags, activity); } if (inputs.length < 2) { - throw new InvalidGraphCommandException(); + throw new MissingParametersException(); } else { int interval = Integer.parseInt(inputs[1]); Ui.printTagsGraph(tags, interval); diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index f143708a8..724960fc8 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -27,6 +27,7 @@ import jikan.cleaner.LogCleaner; +import java.lang.reflect.Array; import java.time.Duration; import java.time.LocalDateTime; import java.util.HashSet; @@ -153,12 +154,12 @@ public Command parseUserCommands(Scanner scanner, File tagFile) throws EmptyName case "graph": try { command = new GraphCommand(tokenizedInputs[1]); - } catch (ArrayIndexOutOfBoundsException | NumberFormatException e) { - Ui.printDivider("Please input an integer for the time interval.\n" - + "If you'd like to graph by tags, enter the command ."); + } catch (NumberFormatException e) { + Ui.printDivider("Please input an integer for the time interval."); } catch (ExtraParametersException e) { - Ui.printDivider("Extra parameters or invalid format detected!\n" - + "Use activities / tags / allocations to view the respective graphs."); + Ui.printDivider("Extra parameters or invalid format detected!"); + } catch (ArrayIndexOutOfBoundsException e) { + Ui.printDivider("Please specify whether you want to graph activities / tags / allocations."); } break; case "goal": From cac5367d20dabf0bdee469601f1c7b917ea8a55a Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 12:50:18 +0800 Subject: [PATCH 305/415] Update error messages --- .../java/jikan/activity/ActivityList.java | 16 ++- src/main/java/jikan/command/AbortCommand.java | 4 +- .../java/jikan/command/DeleteCommand.java | 6 +- src/main/java/jikan/command/EditCommand.java | 20 +-- src/main/java/jikan/command/StartCommand.java | 18 +-- .../java/jikan/command/ViewGoalsCommand.java | 10 +- src/main/java/jikan/parser/Parser.java | 16 +-- .../java/jikan/storage/StorageHandler.java | 121 ------------------ 8 files changed, 47 insertions(+), 164 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 9212ae4d2..4627690e4 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -107,7 +107,9 @@ private void updateFile(String dataLine) { try { storage.writeToFile(dataLine); } catch (IOException e) { - System.out.println("Error saving task to data file."); + Ui.printDivider("Error saving task to data file.\n" + + "Your changes have not been saved in the data file.\n" + + "If the data file is open, please close it, restart the app and try again."); } } @@ -139,7 +141,9 @@ public void deleteUpdateFile(int index) { try { storageHandler.removeLine(index, storage); } catch (IOException e) { - System.out.println("Error while deleting activity from data file."); + Ui.printDivider("Error while deleting activity from data file.\n" + + "Your changes have not been saved in the data file.\n" + + "If the data file is open, please close it, restart the app and try again."); } } @@ -147,7 +151,9 @@ private void fieldChangeUpdateFile() { try { storageHandler.updateField(activities, storage); } catch (IOException e) { - System.out.println("Error while updating activity from data file."); + Ui.printDivider("Error while updating activity from data file.\n" + + "Your changes have not been saved in the data file.\n" + + "If the data file is open, please close it, restart the app and try again."); } } @@ -161,7 +167,7 @@ public int getSize() { */ public void saveActivity() throws InvalidTimeFrameException, NameTooLongException { if (Parser.continuedIndex != -1) { - Ui.printDivider("Ended: " + Parser.activityName); + Ui.printDivider(Parser.activityName + " was ended."); Parser.endTime = LocalDateTime.now(); Duration duration = Duration.between(Parser.startTime, Parser.endTime); Duration oldDuration = this.get(Parser.continuedIndex).getDuration(); @@ -176,7 +182,7 @@ public void saveActivity() throws InvalidTimeFrameException, NameTooLongExceptio Parser.resetInfo(); } else { - Ui.printDivider("Ended: " + Parser.activityName); + Ui.printDivider(Parser.activityName + " was ended."); Parser.endTime = LocalDateTime.now(); Duration duration = Duration.between(Parser.startTime, Parser.endTime); Activity newActivity = new Activity(Parser.activityName, Parser.startTime, diff --git a/src/main/java/jikan/command/AbortCommand.java b/src/main/java/jikan/command/AbortCommand.java index d7788398d..9e38b4c8c 100644 --- a/src/main/java/jikan/command/AbortCommand.java +++ b/src/main/java/jikan/command/AbortCommand.java @@ -27,11 +27,11 @@ public void executeCommand(ActivityList activityList) { throw new NoSuchActivityException(); } else { Parser.resetInfo(); - String line = "You have aborted the current activity!"; + String line = "You have aborted the current activity."; Ui.printDivider(line); } } catch (NoSuchActivityException e) { - Ui.printDivider("You have not started any activity!"); + Ui.printDivider("You have not started any activity."); Log.makeInfoLog("Abort command failed as no activity was ongoing"); } } diff --git a/src/main/java/jikan/command/DeleteCommand.java b/src/main/java/jikan/command/DeleteCommand.java index 4356d58b3..f784ead0d 100644 --- a/src/main/java/jikan/command/DeleteCommand.java +++ b/src/main/java/jikan/command/DeleteCommand.java @@ -24,7 +24,7 @@ public void executeCommand(ActivityList activityList) { int index = activityList.findActivity(parameters); if (index != -1) { // activity was found - Ui.printDivider("You have deleted " + parameters); + Ui.printDivider("You have deleted " + parameters + "."); activityList.delete(index); } else { if (parameters.isEmpty()) { @@ -34,9 +34,9 @@ public void executeCommand(ActivityList activityList) { } } } catch (NoSuchActivityException e) { - Ui.printDivider("No activity with this name exists!"); + Ui.printDivider("No activity with this name exists."); } catch (EmptyNameException e) { - Ui.printDivider("Activity name cannot be empty!"); + Ui.printDivider("Activity name cannot be empty."); } } } diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index 1ccd60107..85263afe9 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -49,7 +49,7 @@ public void executeCommand(ActivityList activityList) { Parser.activityName = parameters.substring(0, delimiter).strip(); newName = parameters.substring(delimiter + 4).strip(); if (newName.isEmpty()) { - Ui.printDivider("New activity name cannot be empty!"); + Ui.printDivider("New activity name cannot be empty."); throw new EmptyNameException(); } @@ -74,7 +74,7 @@ public void executeCommand(ActivityList activityList) { } if (Parser.activityName.isEmpty()) { - Ui.printDivider("Activity name cannot be empty!"); + Ui.printDivider("Activity name cannot be empty."); throw new EmptyNameException(); } @@ -102,34 +102,34 @@ public void executeCommand(ActivityList activityList) { // no new details provided throw new InvalidEditFormatException(); } - Ui.printDivider("Activity named " + Parser.activityName + " has been updated!"); + Ui.printDivider("Activity named " + Parser.activityName + " has been updated."); } else { // activity is not found throw new NoSuchActivityException(); } } catch (NoSuchActivityException e) { - Ui.printDivider("No activity with this name exists!"); + Ui.printDivider("No activity with this name exists."); Log.makeInfoLog("Edit command failed as there was no such activity saved."); } catch (EmptyNameException e) { Log.makeInfoLog("Edit command failed as there was no activity name provided."); } catch (StringIndexOutOfBoundsException | ArrayIndexOutOfBoundsException | InvalidEditFormatException e) { - Ui.printDivider("Incorrect edit command format entered!"); + Ui.printDivider("Incorrect edit command format entered."); Log.makeInfoLog("Edit command failed as an incorrect format was provided."); } catch (ExistingTagGoalException e) { - Ui.printDivider("Tag cannot be edited as there is an existing tag goal!"); + Ui.printDivider("Tag cannot be edited as there is an existing tag goal."); Log.makeInfoLog("Edit command failed as there was an existing tag goal tied to the tag."); } catch (IOException e) { - Ui.printDivider("Error in loading the tag file!"); + Ui.printDivider("Error in loading the tag file."); Log.makeInfoLog("Edit command failed as there was an error in loading the tag file."); } catch (NegativeDurationException e) { - Ui.printDivider("Please enter a positive target time!"); + Ui.printDivider("Please enter a positive target time."); Log.makeInfoLog("Edit command failed as a negative target time was provided."); } catch (InvalidTimeFrameException e) { - Ui.printDivider("New target time cannot be empty!"); + Ui.printDivider("New target time cannot be empty."); Log.makeInfoLog("Edit command failed as an empty target time was provided"); } catch (NumberFormatException e) { - Ui.printDivider("Please enter integers in the format HH:MM:SS"); + Ui.printDivider("Please enter integers in the format HH:MM:SS."); Log.makeInfoLog("Edit command failed as an incorrect format for the target time was provided."); } } diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 8006c12bb..064b05b17 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -256,7 +256,7 @@ private void addActivityWithBothField(String durationInfo, String tagInfo, Strin } catch (DateTimeException e) { Log.makeInfoLog("Allocated time provided was not valid."); Ui.printDivider("Time provided is invalid, please provide time in this format" - + " HH:MM:SS"); + + " HH:MM:SS."); } } @@ -278,10 +278,10 @@ private void checkBothField(String durationInfo, String tagInfo, String activity Ui.printDivider("Please provide a valid tag"); } else if (allocatedTime == Duration.parse("PT0S")) { Log.makeInfoLog("Allocated time is zero."); - Ui.printDivider("Please provide a non zero allocated time"); + Ui.printDivider("Please provide a non zero allocated time."); } else if (tags.size() > 2) { Log.makeInfoLog("Activity has more than 2 tags"); - Ui.printDivider("Cannot have more than 2 tags"); + Ui.printDivider("There cannot be more than 2 tags."); } else { Parser.tags.addAll(tags); Parser.allocatedTime = allocatedTime; @@ -304,7 +304,7 @@ private void addActivityWithAllocation(String activityName, String line) { } catch (DateTimeException e) { Log.makeInfoLog("Allocated time provided was not valid."); Ui.printDivider("Time provided is invalid, please provide time in this format" - + " HH:MM:SS"); + + " HH:MM:SS."); } } @@ -314,7 +314,7 @@ private void checkTime(String activityName, String durationInfo, LocalTime start Duration allocatedTime = Duration.between(startTime, endTime); if (allocatedTime == Duration.parse("PT0S")) { Log.makeInfoLog("Allocated time is zero."); - Ui.printDivider("Please provide a non zero allocated time"); + Ui.printDivider("Please provide a non zero allocated time."); } else { Parser.allocatedTime = allocatedTime; addActivity(activityName); @@ -334,10 +334,10 @@ private void addActivityWithTag(String activityName, String line) { ArrayList tags = getTags(tagStrings); if (tagInfo.isEmpty()) { Log.makeInfoLog("No tags found with tag flag."); - Ui.printDivider("Please provide a valid tag"); + Ui.printDivider("Please provide a valid tag."); } else if (tags.size() > 2) { Log.makeInfoLog("Activity has more than 2 tags"); - Ui.printDivider("Cannot have more than 2 tags"); + Ui.printDivider("There cannot be more than 2 tags."); } else { Parser.tags.addAll(tags); addActivity(activityName); @@ -368,8 +368,8 @@ private ArrayList getTags(String[] tagStrings) { private void addActivity(String activityName) { Parser.activityName = activityName; Parser.startTime = LocalDateTime.now(); - Log.makeFineLog("Started: " + activityName); - Ui.printDivider("Started: " + activityName); + Log.makeFineLog(activityName + " was started."); + Ui.printDivider(activityName + " was started."); } diff --git a/src/main/java/jikan/command/ViewGoalsCommand.java b/src/main/java/jikan/command/ViewGoalsCommand.java index 60dc1cac3..8520aa77b 100644 --- a/src/main/java/jikan/command/ViewGoalsCommand.java +++ b/src/main/java/jikan/command/ViewGoalsCommand.java @@ -51,7 +51,7 @@ private void getGoalData(ActivityList activityList, HashMap ta } Ui.printGoals(tagsGoals, tagsActual); } catch (NullPointerException | EmptyTagException e) { - Ui.printDivider("There are no tags to display!"); + Ui.printDivider("There are no tags to display."); } } @@ -68,11 +68,9 @@ private void populateTagList(File dataFile, HashMap tagsGoals) parseDataLine(dataScanner.nextLine(), tagsGoals); } } catch (FileNotFoundException e) { - System.out.println("Data file not found. Could not load into the current session's tag list!"); - } catch (InvalidTimeFrameException e) { - System.out.println("Invalid time frame!"); + System.out.println("Data file not found. Could not load into the current session's tag list."); } catch (NullPointerException e) { - System.out.println("Error!"); + System.out.println("Error."); } } @@ -81,7 +79,7 @@ private void populateTagList(File dataFile, HashMap tagsGoals) * * @param s String to parse. */ - private void parseDataLine(String s, HashMap tagsGoals) throws InvalidTimeFrameException { + private void parseDataLine(String s, HashMap tagsGoals) { if (!s.isEmpty()) { List strings = Arrays.asList(s.split(",")); Duration duration = Duration.parse(strings.get(1)); diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index 724960fc8..1789e600c 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -73,7 +73,7 @@ public Command parseUserCommands(Scanner scanner, File tagFile) throws EmptyName switch (instruction) { case "bye": if (tokenizedInputs.length > 1 && !tokenizedInputs[1].isBlank()) { - Ui.printDivider("Extra parameters detected!"); + Ui.printDivider("Extra parameters detected."); break; } command = new ByeCommand(null); @@ -83,19 +83,19 @@ public Command parseUserCommands(Scanner scanner, File tagFile) throws EmptyName command = new StartCommand(tokenizedInputs[1], scanner); } catch (NullPointerException | ArrayIndexOutOfBoundsException e) { makeInfoLog("Activity started without activity name"); - Ui.printDivider("Start command cannot be empty"); + Ui.printDivider("Activity name cannot be empty."); } break; case "end": if (tokenizedInputs.length > 1 && !tokenizedInputs[1].isBlank()) { - Ui.printDivider("Extra parameters detected!"); + Ui.printDivider("Extra parameters detected."); break; } command = new EndCommand(null); break; case "abort": if (tokenizedInputs.length > 1 && !tokenizedInputs[1].isBlank()) { - Ui.printDivider("Extra parameters detected!"); + Ui.printDivider("Extra parameters detected."); break; } command = new AbortCommand(null); @@ -111,7 +111,7 @@ public Command parseUserCommands(Scanner scanner, File tagFile) throws EmptyName try { command = new DeleteCommand(tokenizedInputs[1]); } catch (ArrayIndexOutOfBoundsException e) { - Ui.printDivider("Activity name cannot be empty!"); + Ui.printDivider("Activity name cannot be empty."); } break; case "find": @@ -132,7 +132,7 @@ public Command parseUserCommands(Scanner scanner, File tagFile) throws EmptyName try { command = new EditCommand(tokenizedInputs[1]); } catch (StringIndexOutOfBoundsException | ArrayIndexOutOfBoundsException e) { - Ui.printDivider("Activity name cannot be empty!"); + Ui.printDivider("Activity name cannot be empty."); makeInfoLog("Edit command failed as there was no existing activity name provided."); } break; @@ -147,7 +147,7 @@ public Command parseUserCommands(Scanner scanner, File tagFile) throws EmptyName try { command = new ContinueCommand(tokenizedInputs[1]); } catch (ArrayIndexOutOfBoundsException e) { - Ui.printDivider("Activity name cannot be empty!"); + Ui.printDivider("Activity name cannot be empty."); makeInfoLog("Continue command failed as there was no activity name provided."); } break; @@ -170,7 +170,7 @@ public Command parseUserCommands(Scanner scanner, File tagFile) throws EmptyName command = new GoalCommand(tokenizedInputs[1], scanner); } } catch (StringIndexOutOfBoundsException e) { - Ui.printDivider("Tag name cannot be empty!"); + Ui.printDivider("Tag name cannot be empty."); } break; default: diff --git a/src/main/java/jikan/storage/StorageHandler.java b/src/main/java/jikan/storage/StorageHandler.java index 5f1d0aaa7..3707c4192 100644 --- a/src/main/java/jikan/storage/StorageHandler.java +++ b/src/main/java/jikan/storage/StorageHandler.java @@ -44,23 +44,9 @@ public void removeLine(int lineNumber, Storage storage) throws IOException { List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(storage.dataFilePath), StandardCharsets.UTF_8)); - //int removedIndex = 0; - fileContent.remove(lineNumber); saveNewList(fileContent, storage.dataFile); - - /* - // Remove line from fileContent list - removedIndex = removeLineFromList(lineNumber, fileContent, removedIndex); - - // Rewrite list into data file - Files.write(Paths.get(dataFilePath), fileContent, StandardCharsets.UTF_8); - - // Update indexes of subsequent lines - updateIndexes(fileContent, removedIndex, dataFilePath); - - */ } /** @@ -96,111 +82,4 @@ public void saveNewList(List newList, File dataFile) throws IOException printWriter.close(); fileOutputStream.close(); } - - /** - * Removes line from a list based on its index. Returns index at which the line was removed. - * - * @param lineNumber Index of line to remove. - * @param list List of strings containing lines, each with a starting index. - * @param removedIndex Index at which line was removed. - * @return Index of the removed line. - */ - private static int removeLineFromList(int lineNumber, List list, int removedIndex) { - assert lineNumber >= 0 : "lineNumber cannot be negative"; - // Iterate through the lines - for (int i = 0; i < list.size(); i++) { - // If the current line matches the taskId - if (list.get(i).startsWith(String.valueOf(lineNumber))) { - // Remove current line - removedIndex = i; // Store index of removed line to use as initial index of next loop - list.remove(i); - break; - } - } - return removedIndex; - } - - /** - * After a line has been removed, updates subsequent indexes. - * - * @param fileContent List of strings from the data file. - * @param removedIndex Index at which line was removed. - * @param dataFilePath Path to data file. - * @throws IOException If an error occurs while writing to file. - */ - private static void updateIndexes(List fileContent, int removedIndex, String dataFilePath) - throws IOException { - assert dataFilePath != null : "dataFilePath cannot be null."; - // Update indexes of subsequent tasks (e.g. if you remove task 2, task 3 becomes task 2) - for (int i = removedIndex; i < fileContent.size(); i++) { - // Get current comma separated string - String currString = fileContent.get(i); - - String updatedString = decrementIndex(currString, i); - - // Replace the line with the updated string - replaceLine(i + 1, updatedString, dataFilePath); - } - } - - /** - * Decrements index at beginning of string by 1. - * - * @param currString String whose index must be decremented. - * @param i Index that the currString's index must be set to. - * @return Original string with its index decremented by 1. - */ - private static String decrementIndex(String currString, int i) { - assert i >= 0 : "i cannot be negative."; - - // Split into different cells - List cells = Arrays.asList(currString.split(",")); - - // Change first cell (taskID) to new ID (taskID-1) - // Task 3 becomes task 2, task 4 becomes task 3, until end of list - cells.set(0, String.valueOf(i)); - - // Recombine the comma separated string - return String.join(",", cells); - } - - /** - * Replaces line in a data file. - * - * @param lineNumber Index of the line to replace. - * @param newString String that replaces the original line. - * @param dataFilePath Path to data file. - * @throws IOException If an error occurs while writing to file. - */ - public static void replaceLine(int lineNumber, String newString, String dataFilePath) throws IOException { - assert dataFilePath != null : "dataFilePath cannot be null."; - // Read file into list of strings, where each string is a line in the file - List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(dataFilePath), StandardCharsets.UTF_8)); - - // Replace line in the list of strings - replaceLineInList(lineNumber, newString, fileContent); - - // Write new list of strings to file - Files.write(Paths.get(dataFilePath), fileContent, StandardCharsets.UTF_8); - } - - /** - * Replaces a line in a list of Strings. - * - * @param lineNumber Number at which line must be replaced. - * @param newString String that replaces the original string. - * @param list List of strings. - */ - private static void replaceLineInList(int lineNumber, String newString, List list) { - assert lineNumber >= 0 : "lineNumber cannot be negative"; - // Iterate through the lines - for (int i = 0; i < list.size(); i++) { - // If the current line matches the taskId - if (list.get(i).startsWith(String.valueOf(lineNumber))) { - // Replace it with the new task string - list.set(i, newString); - break; - } - } - } } From 2917627bc2411b1344a7c509ef984653563bd3b0 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 12:50:38 +0800 Subject: [PATCH 306/415] Delete unused methods in storage handler --- src/test/java/jikan/storage/StorageHandlerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/jikan/storage/StorageHandlerTest.java b/src/test/java/jikan/storage/StorageHandlerTest.java index eb31ff5f8..7bd0d4cb9 100644 --- a/src/test/java/jikan/storage/StorageHandlerTest.java +++ b/src/test/java/jikan/storage/StorageHandlerTest.java @@ -65,7 +65,7 @@ public void test_replaceLine() throws IOException { int j = 0; Scanner dataScanner = new Scanner(storage.dataFile); - StorageHandler.replaceLine(2, replace, storage.dataFilePath); + //StorageHandler.replaceLine(2, replace, storage.dataFilePath); String replacedString = ""; From 792fe4903a5ad35c25868b3d2cacbdd6baf14d24 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Fri, 10 Apr 2020 12:51:49 +0800 Subject: [PATCH 307/415] FindCommandTest --- .../java/jikan/command/FilterCommandTest.java | 83 ++++++++++++++++ .../java/jikan/command/FindCommandTest.java | 96 +++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 src/test/java/jikan/command/FilterCommandTest.java create mode 100644 src/test/java/jikan/command/FindCommandTest.java diff --git a/src/test/java/jikan/command/FilterCommandTest.java b/src/test/java/jikan/command/FilterCommandTest.java new file mode 100644 index 000000000..597457787 --- /dev/null +++ b/src/test/java/jikan/command/FilterCommandTest.java @@ -0,0 +1,83 @@ +package jikan.command; + +import jikan.Jikan; +import jikan.activity.Activity; +import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; +import jikan.exception.ExtraParametersException; +import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; +import jikan.storage.Storage; +import org.junit.jupiter.api.Test; + +import java.io.FileNotFoundException; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashSet; + +import static org.junit.jupiter.api.Assertions.*; + +class FilterCommandTest { + ActivityList activities = new ActivityList(); + HashSet tags1 = new HashSet<>(); + HashSet tags2 = new HashSet<>(); + ArrayList expected = new ArrayList<>(); + Activity activity1; + Activity activity2; + Activity activity3; + + void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { + activities.storage = new Storage("data/activityList_test.txt"); + activities.activities.clear(); + try { + activities.storage.clearFile(); + } catch (FileNotFoundException e) { + System.out.println("Could not find file."); + } + tags1.add("tagA"); + tags1.add("tagB"); + tags2.add("tagC"); + tags2.add("tagD"); + LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); + LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); + Duration duration = Duration.between(startTime, endTime); + Duration allocatedTime = Duration.parse("PT0S"); + activity1 = new Activity("subject1 quiz", startTime, endTime, duration, tags1, allocatedTime); + activity2 = new Activity("subject2 quiz", startTime, endTime, duration, tags1, allocatedTime); + activity3 = new Activity("subject1 final", startTime, endTime, duration, tags2, allocatedTime); + activities.add(activity1); + activities.add(activity2); + activities.add(activity3); + } + + void populateExpected1() { + expected.clear(); + expected.add(activity1); + expected.add(activity2); + } + + void populateExpected2() { + expected.clear(); + expected.add(activity3); + } + + @Test + void executeCommand() { + try { + populateActivityList(); + String parameters1 = "quiz"; + String parameters2 = "final"; + Command command1 = new FindCommand(parameters1); + command1.executeCommand(activities); + populateExpected1(); + assertEquals(Jikan.lastShownList.activities, expected); + Command command2 = new FindCommand(parameters2); + command2.executeCommand(activities); + populateExpected2(); + assertEquals(Jikan.lastShownList.activities, expected); + } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { + System.out.println("Field error."); + } + } +} \ No newline at end of file diff --git a/src/test/java/jikan/command/FindCommandTest.java b/src/test/java/jikan/command/FindCommandTest.java new file mode 100644 index 000000000..d035ce8d4 --- /dev/null +++ b/src/test/java/jikan/command/FindCommandTest.java @@ -0,0 +1,96 @@ +package jikan.command; + +import jikan.Jikan; +import jikan.activity.Activity; +import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; +import jikan.exception.ExtraParametersException; +import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; +import jikan.storage.Storage; +import org.junit.jupiter.api.Test; + +import java.io.FileNotFoundException; +import java.lang.reflect.Array; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashSet; + +import static org.junit.jupiter.api.Assertions.*; + +class FindCommandTest { + ActivityList activities = new ActivityList(); + HashSet tags = new HashSet<>(); + ArrayList expected = new ArrayList<>(); + Activity activity1; + Activity activity2; + Activity activity3; + + void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { + activities.storage = new Storage("data/activityList_test.txt"); + activities.activities.clear(); + try { + activities.storage.clearFile(); + } catch (FileNotFoundException e) { + System.out.println("Could not find file."); + } + tags.add("tag1"); + tags.add("tag2"); + LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); + LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); + Duration duration = Duration.between(startTime, endTime); + Duration allocatedTime = Duration.parse("PT0S"); + activity1 = new Activity("subject1 quiz", startTime, endTime, duration, tags, allocatedTime); + activity2 = new Activity("subject2 quiz", startTime, endTime, duration, tags, allocatedTime); + activity3 = new Activity("subject1 final", startTime, endTime, duration, tags, allocatedTime); + activities.add(activity1); + activities.add(activity2); + activities.add(activity3); + } + + void populateExpected1() { + expected.clear(); + expected.add(activity1); + expected.add(activity2); + } + + void populateExpected2() { + expected.clear(); + expected.add(activity3); + } + + void populateExpected3() { + expected.clear(); + expected.add(activity2); + expected.add(activity3); + } + + @Test + void executeCommand() { + try { + populateActivityList(); + String parameters1 = "quiz"; + String parameters2 = "final"; + String parameters3 = "subject2 / final"; + + Command command1 = new FindCommand(parameters1); + command1.executeCommand(activities); + populateExpected1(); + assertEquals(Jikan.lastShownList.activities, expected); + + Command command2 = new FindCommand(parameters2); + command2.executeCommand(activities); + populateExpected2(); + assertEquals(Jikan.lastShownList.activities, expected); + + Command command3 = new FindCommand(parameters3); + command3.executeCommand(activities); + populateExpected3(); + assertEquals(Jikan.lastShownList.activities, expected); + + } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { + System.out.println("Field error."); + } + } +} \ No newline at end of file From 06283cfc3b8a9c39dc54d3d8f4729ea54855d8cb Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Fri, 10 Apr 2020 12:59:22 +0800 Subject: [PATCH 308/415] Filter Command Test --- .../java/jikan/command/FilterCommandTest.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/test/java/jikan/command/FilterCommandTest.java b/src/test/java/jikan/command/FilterCommandTest.java index 597457787..5794941f5 100644 --- a/src/test/java/jikan/command/FilterCommandTest.java +++ b/src/test/java/jikan/command/FilterCommandTest.java @@ -62,20 +62,36 @@ void populateExpected2() { expected.add(activity3); } + void populateExpected3() { + expected.clear(); + expected.add(activity1); + expected.add(activity2); + expected.add(activity3); + } + @Test void executeCommand() { try { populateActivityList(); - String parameters1 = "quiz"; - String parameters2 = "final"; - Command command1 = new FindCommand(parameters1); + String parameters1 = "tagA"; + String parameters2 = "tagC"; + String parameters3 = "tagA tagC tagD"; + + Command command1 = new FilterCommand(parameters1); command1.executeCommand(activities); populateExpected1(); assertEquals(Jikan.lastShownList.activities, expected); - Command command2 = new FindCommand(parameters2); + + Command command2 = new FilterCommand(parameters2); command2.executeCommand(activities); populateExpected2(); assertEquals(Jikan.lastShownList.activities, expected); + + Command command3 = new FilterCommand(parameters3); + command3.executeCommand(activities); + populateExpected3(); + assertEquals(Jikan.lastShownList.activities, expected); + } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { System.out.println("Field error."); } From faf0d1dd8434a7ae53db6a0b68ab8a4ba585c5e0 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 13:06:43 +0800 Subject: [PATCH 309/415] Edit continue to only accept y/n inputs --- src/main/java/jikan/command/GoalCommand.java | 24 ++++++++++--------- src/main/java/jikan/command/StartCommand.java | 4 +++- 2 files changed, 16 insertions(+), 12 deletions(-) diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index 70b5a2434..9c033754a 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -80,14 +80,14 @@ public void executeCommand(ActivityList activityList) { throw new NoSuchTagException(); } else { addTagLine(tagName + "," + goalTime); - Ui.printDivider("The goal for " + tagName + " has been added!"); + Ui.printDivider("The goal for " + tagName + " has been added."); } } } else if (deleteDelim != -1) { tagName = parameters.substring(0, deleteDelim - 1).strip(); index = checkIfExists(tagName); if (index != -1) { - Ui.printDivider("The goal for this tag has been deleted!"); + Ui.printDivider("The goal for this tag has been deleted."); deleteLine(index); } else { throw new NoSuchTagException(); @@ -97,22 +97,22 @@ public void executeCommand(ActivityList activityList) { } } catch (EmptyTagException e) { - Ui.printDivider("Tag name cannot be empty!"); + Ui.printDivider("Tag name cannot be empty."); Log.makeInfoLog("Goal command failed as no tag name was provided."); } catch (InvalidGoalCommandException e) { - Ui.printDivider("Invalid command format entered!"); + Ui.printDivider("Invalid command format entered."); Log.makeInfoLog("Goal command failed as an incorrect format was provided."); } catch (IOException e) { - Ui.printDivider("Error reading the file!"); + Ui.printDivider("Error reading the file."); } catch (NoSuchTagException e) { - Ui.printDivider("There is no such tag!"); + Ui.printDivider("There is no such tag."); Log.makeInfoLog("Goal command failed as there was no such tag saved."); } catch (ArrayIndexOutOfBoundsException | StringIndexOutOfBoundsException | EmptyGoalException | NumberFormatException e) { - Ui.printDivider("Please enter the goal in the format HH:MM:SS"); + Ui.printDivider("Please enter the goal in the format HH:MM:SS."); Log.makeInfoLog("Goal command failed as an incorrect format for the goal time was provided."); } catch (NegativeDurationException e) { - Ui.printDivider("Please enter a positive goal time!"); + Ui.printDivider("Please enter a positive goal time."); Log.makeInfoLog("Goal command failed as a negative goal time was provided."); } } @@ -130,7 +130,9 @@ public static void createFile(String filePath, File tagFile) { tagFile.createNewFile(); } } catch (IOException e) { - System.out.println("Error loading/creating file"); + Ui.printDivider("Error saving tag goal to data file.\n" + + "Your changes have not been saved in the data file.\n" + + "If the data file is open, please close it, restart the app and try again."); } } @@ -181,11 +183,11 @@ private static void updateGoal(String userInput, String tagName, Duration goalTi if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { deleteLine(index); writeToFile(tagName + "," + goalTime); - Ui.printDivider("The goal for " + tagName + " was updated"); + Ui.printDivider("The goal for " + tagName + " was updated."); } else if (userInput.equalsIgnoreCase("no") || userInput.equalsIgnoreCase("n")) { Ui.printDivider("Okay then, what else can I do for you?"); } else { - Ui.printDivider("Incorrect format entered, please only enter yes or no!"); + Ui.printDivider("Incorrect format entered, please only enter yes or no."); } } diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 064b05b17..6e2e93252 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -387,9 +387,11 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, Parser.continuedIndex = index; Ui.printDivider(Parser.activityName + " was continued"); Log.makeFineLog(Parser.activityName + " was continued."); - } else { + } else if (userInput.equalsIgnoreCase("no") || userInput.equalsIgnoreCase("n")){ Parser.activityName = null; Ui.printDivider("Okay then, what else can I do for you?"); + } else { + Ui.printDivider("Incorrect format entered, please only enter yes or no."); } } } From 0d81f424ffc90ebfb03bb99af98d6ec73642c06b Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Fri, 10 Apr 2020 13:08:25 +0800 Subject: [PATCH 310/415] Add to UG --- docs/UserGuide.md | 119 +++++++++++++++------- docs/pictures/afterClean.png | Bin 0 -> 25210 bytes docs/pictures/cleanEg.png | Bin 0 -> 11366 bytes docs/pictures/cleanlist.png | Bin 0 -> 28781 bytes docs/pictures/graphallocations.png | Bin 0 -> 11240 bytes docs/pictures/listforgraphallocations.png | Bin 0 -> 17211 bytes 6 files changed, 83 insertions(+), 36 deletions(-) create mode 100644 docs/pictures/afterClean.png create mode 100644 docs/pictures/cleanEg.png create mode 100644 docs/pictures/cleanlist.png create mode 100644 docs/pictures/graphallocations.png create mode 100644 docs/pictures/listforgraphallocations.png diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 45159dbfb..d2715f138 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -26,10 +26,13 @@ Jikan lets you record how much time you spend on various activities so that you To start, record your first activity using the `start ACTIVITY_NAME` command. -Add some tags to your activities to group similar activities together using `/t`. Tags help you group activities of the same type together, in this example, we use the tags feature to label activities according to their module code. +Add some tags to your activities to group similar activities together using `/t`. Tags help you group activities of the same type together, +in this example, we use the tags feature to label activities according to their module code. +**(Note that each activity can only store two tags at maximum.)** + +Add allocated time to your activities using `/a`. This allows users to set aside how much time they would like to spend on an activity and +keep track on whether they are spending too much or too little time for that particular activity. -Add allocated time to your activities using `/a`. - When you are done with the activity, or want to move onto something else, tell Jikan to `end` and the Activity time will be recorded and saved to your list. You can view all your activities using the `list` command. Or view all your activities over a period of time by using `list` with extra parameters. For example `list week` will return a list of all activities this current week, as shown below. @@ -39,14 +42,14 @@ The list still looks very cluttered, we can reduce it further! Want to find ever ![Continue command sequence diagram](./pictures/filter.PNG) To easily see what took up the most of your time out of all the 2113 activities, use the `graph` command to view a chart of your activities. -![Continue command sequence diagram](./pictures/graph.PNG) +![Continue command sequence diagram](./pictures/graph.png) Curious about what module took up the most time this week? We can use the `graph tags` command on our weekly activity list to find out. ![Continue command sequence diagram](./pictures/graphtags.PNG) Evidently, it was CS2105. -Not done with an activity and want to continue it? Use the `continue` command to continue recording time for a previously started activity. +Not done with an activity and want to continue on it? Use the `continue` command to continue recording time for a previously started activity. Finally, when you're done and want to close the app, simply say `bye` and Jikan will exit. @@ -60,7 +63,7 @@ This is just a quick overview of what Jikan can do for you. For more details on * `ACTIVITY_NAME` can contains spaces and must be less than 25 characters. * `ACTIVITY_NAME` must also be unique (should the user start an already existing activity, the option to `continue` will be given). * `ALLOCATED_TIME` should be of the format [HH:MM:SS] and cannot exceed 23:59:59. -* `TAGS` must be single spaced separated. +* `TAGS` must be single spaced separated and a maximum of 2 tags can be stored. * `ALLOCATED_TIME` and `TAGS` are optional. **Example:** @@ -143,8 +146,8 @@ By using `find` and `filter` commands, the user can reduce clutter and zoom-in t * `filter TAGNAME1 TAGNAME2` ### Chaining Lists, Finds & Filters: `-s` -**Usage:** The user to `find` and `filter` based on the last shown list by providing the `-s` immediately each -`find` or `filter`. +**Usage:** Users can provide the `find` and `filter` command on the last shown list by providing the `-s` flag after each +`find` or `filter` command. **Format:** * `find -s KEYWORD` @@ -188,8 +191,9 @@ Here are the matching activities in your list: ------------------------------------------------------------------------------------------ ``` **Example:** -![chain graph activities](./pictures/filter-find_chain.PNG) If we want to find all CS2106 tutorials, we can first use `filter 2106` to filter out all activities tagged `2106`, then use the find command with the flag, `find -s Tutorial` to get a list of all 2106 Tutorials. +![chain graph activities](./pictures/filter-find_chain.PNG) + ## Graphs By using the following commands, users can get a visual representation of the time spent on each activity and their current progress. @@ -216,6 +220,7 @@ Note: As the units of `SCALE` is minutes, if your activity is less than a minute **Usage:** View a comparison of the absolute time spent on each tag in the last shown list. ![graph tags](./pictures/graphtags_example.PNG) + For example, if we `graph tags 1` for the activity list above, we will get the following graph: ![graph tags](./pictures/graphtags_example2.png) @@ -231,11 +236,21 @@ As tags can be used to group activities of a similar nature together (i.e. same **Example:** `graph tags 1` -### Activity targets graph: `graph targets` -**Usage:** View the progress of activities to see how much time was spent on the activity relative to the time that was allocated. +### Activity targets graph: `graph allocations` +**Usage:** View the progress of activities to see how much time was spent on the activity relative to the allocated time. Note: Only activities with an `ALLOCATED_TIME` will be shown. +![graph_allocations](./pictures/listforgraphallocations.png) + +For example, if we `graph allocations` for the activity list above, we will get the following graph: + +![graph_allocations](./pictures/graphallocations.png) + +`activity 3` and `activity 5` does not have an allocated time, thus they do not appear in the graph. +The percentage shown in the graph represents the activity's progress relative to their allocated time. (`activity 4` have a duration of 2 seconds while its allocated time was 5 seconds, 2/5 * 100% = 40%. Thus the progress of `activity 4` is 40% +as shown in the graph) + **Format:** `graph allocations` @@ -244,17 +259,18 @@ Using `list`, `find` and `filter` commands you can sieve out the information you **Graph Activities Example:** ![chain graph activities](./pictures/filter-graph_chain.PNG) + `filter 2113` gives all activities tagged `2113`, then we can use `graph activities 5` to view a graph of the duration for each activity. **Graph Tags Example:** ![chain graph tags](./pictures/list-graphtags_chain.PNG) + `list 25/03/2020` gives all activities completed on 25th March 2020, then we can use `graph tags 5` to view the graph of the tags. Each asterisk represents 5 minutes, as indicated by the `SCALE` parameter of the graph command. **Graph Allocations Example:** ![chain graph tags](./pictures/find-allocations_chain.PNG) -`find Lab` gives us all `Lab` activities, then we can use `graph allocations` to view the progress bar of each of the activities to see how much time was spent on the activity relative to the time that was allocated. - +`find Lab` gives us all `Lab` activities, then we can use `graph allocations` to view the progress bar of each of the activities to see how much time was spent on the activity relative to the time that was allocated. ## Tag Goals @@ -279,37 +295,68 @@ By using the `goal` command, users can set specific goals for how long they woul **Format:** `goal` ![goal display](./pictures/GoalDisplay.PNG) -## Usage of Automated Cleaning +## Automated Cleaning + +Jikan provides a `clean` command where users can automate the cleaning of activities from the activity list at application startup. + +### Activate cleaning: `clean on` +**Usage:** Switch on automated cleaning. + +**Format:** `clean on` + +### Deactivate cleaning: `clean off` +**Usage:** Switch off automated cleaning. + +**Format:** `clean off` + +### Set the number of activities to clean: `clean /n` +**Usage:** Set a number of activities to clean. + +**Format:** `clean /n NUMBER` + +Note: Once cleaning is switched on, the automated cleaning persists (i.e cleaning will be done at every application startup) until it is switched off. + +**Example:** + +![CleanExample](./pictures/cleanlist.png) + +Taking a look at this cluttered activity list, we can see that there are some activities which are done (i.e duration > allocation). +Thus, to reduce clutter, we would like to get rid of these done activities. + +However, since the list is so huge, it would be troublesome to use the delete function as users will have to manually navigate through +the list to identify the done activities and delete them. + +This is where the `clean` command would be useful. See that activity 6, 7 and 10 are done. + +![CleanExample](./pictures/cleanEg.png) + +By using the `clean` command. Users can choose how much of these done activities to clean, for the example here, the number is set to 2. + +![CleanExample](./pictures/afterClean.png) + +Upon the next startup, the automated cleaning will do its work and clean the 2 oldest done activities (i.e oldest here is based on date). + +Note that since the user specified to clean only 2 activities, only activity 6 and 7 are cleaned and activity 10 remains in the activity list. -As Jikan is a time tracker application which works with various data files (data file for activities, log files for execution history -etc.), over time it can be a mess to deal with these data files especially when they get too big. Thus, Jikan provides automated cleaning -services for such situations. +### Automated Cleaning for Logs: -### Activating the automated cleaning: `clean on | clean log on` -At runtime, users can switch on the automated cleaning services. Once the automated cleaning is activated, the application will -do an auto cleanup of files at the start of every execution until this services is switch off. Do note that the cleaning will only start from the next execution. -(i.e no cleaning will be done for the current execution which activated auto cleaning). +Jikan also provides cleaning for log file which are used to record important information during program execution. This feature will be useful +to users who are running this application on systems with limited hardware (small storage space). -Note: \ -`clean on` activates the cleaning of data files where activities are stored. \ -`clean log on` activates the cleaning of log files where application execution history is stored. +### Activate log cleaning: `clean log on` +**Usage:** Switch on automated cleaning. -### Deactivating the automated cleaning: `clean off | clean log off` -At runtime, users can switch off the automated cleaning services. Once deactivated, the application will -stop doing an auto cleanup of files at the start of every execution. Similarly, the changes only applies to the next execution. +**Format:** `clean log on` -Note:\ -When the application is executed for the first time, the automated cleaning is deactivated by default and will remain so until it is activated by the user. +### Deactivate log cleaning: `clean log off` +**Usage:** Switch off automated cleaning. -### Specifying how much data to clean: `clean /n NUMBER | clean log /n NUMBER` -At runtime, the user can manually set the amount of data to clean using these commands where `NUMBER` is an integer based on user input. -Thus, `clean /n 5` will automatically clean the top 5 oldest activities from the activity list upon every startup (assuming automated cleaning -is activated). +**Format:** `clean log off` -Note:\ -Default `NUMBER` value for data files : 3\ -Default `NUMBER` value for log files : 10 +### Set the number of logs to clean: `clean log /n` +**Usage:** Set number of lines of logs to clean. +**Format:** `clean log /n NUMBER` ## Command Guide diff --git a/docs/pictures/afterClean.png b/docs/pictures/afterClean.png new file mode 100644 index 0000000000000000000000000000000000000000..020f87a219d4b993e6045ed7a0cd4a69d0bb3242 GIT binary patch literal 25210 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 literal 0 HcmV?d00001 diff --git a/docs/pictures/cleanlist.png b/docs/pictures/cleanlist.png new file mode 100644 index 0000000000000000000000000000000000000000..24368c7c67c24090511e83f3b703dac75ff1df43 GIT binary patch literal 28781 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 literal 0 HcmV?d00001 diff --git a/docs/pictures/graphallocations.png b/docs/pictures/graphallocations.png new file mode 100644 index 0000000000000000000000000000000000000000..d3bca715a10de080acd9a3c722ce607cd80eca36 GIT binary patch literal 11240 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 VQfPf;oOn_rmFJoYmGYKv{tf=(p*;Wq literal 0 HcmV?d00001 diff --git a/docs/pictures/listforgraphallocations.png b/docs/pictures/listforgraphallocations.png new file mode 100644 index 0000000000000000000000000000000000000000..547eb1abb2043ba330e9772bf11db0ee05f2e58b GIT binary patch literal 17211 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 AI{*Lx literal 0 HcmV?d00001 From 6e3f5b8a6430e03eb419cef9017e24bfb31e0529 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 13:15:57 +0800 Subject: [PATCH 311/415] Fix style and text ui --- src/main/java/jikan/command/ListCommand.java | 12 ++- src/main/java/jikan/command/StartCommand.java | 2 +- text-ui-test/EXPECTED.TXT | 75 ++++--------------- text-ui-test/input.txt | 9 --- 4 files changed, 23 insertions(+), 75 deletions(-) diff --git a/src/main/java/jikan/command/ListCommand.java b/src/main/java/jikan/command/ListCommand.java index fc6e77efe..d1b1ff030 100644 --- a/src/main/java/jikan/command/ListCommand.java +++ b/src/main/java/jikan/command/ListCommand.java @@ -7,7 +7,10 @@ import jikan.exception.InvalidTimeFrameException; -import java.time.*; +import java.time.LocalDate; +import java.time.DayOfWeek; +import java.time.Month; +import java.time.YearMonth; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeParseException; import java.time.temporal.TemporalAdjusters; @@ -101,7 +104,9 @@ private void listInterval(ActivityList activityList) // Fallthrough case "monthly": startDate = getStartOfMonth(listInputs); - if (startDate == null) return; + if (startDate == null) { + return; + } endDate = startDate.with(TemporalAdjusters.lastDayOfMonth()); break; default: @@ -144,7 +149,8 @@ private LocalDate getStartOfWeek(String[] listInputs, DateTimeFormatter parser) } } else { startDate = LocalDate.now(); - } return startDate; + } + return startDate; } private void printList(ActivityList activityList, LocalDate startDate, LocalDate endDate) diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index 6e2e93252..b913f03f9 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -387,7 +387,7 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, Parser.continuedIndex = index; Ui.printDivider(Parser.activityName + " was continued"); Log.makeFineLog(Parser.activityName + " was continued."); - } else if (userInput.equalsIgnoreCase("no") || userInput.equalsIgnoreCase("n")){ + } else if (userInput.equalsIgnoreCase("no") || userInput.equalsIgnoreCase("n")) { Parser.activityName = null; Ui.printDivider("Okay then, what else can I do for you?"); } else { diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index ca9bc9c04..9ded1ea0c 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -10,57 +10,31 @@ What can I do for you today? ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Started: activity 1 +activity 1 was started. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Ended: activity 1 +activity 1 was ended. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Started: activity 2 +activity 2 was started. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Ended: activity 2 +activity 2 was ended. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Started: activity 3 +activity 3 was started. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ activity 3 is ongoing! ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Ended: activity 3 +activity 3 was ended. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ activity 1 was continued ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Ended: activity 1 ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -Your completed activities: - | Name | Duration | Allocation | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag1] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -Here are the matching activities in your list: - - | Name | Duration | Allocation | Date -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -Here are the matching activities in your list: - - | Name | Duration | Allocation | Date -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -Here are the matching activities in your list: - - | Name | Duration | Allocation | Date -1 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag1] +activity 1 was ended. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ There is already an activity with this name. Would you like to continue it? @@ -69,51 +43,28 @@ There is already an activity with this name. Would you like to continue it? activity 1 was continued ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Ended: activity 1 ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -Your completed activities: - | Name | Duration | Allocation | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] -2 | activity 2 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] -3 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag1] +activity 1 was ended. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Please input an integer for the time interval. -If you'd like to graph by tags, enter the command . +Please specify whether you want to graph activities / tags / allocations. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Please specify whether you want to graph activities / tags / targets. ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -Start command cannot be empty +Activity name cannot be empty. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ You have not started any activity! ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -You have not started any activity! +You have not started any activity. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ OOPS!!! I'm sorry, but I don't know what that means :-( ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -No keyword was given. ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -No keyword was given. ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -Activity name cannot be empty! ------------------------------------------------------------------------------------------- ------------------------------------------------------------------------------------------- -You have deleted activity 2 +Activity name cannot be empty. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -Your completed activities: - | Name | Duration | Allocation | Date | Tags -1 | activity 1 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag] -2 | activity 3 | 00:00:00 | 00:00:00 | 2020-04-08 | [tag1] +You have deleted activity 2. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Bye! See you again. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 4d42bc6a2..02e43cb73 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -7,23 +7,14 @@ start activity 4 end continue activity 1 end -list -filter tag -find 1 -find 3 start activity 1 yes end -list week graph -graph 1 start end abort hi -filter -find delete delete activity 2 -list bye \ No newline at end of file From b4c3b59532c83cc81df8d03a788844a46bfc7700 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Fri, 10 Apr 2020 13:25:08 +0800 Subject: [PATCH 312/415] Set theme jekyll-theme-architect --- docs/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index c74188174..3397c9a49 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-slate \ No newline at end of file +theme: jekyll-theme-architect \ No newline at end of file From d3054a36a1c5710793783ed7cdb2614053a05d77 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Fri, 10 Apr 2020 13:26:25 +0800 Subject: [PATCH 313/415] Chaining tests --- .../java/jikan/command/FilterCommandTest.java | 18 +++++++++-- .../java/jikan/command/FindCommandTest.java | 30 +++++++++++++++---- 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/src/test/java/jikan/command/FilterCommandTest.java b/src/test/java/jikan/command/FilterCommandTest.java index 5794941f5..3bfc1e72f 100644 --- a/src/test/java/jikan/command/FilterCommandTest.java +++ b/src/test/java/jikan/command/FilterCommandTest.java @@ -45,7 +45,7 @@ void populateActivityList() throws InvalidTimeFrameException, NameTooLongExcepti Duration allocatedTime = Duration.parse("PT0S"); activity1 = new Activity("subject1 quiz", startTime, endTime, duration, tags1, allocatedTime); activity2 = new Activity("subject2 quiz", startTime, endTime, duration, tags1, allocatedTime); - activity3 = new Activity("subject1 final", startTime, endTime, duration, tags2, allocatedTime); + activity3 = new Activity("subject3 final", startTime, endTime, duration, tags2, allocatedTime); activities.add(activity1); activities.add(activity2); activities.add(activity3); @@ -69,6 +69,11 @@ void populateExpected3() { expected.add(activity3); } + void populateExpected4() { + expected.clear(); + expected.add(activity2); + } + @Test void executeCommand() { try { @@ -76,6 +81,8 @@ void executeCommand() { String parameters1 = "tagA"; String parameters2 = "tagC"; String parameters3 = "tagA tagC tagD"; + String findParameters = "subject2 / subject3"; + String parameters4 = "tag A tag B"; Command command1 = new FilterCommand(parameters1); command1.executeCommand(activities); @@ -91,7 +98,14 @@ void executeCommand() { command3.executeCommand(activities); populateExpected3(); assertEquals(Jikan.lastShownList.activities, expected); - + + Command find = new FindCommand(findParameters); + Command command4 = new FilterCommand(parameters4); + find.executeCommand(activities); + command4.executeCommand(activities); + populateExpected4(); + assertEquals(Jikan.lastShownList.activities, expected); + } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { System.out.println("Field error."); } diff --git a/src/test/java/jikan/command/FindCommandTest.java b/src/test/java/jikan/command/FindCommandTest.java index d035ce8d4..addc78be8 100644 --- a/src/test/java/jikan/command/FindCommandTest.java +++ b/src/test/java/jikan/command/FindCommandTest.java @@ -21,7 +21,8 @@ class FindCommandTest { ActivityList activities = new ActivityList(); - HashSet tags = new HashSet<>(); + HashSet tags1 = new HashSet<>(); + HashSet tags2 = new HashSet<>(); ArrayList expected = new ArrayList<>(); Activity activity1; Activity activity2; @@ -35,15 +36,17 @@ void populateActivityList() throws InvalidTimeFrameException, NameTooLongExcepti } catch (FileNotFoundException e) { System.out.println("Could not find file."); } - tags.add("tag1"); - tags.add("tag2"); + tags1.add("tagA"); + tags1.add("tagB"); + tags2.add("tagC"); + tags2.add("tagD"); LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); Duration duration = Duration.between(startTime, endTime); Duration allocatedTime = Duration.parse("PT0S"); - activity1 = new Activity("subject1 quiz", startTime, endTime, duration, tags, allocatedTime); - activity2 = new Activity("subject2 quiz", startTime, endTime, duration, tags, allocatedTime); - activity3 = new Activity("subject1 final", startTime, endTime, duration, tags, allocatedTime); + activity1 = new Activity("subject1 quiz", startTime, endTime, duration, tags1, allocatedTime); + activity2 = new Activity("subject2 quiz", startTime, endTime, duration, tags2, allocatedTime); + activity3 = new Activity("subject1 final", startTime, endTime, duration, tags2, allocatedTime); activities.add(activity1); activities.add(activity2); activities.add(activity3); @@ -66,6 +69,11 @@ void populateExpected3() { expected.add(activity3); } + void populateExpected4() { + expected.clear(); + expected.add(activity2); + } + @Test void executeCommand() { try { @@ -73,6 +81,8 @@ void executeCommand() { String parameters1 = "quiz"; String parameters2 = "final"; String parameters3 = "subject2 / final"; + String filterParameters = "tagC tagD"; + String parameters4 = "-s quiz"; Command command1 = new FindCommand(parameters1); command1.executeCommand(activities); @@ -89,6 +99,14 @@ void executeCommand() { populateExpected3(); assertEquals(Jikan.lastShownList.activities, expected); + Command filter = new FilterCommand(filterParameters); + Command command4 = new FindCommand(parameters4); + filter.executeCommand(activities); + command4.executeCommand(activities); + populateExpected4(); + System.out.println("sup"); + assertEquals(Jikan.lastShownList.activities, expected); + } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { System.out.println("Field error."); } From 96f8b20cb24514f9df41f4ab8d7a3143d24afc75 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Fri, 10 Apr 2020 13:34:51 +0800 Subject: [PATCH 314/415] Modify goals to use storage and storage handler classes --- src/main/java/jikan/Jikan.java | 10 +++--- src/main/java/jikan/command/GoalCommand.java | 31 +++++++------------ .../java/jikan/command/ViewGoalsCommand.java | 21 +++++++------ src/main/java/jikan/parser/Parser.java | 8 +++-- 4 files changed, 35 insertions(+), 35 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index d3f671597..be1741a92 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -28,6 +28,8 @@ public class Jikan { /** Storage object for data file. */ private static Storage storage; + private static Storage tagStorage; + /** Activity list to store current tasks in. */ private static ActivityList activityList; @@ -46,20 +48,19 @@ public class Jikan { public static final Scanner in = new Scanner(System.in); - public static File tagFile; - /** * Main entry-point for the Jikan application. */ public static void main(String[] args) { ui.printGreeting(); storage = new Storage(DATA_FILE_PATH); + tagStorage = new Storage(TAG_FILE_PATH); storageCleaner = new StorageCleaner(storage); try { storageCleaner.storageAutoClean(); logCleaner.logAutoClean(); activityList = storage.createActivityList(); - GoalCommand.createFile(TAG_FILE_PATH, tagFile); + //GoalCommand.createFile(TAG_FILE_PATH, tagFile); } catch (IOException e) { Ui.printDivider("Error while preparing application."); } @@ -67,10 +68,11 @@ public static void main(String[] args) { lastShownList.activities.addAll(activityList.activities); parser.cleaner = storageCleaner; parser.logcleaner = logCleaner; + parser.tagStorage = tagStorage; while (true) { try { - Command command = parser.parseUserCommands(in, tagFile); + Command command = parser.parseUserCommands(in); if (command == null) { continue; } diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index 70b5a2434..b9dfadcee 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -8,6 +8,8 @@ import jikan.exception.NegativeDurationException; import jikan.exception.NoSuchTagException; import jikan.log.Log; +import jikan.storage.Storage; +import jikan.storage.StorageHandler; import jikan.ui.Ui; import java.io.BufferedReader; @@ -25,7 +27,6 @@ import java.util.Scanner; import static java.lang.Integer.valueOf; -import static jikan.Jikan.tagFile; /** @@ -35,15 +36,20 @@ public class GoalCommand extends Command { private static Scanner scanner; private static final String TAG_FILE_PATH = "data/tag/tag.csv"; + //private static File tagStorage; + public static Storage tagStorage; // Storage the list was loaded from + public static StorageHandler tagStorageHandler; /** * Constructor to create a new goal command. * @param parameters the parameters of the goal command. * @param scanner to read the user input. */ - public GoalCommand(String parameters, Scanner scanner) { + public GoalCommand(String parameters, Scanner scanner, Storage tagStorage) { super(parameters); this.scanner = scanner; + this.tagStorage = tagStorage; + this.tagStorageHandler = new StorageHandler(tagStorage); } @Override @@ -180,7 +186,7 @@ public static int checkIfExists(String tagName) throws IOException { private static void updateGoal(String userInput, String tagName, Duration goalTime, int index) throws IOException { if (userInput.equalsIgnoreCase("yes") || userInput.equalsIgnoreCase("y")) { deleteLine(index); - writeToFile(tagName + "," + goalTime); + tagStorage.writeToFile(tagName + "," + goalTime); Ui.printDivider("The goal for " + tagName + " was updated"); } else if (userInput.equalsIgnoreCase("no") || userInput.equalsIgnoreCase("n")) { Ui.printDivider("Okay then, what else can I do for you?"); @@ -196,7 +202,7 @@ private static void updateGoal(String userInput, String tagName, Duration goalTi */ public static void addTagLine(String dataLine) { try { - writeToFile(dataLine); + tagStorage.writeToFile(dataLine); } catch (IOException e) { System.out.println("Error saving tag to tag file."); } @@ -213,17 +219,16 @@ public static void deleteLine(int lineNumber) throws IOException { List fileContent = new ArrayList<>(Files.readAllLines(Paths.get(TAG_FILE_PATH), StandardCharsets.UTF_8)); fileContent.remove(lineNumber); - saveNewTags(fileContent, tagFile); + saveNewTags(fileContent); } /** * Saves the updated tags to the csv file. * * @param newList The list containing the updated data. - * @param dataFile The file to save to. * @throws IOException If an error occurs while writing the new list to file. */ - public static void saveNewTags(List newList, File dataFile) throws IOException { + public static void saveNewTags(List newList) throws IOException { clearFile(); FileWriter fw = new FileWriter(TAG_FILE_PATH, true); @@ -243,18 +248,6 @@ public static void clearFile() throws IOException { fw.close(); } - /** - * Writes the input string to file. - * - * @param s The input string. - * @throws IOException If an error occurs while writing. - */ - public static void writeToFile(String s) throws IOException { - FileWriter fw = new FileWriter(TAG_FILE_PATH, true); - fw.write(s + System.lineSeparator()); - fw.close(); - } - /** * Check if the tag exists in the activity list. * @param targetList the activity list to check. diff --git a/src/main/java/jikan/command/ViewGoalsCommand.java b/src/main/java/jikan/command/ViewGoalsCommand.java index 60dc1cac3..5a63d7736 100644 --- a/src/main/java/jikan/command/ViewGoalsCommand.java +++ b/src/main/java/jikan/command/ViewGoalsCommand.java @@ -4,8 +4,9 @@ import jikan.activity.ActivityList; import jikan.exception.EmptyTagException; import jikan.exception.InvalidTimeFrameException; +import jikan.storage.Storage; +import jikan.storage.StorageHandler; import jikan.ui.Ui; -import static jikan.Jikan.tagFile; import java.io.File; import java.io.FileNotFoundException; @@ -20,22 +21,25 @@ */ public class ViewGoalsCommand extends Command { - File tagFile; + //File tagFile; private static final String TAG_FILE_PATH = "data/tag/tag.csv"; + public Storage tagStorage; // Storage the list was loaded from + public StorageHandler tagStorageHandler; /** * Constructor to create a new viewgoal command. * @param parameters the parameters of the goal command. */ - public ViewGoalsCommand(String parameters, File tagFile) { + public ViewGoalsCommand(String parameters, Storage tagStorage) { super(parameters); - this.tagFile = tagFile; + this.tagStorage = tagStorage; + this.tagStorageHandler = new StorageHandler(tagStorage); } @Override public void executeCommand(ActivityList activityList) { HashMap tagsGoals = new HashMap<>(); - populateTagList(tagFile, tagsGoals); + populateTagList(tagStorage, tagsGoals); getGoalData(activityList,tagsGoals); } @@ -58,12 +62,11 @@ private void getGoalData(ActivityList activityList, HashMap ta /** * Populates task list from file. * - * @param dataFile Data file to populate from. + * @param tagStorage Storage object containing the tag file. */ - private void populateTagList(File dataFile, HashMap tagsGoals) { + private void populateTagList(Storage tagStorage, HashMap tagsGoals) { try { - tagFile = new File(TAG_FILE_PATH); - Scanner dataScanner = new Scanner(tagFile); + Scanner dataScanner = new Scanner(tagStorage.dataFile); while (dataScanner.hasNext()) { parseDataLine(dataScanner.nextLine(), tagsGoals); } diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index f143708a8..47d209933 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -4,6 +4,7 @@ import jikan.log.Log; import jikan.exception.EmptyNameException; import jikan.cleaner.StorageCleaner; +import jikan.storage.Storage; import jikan.ui.Ui; import jikan.command.AbortCommand; @@ -48,6 +49,7 @@ public class Parser { public static Set tags = new HashSet<>(); public StorageCleaner cleaner; public LogCleaner logcleaner; + public Storage tagStorage; public static String[] tokenizedInputs; String instruction; private static Log logger = new Log(); @@ -60,7 +62,7 @@ public class Parser { * * @param scanner scanner object which reads user input */ - public Command parseUserCommands(Scanner scanner, File tagFile) throws EmptyNameException, + public Command parseUserCommands(Scanner scanner) throws EmptyNameException, NullPointerException, ArrayIndexOutOfBoundsException { makeInfoLog("Starting to parse inputs."); @@ -164,9 +166,9 @@ public Command parseUserCommands(Scanner scanner, File tagFile) throws EmptyName case "goal": try { if (tokenizedInputs.length == 1) { - command = new ViewGoalsCommand(null,tagFile); + command = new ViewGoalsCommand(null, this.tagStorage); } else { - command = new GoalCommand(tokenizedInputs[1], scanner); + command = new GoalCommand(tokenizedInputs[1], scanner, this.tagStorage); } } catch (StringIndexOutOfBoundsException e) { Ui.printDivider("Tag name cannot be empty!"); From 84966c32e09c3b92aea75eb5f22f27803b867dfd Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Fri, 10 Apr 2020 14:08:34 +0800 Subject: [PATCH 315/415] List Command Tests --- .../java/jikan/command/ListCommandTest.java | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 src/test/java/jikan/command/ListCommandTest.java diff --git a/src/test/java/jikan/command/ListCommandTest.java b/src/test/java/jikan/command/ListCommandTest.java new file mode 100644 index 000000000..bf65826dc --- /dev/null +++ b/src/test/java/jikan/command/ListCommandTest.java @@ -0,0 +1,113 @@ +package jikan.command; + +import jikan.Jikan; +import jikan.activity.Activity; +import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; +import jikan.exception.ExtraParametersException; +import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; +import jikan.storage.Storage; +import org.junit.jupiter.api.Test; + +import java.io.FileNotFoundException; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashSet; + +import static org.junit.jupiter.api.Assertions.*; + +class ListCommandTest { + ActivityList activities = new ActivityList(); + ArrayList expected = new ArrayList<>(); + Activity activity1; + Activity activity2; + Activity activity3; + Activity activity4; + + void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { + activities.storage = new Storage("data/activityList_test.txt"); + activities.activities.clear(); + try { + activities.storage.clearFile(); + } catch (FileNotFoundException e) { + System.out.println("Could not find file."); + } + + HashSet tags = new HashSet<>(); + tags.add("tagA"); + tags.add("tagB"); + + LocalDateTime startTime1 = LocalDateTime.parse("2020-01-01T08:00:00"); + LocalDateTime endTime1 = LocalDateTime.parse("2020-01-01T10:00:00"); + LocalDateTime startTime2 = LocalDateTime.parse("2020-01-15T08:00:00"); + LocalDateTime endTime2 = LocalDateTime.parse("2020-01-15T10:00:00"); + LocalDateTime startTime3 = LocalDateTime.parse("2020-03-01T08:00:00"); + LocalDateTime endTime3 = LocalDateTime.parse("2020-03-01T10:00:00"); + Duration duration = Duration.between(startTime1, endTime1); + Duration allocatedTime = Duration.parse("PT0S"); + activity1 = new Activity("subject1 quiz", startTime1, endTime1, duration, tags, allocatedTime); + activity2 = new Activity("subject2 quiz", startTime1, endTime1, duration, tags, allocatedTime); + activity3 = new Activity("subject3 final", startTime2, endTime2, duration, tags, allocatedTime); + activity4 = new Activity("subject4 final", startTime3, endTime3, duration, tags, allocatedTime); + activities.add(activity1); + activities.add(activity2); + activities.add(activity3); + activities.add(activity4); + } + + void populateExpected1() { + expected.clear(); + expected.add(activity1); + expected.add(activity2); + expected.add(activity3); + expected.add(activity4); + } + + void populateExpected2() { + expected.clear(); + expected.add(activity1); + expected.add(activity2); + } + + void populateExpected3() { + expected.clear(); + expected.add(activity1); + expected.add(activity2); + expected.add(activity3); + } + + @Test + void executeCommand() { + try { + populateActivityList(); + String parameters2a = "01/01/2020"; + String parameters2b = "2020-01-01"; + String parameters3 = "01/01/2020 20/02/2020"; + + Command command1 = new ListCommand(null); + command1.executeCommand(activities); + populateExpected1(); + assertEquals(Jikan.lastShownList.activities, expected); + + Command command2a = new ListCommand(parameters2a); + command2a.executeCommand(activities); + populateExpected2(); + assertEquals(Jikan.lastShownList.activities, expected); + + Command command2b = new ListCommand(parameters2b); + command2b.executeCommand(activities); + populateExpected2(); + assertEquals(Jikan.lastShownList.activities, expected); + + Command command3 = new ListCommand(parameters3); + command3.executeCommand(activities); + populateExpected3(); + assertEquals(Jikan.lastShownList.activities, expected); + + } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { + System.out.println("Field error."); + } + } +} \ No newline at end of file From 0c6debe798b87edd8af0ac2631d085afa8a798c3 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Fri, 10 Apr 2020 14:48:43 +0800 Subject: [PATCH 316/415] List Command Tests --- src/test/java/jikan/command/ListCommandTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/jikan/command/ListCommandTest.java b/src/test/java/jikan/command/ListCommandTest.java index bf65826dc..877abf254 100644 --- a/src/test/java/jikan/command/ListCommandTest.java +++ b/src/test/java/jikan/command/ListCommandTest.java @@ -25,6 +25,7 @@ class ListCommandTest { Activity activity2; Activity activity3; Activity activity4; + Activity activity5; void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { activities.storage = new Storage("data/activityList_test.txt"); @@ -55,6 +56,7 @@ void populateActivityList() throws InvalidTimeFrameException, NameTooLongExcepti activities.add(activity2); activities.add(activity3); activities.add(activity4); + } void populateExpected1() { From fe570fca5b3cca8e0c7462ed406313dca8df2005 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Fri, 10 Apr 2020 14:48:52 +0800 Subject: [PATCH 317/415] List Command Tests --- .../java/jikan/command/ListCommandTest.java | 50 ++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/test/java/jikan/command/ListCommandTest.java b/src/test/java/jikan/command/ListCommandTest.java index 877abf254..75430e375 100644 --- a/src/test/java/jikan/command/ListCommandTest.java +++ b/src/test/java/jikan/command/ListCommandTest.java @@ -11,6 +11,7 @@ import org.junit.jupiter.api.Test; import java.io.FileNotFoundException; +import java.time.DayOfWeek; import java.time.Duration; import java.time.LocalDateTime; import java.util.ArrayList; @@ -21,11 +22,15 @@ class ListCommandTest { ActivityList activities = new ActivityList(); ArrayList expected = new ArrayList<>(); + LocalDateTime currentTime = LocalDateTime.now(); + LocalDateTime nextWeek = currentTime.plusWeeks(1); Activity activity1; Activity activity2; Activity activity3; Activity activity4; Activity activity5; + Activity activity6; + void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { activities.storage = new Storage("data/activityList_test.txt"); @@ -52,11 +57,15 @@ void populateActivityList() throws InvalidTimeFrameException, NameTooLongExcepti activity2 = new Activity("subject2 quiz", startTime1, endTime1, duration, tags, allocatedTime); activity3 = new Activity("subject3 final", startTime2, endTime2, duration, tags, allocatedTime); activity4 = new Activity("subject4 final", startTime3, endTime3, duration, tags, allocatedTime); + activity5 = new Activity("subject5 quiz", currentTime, currentTime, duration, tags, allocatedTime); + activity6 = new Activity("subject6 final", currentTime.plusDays(1), currentTime.plusDays(1), duration, tags, allocatedTime); activities.add(activity1); activities.add(activity2); activities.add(activity3); activities.add(activity4); - + activities.add(activity5); + activities.add(activity6); + } void populateExpected1() { @@ -65,6 +74,8 @@ void populateExpected1() { expected.add(activity2); expected.add(activity3); expected.add(activity4); + expected.add(activity5); + expected.add(activity6); } void populateExpected2() { @@ -80,6 +91,19 @@ void populateExpected3() { expected.add(activity3); } + void populateExpected4() { + expected.clear(); + expected.add(activity5); + } + + void populateExpected5() { + expected.clear(); + expected.add(activity5); + if (activity6.getDate().getDayOfWeek() != DayOfWeek.MONDAY) { + expected.add(activity6); + } + } + @Test void executeCommand() { try { @@ -87,6 +111,10 @@ void executeCommand() { String parameters2a = "01/01/2020"; String parameters2b = "2020-01-01"; String parameters3 = "01/01/2020 20/02/2020"; + String parameters4a = "day"; + String parameters4b = "daily"; + String parameters5a = "week"; + String parameters5b = "weekly"; Command command1 = new ListCommand(null); command1.executeCommand(activities); @@ -108,6 +136,26 @@ void executeCommand() { populateExpected3(); assertEquals(Jikan.lastShownList.activities, expected); + Command command4a = new ListCommand(parameters4a); + command4a.executeCommand(activities); + populateExpected4(); + assertEquals(Jikan.lastShownList.activities, expected); + + Command command4b = new ListCommand(parameters4b); + command4b.executeCommand(activities); + populateExpected4(); + assertEquals(Jikan.lastShownList.activities, expected); + + Command command5a = new ListCommand(parameters5a); + command5a.executeCommand(activities); + populateExpected5(); + assertEquals(Jikan.lastShownList.activities, expected); + + Command command5b = new ListCommand(parameters5b); + command5b.executeCommand(activities); + populateExpected5(); + assertEquals(Jikan.lastShownList.activities, expected); + } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { System.out.println("Field error."); } From caba652bcdcaffbac85c2690937d7ed2d0055dca Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Fri, 10 Apr 2020 14:54:50 +0800 Subject: [PATCH 318/415] fixed style error --- src/main/java/jikan/activity/Activity.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index b1e384d43..d286ba899 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -24,6 +24,7 @@ public class Activity { private LocalDate date; public static final int MAXPERCENT = 100; + /** * Constructor for a new activity entry. * @param name represents the name of the activity From d23ad4ffcec9c8e318728c76948eec239a78fa29 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Fri, 10 Apr 2020 15:18:38 +0800 Subject: [PATCH 319/415] Resolve some formatting issues in UG --- docs/UserGuide.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index d2715f138..948ecaf40 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -36,15 +36,19 @@ keep track on whether they are spending too much or too little time for that par When you are done with the activity, or want to move onto something else, tell Jikan to `end` and the Activity time will be recorded and saved to your list. You can view all your activities using the `list` command. Or view all your activities over a period of time by using `list` with extra parameters. For example `list week` will return a list of all activities this current week, as shown below. + ![list week](./pictures/list_week.PNG) The list still looks very cluttered, we can reduce it further! Want to find everything you did for CS2113 this week? Filter out the activities you want to see using the `find` or `filter` command. This is our list after filtering out all our activities tagged as `2113`. (the -s flag tells Jikan to search our last shown list, i.e. the list of activities this week in this case) + ![Continue command sequence diagram](./pictures/filter.PNG) To easily see what took up the most of your time out of all the 2113 activities, use the `graph` command to view a chart of your activities. + ![Continue command sequence diagram](./pictures/graph.png) Curious about what module took up the most time this week? We can use the `graph tags` command on our weekly activity list to find out. + ![Continue command sequence diagram](./pictures/graphtags.PNG) Evidently, it was CS2105. @@ -192,6 +196,7 @@ Here are the matching activities in your list: ``` **Example:** If we want to find all CS2106 tutorials, we can first use `filter 2106` to filter out all activities tagged `2106`, then use the find command with the flag, `find -s Tutorial` to get a list of all 2106 Tutorials. + ![chain graph activities](./pictures/filter-find_chain.PNG) @@ -224,6 +229,7 @@ Note: As the units of `SCALE` is minutes, if your activity is less than a minute For example, if we `graph tags 1` for the activity list above, we will get the following graph: ![graph tags](./pictures/graphtags_example2.png) + `activity 1` and `activity 2` are both tagged `tag1` and have a duration of 5 mins. `activity 3` and `activity 4` are both tagged `tag2` and have a duration of 2 and 3 mins respectively. Adding up the durations for each tag, we get 10 mins for `tag1` and 5 mins for `tag2`. As we chose the graph to have a scale of 1 min, there are (10 asterisk representing 1 min each) for `tag1` and 5 asterisks for `tag2` in the graph. @@ -258,16 +264,19 @@ as shown in the graph) Using `list`, `find` and `filter` commands you can sieve out the information you wish to be graphed. **Graph Activities Example:** + ![chain graph activities](./pictures/filter-graph_chain.PNG) `filter 2113` gives all activities tagged `2113`, then we can use `graph activities 5` to view a graph of the duration for each activity. **Graph Tags Example:** + ![chain graph tags](./pictures/list-graphtags_chain.PNG) `list 25/03/2020` gives all activities completed on 25th March 2020, then we can use `graph tags 5` to view the graph of the tags. Each asterisk represents 5 minutes, as indicated by the `SCALE` parameter of the graph command. **Graph Allocations Example:** + ![chain graph tags](./pictures/find-allocations_chain.PNG) `find Lab` gives us all `Lab` activities, then we can use `graph allocations` to view the progress bar of each of the activities to see how much time was spent on the activity relative to the time that was allocated. @@ -293,6 +302,7 @@ By using the `goal` command, users can set specific goals for how long they woul **Usage:** Displays the tags with their goals, actual time spent on activities with these tags and the difference between the 2 timings. **Format:** `goal` + ![goal display](./pictures/GoalDisplay.PNG) ## Automated Cleaning From 5b872e86596f87add4778bca548b432b6ade59af Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Fri, 10 Apr 2020 15:48:56 +0800 Subject: [PATCH 320/415] added Constants --- src/main/java/jikan/activity/Activity.java | 5 +- .../java/jikan/command/FilterCommandTest.java | 49 +++++---- .../java/jikan/command/FindCommandTest.java | 69 ++++++------ .../java/jikan/command/ListCommandTest.java | 103 +++++++++--------- 4 files changed, 115 insertions(+), 111 deletions(-) diff --git a/src/main/java/jikan/activity/Activity.java b/src/main/java/jikan/activity/Activity.java index 25ab0ffa9..dab89da05 100644 --- a/src/main/java/jikan/activity/Activity.java +++ b/src/main/java/jikan/activity/Activity.java @@ -6,7 +6,6 @@ import java.time.Duration; import java.time.LocalDate; import java.time.LocalDateTime; -import java.util.Arrays; import java.util.Iterator; import java.util.Set; @@ -23,7 +22,7 @@ public class Activity { private Duration allocatedTime; private LocalDate date; - public static final int MAXPERCENT = 100; + public static final int MAX_PERCENT = 100; /** * Constructor for a new activity entry. @@ -109,7 +108,7 @@ public void setAllocatedTime(Duration allocatedTime) { * @return percent completed */ public double getProgressPercent() { - double percent = ((double)this.duration.toMillis() / this.allocatedTime.toMillis()) * MAXPERCENT; + double percent = ((double)this.duration.toMillis() / this.allocatedTime.toMillis()) * MAX_PERCENT; return Math.min(percent, 100); } diff --git a/src/test/java/jikan/command/FilterCommandTest.java b/src/test/java/jikan/command/FilterCommandTest.java index ca3923903..f6803d60e 100644 --- a/src/test/java/jikan/command/FilterCommandTest.java +++ b/src/test/java/jikan/command/FilterCommandTest.java @@ -21,6 +21,13 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; class FilterCommandTest { + + private static final String BASIC_TEST = "tagA"; + private static final String NULL_RESULTS_TEST = "tagZ"; + private static final String MULTI_KEYWORD_TEST = "tagA tagC tagD"; + private static final String FIND_CHAINING_TEST = "subject2 / subject3"; + private static final String CHAINING_TEST = "-s tagA tagB"; + ActivityList activities = new ActivityList(); HashSet tags1 = new HashSet<>(); HashSet tags2 = new HashSet<>(); @@ -53,25 +60,24 @@ void populateActivityList() throws InvalidTimeFrameException, NameTooLongExcepti activities.add(activity3); } - void populateExpected1() { + void populateExpectedBasic() { expected.clear(); expected.add(activity1); expected.add(activity2); } - void populateExpected2() { + void populateExpectedNull() { expected.clear(); - expected.add(activity3); } - void populateExpected3() { + void populateExpectedMultiKeyword() { expected.clear(); expected.add(activity1); expected.add(activity2); expected.add(activity3); } - void populateExpected4() { + void populateExpectedChaining() { expected.clear(); expected.add(activity2); } @@ -80,32 +86,27 @@ void populateExpected4() { void executeCommand() { try { populateActivityList(); - String parameters1 = "tagA"; - String parameters2 = "tagC"; - String parameters3 = "tagA tagC tagD"; - String findParameters = "subject2 / subject3"; - String parameters4 = "tag A tag B"; - - Command command1 = new FilterCommand(parameters1); - command1.executeCommand(activities); - populateExpected1(); + + Command basicTest = new FilterCommand(BASIC_TEST); + basicTest.executeCommand(activities); + populateExpectedBasic(); assertEquals(Jikan.lastShownList.activities, expected); - Command command2 = new FilterCommand(parameters2); - command2.executeCommand(activities); - populateExpected2(); + Command nullResultsTest = new FilterCommand(NULL_RESULTS_TEST); + nullResultsTest.executeCommand(activities); + populateExpectedNull(); assertEquals(Jikan.lastShownList.activities, expected); - Command command3 = new FilterCommand(parameters3); - command3.executeCommand(activities); - populateExpected3(); + Command multiKeywordTest = new FilterCommand(MULTI_KEYWORD_TEST); + multiKeywordTest.executeCommand(activities); + populateExpectedMultiKeyword(); assertEquals(Jikan.lastShownList.activities, expected); - Command find = new FindCommand(findParameters); - Command command4 = new FilterCommand(parameters4); + Command find = new FindCommand(FIND_CHAINING_TEST); + Command chainingTest = new FilterCommand(CHAINING_TEST); find.executeCommand(activities); - command4.executeCommand(activities); - populateExpected4(); + chainingTest.executeCommand(activities); + populateExpectedChaining(); assertEquals(Jikan.lastShownList.activities, expected); } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { diff --git a/src/test/java/jikan/command/FindCommandTest.java b/src/test/java/jikan/command/FindCommandTest.java index 11bb486d8..a282b254d 100644 --- a/src/test/java/jikan/command/FindCommandTest.java +++ b/src/test/java/jikan/command/FindCommandTest.java @@ -11,7 +11,6 @@ import org.junit.jupiter.api.Test; import java.io.FileNotFoundException; -import java.lang.reflect.Array; import java.time.Duration; import java.time.LocalDateTime; import java.util.ArrayList; @@ -22,9 +21,16 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; class FindCommandTest { + + private static final String BASIC_TEST = "quiz"; + private static final String NULL_RESULTS_TEST = "popquiz"; + private static final String MULTI_KEYWORD_TEST = "subject2 / final"; + private static final String FILTER_CHAINING_TEST = "tagC tagD"; + private static final String CHAINING_TEST = "-s quiz"; + ActivityList activities = new ActivityList(); - HashSet tags1 = new HashSet<>(); - HashSet tags2 = new HashSet<>(); + HashSet tagSetVersion1 = new HashSet<>(); + HashSet tagsSetVersion2 = new HashSet<>(); ArrayList expected = new ArrayList<>(); Activity activity1; Activity activity2; @@ -38,40 +44,39 @@ void populateActivityList() throws InvalidTimeFrameException, NameTooLongExcepti } catch (FileNotFoundException e) { System.out.println("Could not find file."); } - tags1.add("tagA"); - tags1.add("tagB"); - tags2.add("tagC"); - tags2.add("tagD"); + tagSetVersion1.add("tagA"); + tagSetVersion1.add("tagB"); + tagsSetVersion2.add("tagC"); + tagsSetVersion2.add("tagD"); LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); Duration duration = Duration.between(startTime, endTime); Duration allocatedTime = Duration.parse("PT0S"); - activity1 = new Activity("subject1 quiz", startTime, endTime, duration, tags1, allocatedTime); - activity2 = new Activity("subject2 quiz", startTime, endTime, duration, tags2, allocatedTime); - activity3 = new Activity("subject1 final", startTime, endTime, duration, tags2, allocatedTime); + activity1 = new Activity("subject1 quiz", startTime, endTime, duration, tagSetVersion1, allocatedTime); + activity2 = new Activity("subject2 quiz", startTime, endTime, duration, tagsSetVersion2, allocatedTime); + activity3 = new Activity("subject1 final", startTime, endTime, duration, tagsSetVersion2, allocatedTime); activities.add(activity1); activities.add(activity2); activities.add(activity3); } - void populateExpected1() { + void populateExpectedBasic() { expected.clear(); expected.add(activity1); expected.add(activity2); } - void populateExpected2() { + void populateExpectedNull() { expected.clear(); - expected.add(activity3); } - void populateExpected3() { + void populateExpectedMultiKeyword() { expected.clear(); expected.add(activity2); expected.add(activity3); } - void populateExpected4() { + void populateExpectedChaining() { expected.clear(); expected.add(activity2); } @@ -80,33 +85,27 @@ void populateExpected4() { void executeCommand() { try { populateActivityList(); - String parameters1 = "quiz"; - String parameters2 = "final"; - String parameters3 = "subject2 / final"; - String filterParameters = "tagC tagD"; - String parameters4 = "-s quiz"; - - Command command1 = new FindCommand(parameters1); - command1.executeCommand(activities); - populateExpected1(); + + Command basicTest = new FindCommand(BASIC_TEST); + basicTest.executeCommand(activities); + populateExpectedBasic(); assertEquals(Jikan.lastShownList.activities, expected); - Command command2 = new FindCommand(parameters2); - command2.executeCommand(activities); - populateExpected2(); + Command nullResultsTest = new FindCommand(NULL_RESULTS_TEST); + nullResultsTest.executeCommand(activities); + populateExpectedNull(); assertEquals(Jikan.lastShownList.activities, expected); - Command command3 = new FindCommand(parameters3); - command3.executeCommand(activities); - populateExpected3(); + Command multiKeywordTest = new FindCommand(MULTI_KEYWORD_TEST); + multiKeywordTest.executeCommand(activities); + populateExpectedMultiKeyword(); assertEquals(Jikan.lastShownList.activities, expected); - Command filter = new FilterCommand(filterParameters); - Command command4 = new FindCommand(parameters4); + Command filter = new FilterCommand(FILTER_CHAINING_TEST); + Command chainingTest = new FindCommand(CHAINING_TEST); filter.executeCommand(activities); - command4.executeCommand(activities); - populateExpected4(); - System.out.println("sup"); + chainingTest.executeCommand(activities); + populateExpectedChaining(); assertEquals(Jikan.lastShownList.activities, expected); } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { diff --git a/src/test/java/jikan/command/ListCommandTest.java b/src/test/java/jikan/command/ListCommandTest.java index aa8936e0d..aefd49cc8 100644 --- a/src/test/java/jikan/command/ListCommandTest.java +++ b/src/test/java/jikan/command/ListCommandTest.java @@ -22,6 +22,23 @@ import static org.junit.jupiter.api.Assertions.assertNotNull; class ListCommandTest { + + private static final String DATE_FORMAT_1 = "01/01/2020"; + private static final String DATE_FORMAT_2 = "2020-01-01"; + private static final String DATE_RANGE = "01/01/2020 20/02/2020"; + private static final String DAY_FORMAT_1 = "day"; + private static final String DAY_FORMAT_2 = "daily"; + private static final String WEEK_FORMAT_1 = "week"; + private static final String WEEK_FORMAT_2 = "weekly"; + + private static final LocalDateTime START_TIME_1 = LocalDateTime.parse("2020-01-01T08:00:00"); + private static final LocalDateTime END_TIME_1 = LocalDateTime.parse("2020-01-01T10:00:00"); + private static final LocalDateTime START_TIME_2 = LocalDateTime.parse("2020-01-15T08:00:00"); + private static final LocalDateTime END_TIME_2 = LocalDateTime.parse("2020-01-15T10:00:00"); + private static final LocalDateTime START_TIME_3 = LocalDateTime.parse("2020-03-01T08:00:00"); + private static final LocalDateTime END_TIME_3 = LocalDateTime.parse("2020-03-01T10:00:00"); + + ActivityList activities = new ActivityList(); ArrayList expected = new ArrayList<>(); LocalDateTime currentTime = LocalDateTime.now(); @@ -47,20 +64,15 @@ void populateActivityList() throws InvalidTimeFrameException, NameTooLongExcepti tags.add("tagA"); tags.add("tagB"); - LocalDateTime startTime1 = LocalDateTime.parse("2020-01-01T08:00:00"); - LocalDateTime endTime1 = LocalDateTime.parse("2020-01-01T10:00:00"); - LocalDateTime startTime2 = LocalDateTime.parse("2020-01-15T08:00:00"); - LocalDateTime endTime2 = LocalDateTime.parse("2020-01-15T10:00:00"); - LocalDateTime startTime3 = LocalDateTime.parse("2020-03-01T08:00:00"); - LocalDateTime endTime3 = LocalDateTime.parse("2020-03-01T10:00:00"); - Duration duration = Duration.between(startTime1, endTime1); + Duration duration = Duration.between(START_TIME_1, END_TIME_1); Duration allocatedTime = Duration.parse("PT0S"); - activity1 = new Activity("subject1 quiz", startTime1, endTime1, duration, tags, allocatedTime); - activity2 = new Activity("subject2 quiz", startTime1, endTime1, duration, tags, allocatedTime); - activity3 = new Activity("subject3 final", startTime2, endTime2, duration, tags, allocatedTime); - activity4 = new Activity("subject4 final", startTime3, endTime3, duration, tags, allocatedTime); + activity1 = new Activity("subject1 quiz", START_TIME_1, END_TIME_1, duration, tags, allocatedTime); + activity2 = new Activity("subject2 quiz", START_TIME_1, END_TIME_1, duration, tags, allocatedTime); + activity3 = new Activity("subject3 final", START_TIME_2, END_TIME_2, duration, tags, allocatedTime); + activity4 = new Activity("subject4 final", START_TIME_3, END_TIME_3, duration, tags, allocatedTime); activity5 = new Activity("subject5 quiz", currentTime, currentTime, duration, tags, allocatedTime); - activity6 = new Activity("subject6 final", currentTime.plusDays(1), currentTime.plusDays(1), duration, tags, allocatedTime); + activity6 = new Activity("subject6 final", currentTime.plusDays(1), + currentTime.plusDays(1), duration, tags, allocatedTime); activities.add(activity1); activities.add(activity2); activities.add(activity3); @@ -70,7 +82,7 @@ void populateActivityList() throws InvalidTimeFrameException, NameTooLongExcepti } - void populateExpected1() { + void populateExpectedBasic() { expected.clear(); expected.add(activity1); expected.add(activity2); @@ -80,25 +92,25 @@ void populateExpected1() { expected.add(activity6); } - void populateExpected2() { + void populateExpectedSingleDate() { expected.clear(); expected.add(activity1); expected.add(activity2); } - void populateExpected3() { + void populateExpectedDateRange() { expected.clear(); expected.add(activity1); expected.add(activity2); expected.add(activity3); } - void populateExpected4() { + void populateExpectedDay() { expected.clear(); expected.add(activity5); } - void populateExpected5() { + void populateExpectedWeek() { expected.clear(); expected.add(activity5); if (activity6.getDate().getDayOfWeek() != DayOfWeek.MONDAY) { @@ -110,52 +122,45 @@ void populateExpected5() { void executeCommand() { try { populateActivityList(); - String parameters2a = "01/01/2020"; - String parameters2b = "2020-01-01"; - String parameters3 = "01/01/2020 20/02/2020"; - String parameters4a = "day"; - String parameters4b = "daily"; - String parameters5a = "week"; - String parameters5b = "weekly"; - - Command command1 = new ListCommand(null); - command1.executeCommand(activities); - populateExpected1(); + + Command basicTest = new ListCommand(null); + basicTest.executeCommand(activities); + populateExpectedBasic(); assertEquals(Jikan.lastShownList.activities, expected); - Command command2a = new ListCommand(parameters2a); - command2a.executeCommand(activities); - populateExpected2(); + Command dateFormat1Test = new ListCommand(DATE_FORMAT_1); + dateFormat1Test.executeCommand(activities); + populateExpectedSingleDate(); assertEquals(Jikan.lastShownList.activities, expected); - Command command2b = new ListCommand(parameters2b); - command2b.executeCommand(activities); - populateExpected2(); + Command dateFormat2Test = new ListCommand(DATE_FORMAT_2); + dateFormat2Test.executeCommand(activities); + populateExpectedSingleDate(); assertEquals(Jikan.lastShownList.activities, expected); - Command command3 = new ListCommand(parameters3); - command3.executeCommand(activities); - populateExpected3(); + Command dateRangeTest = new ListCommand(DATE_RANGE); + dateRangeTest.executeCommand(activities); + populateExpectedDateRange(); assertEquals(Jikan.lastShownList.activities, expected); - Command command4a = new ListCommand(parameters4a); - command4a.executeCommand(activities); - populateExpected4(); + Command dayFormat1Test = new ListCommand(DAY_FORMAT_1); + dayFormat1Test.executeCommand(activities); + populateExpectedDay(); assertEquals(Jikan.lastShownList.activities, expected); - Command command4b = new ListCommand(parameters4b); - command4b.executeCommand(activities); - populateExpected4(); + Command dayFormat2Test = new ListCommand(DAY_FORMAT_2); + dayFormat2Test.executeCommand(activities); + populateExpectedDay(); assertEquals(Jikan.lastShownList.activities, expected); - Command command5a = new ListCommand(parameters5a); - command5a.executeCommand(activities); - populateExpected5(); + Command weekFormat1Test = new ListCommand(WEEK_FORMAT_1); + weekFormat1Test.executeCommand(activities); + populateExpectedWeek(); assertEquals(Jikan.lastShownList.activities, expected); - Command command5b = new ListCommand(parameters5b); - command5b.executeCommand(activities); - populateExpected5(); + Command weekFormat2Test = new ListCommand(WEEK_FORMAT_2); + weekFormat2Test.executeCommand(activities); + populateExpectedWeek(); assertEquals(Jikan.lastShownList.activities, expected); } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { From 1b2673527e00fd5695b0acc47fbd3377ffc50279 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Fri, 10 Apr 2020 16:57:43 +0800 Subject: [PATCH 321/415] Updated the Design Section --- docs/DeveloperGuide.md | 20 ++++++++++++++++++-- docs/pictures/Architecture_Diagram.png | Bin 0 -> 74181 bytes 2 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 docs/pictures/Architecture_Diagram.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index f6435ce09..ec16149a1 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -59,8 +59,24 @@ * Run the tests and ensure they all pass. ## 2. Design -![image_info](./pictures/ClassDiagram.png) -_Fig 2.1. Class diagram of the Jikan program_ +The section provides a high-level explanation of how the Jikan software is designed. + +### 2.1 High-Level Architecture +The users interact with the Jikan software which modifies the local storage data file. + +Within the Jikan software, there are 5 main components: +* **Parser Component** - Parses the user inputs and calls the relevant `Command` object to execute the desired +command. +* **Ui Component** - Prints to the user the output of the desired commands. +* **Commands Component** - Contains all the `Commands` to be called by the `Parser` based on user inputs. +* **Activities Component** - Maintains the non-permanent state of all `Activities` in the `Activity List` to be accessed +by the executing `Commands`. +* **Storage Component** - Interacts with the local storage file, which contains the state of all activities, lasting +even when the program terminates. It retrieves this state of activities and populates the `Activity List` at the start +of each session. + +![image_info](./pictures/Architecture_Diagram.png) +_Fig 2.1. Architecture diagram of the Jikan program_ ## 3. Implementation diff --git a/docs/pictures/Architecture_Diagram.png b/docs/pictures/Architecture_Diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..25aa43105bbfd3efa68f623fad68ad22ff637f85 GIT binary patch literal 74181 zcmdqJ2~?9=*CrbE6RS#vQdDGi0#p=4=2=S-Ed)dbM208`C{siTGYM5rAOe;s$QVjc zlqt-C0Eq)b$&5n6JcLmKgee3FNqWEd{kOZ<>ecJs)!pmf|E3leHPAXUr#O@}OE%e}mkfVw5S(E_zFRdyw z7T)>!?s*#@6l!l0^0VOr_WlcabBpfcZL6R|C4I`ht_K zEUOG>m1jp(gkt{Q=9I9l|MIQh6fIiSEG|cDR-SleGZuxee?Rpg{;ZBmLgMe(`qs;5 z^#jFTT%F%|J2C8ro6ZS`*^{q++4iUW{kNOe__K}GC%6fLE}g2ud;3}RNP1*f@H9Jw zj$2Cq9O9DO;XK`4;=Tzc1+Vi)^qj3fehq6ri`w$z*CRVWY*_#8)RTW90)p4G0~@4% z{FZV4KmToqalV?wp1&;WxJQrq}Lb)cBuJs8eKQ*-2sD>aw+2G5uf2 z+a{iscIIf2eZN1)ih~$@58ygPQ8z>{Rg4jA;!)CZEr{gqh=SNWHqvtJW3fLY!b;lq zpH^u1Y{XyzoK_@9cIz+M?$*XwcHuRv zs$+YU9VB`@zUc<-<~(6A9NLc4a|dz#HgjHUJT|qCQDc%mwNRlR%wv$^)RxJ4JYB{9 zC=r9@eFqMduC>R_eKGe+4Vccd%x1idM`sf?(Y7#j8XMWv){QVs-Dg$VsBD~%XU;Xs z>$a6tTlP~-2(xUjU*|_tAzS~xmAd67WuloL>2q}G@M{A4*Pak^Mq4>CMyvcIo!-CP zbIr2oD8;|Fi(OaiaMy2}e!zJieRoT94BCFKCt!4xz7x&LxI*1AS|@uj94syD#kD_o zqEOcddsPgdL@HP6sf0v^Un>YPS{sYEuG2i1Dgl$y)DiHxveh=O(M^&RqqCLs^X_x( z9SU`eTV%aTQ{hvUrv9vN9p{Dn5wm?%a!Upw=Wof^cLsBZlg zo^V?n(b-)SBAUIlL8i3dl;o9}DmfPegX3NlpUYGEP6I;YgrNBZp`v<+z?F_y+Ps#i zRsFjY){aw~T{X!D2N>PiL=3j-o9wHuK_(*FBv$e+RawFwFTrvWdL!Zv@f`DXUTP zJ-yg*S*MXUg<3^rYWF#R1R*qzyTFw5zmy3mkLQ~Y1q*m064G2oYOtEl5?Hg$u#%o8 zWr6o?ct{){T_>CL?e-&^>bfFEZA$P>L2(jsQNGO#qfi}JdR;FqCR%GFGPuB<}39L#2N&F%-Ovs zH3mW!&V?@aQPdC}t>}$G-V~ZvJpn)Yl>UqpdG|gpSZJi-E871BW2d~7JG=okQT*H` z-%=^SpkNxN*D=xQYQX)zN*xI3Yw{kXJf;b>r>oo8;|42Vnw(kJa!2z{S?|Xw` z*v=R0ODHz-I7X&K;+^?Dr{yxWW?iWCK(vbt#cOr_QvNW}o5$u}W zH~Fg&MjR-o&Z@O6-xQ8g+w!+UdeMjs~QQBTgXukiDv837oST7@opwdbw4(wuKG za#ZW&AGtS`FVAm9)-5TeyA&=eaZE*gZqC4~0)O*VCAYak#b=cunUdYJDX$sk9Bu7@ z%QY&wSk8%C75CjT6MXx=kCU>NE{o!K!HEUNpf&h`x04waZhB9o%zTWmZ_wtsu$=`? zAH|Om2ki898^(orE%s))M&@b5jz@h0pxuhsD78QnE7z_gx-0rQ=bM>fd0T-ZfBgBL zj)gvfj=uLwJuN!4W`1`dlLvrA`SK70k8It8z_G6zVY1x07e|kpgIlY*N&#auaiJZf zfjx2CCuBu2$-g3~(}hDo%Q4*Ax~1)4v`1+w8jTG+J)I~S{M8|VISF$wTdE!KYIR4r znZWVq-%(+vAKq5}Yn0rN7u;X&`PNcX|5DMZdD!RR0mlY&PjTKVYbP?)?$~RkR3myh=Qv8|RE|;W!L={hmRu(b(0x0t}0n8?nBj4vGJM={;j?@WI5JA6) zpB)lHYj*hYg3!TOi^gCEF=}#})RULA*r>Vg*Pm&C%lIIF3bkbgQ7hDWTO}sA`+cT} z_-S&!5`g}3>x?Mh;^Zb_;7vD#q()qY5JGu}nTSv^7y^b!-&L_rtLCjNB2!HykC<3ZIdc?a=2ywfe(DBO0cVvbpZLf!JBIr$VR{h?88 z`o)z|dqLCL9*HT6B@zFbU|UqX^I=LC)w9$l$DvAxc@i$A_5Gh(;QwB6{U3Uo#ky9c z9ki_q!d7x;Dl9B5cQ?cxkDQ#GyjFhC`NfMDX9)(OuZxS-f)*!sB!T3TI`Z$0)(5bv zIF56Snu6PHuLD*_uju2I-{q%6FEtaR+q9@v-w{Y>PjK0q5(sYjlX*)dRn(=zb78d=w zu&}UWsD~_rUz-b9{hn!yo%SU4(I#g-?M3A;hL1MHXX0Yu17Tyx8usx^9yne1Dj$v8 zv*pIimoFo@RV6ew9gU1>mP>7RY)VvzPzKanK>;l7Ml30aJz2IgmUM+hlG|{td&7;h z)r^|R;r?KjX{eoKwz@m*Y|Wq6!!aC#RO}J>obNqEZ!`jxDa(#W8w~O=AW>u&{_Jjk zrIK!1yR|s)Oq8qIT|)hR)w2!4D+J5e)>x(@XHA>7*u(=Me31VQ!qE@%tkHP1R}p1v*SFkU z*LTOS7r!&*vchROHli{5e2=vj%uM*^mqcfKVVG&sD?1ttc`D9|=pY>_rtI~Njwm3q zPplQ^hPaaNOp^15&K<`?R-(#S=0%MGFwj2L_2u1RQMg`7)Y?MlhQw`yRyo(&-V&(+ zbBt@C)Sy?nO?8QH{QK?2zwy;{9kSheP9b`kcn~BSrm=((EMaWoTi<^si5RXOPJLx9 z9>W`jcaYd<$9_cWqNENh+maP`k196JGgb+I2~`(^JLMPP zew|$i&LmZ)_;nxIqh!}9ABrfiMvq64e2X>$AqRYecejG+|43dyqNh;l;DG}(mAt&_Vd=S^ucZDUMFa#~&g9GJ2b~QJ3|wT= zl{@HY(BH-cRRx#ES33Z}JPM}~`1<^4dt`2D_fcjK?H`^MgW)NeW#adRzcL;ayhN6QjsIMu@|3ZAond5Zmr>vM6_S>);;B+PPj%rj5mwh0{lg z-_qX&=j7OQcvN^AepBoZ@UfwhHtQ67263K9uX>3QdI~U8T?DI;E5)iq;*=pMV>gg(%dGbg=f@2TMvyR6yX% zY$84d^rdxw$nuc!TyXfS-JZzIo)rM1NSOQf>*1$kY_r2H(&VYKfKH~=W>Sa z&kz@GK#cg5tItA{W?k5ZO%E{OH~Sq5PWIb$$#u+5FFT2dQcer)p^y*buCtj2l8{*K2d2}0H;CnX(MbXhL?YMqC2 zb8L2#%*vImh&Hi^EwtVQYr4D$OVwxYM5Udn$3`x%(kT)LjivS)86{!v;t^pr;6gon zPp(jwXFtaj%E)-!L#B}$aI%UgwE>k@wBy5ujFGV<;YL{&K|C`4D)Ir8?|FM#o;?870hEScM@L6n zg+D8&0oC~qn}IR027iFy``WOqAbhu?)!DOWot>Q>dw^_A^j8HhPIamBc>@Cd|KKN+ z?8anm)vRnuL0ZMTcZXLOzl-kJ0SIim))K+&rf7OrxBo!nZE8_IthDG-GBKvLKu0)|a7kwS&qM*r7rCC{7?{adUBIE~r?p6vP zSk47KN}WvbSt^d_h)^h4kuk}u@4CGc{Obsa9^F;ssz5{hw5AR%-8iNbASvCPU|@0m zdiT(8<>BGxo?Qni{1RgAr}%+zE?-U2&8^#2s7Ij!BV#NxH@ZsHWUhYs2g^H4BW*fa zG|3ZrJ;~M_#w-vpb0v!IRyCm_20M*~bx$yFg7xzQg2{CMbiXFUBBg^wo0#Uvn`r%}!%puy=_`ac^cNwjgR~Ntro@2B?_$FrzkABo z&d`V$DeMT2jmDqku;wDXBq_?$zCxfZbtU*RRV!MKTN^f>&v}(&vIP|;T(eCpZ2KZ3 zQn~aU4`d_uSSIK;&3Ti@J%mfX(!@CE%~gx$3g>GeOv!1o{k;lyvb_^=5eo!CNXT~+ zv|C$aG2m`B?1s3gf|-Zq-Q`BrmiCs;o;#T-j#S=KWJ~CbkEEKe@^J`>qx7l8?tssl zGKmJtd#+OAuov<#bid8eYUUC#b%->J#tiIdu^?NcnAbBl@gm@DAEAVAY|`iX4jH~$ zZo=RWhHSd+il8Z#&nC{bo)K}j|GlavQVfI?IsErynJ4;7od+Ln6W>Vy*R+*fYD@B( zLyQzR7l|&u{l1ZX+^*~d5RAPb;P8+4x71lv=3n}y?2b3L;4}@tJIIMt4)ulmyAYamt?4NJYXa$n+i<{<+4`Euo#cxGQ zVmD$7LRRJxx;gySM0xtsP|s>=;8?=)s4`xhx?H2o$R+h3ok&DP_s$~yav%@#VYO#O z^mh%{Mn%Fl97c8^2Xo=P7BnG`BPQX3&o zAB4!@bbfL3pD7AqlLVL_8a`CbQ)8;wLnz!?*;N8Xd?>lKswVy6|+ zE59dI@gab58f#3j8F(Z__M4V)uJDv~<B(sa5_xezfR1US6dj*h-IeS3s_X*U;V+-Hm&pW zAQAn=OEkIS1VB6u-6EoKjEv{?&y|4-g_P}qY^53T%w*qJ&PRa6PFzBQM346VAZBik z$!#Cys>RE(<6JhA4ov>;&?n&%vEEgfC_t1k!rO18mx4ARcfx)HCl6U@>ZyDLEKQ%; z(|WAoGLZLH3na3;anSnm<*#GJ0>_#sIgf2ltY3OovL0)oGIG6a>RYB4y8=eqToJBG zz#=T(Ic^X&-)82?wM6wT>NDLi3E}c?!)^o zp$K;kt_UB3S-gWd!#NUI*Vi1A{m#nN)q9Zs)cBDh zvPVLWf9&Xa_QUt_xL*;zO?%TS1P6~h?a97y5D8DZtr?g0FVsFCh18Hg!`_NAzrHaE zVZOlJ`gi(C6`nBh>%Y|C&Qq>8*OP4U>;E54ZU3wOA~N>asKH$Nl4BAktVm}M6e@u^ zgqg|zIM}VSgTvejQQI10_x>1lcls@RVc(zn$RiBVK8+Y9d-5%Nq#z&#Ik&ta+Lr6C zM8@_VSlT@l-1y9vW+>2x+PbFpB%;P?K zT2so8GVcKoZpyhnkMk&<6t#)p@GLQ}TxkxYFE~yP{UjxXx~{|)1c%HnZTW=6zzBN1 z_48cwsR1^%DJ<&hUEs z89B_DGt3sOhVdR%=hFLJ{H{p8v#}HJe#);{ zisAF>3zdrgU=x6(!7D6oLT!UxS6biB7^0zVE=>R2Q2oIeeJPIqUCdLx)v}z&ZFd@p zIpK;pAERDvc69XuQ-)=4w{tu>&@6ei>Dz($hNZuDQ9$kCC7I<;+gwcIW(tnXEi2== zkvS&JU2g8~!{J0}nfs4sQZz$s2fj|qdDF^N=0J29Fdx?$Hl3x%UBg=JmT^3!3x#BT$lm<=KdRsB^RGINQOr zR0-~%3b;|rvtS2VUZvWnOuDzzXy@R9H`ktI1pl|NwN1J{u;M~xv#jGZ&o_+To4YSq zJIyEuEi5%6qWxJeElDYpq0ACXV*Bc3_+)AXte4$_eD*!n%%1vC&&P8m8F4JAQ^B1h zE*~tb9Ckb3_jC6RVZ5Z*{F5Hzj-?ijH$~r%kw^@fK{VAKUslm}GG0B~jX~Km6SbhE zrwsajp|aH9`-0uQk8<9PJL<;l9UVIs{&o8I;iU?%Nc7s0ScGcRDn~Ig*sDSl z45&YiyUO?^CK^Ks`Siuq!5=Eo~U(@1;@kc zSw%3j%C$zt2##0(w*>~ZnTunnTDVTVS{M$_By^2z`*6I}Gvq()wYueOpK3V;lz6xh z&C`3^t135F)LKz?C|aBGYI!bDEb%Yom=7XPS0TG!vIg>^F;8{&&)KmU&&$~49*Kvp zh`c=gW~4K5<1Z?QY^&=|x5L8Z{JIu=kR9FA!5(914o}IZ>|Vd)bOTsX=gm_CdpK1T zqBOUpdN`if;%rfrCC|c^+bKB&E|t7{Rg~67m?2E1a&Y*-P6}dxrZc+! zgBq8bvJ&_Dw)O|QPB$jZolO_lJ^r)8%kb_Y^?R}_9e-5v(B_P ze2QKGwGxXT&k=YOvKYCM>An?T&*7iD=rpBj>iX?%B^m8+L~v`<(n?6uvE0s`uyWx} z%=z?Tj=^162k6_*&o$p;E@FI-4XCOthW#DYJsND4bPptP{FmFZDeT)HTR2^YI*R9# z13W&4D#K&|vHG$u{fbN*)g6iQ+63lPOE=S2!lcdB+44JY|6BvxY%4|Su(@7!$ZVx0 z))wozKh(V3^;LxV{$btO@cjua z1;6F}k2Q7Tb`|UE3c9M9u^T%c5|3T<;MV9<+6S4m2N*0xW%9wFt~>UuN`Pu8Y3*|u zuolS9U?@};Z+;xU=Z;Gko;J9qls4;l!& zU)PCcA||+7EGkA(NrFHc2p^FXv1P=^uN`HTgV`{0yqz2$ZwOt-Ymvq>YR%0~B9Tw1 z9BK|98daIAXF7se%Qc_O&c50A%)7@N({tlXLkP!<_eOUzE}pucE=8P%=QI|Picm=icjVjfAL1MZB`&=k=k{=~-rc)T z0om>J_^zg<2%<94?ubz{M-|j`Q?uyV^Gg-{y~Z-3cKyx?d&ODBHR1*s~5l__xBgUZ%3xN%0B$B`(7ogV$9Mtm@I*xV9`)+35)om{adzk zmm_lz%A1xM2yK_z0M7G{7Ti1>S%FtM7b9-pdieoj z)rd$`U}Nk8YcQgm(8%xr#ux2~x`l@+E1y1)6YStPCa-Dc^p(k_KWq)B>^S;Onzp&k z8AG8 z8NByU?E_ z;9Rzn(jB#fGs;D>k!OS@_Owv1b-g39Ie3%HwziTBsi|T_K`0bWxH%jP*6nl6eLtHE z9#62gVD1=S^*4z{g3|MtB3{p$!l z1#RvrM-6u1Cco5no6lVkz|0X`L(-VkEZgJ^_ ztWnp3%Xr_Jyygwu?GZaZH*8HDDp9E)y{9riG0b?VfPM<_wzCJJ(yLU>lH{8{M@8dq zPyMv6fpw{?Jy%plW46cNm;&@h!UVh0d%$oVQ6+pnW{2!!3~&MoE`-of>0@P(h8`q@2g?Ij{yZBF1nPjUiC4J0DGu)zfPQuA33u7b?h z$4p;-eu3LOx|P>`<#L*a`%KQY*|k4~>Ly(%KqP6mmCI!18_OC=f}RphyV$+Rn|r90 zBi1Tuf-s?$De{Kf-F{7~igSoB(v0D{BvnD;5MIUc!eSq)VBUdeGIv|DXpgTjgC-NG z@}-yt@mq)iv{CGK2(BBb9NC+dn`^r5!GQyLl?;-k+BZe_3xAjrbA#2zKNy|eCZknm zk$=^7NO3Fka|VvUj1OP|BOa;3tiZu;ynu`9lPRiSZ;ffRr!FjH{wAat|A%@8@;mC1{XpBM= z1Y?qjn1`RR*EyUP->ej1}F?{=dq0Ia5~aqP6kq!UNCa^qz*ly4UjJU2d-D zJXn7Ayi(+Hf~Ub10SA(D<<%NU)YVT}Na4m1`NnTKij3hdeA97uXGK}YM~^C}XuZ-d zTu)g!KlO2zeEeAC6RLC8qxT&j7fEH6V{iB9Uy;1}=4*h^JK znn*~af!-htL;g&eEc)K*exElzFKGfEILbq%+N@6tJLC7|;wp5S!ADlRFZKIeN*ahY zcGd6pNE-X|gHyED+mCc$mib))*$AMl;(8qS6Zp5LFn*aHD8uI=REgb zD(u#l8Uw1qpJ{;xC$n6$^zC}x-0p`$v$J+fpw+-rer!} z)>iAm61DIEPV@Vu7Q_AV_;zzTLD~w)1LJ7{@FK_7)4_F{RA*vf%iu663kj-JCeo@z zU1?E!9s2im_FP(V@leWj_iBv47gh@ zLAT=hVWAAqGmtZ4@{MC=sLC350n+8v+FFIgI@x#!#QiVN=Z7-m2Pa~MUky{=l37zq@CJ`n(>9PzjPW$y7(Q-?kCRhqP+D=tyaN8%f5 zAfVLswz^_sS~*XyzVs%5$tZ)vX~}ks?NmuTM*QnmWnt`CYD{2aoQi z9>0C09z-3l>1%@q=TiBH)z{~bYycuvTx&%)$0&d4R2kP4PsJf@^J7IO>F@*-(j`7` z4clD)o{DLy$nT(!^=z5ZO{c^LRKjE{RVmMx@Yz>D*&;s;gb)j6Up|x!q0+D|xt!9Y zFDS4U?-g_6`EAIl0SdLxU0Ne7a#_pcJ%n^=r!pZn)dPBqWQq>=lgs+tk3-xcT5En@ z&ze+cn{q)kFGd%W+_{Y%7LiL8G)&cXhdzA>pV312C=zQII5jITli}YO z>(tQWtesDo5^sFOp)-0hbFxxYS(t zk+wQ@+i}G2ArHU>ej)B`F<)_Fy1v!0q${>itXjEUklR4!yS(%zGt=P*v(I>QW@bZt z1`v{KWZw&ocpR>BZL(nwg8N}Z%BpNZpDVZ8wRGj;M{XPv(Mw{g+9m=Ju>a*mmILwk zsr2{sdVf>SOrPZD`;cXu`()Bmw>CarSD86hW2H}eqCCT|>16xxCei7@>W&2m+r+X< zZ(U^ew^(LNP^}S|zv{ZXqhkpPtD$)2NuYUCq%%f2o3PS>r}NuLzFaHi?KX6QsCjcl zJUUeSzyZHrTwP~y%jx4XCSQZ&7b)tN4V9VW9Wkm090$d=)cO&oMK`UA{G(f&LHC># zHwluze%ZCpoz_=0su%}pB4LlaE%W+Um{c=&gM&?dpRofiqMs1w*#P z^HT1aCBqY7vR-uVI#8Wz_<1nQ^g63wPUZIPn;W_xC35Ks*U_$!Mgaw!#@epWqZ0)O z2pV^4Y{lvz8fhUvb>R&qCLM@h&=p<3F1ZO7`bC$Wl!=hIoQ8kgfwdq(+rN`tm-Zpo z5pMF>-K(Dbv{H%teRREc5Rxlf;VA5YBd`~5$dDB(rT>MfHIQsbKO+wh+w<#(4QuN_ zK$BBLvNO&6er?EOBNtC?h2sytIXFlaa7{Mx78nQ}{%Qaz{QI+z_sX8#qs&OJsCX+#f6%)0V=*14*#N}>0k?f zJ)YKg4PhD#$V4TuXV>SyF4*&z08o-~_2QdJR5)a2l#i#n`>rkZU}E6ZU97i7PRwqn zQD0=CjKTV(C82EkSslRB2?%L+_3|YLmd`=9gNC=iaz#`j`R;EY=^S8j5cnxEZ>~=) z{|{JZAjC*dOq9wp2A5h4xE{SY?lc=6BcTrGP5v-t+jbe`>0!|qpxEjG62n49WOpwg zs&~Q@6Coj3KF)}<^*XXl2BN&a=*R0B)>FU0vzuNmCq*20GjwZzw_K}9X?yLCkUblb zb?pdy0UMl%WJ&>@9qw|W=2b2=bgApl9&>O5Nb;S1VqF;LBT&L=C{Oh>2xZn93wJ7# zS)UUM=`P%r20_h5_&_^11qMU*_`kh60rW5m==x50Ssyt` zgXB^;ashFA@QHy*rr>Uq>H1{W10IwoluEY#l8IX=p0Kz3%3uQPkNLQ1i>v*Qz4L@) zp4ML=-^GWI9jDCHjoZJ%euwj5d4s>8+6~SFPd!Eoz23lQ>HwXOl<~kv8H0Y?#6u~s z=j(}BLL(VY875AE*d+(+8}PQ5Dv%8N5~ukK+3v>_|3C^lUO*Ze5-$TD6+aIvoK=c% z`0uW!K#2Yt98&)Rgo1~JwQpaeIj^gJtJ%dmROcy}qCCWZ2hH>}=0g5%xVrJw-!wlP z$+-w)fw7ufe79$o8^W2Aev$-ybv&nVwte$-1f39p|%scg9A2yDp- zBBT3GnS^`i?D*dl3zfEqncecti7K&$lQtn#t9XZBR36K(h5SS~Gnmzs?%w>HBdQoq z+xE#pD#Zv6JtnC$;G4m%DLo;JIonI1QvT^SZ?Emf3--Y=T$ou_!~E-sLfWx1EFi+| z?SgUC`3wK%&F%P5Ae%o8pw6S?uj28-sI>h9?x<5o;kf*~1(M#(Zy8T7v-WOG;3EZx ztv~1XO{HI}SU&(mO=OUBCS>es%PBl;!iFuU+(!zP((G3Rhgxf&1nsJkGo&0^lF|AH z?{niyzC6;z0DBXzksyB8p7eC$YsYE_^oCjqoII;1bFyz-feI#6Yg}WPd*e1O)ODxW zWkcimCTRRP)ibgBB}WnYbXt1Xp^aq|anR&&%C%!u6!!&jy8oD&fec!^1@S0 z8XTE2J+)!>TWErnMw)JQTvB}X?3sohITTpLJEZgiwa*ecyqn|DHFfy^G#aPF1m0IQ zPm|1|rAbWL__f7(cJj|EsbvL@HiBv2f)`fXY#Ik}k7?7`BCsX~*fvf=19Dqhg(7w!~ z{N8wnpgU6jz1}wQpM@Zjk7`h=IHp9Nc)iEonzOCfr$yhw$|{b1BCW%#V!E_?nBODx zp?1PwRKB)XdqF~)5HQ@4J4u8<3#U2MUF{==_PZHNefqLtlp#jt2TI)=+!58Re`5M? zmrZ5P9Sx3SPYvs0eF#s)Qt>J>2`jgeed1B)N3}*;iRTCgJvFJpp#@#&pG?RK!P_OS z8Jf&~ioK0{hiw_D+m2`h{n?8XO=mA~?1@wU5lySIMO zDh&zfPY7+uimxems#VwFFU*M<5g86DRL9f3s@UtH(!2)0Nbvs0D9dm3B|0p^S9Wi8 z#2Gp3!9?HL&HmO%y!I<{i!zI9K2=T^OUK(#g;d3CulRrsTrBr-)6?d>Uv5Y*0unyp zRZ;DYmff*MSU=5(ns06Ga~c0wYPG|~z1f;2(!An;?71a7kGpnNDPaE`mZ}+aadEN) z%cJM=Dxp+s=trYoqI6z}k0s5?P4A!A;dx0|C`*|~>SNtPqht*Ynze?X<~%;Dh#c8K zi9Itu(Ie{l^XIR0{k?XH^uS-AWR%aWD^bxoC1Oi)*4OG~xj zP*|@=pHok@&x#u)siF$T?Vf2a+gb|>`xtS$nDDQZ(D~8}WQBw0WTdGTGxb_a{|t-9 zf3fpVZaEfk;K`FGuS-iy)0PCm4Oo@iger-Y29A{8iG|dFks;#+r3D*0Yt zlUH+96LWm}xU0*M$fs!IebrM zNM={4(7^*>Z^e~E7~A$FmTJcf8m_;y7;Dp}PtN(Ch!vOqoztIWOivEpc&cI9a7#)( zm=J)|3O?jpLBQAnlU=mmw8U4T1C4M*4u-gLtF&KSa~!0hP6s-052rdn2zrv;;c zw*aet=+cZ{_%g%@5(^5dpfXf}Z~4S(*nJZzVBNfWrf~UhUp7 zhoICyg2R|X(+>B@*8|bPyQJ>%ygro_2-1kPFpTGA)}X$~EJhLt z%3HOH>cJhxQab>(Y~szgUQE@~#w=^x`sdlJlg__iwX&*(KK|EPSx3j3QzXwk+IGQ1 z09B23>U6tU_A@9Gv-x@tdc}>m85R#3xahCkt>k`uehyC~lvn|OK102CJMwc{csPKT zm&H$-U{pmnFQy>wLf4B<9lWG?fFTyoBiA?`uHL^z<}b|vM0_t~vA=yB&blHtBe(gr zXjzzc&U&zzgwF7YqiE%gYFmCt#__ z>|f|+mIhVNRzDCV#iddtr1 zQK1)auU^32*wCw%mNm)RK1kgv((M%^D#;M^r>8Wz)cax@>gUCKK#HsTiPeF%} zBzPQX{a_T-$wc}OglZl*07dh$q_FtSLzh3iAs9+^eH?XZAvr7Gv+< zS7Idjh=?9WhU%}3!8-*Ee)vP>c5B)Ml;;*DWsXZa+3&Tox0hCRZO$s6dfn<|>U}b|7|KHf#u8i|o0GM@C;on13r#>0#Wn(pA$O{XJ-r2b zb%Lh~jEmGQt*te?6?1|)Gi*8tNL|9+y}t;{yck4T<*;OXFx1eZ7Hdl4!Plovv4jpb zI$fO*N#Xfx$J&C+abS0q(44WD0II0#>&pq77rcVOnKFziD8oHU*MidOcNSgHq zv#Px3zbI(xIM~>T_f`1ER4sL9pU%JP;Lv|KEIWJrvEkZH$Db@Sp?_4VYVoTUl#g#+ z{TOU&YWh@4yRb{Y1KL2H7}XJhg1=s2o@QI+K7rv+Xt63F2r7!8oQX9T&dRr z)#!;;8o&*|C=imhhCM+u0^Q#yVdHlV=5e<{PiwV4r}x`PVJ4<>?i`fz6Wiv%#1W-s zaPw!}8=*ClU;YnCte-rsV4C=1*~9p3GL~i&WgsFaCpQPR+BMGc_It$aeJ!$A?a^2) z7HNQMGC%_oMnL&BhNX%LP^@=A)Uv__q3u=o3-3}rl=^dia4ZU~9!GB?S3 zSu4CMI0|w8lsPinP6H9p9PkdkPgkDq$uwebMCE$}-Igr*W^SlIx11iM;b2Ww>eX5qi52}!V)uax zwGq+OSNg$zk#1QzIUc(xa!4axihsX0!Z=-elxzwQA-^3~RD>qwxA+Cp>(>Wh_Y$`o zPu3!>!(wWiT-#o7C?n}FB(Ysww|_trT~GS8l689YaU(Hd~{9oeLS?kA??60A9gT&K(l9n z#~F|fo-VOI-9m?sNvSt)-gpC*Cr$KsRGC3LPvV-#F_`Nrn@OJX_ywkE2IJ5$_TX?{cLozJOUd3i^TUW$*Dz|6tPY2aIZ>=G> zQ1M`psPGgD{}u;FLZ8F;lXUz!IYH`Cil8Rbv&*d4mR~Q35(6iRE$xCT&@%70j;!a9 zPM-xZQS;WW0dleRdaWwD$;b!-iaU02>~f#TN=&W{8My-yRP`{rpZdMSDzQ*tO-bJS zcK7bxHNck8m#QG3l=|0QkM_wpf4hNIRj>J`V@Ip$(757qhKQB+X;f(vas%qK`Jpc} zd+URF-kC*kDem4>?BAzMek&{fM0(3V-PfK|gxxNsbpilglDG239QXB|Crl)J_!`hxqvwp2R=Pj|eY)z1yu5Oxc`wCUlPF_z1GUP^j2? z&7Cor+q3N$l6|6Qtg@OOSXw#+q1Ep5n}bCz!Z%q=>MzdTl=KC%AsvZ|j)H6n2d^MA zfEPTXYHJ0~kI0`1pP!$v97h@`6;gaJXJOHPUCx1<{@8!!QFWR3Fw!lL(HFD3dpdm> z+iMc`?q{U7TPO(XUB*(UWqmNSVf)@mnze+#FR zaVk!=hxm^I0V)}n2@fIsioCA(t?&|TW5nNXo}SY}RpYLyfi6iMJzo<_Q2Fm0#2%at zsYGADKF{vRrqfIvtS^7nom)nD)8mS72J@SrHN^204>f28=Z{+v+zMHJoaGS4TnO*Y z5%le4;FV4dO(ygFJ2MW&=X^N8dZUoVTY;bKPq?^gi?GKm8$9@{POr7)xw#np+Ci_f zp-1n)k`WG78Vntyww3?7d1VG@RrN413vXybuIVgr8t$-0M*#snRBF<#Ii2X9_eGNN zB0j$Esko{mC`jPvTnL=Y`p*2J?K4)~6g^P)5M?mwOW_rs_g|e}=QIcY+E{)*`6Ewty^e2Qh9Y0bI-^MflZ+1Ht z+RQwpkG}9XYt<~JM3(8k6Fyv9MG z!%3t82wV0%%sc+xzwI@oX3!;WmOMfT&C^MsiMsvntxE?~xLia7yXzdmu5A27(me63 zYj2LO(}@8GA6`RZ|H9HYLYMs9ayGHJN%?NBV$(C_J4=V4uOzSck^hG2%(rjl0niFw z8H5JK1_x}HPlgSM19BVYr7+N4Z^JB5sk7kDc$bq*o6Hg+IK2O>>+Imixmdy)0Gaz* z%piRIfhw%hc6M*(#e}bE1c$1i-65XA4Vt=lVS7{pW~p)CjwmTbzrT_xuVh2M_2qfl zRAGbTRA)h3^1lPl`=gft0g(>jz=3Q~2lWZ=Q`P419S6@9Pn4USLf?3Rj$N+&N`OhTif!F-y z*z={Il0aq*m%a;z4`Ob2dE|<#x>Sq1Cb!+tt`6bR67&M^F{ZNMTQ-yn_|VNmBL%`4 zhbUJH8b}%2vLH&S9)36zWp(-TPOu{tkIsA{Cl5FD(_`?LT(j^oMMaZs_wSY4+2MKY zh|tlbsxk_E4TIX8{s4x`n|JVO)*e^Wv9hyE_CIIycd)40s}p~>6*&MY(Coc?#&H0! zV0&C7aCH|)YWlgT-=&m5ry2i~cqlSJymqY&*IiPpBT|kZug*Le_9+yl76)^l;aABcnc1qPy3T zFCoE_Vuf3}YQ6e+tp@D($3=VeR9qcmLo1>;#Aq)OG=%=W z?!jvm{ZBLzVTc2e02BEhk?mPGp)1|AdG^TBqrY#{M}QQly}2E>!*ctl2Mh+IdX>(* zDIhm=0s;b~NKQH`C<2P)tRh)JB!>n@M*$@$3J6G0B!^aVYzzbu zp@~hV5hO?hO>UrR`mNpieRa;Ock0zU@723?Z{4mMb-Mpy@3mLnYyI}Tm@wzQkWE_W zN0fGxPZ!;~@k%v}tMhhzjD^44+{zz9FP~83UY!dP!Epe4mv1l ztpRFN5Jj&UDdCS0h2Q_ZC7!zrE@zFfaBBre;6YAKj)o%sc2E9Sn|w#xiv@VUO;&BE zUXta(`DTle$j!>?9kM#2@Cc;r`<%Hs4Uv2eh~aMQn*wE&L>gN}#6fSj`?zP(<$kxuQXpJaVl4u z^MZ_D(JIzXB0?p)(qgf>VoH}m^}9jb-9a@`l|WH!c5DpH*@H3OJU#E#ud3cn&09)fBVnF-KXmQtF^D+ouG1kRA{S?dpII zq==@BO7i?}80*l-3!G-#jK1$QjeF)S{T%|Fn58Gz+9CH_GlH7d>7-}NA)@E;vn7zn zYPz54_v(g>UQzF%esUvgtOQVnj*QCzOynCst50H?w`75fJbtL1$s+15x)*Of+)Y zX{!%TPQGakYvyt9{``Xeo!{H$Ed-zJ<4L~Io3Lb)iS=e+S?j$?O4Rz#I4Scz72y5} zZfva8;5~c2gQTk^>`;7;3dKqgoik^`mS))GEo#;F2=^6uratY>2<@b33x ziizo0=2dnrY<* znnzm~)jZVC6&gSOKF4A^yW|`|&93pFP01Yttj4|}L$koB?=~vcZwKn=DRdLY*4O%d>y6ZR)p`j)vGIh} zYoPm~MgBJ3T(dn*(_twzDH_6impV?H8ZeN<;17j3r;Z5J&v4dwWf zdVGS`dh9jB<|_FT1|~R;u%G~ilMozyZja(opP2pi8y2f~71zeAzhm)hG1JkqeQ$H0 zFHf_fuy!4imtoD2`rA9IhOMN|K{8s1XvXnT55KNaA$B&=*}GlAxmpxKs~}7{%Ma^c zUTlopS=VgB+&Yg@OE&=JA@dS>HqWD?q~r&AH<>1Y0XeAPaXXYpK^lzCO>hQI+O@qA z{B%Fwsa&`&oX3RWj*m4(J1J-HZ!5}3BsTAGnC`x;uFiVD9`X+yg;OK|X<;Mb+|QNx z(Oyakk(6&jo?zM|B0qm-s)qQ`XmwfFA%ahR7uV_Ib7d0~Nq=B$B~Z3oaLbcmTWNqD zEv4c6`ml^4$i76tc0|;{=)xM5BBE@Vljs|qXtQm+YWt;cqvd&J{(p_pM4U6y?v==+ z-$Lr0%N8CUd`o^`;|jS$jynwhzL}A#mHeF}c?~-8elzjeD5U9ex?$kj7(W*O?sv=? z8nPpUAdT@}l_0+-{Ti>?+1b4WRypZ8(~n?Wm|l9tSeyfwA9mtZLt}B}`g|jToOrD= zO}~E+AhrZ}lfa!h+eHG0A*4QN7w0w5ypqJYzC$xJ6%;K+b5m39gbR2YHJ0F)wn16l zoDH-ZpO&$hHG_1I_{f)%020_C`E{GknBH?>Nqz(*Mwh;{e1&E>oM=9+O|zb;0!gjN(uG^DoH|7z$Pd;QcFNATM7w{ zQ@(lDDytW{A$ux@FAnH&I!S9#>vc~vg2dZ&`8sR|iwOm$wEIE=5mNR5)f3yX02_It zZZ z=MT2H+-yilP^RiOZQ0hrP$DVY#F%*)J;Mq$tr^R7_Ze1#Jqf9gkK-wy$-w~}l=8bK z2ze5yQeeji!EK4&qG^I}nFT$1v0u%_49t#8pJPeUho2U6;V-XQAu8@8+f!7L0XiAQSZk1OmXe%oSMMj8Z{1BbvRBqm;tdrGbh!vM3|( z=ew9WUA*f??;hDZ4A^RHkK-AKn;I2--!>;>mmk@%D{9|Kc1OE{Q$lAplGtw>@(B>+(Eea|8qOC0 znq-W*oEstqPC~dOJ5xHsRYZ{Kvmdb98?=Wf&QrMlDZg4B#KNpGu9cHn**77U+P4ov z+R%H^ei|mQk>!xqv3t&g5RyELj zW^^SbHciNagN_yhnVDg{?+lXX1I`k@6(6qoBHN0#?zrzx7+6xyZrPbQTF{mJ_tv7m zz3xYb(YB_rre5fzlVRclf_ zF;t9H=10XfuO)@RM(n!}k>UT^5Dh=*Z##&|kyLrm)+(aZB0nz+0Ns3b+`-^QteYU zUe0~{B9xX5O(BC4azwwT-d8R6(34!+{k62-TpSqMx$Qr|MPDi zl%0jx3peDV>c`z321sQd{Vw${q#cbF*CtZJ>WuaDI+Kh2EWslVg;-2?Fez=OVa+lx zKB}{y7fX&vnK6X49&2ArR8+0D8qWdnbS%Hd%SZsfzg*!4dr}K2h@F!qnd8Z+g!K~q zQf|#j97FlL160n^ssTs39$+)LM(QJ+?_Mc+Q?+kFX{S4-31SIe6UQPwjd*D>=iR_w z4*Q7*D$!oP_$shTzecg;KTXWpqDOKKXO=Ut*`~$J9 zkHU1J&Y&wwW)FYOK8C!GQ--3tNag_HP*B6RH0Kgz>bN1%w{_`hp-lhKhx=?c-knB} zJuR?QntJ<*YpVwAdS@ILgjBiAP)Km)Wq~~BFVBTTZkQvviS<~GjyJV%{a~S1jM4!k z;R=Q%lliL!^A%fM2JtaUs#U)GacQvVsF@y*2;(k$iy8(2u@c;!})SCb} z7(4I`-YX8tq1NkmP0?I3PNu_mque24eyLANg7i_kJQ>F?A}nloy5O!EVCPw64<@1g zDFDBb?AbXAIe*Q5wRd|jNow}>_SkR~*E37iTHgIJ)O`%?6}k`&BjGVZyw&g?*tC|8 z@_F?5C)^NVAhDat_^+=Z6u7~|DL^W)kaz?l^LUL1Mv{VU$^X-9b_i*u$LC-RHXl%; zZo`K38t9V8lq(SMp)FTPBs~35)wB1(Z&$&+2wM&@v4H7UF1B43^Kk+L%nG}kO}Fdx z!ImC!Dm{`0`I*Do@M-UK6?%2_QynN&)K;A=0T*xpTUV`#& zmi6IHihkKT99rRgD)@%puG|1fxrxOkAVIqTuYye8I5rFgqM+=DQMf;0gQvspP)M2U zxS+BnT!KLTAb^kuWdV!roz#cYazLtn*qNN>y(z#cecMo1SGNYTr187F(6mwLfhJr) zsM#&kzZV>}-sGNSsOZ6*DgG~OBjlfeUO>4Hh?`GAj-CT7iDS_3$!H%Gr69pdODHeI z65bdC>ZKmti(h%rAq!THe1ya8O0<{>JD6+pbvh-$`5D!LK7PY;cRvWcv%t)pK5(E) zTKPLXu+B*UQ_@ZR+dZid&=oV!{pR!_gQkI?9K*zlyI-I47X*?HgWY#{#t?jx*C~39 z?y)1T(4!#Y<}^FwYx%D0{Q671uMfU;7_pjG1D{-Q(94}Tx`~s_6y_1n<*v>u>R7AP zcp|3dl>ei8LFfRu074hE(-?w-xP+xnV;+~v2cQPCST6KV4!U)~NI4x$luI1#EWHQ{ zK3FE107nk~zWvvuN9Fb4J;=!8!7AlWKzw`=!8`&2=tXdsqT_x8yiDu4o9LeZTP&FW zQoo;x&jOnawdM>NFYs)_pg_XiyCpN%{OM$gPRko8c--$$vI0=kfCZu(b6_B)k*m6( zI&Y>*CL&Lc`deW19Gg*~7TT5v$U5}-{omLiSr(f^4%f|JF#od(PkTL}l1 zV8dydj=!bf))rsbTI5R!i_5tTojy=?%5$3w;Q*measm`=Ge1A^vb$g8%!w&tS{@Ps zPiQk{V*fgs2b$}Sn%P%e=vb5H#n^741RO0#CwH_xX)H%iuqwy*DG@#3SQF0og4fM2 zT$nO7=1S_l2`D3*K(~pvTIJ5}#at{R2YWKEJR( zYpZ*qY&1}n*MA=1QM{I#s_Q>q(EEwLd4Q=JTHY%FLef}MK;8z~m)BQTd3_=!r*Sjv z`T(#U490fooA(ts^ka-pCEGx(jcH;cVPTfcE!OqF23Xxl8Ce)p;hqM=;T0*Xsf{sewI4YO#G%k#UXeMPy?{>| z5|sD?@I&Fx1AP9A+Qd^LeZA}Go4C=;OP9CJ+X1!oWy z)RN*1?$Ep!k{)|P`v%|z!tH?AiF92*HbSXw*ug1a;tI1OoF|$&Sm_&R_%9e=KC)Ys zxUJ5kAreQ?eM}JaK+SG!1ih@YOL?&-XJs}8kTRiC*-e(|u5_QT!ms2a%9gCH!JwQw z=cAw^y$9;3F#vW{2>6F9?Kx^tBfp9}5t`aaYW9KNmX=pca=`CHQ4ik1D|Oe(X-|K= zgR66bz>XtSLAYNU;k6=qL>UKM228=NxD#J}4B>W!4Tm1T5Mz`02;O?7h)}^7yN^k) zbFd0~&N2@TihqL01O(|4#FD7p{6;J+KK&b2x#zv2VfTtwG<@PkTafJg$b1%|~X`(&_=fH=kDofQi+Az9zVjZ%yZeqwjwA zh$?Eok`MfiiLXN3DBj~wQkGS5>lEcuG@W_2MXGWMGlXxKU_H9&z#sH zK$2(HFb8TmeGuK50{ptuDQSPPqs}#MfMzWkQXZ?${}VAS@f=`FYCs`6P!MCQfM})& z3wy7RdVG@iF(CZaUXGEHH|TfBX0KXKkmL=Pj8HjQ?y*Fx219DhRJ$!9P2MxkVsZ51 zd~3aapRPh(^9p$32rg>D@;ZZHgRtD7%>4iY1)F$dKNz6Gi?ugTlT!SXCLy*11CUaZ z&|85DZkL9ps&AS76_f@13CJ60(dAzOmxKeid@T%&DX(gL6c_R6lQE7$<;QA)IbMEe_WcaTa-StNn_e{mFSLP#Pj=u{6 zxX;!t1q@b@rzCXBQp?z{xt;K`x)HRe46#SfWe^)_1W*p8(8EZ&fXx8DPBRYi3%rQ= zW=+&L1)q!cuS*6)Hx#BiCdpknW^85^g>=d!e!Y(TPA92txl#&VlK1l^m!>+>-R|GZ z{n;ZqqNTu3eud=R`hRtFyPqv)2>GUqfzL2ACqpA_Uox2ry~NOS(kou{vya4Qv+VU} z%g`~+ww+I^5H17onzl&?z!j+}C`fd`^)WAdzYQvG-d;k$5?U&wp*f9k{KKzyr(Z2x zn}3G}wL#SGL}rcafG#3#*P3_#YX5@9ruTxlU!6gy?`+sv5a2m$ucO5b40`|#Bu4?v zr+Wfg^dS!8gjU*f2+19o$sfQkgHh|(oD5q5be)OfRvejte6YlS!EcQApB+oUg-e3w z-ew45f{CUF$1;H;cpDymY9t3bX#V4HM1g^c+8tHL^Ga>~h*mXxd1b;7CjIJyYuVvn zzVmIOPPMnO>9R@;LPgkWA?Y^Ja$Hp!-Y{i}Jd1OyDGp^uu_grH&!J#LS(J!qw= z5|aNMi9siYjN{ijam5o$5~!n&#H1-kIuOo?VTIm$StytTEwz=ybT6)I**IkcBIw6} zgbYn(2v`Q1>~=bVJ_TyjgXa01k}BDXb{U7rV54Q1I&^m8@i0S#9hT24jjqESf~h}I znd%_By&5jm* z$qs}8(nC@ZB7b927J1@lHmR40hP7Xj<6rWZC>x6WJgT9}Y~`BJ06E{f1}IRf&;r)6 zMg|sA1%MgiCnk{(TLF)320RngQ+KRr1HlLo&oO^W-VJPEd>vYBQTO1Xegf)PhBkcb z|Eu0I1T$s*pL)yCc%UZ@nm7L?3B3QYx6HtNu20{r>)(R#bNvnhj}-o;O?~|WIiGG=R`O_&_u{s z`o+El;yckp13kdIy4Z@8#L=T@kuyn(V&uEb_kBKtP7#rR2JmE-2r>xa=iHTJgfO*0 z_kMSy3P8m_tzf!3mX%ZAA>zP4TqRastCsYq@ZRn}VN;TciYP4-Pj}V4tz7`;vdF*r z8Sbe_{+4XDo;1SnD>dTycIe3t=Gg^@;#nBE4t~$c=-j^+yNfS32thxA6{T-Dtb6Uk zTpJ0=#_VojGG7G(6~=y!pbqh{*-3-#2eMf7)>A_iB}uvC~Hgm$W`!(%Ovcavv>^ z99JY@m8p`fO3pJhcH|Vm=ggizhM51r91en&V}72T`xn~d=Oau94!->kocZ(DyZ??P z<^Fwe4>xc%CI`+%8QQQd`W7LIRa$;eUloVgACufF^4SwQOr#CzlWKl2ZRl8SX*S$%T%k?09uSK%kZO&&WuwfyE_1 zddNPOv}y@^;t6rQ&l&Cxa`5rvvqD^1zwS7tb9M6>o>(PURX56dW9X(2S?Xhi2v;rn zBYP&xbu{8npCpZ*yFc1<)3G??%`t1jOYI+`QR<@=$anez{@)oMukq;;%Mzl(`G)mX zDP@n|HzBQ6uIVq}iTH|5yTffB7nxP7Bym&}4ZdpY8h2H0^t6L}pMy>gw_(bh)3f^|Sz5wy=X?CFI=T}xx**Skh=@j07IM${%`I~2bh8>quQa{9BE@ z%)?3*i&ar+Rv3Nb=lKWMZv=L@x8;T5176Hs+t0~lNxby@XxFfT0>$)(30ywhk`fV8 z&s(a}EcfFd^?JpV!yi@}M*||p#7ssj9G(~?ioyNKC(*RR-(1Tq-FVc<3+G;3UxFt47E0K)=LRIV&|BX7SD0v z*~gEIghuttmc;a=n!-!ZZpO2VrA&t_=zC%HMyZS+g7GzsLOV7Srz*|;`}ga5e|`Nx zAgUPW(?1m}Ih+Dp_&*{AS~DHG?EB1gudz}h0)(Q)jaYO0N+Moco1AZlMm+){YpE$o zQbsvmO7iGYEIvE?Rn|tXPwp40v-_lG>a~;D-i}47zU6?8bp7dLMYPqI1d*3P#OXe@ zZ&&;y+pjkkM4gBs=&$0RQyj?4(Rokp;G=NX9 zYvXlfq+xN+X*xDCB27y(fb{0l4Xs2MAe;RaaDL_H2dfzgrBxY51tMGSowC^&y;t*O zD9R=&^*0f~?Y@&r(z78|7ep+; zKdNx%F&*)t(N`;Ld`m0mbqaa!e%E#x8DM za3U(|7fDfv!sS)49>mD z>~x?w%{BKqtDS#C#ZBI)B7NYKbjL5ue${reL-yN~`&ql*GoOV0I0sKT3Y4x000r>Q zgv`@cWOMgZltB$zQ?$oE;R_CuJIyhBD!`E@OPu@SN+4zo1_!UYj@A7U#Qpr_R}qDP9z{~7t_X9wK!l>M z^}G)yHN4ZtT`Q~N^vP`5nfEhtnShHQ_>iI|3I`fJZQNF!SaE`c&5FY9=nA6{W7IZZ z^{waWR+_utH<|WXl=5!-%$0sT=|hn2K}T)&6MEFME|F%-{h|*Q7w-&Dgy|pJ@G5FP zi?}d8u_}K@=9go+q$sQZV{w)Y!(X~P(OQ4ZKX>i#4IO^Itj?fXEB8H|ZrFsE z_aj#q9QN-$e;!HYWku$&ra~+?*@aKL>bIF-rm0b!>bZ@JMYuVHqPKb(` zP0xxoz&J%dl>n8pzl^YuEK9f|_KJ@5*c%dvO9rNirDKw zBJIoeY{FH}-UE>|#z8v+rbQM!(Zk!>qn_XL6Kj`0TU3-&csdWRfEJGu%3gZjq5Xug zLwxrik`i3pTHv|nR!x^YdR%b_Pp{7$T%H)|d?;pB^wPH>^&~P9{g=hVURyV@QsbrV zZq~6ZJlikj5bab#a=)L?wJFMR8mCCpNOg=&Q&If>IR$NtTGq*sYCp$VJU$n$DB@Dh zoIPI)hm-@mP@=c~F5ktu3D1FK5i%X@qkgZx8O9B*(_1yZ2qfntQkUj8Ryo1fY?THkFx`HUv%VtU@R@A|=7*pd>d_=$Nm0_9{ zSE?Sd9xjgX@7n#vaDlU)S8pV_IA`qaCraMjLRC&-;g?o-D@Pl9^enERyrRq!N>NuW z(w6X_wW4)*N<=#KhwrqzR2BeW2lh*D9c7%{DuBsO$r7%&_FFL1B8j%U1y@X!8T8X@ zbPl8$UQWH{GAJx0;D0>v^aZ0dyZOkpmxx?$lzw3shK7!WwS7S6k3X{G?mDgK$h8(` zWPB`cY*vvOnMh{pwnK(+K zJ9B`lykNREt}Ak&kMZWx&59syZ{79L`Dz2(iY#FPg9KxVb~!D1me`qAnENBPW?4!5 zj|F<#X38enGYYCj!K?%55C3IiH_bN}Q%}VlsB?TosfA zDiwVLAvt}Dx~ojdg%;+?$ZlIx-MV$F%RtMwkQB|tgLBvQ`3n%c)hs0zI}ZqsoJ4kP zc;bylN{w<{+`#7y7<<-!INNv%Pw@|-l{k?AORQchs<;H2acbxWyL+RfqU&l6Sc1`t z&Pq+S*0a&51w8(V-7_n#DFrhYZQCcdFUcQuVd#B&tik^kalOnS9jETdupduIL7bcA zIQQ{ENS_UM?NX{^dZMdSs;ji^%0R1Ay~V91^VR%f6_e~iK4fAJQ8o$3q*Hk{H_bDehSiE97u{7Y?lSDh8o@&z#s`_}D zowhdjorxPEG$Ez!*(MTTmBQk|`{jD7D-yMGWF8hZ>Y&DjoLxKo!9KBCm=wNU%bd@$ zmucU=&{RAq;zBdu&i$ek3;vGLQox9&jAlRHGTlPJiS){`PyNFs&<8suHIEo7%i3Kt zd{OGuZ9c$qQL%WG;2*80V&7YxcHx4NCWoA3+nbu{`j>v{VI)_*gmO2{e*g8e+v`LL zO7WfEmv``S?I7rn(T1K6+8FeCG^~4v&~C}A>=WIBe>484@aODHO?pbCQL8wSLhuMU z)gq@!{N8Vj(`+RAdvj9>@zaY{r)u+t&I6n4L&X#1$n_|8k_#YW^3{& z6gtM2R+SIkTK>v8*S&?RMqvw&7!=~>16F(l#z5BCab-lLE7I7^j5?t|t!&{xcVT$B zYLDXEUd!xfnPH$PN4|gZIp5bL6E?DEiZ?>(PCyuu$Kkl5Ni6+J{P%s{k}4arbZi=C za+b7F{H0j(!KZ9r7AqfoW8;3VnU-QlMTjFpEG*T+)D;EW3u1B~x>Z5k@;U5Yr}Jh^ zhC~tlYW1v;%B6l~TKkoSfmGFzsPV+GO#v0h$gOg#fBI{9=$H{z7ou}t0|&8oy%t>{ zX5(~UurDADS+L=AWB7Q@Lr_XR;B!4IrH`3llRIgskYNkaApZ2?1 zbDy)Ts`1wPi&iOf(q15*RQ$d>m?v8_WeAEsN8*c;^P{HS?)GFgzPHw7It&eWVspLV zI?Sc>XLW;?Y+JsW=w+3wI3SlQ6ojDJhe5`bDwaD{PunNR5cD^!*pjV{`QH}j$F{k+ zNAZ0?U?OG2S%%yx%<0XVJ9egkA6g^zhF$DLh~R?u-dLz_Y_?2IkH39woNhcIbqJOq86Cm* z`Dvc7+vS(VQ&BdF4fgi=5Uhnb1RnrnvqwD6u}V+NVR@6=(kaa{SrAm{EvM-kR@ebA zdG8)thHk?e-#b0|ZMIxxCYD*3Zrm`Ho?R>b&ev75Xs0u>TF)2Z`>;RpU}RL;{KuX4 z2i{-sDxP=j$^ZWJVZ0;WJ7Gztz1+3zxv<-S6`?B2j3&`n3=}i;g>d$;+8(8`ZgAGe z0u~7($5s|oB3MfpX*Re;YHZqwFN8f=yJXDa5TcrC2tNp9Ifn^wr=ONqfut1ec{cwI zqLmcyMtwQwlH}yWNEPMwc?K6qn3pLJE<~s#9{el%YZ70(pk^p>TA^bFt7x(sWrwY_ zaNBS%qUVYq!%ieM=)_qYdy2=LdXUGb75kEx6CKM?WVIX7Y=GJ$^C(U#yRZt3nHPAD z*^1Ip>a_wk4B@f?XdnwnvMa9=QdKk@^)aNf9EyVwq=$V~*>QL8N^1kzi^p|dcvW0X zJ8kc+i7=U4ierru_>AHKyJv!`AfC9zBKtE&>@`-#LNh=^oL;q}i90TfcDS9c;~)3= zBlO_7Bx#Hb-5llecdlAfPn`z8tn>0pl<;$Lh)@Q-e$n2a?-jv9Gc6#FD#Qf}OO zmywq2_hhfBziF08OM;_bXEmM_@1mK1grBdO`on(qR4&<#ejuhEH1{DCKO5QERf6m5 z^6|)at6d`2{_8GP9VS<=J~>&*boV_LG)HDkw%4QRO~%yw0ynxs#x==O~rZnnJ`b-0sW;b(`WlZc#T-vL_tT0}bA+gd}arN2vPVrk=7* za*4JkDjtE{7;|tKP+kKmSk9yv@D`!4-Q3Wbj`x{$4CzaUNDe9anFNJec$}666&(7b z<(?Z><;y658uX@3`((=;eGNIBkiPBf(~&#ScES@2c4oW~$orZ&(qdXxe(%BGq-65`6VdlkL(KD7tWsS9! zPb`zUV>*Ne?p+to>+=srA_q5ws^8;%eCNcefdDIq+T1-5O^E>Gl4&EzgtQey{-gGY z8gEpoImzt4bHl-h(bR~(nT)QYuDJc|b&zWjGG7ReqUwwv`6A3HB(FF{pZLQ2Hpfcj;jg&8%YKg+X(uf?tt5Dy^E7(?rWBd zBOve4*Igxfkmd?;Nyl28+WB2v{+?A@a&cr~b5ODwhd{|@Y^m<`9`|zUuP9o(N=1gN zOXy1W=_(U%B$nW5cgk|h&wVYpxwv>G`*!>zE!mN;IXKHSI`Z3wxo*0TPCb@rkpBl3 zWhQ4ids@i=rV;A5T7(q*-8Qg21D`$IhQS}_va#^HRM&;vq=_F%bs;v1dMQ*sxUG~L zJ3dcj_$GOalWksU*{hlgwx@dun!hV+n@AGCyANC>$n+&1lEK$~`|yX&OHO_Zf3a*#&WY!1oy`j4h0ck&{R;GTm3l~`8F*JC(m|{p zd+*-8(%VBzC&9})FliE0_HYLjOE62%8 zpc}#oF?N`XM9st0mOi5u&wGR?O?s`_Dpj)ptmsdj%iz2 zc2=|=fu^RDUN?0`B`i#4;Pg1vOYPNLjf}{JK~SDYSY}$-3SHjcX=+OX8wpVMa;*tRTEuS1q** z#3tR1H84c(L)e5zOVy1()E+qeBUpQ=Mt-ZZ%x}rozujS|fhYMsF0UNCWW$O-h9bcT zXY3C6c~sATC$YSk0f9+2xi$&LJ*Fov#TFuV&pFN-)jmwRiU z7C!OS(;IUp(Q(mTgvbz2=R1(MFK)l{Uh@8x{=I>5!YKKSIYYO-W_a8d?JfHZB{>1( z!sq|P)c5~>98loDxoz-2mUc6Y+q2X2elchi7;l{?#!o4%nCoHMPbizY9^LDB)D2lB zzmh}^R3)fi1SeUptdVgea5B6d{_>{D_uEL~5$<%F8|E|Trhdk%_W2yfz#~IO1>d~c zj+S8hE%L{lWtzPfT)Y(%$i*q+eRG|%U1zxPQ^XffVaWRoan7JU0$sZXgUchUtVfo8Ne-sX%C znbQ#(uQ&mfCN1E#$(?dt{>q$}92&OQ-Hz<2VilFOrj;2QWx)(A+-XDD8Rh1rHNVJN zCU=em`^CV~X-3`)Rh}t}@y@IkzDo)3R>fIhE9L}q7wBq3Brdw{5GA~EWv#S<%@T&Z zfc6ScU;H`D$aJ+T^J!&Vxa1BPd?aMFK-_ku5#l(Ln&~;cbisgAO4bCLA_Pj$-?$AExDCaofX!F6I#{8-)+A#@slGlp{9?Xg(GTHk z?taAFjS3D97O)V5E>RwXkr8ulTCq0lU|kLW*KhkIAc-=fUcD+f=tmjwLuaV&{#or5 ze5qX}bn9b|uC*1onS+F7U}1v?e*RffM!bu@sgzxw?sOXep^Y1@fEJ&Y!^|077o$!p zSRx9+Mo&YMMg)wY$hpS@)_neS{n2rJ#(>+91&UY!Bf`JTWW6Y(a$xu10U zG*+Hk@Ir~Q;O7auqVqp1n;bHKjcL4cz=q_{4}?ji%mB9J;IG#%4p2$;zyo>DiaAc0 zbL%L_CQ`(KlK=kw*Rb*j8H;QY;XHjs5My%G<9UA04gwHwaC2cvioT+CgcU3p45;_W zP0@RtYsskcY+8GPnCK)MiQs9l33FKD*K~|vO+vlqdboI8?@*QakKQcMln%!(cgvAS z2E9B@!&G}Vf$sl{xn2%Wg@GbKSeq)wkpb$XupRMl0-)&yXTRt#5$Z2V0u0eWpPxlO zMKzwJ06swPxl5!u>vkUl8x?+_n7&d^u5AtCdEtKOnMy40WxR15B@gQ3s?ZK2=DqPS zEJvp;gT(7{F{eUnG-8i@Aq;dXk$#hC9dju7ndr2-R}e(Q%*_;Uv?6TQs8&u z9iTMtPIifAhux_pKQ_569nGC$=DDgip=eqEBt zyJU>Nd{LA>7JpE3j_wx&GjZ4YNw5qcR_*s~($ga#SdW>!1O-x8(|;0wn=ueyak=;M zDpXKqkJOD-K*e5$4pZI?w}d6h%dwv@e@QvTs=0B?=LAfcWCeCDfvFwdbEN^34uet| zs|Xd5>S*-_6}|K4t)D7e-hV0y4u+T4FB(ZMz_MUELhkv&W&toOF)_jOk&*(X(Acqm zeW=Q4np&R{p1tIoWAN6zDiN;9kofhO+w;$o@}5#ag@rv3J`U4@&wpD$k!2e5>ftUtnl?C{O+T^rPSd zZPShu*;wa89u69b^1>tm;C7(pcJ#19T62X>73D}hH!Gof-4uTrW(;GkN58qf$8Wz? zMY$Kb+Di6R8hImmCA2|D=)#ZuHm1%%p2B|Msz9j*=Vg`Sj~>U>!lg!hlJj#xH@}at zTsVK;MZ172?DZBy6Sp7z0`kSAlf@(_+Hrg1=M-jbLl$h5e|`l6MCa2@EL9{H$@`ye zSa&#(fEDIDVDu|F$(Oh+J?obcp?hByIv}V`uTNU4OJxm&2H~d^B zk$XEI_UiK!A`PBQ|LOp!hspO%U4yK(7n zuSy>fz$|^Tm4z>oj{uK!Jf%}-c(KjZvcNVuQs#%2?A>~N(~q0!$5F1qMS(>xp&Vt8 znVWgi!G$)%cJ0j_&$bFc5-C7g6fqhI53u+d9*3?ptcI8G&BaNV^I#PXMMM48UwLhe zj>B-^qPOf&z7QehI zzBT!S-2B^=qepL!O~tx&TvDt1p7|_ac{#PqoT-8^OU)_+KtOHVo=U6A)qWF~wT7OE z!h=#iy2x^Y!hoVQ&<|k{hfI*DlgGvFqdPaArE5Kc>@g)D7B{d6olY94nhMFK8P2=T zL>gh$PwOW~5>GL2PRL8Bu&$zXd)9rgK;>4~#gMs7)}AcxOEj96nHg|d6-V{rhK&}9BC@x>V9eAoUR2VXQ$24$mfSaht(uW$W=F! z#z`afby$`G6Y@x3ksV(UUw?t}6;u+^@;UY%D<-f~c65cL2BHHobM7md-C_4OGn~-x zpA!*%DvuvO9t`l>1n1Jhk>Rzy;r!kqk@jvho2QfmW{N;vYls z_KNC7{9%yt(TdPQ=CJPFW2$V->1)g>=E1tHQKyqAr;Z+d4Wj##Zx9V^YnWvJU5(d6 z_x|trZR_;7pPuFEyJMYDiu=Lq&PuQ?Db+CyLB3d?!Y@x|qPpmo>xD2>EtS>KQpfIGBR<#G3mg}q*Hy$(LQE_Swf&MkkTw#oXDE}>;Wmun zmKTV!+eY&ruU!Dj=1>{a&H;xqb+g)*m9c9bwu^mA=VlP0l@Xy0u}p4z4x-sw?aaub zCIMhp=)se(KNcg<83e!KeyGZad!LztXOm|a;$11!JrKBUeD=PtYK8Q4!5{;A@g75` z<01i$kd9Bm|ckmzx z-uwVkCf9ePE`#K=_MlCWCLz*L8`(*h;Tl=S`a*$nT4{#S%e(88g#kV0)l7-_P`=u0 zVqX|gAI@VrSm|v<2_QW2O@Rd>4WJ%1;-Ab3<{;g(ICjIm%>&1)cD}3GY+>L6^C75$ zDfz6z`cNXW9plsH9@^D@o=n=DL(E{?vSY`N;lv}!-lU2tol)N>{w za1P^nNJY!pWyAQ^Q>j~-4j)XOxq`=c0XgLCY~a)cNYg)|%)qS}hd+^H5cU@=H&S%j zovI}R%b`qlmB;*Dmic=fT31-#&b5_zT$um~Nh5~1nK>h*T~IY%Zuqq8Mr~`pccUMQ zb1{bKkOqvc?lP&u*R9Wyz{R5j^V(>m0SoVe-*W_*94arBpnmsXWBRF+nCq&VZnY5I zI==q6ptq#Y$+vF9*OTDc0QbE&hH5~}nUuwtK@Mc??5Wv5Y?1v5>_iO@$=V_ytQ%OG zK^ftPP|`jonKGI8p*r$2Dem8Is9gYlVY3hww`Y$r>yRJ`Al2`{l-97``=8W~IZ;R@ z0iaM&JdfVUl-3j?%uSa5T~g#WGBe!X-P%9v$_y_v*Jn|@BEw=ohty@pOFLblD&`Cp z6`!|E9FP_cg#oFZule_YE-@dg0Rwu^^$jsFB739wWXvyX*B=2z67P=2?DkjkG{Vz# zgY;{*Z6&FFke5>e2K{~!GRr`AqzhUm{1~6)=cZZ6pd_|sUYgtXPU~-%U6_v0YHq2w zgYu046_45d0$OL1J%}cr-Z={?qhQ1_#Dkklxn}u}z(6oLnZ(tn0bYABWz6X{$E9 zI!>W~eJoMq9IjOUu{fRLdw5U3XZ6cM6_+p1yD7n+L>H$A`(|uAx(zQa; z&ApVXax?7OnJ*ue?yDi1I336}F8u5nizwZ>*7^u?P2clB;Ks!pJ(DKCu95xu$hj4Y zU~A57O-)UGr=2|(g2T#hRH+^^kB5g> z{N@Ygr~9Z$5}#KuR@4oRDFoF-b+P2^y=Z;+>o=v5hoUsK*0K2Uirb(-nggzFeQJz% z!Z+I9`I)gYY}g(cHy5)7!&O$F+b@P=pXj-doCVf;Ya(J|O371*xIvg0_^_t7|hK+ zt?G=z0qpKG%AA{GzWy$YvHxVT2Mpw?FrtX0^M`w?3R#m`j~VPH`#B7{(fX1VQF&EB zLuypW>&0Py1|-Tp;rE-Bw;e7$brE0D>(+R!^E%!0{z zl^=U^KKjNv%b0}n?-d^i!im zjCdFwiks5E83q+QiWXWVVI6+owg)dT^86W3UvZdDgvyZ(i=aL4mZD8+pR=UZDp0C8 zu-i=&N*ONcN$j+l)}}b{vLKfM0vxC+0wmA%+@0-FP2=;HeP}9^(Yj4>bqCAN9Xlo$ ztH|Z_hgmQQ%NHJq5t2&!jgL&-hC!n7xNJa4X!G`&B-!DGN94S)LwV(Z5(mD_4lo3# zuUXbtKXcjNn#CJ1(-TU5YL$KK+sBpJksl`)3J5o!C2gGU-KccGUC^n|srE1`I$E{i z^#uUFpg+69N{!uU5ISi|%vmG=%V*5`r#6b<#7veGVH-_3UZJFo{6I5KSB@*o&usL7 zlw;f;;l?gqb0e&KXURNGHyy^S94jX&sFe_j=arK4*RztUQko&{+xJ7dF)7CMpg#i} z(nsyVMu>D(iJUkQ>g!a+FF*6nA+<|Yal?=ZhoBdUlE<490?bmBt;+-Sm8g=|O^<~6 zG#-Pj*P-vHi-fBKf}|ZSL3r%dmIMaUM`_oVLo4Aea%E~q^#_F(*iU5KA?Ypo9*&PQ zz*;ww`mDM#1S#*bI_)IleRMK)HR!XSa(X2gz7Aiux3iK8fH*rS74ldJ?hgm}7eY4w zK-ukCa#^E(_0w(kboc6rC8Aj(c!Y2eH>|@* zDe#=q;c|zOx+9*q`o~{<@`e4yW!!%De(LOJ*_p+5NNI?wvm5kPU#YL=0O|&VETxn- z?TIocy)KniPEr&b@tx{hcw19cKj=3ZyBJ)^cfe8K>L+cF34;fxY_L)Fh1?2nE*&Q- zygt`gY}C0#>^|u-wlyH{uGk05Jrquk1gsMgZmU=F(DcLoOXb-|5ZvhO8uULcuS3D$ za26T&*o49reX?*6UfnD^_kF^3##`?pPi!9jQDiMZ?r^1}D$Sy>;0f%c-O1T`(Y9#= zPo>7c8Z_wY;>XuHIC@cIz6YpATejz1VJiYihr`b0)pX80X%D3@M zB)DVV9X$2>?Qgv98>U}R05f`q9~I}F{tMJr2;V$ad8tr#X@yP1G3ie$^*U{{SjC0m zo!b4@K_V({5r%TLR!D<^M!nT@*J(eL0Jv%V{tq$_?{L7)Co4mk_GPkYBQ8$XO8qv2 ztkr2A@rO>@c_3X_BaU+~Ts7hke|Yp;c6Bc$Z^_<8I;w9zf)qGySuy8}bhb|Zof~!3 zUdwT_e0$3haWl4(2pY+gt%Lv*lAj(BTia7w{$*bZuw*cPOJ2B^uV?mL0qY!z{7e|( zFS&f?ae1$;1{(Ge@IrP~qD0l4j~l%0g<;c@Fy&i%V(^x5`J~M<_ysKzh38rX7 z@~ltrH%7d2Tudx?Zq;|JmV>E4=gp@Sh9(zRvyn=Dy&67^m{HfeNk}7>wOVd@LbihN zKnjm@HIe{j;UI{V#a|IB)Z4?${Jz{=YCJxM!%P#B(^tJ7w`nfkG9ph~GoX9|x5WEV z;6d2Fr-|lw^pJKbt)gb8OHBw5I^kU}q7mn$bBC=^f*6;;OmN@n*w?wuIosz)Sl5WB zO@cPr-*07Zv1Xb!g;yi$oY|PkNErdUo3U5~$6^}WkxJ^qGo_Cib^ar)gQgLT{$HDv zU!{!b@iO3tfDuInOu))CXHP`&OSITeygNOzcYgcg&(iT7?+fp-q*-`oX$O0QY}(Li zW2rLc5x`~9b4&RS=Fj4sx$ml-CcVQF&l-u7w?gR91Wst6>I9$69`$~_PP&B^H>U^L z>{I?)p!e`|VZHFg%r8meYYw@pES>skZ(UZfR6(bJ)i4>>626|17N6|0GY)1+N%;fM78gDS@jM%vq9fFbqG}ySQ99HIGnEQe6GU55*K?rTR zV(84s$M%Wh8rrE!Pu@KY4%TV@ zVfMrH)($Sg$_;C#MP;nT&n<=aaP~FrzoS2%$&m;p!#!#7#I^NXcRQE5tag?8B>5OC zVo6&%6DyF8Q>Bz$aB*3Lce_;}d++=8WDr%OE1xjqd#fLp_N_&^g7VbgJbS0^vwL;< z8)MABG8{#j3KW?s=M9o)QX2}O2(IbpC=N4jzhD@?dDahZ;$R8NdQpr_) z<={9uV4a=YR?U`(m+;n|hsSC|pM|uEqh87aG#j7!)N*Iscr%98Do#Cr{diu=9;Fj5 z9UWqy9_n)m>kh)&YV4vegE{kB{t(o*iS##ZhT|NR-u5xdby8U>8&&lWu(PM7AL#e5 zm}Vt8)253b!|LY{p)PoZjg=3FZ-f?Gul zv@3MGM3_lx{q3#82&mx;2(W)(jKq7GZklhaO{7!661aTQV@xyrp$>tcH{e8b^`(~*F@xz5afJ)qeFX-EgBt;?1gh}(Vt5bb%9lyyOKUu?KP<$9#rlf0 za=e?zT}4e};!GEm#}hfw!@?D+=2fH*%C1D0E=q8GuN*{XAINq7?AfzLR2}ewamy4G zlFk#rJG8y!ROMheygZ*$dMa#J9PwAKsKyd6P9b^Nv?#9N9^&g(%rM?J;xcAkVfcs~m9s7UAv6nb`uiO!He8M}ce~9(u$3^=W8wcadUQCR z*ZsZVOXH$no_vB`n!_Niqg}*o0i^_6>47!$bWMhB(PY!2f=feNs!8hQtTpPNyu1qy+|kZHxrY7HdGZ6_ z7jXDUFF(!nq?{|U9|I+|)Hj|~>pf-Fjyb7J$!xb$w07STn{>NSdw5yNV^F}ww}R-%T4GbK9IM(Y&~SP<2fULI zYJFC!RyFMy_F{q^*O!2P+2i5UJ)-Xt-rSMUxw`k=sS}3U`Ld*R z0T-?>$Z$7&eDGuTPG=@3zr76o7WT_&`uE4U>gc%_!%Z>-SuxvKr0lwvkq8_L>feV1 z4VZ!3mxA|Qe~k^=##1cd?b~0?R^pj)Q>+k%H36%dnk*{(JTFA!gDHNhjO-NBg$L=v zCOk_^QXHF2)KeCX{aE&Hgw(J?6Fg+%96PXP6Z_Yv5S{dzn#`V{n0@bz+q12iHNg(} zhqMqj%+<31m2)$A|I_tvo;{!6>TP)dLr0#HNLXPe!H(ZmOs89R=Ko;tyQ7*+zdvyt zb;g2X0qH8ECdN)E4@dg*D&KCN>u@ot|B!+=pZFnDAJ{OA_NFMQbPzy z_C7e@-+q6)`#WcM|J!r+JtxCRc;ELax8Kjb50)6Zl{$oPPtQ5KNwyjREe5$qoaQp8 zBljKxU*V*&ud}AR5 z+GX}>26IB~W3>6F$Wv_~QAo3jT;S|vy6(BA8h666^}L0-!|?!1ejOos`=*iQOh|o{ ziD%hJM%1ecDoBlAt(6uSJ^pl!Jv`ij;Ot>Kh-h#rCJA*?s9ySJvbg8T20D zm$J4=xplN1X$K^?BTpM1CNZf)rOaZ3b82L+yv1Qp#$3th2VW}AX-|x@#xU#4=Y>`S z$7YdzbI#+$11eeypc|)bww}v&)=s$9A(69Zi@M(TmovnzTG>ZqZeH)0Q@%Rb$r8*% zS~Wde>eK_UagJaia`*L@L0KQ&mVpY3-mg2i7+zfr?2SlMZSF<;ai-{g%-dAe8HK_x zg%d`p&mSQ|JBw^I)5G0wR0rbmb=rlriK#O=K=8&`dUoj~lmuQ0oxzkBX>T#aaf+FO z6IT5^2DklFjJZBBdx=H2Sf}5bi9eq0tD6cpEf@-do6nap^7v>6O;oVrxPl6va53|f z>|eNs!j@5xl_nC58~Rle$3|JMlh3+*Vc2Z%EqC5vv;Nt!Qk1%75cb^AM&#qWHW3J! z)L%F|8K7hG)IpB%w!KIAoYlm*Jfnzu@#zXa^NqTa-iZ$DcT5>WlexSDX}7K$;^%5Ll8r=H!U~!3<~}nW&t*@<04_XcBUxt@xyQ9Iv~)N{!-E@Ck$>XbV~6_@tg-a zXJM_o`U7LSe{DKAA*BpYtoL9x++0_%=n;SOHbu3UUR-$b9Qz1fA{Hb+Q2>R7AM>?w?{MIpea)W+;$fe+h-L_T! z2d)89oed~t4x%i+W9gxJ_?2@xZ7(%3F1o#4$uq{-fba?$fm z@Y?wGslx`T_VOXWVc?mk_lIs`Dg+W%=Q&#|)_!jSp9z^8v!!)8Pm>#wS#=}1QMT|p zI~y|J4gH$^UxA;7;xpMQT2ZGUeBkRwOm6Un{c4$7j)+lSgLWsmrL>l#xULeUw48QU z6ZyPdvPvwR;z5}$dq)~YBRA|xRL>klqS7A>BHfr*3C3^v-O{rl5L^t#=L+ZoMTw?` zkP;xBEQMf|Lia%ag-ySIDdEZ}AyB1uyl3|lv=hi+uQr3%huv(!U1-Pv3Ui!hg;z7& z;R`elWD`k3sL_Qj;^0HX3i0YIdV**p(DN2hWU~5{#%QlnJP-dlc{~RPImuHyAj!Qi z&08_C!gBwLy_J2QvE>icqkwH(hH9xpjwf=mdqmHv`L1 z{NpTJ&aRm5ShQ0C`VpT{i7F34Fk3gz^qM%F+CHD}L(OQ(s+yRw2G+q}O7e^SrTX5gP7-|KybSjoTS?`BoqO=z^IN8vFDZl)*nI#-|fgec5Ec%sB(_-K1KSs zD@BCX2DCEVD(Q!SwZGhV?<$)^b|;C)$1dny+arrio;xp9%c+B2DwX(x(y|_(q#^1T z55;LPv^TS>hLHBL{*Y5O*IhkVsjiS+E9hty`*^Xt{IOQ7+Z+ncRF(`qS1quq;~PG= z9`9{j+at*8@m+Ch$c%sd5CnU?`l-?~!F4MV(n}A;s&1jlRX~rasQD=1uKl}G{d7sI z$aA~JqOQgNEDGr2qO#Uw+F?0fOBq%oA=5YS#`!tkG2}a7j4ikmexV_?%7T$4Vvda7 zYM?TWWPeXI=nEowijhW3)2VNby3qDn3HqcDU+Fmt6=EH1f*?*dAT4-ls}_p2oLUc? zb+Qf}kemMcd4CC7x7sjlTKg*OVS~u>6qswsqd|dXt?lPf1al#fR^&QAWd%Z>R2?xh z#&84XN}y(gL_&lxn#yFQulk}W9gdue;U0#ekxr9t?htZR89gN(P?%76K#|J`4y0YV#7J z`as@EGKeIcy@cs_(R<{4*8~bS)4zOt+bk2#CFpm4zH%-sD=`Z8IJuu_;+g`&L|KXc zd+63HhP8id@2Jw2;cug}v& zD|P+sP%y-l&3#(!DOJ2we;dhD~9$xD_uGSsW#ddvX zXT0B~wsub|HjWRZHy7MZLLo%l-O%?H)GbGNyZvukLg9?<6*ir%o5|0hY53tEyZ^&+ zh>P6jWj=%@h3o$!X_kJ3h-?%o>eL!_(Fi3ZpZ$q&5z~B zf8eo8&X#Ggt-_Oi5-4}Kuq|4S3mZXWn=i+=7>Z?m7yRuKyS&C(g<9W>GH(5)o-S+G z0e`bKS9^)*4)3}o4$zzVV3}?iIWSj1 zd@87Yy44-Q3m}WW9S~>=^_D^PDH#}2XbpmRZGM4+zJ#~;rb-wbBoX2xx(Iul;tmqU z)yK=tH@~*M4qw;#>E_AL$I0a>*KOF%(`n+!Yi9G;hn#e0-hxR>=tZJQCx~rCk#5SLq zkC2CXbrb5LusqKF6Y-en+Nx-umz10zE58kf#4fhss8<2cl(nJ1p+%73K|byrn@_fd z-F}#!s&Osx`;rL&(%L&q7DhjX|3J^Mv1J0F_{;OBCe7h6)n+f&0Y7GAFTRGo&9A^x zPjJb+en;N-awwzuu_IbAjj<1VMPJq_kqOZ&OkS49qh9a0IiX{tR0p}9$x5cyBkJa` zUNg~*zV*EbH?^4tu&0uDossE~t2T3|c>jas$@fO|tndWwvNI?Aq?8b(7_K8*xA1+i z)rVE_$RB%@MWvKo3tpq0xOS+RzceuK0p-;tE$Obp(n9Ry{9CW5fwx~ftM`xo7n zSQaS`yjceO>gK)&XAS7au1hD1(M}SLAd3hOzYL7WX5ECSspAHhWhHhgR66Ww@Wl97 zWfHK-YHya-#=CorAK)!$CPe$spaQn(8Z_+yL4s~_5%FR6QmsK9rDQ6SqOs-cz5iS! z@cPex;EBg1*=%b~*!}gr%oai_9>WREhzvWT#TuwTDE~Dd?48&qU%UcVvH)b&fA9u3 z8a3O7Ao>gW-b)B2@E`24xm;|hWasu3XJ)~9kOaa+3(fBzDy}cgEdq#f^WGys)g_wyZ9Aww~>74fz(Dn@tGoAs`?&Z`8#h@V0;LH=w{LPbMoC zx{Dl1I3T&9MZwG=OtLGMZw7BbH)%aUNEECZHji6ZLXaLdwyOYMIwCrQ*VtD@Ozp5O zaw1!i%wSNNLzKvD?5Ru0f(Gott;?JI0$>LO`$E_M+lU)v4591)s7n{R;eXpwLJEgX z*I>i`vuZ&F0)OXE6(sJq}!|D0l6C18hZnE4g~m)7h-*3Kbd*UpGrVU*^}TO#7a9lPtav7@>xz@<6iE zu#@ts^jmz@#OdYJ@cyma8A9vSO4*$|7ndlqXB8wY9`7aK+LpI{$xgC2de!A;(tN5J zsgm=zRfA-nxbD35+xAP%zkGZBXY569%Mf3yTL@Sz3DE0f$KE1D+(ev%fCf1D0O-Ae znL*gQBIh2TXhSm#!Jr(mErzU_oFLqG;~1vru*$Btx!2tUcas}Tn5$$2;Y1ii1aTIo zunJ7__4|3QR0&MgC$>3m$p z_w^D&uZGFbrlUV=hcloiULICl%K?0L@0$6ikV$xeheIbWkNAdOJ@*;Y=w9!sRh9+j ze$*J?XoqO6a>;;GTqnz@gl9%juR~KUC=;sg5x+pjqtW@X%8BID8|7ACDmge15b%JB z1T14pmP@t#Db2>40F%*7luE1 zGD2lcn!&App9b6MW4nbwN?17XjlZ*SOKe>F>kk%Ui zQYRSn@Whgn5tTMYmu6v^wA*=)Sv3 zfzkg?QbQy}V12D4oYaCH=0?QzH7>C0r2kBQtJ;*TJHXo2*9B+ z^0Yq&rDwYj1FBp<;1Y@HZg}-7pLcbGn;fgEWvXZU;F%*hwj7qLPKt^af~;S?x<0rH zKX(iI=*;?lF`k;yVe+6~tj8*VSecs9>We)^1w8jBfiSvy!>?jGW7s@+JgAgjlo(0J074QLf~{ZY=3dF$|c6YX#To2iaaEkYGKE7t0)t4B`*NSP_8e8Z$KpqpTC0w9jj<7`j##6y3e{MKfK6xb7w}m7Gi%@!&UO4`Caz;Z zLKd%HR;iMx%l#J0jjjjY_ns%{coE;GUR#)O#?+`)P2VN?MS^64S40})@J&Z|@V#I% zbLjI89vhQR$sIk56LyXnXFlcnJd56Ck=%qx`Do;6XY$aMW2WN=U%dZ5kQ|0zse||63R6=(tXiXGe1fQ8=3s^$zq(yx$@>P~-IHGB?;PtzTqqXBMmk zKtp}rt5|W@+ej9_yR#v6>NFH=2~4>y>K)oz02ITc`bIBxRzGrY+%fIPu@*utNT)!d zel@9aN7i);k;ZZj+k%DTAzL-B*4:!6H85CcOcfmHz!SgcdPz6Y)VXTL?%DA`jk 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

8bbMl_y_tPGC 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 Date: Fri, 10 Apr 2020 18:37:35 +0800 Subject: [PATCH 322/415] Add JUnit tests for edit and goal commands --- src/main/java/jikan/command/EditCommand.java | 44 +------ src/main/java/jikan/command/GoalCommand.java | 31 +---- .../java/jikan/command/EditCommandTest.java | 88 ++++++++++++++ .../java/jikan/command/GoalCommandTest.java | 115 ++++++++++++++++++ 4 files changed, 208 insertions(+), 70 deletions(-) create mode 100644 src/test/java/jikan/command/EditCommandTest.java create mode 100644 src/test/java/jikan/command/GoalCommandTest.java diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index 85263afe9..59eeb8db4 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -2,7 +2,6 @@ import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; -import jikan.exception.ExistingTagGoalException; import jikan.exception.InvalidEditFormatException; import jikan.exception.InvalidTimeFrameException; import jikan.exception.NegativeDurationException; @@ -11,11 +10,7 @@ import jikan.parser.Parser; import jikan.ui.Ui; -import java.io.IOException; import java.time.Duration; -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; import static jikan.command.GoalCommand.parseDuration; @@ -35,14 +30,11 @@ public EditCommand(String parameters) { public void executeCommand(ActivityList activityList) { try { int delimiter = parameters.indexOf("/en"); - int tagDelim = parameters.indexOf("/et"); int allocDelim = parameters.indexOf("/ea"); String newName = ""; - String[] tmpTags; String tmpAlloc = ""; Duration newAllocTime = null; - Set newTags = new HashSet(); //edit name if (delimiter != -1) { @@ -52,13 +44,6 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider("New activity name cannot be empty."); throw new EmptyNameException(); } - - //edit tag - } else if (tagDelim != -1) { - Parser.activityName = parameters.substring(0, tagDelim).strip(); - tmpTags = (parameters.substring(tagDelim + 4).split(" ")); - newTags.addAll(Arrays.asList(tmpTags)); - //edit allocated time } else if (allocDelim != -1) { Parser.activityName = parameters.substring(0, allocDelim).strip(); @@ -81,15 +66,9 @@ public void executeCommand(ActivityList activityList) { int index = activityList.findActivity(Parser.activityName); if (index != -1) { - if (!(newName.isEmpty() && newTags.isEmpty() && tmpAlloc.isEmpty())) { + if (!(newName.isEmpty() && tmpAlloc.isEmpty())) { if (!newName.isEmpty()) { activityList.updateName(index, newName); - } else if (!newTags.isEmpty()) { - if (existsInTag(activityList.get(index).getTags())) { - throw new ExistingTagGoalException(); - } else { - activityList.updateTags(index, newTags); - } } else { assert newAllocTime != null; if (newAllocTime.isNegative()) { @@ -116,12 +95,6 @@ public void executeCommand(ActivityList activityList) { } catch (StringIndexOutOfBoundsException | ArrayIndexOutOfBoundsException | InvalidEditFormatException e) { Ui.printDivider("Incorrect edit command format entered."); Log.makeInfoLog("Edit command failed as an incorrect format was provided."); - } catch (ExistingTagGoalException e) { - Ui.printDivider("Tag cannot be edited as there is an existing tag goal."); - Log.makeInfoLog("Edit command failed as there was an existing tag goal tied to the tag."); - } catch (IOException e) { - Ui.printDivider("Error in loading the tag file."); - Log.makeInfoLog("Edit command failed as there was an error in loading the tag file."); } catch (NegativeDurationException e) { Ui.printDivider("Please enter a positive target time."); Log.makeInfoLog("Edit command failed as a negative target time was provided."); @@ -134,19 +107,4 @@ public void executeCommand(ActivityList activityList) { } } - /** - * Check if the tags have associated tag goals. - * @param oldTags the tags to be edited. - * @return true or false. - * @throws IOException if there is an error loading the file. - */ - public static boolean existsInTag(Set oldTags) throws IOException { - for (String i : oldTags) { - if (GoalCommand.checkIfExists(i) != -1) { - return true; - } - } - return false; - } - } diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index f1cafdace..3931d0884 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -13,7 +13,6 @@ import jikan.ui.Ui; import java.io.BufferedReader; -import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; @@ -36,7 +35,6 @@ public class GoalCommand extends Command { private static Scanner scanner; private static final String TAG_FILE_PATH = "data/tag/tag.csv"; - //private static File tagStorage; public static Storage tagStorage; // Storage the list was loaded from public static StorageHandler tagStorageHandler; @@ -64,7 +62,7 @@ public void executeCommand(ActivityList activityList) { if (tagName.isEmpty()) { throw new EmptyTagException(); } - index = checkIfExists(tagName); + index = checkIfExists(tagName, TAG_FILE_PATH); String tmpTime = parameters.substring(delimiter + 3); if (tmpTime.isEmpty()) { throw new EmptyGoalException(); @@ -91,7 +89,7 @@ public void executeCommand(ActivityList activityList) { } } else if (deleteDelim != -1) { tagName = parameters.substring(0, deleteDelim - 1).strip(); - index = checkIfExists(tagName); + index = checkIfExists(tagName, TAG_FILE_PATH); if (index != -1) { Ui.printDivider("The goal for this tag has been deleted."); deleteLine(index); @@ -123,35 +121,14 @@ public void executeCommand(ActivityList activityList) { } } - /** - * Creates a new tag file. - * @param filePath the filepath of the tag file. - * @param tagFile the File object. - */ - public static void createFile(String filePath, File tagFile) { - tagFile = new File(filePath); - try { - if (!tagFile.exists()) { - tagFile.getParentFile().mkdirs(); // Create data directory (does nothing if directory already exists) - tagFile.createNewFile(); - } - } catch (IOException e) { - Ui.printDivider("Error saving tag goal to data file.\n" - + "Your changes have not been saved in the data file.\n" - + "If the data file is open, please close it, restart the app and try again."); - } - } - - - /** * Check that tag exists in the tag list. * @param tagName the tag name. * @return index the index of the tag in the tag list. * @throws IOException when there is an error loading/creating the file. */ - public static int checkIfExists(String tagName) throws IOException { - BufferedReader br = new BufferedReader(new FileReader(TAG_FILE_PATH)); + public static int checkIfExists(String tagName, String filePath) throws IOException { + BufferedReader br = new BufferedReader(new FileReader(filePath)); int index = 0; int status = 0; try { diff --git a/src/test/java/jikan/command/EditCommandTest.java b/src/test/java/jikan/command/EditCommandTest.java new file mode 100644 index 000000000..17e0d3a75 --- /dev/null +++ b/src/test/java/jikan/command/EditCommandTest.java @@ -0,0 +1,88 @@ +package jikan.command; + +import jikan.activity.Activity; +import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; +import jikan.exception.ExtraParametersException; +import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; +import jikan.log.Log; +import jikan.storage.Storage; +import jikan.ui.Ui; +import org.junit.jupiter.api.Test; + +import java.io.FileNotFoundException; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.HashSet; + +import static org.junit.jupiter.api.Assertions.*; + +class EditCommandTest { + + Storage storage = new Storage("data/activityList_test.txt"); + ActivityList activities = new ActivityList(storage); + HashSet tags = new HashSet<>(); + + void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { + try { + activities.storage.clearFile(); + } catch (FileNotFoundException e) { + System.out.println("Could not find file."); + } + tags.add("tag1"); + tags.add("tag2"); + LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); + LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); + Duration duration = Duration.between(startTime, endTime); + Duration allocatedTime = Duration.parse("PT0S"); + Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags, allocatedTime); + Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags, allocatedTime); + Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags, allocatedTime); + activities.add(activity1); + activities.add(activity2); + activities.add(activity3); + } + + @Test + void executeEditName() { + try { + populateActivityList(); + } catch (InvalidTimeFrameException e) { + System.out.println("Invalid time frame."); + } catch (NameTooLongException e) { + Log.makeInfoLog("Activity name longer than 25 characters"); + Ui.printDivider("Error: activity name is longer than 25 characters."); + } + String parameters = "Activity2 /en Activity4"; + Command command = new EditCommand(parameters); + try { + command.executeCommand(activities); + } catch (EmptyNameException | ExtraParametersException e) { + System.out.println("Field error."); + } + + assertEquals(activities.get(1).getName(), "Activity4"); + } + + @Test + void executeEditAllocatedTime() { + try { + populateActivityList(); + } catch (InvalidTimeFrameException e) { + System.out.println("Invalid time frame."); + } catch (NameTooLongException e) { + Log.makeInfoLog("Activity name longer than 25 characters"); + Ui.printDivider("Error: activity name is longer than 25 characters."); + } + String parameters = "Activity2 /ea 10:10:10"; + Command command = new EditCommand(parameters); + try { + command.executeCommand(activities); + } catch (EmptyNameException | ExtraParametersException e) { + System.out.println("Field error."); + } + + assertEquals(activities.get(1).getAllocatedTime(), Duration.parse("PT10H10M10S")); + } +} \ No newline at end of file diff --git a/src/test/java/jikan/command/GoalCommandTest.java b/src/test/java/jikan/command/GoalCommandTest.java new file mode 100644 index 000000000..70f6e0b42 --- /dev/null +++ b/src/test/java/jikan/command/GoalCommandTest.java @@ -0,0 +1,115 @@ +package jikan.command; + +import jikan.activity.Activity; +import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; +import jikan.exception.ExtraParametersException; +import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; +import jikan.log.Log; +import jikan.storage.Storage; +import jikan.storage.StorageHandler; +import jikan.ui.Ui; +import org.junit.jupiter.api.Test; + +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.IOException; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.HashSet; +import java.util.Scanner; + +import static org.junit.jupiter.api.Assertions.*; + +class GoalCommandTest { + Storage storage = new Storage("data/activityList_test.txt"); + ActivityList activities = new ActivityList(storage); + HashSet tags = new HashSet<>(); + Storage tagStorage = new Storage("data/tag_test.txt"); + private static final String TAG_TEST_FILEPATH = "data/tag_test.txt"; + StorageHandler tagStorageHandler = new StorageHandler(tagStorage); + Scanner scanner; + + void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { + try { + activities.storage.clearFile(); + } catch (FileNotFoundException e) { + System.out.println("Could not find file."); + } + tags.add("tag1"); + tags.add("tag2"); + LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); + LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); + Duration duration = Duration.between(startTime, endTime); + Duration allocatedTime = Duration.parse("PT0S"); + Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags, allocatedTime); + Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags, allocatedTime); + Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags, allocatedTime); + activities.add(activity1); + activities.add(activity2); + activities.add(activity3); + } + + /** + * Check that tag exists in the tag list. + * @param tagName the tag name. + * @return index the index of the tag in the tag list. + * @throws IOException when there is an error loading/creating the file. + */ + public static int checkIfExists(String tagName, String filePath) throws IOException { + BufferedReader br = new BufferedReader(new FileReader(filePath)); + int index = 0; + int status = 0; + try { + StringBuilder sb = new StringBuilder(); + String line = br.readLine(); + String[] name; + while (line != null) { + name = line.split(","); + if (name[0].equals(tagName)) { + status = 1; + break; + } + sb.append(line); + sb.append("\n"); + line = br.readLine(); + index++; + } + } finally { + br.close(); + } + if (status == 0) { + index = -1; + } + return index; + } + + @Test + void executeGoal() throws IOException { + try { + populateActivityList(); + } catch (InvalidTimeFrameException e) { + System.out.println("Invalid time frame."); + } catch (NameTooLongException e) { + Log.makeInfoLog("Activity name longer than 25 characters"); + Ui.printDivider("Error: activity name is longer than 25 characters."); + } + String parameters = "tag1 /g 10:10:10"; + String tagName = "tag1"; + boolean found = false; + Command command = new GoalCommand(parameters, scanner, tagStorage); + try { + command.executeCommand(activities); + if (checkIfExists(tagName, TAG_TEST_FILEPATH) != -1) { + found = true; + } else { + found = false; + } + assertTrue(found); + } catch (EmptyNameException | ExtraParametersException e) { + System.out.println("Field error."); + } + } +} \ No newline at end of file From 6c468002bbf9424586143073c7bd863d21756cd6 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Fri, 10 Apr 2020 18:40:50 +0800 Subject: [PATCH 323/415] Add JUnit Tests for Edit and Goal commands --- src/test/java/jikan/command/EditCommandTest.java | 2 +- src/test/java/jikan/command/GoalCommandTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/jikan/command/EditCommandTest.java b/src/test/java/jikan/command/EditCommandTest.java index 17e0d3a75..89bbd161e 100644 --- a/src/test/java/jikan/command/EditCommandTest.java +++ b/src/test/java/jikan/command/EditCommandTest.java @@ -16,7 +16,7 @@ import java.time.LocalDateTime; import java.util.HashSet; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class EditCommandTest { diff --git a/src/test/java/jikan/command/GoalCommandTest.java b/src/test/java/jikan/command/GoalCommandTest.java index 70f6e0b42..7469dad93 100644 --- a/src/test/java/jikan/command/GoalCommandTest.java +++ b/src/test/java/jikan/command/GoalCommandTest.java @@ -21,7 +21,7 @@ import java.util.HashSet; import java.util.Scanner; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertTrue; class GoalCommandTest { Storage storage = new Storage("data/activityList_test.txt"); From 99110ca26d450b89dfddb95046d49e36c636daa7 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 18:50:41 +0800 Subject: [PATCH 324/415] Add junit for graph --- src/main/java/jikan/command/GraphCommand.java | 1 - .../InvalidGraphCommandException.java | 4 - src/main/java/jikan/parser/Parser.java | 2 +- .../java/jikan/command/GraphCommandTest.java | 91 +++++++++++++++++++ 4 files changed, 92 insertions(+), 6 deletions(-) delete mode 100644 src/main/java/jikan/exception/InvalidGraphCommandException.java create mode 100644 src/test/java/jikan/command/GraphCommandTest.java diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index 9d1cffc94..b7cf6dccc 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -3,7 +3,6 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; import jikan.exception.ExtraParametersException; -import jikan.exception.InvalidGraphCommandException; import jikan.exception.MissingParametersException; import jikan.ui.Ui; diff --git a/src/main/java/jikan/exception/InvalidGraphCommandException.java b/src/main/java/jikan/exception/InvalidGraphCommandException.java deleted file mode 100644 index 1b850581e..000000000 --- a/src/main/java/jikan/exception/InvalidGraphCommandException.java +++ /dev/null @@ -1,4 +0,0 @@ -package jikan.exception; - -public class InvalidGraphCommandException extends Exception { -} diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index e7f2325f6..d0775a965 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -159,7 +159,7 @@ public Command parseUserCommands(Scanner scanner) throws EmptyNameException, } catch (NumberFormatException e) { Ui.printDivider("Please input an integer for the time interval."); } catch (ExtraParametersException e) { - Ui.printDivider("Extra parameters or invalid format detected!"); + Ui.printDivider("Extra parameters or invalid format detected."); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("Please specify whether you want to graph activities / tags / allocations."); } diff --git a/src/test/java/jikan/command/GraphCommandTest.java b/src/test/java/jikan/command/GraphCommandTest.java new file mode 100644 index 000000000..b18432c60 --- /dev/null +++ b/src/test/java/jikan/command/GraphCommandTest.java @@ -0,0 +1,91 @@ +package jikan.command; + +import jikan.activity.Activity; +import jikan.activity.ActivityList; +import jikan.exception.*; +import jikan.storage.Storage; +import jikan.ui.Ui; +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.PrintStream; +import java.time.Duration; +import java.time.LocalDateTime; +import java.util.HashMap; +import java.util.HashSet; + +import static jikan.Jikan.lastShownList; +import static org.junit.jupiter.api.Assertions.*; + +class GraphCommandTest { + ActivityList activities = new ActivityList(); + HashSet tags1 = new HashSet<>(); + HashSet tags2 = new HashSet<>(); + + void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { + activities.storage = new Storage("data/activityList_test.txt"); + activities.activities.clear(); + try { + activities.storage.clearFile(); + } catch (FileNotFoundException e) { + System.out.println("Could not find file."); + } + tags1.add("tag1"); + tags1.add("tag2"); + tags2.add("tag1"); + tags2.add("tag3"); + LocalDateTime startTime = LocalDateTime.parse("2020-01-01T08:00:00"); + LocalDateTime endTime = LocalDateTime.parse("2020-01-01T10:00:00"); + Duration duration = Duration.between(startTime, endTime); + Duration allocatedTime = Duration.parse("PT2H30M"); + Activity activity1 = new Activity("Activity1", startTime, endTime, duration, tags1, allocatedTime); + Activity activity2 = new Activity("Activity2", startTime, endTime, duration, tags1, allocatedTime); + Activity activity3 = new Activity("Activity3", startTime, endTime, duration, tags2, allocatedTime); + activities.add(activity1); + activities.add(activity2); + activities.add(activity3); + } + + @Test + void newCommand() { + ExtraParametersException extraParametersException = assertThrows(ExtraParametersException.class, () -> { + Command command = new GraphCommand("tags 10 extra"); + }); + } + + public void printTest() throws Exception { + ByteArrayOutputStream outContent = new ByteArrayOutputStream(); + System.setOut(new PrintStream(outContent)); + + // After this all System.out.println() statements will come to outContent stream. + + // So, you can normally call, + // print(items); // I will assume items is already initialized properly. + + //Now you have to validate the output. Let's say items had 1 element. + // With name as FirstElement and number as 1. + // String expectedOutput = "Name: FirstElement\nNumber: 1" // Notice the \n for new line. + + // Do the actual assertion. + // assertEquals(expectedOutput, outContent.toString()); + } + + @Test + void extractTags() { + HashMap expected = new HashMap<>(); + expected.put("tag1", Duration.parse("PT6H")); + expected.put("tag2", Duration.parse("PT4H")); + expected.put("tag3", Duration.parse("PT2H")); + try { + populateActivityList(); + HashMap tags = new HashMap<>(); + for (Activity activity : activities.activities) { + GraphCommand.extractTags(tags, activity); + } + assertEquals(expected, tags); + } catch (NameTooLongException | InvalidTimeFrameException e) { + e.printStackTrace(); + } + } +} \ No newline at end of file From d07e9e9c94ddf18c53e48dcde7cfe346dd51c28c Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 18:55:10 +0800 Subject: [PATCH 325/415] Fix stylecheck --- src/test/java/jikan/command/GraphCommandTest.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/java/jikan/command/GraphCommandTest.java b/src/test/java/jikan/command/GraphCommandTest.java index b18432c60..0dacada53 100644 --- a/src/test/java/jikan/command/GraphCommandTest.java +++ b/src/test/java/jikan/command/GraphCommandTest.java @@ -2,9 +2,10 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; -import jikan.exception.*; +import jikan.exception.ExtraParametersException; +import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NameTooLongException; import jikan.storage.Storage; -import jikan.ui.Ui; import org.junit.jupiter.api.Test; import java.io.ByteArrayOutputStream; @@ -16,7 +17,8 @@ import java.util.HashSet; import static jikan.Jikan.lastShownList; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; class GraphCommandTest { ActivityList activities = new ActivityList(); From 6c6cd4cfbee27915814cb276d860ba27bdbf930b Mon Sep 17 00:00:00 2001 From: nigellenl Date: Fri, 10 Apr 2020 20:18:44 +0800 Subject: [PATCH 326/415] Fix goal JUnit test --- src/main/java/jikan/command/GoalCommand.java | 28 ++----------------- .../java/jikan/command/GoalCommandTest.java | 3 ++ 2 files changed, 5 insertions(+), 26 deletions(-) diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index 3931d0884..8422704db 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -13,7 +13,6 @@ import jikan.ui.Ui; import java.io.BufferedReader; -import java.io.FileNotFoundException; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; @@ -83,7 +82,7 @@ public void executeCommand(ActivityList activityList) { if (!existInActivity(activityList, tagName)) { throw new NoSuchTagException(); } else { - addTagLine(tagName + "," + goalTime); + tagStorage.writeToFile(tagName + "," + goalTime); Ui.printDivider("The goal for " + tagName + " has been added."); } } @@ -174,19 +173,6 @@ private static void updateGoal(String userInput, String tagName, Duration goalTi } } - /** - * Updates tag file with new tag. - * - * @param dataLine Line to write to file. - */ - public static void addTagLine(String dataLine) { - try { - tagStorage.writeToFile(dataLine); - } catch (IOException e) { - System.out.println("Error saving tag to tag file."); - } - } - /** * Removes the line whose index matches lineNumber from file. * @@ -208,7 +194,7 @@ public static void deleteLine(int lineNumber) throws IOException { * @throws IOException If an error occurs while writing the new list to file. */ public static void saveNewTags(List newList) throws IOException { - clearFile(); + tagStorage.clearFile(); FileWriter fw = new FileWriter(TAG_FILE_PATH, true); for (String s : newList) { @@ -217,16 +203,6 @@ public static void saveNewTags(List newList) throws IOException { fw.close(); } - /** - * Clears the data file. - * @throws FileNotFoundException If file is not found. - */ - public static void clearFile() throws IOException { - FileWriter fw = new FileWriter(TAG_FILE_PATH, false); - fw.write(""); - fw.close(); - } - /** * Check if the tag exists in the activity list. * @param targetList the activity list to check. diff --git a/src/test/java/jikan/command/GoalCommandTest.java b/src/test/java/jikan/command/GoalCommandTest.java index 7469dad93..a010172bd 100644 --- a/src/test/java/jikan/command/GoalCommandTest.java +++ b/src/test/java/jikan/command/GoalCommandTest.java @@ -90,6 +90,8 @@ public static int checkIfExists(String tagName, String filePath) throws IOExcept void executeGoal() throws IOException { try { populateActivityList(); + tagStorage.loadFile(); + assertTrue(tagStorage.dataFile.exists()); } catch (InvalidTimeFrameException e) { System.out.println("Invalid time frame."); } catch (NameTooLongException e) { @@ -107,6 +109,7 @@ void executeGoal() throws IOException { } else { found = false; } + tagStorage.dataFile.delete(); assertTrue(found); } catch (EmptyNameException | ExtraParametersException e) { System.out.println("Field error."); From 49856c9b4b9e0a4d298ce66369ccff9ca82f9432 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Fri, 10 Apr 2020 20:21:24 +0800 Subject: [PATCH 327/415] Fix goal JUnit test --- src/test/java/jikan/command/GoalCommandTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/jikan/command/GoalCommandTest.java b/src/test/java/jikan/command/GoalCommandTest.java index a010172bd..1fe81f472 100644 --- a/src/test/java/jikan/command/GoalCommandTest.java +++ b/src/test/java/jikan/command/GoalCommandTest.java @@ -109,8 +109,8 @@ void executeGoal() throws IOException { } else { found = false; } - tagStorage.dataFile.delete(); assertTrue(found); + tagStorage.dataFile.delete(); } catch (EmptyNameException | ExtraParametersException e) { System.out.println("Field error."); } From ee08e4ef94cc95f5749f977bde7c6eb4beb307e1 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Fri, 10 Apr 2020 20:32:00 +0800 Subject: [PATCH 328/415] Try to fix JUnit test for goal command --- src/test/java/jikan/command/GoalCommandTest.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/test/java/jikan/command/GoalCommandTest.java b/src/test/java/jikan/command/GoalCommandTest.java index 1fe81f472..f6274ca5f 100644 --- a/src/test/java/jikan/command/GoalCommandTest.java +++ b/src/test/java/jikan/command/GoalCommandTest.java @@ -8,7 +8,6 @@ import jikan.exception.NameTooLongException; import jikan.log.Log; import jikan.storage.Storage; -import jikan.storage.StorageHandler; import jikan.ui.Ui; import org.junit.jupiter.api.Test; @@ -27,9 +26,6 @@ class GoalCommandTest { Storage storage = new Storage("data/activityList_test.txt"); ActivityList activities = new ActivityList(storage); HashSet tags = new HashSet<>(); - Storage tagStorage = new Storage("data/tag_test.txt"); - private static final String TAG_TEST_FILEPATH = "data/tag_test.txt"; - StorageHandler tagStorageHandler = new StorageHandler(tagStorage); Scanner scanner; void populateActivityList() throws InvalidTimeFrameException, NameTooLongException { @@ -88,10 +84,12 @@ public static int checkIfExists(String tagName, String filePath) throws IOExcept @Test void executeGoal() throws IOException { + Storage tagStorage = new Storage("data/tag_test.txt"); + String TAG_TEST_FILEPATH = "data/tag_test.txt"; + tagStorage.loadFile(); + assertTrue(tagStorage.dataFile.exists()); try { populateActivityList(); - tagStorage.loadFile(); - assertTrue(tagStorage.dataFile.exists()); } catch (InvalidTimeFrameException e) { System.out.println("Invalid time frame."); } catch (NameTooLongException e) { @@ -110,9 +108,9 @@ void executeGoal() throws IOException { found = false; } assertTrue(found); - tagStorage.dataFile.delete(); } catch (EmptyNameException | ExtraParametersException e) { System.out.println("Field error."); } + tagStorage.dataFile.delete(); } } \ No newline at end of file From 2dcad0d9eb2e876365bc15df9c537689d417cecc Mon Sep 17 00:00:00 2001 From: nigellenl Date: Fri, 10 Apr 2020 20:35:46 +0800 Subject: [PATCH 329/415] Fix style issue --- src/test/java/jikan/command/GoalCommandTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/jikan/command/GoalCommandTest.java b/src/test/java/jikan/command/GoalCommandTest.java index f6274ca5f..0dff53eeb 100644 --- a/src/test/java/jikan/command/GoalCommandTest.java +++ b/src/test/java/jikan/command/GoalCommandTest.java @@ -85,7 +85,7 @@ public static int checkIfExists(String tagName, String filePath) throws IOExcept @Test void executeGoal() throws IOException { Storage tagStorage = new Storage("data/tag_test.txt"); - String TAG_TEST_FILEPATH = "data/tag_test.txt"; + String testFile = "data/tag_test.txt"; tagStorage.loadFile(); assertTrue(tagStorage.dataFile.exists()); try { @@ -102,7 +102,7 @@ void executeGoal() throws IOException { Command command = new GoalCommand(parameters, scanner, tagStorage); try { command.executeCommand(activities); - if (checkIfExists(tagName, TAG_TEST_FILEPATH) != -1) { + if (checkIfExists(tagName, testFile) != -1) { found = true; } else { found = false; From a5042e48fcc13654b4276d62e50685cfe90f4ae9 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Fri, 10 Apr 2020 20:42:18 +0800 Subject: [PATCH 330/415] Fix goal JUnit test again --- src/test/java/jikan/command/GoalCommandTest.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/test/java/jikan/command/GoalCommandTest.java b/src/test/java/jikan/command/GoalCommandTest.java index 0dff53eeb..27bf13194 100644 --- a/src/test/java/jikan/command/GoalCommandTest.java +++ b/src/test/java/jikan/command/GoalCommandTest.java @@ -84,10 +84,6 @@ public static int checkIfExists(String tagName, String filePath) throws IOExcept @Test void executeGoal() throws IOException { - Storage tagStorage = new Storage("data/tag_test.txt"); - String testFile = "data/tag_test.txt"; - tagStorage.loadFile(); - assertTrue(tagStorage.dataFile.exists()); try { populateActivityList(); } catch (InvalidTimeFrameException e) { @@ -98,15 +94,17 @@ void executeGoal() throws IOException { } String parameters = "tag1 /g 10:10:10"; String tagName = "tag1"; + Storage tagStorage = new Storage("data/tag_test.txt"); + String testFile = "data/tag_test.txt"; + tagStorage.loadFile(); + assertTrue(tagStorage.dataFile.exists()); boolean found = false; Command command = new GoalCommand(parameters, scanner, tagStorage); try { command.executeCommand(activities); if (checkIfExists(tagName, testFile) != -1) { found = true; - } else { - found = false; - } + } assertTrue(found); } catch (EmptyNameException | ExtraParametersException e) { System.out.println("Field error."); From 33942f90a71429efe6eaea67de1c6fab3971aec4 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Fri, 10 Apr 2020 20:53:07 +0800 Subject: [PATCH 331/415] Try to fix goal JUnit test --- src/main/java/jikan/command/GoalCommand.java | 1 + .../java/jikan/command/GoalCommandTest.java | 47 ++++--------------- 2 files changed, 10 insertions(+), 38 deletions(-) diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index 8422704db..7eb2d3436 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -123,6 +123,7 @@ public void executeCommand(ActivityList activityList) { /** * Check that tag exists in the tag list. * @param tagName the tag name. + * @param filePath the file path of the tag file. * @return index the index of the tag in the tag list. * @throws IOException when there is an error loading/creating the file. */ diff --git a/src/test/java/jikan/command/GoalCommandTest.java b/src/test/java/jikan/command/GoalCommandTest.java index 27bf13194..1af4368e7 100644 --- a/src/test/java/jikan/command/GoalCommandTest.java +++ b/src/test/java/jikan/command/GoalCommandTest.java @@ -20,6 +20,7 @@ import java.util.HashSet; import java.util.Scanner; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; class GoalCommandTest { @@ -48,40 +49,6 @@ void populateActivityList() throws InvalidTimeFrameException, NameTooLongExcepti activities.add(activity3); } - /** - * Check that tag exists in the tag list. - * @param tagName the tag name. - * @return index the index of the tag in the tag list. - * @throws IOException when there is an error loading/creating the file. - */ - public static int checkIfExists(String tagName, String filePath) throws IOException { - BufferedReader br = new BufferedReader(new FileReader(filePath)); - int index = 0; - int status = 0; - try { - StringBuilder sb = new StringBuilder(); - String line = br.readLine(); - String[] name; - while (line != null) { - name = line.split(","); - if (name[0].equals(tagName)) { - status = 1; - break; - } - sb.append(line); - sb.append("\n"); - line = br.readLine(); - index++; - } - } finally { - br.close(); - } - if (status == 0) { - index = -1; - } - return index; - } - @Test void executeGoal() throws IOException { try { @@ -102,13 +69,17 @@ void executeGoal() throws IOException { Command command = new GoalCommand(parameters, scanner, tagStorage); try { command.executeCommand(activities); - if (checkIfExists(tagName, testFile) != -1) { + if (GoalCommand.checkIfExists(tagName, testFile) == -1) { + found = false; + assertFalse(found); + tagStorage.dataFile.delete(); + } else { found = true; - } - assertTrue(found); + assertTrue(found); + tagStorage.dataFile.delete(); + } } catch (EmptyNameException | ExtraParametersException e) { System.out.println("Field error."); } - tagStorage.dataFile.delete(); } } \ No newline at end of file From 7cd3c0027c105c7d9a696c1a2163c917794a7294 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Fri, 10 Apr 2020 21:33:38 +0800 Subject: [PATCH 332/415] Create new section in DG for start feature --- docs/DeveloperGuide.md | 186 +++++++++++++----- docs/pictures/StartCD.png | Bin 0 -> 13201 bytes docs/pictures/checkActivity.png | Bin 0 -> 52833 bytes docs/pictures/checkTimev2.png | Bin 0 -> 57597 bytes docs/pictures/checkactivityv2.png | Bin 0 -> 45894 bytes docs/pictures/checktime.png | Bin 0 -> 66582 bytes docs/pictures/continueActivity.png | Bin 0 -> 26649 bytes src/main/java/jikan/command/StartCommand.java | 6 + 8 files changed, 147 insertions(+), 45 deletions(-) create mode 100644 docs/pictures/StartCD.png create mode 100644 docs/pictures/checkActivity.png create mode 100644 docs/pictures/checkTimev2.png create mode 100644 docs/pictures/checkactivityv2.png create mode 100644 docs/pictures/checktime.png create mode 100644 docs/pictures/continueActivity.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index f6435ce09..a951679bb 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -3,28 +3,30 @@ - [1. Setting Up](#1-setting-up) - [2. Design](#2-design) - [3. Implementation](#3-implementation) - - [3.1 Automated Storage Cleanup feature](#31-automated-storage-cleanup-feature) - - [3.1.1 Current Implementation](#311-current-implementation) - - [initialiseCleaner](#initialisecleaner) - - [setStatus](#setstatus) - - [autoClean](#autoclean) - - [3.1.2 Additional Implementation (proposed)](#312-additional-implementation-proposed) - - [3.2 Storage feature](#32-storage-feature) - - [3.3 Storage handler](#33-storage-handler) - - [3.4 Edit feature](#34-edit-feature) - - [3.4.1 Current Implementation](#341-current-implementation) - - [3.4.2 Additional Implementations](#342-additional-implementations) - - [3.4.3 Design Considerations](#343-design-considerations) - - [3.5 Continue Feature](#35-continue-feature) - - [3.5.1 Current Implementation](#351-current-implementation) - - [3.5.2 Design Considerations](#352-design-considerations) - - [3.5.3 Additional Features](#353-additional-features) - - [3.5 List feature](#35-list-feature) - - [3.5.1 Current implementation](#351-current-implementation-1) - - [3.6 Find Feature](#36-find-feature) - - [3.6.1 Current Implementation](#361-current-implementation) - - [3.7 Filter Feature](#37-filter-feature) - - [3.7.1 Current Implementation](#371-current-implementation) + - [3.1 Start Feature]() + - [3.1.1 Current Implementation]() + - [3.1.2 Additional Implementation]() + - [3.1.3 Design Considerations]() + - [3.2 Clean Feature](#31-automated-storage-cleanup-feature) + - [3.2.1 Current Implementation](#311-current-implementation) + - [3.2.2 Additional Implementation]() + - [3.2.3 Design Considerations]() + - [3.3 Storage feature](#32-storage-feature) + - [3.4 Storage handler](#33-storage-handler) + - [3.5 Edit feature](#34-edit-feature) + - [3.5.1 Current Implementation](#341-current-implementation) + - [3.5.2 Additional Implementations](#342-additional-implementations) + - [3.5.3 Design Considerations](#343-design-considerations) + - [3.6 Continue Feature](#35-continue-feature) + - [3.6.1 Current Implementation](#351-current-implementation) + - [3.6.2 Design Considerations](#352-design-considerations) + - [3.6.3 Additional Features](#353-additional-features) + - [3.7 List feature](#35-list-feature) + - [3.7.1 Current implementation](#351-current-implementation-1) + - [3.8 Find Feature](#36-find-feature) + - [3.8.1 Current Implementation](#361-current-implementation) + - [3.9 Filter Feature](#37-filter-feature) + - [3.9.1 Current Implementation](#371-current-implementation) - [4. Appendix](#4-appendix) - [Product Scope](#product-scope) - [Target user profile](#target-user-profile) @@ -67,10 +69,102 @@ _Fig 2.1. Class diagram of the Jikan program_ This section describes some noteworthy details on how certain features are implemented. -### 3.1 Automated Storage Cleanup feature +### 3.1 Start Feature #### 3.1.1 Current Implementation +![StartCD](./pictures/StartCD.png) + +With Jikan as the main entry point for our application, + +1. Jikan will receive user input and pass it to the Parser class to get the corresponding command. +2. The Parser class will initialise and return a Command class object based on the command in user input. +3. In this case, Parser will return a StartCommand class object to Jikan. +4. Then, Jikan will call the StartCommand#executeCommand method to start an activity. + +Additionally, StartCommand also implements the following operations: + +* **StartCommand#checkActivity** Checks if the activity already exists in the activity list. +* **StartCommand#checkTime** Checks if the allocated time provided is valid. +* **StartCommand#continueActivity** Continue on an existing activity. + +**checkActivity** + +![checkActivity](./pictures/checkactivityv2.png) + +The diagram above shows how the StartCommand#checkActivity function works. This function is used to check +if the activity to be started exists in the activity list. If the activity exists in the list, that activity will be +continued and this way the user cannot start duplicate activities. + +1. When checkActivity() is called, it will make a call to the ActivityList#findActivity method. +2. Once the findActivity() method finishes execution, it will return an integer index back to checkActivity(). +3. If the index is not equals to -1, the activity to be started exists in the activity list and continueActivity() will be called. +4. Else, the activity to be started is a brand new activity and addActivityToList() will be called. + +**checkTime** + +![checkTime](./pictures/checkTimev2.png) + +The diagram above shows how the StartCommand#checkTime function works. This function is used to check the validity of +the allocated time provided by the user input. If the allocated time is valid, the activity will be added to activity +list. + +1. When checkTime() is called, it will initialise two LocalTime objects called endTime and startTime respectively. +2. startTime will be initialised to time 00:00:00 while endTime will be calculated based on the user input to the start +command (i.e `start activity name /a HH:MM:SS /t tags`) +3. Then, the method Duration.between() will be used to get a Duration object that holds the time difference between startTime +and endTime. +4. If this Duration object is non zero (i.e user gave a valid non zero allocated time), then the activity will be added to the activity list +using the addActivity() method. + +**continueActivity** + +![continueActivity](./pictures/continueActivity.png) + +The diagram above shows how the StartCommand#continueActivity function works. This function is used when the current activity +to be started already exists in the activity list. Thus, this function will check with the user whether to continue on that activity +and prevent duplicate activities from being started. + +1. When continueActivity() is called, it will make a call to the Scanner object to read in the next line of user input. +2. If the user input is "yes", information about the activity (activity name, tags etc.) will be forwarded to parser and the parser +will update the activity list (i.e when continue is used, activity duration is added on and needs to be updated). +3. Else, if the user input is "no", continueActivity() will notify the parser to read in the next line of user input. + +#### 3.1.2 Additional Implementation + +1. `start` command have the ability to continue an activity if the activity to be started exists in activity list as discussed above. However, the second +start command's tags and allocated time parameters will not be captured if the activity originally did have tags or allocated time. + * `start activity 1` + * `start activity 1 /a HH:MM:SS /t tags` (this command will continue activity 1 but won't add the tags and allocated time to it) + + Thus, it would be best for `start` command to address this issue and allow the second `start` command to not only continue the +activity but also edit the fields of the activity. + +2. Allows two activities to start at the same time. As a user, sometimes the activity we are doing may be linked to another activity (i.e activities like +revising CS2106 and doing CS2106 Labs are similar as doing the labs can serve like a revision too). + + Thus, it would be good if more than one activity can be started at a particular time. + +#### 3.1.3 Design Considerations + +The current design is centred around the Parser Class as all the relevant activity information (activity startTime, endTime, name, tags, +allocated time) are stored inside Parser. + +Since Parser is a public class. There are some benefits to this design. +* All the command classes have access to activity information. +* Makes the classes more lightweight as there is no need for local variables to store activity informations. +* Reduces coupling between the commands as they interact through Parser. + +However, there are some drawbacks to this design too. +* Since all the activity information are public, every class in Jikan can access/modify activity information which is +undesirable. +* This creates a lot of dependencies between Commands and Parser which makes unit testing harder to implement. +* As more commands is created to accommodate new features , Parser will be overloaded with new variables and classes. + +### 3.2 Clean Feature + +#### 3.2.1 Current Implementation + The storage cleanup mechanism is stored internally as a StorageCleaner class. The StorageCleaner class has an association with the Storage class and thus it is able to access and edit the datafile which contains the list of activities. Additionally, when the StorageCleaner class is first initialised, it will create two files, namely a status file and a data file in the “recycled” folder under the “data” folder. The status file keeps track of the activation status of the storage cleaner while the data file serves as a recycle bin for deleted data. @@ -113,7 +207,7 @@ Step 2b. If the attribute `toClean` is equal to `true`, access the storage data ![image_info](./pictures/SDautoClean.png) -#### 3.1.2 Additional Implementation (proposed) +#### 3.2.2 Additional Implementation `StorageCleaner#setDeleteQuota - Allows the user to manipulate how much activity is deleted when auto cleanup is activated. Currently only delete the oldest 3 activities.` @@ -121,8 +215,9 @@ Step 2b. If the attribute `toClean` is equal to `true`, access the storage data `StorageCleaner#initialiseLogCleaner - Gives the storage cleaner an added functionality of being able to clear log files too.` +#### 3.2.3 Design Considerations -### 3.2 Storage feature +### 3.3 Storage feature The Storage class represents the back-end of Jikan, handling the creation, saving and loading of data. Jikan uses a `.csv` file to store its data, formatted in the following way: @@ -139,15 +234,15 @@ Storage provides the following functions: Loading a pre-existing data file via `loadFile`. If a data file already exists for the provided data file path, the function will return `true`; if the specified data file did not previously exist, this function will call the `createDataFile` method and returns `false`. The return value is useful so that the application knows whether or not this is the first session with a specific data file or if data already exists. - Creating an ActivityList via `createActivityList`. This function calls `loadFile()` to check whether the file already existed or not; if the data file previously existed, it will construct an ActivityList object by passing the data from the data file to it, and return this populated ActivityList object; if the data file did not previously exist, it will return an empty activityList object. -### 3.3 Storage handler +### 3.4 Storage handler The StorageHandler class functions as a support to the main Storage class, allowing the Jikan application to manipulate the stored data file. Its main provided functions are: - Removing an entry from the data file via `removeLine`. This function takes in the number of the line to remove. - Replacing an entry in the data file via `replaceLine`. This function takes in the number of the line to replace, along with the String object that needs to be written to the data file in place of the replaced line. -### 3.4 Edit feature +### 3.5 Edit feature The edit feature allows the user to make changes to activities that have been saved in the activity list. This is to allow the user to rectify any mistakes that may have been made during the initial recording of the activity. -#### 3.4.1 Current Implementation +#### 3.5.1 Current Implementation The following sequence diagram shows how the edit feature works. ![image_info](./pictures/EditSequenceDiagram.png) The current implementation of the edit feature allows the user to edit only the name parameter of the activity. When the user wants to edit an activity using the edit command, the Parser creates a new EditCommand object. The `executeCommand()` method of the EditCommand object is called and the specified parameters are updated accordingly. @@ -158,20 +253,20 @@ The order of method calls to edit the activity details is as follows if the spec 3. The `setName()` method of the Activity class is called to edit the activity name to the user-specified name 4. The activity with the updated name is returned to the activityList -#### 3.4.2 Additional Implementations +#### 3.5.2 Additional Implementations The current implementation of the edit feature only allows the user to edit the activity name. Hence, additional implementations of the edit feature should allow the user to edit other parameters of the activity such as the tags and the start and end dates. This will require the implementation of more update methods in the ActivityList class to allow for the changes to be updated in the activityList after it has been edited. -#### 3.4.3 Design Considerations +#### 3.5.3 Design Considerations By letting the user edit the name and tags of the activity, it will allow them to correct any mistakes made during the data entry. This ensures that there is an accurate record of activities such as in cases where the user may be trying to record the same activity but has misspelled it, resulting in the program regarding it as a different activity where there would be multiple unnecessary new entries in the activity list, making the analysis of the time spent more tedious and inaccurate. However, by allowing the user to edit the start date and time, there may be potential inaccuracies in the actual activity recording. This is due to the fact that the time recorded in the program is based on the LocalDateTime. By introducing user input, the dates and time may be recorded incorrectly, defeating the purpose of the time tracking program. -### 3.5 Continue Feature +### 3.6 Continue Feature The continue feature allows the user to continue a previously ended activity. -#### 3.5.1 Current Implementation +#### 3.6.1 Current Implementation ![Continue command sequence diagram](./pictures/continue.png) **Continuing an activity:** @@ -189,7 +284,7 @@ The continue feature allows the user to continue a previously ended activity. * The elapsed time is added with the previous duration of the activity to get the `newDuration` using the `plus()` method of Duration class. * `updateDuration()` method is called to update the `duration` attribute of the continued activity in the `activityList` as well as the `data.csv` file. -#### 3.5.2 Design Considerations +#### 3.6.2 Design Considerations **Execution:** * Continue by activity name (current implementation) @@ -202,11 +297,11 @@ The continue feature allows the user to continue a previously ended activity. Although the current implementation of the continue feature disallows users to have multiple activities with the same name, we felt that the versatility of this choice outweighed the cons. Firstly because if the activityList got too big, it would be hard for the user to get the index of the task they wanted to continue. Also, the index would constantly be changing when changes are made to the list. -#### 3.5.3 Additional Features +#### 3.6.3 Additional Features As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, they will be given the option to continue the stated activity. ![decision flowchart](./pictures/continue_flowchart.PNG) -### 3.6 List feature +### 3.7 List feature This feature is used to list activities within a range specified by the user. If no parameter is passed to the `list` command, then all the stored activities will be displayed. By passing a single date, the command returns all activities within that date. @@ -217,7 +312,7 @@ will return all the activities for that day, week or month respectively. Additionally, the user can specify a specific week of month by including a date (e.g. `list month 2020-03-01` returns all the activities in March 2020.) -#### 3.6.1 Current implementation +#### 3.7.1 Current implementation * List all activities: `list` * List today's activities: `list day` or `list daily` * List this week's activities: `list week` or `list weekly` @@ -230,10 +325,10 @@ Additionally, the user can specify a specific week of month by including a date * List activities within a time frame: `list DATE1 DATE2`, where both `DATE1` and `DATE2` are in either `yyyy-MM-dd` or `dd/MM/yyyy` format -### 3.7 Find Feature +### 3.8 Find Feature This command accepts a keyword and searches the activity list for activities with names that contain the keyword. -#### 3.7.1 Current Implementation +#### 3.8.1 Current Implementation * This feature is called by the user when the `find` command is entered into the command line. The string following the command is the keyword to match activity names to. * The Parser will create a FindCommand object. * The FindCommand will invoke its own `executeCommand()` method. @@ -247,10 +342,10 @@ This command accepts a keyword and searches the activity list for activities wit ![find seq diagram](https://imgur.com/Icg5rdB.png) -### 3.8 Filter Feature +### 3.9 Filter Feature This feature accepts multiple space-separated keywords to search for activities with tags matching each keyword. -#### 3.8.1 Current Implementation +#### 3.9.1 Current Implementation * This feature is called by the user when the `filter` command is entered into the command line. The space separated strings following the command are the keywords to match activity tags with. * The Parser will create a FilterCommand object. * The FindCommand will invoke its own `executeCommand()` method. @@ -264,17 +359,17 @@ This feature accepts multiple space-separated keywords to search for activities ![filter seq diagram](https://imgur.com/hybT3R9.png) -### 3.9 Graph Feature +### 3.10 Graph Feature This feature gives the user a visual representation of their activity duration and activity goals. Graph can be used along with `list`, `find` and `filter` to sieve out the data to be graphed. -#### 3.9.1 Current Implementation +#### 3.10.1 Current Implementation ![graph seq diagram](./pictures/graph.png) * This feature is called by the user when the `graph` command is entered into the command line. The user will then have to specify what he would like to graph (goals progress bar / tag duration / activity duration). * The Parser will create a GraphCommand object. * The GraphCommand will invoke its own `executeCommand()` method. -**Graph targets** +**Graph allocations** This displays the progress bar for the duration with respect to allocated time of activities in the `lastShownList`. * If the user indicated `targets`, Ui calss will be called to execute graphTargets. @@ -292,7 +387,7 @@ This displays a bar graph of the durations of each activity in the `lastShownLis * If the user indicated `activities`, `GraphCommand` will call it's own `graphDuration` method. * `graphDuration` calls `printActivityGraph` of the Ui class and passes the `interval` parameter, which is how many minutes each point in the graph represents. -#### 3.9.2 Additional features +#### 3.10.2 Additional features As graph gets it's data based on the `lastShownList`, users can pair the `graph` command with `find`, `filter`, and `list` to sieve out the activities to be graphed. @@ -300,7 +395,8 @@ As graph gets it's data based on the `lastShownList`, users can pair the `graph` ### Product Scope #### Target user profile -* Students with time management issues/poor time management skills. +* University students with poor time management skills who are struggling to allocate time efficiently for + the numerous deadlines/tasks. * Users who are reasonably comfortable using CLI apps. #### Value proposition diff --git a/docs/pictures/StartCD.png b/docs/pictures/StartCD.png new file mode 100644 index 0000000000000000000000000000000000000000..97539d709386ad9683a5f28ff5a338425f4def62 GIT binary patch literal 13201 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 literal 0 HcmV?d00001 diff --git a/docs/pictures/checkActivity.png b/docs/pictures/checkActivity.png new file mode 100644 index 0000000000000000000000000000000000000000..3f08eec99d44417f4cff13ea04950480db8fd0d6 GIT binary patch literal 52833 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 z z)l|IFA-K&UL(nY7@4>RaL>MZFO_}Dfz=F7zhJJnT|+8`3CL&AlQ%4T z=$G1SuMCt%1f|+f`0%nW*mz8e?vN0SmAPH-(|G+NQbdqK5WutPzqsP)q2wn^UZoW1 z&x62x%RrgTXw`D%b|qCOga`R>NY2BDr{ootV{EDM^wCoRZ8P;XCSx{!kO+Rjt1bDK z5E3jb%u9TE8d1kU?(nW6&KFEnOEcYH;-LO4l zLkMr@f3gy(_BBvpYNVL!5G&u6*`k7Pc~mYP(=mrY8#!?zNz<4Ai;UdRLbtlRa*qF^ zVR^Jhd_;=}16uZXs6I4S;mZVdJ=d;ad!g5olyQBc;lQ6 zE-n;AZW2#^LN+JqE8lJ}M@uM=wwuTsRvZZBiN10jS0!r&7x>GdA3t(Ig~pbK9+T;r zXsn6X3Yel*{5)7drVp=nHPy&2sw~jYQ?J6}PnDYyX`@G8q87krBir<4ryG4jM}2w6&$eADz`(NsZgsAZ)nhs2l=Aag15P`Td z5L$^g5WUSCf3@{tdp4f--K)K*uHwp!7Qf{vh*5Aa^#D<7BvF0=JU43@3rF!^W`#`6 z&IbJHKD&JzJZI2kz`<+F%<-?WZKYJw1 z?h%Yi{m@Eb-IyryN{e!chMQ}Sxa;DtqB(X^qf?El<*2F4ut)K|%5ndE(B+!_on%0L zUf+)N{E!~;hhh0KL!v|efqxvQ~&6ojt_}3%IC1hlqGbhYGQ`&; zEM8%(6U*JjWN2gGVnnp~DZO;6ZxQKn=v>gL)QalIGQSoY!J{}5&TO%K_K=JWcr{QEt4RSzk$SfH+Jr}$3F4NQ%aV1os zyU=ddGvicMK*YMqaEMEO`H%-u6SvSqRn)TWVmju*f(#LIKQOfb&A13VY&1I%pQo)c;la7qarQ(X7q64klod2h%Xp#=pVnk zDloH@RREHvup~o7vzLlUlZm+5?wVilvQ|;bObC54%tOOqX&ef(ya<#fd+N@ zw9u`~!!0GNsR5!Jl9G`$HBbP4)9PW)!*lAF!&U3l!#Rl@y7Q#g9E8usxqe2f-)->x zsil&B7843Aad=! z8!ae{Vio zb3&j_V+hQ~fHLV6imDT__EALQUVU(K%gsHze~PBTIZ;Pr7S_7O$I+pbEUG_g5jh%Y zfXW@latxPD&F~k0n%sn*Bx!$qv~8l9<@5!Ns8RFhfwS1i$qO4(7zUHLM0~wX*CbCq zbcU)h3NYeLKrPdi1&?S~GDLVm=c@kn^|Z!!fX%*)cgWBjyU z2KUs`ushEDYSR%-5B%D*mF7O0GQn097EIdMAv}AD>D7jBxN6|@d{+w~n;pt6HX@$! z(_UN=(zzjlpFTY&rGDwE*7reVj?*{MVkre%rz#Sr4i@`|ZG@ZBS$mOE3)ie@H>=9f z2%`iefn%hSu6WpO!*DQMs>IIEL-Kj_LbizpE8fM1B5(V$-YIZ2WbA;9U*WF)J?Gl!#RS-DA+Ka=>Dwy%J%wiW8M530?SibB= z;xBEv9kNTXqG*{L;LUA_)i<+nbx<_*q)D@1L8^e|p-R&7R&bIR4Y{U#s&U zc>D(){uiKzOnDC%gv?$z6Zr{ITvM%+={zoGucrqHpAF?WjqmE+8P7mp)C0V`ktg2V zU#;jkKDO;NPT+S|JJml3-H&Y7lXG!IE8cX(vOIvVWCqt|j`@82=(yF6avYb1!HAAQ$)wSbYs}%)p5Ues(1RG3uKe%_ou5j%482I*ESs`?VVxTW0KnEgT0M911vw%RoDgKc?;s0Zt3% z_wGD!mQP!9+^T^K{s4&#Ds19~g=u#eQhpt_apEoIBt0G3nCGLa6?nTlLS}W3uj}s) z9H9V{vfc_i9E%KCKl}c1J_R01yg8BFHnc92SF6IPs)m~kr)x?&5X(ce&RdBnFJXZV zrRxVY9a5Gw2P7v{P?hvG1#49uKbNt#8CiX#S~DS62!eNE zEfy0CI+!GLy$aTbUzeGZB$&+{)_hkNi;)3L?K8L_l786BFuf`F+#4a!YjJ+D+Fgb7 zzYYhBsw`aV5iFuGz^&_zt>?eL=cPzHciiJ{<$}0WC9pe&e#S-hzb-l!BLW?DZh6G#Qoboaj0Qc zqUx$?lXgylGp76=prie4b4Aly^R3+bwP0r0X9!p?SJv z6YspN$m7ow;8j86yiMfzIGzS7c(0R*z03c_pTNPZJGZBE$C>=i`{4v+?zj7YmEQD` zwNd)@_h2)lZCaVX)&`#>{j`K^y@)HYy~DC#U1!;{MhFUb-83}1d<sIIApY04%j06v!M(aL#qD#7 zaiu#{L|xSckJ-LBafJ1Y?q1F1lUD_PUQtCS?$6Idi`zuh%02oP8tsHuYzS}d$uPQz z3SC>{Z{6Ekfj~-SWHC0PstQ2tVLI;fE|643q;k=YhftzkF#f7ub9!Pl(bRr~D zVcxV?RQfv0c@p1B>SXG=RrIwZ*h??QHF)2h$8SSW$hdX(k;it$&EJ3>?Quhi%xd@T zV&^%hh)E?agb9CZH*n-Tvqm1+!A^MIa?_?^G?%`cTF$JQ#Kck;k5(+000R!@H5UK! zbL4XW96EISdkiCn5C<}nRW{i86 zUYeAh)xqv;%>$dKC3uprjN5|ge&*&E&VIEzww?)LGY!*^DS!MVlGmJBOo%peq@<*bHpFKJ)mWqrfqJXkm413dIs%(d zRG&5PFS(>bVmw1TP1gM>lE3}N*)hH|Jh7EJ>RuCzW?xw;6CLw6_1ekNp9Ou3AsiDB z!5@NC%j?KsaQCKwRAMhnJ~!S@7NFrS{Y|NmrKrWh)?+p&m|vT83R(teH~zK0qr}t; zDusD^e*SDmT8R~vY8SFVJ@p2Dc#Z9n2vnLb3f24Br)9GCtny9cOZ9{ERs8m-?0`;+ zy$9<0&96ryBxltO@57d1_Slx|FL1{unzZUpbDq4mVB}$^!|{o78f7vdGp!U&@S;?O zecpV>yvh8(DtfGbujn}|HL({hgrnu)@e~BND#)lW#%$q*xzM!>S&AD~btG}gjY3o* zuRShNR7|0Lce?cPr=|wS z8z^eQlEOyii{4ex94wOU48MC6TM-Ci{42EJ>(JJ-fYzSV^PGZhL$E3PfuLMzcTX+Um-O{HozS>9?CUb1Xke#08=hS(lfg0wYu68GcJl$JI!QWW7pA1TUe2XcNlfqr;Eu>BwM4f9V z5Hvr2%>)gZA!>q;v9jv=$WMT2N8L<<(L zv?O|OBbwK;ikIN*ZY8{ec}#7xij=3HfQ$ni^9$E3#U)s*CMHr&XY7rT1*;`0+})vI1o6iBzRo=ER4Q!=yM5J zV$dUFyC57Ra?CwYKwP)8rTuhu#;E6URMG41lT<|+EVH@g)C?^;T7IhS-sLBqUkDCq zNK&JFF)Zn=6|L_IzlT=Pm^eQ^OrPi*+E9GBNb7}yF~{3Od`ZUJ+&#X`fe8y|colUk zeY?w@m#%@UL%cjcWJwBfcprlV_&!99bJ4ZY-fm+EhkIK$Xlg)~lQGN182 zfTI7JJYq1rzGR{&3X;?{W{o?J2PJxYw9eNXeXXN8Na?0NJ(qmBAX($yMI?sI@xJ?E zROe?~m90@0mLRdb%V;p0YxbybxskB>f{-a2>Wh|GKBFl#EEQd+aJ&p_B@{$WuI{eXDY|K{AsFo6v7zIOAFUHNVP6Q6$5%LMh^n3( zWQs^Yn{z}Ze?~(0h_7VrnM?gZij>W680A+{|7S!oY4d_hYSh1Sph-Pv-uD67aE!mL z{Opzwx|T1{K9XeK?N{RP(PUc5!k!e-6Fb5P|?b0|UAS~MlN$2?O;8J{hfYcS^0!IFoVXaP=I3}Cv>-o6I#)AjXO6yRh4YH?k< zCih&T3%xBO%xvehkcI0h<%d=eZbtAs&1_uBxhGDy6M`m(xg$XC+qjK_9=9`lLdQAn zEP3=Gn*)I&IFmfDb_m=49B%(rsVqQQONq_eYhTDvq7i7cI_#9>jBz5adU?xw(f<7| zAiHc3KUg`4clsWKRmE`(F6B!fQ_bf1>=Oj!PngXzr8oKyp36EKUR6XAcRE#fa;!bn zxD6{`yLo+Bv)0%5@*6drkYb{HIKDzM>`cN^HkKdVlWv1@J6duMLbb;eqW*pz@|tR= zd-vJOi-=&AyFwM&^W19!O;I}&D$tKx5>oPQ@&8EVva-+QWku{=;DqUxgARlsU*n8T z#07pdM;|^czv0Y{vL%~mo>M<}TE`bH-=2%5NSBv;XK^M?+v?+1IoNyH1jHSL(L?I8 z4u}}rj63q0YRdnKs2(?qd$iKFCu&p=+zz&Mtso@0R%FWI;{DF3|DPyrFXlu@=#KC- z6i{H9zPso@I_&>i34nvD(lftoz_Dv1KwT6d*eufwUEf)IZ_6PZ55>1s#J>RqL)_-I zg_HWHzvphf@$&qdFh6%uSi6S^?6_yL)~8W}{Z&9+UgxsjI0LauTSkr`?p9Ha5@@=d z7=V*sCS7xxV2TLTZ!k>}_`Z{8Hjz9V{<(?&`dwNh+d*zq$^NEhl8(Uw)WxJmoKzCHX!7^8Zg&i`k;}n{LBKsB9 zXM8#;?=wuIs_l=>^1i)k4A6Qz%gpsllA%2VIgQT&N75TwDMr5r95p6;&LwW*15xfC zjveeHvYly`8IWf8ZS7>2A0gB`;~tE_Yf1Tb0^=_@HAN>t<`KKj3<3F&>Cf+2bcD0N zy?qRf(0<9`tv_A<1_pKvVGmJXu*q}oBqK(PPv<7W$w|U&{eC#!(}lp_R6$5r6K-}# zAVs})j#}fQn5oMX z_B>blqy@Z3=ah1a-KAF=-R`2JOp1P;4YGCr5}0ZCDsgAr{^fxsmrCu-*pQAym%05v zEfm5B{EKg1+n+@LfsyiXh8(0G_dFl#H;y0IiRQgEq&!!lNxcxQupGLQ$*txM<;MY3G1|xqyJOF)wM(Q1EkjQPP>P@_0XmPyWe^BODbac+1{vSEeObGO zzBPp2zm%1|kG-!T(r`YHOxwcm%towwjGIVf8x1K%=B|?M@w_bqX%FlpU2{k)*W}-5|+dK%QBXlsk_dL5(f&Fr$5t|UVu>7JjXF>CS zpI(V`XA<;FXnW`f4%_d2^?Bn*nSKw#MJKJrR#O0GV85Q0ffnl%{3(L&p#L!DRHpq0 zFujQ2sK+NWBhPJnW!k=SuW-CfPx&RmXCjsZa$+?gF+I`~=FBe-jjZ^~2jVAzo+ABo zngkyAW!+b)_Yn51dM&MC z2^un-m>A#QhB&tk3o#28C&>PvK7#RKxl(b)nrMoC&U_cr z_-Kx|%l5*$O%6ql5i=VNnPg4PcFjN&^Ecv8zjP1f&&}RVTYkjv!PfFG5P2SLt?AK) z!HUwHjLJD)r8+-4$TS|gsgEfqh~(9M6}SbEF9SEA#F|^K9e>g}^+rL2n+0V;~{5YP8)RSriI=9 zgr6OVI^M(n(1PH1QSRhSITWYMutSjUl(S{H2!UYQBH!)aHK3ay$hG0qyEpZ>_z7VT zUb4MfDI|Ojwqa3ZxP)t3n;LeRgXiH11&uEU`d=yWY4*#HbjGHuzuLfG6|VfX1sWS@ z05>&(55t!^I%C)$2uSDjg)=y~J@4a_N103cd`Fatvm!^b_iBcMcV?dwU?t@o3M>4$Yyyv9Uhw?Dv_c!Kmf_-1s9f&I{CzTga)OA@IzY9`3Rpx($IBCG zvyKzd7{cQO@$!>|62?dN41OaDQqW=+q@Bq&V%${Z;2H4yQ`_K*XK$7?9R$${WM3AD zTrN|s`}Ge#6{zDa6+Vic4XLGAExhpR{7G@xyXeCdnX2WlIn1e3Kx1@W*Y*t9+lr$% z=g~Y3>mEd#z*jNaa~p*TLPZY_y?Ur$cfTFzq}?G=%Wrb+Jfm{&Eb|=2>jo{~OI-#V zHn-fKVB-@@BAoyhO8MlR=m0~I?yHc^s*fL|I#=KEz76G)FJTr)i+DK2 z^2WZhdKz~9g>B%VzX=nw($fc4`S==JxY z#K3&@IXm!i-241*Z8{p0xVePhT)LFYWZ{P|{x>fdvAAtt)_Hwm5LZPwI&8y$rvGz) zU`2s|OGqY#D9z#UkMwbiOT5bAD`vd$yK}eb-T_(j!JRNDAuC~9Lja;LhYgGEEGE=n z-X+c@Yhzj4t6#Ge8R2KSmK1b!2G`wySLr1Q5OC6cH-6r`yohY+eSptgGxxPjy?zP2 z>m}xmNkwEqtZjt%FdEyiQ{V^4N?ExlGn8MKNDj7}X#) zbdg+aA3eKdft^C+q%-?inA#JW{6tvj+32Sko z$JX}O>&PMGfG%DMZt2U_o?B%doO*MVfn7)4P}MeY51YY*(&e_p)79oEr%NN*+}Df} z1BFF2B%_iN|FG=Om@EdK4y99K+csOf37|ABtPOThLkSdSQ`|?rX&~gD!DS~rfTWUR zGNs-EPTGjXk`wX=CAguqwcT-yd_<=7 z4;VI2f)l?JLsVa@{Hy%nsqZ#VzSpa{8GVzPxNijc2!fQZCbsc@GD3)dnbHb0*y~&T z3;H&h0?7a-5nkjxTbkuB>IF}+*e6GF!BCBPRncK+wjAR@QHm;XS7hmnHc{mvQAI>@ zI47W}IZ>9fi@{fMg#1Cha`!N`b58aA!a`BWFlzHzLFC;Qt{7sF zO6ASKtnF-|m&!?o>!Vm#7a)}v+#JQOPf(zgU0xp-@w-M#@bvrZaoG8>Qm%X=hEaGs zm+)LIJR^(Fs4XwOZkk5KmWCM*HMYvxOZ9=OSpLqP=xB)lLS6#ba&9<1gh+LCKE9OW z4PhTPTBOS+N-UhA+324<+|VI9_E;UNkrB}G3M!^_IAcFe)J3YkGS}_N*1BP_oHFoI z`1KQ7RvhaMBJhZK3G->I>_DhB`$s4$G@X2cXEm9%^cg&)RjxydHa3iRaNn5=o1%Rf_& z(CtthyWh$XFW!P{iN)=3rDf6@ldo54IEJ_u0^h&R#`|1mv&wf{6OETHhQtS=uFilbzo*S6 zZ_Asl5m+{7FW7YMm-tPKwIqsA*}#~eOoZ=Wnf9+LC(Zho^LAoV!KImnpY@rmEIeoRca4sQe$Lc|YRJUNv0IC1-eV2(w<{boz?6+TNTExlUm6&i z1BpArvC)s28?tYYvcK<77I7!S!LGXdNCVYC@z4j_@?o`wR^CN&!gxkrSiYTo?ab5% zAI!mXlw)SKkA@oNtm%Xv76!2RmzSX?eM8s;s3!P_DKxrkO+c=0{?X-tEojDqLc1s-*{VV+Tv{n0ET%=>Kio1ZS*<}j9So@#k$(lkTFj2!bi;_ci=l|T%mnu1>Y z0pZ^TA6CP95BR>tdMUr<%Ew^lexpMki2tQxkUM7$2+z7BG_@?*U6J95&fW2GT`K=G ze97uO#b!gA6Gio_qP4f?KnLB3k0`|m@~_WPLmDbaPp!0i&Px-cWMH=*a`h4~OaufV zy?9lxnhqH>I0>8Z5e1ZzDQ>^kpJg2-&L|A|Nr!w_<{N=xd1Na>sthK+J35L@xjl^-3mKE#mw2MGN@1S8zQDzXb#(ZMx@hn}JM?X@Ve zHFNH-bboeFvMhg7zGuU}d;@G&8f)nF#Vm>h7aN=Y4dads9tLIpC{+X*H)>9Y2z6b{ zDCx>kQacX`fLqbAQC%*VmrdyoD#?aj>FVkqwTjIW89@c5)$Ib4Q1{Bbwe7E#G6GN^ zo4`oD+2*cQ!L>lvkncn8xUH6}*#oH%H?(l4*BA(P8sJwM6*9>Z9jG^lya0*x^khgI z^eR2j@QUBg(>v=U12VYgj!u}E*fly^K<} z`h}lxyJ$%C{Ua}w--0FCBbBL;Np*NofT~2-SA*yKZbyB6EbB&8(pNzI3G5s$<~)V# zcsp)A?h#3=r9V7P1d5A9p2&eJ(vPaRN#2d1%8OcTpa!kPvRm{O5lXx!MxA_(SOGSP z_x<%t$oD}Y>GW2Qi0x_8d-7W}VjOSNYE3)SrEzeVevy{=83_7C3QCU_q<9h$IGbjY zmI{;m0-NtjMRomrz<Yn4oYZIY&A8S)i1j} z`m8uz-l9q!_#}Tl5I|)b^4E?d#?N#`wEbN4#|>Ov)Q4<-EP&dm$^WIINw_{zA3p)9 zgjcgb&nE}xjKlgt6-~hxR#2a>;!$!R2))pyXp@UEZQ7Yy1n*f>SITK2zvEtp!?Y)| z@G2uhf4MqD0<)Yxspst&Ndy|Zpa#BVQZ~vpfp$`wKsKM3u)@e-UoLP^w?L0aJ^5*@ z2h?IF$M?JG@+iFUXk$HH^5E&#ueaYtRku!|2QbZpbVW|3!q%I{k`utoW)GLlCe_!Q z561@Ydr}+ix&#MvQy(g2@>dkGiP_MziUy(E0#ntENj2~VYhhc8Rn;hx<7i7G+@KIo*1S_XDuz44p!R=W1w`i&I;$s9JI+<-w^?E0o+BbQyhrWi&^OA8Q5VIkz!#f!>xd-*> zj9D_F-ex`(t(R!Z9mzrjqyqAO^D=C(kbDmNcJkxZ&Mpcr>431iuUTMdXSmDeMg_nlHrJlp2D(FQUPf@#L!tO04ibr6xsULF0*GMm8p3gXCY~?$5)-2wI_Z~BtV4!$yJS(5p0AdAspd@<}kZpULQyGH%4Yj!GJRP|2Onjinqbv^Kn=4v%M( zo3~#+)l_Zm-V#n|4hL}ICp*^M|_c8{#WF%G?8f+Lmt+sRb+RNY5!{B ze%9*A2L^D9)=o3e!umg~eLBzqglcC-oP}LFGp5*5Ebs(L9T1&O%Y9(LE<#kHuEZx& z#2}$~@O1IJ^Jb@->WC^Qnua8mDYz?0dxdOHWfLK_KQkHA+s5yCfpY4lUaLOt&)_Fyw4Vi4pU;O2Ms>P~?N-lo^EDI4^&_0J7>HM;V zkN(C2<;W$6_ivuY-fo8jvm@6!=lOp7^2GjKyL(J$?w8(B*PuY?vb#|_t|mUjs{Wz| zZ)Gcdcf=ot;~J#$+hZplQceR*`EsJ<@F%iH?%Q^a)RcHW&u;AMs}Xt@6yvX&s6x!Y9i zyf1B)>d8(>{~AT`cL^vp%_6*hW{MoFx94`xtMlzFj!1lPk7KEgU|(yA(I3sc2VeVHiaYS{sp2B20;GLlIOHJ37%i* z_}*9T8gW;<+bR!B-I?bqA{3{*di1-la#>2p=eiCN{~b}e)3NK|Xp#VSuXFRid zc`3eTnF;|qo^!sax6jSpRdO})k|UQG&((o{6lA@bAC<$D_WbxdI4(r~>BhO^X!5I) zhTylg36*${{O%a}Z8}lA>yT7MPcT$tGd+D9zQ$WdfVecj^sI*Ynx~33FXy$@Uu5p` z@8B71zK-{xjH*QU%4Q97Y}vZtGL#I@OBqHl)e9_OcH=zMSWsQ3W%jLB?$L9Q})9{UV70m5xUAmfK7#TZy+p}wKJNlVUxUi4n=X;w>xHU*3rJwgkL_& z(VlkkFLHE``TlhLnM(0pk)=nhX@6&&LVR%Kkj~^CXOCE4u>>Jf?6OJb-qI#bU&<373$~^`RVn1H_?x+j(6nzYzpbROyPt~D9L^`_K$m0hxsvvt z?Rqbuq>I=8P8?9J6zqf%&SO(SlHG&_*LldgG~^Z#9{$DP3aq)MAyWgqWWA-cH`jD6 z`BzQjb#AEoxXlsE8WDw<64%E27GP4ArGg7kQBV%FY11;T&@GoO`C(=J1vA z5lcn)JuKMzbs|8WE2z&!6x%JAn$Xohlb?3tJR7h^#Uf;UM;-1OJCM%N88XCTU&`aYT* z>AW=)P8g@%gPM?b1?yGkROjjl!tT}3z`VXkSB%Y?n`+RK0WNq2mZd(}? zth;{qe?wWgJm)=qDeWpCJbT`(Yvx;wgyv4lQm`X^O((KTDztLNaybN7hnh7!dJLv% zA{6>$s(vQ1=ZIdgO> zfbe8N-qz3Ci%;t+nsXZ>7^?tR!)%R0@oB2(CuFm^|OBOTJ|||AKhF)GH}DYUzF_wG4lyudqiQ@B6+b1E)`!n=j#YByov&%_IAwJ zN|3sn=}hzux^ewY@K{rkWDAU*&uO|x=?um?gi?BCLA8h%)*2lxonKh$>NxaA@IJPc zHS=xGr={DMqk+fww6$ZAg6R1395q!tldZ3Q4{irgFndKo-t*_wvDTUjRk0prrg3iZ z?c3yNAecJ_=e2ZZd_Bsz@ps|37>w@?>s2ug%tQ3SrJloqBOYbNaXC)A7OK>+Zc&x5 zlOd}4Qso&tx9v?Ff%X>p68}(`z%A(ZSpxE_$M5}d;=0eijVLa&KQJ2brps8p7hf*$ zF`ZSi8+{T#l`!@?ehN&NydWa?@KQK!F#C&@%3E;vX-YVeqyhWtGv~0>_s3qBe!_w- zEvm9iYIE=r)b=}wEOtICQdgh_fKj<>{Y^QM+ zg*}vCnx_eqi5QHNE4qpvhmGYJlWDE(Oa0DegYl^kH2Jq|zR$ZB3qvT->$( zZC8UaIdD{fpJ%GOJ7Xs<56oJ4;?1crPRjU>o=Th>^1vSu3h;nGxRj4Y+t~S5!{99p zYv+GbXxTsfz23&oDl47)s_ZvSd7AE5!Bl@^kFcDsLNTE&x)RmI=-@9Sq-<1pqgu{3 zS9O^tN2rSxJXJ-P~ki7mTedcXv>ZJb7WczHsYh|9Q z$!X&k_!*aRNwhaB;|VbP$#tI}=8)SWMb-7B_GBy5NDH_^1P}gO>N(5whk_bCzrBQx%pHHzhXF- zxbVF0-4%DDyw`x67$=$BnRw|7lT#>Byp%7-%=22cJPd6vd$zOCY#l^n14n%+_xykl!vH-|Fi&YI4`s_C|~ zb9wkMnekXgh1&Ooj+4TAT%1`tkQ6Is)J^!j+GHl2x;NPKrC|IoKTXkA(c3TIJecHa zY;A#~k!ZK-mV@V=d(6Dd1`pRX`VPamUTg1os64$_OLn=1zOPhsE?~K`!T4R7^?n>o z`SZSE>E0cONv;7WdGHL<$X#0vs+oN8c#EjxI1Z*)T?+HLYa3wRRl<{b@LEh^3ogw1 zUh!w0EIg(~ohB#gWjn1$^3$OTjbf zCB(^SN&&w9nG*GXnRNKipX0}BLNA074~qVuwV7+5hk{P(0=fI^hsOzrFymZMmj6o~ zxItE1W-O92I2YiBrI8F>%Pi4wMo^q`>`w7o)tH4mK4RBeyC9> zw=pUg2V%)lo!TeKcsf zdoA(;79tvQCsHg*%+w3g2bv>vp) z^@?Lq^MZ9FW#?s+{dah@KAXtYufU zkJGb?h{YRI?7{u3uY!cUB{7}gaM*s*JZLDodotGm?^16Qz1L#kmvmzKo<;QgG)=g< z%EB27%@%7pJPFs-{}N>bFtLEY1c`iG(2$VI)6VrtdWu$x=KsS1&sxu7|CI$Bxc9Li zk>dmgV-gpUg-HW834Me4Z;LL;pMLBFo1zlO9?1)s5U3R3d20@z!~Hx!=l$d>wf+Q{0+_ zY2KxS$2clEJH-g!zxqm((;Iy?J@~Vt*1?dlH{>eK^NE{DW=h2N<>A0UdBQCg^R!~Y z@KPqUj)}KbSgU@s<+c$$#-l#>wEI2y1HnM42mdk5e^j7u>DNQ18~&xd<+XeSb4Ge+ zZ}RPN35}nxTMGWlX~P||cjeH&v3dK4tS&trQW@*p1I4^H1?Eg^-BN-}h5b$Ati9Iq zk2$)jRB^S^4{$du%9h0Lv+QPF8VX#F@p}#VOte#tV0c69BEQJLZt`pZ7q&-TE)_dB zWS^BpX&5VnLIwu9GR(MMgxz?mpayi{F8QVQqe={qVUF$bJSnFUU21= z30~wMJIHF0AUfU8sVMa~P7a&s&=AXSUe~lH?}%^{5gz0c-r>I3D%JB29_wTRux9U0 zU5T@_e7$%9UbW1;ri({fs0w(Gg}!LAdmx|G%*l~U#}}0{RF57Gw9s~>x0IRcKCWuK z#UyZDo{()$q%~8W$7IU!^7%@qlH??(2~K^5t(j+dz+#bTlpS9zt<$`Cy{Ry8DUILR zB~F2gyA9rt&YxrdRrL_zJfipj}i(emfEPcNmv6j z6~QnK=b42n&0OAs%-w1(M3&D0TpS}t}fyk%N! zeL*Zi)yWJc82K8dro!Ev$j@Qf*Y75)P~>a8V?p-2X|5v^y4_OC)_x_{a@YNhpW4b! zLPtS7p+_2r>=Y+IJ$uQ?tS@e8`oXVH~b zQRjK8)}D0h^iG-4r?THfmFBM+nq37?s}Am8vI4x$Q@Fav;lizX$PYw+lYw5TA=PJK zE4WztN-M2tI(|yrGm5qjl&%4gZ8h9=uChL+tX?wvdSrRb4RU(eW-@B$ac2JG5-Hhu zFn`mdl*B~r?W0>Wb-INVS3W}dzkJoO&sLQm=Ygv(xoHv=u|s(I6p03_!Eymz(kK4& zk1g`>-0?BbE7d;ZARdw4*_W7YoGbR$e#&Q08j6}S^%;x8+L}W=8vKI zq(7<~OINzG6i6Y?lZpD}d!Y<)My|VLHDTwDonGXj@AXoW7xr(O`|Y?vSI?&%pC4yv z#O$ob?-Mgkd5BOYko`{WF3#n3nX8yCXl+-?Agx=4$s1Vc7@S`K&#>1#bW#eNBT#H2V)lB>-JKngTD(4L>NrrgidGbRSsy3 zr*NG|Hy(}3#@<1Yiba$UkO(yiG$MPJzecA;DZ)N^* z-KTO>yVLZ3mp7?=iU8S6Pdf`XcNFBWKh*KR(Ud<6w<;Ef88J?R;KS;SB|9VAo~Z6| zGsV>}yFi@K4?WNH^u1jQZwT5lVV=Sf*AnnC}c`)v* z$ePjtTWKr_Z5M`Yz_)w+r!TyVayvSa61XNQa<;I#qz9Xm6rz1`RHj8gBsHQX!Z4k>+)sH zG>Z!wu|9|eT(KbjCbM#x(qwV_!*A8(Y}82#t@eIR<7e4P6sJbB=yp-&=~i8yu#har z-4=Eu2y}zx?-`3k(^>fJ$pyAqX7Veeog~T`$9NN)XywQB zmwQA^jan0=@a2Dsgj+HmTddv~d~xhL^j+|9U*ZjR5 zGIzWkp6`0r{Rx@dP8&4E8Pt8JpR%b)VRU6to*fKtNP$3!70RMwfpV_T(q@89uc=~b z#0JZ@M zJduoJ3hl-8mVKm#ysdB+(WxiqQdoT{q-nlB9s9S6cKp`H>r;xXtk+z!oSk~M;At1o zMD0_QnQu2Ip0IFeD?2OJ>Rz)(!}k!6H@S1Sl&wRKy+R)bnCCL;<`ZCwaq$?r!YQRN zdC++vn)`TPz_oFY;tF|_W~iN844~8$hM^o0PIV!Zoku!O+Hm@kVPjr*56AfRT0K5- zfs#}9Zblk_QOPMIiMI~M^+G3z9_|*#Z(_QquQWB@jKAmct~ZbQszD`A^;5E;$+b2m z@~P?d)kWg2M4jQqezJ4BXOri?-Qq$^fe^f;Bw0?CS;@XRe6tRUieY~9ANERJo0w1D zpApeD4~o_8p}=LY&FKEPS;92sr}=~;^iUR z1Jrf^+hay*P+Xg*pe(BZ2FO2mZ@>g`vJGyts=(%tM!T>}zWCCsWH<5Sh6QvsT`cTUI9B32ObXM3`7eD(bz841*rjuj{poyDyOJTHn$(l zjuQOf*X1zqgQ-m{f{K_9q3<+&$0Xx<#;k{0u7Ls!n5YQym#3 z@EuMtftYzz6Y#0HY!1J^L(o#&(-d_<<3l+WaF22j1yC^_@0bJCNpbma7)u+If8*e44Bf%m- zjSq}FQOlDHalMj&j09a~^K&4_WXS?NNoj~|R#jLChi8{v8I8zAJ7(tq^djry25=2} zE8yOXtFkMlAB`IB-FTVh+q=je@}*hmWjsuj~%C3J(8nC4VfLPz?gikt$>mgt95u) zOa4G0-8Rqw5OqD$6R9DiL9l_R6^B7ZF|>jee6E1#y)RvAI`%P2qHjLK$G8XU-8C=6 zuX{1sZ#MgZ0B=&}NaG0;PI{4?)S!o6Nwa9BzSO|23p7aVelvtFYn}F#&xGS-nMIeB zgK7`s!UC4ku;stoNbx@1D9*c(bSx=*lXwM;nFRfcq7Iu3ytl;BZeO1CT>8#!PMpRz z3X4w06STi2zB(HNAY>6iL^o9M&h4q)r)iA>cb3@gfHVS+SVMCxb9thv0{wLu>5%t$ zg0_+cBm%~5++sqGhG=>E&Z_3sq8*Qd*QnObaztqCe0kKJX(vX6vl4ZOV|Ho^2=N^z z$^cA5`BIv=yV0{vvemsP-#v*e!E(O#05HQKD%yeqImOXhk155Y+K(y0^_-;|-idq0 z%Ei9iJ~Aqr1WdtM7bgYYcXZL zs!$9qhah0URk~n_npgY0AOb0xkY#7en@VY`{F6e8S5UG z&9%BK;(1kKkllkRVMV=qjeQme0$1m0*p1(j=Q|&`@L19zVAuYoULFzYaVa)o;RN-W zP)7aA#a2MUc>3+|)pUpZl97>df9clvAN{>J)H&m{mPym_Zdc#Vg!t4Q{UW0&5L^-L z64VFL6eIA*ms{#Z7n>r}qrR8)n4kUfxl%-g%nuks#hRCFf6JJA3e(hG?Di++y-%DI z+)zz83zlBBKWW%UqiyAq$~UE76infc;u3|d>F}d}tkK9yg?DVX_*dTq+w}PK?Y^Uf z8tOHpZeRr`6$VklvXuQn&Z7N^nlcm>qzsnNruvo%v|dM4-RlNWZP2WeoTB4D7k$dP znhOlbS;+JCvU*hW%v|@YaEWb1p&D-4m>nJfU||<;ShN9!-3AQ`@y6D}f;nY-{)?yl z_j%0>7X*0~MW8#PZycF*QN!ds4H(-jz5qx(lh{Agt8N4d%l z`>DH|x5dBSQJ-M(DS7Q6b;_nsx8LTe+$@l6`+MWp5Nzf`SQ$@k#=!{}+pFflf-cV_ zb1&z>9Bj1Lzb`VWWfs-iP=E#;C?bL*bo=&JQ!2L+rbSa`g9SkqBOVV|8bB~0QQ?0y zw_cY;#4nPq{Owi*|NT49S{~Q?x|!WYpkMy8$rn8q*&yw+8?328PT;q8>WaqhOBvIaDhcC#Z+SRr5d#QUPhbe&bT{xxmTP2Nb3` zBxlC&@E1XE;TejIHZCQ&63Q9(pa^6~dC`i=7q2m9+t~H(L-Lp3T7TV;dGkLi9U2U) zbD#^aq?}_x5qi4>(z^B^7X!gl_8Mz&m}LfrK1eZ?x&z1sLoXxQUk4}ZZ^~Lx6chy= zJ30ampIF{Pb}YAgu~<5=-)MH;Id_Zz1wnjj+%$XrV`8%xc+N}~Z43GY#dYk9D?fGa z{kwhQ(>YE91{Pm2m6<^4p5o^09!Aw@%1VoE{K=s5sUP(TM2gxLAx*YE1=I5Dwmm0a zh5~j)*=F(mJeDZGte>*Bl$DEA76ez&*1W`{o3sx>;9F5}H3kiV(W`(DzZvSI$cD2p z&O;aWl`uT*0mHjAU_w3fJ}|Z_e7nO?c*{nbw>V^O(){$2q?wZE;kE)`Grpz4FX&TN%QkrC{{t|Me(?_olK!@B`!D)V zwCaPhJ5K#OuP*q>e|Mo{EYBMMsNS5${|24WyZ(<4R1z3Rcsc5Pv_xCXrn~cV5&pev zq698~ZTD+9q3O&!jAk7=2m+wG3S;0&+?!hp?LP65Ui`T&*JpA3Oj(N-=UzjkpmLsl znHHKePD~jNd2+u{8=*5f5BLM#5S&*Q#%Q#E(NOUvKSCHuKirP#AUXo85CA^TX9EY7 zv_bJgxyQe1i5Ph6Z(mSf^AC9ylzOoWzjH~N1F4B^9%Rnd z)DWD%FsRS?C2oKDb8o0=ta-Y!Z?t05uA;m-pr0@A()oZ2VqQoVqz0&eeEopd!IBO= zIM6ZBtmy{Gup#27v4DpgqV}GB)Q>M@%v>atBCKa7xVW9VdGUW)C`HD`6XtFo1+7xu zM;~aqz)>>ymK2a$3JZ?x-HN?Uf+Eq6-N;CX<9Xd9l8sLv*wz8~b>Xmk-Ld>mjTOM% zFr|r*8EsNg4Ube{5|XCcl93wr9}+DkH#i$hIz}lhrqg`xE^&+l3|VjV6i)R(f+rG` zJbJkA@AzF@U@al}?gq;}@#>G6s2b$y|K;WJUr#NjN3(-&qkCCPloGKSSdt zz~*^11|dhBbLz7M_M;x&A4q=Mt&MFDCl$nE3L?kUF!2pL{93#_>g2{uG7nq3b{uky za}}kYI%GZAEI6Xf>Fn-jQmW@@MZt^(0CGN5a&o$7PLKj#t?h$67G+1;n|tKHmI;Dy^Ec~6GcRY%DyFC zE4hp-73vR)uax=~FYAn7k+pe}r$KpUI~+sPq^=~kHxkOfJ~}ShC#vj4woQo9zCiBh zeY^+3`ts`!tL_)g_Nj);Qn-bg@93!)WdEi+?STp5zO^zI6SjGZ^CrrwveH_$Nwud_ ztQ4h<8};;z_`uOLz1y#nylR+(>?$}L%FuIR z#SUU3&F*HhIL&RNAu*P6A{Atm`D9l$8xsxQXPog&POv{B?hJtIAO-WL_+Z#H=PTX9%hpLcAfIFqw#OKBuyHf90gxfku*nJ0LwyB(2KG^A z8ySc$Atb*P2$L&>++r`EpLnow6^0HX4$FM{6#c5Y_*|H0LoPa?LZUdkD^^D>nWk-N zZoZXW-zLq|6^INEofnaCN|MMTksyZ8wVPY^oQmT z8$VWc@Gsl+nWH^JuZyk_n}dwUTQ6UI@Y(sEdS)c9`o@PxjEduLy`o?N9KD=e`5cZ-#cCIH<@l zlUM4xl$3mnH_a{ddcGvUky?@$64a+Bg7G8v4|38*A#OY0KPpP=smyd|k(F5N4&jUX zQ^jj=LRX+sje+j?*a-jncbl=mEq%~k0A^jWZVKIx5Hu3U$#}nw@Jc}+0UkRSrfUQK zShB}{aV@h+wmX<;(1P&w!H+kMy(gZz2^L*rreC0h#Lz@zbZ65|V*E9*CKXxl+CAF) zlf5bxR&SCX`~P^eJVw!%<@wBueJ+P%<~aAyUkak_$`zU!`pZ4 z?5Y8;a#GKfc%g?%{GJbjt5u*WKH9};9m$w+ztmKDvFU}T$Jw#l;O=poMeFJ5>C-`N zoxJIJ8t9Gp#;1xzJQKM`AAz3L*dl9lK(U2D%J=s|zRNh7Y;I}<2F@iAl^~+(^$;Yv zqp)IXeK}9*EeOPLj8nM|aLQ{m4@ClF5M_@`oJc>QNl9!#yQ(KiXHUxNs1Oh{v%w2U z=AC7hobZLKEhbb&&+SMj(QTBm&@6^`O=BE4JOfH$M`&K1#I%z)h7kTCM#9=feP7(3k1O-K4$pKhQlj}G5ViK+@8FHo z=DgVX;tj_a`zf~Wjvc#(qAex!L$|h`C2Ba%biLOOiWe`@EK++AYq8Q~NFj5luYKZY zT`@a9jx?k_*>Vck1GO>f<6b7$*1P;%b~*BDWO7n9>e+pMkP~6| ziz&`!za+op$i7$CpgCPR%yKDlAm#YVrH&(g(fp|%2u*Mbg7Rgb^w2!T! zsAH8taam40Fd2PA26T`23EG9NdM1iYLZhQ)``U^18;uVi(+SfKu8$?!q|*R~h2{X# zqh`1`uT3)7L9g{|;t7%6Q^JA~-K={@S`^v1qls%Zw&*f~-9G9`@M0{3)9d}!>(g5_ z?$VTW_Xz23QGE({xHuaP7dVn}L)|EO4<-A_P;^jrq!$mqcn5@#2y_&s%@f@+7RX?8 z@wT~L&vbGZ)r8VA+E&q60MthoIR#Y<>R6;3%tZEn`+Ty0C3w$&rK~aM@C}_e&W>cK zDwt%DR-k^@D?8`v)gQkghD40@@cgl&Fqjg17|_g+`-x6!jsfs)MN-i@3Pt@0R;*?Y z&J`elR?B#vxO-*qW=zpAGz+lZRifavg09VhoB*$|zC!GI>svRCG|=p_9FFEZ69!E3 zG%zks_c8mfA|7Zw(W46;&&Y1)MG4<;pl+~T1A=62qGz*6Sr>2lQ6ohlpmJf1W97I4 z6q`JNVu7JHJg>gRFr+Frjl;lyN3x;K(-8Gy|Fcayw9c#<4%r}n1z3^`QTWEKydIa$ zezsX#U1^n<=mBY5H&9J_8N|>Z98AbzXjykZIUh@~`%>pHROQnuf^pZYd#nK6u+^X} z3t_@&x`Xt^gYy%=_vbqdUlj6Mz!&fD-qc-p>imaJwgP zx7pej%yjisJ+yc2W*eDE8yFv4f13#8i$!W*g6i-6u0if zq^ZRLVg5KHimj7{b3&e%Ti*+wL2V0eswwQF(sC5p%?HXR%DFY902PJPA1XE@IMrzv ztar=YO3*P(M^mU8#loB6 zehramdx=o2R%6r){x}$`G(Ix$5^E{@JJLOZX2={;jy(bb=wQGeB;2t{S<%00I6gje%HN!VHp(?v{+28toVgof^FjnoE2`+*#-#YdzXG2-i-+_JJUp6laHo z>`=Iw?GjoV1f@z2!VLIy2InI+9&&s#1a-7gY|^*N?PW+|i)|l@zRa-VXZH4bEDj(5 z73-bE{})kiv8DL_6lW2r35h+O&SE;zBOuUp8$4-$6X$;TP?)1ec`OpYFgjugr@s-9 zCax%A%hY7C{Gi$^zI&ydMG0sHz}Ooa)xy-Ccny@!>x1%dea?T)#Sd`ocloFj(fHVIs-VLFsp8tq+x6~!GIn!-&LnKvHOd% zF(IaVlrxr`VO3fN49W3@LQ&4|8o3JtWe}WRGf(-qoNVY?22zAP0n!+TtkCX$k#>n{ zC-UT$Z}5sO0kEQD1$FC>=ys%=Y?ZS%I=tcg#mEM)jB)Ri=JK?-!}+8KGDuxMtxL!_ zHs+`;{Uw-Dkzf4OwZ{R%lBEkGM^0R!+{sG+2+d;Y#|#fH*(>j4$Dle3G_r^}C7yPe zH&pv#rN4$liC5VOw0|7~0Qc3JLJADJcGTKPx2F=v(^WpHA89~lBaQNZ95o)1!%jR_ zBEKd-0;mpj29QjOG-VH%5&T!$n?1aN!iZ1pJDwD_vp=9by$CTQKd#*=lcHp=sm9ZH z7Mvp6E}>2M3;U7^PHLOYLG~iO>!c#J0A6qQremv>pUInB*KzWnWFhBZT6VCng|_Te zIztwMfT8)dT{>j~q0%pSawtA6_2*cKtHiqk>`H<0lKcno^e|2btSO2(ylA}R*4@vD zmajlFAGcV*j^sW-Tb8kwjX);sAhw6}F0KJdGKvT%%;%UC03(21pu?n3@SWli}(kq`KqHHIw5tU6CDdv@bJcaQ~~ zg54^=KM_e;Suqv?KD?1-Nr;<9V}c=9v9bPB88O`(+>iJxfUa%&%c;2ml)CkiKDR;O z4sZ;^Lm|$h&Aqb&?(KzeM6c2s0DSEOg`c2#xrW9y@{uGJBu5?bYv}ZyP?!>d?@pz# zCuiC`tNxzcNW!*y-gJRjzxCfE-5?KLi9B>u3nHtS=kO8{indDlv2Dc&I zT?x!p8K417_vx7qmoxZ#9p#r|ch-8q0t``rqkk-;)tje+YfL0C+Cj-v#O{OgO_Brg zWKbmq#UbSzlpRs_QJ|-Qmq1_tF+7WY^A8IdO!|N?hit_znqaLRHz~Y%>7O5@eHDk2 z9vn-XiwK|bJ@8h7%C%y5p3CQ$M3qr4!cJsC?3#w_5f+T;Tb6H>@v zFrbL9J*lVVfu6XexCaDm-g5J-wCPHi`@88sZC*{THSjXz^!SMI@SEDEsL@ z-Xoef-kM;zbrQi{>4=4FFCqV$^xa2RC$~^%?SH4rXQsPpmfWdi?MW002_kwu^ycfUQ%gzrVkD zfO7^-H`qA&-wXJz=~15Lmn2j%kXDFCRHg$6WZ+l}Aoew~vuc@k`o@`fm{{9s z!7a`j6;iaHO^Wp*EGCfv)Y|27MU z!F*pY^IAXY7U`Azz1ec>_9HUuMi20ul|QvB=N=5@ez$At+hNhzpxz6wf)4%~h&lOX zF=3quPyu2ls3<`i1MOm)il;_q)=*OTVd>=i$(}aoy;1uQ+{n zOI?gtIiH@3Z>CMXgeS3OTCgOiqM~9tJ1d9$t-w}c^Esf`(H+2e#4b+R#`|FEuX}sH zF|Jt~bnt$6-{zy`wJPuHCElN2u=`LrG6K51rpCY5I8>2R88~ zOnW9ezzZ$ja~7C*2VgW?%XaOQpYy<**Kt-S+=l#tkRMu2s)lwq-teeuTdUG)byL8Q z?{t0}G++k*&=uNut?nt9BINl<7IG-xhGLe@MxXJT9bl|@M71-3WzKJd4uKM>r)?j- zGnAtORX6fAzBGz&Qx_acYeoaT^h;wjcZ5i9$egZ=O2?t&q2O?-(P%OtKMo!M*YuI=zoq1@S&JXi8gV`PO*RU4ec%GwunaQc^VyQ|qgeW2+&nlDqmp)R+dzA{JxCnZ>#@ z1=Eq@ESL|(baDM9G$|Yniao^cCh+qlp+2ccU>ElmL4BQeKhTn%ncJtyS;)1W9$|Sh z^+sKa(zcGW3{$nZnP! zR1@nUxTT({5r(V+m?36gS;*J6pN0ku58TD|eS2V3d==hN~wdU-BhEK(tN*;!M z*HjESk`nXmAo&8rU5+X78!N>Q_x)jYNoL0yEvkiw&xEnXftW*c@Bg2lJ z+clniiYz|X{3zr;5>c1!Q%3Vu28zr+B8A4Kk~O289^j$kMK8@5Y&(4YvdWh-#}5s# zR85!lDg)iP2?*lyDHV>@+ClL&(UXulG-0IC6gd)3Ww!}P*TfLpa5(K{r%vB;Ku0n% zxk%^<^Vg;qg%GrBCf<}N7Byk z5kY!n|Ck^;(Fb_EDKv6sv^k}zO8>1$)k~-m8Ivw$mJfSXY7olM3?LRdCfBv0%rISd zxs0SHc|PA|L1x?>@^UCCw@|GVyU38pz&E*C;^`|VpSca(NSAGraqSPpwJX%y+XkdP znz=xiSq`#GAqxK*(V+m5%am2!R$6F2=antO@*a62)jeTa$*)>@-F+w`K~Hta52|L; zV(rnDw%oX#;$S4a;iy_{8ypZ!-lq|pTw5{FE`I2m!|G9Q%^-t~ne_G3N9``f>J4=c zshpkEs9l79)_Lcx7yjCJ302WSA_9_RsjE&8qy&#?h#S`R_X24@{rMPG^CzPrGE=e4 zNB%mNQ$a8HJD~k4Y*!i=!?RCk2Fn^fmysjKkrPTIcB#&I`n+1oDl>3>E*HstO*jfU zKlz&vEpS-TpQfT&AiFp}kuq{ppn{xHhKSP&&VE_lx0`Xqv|G=s+t2bxPBW zF&Qs(j4#8zpE=|wI@TM53k|O0!3~vEn_KPZRAna9&k_Zk{Q>ZjN{N|TUy#4V+#_oG z#)p5wm>GL<$dJ;#d{(Od_m)gtdDw;0tBf&l=NVYVshx$Kk&w(x$g@`IP}rgLa<$}SFtT-5r; z!&$*Ct2{@@pmJ{H&J^@ee|cb~CAeuMim3KH#&gu2`^+*fotUJCP(zO4))A0s|^zXI>kOWWSl)kc@ylzDPEKm z>}+k(F&ms3ZZB$jG1Rr($BLeIV9qV|Q2&HZTU_yRT#BmS((Ss=!{lRkTxAS>qi98~ zPKxA@0b~1aDjvo~^)QlLsh-MrmlBJ{2DHTa%FpR8C2MfDxhsr?2f2Z;ZQmmO=#Anz z`_BA2YWE{EN{n7P&+u{)71v$W@uHbvZf(10r=Jft z%RIYMWv}ze#dag(l!%g-pNHd+;oX+k=CNva#-cwLYxE#jtk!|d8l%aqVj+PjGBeiw zaK`C+feDwnNs62K(*0)V6@|#>lDJQ^cqMlj3OM6#5xH0rTt;QJ`uhy|&F7iUd@L8& z^(K2F1gq0@_1JJ&8WeD%pbJuMCpaS3xIND(}dyzSajf)=Vo$L-ipE%6R9yNh4LOHzc znNBMBU|Z`zGVP11MBg0~1$;1x`s?$IQn$MIL(ZiaN?vnB+y=Nw(%mG~T#LU%%slcF z;mSDqt;1RU>FU%Ql}Xvyq2zis0XM6>>t;1XwYaDo=?QX2-w1ja_RVh z={YF#S_gWc><-;|_fzQA;^z3>RLg3w;r@mUGb#TgV?_*BhLRzlM&ct1*8! zlqnB{?3^CNP!(DyM}|si4i6Tqr|F^Q$uB)E6`#$(BQLHQACfX`(b5n)^|dsyGW$;p zdPdpBHm4qiHlOsP>qaGF9-~sJ%SBDfS@|N0x@&be(siXf&6opi%f9IW9GKWA&?D3a zm#9i;cfTZlx_KI_E|#wCEv)hM*Oz)%(%$T|uW4HF@weL2=D6DaY^qdmv$5^#9*k8H&st-dno!o z!RmXf?}%dbg$mn>NN8uu$QUll zjD2mqSX^UE?a=B}Vh(MvBF$CCuW2X(()F>`7}!t5fW^M@l-AqWlO2i43c0_YTf@k0 zm8#dMm5A#5|(72Xhv9=I{eV#n>^pt41 zj7_*N)%v1OrJQCl^Yq?}j1u86-HxoTw_yR(Q4QYov>tDjJz0{Tl&oP$*9od4Li+rU z<%t9SC8mF=mB%JlmZw@Vx4d#<@J@LpF51QTQL+$B@eD9w92?ug&SJGdjqSU9@clUR+ z4n#K*bga)-_(K`lIxs;!*7>o5$1y$Ar~Jxw7tPpn)seR^y)kO49mQ`}e;70L)UQhL zWIy&BdF*UvlUhT$2rW}P*cP)>CG zGmPXt9WSK$$94OfQ=(MeT@h#g2&iI3296(t z6VPOgRrIYturDMkBvTzSc{0fRV~aIBZXR*xv^s@4tm&0`hZw^*s7(p9X>tlV{WCJO zz-Mt*yLC3aR*%)E{Eus9Nd;a+~f&d*aQ=vP+ZIU;uKm=W`n&Yd}rd#~nzF z?oPXyo0o921?Q@9Gb-E4xeH3fo)vFuU%h(1&t@sw`{9y(_Sxhsi)K>uEtAy3YLJ^3 zC~O(oL90mD%FxuQxh$uvJ^?|Se1jY(c7{oAs0n%1wnn4-^|cWL=tZr}q&dAxed0wL zdC240oG0g7_tebc%^~J8feT3=cbp_Qc^w*lf}mwRu9sQGS7e6uw$=Z90&{T}hE+-#HlTZg+j3(^yb?v!tTTsIs5 zc$cKS*Gzxwv+BaU$hAfW&y$3XpW=}0p0?0Fs|s2!(Mx>01uLgdNE8?0Z@)M0MCo>6>snz-??} ze5CP2Dwa`_*E#p~9g-;Pbc$7v?FXhL0RJ0O`i=*QOem{-&$K9NtrDZ2U~#QHe$Y{R z;9jC4mDR{lu36I>9uIfVUd5izq+*+QoYTPc>TvFEKB=}oA<5f!)8LEqgw?mB>-r8hLdK71G7(V>W&1LlKrBLi#`IXV4rn$>)ee}7D zgl)o`ep^{xx-B!Iv3|2A&C8;LzHlv$&UbHNuw^A_&Vpdor$Vr@x8k$+YKv(klrFz+ zw6!(K;8jkx^?{O<@ycS@x_ZeOreo%hHRP}e9mxxXma^s7EEySmks?%bG6@sZfD;YX zA}J>H8l2*0NXs|cvQq5FH|%@x<;xcb7Q-v|%gL_3K|Y{zj6~LE0+%LQ6M9bE2^V}$ z{rymaxS)V5_r6e?&NBDt&D}mXiy25}8FoYapk8{S>iM}sa})Dst>4N0DRG|c5ir|z zfXB0AKEO10Rr!6tjVVYznyhm!5_1|G#B>(pqLeI)ku`X~b*XCq6#a`ZRTg-wvNunk z9?av_{H^@c&B|8g(r{;G1*tSUZoXx@^G1Bvu|VjXpoP^JJkX*b)Ww^<=DD$mBU7fp z-cP{`&8H#KO7@#$nf&y)*!IFF2PQ%$i6^Iad?;cCN0dM9FcAnW?(r2Y_Cw;^Tlgh= zy3if}xiz6gjrA;7GBe!sXr9J?_Yn6DsfJU-1FJTKcSCTa;UfFZo(qCw=)4GwR9$ix5^lVG~kX{erc^Dpr(gNV5o3 z?)C$IkXb4+v7%NZkXDU9@SyQ^o0hpB@yU!{=oMz~O%u*RfeD{Eg_yZkd?0JObvSOu zO7vOOVv&Vkv#WMZkDHU*Nb6y$ADHn?FA6M{i$}PB2RU*6a;n{&l?Q96G_dAI`bZ3I zAt7;pKV3bg23ibU;KTv}3;-0T{1V;Y=9<<%T42U(i>3x>3TFk>$WJYE)h#m>HefWp zK%l`1vA<Vv=0_ofpwq4%LufLFWRzw9a>pb6u5$|LlrZ*4 zrC@aEH{tRK2CEv&xvO+1ltzEQl#5gHhT1Na>A;i zIOg7lpoj7Q80;Mz#}$dDU|WmUJb@ULwOdEdrwGK&4wa?6WHWEMS7~4;bjJPOG!V*8 zpFpJ z6Ri@lGIa2ob$|_SpS%I1PXf+1XPs8FX1JJV;upz4ei7^mm1%s{N61+hl#ZRBs&j-sb zpDnc)K|8RO1b|c3)wkt<>3N)FPcFrF>k>Zvg$NqT1d)D(`|0I1?ew>4bqBJmDh-m13(5+d7=0EpDx+m|NUcS-m7s+VwF9(ct zx)+NE>!0jLtDLk5+M}yj@F?y{Wk8fR7fbl7qeh1BHjn@$y`a8PsC^v9xAedyU2n^V zSMvK{M5NZU2syjDTNHy)mQ85s%Ho8SyTuZ+im3o*dHQL!+#|rr$^w#mip=?tv~7`+ z`FL;nt8mqE@Lv!?TgLJkx}#)~zs!s6t{`hd!>mL%b$Mg-P?+Wa@lfig8Kl<6g1K!^ zSPNVy6I52$9w`S8;M^bJs&mGDhBqyAO~+@iAn^Uq6%p&Cc{fBoaOQPGysgzTo2Rkr z5hZdVW`M1+Bi6gj4wPf3Vi0+t0lPQ+4M?>(%Hf~A$d;o5sF7S4#;Nv&nw3&95dOT( zV(KaViG-i)xp*S7wxFzpyPT^)^Y9=FcnMne5?=-ETZ!{bVEOSA%uC)Z&^YOXeD?+n z?&~-QSTsGK0WE+@NQ?Hz=#bOI32-X074lvKql+?SOcK$k+|9b0C|sti@^E?9%hiwj z(S$rgI(eOzn_5+h=0Jr|J5DPaTq41zHr)D!sw>KhEFCpUFV;}ZHOS9FR$k+M(bTq+ zXt;vvSYo{Uik|>Ne@4N)#c2@?0wP`hu5J>St z_M?0|lBt4Ktza>*;Wj?F3>b6s!DJ-NkYz1(PA?1AwoZ(WCpd%Qm1)YYI!+R3?k+!| zuB;*s=Xzk|x$mHi!KZ{BN%gRIz02%6ssol&dUHR~f;*;aP@O-7FP2F4h!#{!(NyKd z>SK|R%ei?3lsGQt**QoGGBmefOh3d-@f7?_R7lrBNHn8l$(eC-db}hrMsj)9LUi}d znj#lb(b4Lun8GK(`jlSd27UmAiJ(hS2T!NPH17~+TiX3!?R|G#lj*)ED(WyQDmsIR zU_n4;5D-+PTLA%yfb_0(DGJg;Q)EVG=tV$~paMafC?H4;=uv7wx`YyyCV?0P0+Ntq ze@~n_bI#to=gywJd-r_ybMudWfF$qpzEAm;ZwY)c-JEb=X|KDcyrhGEYPyHo%IwSZ zij*xCydwrcgR2qB$?(+`?jD(|vw>C%bs`<>)Pt3Jny{p$dCB=N{^85oa<-nc=9>PJ z$7IB2OEYScJ6ayiYp0{s8>=pWvjxr`J(w{MN6^qvpQ?nVX7z5rxAw%+gN_`5BtdTZ zHJ(!06t|V0Ll&6jAeFl%sp9dgz(MLQKEvL5p9(lxQt+X@f@0nq5kQ8q@03G!kQWcI zBnA=B{rXuSM2g?*GKf&^m~G|dFR4XWxpgSse(Dva2Cs0M;l42-73Sy08}1XY0U)mr z;k=1>R%wu9?a18WoSN1E8UFppVj?)G)TXwZ+I0kkznm2+rZn+W#WPwbCql&y%Trc* zPq<;9`(7@9qPr^ z8|xl2DPV z`JnfjRzuu4!g=P#cg{Kf#a}0K2zDQOum&~$BUSj369Ki5C(OeJ{FoAXR}p$0zHI@v zUFt3&&|YZl?~aPWs3;hQN;H3DMtzA*TI1bq0HXn|ZH6SN_$+kb!oEYAA4KItZbTJ ztQ+&u4V!#6a;bAH^Em=935e(6=ISfql7(7(!M=Z>Y#N$@4ZN%5L^!Y%y$ zW{s66SRjT@Pu3!Ko6*(b@6gk`{pRbnHXA3IAL{>_I)KqDC#DW;zYhe+?$AbN=qrQHTqw5O(tW zvorIab*{p1gQ;Qty9d$#CI$r{C!mplrnX$ue^SyD+<@roTy+LnΝuERf$R!bSE% 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 literal 0 HcmV?d00001 diff --git a/docs/pictures/checkactivityv2.png b/docs/pictures/checkactivityv2.png new file mode 100644 index 0000000000000000000000000000000000000000..af0cd3120942cf77ca1be2b62300c16841475fca GIT binary patch literal 45894 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 literal 0 HcmV?d00001 diff --git a/docs/pictures/checktime.png b/docs/pictures/checktime.png new file mode 100644 index 0000000000000000000000000000000000000000..b3350f2fe3541e55ea47af395baeb71baeb43a8a GIT binary patch literal 66582 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

if*@bUKVJ98B9#j(`}!CL^wmqX#s}d;B)7b_Y=Z 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 literal 0 HcmV?d00001 diff --git a/docs/pictures/continueActivity.png b/docs/pictures/continueActivity.png new file mode 100644 index 0000000000000000000000000000000000000000..4142a34ced4b8b7e64866d5868e639c194d5e863 GIT binary patch literal 26649 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 Date: Fri, 10 Apr 2020 22:45:04 +0800 Subject: [PATCH 333/415] Updated DG slightly --- docs/DeveloperGuide.md | 58 ++++++++++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 16 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index ec16149a1..aa3ac7da5 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -246,11 +246,34 @@ Additionally, the user can specify a specific week of month by including a date * List activities within a time frame: `list DATE1 DATE2`, where both `DATE1` and `DATE2` are in either `yyyy-MM-dd` or `dd/MM/yyyy` format -### 3.7 Find Feature -This command accepts a keyword and searches the activity list for activities with names that contain the keyword. +### 3.7 Find & Filter Features -#### 3.7.1 Current Implementation -* This feature is called by the user when the `find` command is entered into the command line. The string following the command is the keyword to match activity names to. +#### Find Feature +This command accepts keyword(s) and searches either the entire activity list or the last shown list for activities with +names containing each keyword. + +#### Filter Feature +This feature accepts space-separated keyword(s) to search either the entire list or the last shown list +for activities with tags matching each keyword. The keywords should be an exact-match with the tag names. + + +#### 3.7.1 Design Considerations +As the `find` and `filter` commands are important for the user to analyse and eventually graph time-spent on each +activity. The user should be allowed to query for all useful combinations of activities in the activity list. +This entails: +* The user should be allowed to match for multiple keywords at once. +* The user should be allowed to exclude certain activities by limiting his search to a previously shown list as + opposed to the entire activity list. + (chaining `list`, `find`, and `filter` commands). + + + + +#### 3.7.2a Current Implementation for Find +* This feature is called by the user when the `find` command is entered into the command line. +The string following the command are the parameters: + * `-s` flag indicates that the searching should be limited to activities previously shown to the user. + * The remaining parameters are a string of keywords separated by ` / `. * The Parser will create a FindCommand object. * The FindCommand will invoke its own `executeCommand()` method. * The Parser's `lastShownList` will be cleared. @@ -260,14 +283,11 @@ This command accepts a keyword and searches the activity list for activities wit * If `lastShownList` is not empty, it will print the matching activities. * Else, it will respond to the user that there are no tasks which match the given keyword. - -![find seq diagram](https://imgur.com/Icg5rdB.png) - -### 3.8 Filter Feature -This feature accepts multiple space-separated keywords to search for activities with tags matching each keyword. - -#### 3.8.1 Current Implementation -* This feature is called by the user when the `filter` command is entered into the command line. The space separated strings following the command are the keywords to match activity tags with. +#### 3.7.2b Current Implementation for Filter +* This feature is called by the user when the `filter` command is entered into the command line. The string following +command contains the parameters: + * `-s` flag indicates that the searching should be limited to activities previously shown to the user. + * The remaining parameters are a string of keywords are space-separated. * The Parser will create a FilterCommand object. * The FindCommand will invoke its own `executeCommand()` method. * The Parser's `lastShownList` will be cleared. @@ -278,13 +298,19 @@ This feature accepts multiple space-separated keywords to search for activities * If `lastShownList` is not empty, it will print the matching activities. * Else, it will respond to the user that there are no tasks which match the given keyword. -![filter seq diagram](https://imgur.com/hybT3R9.png) -### 3.9 Graph Feature +#### 3.7.3 Additional features (Proposed) +Developers may include the feature allowing users users to chain multiple queries and multiple commands +in a single user input. Possibly "pipe-lining" the output of one query into the next query with the pipe symbol `|`. + +**For example:** +* `list week | find -s KEYWORD | filter -s TAGNAME` + +### 3.8 Graph Feature This feature gives the user a visual representation of their activity duration and activity goals. Graph can be used along with `list`, `find` and `filter` to sieve out the data to be graphed. -#### 3.9.1 Current Implementation +#### 3.8.1 Current Implementation ![graph seq diagram](./pictures/graph.png) * This feature is called by the user when the `graph` command is entered into the command line. The user will then have to specify what he would like to graph (goals progress bar / tag duration / activity duration). * The Parser will create a GraphCommand object. @@ -308,7 +334,7 @@ This displays a bar graph of the durations of each activity in the `lastShownLis * If the user indicated `activities`, `GraphCommand` will call it's own `graphDuration` method. * `graphDuration` calls `printActivityGraph` of the Ui class and passes the `interval` parameter, which is how many minutes each point in the graph represents. -#### 3.9.2 Additional features +#### 3.8.2 Additional features As graph gets it's data based on the `lastShownList`, users can pair the `graph` command with `find`, `filter`, and `list` to sieve out the activities to be graphed. From 8ae17c0d8d074d4a3b7a9f37e6daf4de41a69d48 Mon Sep 17 00:00:00 2001 From: btricec Date: Fri, 10 Apr 2020 23:12:28 +0800 Subject: [PATCH 334/415] Add command diagram to DG --- docs/DeveloperGuide.md | 5 +++++ docs/pictures/Commands.png | Bin 0 -> 205353 bytes 2 files changed, 5 insertions(+) create mode 100644 docs/pictures/Commands.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index f6435ce09..59e437c33 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -62,6 +62,11 @@ ![image_info](./pictures/ClassDiagram.png) _Fig 2.1. Class diagram of the Jikan program_ +![image_info](./pictures/Commands.png) +_Fig 2.2. Commands of Jikan (private methods omittedd)_ + +All the commands inherit from the abstract `Command` class. Each command has a protected `parameters` attribute from it's Parent class `command` and an overridden method `executeCommand` which is called in `main` to execute the relevant command. + ## 3. Implementation diff --git a/docs/pictures/Commands.png b/docs/pictures/Commands.png new file mode 100644 index 0000000000000000000000000000000000000000..59f5a2a43e580c34ab222b8986b81ae54f8ff4a4 GIT binary patch literal 205353 zcmeFZcT`mAw=G)T+G-mxXM!ySiUCwW5CpVUphQ4G$w^TVk(>l1*alj~LJE|qh-68U zb5O(*5Ro8AR>@hign~Ce@VxiV8E3pd?zs1j@$Psuzh6m(U3-7u3Ukdh*S>dFL1xwR zZObVX$|{=dNo5LU$yW;HkF(2`;F+weK^AyeY;;`yIE9kvxnkzRANYHRfvmDTh2qFd zp}5_qP^R#dTNj05dw@de(Wg+v{3w*o7C~7`NAbdvi*hn2DRbn%=ed#Ic;-(FSq*Cn zWlJFW-)}VATRwPlsSQp3)Y7)a%h~oUQF}S$jw4cNCy$@IUfbjMZHHT?;yP(RdNJ^XLAyR^JNe*aBk)Fs{mU2s&IpT- z=a+s>j$A!;>)KL$jH10q+^+9YwMgYZZQCiA^e$Wop%rMjhT=VL75}a!d$%R^-NWs> zXpX&c=_xkdmDk)CQ65z{HpV&)WXdo`8(L;nj~qEt$Mz@Q`d(Ce{=BOV%0wtzj<}45 za{2cQ)@Qr+z@8Um2$s@(0?!fm|cr^I!*AwK)9k=E$n*0+#Ti@oaCXW_tv$C_t zW~T?`7y~&Y3hkYpM&eZR!m%e_A)77qb*fcq1-a`sI)XyLBkK9$jfc-y^ed! zVQV{tQ&UroJqP>yZGCdD4_*9RTPw~`lA*IJIXGm_4h+tI?At3KAVMp`*NpsZ%(T90 zW~S=woZHje%VArItxPqk4Y_>Le#4NtL4Pezlhf9shXBkfw+HEx7@mX7trBm~r|GbMk1y@f^e zg^ip$d-jplQ`IJRDVN4X^V)cwscuEr0IM6iy3fSK#f4pFt}~B#8|00A6o-WMS1vK3eVRi+Gevf;Wo}}wn=U?Zz}BO}J--}Rzomc6Z^YNW z-nWJ|ey*wMc^MO5DKXL5Dw}88n4zSjqa)@rlR?Xab(jo&FUlHvw|%TD)H8spg2=Ep zA?Jm8K1&sD^n$jyuRgWZYYXwk(XY2w2QU+I$2IFSVwLR4bz&8%-FT)^lio?BiTxvd<-7Pq{_Rw8plh zy}kR#w?fU7D_&H-Eh}GUXE)?TWM*pMqe9I5(MmZiq2SP5yWVU#wL4*MDuH9{2RV^8 zEf<$OJ6H}*wPt8a|3H)sm-D$=ZR>~lKv`7A@URt!l#BLj{j=Le%!Dp;idr0lu?vTG z!TRkdrS!2p6brBUb#haBuy#|Z+Hlva*V6Jlo{jYxmZ2^)tz0p$UL7!IgKa z(pu(bCxneYvcqP{dNSJBj~jaO2nZ+!yUu3byMT4%J+fuxlJn~7U81wEmvU9pImCUu zy+fZprQ%ED&&)U@9~N9;-rywH8h=F~ca-5W>>a$)IO|PL&e2?KI^CGB zN+ZiA`d8e_otvGW>Ps$XFP{(*Zhv!U1&8I);rHCUH$OKw$G>^=x5STvMUIp0zP4Wr ze#@QeiJ7W(WvQ|1f?579KMT2fZZ74_cy7FT(M>mQe?MF}wg5ieRUNHTpYNJajZRLk zVqd@f&WALK<94v8fJ3phI#D=m?$7TJrmCb^D(BCg3wz2|#W_+LE;km+#gdg`bt^8_ zDV&eX(udZOFF6&a~)H2{Q1p&DZ9M&c%MeuQ*pJM$Bro;9lAY`JE6dXsbQ2Xzrw_wL#ylWo^el3`u45ppAb%Tj#Cy^K#> zmS1Zu@@bou-FWowMK_PVtI_H0?ye{m$Pcp1&9$j~_+&m0?A>TWk`E>0`%$tmxFq)8 zSOkIN-n$fQJhlpwoQ2J|o_QdU=ahPB7 zWr8%rZE`eXC1vBQL>iyNqJ4E8i(^X->t0>B#m#qkL#>``ZmT8CgL~32?t!lvOEfz~ zyY-l(lM^EIT3k_YfJwY%Y`U+nZzMiSbDf)THKz~a%;R;kg^)au)@6oGD_)!uyYcfC z=k>2QAKWKNl#+CFF*_dI_R@uQz9GSnwfpK_MF6F@)gx$xn#5;HkByBnrq<~`e*9R> zy2FEwOEUK5%RMSJPxfmG*$-%wRD!f{)!f`Z$fPCD`Gjt0iDXs&@wxo?)c;N(lYBn5%avLDTg`MMA`U@QxDFms8kIKQwOE&2ZHL%kS!4V;mB3- z4Tko(IQak}8r;`5R$lG=`EV?apwY*uq@+p@QSEHIxcJPDZE@O}mDJf-YLl;?OEhbG z!sKJnk*(Xk<{^jg`h~2jma^R}32~yNWjJRj0SO1RlB{pPQ@0 z>B+R5ap!W08W=ERCCrWGvrl`kw`GiyD1P!YvhrxXNrHc;S$6+nnlerjP$d$H$nTPx zf&$&(b|Z&4tExSa1*WH{qU18k-h zmEP>wyWe@FOvEsYnUj-~())Bj(#!P3pl`Lvo4$A3&25fO2+R!&(4)6W&COT~4)1N! zH0vx6w(oOof2?*+S9c&|7N)|>Lq~MkubuJf;NSglnQAUp1y{I4Gb4w;>3h)w5<5nI zlJFQjHyPa9RS`NBlRp*n7tbfd4}Kv=&m5#jI?ENa*|?-dW+mZf`Y8qr#;Ig9^K)pA zfB={BuzXM8-9$u3IbZ(ARMV!c&mJD$Q|r{+S98_C)w;G^Fw$$4XVfI<4PKYT`XRmW zPV$aD{2~ss*O=}n0AQ@6`FiUrX3B&1_IAGBx2xKx`c0ZO5*Ob(-v1@BFfl(eQl^#Z zSqo$8&M@p1Cb9FGV-Fv5)}~5{UnlDvjOYYsuHDQ}%l$f8K0vZ?AEkT0;OmwPHy>P< zuMj<}932_SWVf%97vbBri`kdVIT48+*Sj%v=VGFtS?*ZPg*badsX@5=C-a>#+1XA7 zozr{mah+%WxF>h_S1w;b=G8B5ZKg=`{>PduKTS4%{^!5I*pt7r{l_bm_d6D1=KK@K zmMq}cg;x*#JHM<8e>^%){krfk{J-1El4860zuYRKv$M4Z^XKxY-5WTrIr2if>xadF(t%D2%Z5W=A<}YnfdXd8^yrHQZmxKRo!l8Rkgj)o{0s z%NBpgyMKSV^cxau^n0|1%-5Oj~LHGf)Mp2rwnwszM$Vf5= zo3tCSw8T_bC?jks*NwACT&Isjz?kNyUFXcpo=Irov$a2mT6t*j@F{Pp$@NbqoDQ4T zVbRXX%Rh9u<~&P{e);mWR@ya7_PH7@^KRs2Ue4)60`rb^qAHQkAwc-%qNVIidt2LX z;_52nyA(q*fwFwI^j%h;lkV%h(H-tPI)Tixe90}=yWL|v{R7#9c|KVhz;E|@AFJuo zXjd-weIFFWHAsuk7iW|$g3YdT&dIsg>XK5JZEbB)3$80%oQ|z%avIF#eZ67XVw;~o zE}TDq-oKW>=*x=(FPA>q|MKNaWq{&3H6^7G0`DGd+Fyxe!Op~XMfeOMCilRZ30?~g zlA83Es=(PRm$c+KB-afL4A@ayV);b&qui9;J`w6E`BMLY-ysPjD-V)Ms>`&@bHk7A zc*NMS80YGixM0y+QsKOp#+8f5AOxw2?7SUJmjU3&=hpUy1Kb}K=xma&{9U} z+<1dILHZo9h+yY&|2p%BCzF{!e^s}9oioFw0t7BbrKi`f4c+*Fb$xnFt`Y%s>u>HU zKc`pXlq=}JoRDf_({MIO%(mp3fcmQfYRkO03N^4E{v_}S=Ng~9>*MUG;@mkD&Lzdg z6{Fo%WwWz2ih+VgbZR$@!M0B?=elM6aQRblBi)IDMXS5u@71Zbx-mN0cE+es=mz=7 zK0YJxnr?v91D9K{ZyiVWhSXM6To`Y%t<|B|HYCiWiFb^k2LdEYP~umP3m4bd*Rz|1 zt$HhI+m77$?K;21sDh%R;%TdLmk+Mf=5uAS(T0j=d3*!;?H)+{w!4^G%qUH_vA6GS zb{dqglk&T>VzU^ho-1pNk2y0UHJ4n+zk9dEQIRjg#QO`b6fK*t@D1)td>iwe`{~Kz zRD(O?tPy%;7=o|IKC9^+p{GjwYupt~G864PxYAc*a?`TK)t^6ygPdRnSZ?kCydOw6 zL+K?z(;??wAS*K;L<{_euoQm%$jie0=R8pf)B}olNM{unCx-+ax_m#>j6|+qK@Z2cnkK+S&LQcag}i#O9RSG2 znRl&S2L8*(ie$4Ui?OZp09JjTz+p}xe zt_EM<8WiX$S1NWgZSzngl6b1?*v*qHBLU<^qnVH0@l-c zsAw}|N;-hBJ)5=jSnP{*I*)ap*=&$itJ#_A`*`5Ght97WY{8sDH*w?us|`(T#mR(n zsGOa560#SRt^X6U_Rjg5fBtZkOJ^0*aLL-4z!~3%e!4NW?VD_^GPUd2HZHt@!oM9R z=(ZxwX~K-znwEBW@`j{*kf;*FW@^+pP9s@5Gc)u5{^p41iz(VZ=VMg;=cwHX`G-9R z^QH$L>=9>Yi%CuvZ17$7^-!RYF@wP2#zt*Y?bop_r5yO1Rirm_Cmv=88&UvkM4mVJhVa!Vob ziC_Kr@z-wUogE!}Ha#$&9`ARY8Dft8Z1pt3zj@cD8E-JV=8Vu$O{L<`{>Ds| zMD;UES96{dWv@Z*36pRd?`oN2wIn-dQj)q_X8T*%i!+RZoewwsg)dm-RM}6gSbQ+2 z@Sz62IAbTFN41q3^0uI^JwXH5X%xo&kq zvu|(iFkGakUM+$`Ja@wR~mRqM1Yne{7)j2Q;XO+?iw#O zQz%t^f8*ZK)pI{q^D*V09X-+z@;hb8ntLbDsj5ck%?|rg8}OY6_IPCJ1_FqD{`{Hn zK6Pw=P^5G5H)~99&NjcC*=l(zREa~(=KYKg|DHXS4@H`<(1#{(3{T!z?p`?Tn9F+d z*xUPr(Mq@9>bx!IP#tY%P0Y=<5YAYC4Je;#R9@FBT1F0E`|^C%_QRK^t?;e!R|xV` zbe&Rp$R#D&5aO{sl=nA#z%NqrBL9=K_#tkVt|b|)$Vj>R`DF^z#?G#!b?ANX*i~$> zX1bY9TH%rd%RvXu`}ze6#l@&G!?KQz|!cEee!{`q4?62~UD77c{Q=gdZz>3+mFWl{FS#iDZiHdUcWAAP%C zare4=gmaCHi^Db^X5Ikb!k9O{n0V&-gt@7FJu&d*;2Jy6=Y- z0y+A5zAI(2_;zpKzCGFb2*vHU95`Z0d3k;p-)>;b1O|g~P4DBYr((9J!5Yr$IZyYe zGs1Y}o)Fr%*iM~t_v_nx>xoSabR|1}y}1-8eBdf*!Wa;(749slxz4!{cIt&zeP0er zutuxsM_(iMCUZO)0wvxXDaDFL!izz^JP(2oHBud0@BPE`jfiB9w?$xq59^&>4e|hK z?~*w6`}ReNzx~Yp_))=mcCz#8wQD{tgSCK3gsaGGGQ&dm*CorCnwoa}EGapy<2?46 z1o{a1zz8fi)~Sn-#6sK71K-||44$+i{LvpPHbp&uzN5i+xwajUupui6Y{8p1Z?3u9 z6cZK!#aGcII>(hJk?slZeT4txE7Z`LhP%DRMMqINf!=eL_#e_j42 zU+?SiwpDW-(o@17qd()Ru8;aDhrW^em4^n%%6;hgi5sDUhbj3Jxr5G%ckbMI852`= zVzopVBHQj=k>-zV&CKFe<21uT)kkGzX=M+I2T=`1(=D@Ar0{ zQ&ZcO-msrWKSayB5KBsRD&LxA9{1WB&d$JR6Q4PBY<()_s@vi`p_5-MLMeF6CnBP@ zl#Tr?e48XLuGt^%^O3%nF;%SS@&d&;t&&hz{T7s!i{@NzmYN971a9xHJy6-2&G5Lt z)}rRAHMi~U4MPtgUdqks*^2_O!_v}n z=#g$M)&MD*|MDD|$Tqud_l+kIW6WJfw!@9o3h%#OckiT4PcEU6$u|_rm-$W~#p3lmn#hRH9uUjaj(@=4>#Zn>UQzYE^}9Aa zly0Axwrwy?kAC&a;sdYdA-+uyqC-MnALTqfycZ!2Ud3n|nM8w*B`c6WlSGXU3p=@2 zHFnGJB)8YUgsb@?(zv)WS|##>@VRs6v>D~6sO!AK){gi;V7A^bx(N5+{buaS#bb=R zuu$PH!A==Ae*dh)W5FNDtDmRFddJ3U_4LjiLE;9|0Ps7jr4>lRFW-jc(TRyly|oFo zC-dfIl>4Ik^Wk)m7>Hq6Kb>RKC4<5ST!cN6Akf99S)m z&Jns+2hA=rkS^x#nTve1C7St)1@_53BLojZ@%X1<8!6EGCacL`}d1?3NHYb zobCy<8zj}IN89Om15akC_&~-9LB(0% zIdnd?%5LHvK$w_T`?RjVcN^WXGj*JvGU-irfo7TQn?}qlrbH~hzrE+}sOa0fmpO1Jf`Y*GU zZqWCqsM9*Dp6cj5yLZbv=`d1mOj~jNXmHLS1m?T7Vvtb-Tw$(7IsS zrlqDv$Htxkr3cO#hykw1!TqG~-YGc)gV1f;x2rVE^aj<;^(SieCW96h<_Wp#nF_=W zNW6{y}P5V+g|&noMD|B|bBh81UC18xA#mL_Tx zTqYnO;GB}uH+3yDG&TU(ta56^e8&cNOt!e?=BdSLw*R!(cWrra|9*ut$3U{bDXdz z+P|ZZLjO2}ko5S;lK^HznyJc8uSZl;lIbR>DeJvKkT{|{I592%_r7)aMAwOrxA{-3ooGh5j1sp_>ed|BG{p6>{p5l%MtYobM}f*z4`Z- zAtA?I@>`TP<4p*(vV2k-misH|-#ht6Ne0jl^#SiV!j^xzOx72y4f|y|tGCzT95R1L zzIgHXsZ*!ux9j!$g1Pfsf)D-E`$Ws^U;_sS#|eHlhFQ*#G_w`7vdoKUba)aagPi*X z#d{q~N=n$P9>XsDvgpiK-bqz}y{s%Te3SoF@+`;oqnymnb3M~Ry9Sd>($$OKiZov@ zq*fuC0*uL@QT_g*5>XMQigk_zF5zXIR{H6l?Uq+vgX5w#BG33=9Ov03P09g}l?(Lr zHAbX!iej=~4qM|f6=n2~3$CfDss>aX&z~Jj*tq--G9K|#^e+Kb<8*WD&lFt=ZmvMd zfyfyVi)dPKtwH7$Y7YNPZ$a5U2ce0a=&#^9-4z2K#os#j$D0*&z8&r_Gcwd)>wof@ zyTvtAKxLv&Ce^luw12GobnKgi+eUV+`;+-^1S&}H#eu>mPok4&BVsY)e z_N%_=o$5_cL#&73r>wIbo@(!LB{^Ao7eDFy^a!oH_r7zayGl{Y_N@cR!QytSZZ8>5 zCA3{_cq%mCO15LbDhOF z+c;p50wNkC3^*mAvya;YS@)c#=F5l(UZx3`Q{O?E7p*8}4YSd#@iF02y2Me1XguCz z*I-JwHf>1jXMFxc7Akhq&FD%0Zber=3+? zBMgFjDkRsH+&{?aDK4#5m(b)Qe=E_~>*z&!hJnyUEiJA5IZotX0vuobpIawGnUUm|T&_U_qZMGfp5YzHg3C%8Nk>AZAsBJi!Mj?PoFe3soLYu0Cs zb+@ERSucs7(-Zit3sBCB>WpHOZ_u+^!rUt> zUmz)6Y09!aBTs_WrLFVOwt&}RTbBNTD`KNn@~3q7hJm_F;Asm&j!nOYKCZYaOh*!i$`ZNv8a5XwdN z$)yj3JRQqBxpOVkmaX0T@EQOT_?*P-&(;WjsmV6)-(*TifXEnKkc}O#5wfvU{oO2z zqrR9MiQ#IcUDB>Wr->$e4$l)IXHO4bsZTMc-_{?N-6`(GDBR{CyrDQW_pbP9Q_+L< z3HvuJ=kt;crhEi#U zQ}1TK$oSDdDmm5EU#lGSK1bFFyzuv^7v5uce=(R8Kza3$(Ov6AJRrgo&uh zIBoRYsz0=pz@Og_V$Yx|I9#q#%qC~Gv$NGxDlaN)%kFn5Pi1s+rw6hPC4}UTa@MAq zHju~)h=P)zfSk_IiYQQm+=&pK)Pe63lbD0d^YFYE;OBA?C>$34^bskc914QyoSMeBm zulE?g-8hjy=ghRONeM10D&pf_Gp*HX9@STsJ9R@+@CCn)^Db9i(2@@2^$iVW??2o0 z=7!7NO;1k`%o>|!X{KJ?Sfxlx67B-7OX7Hhlrl+CDc!nLp{Ug|c~ec#=a}<4I;PUS z)OCM?*thQZDQr^H1=7T~+E+ViSLvpG>iTIdF4Lx1Nq~s{=3K29wFL69vMCMd?+!52 z0L7A%Rp7B9adBlH%E{|)k5fyKw>JXG+YdIUaK})Mc7D6HS~BDL7Wi(aYP7(Sk>p_3 z8K;SX^B^&sbDhRSTt`HBkEV{LiP(uT$hrL%Yv zxH?BBZIB22nI<){2QN3YrfTIn+UAEY74UI(&RhY**r#GYUhdv9s0Mdhs6Rj`Vt==k+!@J`y-B zA%8Z@Ku0*Z+~|9-lxrRUEj)~rr^pMvs1ZA^C)CD(1N5tvocU46yCh~H-L&EG*VH<1 zhswdokE4#cd-(Vc4vwJ&PBpIL-LISTMVr(<0m3Hi2?BU2^gDq8`L7XtKF6rVL`BKQ zsK!AbH&)wH{gOBXztln}c+q<-Y*o!F_lAB|kajaJ`3Cu)|1!7DAdd7As^v(Bkq&=@ zI5s;PK;?l@d+-8;v-Gh>UJZ{GNxxQi2;ncBT?-bB5=Ms64gg@|@gb2e_v}UG_o3@k z@(OIbq9wnwg zHRz*-f7{K^PjY4JNavX2c@-7GwnKpI(G3=&L5J!;O77f0X)Wp3w$>J%Q2GSm-b)aA zsE@3xRfgXeO%LYl@$m4_FKL4KZ55N?^d#uhLv?5AeeokSEz%7>F1i803q=vVJfXa^ zijee(e&v>?H8#FP71*)SwZms@zEY-v@dB zTDDTh;!G~+t+*JrBd=mBBq+X%OurRv!+=EtLSQC#LvEjXG>m|&gwR_*fx|V zGHY9AZ(fv(?|t2KAd|EI;J6yoOZM$rSJ%to$xzY>Dg(H^p}s(Q=)bMHcZ@AVAw+`B zzPLqNb>J(Syhc&nUR%ZdFHf6toIlub?Jwn}6eS4HeK zTwdZeJmC-)qU*MI^M4^K*B$tS06dF(Af8;-FX!|$DqtIV{fz6XvWX~@mnnXB#{cMG zQBZlm-9+G;#8EY0R&H9p=+s`LjP})?n$zNjyAu>$Ttsb6f=?5YsCI!AOLd)d5xn1r zFwCXAvs70ERI}zQ{hKg~zU%$^!4tDR)=^{E4+gh~+<13aE5DFWL}RDdS!gm0#H#o5 zOwJc>e=HPk6xq^#yWaVLF2d0<%bMQk$>cC8L6$Ljf4MGlA7Qx15RLaW_+BrXsw;Qt zQ0KD9sB)X_*SF_jIM(T&8W#d&d!E3v-;-iCK%c9kW|l z4a##pm=f^6p>y`!O!-_jgl0Trake6jNwG>=yE$FWdZqhV$Q%XQm zYWNFnq0Y_uKkwA#bw>myaS*U$LHjl3kZRc~O{)Y-_U}In+RcC^-;4%1G$H@xeWY77 zKMDby0ND=3!-0%KEV;#SnG@ND18#ZvOV5R_jM|PhkEmca%KQ$VK<0{-T1@d(0*(Jm z>(6Xyo1f4iW~P1U!x$dil={m=TB>s=nq$z`z%OPZcA)`T;0H;=D0B>l;!uX*x-QPA zJ?Ye$nHxj~4F<$eUX)VMjwXjRY@!=Pv4;yf#062zc>#sTpOcf5FQcO?R1_t`e+^I+ zjzbfEnt{f8IK~rJHlQ0G7Q~*l17C2!?nnP-JQ|!r7YN4 z#_uys*BP0#6L^wBS-EyWEnBcm4bjyO;fe?se~nbEH3K_koK9?!!u?CFx#b%Q&%l%h z@|>I3z4;5Gc<6UW1YO!TuYTK7w*bTomOU{mp+$tuiwe9R{y)7j6+mf)dylp(1M4eA~X@{jZL_^z)E22aAOW z3HyJ$oGZIk&Kz1rA{LmPc>)gKv-M*&Lz*VW2{kIzuob!4Jfby@r*c|!qZLF`ZAK4WffUgG-X-Me=# z!Sg5Xv2x*n0f%@w3JeCk4%7t zegqFp9c%hcaToi-ZUh8Ims-Mnt$n3M&b8UL*y_9wwhDEhJF zY{=*SLwyM*GM)rt_-80?Dmz2P~R7E z{pdi~bI?0J+qP|^(g2CM^G2ZNiGmCtoq%&_yHJY<=au~PB-GILB#!SJ1%PPFPbw*` zMFj0)0w&38ffCNj@<>m-mHMq_)kZSiWcmFzsC$S40Cf4AtV;KzgsY2xqx9NwHFbVT zGUg%IyOfhVLqHUt*uQ^2omFw=93Bnl!n^+6zAv81<*Lm{K_QepM=n`O$*YdDnDq5# zM#>}mR^R!1zI8%?x^~6^qLz7dexdJ((vr>sxesQXF=eI?(JiC2y~HkqEcxB}J^KLG zjtJ#wOK6PR-p}Z?f5xyKq08y7z)N3cO^x}+RmH@_?CqcZ=bwM}Uc6oP`qol;_mFV( zOmVuQkVZ;?=b$NryG7|GGb1ZWDdAvKMW;ETz#KcAk$>=zC z{U|WF>gnOc{9by|#jIAkxRCRd4QRmRIcQxVTCn%2YMCCvo5enw6kX0WFZC5rq_Oj^ z`x6Rk)nJ#YXwqV%5#g~rY4sl!tdGoE%-4@GObnzhgm5Pcb5!p|O1_q5t5I$sni8Mxu z3>@<-XSi5HOs>^a96K}nQ|pC%OT#ThWA#`)YExqgu5qUxYzlwNJ(lVYbxcoJ*C+79 zRW1pS?#@XtAqhx9PaI!T<}WCdY*?11&2^aC=!t#W5`b<84sXgHxwjeMhtRB0Ggus}sC=nraSngOO zdqkQskkQH}b4`_DiRLQrpO-u@Ob)lx+aBfabNZdXss0E|ksLHW{_vQ6$A_&WIpv*l zPLVF?T|s#dSV>`a8*M_4F2%->Exj6=N z=-mqBw>mq~L`F zcZd;HxI)gpul|$rwenSZHnDjymS>W{SI2~h^Mvn*gyJ(;Dl>X={b@9}lwEduS)@3O zw*?lp4iW7Sh6No?5AWA$U}tkjtB@DY2a>t!-7dWcxw%(OOsb&hio}_9L)&EimVa!H zV<%)aSOB^ef*euj;!^>vnyIYu=;&X{iGQ13#xNM`;?xu0D8*mi-C`ZPU8gSr9uM<+ z-~JP-9)#pDsrO{6L$FwJ>gyU;l%n1%eC7^dH zGx;BlOXu-ABg47=^p<9G{}r40VHg)my2N9+E5V%LaF)+t8VCXVOdVFOS~Wb)qGy?0 zyLRrxiCZ{wD+`iobh24_grR|a(9jiZfu^RWa*32p*P}YPGyUU-%1UMCwBbXsuE8Ld zGjCt5Q9>XtV)90w4_%E?@D+1lp|VuQc)m@4dUb8Y$xtOQNJr|IIcXuyRe$>QbxVb+ zh6Z0kZLi;Oy%pvNllxIeSTLZGNPe4Q?V?=iIqV()TuQ+9Wox*xby_ zt})j%(epOA()6w8ZAZJ5kbBM|TEI1V>y)*%kH(rLw+IhFq0-cWc+>nx!uAoxxlu*K z2Fa|!U%4217{tbN>grLDPrPRj959=ky$#Ns>F2Cj;xA|vAl^;X_9?a(^9P_FRdJOJ zE{|=2dwne~fGcs@RhS>ZRw3}%03HH914pl;4gBVBV?=s2y zDL@EeQ}?INqYdcKx!bNHOlDntbo9aE7=k58qjd&*TUmooNDRGQ4`e}RnafsDE3Q;~ zPy;2Mv!WxBjQrAC;*mO$|AMvoeM2SCFO8VNpkv^mG^%sW42ux3+-NL>LYEkYxdEJv zHw3iMmKaILabc4G(|BI~;E{0+wm#bt)}X6v!35c}_f$e_z6)#1e(7CH-TH5?b(!R< zupw$)PRPWoC#< zeW5LVA{vQid$4r;yM8U5`0J`Bj%F^W$dBj@vzOP2+d*rfJn(!1p`eX6+$;DE^OnL5 zCus5E+r2Iu$?rE#Oo%kJA8w-&+egL_v>ok^3>J$h-S!^Sdd6vy3Qv2k^G}LhOjIwC zoVL-ogOY>ws;6An3^^h5$!ke2z_f;RbFT3#DQ!ysbW5%uS14)=8?;DRP5C5JpP7H@ zjH_vwH@DutUfJb=~FUa5X z`PIz)6swW^L8p1VmJDFhKL(-c{!Ymy=`}-VGdi^qXH108jkg(Ot<@|JU1UO9jn_4% zQ9X2zZog7riU36htwDtgspxC;6=&GoWvHio5%1xDr{CF#U_r}+azkSLivb*@9stCR zmKkz`w~zbJ?5r$y6)TdAw`NLGw#Y$Je4y{r2UI>wCEiKamjpbiWW<{$rz?#cKlDZi z#~HJ`0dSH>X4i_Vqo(A-V`56ZZX~aJ0h#;jKhTZr8}prMipuxGy;U&7RseCD+reH4 z1`jn5{L@M|E=A+08X*#rFkM1U2HCq4DG$B1-?N{oc^tb+Oo8Z;yyp$&XxsQ95 zYJ%>5q%`#WWQNOhYYQ)MNj%aP8Sl=bQ0guRn;o1Sv>t9Tk2XK~L?Xnl>r;r&ICkSo zZw;9pB)l~GURCtA!9i_q%dnJO(|u@lm?Y_T`2^XSr8g)=j%U#(bjWOa#yLVny^AHy zi?zWa=+amuYS*X!E}==X zsFi?;7uS$HjXg=Prmi{J$P=+?q3a(@x+_^(^&ZPVl$D)_&f^GHE?CXhHWg?38GYoY zZ2K4pKaT1tDg6cYW)i&=b;Dz{=@x+9NRYG6_UZBP!|IVwC1?)NaHBa%dViK55)GJ3 zQ9qbq3&4myT*&nSxN6dO8VeSI-=?NnFJYYz=_`128 zSSUe`^C4$<_uJfr63DRnJTxij`k>}So_hw%@@ZwcKnNBJYWXtEph)i zbYZ-&j)=~yMI^i*uNj%VVH}yHopU{rjYBL9xjQW_&ByjKuR>5)M#Bw2Qet1-2S`w^ zr9)(Kh~pm87OuJ@1KPFqp-t$t`y@JUp}&r}AB3%=eIXs&@bFX0El*i8o}A}}wh2#@ z`y`BODY*9j{=~<}uNFUnELNQJQc71aYw(H~P!3;j2HPpf#r-$cH|L#ZDQ@l`nS@xS zC!;$uI-2kD9%%qZbP4>Jr0>|D`1$az;8xPVs7WdFErnFDYz�XcjOMKd6ox4*S7s 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 z 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 Date: Fri, 10 Apr 2020 23:13:48 +0800 Subject: [PATCH 335/415] Remove text example in chaining --- docs/UserGuide.md | 35 ----------------------------------- 1 file changed, 35 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index d2715f138..545806896 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -155,41 +155,6 @@ By using `find` and `filter` commands, the user can reduce clutter and zoom-in t * `filter -s TAGNAME1 TAGNAME2` * `find -s KEYWORD1 / KEYWORD2 / KEYWORD3` -**Sample Use Case:** -If the user wants to see how much time he/she spent studying for quizzes of specific modules this month, he/she can -first `list month`, followed by `find -s 2106 / 1521` and `filter -s quiz`. - -``` -list month ------------------------------------------------------------------------------------------- -Your completed activities: - | Name | Duration | Allocation | Date | Tags -1 | revise 1521 | 00:00:00 | 03:25:34 | 2020-04-28 | [finals] -2 | revise 1521 | 00:00:00 | 06:17:03 | 2020-04-28 | [quiz] -3 | revise 2106 | 00:00:00 | 03:00:00 | 2020-04-02 | [finals] -4 | revise 2106 | 00:00:00 | 01:20:12 | 2020-04-18 | [quiz] -5 | revise ger | 00:00:00 | 02:14:54 | 2020-04-18 | [finals] -6 | revise ger | 00:00:00 | 03:13:14 | 2020-04-19 | [quiz] ------------------------------------------------------------------------------------------- -find -s 2106 / 1521 ------------------------------------------------------------------------------------------- -Here are the matching activities in your list: - - | Name | Duration | Allocation | Date -1 | revise 2106 | 00:00:00 | 03:00:00 | 2020-04-02 | [finals] -2 | revise 2106 | 00:00:00 | 01:20:12 | 2020-04-18 | [quiz] -3 | revise 1521 | 00:00:00 | 03:25:34 | 2020-04-28 | [finals] -4 | revise 1521 | 00:00:00 | 06:17:03 | 2020-04-28 | [quiz] ------------------------------------------------------------------------------------------- -filter -s quiz ------------------------------------------------------------------------------------------- -Here are the matching activities in your list: - - | Name | Duration | Allocation | Date -1 | revise 2106 | 00:00:00 | 01:20:12 | 2020-04-18 | [quiz] -2 | revise 1521 | 00:00:00 | 06:17:03 | 2020-04-28 | [quiz] ------------------------------------------------------------------------------------------- -``` **Example:** If we want to find all CS2106 tutorials, we can first use `filter 2106` to filter out all activities tagged `2106`, then use the find command with the flag, `find -s Tutorial` to get a list of all 2106 Tutorials. ![chain graph activities](./pictures/filter-find_chain.PNG) From bbf1c47308e07cf6e2383280dfff3bdc7dc3d459 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Fri, 10 Apr 2020 23:30:09 +0800 Subject: [PATCH 336/415] Update DG and PPP --- docs/DeveloperGuide.md | 14 ++++++++------ docs/pictures/EditSequenceDiagram.png | Bin 37085 -> 21807 bytes docs/team/nigellenl.md | 20 ++++++++++---------- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index f6435ce09..076934b4c 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -148,7 +148,8 @@ The StorageHandler class functions as a support to the main Storage class, allow The edit feature allows the user to make changes to activities that have been saved in the activity list. This is to allow the user to rectify any mistakes that may have been made during the initial recording of the activity. #### 3.4.1 Current Implementation -The following sequence diagram shows how the edit feature works. +The current implementation of the edit feature allows the user to edit the activity name as well as its allocated time. +The following sequence diagram shows how the edit feature works for editing the activity name. The diagram for the editing of allocated time is omitted as the sequence is relatively similar. ![image_info](./pictures/EditSequenceDiagram.png) The current implementation of the edit feature allows the user to edit only the name parameter of the activity. When the user wants to edit an activity using the edit command, the Parser creates a new EditCommand object. The `executeCommand()` method of the EditCommand object is called and the specified parameters are updated accordingly. @@ -159,12 +160,12 @@ The order of method calls to edit the activity details is as follows if the spec 4. The activity with the updated name is returned to the activityList #### 3.4.2 Additional Implementations -The current implementation of the edit feature only allows the user to edit the activity name. Hence, additional implementations of the edit feature should allow the user to edit other parameters of the activity such as the tags and the start and end dates. +The current implementation of the edit feature only allows the user to edit the activity name and allocated time. Hence, additional implementations of the edit feature could allow the user to edit other parameters of the activity such as the tags and the start and end dates. This will require the implementation of more update methods in the ActivityList class to allow for the changes to be updated in the activityList after it has been edited. #### 3.4.3 Design Considerations -By letting the user edit the name and tags of the activity, it will allow them to correct any mistakes made during the data entry. This ensures that there is an accurate record of activities such as in cases where the user may be trying to record the same activity but has misspelled it, resulting in the program regarding it as a different activity where there would be multiple unnecessary new entries in the activity list, making the analysis of the time spent more tedious and inaccurate. +By letting the user edit the name and allocated time of the activity, it will allow them to correct any mistakes made during the data entry as well as allowing them to update their allocated time for the activity. This ensures that there is an accurate record of activities such as in cases where the user may be trying to record the same activity but has misspelled it, resulting in the program regarding it as a different activity where there would be multiple unnecessary new entries in the activity list, making the analysis of the time spent more tedious and inaccurate. However, by allowing the user to edit the start date and time, there may be potential inaccuracies in the actual activity recording. This is due to the fact that the time recorded in the program is based on the LocalDateTime. By introducing user input, the dates and time may be recorded incorrectly, defeating the purpose of the time tracking program. @@ -325,12 +326,13 @@ Allow users to record their daily activities and track their time usage in a use ### Non-Functional Requirements - -{Give non-functional requirements} +* The program should be usable by a novice who has never used a time management application. +* The program should work on most mainstream OSes. +* The program should be portable to other systems. ### Glossary -* *glossary item* - Definition +* *Mainstream OSes:* Windows, MacOS, Linux ### Instructions for Manual Testing diff --git a/docs/pictures/EditSequenceDiagram.png b/docs/pictures/EditSequenceDiagram.png index d3c9b64b7b68cf122dd5876f2e92b0ce3b8ca339..88e6722a2589dc574737518910887a79a7d616ea 100644 GIT binary patch literal 21807 zcmeIa2{_bm*ElW|lBHC#D@9Q#Thtu|Chzqu{$X{(WudGnHyJ%33? zh6je8qsYkIg~`YkACZws#gdURKTW9Ak|84_chywYy+b0A%FD|e8X9mo-0bYEx3{;5 zh)7sin7+RL&d$#2>S}g&wymvge0==K$jIHhcRM>fH#av;O-)JbKS|@+qz*q)jV9@b z6KM!eLidw!^Q75o(oh1a?HOq-i?r~aw7X5(S|KgBlcvi^L-C}!8q#VniGUXu7uV9# zA`x~;#9h+V2NLoniAW%grjgbsH8eCbGc!pIk4U?l^78Vrv9YAyaMIQ)7z~~rZXxx( zadUIS^``~|1dx6Wkk&?mgM*`^qe-}hoo0{O&rZ1S?yGe!JN>b<-@rcg?%OUkdi%S3`UVDvmseKSFqqxl-SzeL-oAl}pOXXvVS9Uf zW@dI|WNd3|3y;V5_Yc<9)rpFVy1KenS65F?O+SA87>mU^J3FVRr?f%EiD14*M^2i%+1Y1LPD08msinfBogWA={YqurKzczmX@}#u;Ah0AtolKrluAf z7dJ3C2#a|0?R%4+-u<|E_``<}b93`r+d8_sx`u~`KYsc&K0cnDoIE`}{p{H@M@L65 zFR#+lQWy+oWo6ae+&nWgQ(If>@9+Qd<3}GKpE&9_vw&V6F;`JkAbWL`;~wyX=IK2H zS2D75@V&nyO6~#gfI%uZCAB+LGnB^}D9H`U?+22RX{9SE$m>2EUKxu>W}8nO++=BM zqc|b_rENhl)FOC(aPrazA!|jKrV*IdQgBq?0+h+|*=+{K3`Q zu*6P!t`o(;S^J-V|HFa*;lO{*f#>dLgUqZk6T)`*Ml!Nb-$S%Bk z;f_tq@>GzFsT)XRj`^#7*7VabZ8P@Vhn~ipRTj*-z#>argfw2wEIt86KVLCa#7UVG z>VOE)+|Xu2^;UB&ftQ%5@QH}Li4*VS3{2U{ip?`W@mAbE6J(|lcQc~$Iq*&?cP7ih@9*#+PxoF=`+BUm3Q zr_c-f!9L+i)y=VFCKQZ6p7RKqLTGPsvPWBhZ%9l1SA@)!ST~7PUL4Cyt)xNPi*a%l z$mCOWdVGrv?Oj~5(Jup17bMBR3F_z0YMl#$7*BpJF4h3EEGAB0zM_AVx9ID2{ukUU zZWkb3rrlX*O8l6Z@!_?)GVHJEpR&6JGjEeU_t0KU=~$h=K*SX7<^;>GXMr}XxirX&@$;AbThTiC^ULbo-WK2l)OeB#znlxqkAXjl#cfxvsx+6TKzctF`8`S3_~k|#+R9UdiZI)*5lc7V0!ihQ z5Y;7Dv9Xv)Ya@vk>AH=N(42)9P6d^L6wsL4^Ud{v`_kz7c>372S)o1`Q{^POYohRZ z#ohsFl1tB9*;nsZZ$UE`$k6s5tB}b~QjhM-R>ehH-==NHZkM;WzW4UrZOktcC5$B$ zB{n&=;g zZpRSvmdETiTiQaC8XxWv(W+;nqaq%d=jWcWE}mE<#nX?~b?*o|t8JQ?;|fMBA>I6F zL`%QwtQAJU)vx;VBA>t>^yu_SvdJLb%xSQhAmOaHhqh zDly{f2~zI$yoRPTGmTy0>%i|J=&$7Ar=te4FTwCjujc!LwxeCvmYc2nMCQ&qIt;?S z7ExDZN19!u^p4A-n!}r=tvZx^`dk&Wm~SM1xV|l(aMOFPdMG5xB$+r9m1UPi$7v%~ zvc!qX>Xm4xFZEtjvNYfAJ(?j{?K{eT!b<_NWNFzin{>ZPy$<_QZuUj^ma{wlRs8Zb zPytMa7%4gLTti!EVh2HV4t=L3;8-jdT~|}JnUf{$GG(2KZ9%f@2JWkp?%fG)jS9Qp zzOTaujG+jPSOQVS?!$dzb!|xJB8O>4$I`@&7{NsSdG&`kxE9tm61!Ywvz$ncEE!27 z!aC6(#d(shGj~s$%0P3fv5j8tez&uB0-N~~B&`bxuf3DNX$#*9eGn0{IhzQsx~KRb zt&5g5BKaoX+gCV-v#?Z6eNh^*8S~SNMwNXYckm-Eceg_pBC%mYiwwy!#B^``kEq=G z=|Huk-qQwSX-xB-OWKKjELG3emJRg$p5Bs$)}LOO`7WZ^nJnpjKe0zkTJoBa067FR zL|4jQ`q9tvy?}|PwR%$bI?D7$XR>rkp7&xt=UhVNv(*`v#P#{U?b0m4#Oqq)!fmUY zrHkEHnCu8DsBN7XY({byUqWTJMunSF9h4ZSGbho*vN1ZuB-VM1K{RpDodNq;aVvIV z?JZB15NZq+lidALwlEB`{L1UZFQdiJG#|$e`p4ul*@$JZjn-Md#m%~mTFaPRjlAQg z#a&`HH4(nOja!l#Om3^oG)!hpwqsVt)jD%BO!KbznJ5o6#3lcv(cQ4cDcZU6pjunL z6_eF~RlRb$?rO{n!^W{ljeau}_M7*n2W(7A~tz>tO%I15^*Fk%C zX>XhUoC+DX4xrjQTjCLnNpc>lb&{B^{_gJ!w2H7;v520ml_Tt#eL}U5J&Kb*&_TU1 z=O(XjwDU9xX46`opULP+qQs{YH+LHw?--|sMJXO{H~dn%*xMx%vm9WX*=H^Ip31cv zp+D&5-fI=F4IgNaELhcC8>&ZFlrmkHd93lM-}?uEGXoZAyzEEhea= zuC+N^20K;C=NUJvrOa5cCfZP zHz)gHpA4e>9-<%AWy3~Vw;55cmham?G~TI+`Mg$tWnE(@%_`--e)G#^NioS&_zD&4 zjw&uE-^>1TdV=6&c)rD8lavNZvW>IO&$VUsc=8R3#LwBh!IlZbYv)o7T9G`CvC$r` z3mCEp9gnYgg>CL!!po=)Kqc8l-^LWl_-?ca2naZSU&6>Cg+N}rYqUbLCad%y_nGf8 zFi?&lyF@3b`F5x>Uc$6H&L-{g!XJi~AY_ zwy~5?BSDB+U+sNI!oW_fm8SvvX*{&s>9Ws{AVK}@cj4B39fTi26i>K#s?$4?q`Yvi zrR>>qNhhC9EqlqnFn%Fdlr-|$t?R06GRPg5Dz}jCy*ktA#bHrZ?vV7_MV)WE4X~>C z_2pO0LJK*471r(bKjPNsrs;OROtQFBmwu&)4)A?qj#ez>`1Fa!gzupjL-lMocrm zBPQ3P0{QLP>5k$hE$KN0?XAzkI|ba=@+G&mx7ovQ{K)K^V|4CZ@9Zm^4i`hBrB37^Gh2F==n#!%r9o<1@C2hacCWXcg z-XAt;dTchsvQ8u9Ak@i(a@YTeD9Ty-)amq&t2T99Sh|a$4j=DFiuc}FDWA}C;^amS zjOVyHqbZ&w`G45hJ+&kHE@owoC4vhsqx3z=Ho47wB9>sej(uk_%UK4AY%R%J&SE#k zx^P@Oj?D>Q&=F}FNE|Ho`N1d7tD#-e*;TAzC8;IHm)>IU(pyJmEN40Qt-^Iy8h1sM zuOmrD3PRq|TxxXN0o6Oq2KBIzTJCb$Vw!Jz%g*L8g;`gRUe`$Kc3J(_C0lg&7GmIj z--}w=(lDQmmInRaB?i-q-Ik@rkF8RLMR1*>yaBFp!#t#u>2-8$5In5Toaj?AI$4Xy zTdpSy=yTQjR=lnm-@HH2&yN%!GDQI@6{+*_B2u8Xh+j>84>q_Czu50nRGrcbcghy< z=EI8-8nAOl;%!pZm8C^XOyged`46f$VBYg*Ahq;p_@Z!zEkYo zkwlx)8zqU3WApk&4*!Gzjfcr? zgvw4{%g8NwRHTOxxMse^g~~0G98Lmr$$GCE4CphSM?OP@`q$prZW^#>Fcp_>)9>2| zHr0vY@>4`}J7w)mE)8tJ%X>XJ{S+1Pp^^CnU;P`{A|a?*Xz@- zuLiHPz=cj|7O4*V4&_@c@tRiQU<&QiXbn~gE5&W2aOa8;^LQhyx zY+$&4o$Ks|edgyPle*l_osI@4cmiB@sde$AQuai#Jr_e=?s&Befny_4z{5%_-{R$BL9kF=ZtupD)$G)V)uJ&Hz=;Hroi9!co`uF& zHe*)s*rm#!yuJEuwI2%qMO1L!B5Jtl3tZ^86DiQ}?_13ptAk zbe!2|zv&mMR+~>iXEDHuWm;D_T~+P8u~BelvAl3F$yA)V%24jf_uT?wzF|9e|&1dxkB4|9>#m_ND5ULbjjf@3!$leRjdZxu}S)fz51 z*oF7Faj7#1XD?N9fr7A9*X8zt3sstzw5ek1C}pMyG9B1Yp-g*1&aj|<4j5H45ZIDU z2-T)`&p_*~(2CkU)HXGlOadZE`Ckj2W$O=MriA6>Jj?M;NNvS5hu@0O?sr45L zub$rvW~-~b*u_*3y3<=Xh8seftMT1;LFnHVgHXi2 z8A86wWKuzJ{FwN5N#nAYcyGbNw^KG$7zyWQCLqUh2S}$J_TN=|hpy$N`249U){P6VW9opH zrXu^eGiz##dH}22K<`%35(=Pb`Q+^^(09DZbN4j~hKV{7*J~#SLCos2T`r;`Ey%sy zBPlJ@3A}Ol0IQs|A+xzcPDgg_4&u6i9sU^E z;9Y?9WTEEH=)Il)9i>?9oxkny3;~(b$ra%w4pA8aAIc#+V%+mM_8+(hKc_W}y=D{R zGtFR34w?4*8)M-owC2yBk$~_R&QVF!RzZ`YKaK}q`pqgzVRt`;0yRY1vtTV7hh#Q& zLKAv?sHoG^>s9f^-*bGe7k7Cq%lMHUXVfx77lr~ZHunlPV@IEEN;YCg-FA+XqDXGO zOa9Vb2P#7dx1;&Z<++b5QbK1?#%IE(Qw{G#T?9S7L)9bn0kYHHJ_zZ-xB5c6(GgA# z$lY4<*BQMm44>hQrMEzV1+=cI{KW$M@`*b5`Ol)$O6Lv$F!GVp~G#-NZ^OlD2Gq_ zo2dR~>~;}pka^iq)PJ1nufY%`T1Ek}c?ZE9^;^}n6*#tq7JR^z-q(L`Gw7rIUymQK z{f7q@Oq(p5oRsHIt4+MXnKM!S^HpWSJwJZ>qNpILjGnrNGkx1>jUqJr=;+I4hMsB? z%!R2HskT*uwH^>JjrjE|No|a2nuJ;WK_9SSz0J-3SOhBI%Yy6S5j%n37A{!IJcasx zsMWclR3cp1^|oUl>t2BQZWA&!8!8=d{KbO_B{CzURnFjNny_#*FpN zI@RW(Wjn3k#F0FfAfMO)F|NNBrJN3|P@dvm%`v(D!{>WHjlA%WXl=7tK5q$wU^fIv z`Grkvo*8?3u7uB-n(6_i0QGT^`Lh8@%BjX&M^lK{3&L6P?k6F)di4xCDJx@!>_ggz zK5`?&4v+V{Abxd`=wp!RqlAaSrFnQfrR&|n2#oN(HdrZ5jxp>9=5o7>aZg-E_(iS- zB0W}`A12Zl=Ds3b1zN-gz=oF8Z@Aj=AqTVvmtN~uFmXB%JZGt~=7)zq!`H^c#G*7z z8WqmV_uB2_ikyqq@(DLPDfZlg2BCc2I5J+@sK@JX<+7Z{mv=9VF&vB6;p2PVCKk8! zx-UIBw~$MMye9V0v}72u1l=C_(Z(wxsDXO@iL-3vB zQoNzmUl4j^`N7o9!IM5=C;w6kWhE2N3o&y%H4GyX3>5GA9!I6|pDGP-n2Lkzg;(pZ zN;cWKd?Kc!cM%`E zvs800A7x|wYsMYD$lM-|i0J)IR7RnW=cvri-JMfYM4w<*vhhq+G~PMRa_3x@S+-}| zinjakg2!@&EuU)8)q(L3}Rd_X4r|Vf>5BFE2~26CHYLuxUA@We~|G*avWu?JHk-S4CE3%S^I+Z&$G;`ayjy zT;F;&O>f@AQUczDHI6x+_}2UKC=q@{VuEb~zq&%THNG=JLM*`P$S`qW`-p5I8F5=I zy4GhNC$|bii$SW6fUA`d1&Ul@0YCRFy=k)31aUG}kDhEpD|WhWOQ?x!bz**`+-cMa zPoyAQu-ZiQIYBH=*Py$B(MGk2r(|y&rIDtDAg|_3RIs`~F;3_SY{%=9>LXG{)dBBG=+K>gm`Va2@Z!y8xlzgh;7fB?vYQgAunX345x|%2D$9q-$ zY^R+eoIBrETsr)T(qiKe%7TCpVe8`ZT+Qc&cZg#I8LqyaGxfmptIm)1*xM^?6rWwZ zP*Ut|aDNjNPVL5#x);DvyWL4K=Q2zXE`q4=A>H332yHXek;;ywXO~gBAo9mI#56O+GnztiCW@@GG!D)jkzI@wH z!uH<6`S0yzHjInjEw0`i=W+2x#)1drU211E9`rbr%%F!1U0z$i%P~92;3~HBYU+zK z8V)=sW?uHXMNY>DTT^{E=BeH%OfB{O@(ByqT}2@`!!Nu5iFH?$liq+ELX2b-?Jz%Y zr$Whe3vXlu$m)iSuu}OK0wJar<|QSo`sfsko2!$WJLRcR^q8>jZLM){Od*kML5ob;mL0B2usT3jQ^?L1`AOKRa$sZcGEe zfa6AX_i~_)LwJ$V#aGN3$gioj`xkawlhd)E@PD5<4%S~3@jpf%1Xj_pN91k9fhnkN zBQkPCkY{#O5&i+^fz{_wxxnf#Um0y|7iryQ<(O=KKB6uYP03a3JN!P$=WNVhXGP`T zc-35o1%QjQK6M|AxUS;j@GMs%fzifPk4P2jd9f)7+(6@xi#}uoby?AjQ)ndLMdZ_4 z2*{;F{*tc}TsS4PRflax6-GC32Ey0&uK41Hr1g;*(Y6gC{@w~4C#2pl3pf3bfcemPxwuSki zy=>w@4**~tbBUbr(T=D#QpLIKhu?9#ZL^;k_fm#~O?|kGv@)%@{Nm~!_-+4BJ5gS#o~b-N zg>T2lmZ+RHGCnC1qwBtl#(bn7=uV7nu?ct-{;Yr(8?(n|P=;@!DumfSzjB|JtPR z$GUo~w3Wml=b-k>5lK45v}XN~pgED_>(NrU@Ns7J@C41=v&L+ZW!UokVv*$W?#ccY zaebSZcrxaFdc}95-a=j@A1X9ez)KC32QDrUNNv0!{? zJFl)>{jk=jEr4*{iPWTRv9}x8fwnNr{nN6plxj1?9Xh}`wK0@kQ38duW_d6yW9~+t z4k2D<#k$l~or~vV$y73cnG=~RfOa3x*KBD>ieBEikCI1<%DO zn@7My_-HRvvcdrSw@$HwYXj|b^dd4ar(nTwAiv{vTSL6nrkn)mvle?W-l6BGyyJTd zELCP4PWYBP;Yu;n*Cn2b`Al zpAXpCVqTtTLPZ$d00-+)dTVk%x^djwYTF3SKH`!&t7ES_-otgtBct*7O3{U$TM+Mf zfxcF~iXsQllSfjv8!c4pZ8@2#nG3j=4?RADD>3gKmxz#PV+hO0?Ke~U?rpj(y z2LgZWnvU>lOj|+q7v{)jKCV3VcFD6_hGwNDXgsdH6oWid`om&zYz!Y#9^tuodE{Xx zUTV3HR%-4?Rl!=f%!Ko46CnX7WWQmJmtW>kGUo!pytK@$Pz4$yiq7z`Z4^9e85Ov& zqWH+`4Pzl7qiz$1VVQT7q@vL=XUAJRns{pJdPpuwZ-%l4!p<$13`y*X~iod}vLN3%_2`|Y=h zn6r!PJnLdBd~tk5r}-DKZI^VK(tgaoWrxT6Z3CV>{iqZxwqA50_WLX0@?a)rr5nN; zSWZi?ld(Knw+N)NGy#)Xk(KdN4Gbjr>(!VU%B5VqVXN_? zIV(`<6nzk2!p7dp6$mG1c~YNZux>V;| zKQu$8Y0v0r*$-VS&I)$Nf~TXqKhpxWLxeOgNQ%q!v8ksY^;Y@RJ+1iyWAn60g`Qmq zwdGE`GXY13H=!K`T`XkYm(v4N0oRg#Y6F|;ho2QyYR zjhYKpbc~-FWVE??k`*-w%*=c6EArgN;`}T*mTKB)2cj?MN0J?|51&^(6+D>`aOZ9? z2qWHHavu5gf+*5YzylpHu}d5y)Lrv@s4sbJjt1sKloj55y5v~?HJWLE-YtX?YH6{n z$wO4idt!FSWr<YMI1tZko8Qu7}_SOxry9_BTlFMhm&&<+$YpNprx~tZ`&Hwaqbjm}r1t zib{^eZ%$3s=62~p&ZpgcW+ms&fG@0f=gvg}wNm0p+brs3`+#qAYIgm%S$D+m!RUa< zm3-`$k^iS~!ESDjDu~4@@mW(JR?qVdJdJ{CTew+TOMfFWb(crd+1!-kBHA+7_v;%I z7E}sre8czYQJHla2_cxQcDStO<$cBa7B~slA{Gu$*0DaRgjhJPoGA11 z@K#hy3X9!nx%0Z&!hh~g{0q#bbg8-T`Z_+2k4blnz3xXScenW|_RRI)+z$&wV*H8D zpY`?WZXLlC`bD+(ZYu(nTj3exV-iBAv}@kj2B3bq@5*hW(Z;i&sk z`|6YB{ety^hFY33#nO{DwlkE5Z!~z_iQZYSXCnPq^GwWfsaZmvcEju)G;Z4iCs$~b z9AynMlAQwMz&@gE{_lgpl|~eQQklt&s5!4!k6sstvOK~pW=NBd=^Jc!59Y)_ z{2(m~_4~41C$Y8p@OQ}Um@=j@Zsfw?UHmbX-BT}V#6rX^amC_!K+<9(hh;=fYg?EG z98_sJuB2Od3Npq0YK3NYI;i~(I~$N?Q4UkI9+hgZbe35hiVn@*Ws90CAc%aNi@W@m z2nC6uV_ot1vf7$-qUyR#^pB*pqV$rIOTR<)FE0MD73Xt4#8k84R{m--Z3(BzS7zN(G0CRcA47Zs zQ_X38!yMf`f8=1G15CB>Xao9)nGQ%)7;PAOS#8!8j~mP~z5uJ-M#yTqB34wex5>$` z(fQ-R?f(66cME9$ae+ICjPpp&Y-!}z;ya+DBd^pf_X+VIrjWIp^%!em>suWHya&Ly zk5p3HPkhx=_VsITjVw}LAR_SnAzwGBDt9eDUgJ49t7TM+3~uEWF|($sE)LY9K;Fa9 z%Z17>0m*EUMOxfOOuhvBAc){{4A|zkF_6{tLG0v)YvBGs{76;#1J3Ep`L_vC;&ONI zA@cTg2mr`|QWr?hx^?*b>IrOO@@V`OXW*8j9{~1u#-GJv2f1l~Ol>y_(H*pnQ7%L2d`SNlqv6 zZ-4O@qjL*0eeLoBd=M(B|jhum+u)J@EtI4)oyvYhMr?{;ODh54`~1+OUFK z2dbJ0W;m6h${(g+xx*`>_5u4f=AO55cpJ1-<_fL?>~;NP(^=myjaPN$I-buyzV6Mrd|oU{X~?4J4FnbijbfO zlLBHA>N2YPr%-0+g7BcOVm3G!S6{z-yGk{e#*Ljm(vR_VeJY5(Q698>cCN>K-QS=N z=_G}(?wFZb6+V6e5{*kk2%}#r#lvAE;NVG3Q`cb{#XAzOUvzyjQF{auF3%jmO6XlY z5IR4(?7b=fac?TSL9H5Y-6*i4cn&Xeve+UfNF@41^kSSu<$$pmb)P0042Na$YaH`P zk<>{{k*i2Mm1s1!;g&to1ybRORW})6iPM2?| z50vRB;7wqKmWrg~l&P1cvw&7HKDUuqx6W=$Qbu+i+{xmy6HN zHKnM}iXz2xqQp=?670y0lM326o%vwF{P8qpUOm_OJU5O8SAI6GQRG~h8%fR(9k5pO z%ap=LE%P;cOx}jRO$nVId}$2rP34l2Jb<0|VCt1?2Gf{Uje>v``IATh=#19~K4eNu z+w4vi`B-8?et__6UHxz=tE1nDSHs^e#**lDg+}Pz9vm}-9%&e5FSUp19aye>;O#)! zk1U`1uc`<&?eK|S>zR1`v=aCc}w-ZW!vi)a%I=XD-uL9Lc? z^{~CryRdKk^0|>(c4tNExzX>rIw=j43rARnsc1c^q~e!Ru$D{H1yL)ZpDejVmg6!| z1<4s@`X(w;e8@!GL1S_?2maq=a3h`1eh&$CdtF7itiAyadnVv7l{2?iB}2bSDTT_> zG?k-vDScWEaVf0Nb~0y+3lOQlF&&kBsj7NZui54^9}?ev=QMm;LaOJR5U-@Tm~2$! zftd|WyBVoEn___aq3d++sO`9jVq3IyV`ieQ1lL)Eahm8Be4MsYo%Pv*9`#N+249;` zyOY?N%gbs>oQ~snaoex(Q7%5qqhONi_nPrX>E6)CNopo24VKdtwd35Zb1iZV)o^t3 z<>r#fobi1JI}BX1jd_*EL~JgvsTVfpCsLk)*$RT%XG20LE2R#c9-B#fA-w2U+$G$} zW{A>347lP?L5W{&F>w@qIJv}T8K<)H$0`HX&vNwvl4qf9T6NJ+Q!Dr_zzJV>z=T-4tDP)Vd)abTw`X9(_s1eU5 zIK#u>+EU3{Xz2ocHT6W<6D;#Fk?=osty4gDrjub!a8IXpcTZOt-0Y4h9WV*B7sby>F46<+E~@1QtD51>Vs}hkQm^uTkAWGGza!Af_}$q zELdQ)5V&XKB9&|kh^rrX_xw8uE-g|IX*YuFW)fe7m()S%!wo`4WJ57^yG1)4^G#X- zzh}QkOO(*xr= zGp|B?862>$tlS{r249B#z_)D!*Zh-{K*|op7e6|I7Xb`Z`=$%*2i)U-R&o247aRQ7 zs?oqK?>%R_5Bn+e0pE?|+~n zedJH}BDD}&>>MG}X(99gVm2eH0Ak%qo(SVW38^7p(DVJkBI~ zxS*azO#KopktTNk@F) zgEI$;5#5ilW?N}LrTEkdIQHw1o3%0Ydi@NkD;g)F(w!zkA|Eeh*ZVn)dqhosb<(ef z6fm51k4l7VOHp(FiaQ`Cm-GAeCuJai`qhcSawOOIXRZ_L#cT{1B91SJKdCxvxzi;! zTLHbibd$FOG@_)j(H2OBcMUV1&v`sK|87b?(}iGkVd!L&pVPUEL-m(j4+v9Xzcfl3 z)+Zdtw(m^0Qx)Ex7-FBOvvrBfBs}Kzts{Hw<+$2N{=eCoL|@C`hXzvTG7<_Gnw&fAN#^8I9}DYJWsaum^6hk z&Y%@X=QgZlUHI(^Qt9(F?MOsqh5zd1s5!q{o9KXp__VvTbV+Dqmeo~=@HN7EwSi0y9H$rrYO~vJx=TTLNbrKLEiB! z_ta!@b>s@zvpzNI<(yr&xl6&Fo2W&m=AZ|y8tMcwh<2*M4T}u@?=%qa*Z?;Bh#xa?nf!)Z^ zSjd&n4w9xw%#~5X_&%;xI5o1xYsRO7b)sZLnT)fxs5%H@{1apIH7coKI#!rj1oo4mp1kc>H7ltbmlJ{ zpMdnb;U?#zrz$P2&xel3)}Dy+_iuPUZe*wU@!j|+u75+D!}U_vICyEy24Y?UIm!c} zVMD>T6WWMYs7p$pM359`mPC9+{7s4>2S<+^Ig<6{=cza_Rbz@rTEeJ$5YG< z<3|pgD%}zuWW&Xe=fg9lKi7Q7&m6{`DrqTaRqKR*H4e&U4wZOft{9FgF?Hurz~<^1Z3O{UiV7i5Hi9V@?F5)ashVw!$~PNs5_u z39!mq*}0*q8kefYx!@gq_V0{O*3@tfyReP(8XR*Gk{DaJwVQZyVQjMv$w@XgVK^;! z_4m9Q!;%8)l&NiNG#83+$Kd_@2z5@(I4mfY)Ub*HYpw}lsw-c+)* zAC`-g?KOToae;oWi#R>8IsS;(a-W6IvE#W=2f;3*&F2GV07?NNQj`#Yy4VuRg9Il2 z*zo)y5LwAn2;r1}0~)7k|Jobj_r&do>HB?e4Mx;3sS_VfIuX>bdu9Y3cx^I&oO<>r zNKL7yeEh!60R}o85PcE7%$z&6_^y1Y=#G5l2QHg~_`wx%W*DWo$hDgc6$LI3FjUU^ z&-a0U;Vkp?5Of|r=QQqxm*IwO^8=ixGteXN}ZaVpXo-p2=4ByGy`tX}q zD~Ur5%d6p=E2V;1WxrgS{aY5wVd+v0T^8vv2z>gCufaa%J+j(#YS7{6&!b+R_tz}c zes5Dwr3nV=7kIXE@^D_ZT@2*@FFE(Wjk;eHdCUCv zKKK8(Vf?co|K9=y-1waT4?6UJj=DJ09~NJGBv1a2PQC$NX#5N1`p*=jc!qbJ>qLC* zEY*dJz`K*ZWAMO=2@S$!YbT3BS{W4XIXpzyR8g|}0MQ*#Yf?~p0a@_V8~tP)v^8*G zl5}aY_Y-N{q|+^$xR$U#O~dw0f#!K+T9Mk4Dq>`Ed<)i^=xKch)PHdJ=D|%B!;?`f zp5;Yq?UT<|kI1=)xWe(3d2*X1m&zUSCV?%b10x57lZuJKy%B=}jxlv2#HXa4)rRO@ zU8enOA^rm3;e>t!BTBpiYB6yO`pn`e!^u-NUckBCj}Ars9RuN;e`SWQXG}x(X)FHb zjMQ2isqCVxytEqLG~HfRK37?l)A_I~LiFHzreZ!d_W;(f} z8VWKVVmO%dd|-+(EA#i2Fr^{;K>!IzyZIpDVYG4nr!T*4_a7tv?|k`8>`K?$9n#u* zy-)kkEyXBDCn5p}%eB8{-XOmg{t~PRROEZDOvELBhFIMHWvyuRa!~g!B4bSssWp$z zEs}t=E}gAGV;~h9!2(`goBiD4(ZI`%U3%<{#;gs$(v#N!9w{7nce7v-k!xVji26C_0~Ph#+?*rnRT;r08oT=?$PXsH0+T>Jo0$V= za%wWIb3?7wJ5{*ctonplZYEYh3Id?GCg`u}?fYB$D~1aDx6;p8P+||K22~DgVrq{` zJt(50nLn&k0Vt>MpBJw3IxM%D@C+GNwc7oqUNKcMq717d1@%^6{*oKcEGSyZGfer_` z(O|=O)FzPk52djOWcO#I=O%ic!CVGc(KO~CQjd4^3y3n* z1aytTt=9>Ew(RUdSy7n`@>-pjn)yLB(0k_MS&1U00}1wE$Up7QiG`@01k9wZp~;u` z6EX-rK*raE9<@4gE-LKbGnQ392LNOc%Kcs#wJ$MSuOmi&>zaJ~FFm^V5vQo{-P_iH!cy>}Ha-ql*w9X{@1o)yPYaFaS*6d2%|00j2kU z_7T1&Ky3rGDl}4yA{~LPowWHoe|RO4k=6}(Zlt}c%eRZ2K^yXWTzaMS?{Mk-VGjbZ zh&l3icg!0bY$*fq-yv`#*M+K04tYk&O4yxWPn8BCX$Aipo#|>$WE;yiovdHFbJ*O( z4u8loR?-?s+McPmH?jGR;+U=9+ImQl^l5xVx!`VTrjtkMA?TMZP{RCbU=nV79z>eX zbb6Nd=gIa@YmlcPRy7$aXNM1xP(H-Lx_PT-{>mX}XDeF5^IuXX4zk4|JFk5h+_$@27Iku8!KVNgk?HCoj%}x=W==V!`YN??q7K6fBtGai#JtOAMwlG+|od; z(^Im3IUj!wJ9BQ{7GVvG&g?wvf9z>2?yR=}66?i4PWMwY+=JQs6lzGWXvhAk!+9hb z{Q&G1wD=4Pgy{4E8pVPgJ|Qc=izBPl11^D(7(Pnh($Yp=V6hq?Id{M7RY_|kUTM4x zqSO8*pw%KfuYQs?J8?3OuiWJk{$~N)pp;H~6&D21@2FA{sjm`X`>*bn(2fI9@}we>{FBgG`=%YjjAd zlXJv-d?G&>O#BYXMEaEM%eFRdWxa0Db#+VQGM3(9ij2P9A$h*$M)&d(pOy_E9Hg)C z;AZra$7wvX+QiSsJ#knxwT8jyT~dG^uOsZoo3Pp_7C^>kPfbn6ol?BR_lo`zEe+7q z-eJ4o)?~(CU)rvB>~JMr*Re5y=!%omm3y(s zug9}5`2#`}&W#*ZW)3R9NM#7LGTP`~s)!amVY+XGxVy5IT?CBJB}MKTq9YF|_6100 z58gYj#~#t$+p|<;`A7Dp^q2LpFFxptBmMgXY%%J7#FFr}1x1 z4u3U1D*GX3HK@sw{;?BMX|JX2FLJr}^ba6pU-iiPpYLnk7uGlbxYz&Iz5Hp~{99ih z@#j6NKOLLDclU1Jcl;A=|3VH28zU?FTj%EioWEiDpRfP@9C(mJ;$k39-N?xKQ3PPS z+}t_$m47n2eel@h)#AS^5;EUdO_u=NiMo;W?W ZwetGc3uH>aTJ(l1SVD4{1rQMgwGR1}b|h^RnNASCn% zVw5UU0t6C@)DS`u0tCW033^}e^FHtT%KOi^e(O1ZWSw(nX74?F@7ZnUJ+8&?_vYR6zA~^w`&y2b)k1X?(;qp=&_vF+Fq_hSnev&TrMoD?CH5l>CWjL#yD@s zOkrBf=YKfO*0s-`;)fu`i1zmOq5Y=Z5M+C-aV|SP$%0DamT$MBW(qh*Z-t=5Fa-q# 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 diff --git a/docs/team/nigellenl.md b/docs/team/nigellenl.md index 8f56d2a90..72e355562 100644 --- a/docs/team/nigellenl.md +++ b/docs/team/nigellenl.md @@ -28,8 +28,9 @@ ### Contributions to the DG * Added setting up instructions. -* Explained the implementation of the `edit` command (under section 3.4) using Sequence Diagrams +* Explained the implementation of the `edit` command (under section 3.4) using Sequence Diagram. * Gave instructions for manual testing and included sample test cases for `goal` command. +* Added the non-functional requirements for the program. ### Contributions to team-based tasks * Made extensive use of the issue tracker to manage enhancements and bugs. @@ -76,12 +77,11 @@ By using the `goal` command, users can set specific goals for how long they woul ## Contributions to the Developer Guide (extracts) ### Edit feature -The edit feature allows the user to make changes to activities that have been saved in the activity list. This is to allow the user to rectify any mistakes that may have been made during the initial recording of the activity. +The current implementation of the edit feature allows the user to edit the activity name as well as its allocated time. +The following sequence diagram shows how the edit feature works for editing the activity name. The diagram for the editing of allocated time is omitted as the sequence is relatively similar. + +*[The sequence diagram has been omitted in this section]* -#### Current Implementation -The following sequence diagram shows how the edit feature works. -_diagram omitted_ - The current implementation of the edit feature allows the user to edit only the name parameter of the activity. When the user wants to edit an activity using the edit command, the Parser creates a new EditCommand object. The `executeCommand()` method of the EditCommand object is called and the specified parameters are updated accordingly. The order of method calls to edit the activity details is as follows if the specified activity exists (meaning `index >= 0`) else an exception is thrown: @@ -90,12 +90,12 @@ The order of method calls to edit the activity details is as follows if the spec 3. The `setName()` method of the Activity class is called to edit the activity name to the user-specified name 4. The activity with the updated name is returned to the activityList -#### Additional Implementations -The current implementation of the edit feature only allows the user to edit the activity name. Hence, additional implementations of the edit feature should allow the user to edit other parameters of the activity such as the tags and the start and end dates. +#### 3.4.2 Additional Implementations +The current implementation of the edit feature only allows the user to edit the activity name and allocated time. Hence, additional implementations of the edit feature could allow the user to edit other parameters of the activity such as the tags and the start and end dates. This will require the implementation of more update methods in the ActivityList class to allow for the changes to be updated in the activityList after it has been edited. -#### Design Considerations -By letting the user edit the name and tags of the activity, it will allow them to correct any mistakes made during the data entry. This ensures that there is an accurate record of activities such as in cases where the user may be trying to record the same activity but has misspelled it, resulting in the program regarding it as a different activity where there would be multiple unnecessary new entries in the activity list, making the analysis of the time spent more tedious and inaccurate. +#### 3.4.3 Design Considerations +By letting the user edit the name and allocated time of the activity, it will allow them to correct any mistakes made during the data entry as well as allowing them to update their allocated time for the activity. This ensures that there is an accurate record of activities such as in cases where the user may be trying to record the same activity but has misspelled it, resulting in the program regarding it as a different activity where there would be multiple unnecessary new entries in the activity list, making the analysis of the time spent more tedious and inaccurate. However, by allowing the user to edit the start date and time, there may be potential inaccuracies in the actual activity recording. This is due to the fact that the time recorded in the program is based on the LocalDateTime. By introducing user input, the dates and time may be recorded incorrectly, defeating the purpose of the time tracking program. From 571d9cac6420cd186178683847f3d11ea0dd0092 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Fri, 10 Apr 2020 23:35:02 +0800 Subject: [PATCH 337/415] Modify text-ui-test --- text-ui-test/EXPECTED.TXT | 5 ++++- text-ui-test/input.txt | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 9ded1ea0c..4313b455b 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -64,7 +64,10 @@ OOPS!!! I'm sorry, but I don't know what that means :-( Activity name cannot be empty. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -You have deleted activity 2. +Activity named activity 2 has been updated. +------------------------------------------------------------------------------------------ +------------------------------------------------------------------------------------------ +You have deleted activity 5. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ Bye! See you again. diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 02e43cb73..316675c9c 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -16,5 +16,6 @@ end abort hi delete -delete activity 2 +edit activity 2 /en activity 5 +delete activity 5 bye \ No newline at end of file From 5f91138cda0d8f27e7bd45b9a37f73f6360ac825 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Fri, 10 Apr 2020 23:42:36 +0800 Subject: [PATCH 338/415] Fix format issue in the DG --- docs/DeveloperGuide.md | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 865d4f7a5..8656df693 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -63,7 +63,7 @@ _Fig 2.1. Class diagram of the Jikan program_ ![image_info](./pictures/Commands.png) -_Fig 2.2. Commands of Jikan (private methods omittedd)_ +_Fig 2.2. Commands of Jikan (private methods omitted)_ All the commands inherit from the abstract `Command` class. Each command has a protected `parameters` attribute from it's Parent class `command` and an overridden method `executeCommand` which is called in `main` to execute the relevant command. @@ -341,32 +341,32 @@ Allow users to record their daily activities and track their time usage in a use ### Instructions for Manual Testing - #### Launch and Shutdown +#### Launch and Shutdown 1. Download the jar file and data.csv file. 2. Copy both into an empty folder. 3. Create a folder named `data` and put the data.csv file into this folder. 4. Ensure the folder `data` and `jikan.jar` are in the same folder. 5. Open command prompt and navigate to the folder. Run the jar file using `java -jar jikan.jar` - It is important to include the data.csv file to have data for testing! + It is important to include the data.csv file to have data for testing! - #### Listing activities +#### Listing activities Test case: `list month april` Expected: A list of activities completed in the month of April should be shown. Test case: `list 25/03/2020` - Expected: A list of activities completed on 25th March 2020 should be shown. + Expected: A list of activities completed on 25th March 2020 should be shown. - #### Continuing activities +#### Continuing activities Test case: `continue lab 4 ex2` Expected: Message "lab 4 ex2 was continued" will be displayed. Test case: `start lab 4 ex2` - Expected: Option to continue will be given. If 'yes' is typed, activity will be continued. + Expected: Option to continue will be given. If 'yes' is typed, activity will be continued. #### Graphing activities @@ -382,7 +382,7 @@ Test case: (to be done in succession) `list week` then `graph tags` Expected: List of activities completed this week will be shown. -Then a chart of the duration of the tags of these activities will be shown. +Then a chart of the duration of the tags of these activities will be shown. #### Setting tag goals Test case: `goal core /g 24:00:00` From d83a8334a08085129befb51d12e1b7f8410fdb70 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 11 Apr 2020 00:04:01 +0800 Subject: [PATCH 339/415] Change string literals to final attributes --- src/main/java/jikan/Jikan.java | 2 - .../java/jikan/activity/ActivityList.java | 6 +++ src/main/java/jikan/command/AbortCommand.java | 1 - src/main/java/jikan/command/ByeCommand.java | 8 ++- src/main/java/jikan/command/CleanCommand.java | 6 +-- .../java/jikan/command/ContinueCommand.java | 8 +-- .../java/jikan/command/DeleteCommand.java | 1 - src/main/java/jikan/command/EndCommand.java | 3 -- src/main/java/jikan/command/GraphCommand.java | 10 ++-- src/main/java/jikan/command/StartCommand.java | 6 +-- src/main/java/jikan/parser/Parser.java | 50 +++++++++++-------- .../jikan/command/ContinueCommandTest.java | 7 +++ .../java/jikan/command/StartCommandTest.java | 2 +- 13 files changed, 60 insertions(+), 50 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index be1741a92..507313ede 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -3,7 +3,6 @@ import jikan.activity.ActivityList; import jikan.command.ByeCommand; import jikan.command.Command; -import jikan.command.GoalCommand; import jikan.exception.EmptyNameException; import jikan.exception.ExtraParametersException; import jikan.cleaner.LogCleaner; @@ -12,7 +11,6 @@ import jikan.cleaner.StorageCleaner; import jikan.ui.Ui; -import java.io.File; import java.io.IOException; import java.util.Scanner; diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 4627690e4..ec9c8b618 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -180,6 +180,9 @@ public void saveActivity() throws InvalidTimeFrameException, NameTooLongExceptio } Parser.continuedIndex = -1; Parser.resetInfo(); + assert(Parser.tags == null); + assert(Parser.activityName == null); + assert(Parser.startTime == null); } else { Ui.printDivider(Parser.activityName + " was ended."); @@ -194,6 +197,9 @@ public void saveActivity() throws InvalidTimeFrameException, NameTooLongExceptio } // reset activity info Parser.resetInfo(); + assert(Parser.tags == null); + assert(Parser.activityName == null); + assert(Parser.startTime == null); } } diff --git a/src/main/java/jikan/command/AbortCommand.java b/src/main/java/jikan/command/AbortCommand.java index 9e38b4c8c..4b3b3c990 100644 --- a/src/main/java/jikan/command/AbortCommand.java +++ b/src/main/java/jikan/command/AbortCommand.java @@ -1,6 +1,5 @@ package jikan.command; -import jikan.exception.ExtraParametersException; import jikan.log.Log; import jikan.activity.ActivityList; import jikan.exception.NoSuchActivityException; diff --git a/src/main/java/jikan/command/ByeCommand.java b/src/main/java/jikan/command/ByeCommand.java index 08fed5492..aaa0526c9 100644 --- a/src/main/java/jikan/command/ByeCommand.java +++ b/src/main/java/jikan/command/ByeCommand.java @@ -16,8 +16,6 @@ */ public class ByeCommand extends Command { - //private Scanner scanner = new Scanner(System.in); - /** * Constructor to create a new exit command. */ @@ -26,14 +24,14 @@ public ByeCommand(String parameters) { } /** - * Checks for ongoing activities and ask if user wants to save them - * before exiting the app. + * Exits the app. If there is a ongoing activity, asks the user if the activity + * should be saved. */ @Override public void executeCommand(ActivityList activityList) { try { - //Parser.parseBye(activityList, Jikan.in); + // checks if there was an ongoing activity if (Parser.startTime != null) { String line = Parser.activityName + " is still running! If you exit now it will be aborted.\n" + "Would you like to end this activity to save it?"; diff --git a/src/main/java/jikan/command/CleanCommand.java b/src/main/java/jikan/command/CleanCommand.java index 08b0a1991..067fb1d7f 100644 --- a/src/main/java/jikan/command/CleanCommand.java +++ b/src/main/java/jikan/command/CleanCommand.java @@ -45,11 +45,7 @@ public void executeCommand(ActivityList activityList) { */ private boolean isParameterEmpty() { String parametersTrimmed = this.parameters.trim(); - if (parametersTrimmed.isEmpty()) { - return true; - } else { - return false; - } + return parametersTrimmed.isEmpty(); } /** diff --git a/src/main/java/jikan/command/ContinueCommand.java b/src/main/java/jikan/command/ContinueCommand.java index 2aa33acf1..bfd641f59 100644 --- a/src/main/java/jikan/command/ContinueCommand.java +++ b/src/main/java/jikan/command/ContinueCommand.java @@ -25,8 +25,8 @@ public ContinueCommand(String parameters) { public void executeCommand(ActivityList activityList) { try { if (Parser.startTime != null) { - String line = Parser.activityName + " is ongoing!"; - Ui.printDivider("Could not continue activity due to already ongoing activity."); + Ui.printDivider(Parser.activityName + " is ongoing!"); + Log.makeInfoLog("Could not continue activity due to ongoing activity."); return; } //Parser.parseContinue(activityList); @@ -37,8 +37,8 @@ public void executeCommand(ActivityList activityList) { Parser.tags = activityList.get(index).getTags(); Parser.startTime = LocalDateTime.now(); Parser.continuedIndex = index; - String line = Parser.activityName + " was continued"; - Ui.printDivider(line); + Ui.printDivider(Parser.activityName + " was continued."); + Log.makeInfoLog(Parser.activityName + " was continued"); } else { if (parameters.isEmpty()) { throw new EmptyNameException(); diff --git a/src/main/java/jikan/command/DeleteCommand.java b/src/main/java/jikan/command/DeleteCommand.java index f784ead0d..72c36d6a8 100644 --- a/src/main/java/jikan/command/DeleteCommand.java +++ b/src/main/java/jikan/command/DeleteCommand.java @@ -3,7 +3,6 @@ import jikan.activity.ActivityList; import jikan.exception.EmptyNameException; import jikan.exception.NoSuchActivityException; -import jikan.parser.Parser; import jikan.ui.Ui; /** diff --git a/src/main/java/jikan/command/EndCommand.java b/src/main/java/jikan/command/EndCommand.java index 77db96c7f..3a095ce29 100644 --- a/src/main/java/jikan/command/EndCommand.java +++ b/src/main/java/jikan/command/EndCommand.java @@ -18,9 +18,6 @@ */ public class EndCommand extends Command { - - private Scanner scanner; - /** * Constructor to create a new end command. */ diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index b7cf6dccc..b8a7b2fd8 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -14,6 +14,10 @@ public class GraphCommand extends Command { + private static final String ALLOCATIONS = "allocations"; + private static final String TAGS = "tags"; + private static final String ACTIVITIES = "activities"; + String[] inputs; /** @@ -34,13 +38,13 @@ public GraphCommand(String parameters) throws ExtraParametersException { public void executeCommand(ActivityList activityList) { try { switch (inputs[0]) { - case "allocations": + case ALLOCATIONS: Ui.graphAllocation(lastShownList); break; - case "tags": + case TAGS: graphTags(); break; - case "activities": + case ACTIVITIES: graphActivities(); break; default: diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index b913f03f9..ffd475613 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -49,11 +49,7 @@ public void executeCommand(ActivityList activityList) { * @return true if there is a concurrent running activity and false otherwise. */ private boolean hasStarted(LocalDateTime startTime) { - if (startTime != null) { - return true; - } else { - return false; - } + return startTime != null; } /** diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index d0775a965..c5e99de63 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -2,7 +2,6 @@ import jikan.exception.ExtraParametersException; import jikan.log.Log; -import jikan.exception.EmptyNameException; import jikan.cleaner.StorageCleaner; import jikan.storage.Storage; import jikan.ui.Ui; @@ -23,12 +22,8 @@ import jikan.command.StartCommand; import jikan.command.ViewGoalsCommand; - -import java.io.File; - import jikan.cleaner.LogCleaner; -import java.lang.reflect.Array; import java.time.Duration; import java.time.LocalDateTime; import java.util.HashSet; @@ -43,6 +38,21 @@ */ public class Parser { + private static final String ABORT = "abort"; + private static final String BYE = "bye"; + private static final String CLEAN = "clean"; + private static final String CONTINUE = "continue"; + private static final String DELETE = "delete"; + private static final String EDIT = "edit"; + private static final String END = "end"; + private static final String FILTER = "filter"; + private static final String FIND = "find"; + private static final String GOAL = "goal"; + private static final String GRAPH = "graph"; + private static final String LIST = "list"; + private static final String START = "start"; + + public static LocalDateTime startTime = null; public static LocalDateTime endTime = null; public static String activityName = null; @@ -63,8 +73,8 @@ public class Parser { * * @param scanner scanner object which reads user input */ - public Command parseUserCommands(Scanner scanner) throws EmptyNameException, - NullPointerException, ArrayIndexOutOfBoundsException { + public Command parseUserCommands(Scanner scanner) throws NullPointerException, + ArrayIndexOutOfBoundsException { makeInfoLog("Starting to parse inputs."); String userInput = scanner.nextLine(); @@ -73,14 +83,14 @@ public Command parseUserCommands(Scanner scanner) throws EmptyNameException, Command command = null; switch (instruction) { - case "bye": + case BYE: if (tokenizedInputs.length > 1 && !tokenizedInputs[1].isBlank()) { Ui.printDivider("Extra parameters detected."); break; } command = new ByeCommand(null); break; - case "start": + case START: try { command = new StartCommand(tokenizedInputs[1], scanner); } catch (NullPointerException | ArrayIndexOutOfBoundsException e) { @@ -88,49 +98,49 @@ public Command parseUserCommands(Scanner scanner) throws EmptyNameException, Ui.printDivider("Activity name cannot be empty."); } break; - case "end": + case END: if (tokenizedInputs.length > 1 && !tokenizedInputs[1].isBlank()) { Ui.printDivider("Extra parameters detected."); break; } command = new EndCommand(null); break; - case "abort": + case ABORT: if (tokenizedInputs.length > 1 && !tokenizedInputs[1].isBlank()) { Ui.printDivider("Extra parameters detected."); break; } command = new AbortCommand(null); break; - case "list": + case LIST: if (tokenizedInputs.length == 1) { command = new ListCommand(null); } else { command = new ListCommand(tokenizedInputs[1]); } break; - case "delete": + case DELETE: try { command = new DeleteCommand(tokenizedInputs[1]); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("Activity name cannot be empty."); } break; - case "find": + case FIND: try { command = new FindCommand(tokenizedInputs[1]); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("No keyword was given."); } break; - case "filter": + case FILTER: try { command = new FilterCommand(tokenizedInputs[1]); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("No keyword was given."); } break; - case "edit": + case EDIT: try { command = new EditCommand(tokenizedInputs[1]); } catch (StringIndexOutOfBoundsException | ArrayIndexOutOfBoundsException e) { @@ -138,14 +148,14 @@ public Command parseUserCommands(Scanner scanner) throws EmptyNameException, makeInfoLog("Edit command failed as there was no existing activity name provided."); } break; - case "clean": + case CLEAN: try { command = new CleanCommand(tokenizedInputs[1], this.cleaner, this.logcleaner); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("No keyword was given."); } break; - case "continue": + case CONTINUE: try { command = new ContinueCommand(tokenizedInputs[1]); } catch (ArrayIndexOutOfBoundsException e) { @@ -153,7 +163,7 @@ public Command parseUserCommands(Scanner scanner) throws EmptyNameException, makeInfoLog("Continue command failed as there was no activity name provided."); } break; - case "graph": + case GRAPH: try { command = new GraphCommand(tokenizedInputs[1]); } catch (NumberFormatException e) { @@ -164,7 +174,7 @@ public Command parseUserCommands(Scanner scanner) throws EmptyNameException, Ui.printDivider("Please specify whether you want to graph activities / tags / allocations."); } break; - case "goal": + case GOAL: try { if (tokenizedInputs.length == 1) { command = new ViewGoalsCommand(null, this.tagStorage); diff --git a/src/test/java/jikan/command/ContinueCommandTest.java b/src/test/java/jikan/command/ContinueCommandTest.java index e187ad856..3bde1e22d 100644 --- a/src/test/java/jikan/command/ContinueCommandTest.java +++ b/src/test/java/jikan/command/ContinueCommandTest.java @@ -44,6 +44,11 @@ void populateActivityList() throws InvalidTimeFrameException, NameTooLongExcepti activities.add(activity3); } + private void resetFields() { + Parser.startTime = null; + Parser.tags.clear(); + } + @Test void executeContinue() throws InterruptedException { try { @@ -56,6 +61,8 @@ void executeContinue() throws InterruptedException { assertEquals(startTime.getMinute(), Parser.startTime.getMinute()); final Duration initial = activities.get(1).getDuration(); Thread.sleep(2000); + + resetFields(); // End Activity2 command = new EndCommand(null); command.executeCommand(activities); diff --git a/src/test/java/jikan/command/StartCommandTest.java b/src/test/java/jikan/command/StartCommandTest.java index 8c4868e6d..d6025b1c8 100644 --- a/src/test/java/jikan/command/StartCommandTest.java +++ b/src/test/java/jikan/command/StartCommandTest.java @@ -71,6 +71,7 @@ void executeStart() { assertEquals(Parser.activityName, "Activity 3"); assertEquals(activity3Tags, Parser.tags); + resetFields(); // end started activity to test continue feature command = new EndCommand(null); command.executeCommand(activities); @@ -82,7 +83,6 @@ void executeStart() { } catch (ExtraParametersException e) { Ui.printDivider("Field error."); } - resetFields(); } @Test From 9e483aae94bbab05a7d6171b5b009dc499e17ada Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sat, 11 Apr 2020 00:49:19 +0800 Subject: [PATCH 340/415] Update DG --- docs/DeveloperGuide.md | 9 +++++++-- docs/pictures/Find_Reference_Frame.PNG | Bin 0 -> 49715 bytes docs/pictures/Find_Sequence_Diagram.png | Bin 0 -> 53864 bytes docs/pictures/Simplified_Class_Diagram.png | Bin 0 -> 63584 bytes 4 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 docs/pictures/Find_Reference_Frame.PNG create mode 100644 docs/pictures/Find_Sequence_Diagram.png create mode 100644 docs/pictures/Simplified_Class_Diagram.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index aa3ac7da5..5e2ae6d51 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -78,7 +78,9 @@ of each session. ![image_info](./pictures/Architecture_Diagram.png) _Fig 2.1. Architecture diagram of the Jikan program_ - +### 2.2 Class Diagram +The high-level class diagram describes the structure of the components +![image_info](./pictures/Simplified_Class_Diagram.png) ## 3. Implementation This section describes some noteworthy details on how certain features are implemented. @@ -298,8 +300,11 @@ command contains the parameters: * If `lastShownList` is not empty, it will print the matching activities. * Else, it will respond to the user that there are no tasks which match the given keyword. +#### 3.7.3 Find Sequence Diagram +![image_info](./pictures/Find_Sequence_Diagram.png) +![image_info](./pictures/Find_Reference_Frame.png) -#### 3.7.3 Additional features (Proposed) +#### 3.7.4 Additional features (Proposed) Developers may include the feature allowing users users to chain multiple queries and multiple commands in a single user input. Possibly "pipe-lining" the output of one query into the next query with the pipe symbol `|`. diff --git a/docs/pictures/Find_Reference_Frame.PNG b/docs/pictures/Find_Reference_Frame.PNG new file mode 100644 index 0000000000000000000000000000000000000000..1527b9872dbce4d5d15855e5f06abfef67578ea6 GIT binary patch literal 49715 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 Z%`6;)_4~P(ywLX@SJC_}TglA-e*ybb2JZj> literal 0 HcmV?d00001 diff --git a/docs/pictures/Find_Sequence_Diagram.png b/docs/pictures/Find_Sequence_Diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..c55df054b13f77be9842874c0a3eb52843759989 GIT binary patch literal 53864 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%0ANsZjtrTwlt>65exiI2AObMinpwDi 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 literal 0 HcmV?d00001 diff --git a/docs/pictures/Simplified_Class_Diagram.png b/docs/pictures/Simplified_Class_Diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..21f4184549e92009d3cbc3417f1752246e5fd4e3 GIT binary patch literal 63584 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 Date: Sat, 11 Apr 2020 00:49:37 +0800 Subject: [PATCH 341/415] Add table of contents for UG --- docs/UserGuide.md | 36 ++++++++++++++++++++++++++++++++++++ docs/team/nigellenl.md | 1 + 2 files changed, 37 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 545806896..b2a1e310c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,5 +1,41 @@ # User Guide +- [1. Target User Profile](#target-user-profile) +- [2. Introduction](#introduction) +- [3. Quick Start](#quick-start) +- [4. Features](#features) + - [4.1 Usage](#usage) + - [4.2 Basic Commands](#basic-commands) + - [4.2.1. Start Activity](#starting-an-activity-start) + - [4.2.2. Continue Activity](#continuing-an-activity-continue) + - [4.2.3. End Activity](#ending-an-activity-end) + - [4.2.4. Abort Activity](#aborting-an-activity-abort) + - [4.2.5. Delete Activity](#delete-an-activity-delete) + - [4.2.6. List Activities](#listing-activities-list) + - [4.2.7. Edit Activity](#editing-an-activity-edit) + - [4.3. Find and Filter Activity](#finding-and-filtering) + - [4.3.1. Find Activity by Name](#finding-activities-by-name-find) + - [4.3.2. Filter Activity by Tag](#filtering-activities-by-tags-filter) + - [4.3.3. Chaining Lists, Find and Filter](#chaining-lists-finds--filters--s) + - [4.4. Graphs](#graphs) + - [4.4.1. Activity Time Graph](#activity-time-graph-graph-activities) + - [4.4.2. Tags Time Graph](#tags-time-graph-graph-tags) + - [4.4.3. Activity Targets Graph](#activity-targets-graph-graph-allocations) + - [4.4.4. Chaining List, Find, Filter with Graph](#chaining-list-find-and-filter-with-graph-command) + - [4.5. Tag Goals](#tag-goals) + - [4.5.1. Set Goal](#set-goal-goal-tag_name-g-duration) + - [4.5.2. Delete Goal](#delete-goal-goal-tag_name-d) + - [4.5.3. View Goal](#view-goals-goal) + - [4.6. Automated Cleaning](#automated-cleaning) + - [4.6.1. Activate Cleaning](#activate-cleaning-clean-on) + - [4.6.2. Deactivate Cleaning](#deactivate-cleaning-clean-off) + - [4.6.3. Set Number of Activities to Clean](#set-the-number-of-activities-to-clean-clean-n) + - [4.7. Automated Cleaning for Logs](#automated-cleaning-for-logs) + - [4.7.1. Activate Log Cleaning](#activate-log-cleaning-clean-log-on) + - [4.7.2. Deactivate Log Cleaning](#deactivate-log-cleaning-clean-log-off) + - [4.7.3. Set Number of Logs to Clean](#set-the-number-of-logs-to-clean-clean-log-n) +- [5. Command Guide](#command-guide) + ## Target user profile University students with poor time management skills who are struggling to allocate time efficiently for diff --git a/docs/team/nigellenl.md b/docs/team/nigellenl.md index 72e355562..5c66a1029 100644 --- a/docs/team/nigellenl.md +++ b/docs/team/nigellenl.md @@ -35,6 +35,7 @@ ### Contributions to team-based tasks * Made extensive use of the issue tracker to manage enhancements and bugs. * Did refactoring for commands by creating command classes. +* Generate table of content for user guide. ### Review contributions * Discussed with team on how to further enhance existing features (e.g. allowing user to edit allocated time) From ad6afd6af7a196cbc9aa5a9649554fc8f7eade4d Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sat, 11 Apr 2020 00:54:12 +0800 Subject: [PATCH 342/415] Fix style for gradle check --- src/main/java/jikan/activity/ActivityList.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index ec9c8b618..2623f4c14 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -180,9 +180,9 @@ public void saveActivity() throws InvalidTimeFrameException, NameTooLongExceptio } Parser.continuedIndex = -1; Parser.resetInfo(); - assert(Parser.tags == null); - assert(Parser.activityName == null); - assert(Parser.startTime == null); + assert (Parser.tags == null); + assert (Parser.activityName == null); + assert (Parser.startTime == null); } else { Ui.printDivider(Parser.activityName + " was ended."); @@ -197,9 +197,9 @@ public void saveActivity() throws InvalidTimeFrameException, NameTooLongExceptio } // reset activity info Parser.resetInfo(); - assert(Parser.tags == null); - assert(Parser.activityName == null); - assert(Parser.startTime == null); + assert (Parser.tags == null); + assert (Parser.activityName == null); + assert (Parser.startTime == null); } } From e026052350d2210b0131015e7cc572d84eb95375 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 00:56:13 +0800 Subject: [PATCH 343/415] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 712149122..914d127ae 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -80,9 +80,8 @@ _Fig 2.1. Architecture diagram of the Jikan program_ ### 2.2 Class Diagram The high-level class diagram describes the structure of the components -![image_info](./pictures/Simplified_Class_Diagram.png) -![image_info](./pictures/ClassDiagram.png) +![image_info](./pictures/Simplified_Class_Diagram.png) _Fig 2.1. Class diagram of the Jikan program_ ![image_info](./pictures/Commands.png) From e2cf58894938139dbb9bc163ce97ed2e37d476d0 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sat, 11 Apr 2020 00:57:22 +0800 Subject: [PATCH 344/415] Fix text-ui --- text-ui-test/EXPECTED.TXT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 4313b455b..ac804c0c9 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -40,7 +40,7 @@ activity 1 was ended. There is already an activity with this name. Would you like to continue it? ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -activity 1 was continued +activity 1 was continued. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ activity 1 was ended. From 89058bf890e919874b758f78ddf4e0a8e7f881b8 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 00:59:03 +0800 Subject: [PATCH 345/415] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 914d127ae..88ca0c814 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -67,13 +67,12 @@ The users interact with the Jikan software which modifies the local storage data Within the Jikan software, there are 5 main components: * **Parser Component** - Parses the user inputs and calls the relevant `Command` object to execute the desired command. -* **Ui Component** - Prints to the user the output of the desired commands. +* **Ui Component** - Prints to the user the output of the desired `Commands`. * **Commands Component** - Contains all the `Commands` to be called by the `Parser` based on user inputs. * **Activities Component** - Maintains the non-permanent state of all `Activities` in the `Activity List` to be accessed by the executing `Commands`. -* **Storage Component** - Interacts with the local storage file, which contains the state of all activities, lasting -even when the program terminates. It retrieves this state of activities and populates the `Activity List` at the start -of each session. +* **Storage Component** - Interacts with and modifies the local storage file, which contains the permanent (lasting +even after the program terminates) state of all activities. It retrieves this permanent state and populates the `Activity List` at the start of each session of Jikan. ![image_info](./pictures/Architecture_Diagram.png) _Fig 2.1. Architecture diagram of the Jikan program_ From 842aaffd4305e0b36a79131c49034220b05b7e2b Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sat, 11 Apr 2020 00:59:54 +0800 Subject: [PATCH 346/415] Fix text-ui-test --- text-ui-test/EXPECTED.TXT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index ac804c0c9..00611a464 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -31,7 +31,7 @@ activity 3 is ongoing! activity 3 was ended. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ -activity 1 was continued +activity 1 was continued. ------------------------------------------------------------------------------------------ ------------------------------------------------------------------------------------------ activity 1 was ended. From 04d6f7f23fb7610238e0990953867abbdc3c4140 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 01:01:37 +0800 Subject: [PATCH 347/415] Fixed Image Formatting --- docs/DeveloperGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 88ca0c814..9af150e4b 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -72,7 +72,7 @@ command. * **Activities Component** - Maintains the non-permanent state of all `Activities` in the `Activity List` to be accessed by the executing `Commands`. * **Storage Component** - Interacts with and modifies the local storage file, which contains the permanent (lasting -even after the program terminates) state of all activities. It retrieves this permanent state and populates the `Activity List` at the start of each session of Jikan. +even after the program terminates) state of all activities. It retrieves this permanent state and populates the `Activity List` at the start of each session. ![image_info](./pictures/Architecture_Diagram.png) _Fig 2.1. Architecture diagram of the Jikan program_ @@ -311,7 +311,7 @@ command contains the parameters: #### 3.7.3 Find Sequence Diagram ![image_info](./pictures/Find_Sequence_Diagram.png) -![image_info](./pictures/Find_Reference_Frame.png) +![image_info](./pictures/Find_Reference_Frame.PNG) #### 3.7.4 Additional features (Proposed) Developers may include the feature allowing users users to chain multiple queries and multiple commands From 25d32ef9bc9beeebcd07f426a3c1ba0f0b9be3b0 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sat, 11 Apr 2020 01:04:28 +0800 Subject: [PATCH 348/415] Fix text-ui-test --- src/main/java/jikan/command/ContinueCommand.java | 2 +- src/main/java/jikan/command/StartCommand.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/ContinueCommand.java b/src/main/java/jikan/command/ContinueCommand.java index bfd641f59..20471ace7 100644 --- a/src/main/java/jikan/command/ContinueCommand.java +++ b/src/main/java/jikan/command/ContinueCommand.java @@ -38,7 +38,7 @@ public void executeCommand(ActivityList activityList) { Parser.startTime = LocalDateTime.now(); Parser.continuedIndex = index; Ui.printDivider(Parser.activityName + " was continued."); - Log.makeInfoLog(Parser.activityName + " was continued"); + Log.makeInfoLog(Parser.activityName + " was continued."); } else { if (parameters.isEmpty()) { throw new EmptyNameException(); diff --git a/src/main/java/jikan/command/StartCommand.java b/src/main/java/jikan/command/StartCommand.java index ffd475613..ce4ddea45 100644 --- a/src/main/java/jikan/command/StartCommand.java +++ b/src/main/java/jikan/command/StartCommand.java @@ -381,7 +381,7 @@ private static void continueActivity(ActivityList activityList, Scanner scanner, Parser.startTime = LocalDateTime.now(); Parser.tags = activityList.get(index).getTags(); Parser.continuedIndex = index; - Ui.printDivider(Parser.activityName + " was continued"); + Ui.printDivider(Parser.activityName + " was continued."); Log.makeFineLog(Parser.activityName + " was continued."); } else if (userInput.equalsIgnoreCase("no") || userInput.equalsIgnoreCase("n")) { Parser.activityName = null; From 65475112d673ab7ebf8e6348282905e29e111595 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sat, 11 Apr 2020 01:14:22 +0800 Subject: [PATCH 349/415] Edit the clean feature component of DG --- docs/DeveloperGuide.md | 108 ++++++++++++++++++++++++++-------- docs/pictures/ACSD.png | Bin 0 -> 86907 bytes docs/pictures/CleanCD.png | Bin 0 -> 65086 bytes docs/pictures/setStatusSD.png | Bin 0 -> 68277 bytes docs/pictures/startCD2.png | Bin 0 -> 38035 bytes 5 files changed, 83 insertions(+), 25 deletions(-) create mode 100644 docs/pictures/ACSD.png create mode 100644 docs/pictures/CleanCD.png create mode 100644 docs/pictures/setStatusSD.png create mode 100644 docs/pictures/startCD2.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index a951679bb..ecc54cd6a 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -73,7 +73,7 @@ This section describes some noteworthy details on how certain features are imple #### 3.1.1 Current Implementation -![StartCD](./pictures/StartCD.png) +![StartCD](./pictures/startCD2.png) With Jikan as the main entry point for our application, @@ -165,58 +165,116 @@ undesirable. #### 3.2.1 Current Implementation -The storage cleanup mechanism is stored internally as a StorageCleaner class. The StorageCleaner class has an association with the Storage class and thus it is able to access and edit the datafile which contains the list of activities. +Jikan provides a `clean` command where users can automate the cleaning of done activities (i.e activities with duration > allocation) and logging data +at application startup. -Additionally, when the StorageCleaner class is first initialised, it will create two files, namely a status file and a data file in the “recycled” folder under the “data” folder. The status file keeps track of the activation status of the storage cleaner while the data file serves as a recycle bin for deleted data. +![StartCD](./pictures/CleanCD.png) -Moreover, the class also implements the following operations: +With Jikan as the main entry for our application, -`StorageCleaner#initialiseCleaner - Loads up the status file to decide whether to activate/deactivate the automated cleaner.` +1. Upon startup, Jikan will initialise a LogCleaner and StorageCleaner object. +2. Jikan will call upon LogCleaner#autoClean() and StorageCleaner#autoClean() functions. +3. These two functions will check if the Storage and Log Cleaner are enabled respectively before cleaning. +4. Thus, by the time the user can interact with Jikan (i.e send commands to Jikan), the activity list and log files would already be cleaned. +5. Using the `clean` command, users would be able to manage the cleaner's behaviour (switching it on/off, set number of done activities/logging data to clean). -`StorageCleaner#setStatus - Gives the user the freedom to activate/de-activate the cleaner using commands during application runtime.` +The cleanup mechanism is stored internally as a StorageCleaner and LogCleaner class. -`StorageCleaner#autoClean - This operation is called whenever the application is executed. Storage cleaning will only be done if the cleaner is activated.` +These two classes have access to the data files of activity list and logs respectively and thus they are able to +directly manipulate the activity list and logging data. -Given below is the example scenario of how the operations work. +A status.txt file is initialised to keep track of the status (on/off) of the two cleaners and contains information on +the number of done activities/logging data for cleaning. -##### initialiseCleaner +Moreover, the CleanCommand also implements the following operation: -Step 1. Loads up the status file for reading. If the status file is not found, create a new status file and write the character ‘0’ to the first line of the status file. +* **CleanCommand#setStatus** Switch on/off the two cleaners respectively. +* **CleanCommand#setValue** Set a value for the number of done activities/logging data to be cleaned. +* Note: The two cleaners are independent, setting a value/status for one of the cleaner will not affect the other cleaner. -Step 2. Read the first line of the status file, if a character ‘0’ is found, deactivate the automated cleanup. Else if a character ‘1’ is found, activate the automated cleanup. +**setStatus** -![image_info](./pictures/FlowchartinitCleaner.png) +![setStatus](./pictures/setStatusSD.png) -##### setStatus +The diagram above shows how CleanCommand#setStatus function works. This function is a generalized function that is used to +switch on or off the cleaners by checking the parameters to the `clean` command. Thus, based on the return value of getStatus() and +getCleaner(), there are four possible scenarios. -Step 1. Read the boolean parameter `status`. +1. When setStatus() is called, the method will call its own class method getStatus() to check what is the status to set to. +2. There are two valid return values for getStatus() method which is "on" and "off". The diagram shows the former. +3. Upon receiving a valid return value from getStatus() which is "on" in the diagram, the setStatus() method will self invoke another +of its own class method getCleaner(). +4. The return result of the getCleaner() together with getStatus() will then be used to determine which cleaner are we setting and what is +the status to set to. +5. In other words, result of getCleaner() is used to determine whether are we calling StorageCleaner#setStatus or LogCleaner#setStatus while +the result of getStatus() determines the parameter to setStatus(). (e.g "on" will call setStatus("true") while "off" will call setStatus("false")). -Step 2a. If `status` is equal to true, activate the automated cleanup and write the character ‘1’ to the first line of the status file. (overwrite any existing value at the first line). +**setValue** -Step 2b. If `status` is equal to false, deactivate the automated cleanup and write the character ‘0’ to the first line of the status file. +The diagram of setValue is omitted as it is similar to setStatus diagram. This function is a generalized function that is used to +set a value for the number of done activities or the number of lines of logging data to be cleaned for the two cleaners respectively. -![image_info](./pictures/FlowchartsetStatus.png) +1. When setValue() is called, the method will call its own class method getNumber() that will return an integer value corresponding to the number +to set to. +2. Upon receiving a valid return value (non negative), the setValue() method will self invoke another of its own class method getCleaner(). +3. The return result of the getCleaner() together with getNumber() will then be used to determine which cleaner are we setting and what is +the value to set to. +4. In other words, result of getCleaner() is used to determine whether are we calling StorageCleaner#setNumberOfActivitiesToClean or LogCleaner#setNumberOfLogsToClean +while the result of getNumber determines the parameter to these two functions. -##### autoClean +Note that steps 2-4 of setValue() are similar to steps 3-5 of setStatus(). -Step 1. Check activation status of StorageCleaner through the class level attribute boolean `toClean`. +On the other hand, the Storage/Log Cleaner class implements the following core operation of `clean` command. -Step 2a. If the attribute `toClean` is equal to `false`, return the operation and give control back to the caller. +* **Cleaner#autoClean** This operation is called whenever Jikan is executed. Cleaning will only be done to the activity list/logging data if +the two cleaners are enabled respectively. -Step 2b. If the attribute `toClean` is equal to `true`, access the storage data file and remove some of the activities starting from the oldest. Put these deleted activities into the data file under the ‘recycled’ folder. +**autoClean** -![image_info](./pictures/SDautoClean.png) +![autoClean](./pictures/ACSD.png) + +The diagram above shows how Cleaner#autoClean function works. This function is called whenever Jikan executes Jikan#main and is used to +perform cleaning of the activity list and logging data if Storage Cleaner and Log Cleaner are enabled respectively. The number of done activities and +lines of logging data to clean is set to 5 at default if user did not specify a value for both cleaners. + +1. When main() is called, Jikan will first initialise both the StorageCleaner and LogCleaner object using StorageCleaner() and +LogCleaner(). +2. Once both objects are initialised, Jikan will first call storageAutoClean() method of the StorageCleaner class. +3. This method will invoke another method under the StorageCleaner class called checkStatus() which will return a boolean toClean variable. +4. If toClean == true, the storageAutoClean() method will proceed and clean up the activity list before returning control back to main(). +5. Else, the storageAutoClean() will not do any clean up and will immediately return control back to main(). +6. Steps 2 to 5 will then be repeated when Jikan call logAutoClean() method of the LogCleaner class. #### 3.2.2 Additional Implementation -`StorageCleaner#setDeleteQuota - Allows the user to manipulate how much activity is deleted when auto cleanup is activated. Currently only delete the oldest 3 activities.` +1. Currently, the data that is cleaned up by this command is sent to a recycled folder similar to how Windows recycle bin works. -`StorageCleaner#setTimeFrame - Set a particular time frame for auto cleanup to activate. (i.e auto cleanup after every 2 weeks etc).` + Thus, it would be good to have a feature to restore the data deleted in the event the user wishes to recover some of the activities/logs. + + On a similar note, it would also be good to have a permanent delete feature built into the recycled folder so that items that are too old (> 6 months old) will + deleted away for good. + +2. The automated cleaning does not have a lot of flexibility as the current implementation only cleans up done activities starting from the oldest. -`StorageCleaner#initialiseLogCleaner - Gives the storage cleaner an added functionality of being able to clear log files too.` + Thus, it would be good if the `clean` command is expanded to allow users more freedom in specifying what activities to clean. + + * `clean /n 3 /t CS2113` does cleaning on the 3 oldest done activities with CS2113 tag. + * `clean /n 5 /i 1/4/2020 3/4/2020` does cleaning on the 5 oldest done activities with dates between 1 April 2020 and 3 April 2020. + #### 3.2.3 Design Considerations +The current design uses the abstract cleaner class to create dedicated cleaners (i.e Storage and Log Cleaners) to perform +cleaning for various data files (e.g activity list data file, logging data file). + +There are some benefits to this design. +* Creating an abstract class reduces the amount of repetitive code as common methods between cleaners are abstracted out. +* Abstract classes produce a more OOP solution as different cleaners will handle different parts of the data. + +However there are drawbacks to this design too. +* There are some very similar methods with key differences that cannot be abstracted out (for e.g different parameters, different printing). +* This causes the CleanCommand class to have similar and repetitive methods to handle this difference. (for e.g setStorageCleanerOn(), setLogCleanerOn() etc). + ### 3.3 Storage feature The Storage class represents the back-end of Jikan, handling the creation, saving and loading of data. Jikan uses a `.csv` file to store its data, formatted in the following way: diff --git a/docs/pictures/ACSD.png b/docs/pictures/ACSD.png new file mode 100644 index 0000000000000000000000000000000000000000..106fed9cde41b4a314608abebf641f995eaee2d4 GIT binary patch literal 86907 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 literal 0 HcmV?d00001 diff --git a/docs/pictures/CleanCD.png b/docs/pictures/CleanCD.png new file mode 100644 index 0000000000000000000000000000000000000000..fc69b07ba9a4c2b5ce5689f444afae0dbc08927b GIT binary patch literal 65086 zcmeFZcT`i|8#Ne2;S~jpfPgfmD1sCz0@5r<5fG8y5kv%}cR~n?Vx%g)2?Ela^cp~_ zbOGrl^cEn}5+Ia0f%o@)GqYy?`(|d%T0dMaV{&uvx#v7*KYQ=zxqN!|RDqJ>Dg^`r zp;S_odk%q+O+g^%p8Z1x-l?)qZ~*_DwS1uZ00Joty>Rg29Qgk=bH(SX5Qx_e2*me2 z1hNm_@?C;JTm>PJ6;lZ0UJL|6?~qWXE(JayGgDTOgB%n8d_!e~gLlq5DC#*wAPn)u zza&boei7hJau+4l$K-QoDJbvV6MS&}A8tBY5&qpy0DNwj$2QzH)J=nE`U0lU*H;@6s| zg}h=JzcP{uWYUs-&iWqEP$Kfo=WJi!LnSL^CmcSs|GQGROq;~=Q?))RR+~aaoCK^6 zvFaQq(o-{u!Wr??SHHeMs7_xwar%;;yz*r} zKXv-ne-Hcbgh2iqAtyob-@WkPz3|_?@ZY=uf&4d7or@cv#w>Yx3!69Y6B6k$8!VPmSXek|bY{3fv!2Ke$mQA41X0Vt?zAS@jV`! z?|zd*!bgktRg&~w%kOXYum?zDCLTjt z&XX{MyRU!Wcj-fT?UlBm{*?(R1ASQfEc*yeJ6%$xM4u`;%RL&xKz{qdd2poQTTTUp z+%6f1W=tKsnZ6CGnxtO*+Zp1pOjBa2e$ZaK7`8rnd6_pfO2*Su_50Y^%7jK{pbN}^ zHc3}+f9?mDh4MFfIgt_{UN6>rVks~KRP}{=h8riuJLXzg)&=2E`mv*?TI(H=t)SQ9 z8#eGHT&_gwr1ZV1ZM52tVNdt(YWbZ$Gx;HkF!Y6ZY)E289pi_=W1})1Gojg%JB4cO z5c6m*ZsMZe2(Y>t$+BWac>g!AJB+c;0L#z(H*7g0WVOkNMcwc?ZF80p%LQ3dgAjv8 z@BwE(THoilQ@Crir^zq1*`OkdvbZ;J!M+ItGG?b92t&xp@|(U>j0<7<>si=;*=uL$ znVZS4k)K=my~}VI=lXOai6Haol*;X_RC(cj+lnz0ex$~IF5akWNd4JUg%OikWzuyV z7cBhbc%Wl$VZY2I^(ApGpM7nJ=o=4F_{g8_P7R6iy^1*%E-hJE7dRwlsM%vjFM~B| zXMO5!e~WJd-%_TSR3~kwqtMOr8X4oMPrKm5U3`c{&IpSsRLy5VCGQ5+#I|*P>68$d znKEaO^|2oDF=^~1F-b!v+OI&e zvhsF~vKU(W$Jf*-g%?KwBt6S|&MkjuZ4;nvU)X}gcVoCaWo~ZWLUlx^3mm{}3IE_i zFh989&R^Z~LS0%l2Fk@=+mVG{kM(*ZH^^*X#>orWgPv@+XW?^yo!MjE+kOyCxx!yP z?ql-lLkMI(+8;K?fve)WW(o3VH3o^v+#|>Vk%tL3xpJwm} zHN5NK^^YapABLG&Cec_8?Q`4huGF4$43AHB7+(|~dm0xq2BRh`!DEn1w-7!p;}J#z zHX-L6AalPi69q3slTTvbTwVOdz>j3jsD|+isnbC)j&%O<@~5lkWBf0m$x5UVkHHqn zZMPJYE1K%>b(k5FzuP^sDAzcHef-DVv#o`Z;{rOpR37|ai>{V3N`ytHicPD>9zpqq z`LOV{#~5{vU3EFCLCGW#>F>Qr4RK;W*&N?^+Irb|4f=lQRKb*KC9&%SfeBRFj4Q=W zBYF<1r|JBe41#H6tgM@Vz=Ua)e!X2GMd2)vyX$dWNR^hnV?Ypl&#UsOVFo+kGbu>t zOuCM_29z8o6g^P@kyU8wSwd9jztGw zI#fNIlb5fJ z5U}hL2NRKaLR^)gu(xu#G;_0MElcmtoG+IMEYWbJd{MV(YO^T2rXfE6(+md|4Kvkg z^@R^#jgrzG)Yc-DSST*kAnp^E*ZIEK?c2%WbD+T=<(aFvVNcO6s(T*p_Mc|<1s=bF zi|-3;#o&AdPl028=-zS_w~W^Vt&X4@ttLip2(rok5R@}B7AH8o)=2L2on{BY+?RuhTarA zb_ZUxN!-+u6vaKCV#W<&vbeJ0No)oqk+YQ>ZI(cu!S@@8@-qzQ?o*p{HUWP_>lil zme(b&>c?%7)vsg2`=&3~3c&yj*n$#2cJsxfU-soHQo$Dg!ln1kVfZghf7T~qqb6$K zS={B-#%{J3h|ZQEV@n0T>V@kJ1+VXrh)S%MW&6DErG42&U!66|KOkP<&gZ znlXgrgBwE5xdkErhe7$L7d^6SZZCas)lzQ1J$1gdBRhgeISEy|sw>p+?8l1lYc;mO z9<=%-E;&#*Nv48_mmR11PRk18*SocAnX=o|zN80p+&-8&;6B<9fCf9uIro>!^mWN* z9ldW^w$OUBoMV$?k4;1HNJgnhyZv$wOO1*)$(SYALif-37etvjw^%_x+#(3MLO%1t zPS8pPqNLrdqo(6})7?IByDbuin+ZU^M!rta)*vk7$~OHz@_ouIp&xrTH0rHp+k?ho zp?>(}_#GH5yNOJ?+y-vKrI%!tmo|Shr*!8h3YNBJndV@<+g@I~0fOi|Q(Y~-er`dU zu&gy^>SQ-rr79>yyu6V`B&nH}2RkC`;W@M;*=!1T=-T&A>BW>$>rUx_x|;9li`e4aq2CEx>=WBx567q> zEtJa7&HxBxUb<=-fvp@Um1%kWO+;~Y!*5hAn|9dZwq8u>ftiq%HtnR3PE)7wiu6J9 z;wyaA3NE{&dSa5Ngy$unWL#yr?+vyRz*H3K>^F8gB5{O}S2Uc@X%DejOBEHO zgoaxxh=@cAI7_U3M*?J*lPg+0CamsQZpFv=y^7GWT6-Ppf{!ZV$pgVpBne;aVB&pz zvI2a5dKo_Eg^;JTFhct$ncG&;0tT#tYx*W*iLd-r?LuC5dw%Kk8WJSHgISupt5XFD z2|S4-G|i>-3NJSB?GG!EeSMKcn7d-k2oNCcH)dWmO?rI=#Wq~K?x!7dxh(;&z+9Et zUfJG;Gr`uC;T`}A)*eFlRF|&VZ}D-}vc0*KcElM$uYU&;GqZ$7s0^NCe}))3S`v4KV#wZ{FaADA=SXR19q*$MMX`{-hv(`^9-p!xlJ5Y? z3)j@-jnhQ)M6c@CX<=W;tq#YGrG;7LebJ5!Wnm(QkRlbro$~@en-CIHAc${3R?&~dtJI=0nAt}X0VSn^QFY+Z{QPirG>Dmes?3&)K2DD`z+orxXov-7+l#2xL*T>Uc zCVXp$+L+Do@c54x(E&Z<%*!@)BTOL{AD)85JZ&qRix;{0nM#rxfNpJdN$b$uLZ9*L zk9=9#XMX(15XxUnc5WRvb|l>&@p5jqkn7Li`62_uOnQzEFzR*OzB1`#BUef?o`WIN zycnX~ub=wkZ}HChIf!|}37?y~zqL}uEgy02u~NTd@9+J*=dOd{yg9XoPMtS}Lx)n^ zZGL5!_Lk(N{#jqBPF-w^goek1l#gr}r>4}C*48~hamy5mw9Flu_Uj8bmY3MTRUg=@ z5+H7M`dD>r_{*Oe%32|eAcsbuk%#VDr2Kh+)zVA5ng3uPZEdO%z*?6oXAICQX@x8T1nw-7oKw(hb&SB2g4mU);4tw zLQx#*F|Ze|hwBB)yG4%x)HyG!#je?Yamy2smGQ(al|-lJuAru0@|jD#k<=Rq*D$cI zl6TszCPrP5KNnu1F^oL*MVlXyoAt&g0PqQ&-5XOVkcPBKpDyLu&$WN?^W?%0KL{1b z8n|&w%)muUzcTOrT%8>#NwV0V868d9DBIlg*eQIVfYa3MlHv$UmA%rok;5)u@#a<4 z{N$J5oNhpAZ`@waUoaM2j5a!SS5d=8Dp(Ms$ zE31~vFn~Kx9;g-uNdHL({Put@mO3)(Rj$#C^^YkPJ3o1nq`1NsHX(w%xwlG=uq3eN zG>y<;5F%NXh_+n!NVZ&ytcDiGJ%La?TSU4*NaicM3mWp8hk#&=Ay@#IkuKZ=GV{B@ z!M7?$v2JeI8WA2=ho5O}wf!;Y$Sds7Q!Z@D@BR|Z=6n9Zxf3xdC)ju260bbcnv?lZ zIZgoS-;8Ej&@07GM|O(y0lKQwTuG_!v86+HRvH@F5SOSZ=_B~#E0COef0sx1W7O&H z{&9+q4W(SczHZa!DHg;(YD^M$eL?#aRcxOStE@w%cW01hIUP$S9;OmU_n{fh`yup^ zHL{^iEF#q6Hwv@WQdaaR&1bRD-7uJN?TldZDc{L_qoeSu{<--21*mY(FXJKyCuh#q zf`EnwUINt)ATpisrLab{bc$W%!-@heW1&K@%g#kxYLCzjA#QC&Y=79ilmU>AyJo%` z+OKcE^gBJ7R=mt7=b*}>!w3g^)6vs0Cbe9(c`bVoj?MmDyU7;26$ip*^;#}~?~h3| zl!0|a^w#NPtRXJ5JM-qcyCc^ZdDnJdj9_?TMRI8KRc*Rhu|(Z7Up-H@Ld=t=ob6S@6-vu-0}4}P z&k~nlkc@;dMs)ZafTbIHerg7J#(QC*h)Xy;eKrM%2-2}-`%xw0mTJcJsUi#$V~3H8+)$-bL9>x8aVG_D^VwEfpTTI-)H3k67E831+(u-T@mB%Hm? z!k#0g}Rv1GTvLkieH}!?6-&H?^Z$%5sFAFCO;v zTr4juf9$x{tiGh9E;e<*m_b>sX6o2j3LP8s_kLQnMh}g|UC+Jr=S+QV(OE7c3u=6l zbYPYhmPgi1IfVOQ4}}(*KiV#Vo1yRZq4M1!<&)~uP&2ekggM# zbzW{59c8-V9mxH`)JC9tQo$Ahlmd~T$BhcOO&VP_Fd5M6`PKRx#TO82EI23QsRx## zw-`60D7nsj)HXJTJ9H(7h(15@&+gNCJsEf*a3~&D+2LQ{1+&}v#zl@Fp1dM$BM<_l z5aSQcmsM-iis<3He=7^}1I^OpiQ}OD%G5S(sQ|1gVctyQN`pP{#g2e)?|7xxN7uW&_y6JseAxS8k8qc4>Av$=>_f8B#8#S*#4y?*vhc8cF>1Bad-(zQa zg)Y1!8}(_@hqYkhCtW<`cc}CfF?w#i_b=iAtk=t(qUFQfH^zDLt=wOvQ@$Lh?pkL0 zS4}KyeTCqkS{KOYf9c-!ZMo4>pZYH^_YF95gs7G*dwdXwz(>e;FMu%2o~CgcxvJSL zlBAoet&f3F_j13`^248-8NXMQx*U}>RBa9kay(7LpJwJoEj|L%wNZ)lm4(`c;Uzp*c#DIMVu~6UIJaz#c1NQ@;Vy7SZBKEGFUsOsff3=H*V0tFy{e z2OtUDww&FF5*rkr9MX6ipMvTx_JK161q_?F+P>?3$@DjW_vD5cHDm2#IohOy4lj2a zU&s5WboR^Y@Fi*6BqWdvUih;uk>KAYD}r282qn?Mp7s6LDU4eKNH=!~)u5MmYGRXP z7D>e>1J<>(&JuL%#4y|3QWQhe^rG@6CrC^aE}iN^P072!^uUl(rR}WK{86vkTVERS zb|-qGB=x6$5d`v?w-I4MO_gA`M+z z2|^}%;V=3go=ynlbMf4;ngYOS(vTg1lt?2M;>r--o_d??!y3WiDmHv@pW!g%P*RA; z;Rq55Or6M(3&11A#s15f2gEtT8hb*(D$9f1qm@A<1waTYn(P+}QbA1L|4aYkzzW73 zZz#S>(B8@-u2iQ9^bX?jcOwi395)EaCg-ZbImokrnG{Ltb&zlsUaWtpG~~0o#~%i= zmRA!YWjDU(F|GR`%ohTgefRGG1S=(g#IWX6ZPoIA0@BF$0xA9dxp`4&|I+~R*Ycbi zp)8vvHi(5=e{GDP61>08YC-66n?<1)|^CY~mvVoRqcbi2*24 zP>z;u*j|r_~H{V@y^7b?%YPsY5*XTcdsdGf|WDi^&6jj>kU=Xs1|b zV@}{Y<%p{QD{wgkrzm!)IzaakFk&)R4_70rtlvk@Za|z<8C?D_Ldr|k4`5TuRTF0## zi676#!k3sZ{pj2^QPKO4nmU0mIoB0ikaTL8@Ark`lPMuoBL6oDp@=F{bLT3)mn{&$ z6=_Hs2zijP3e_U*87b^5MQ6UnesMdv23&|dzLHo^d69(O(zvnP!29d#a@WDnwRQFW zEn}k+|Fadig@1n?xV;EhJ!B-;1TX__5znura9)u4%INkg@fgFK9hcf-!gZ@;di3p2Be|xM!PVa-qgx+~Z!+Y(dP?4-2CUZ=zltEjy(!l_d7>2d zRX3c^4|Wy~ZpN*M4FYGy|6&Mv$wp@vFi@Y$MLZn*>0E+$mAE64xQ7KK!*RCdwUt$t zyE_EOduqqbK7FLOdj(4LTjyAausWu#nO~Cq9dP1V853v4e)s+JIVm2)VTwryGsu<* z6`SA^OH0}-h=LX08?hq1S0{0eL?6xs83ibCc0+mX7Cl11Yg9%Z?m7h-`1k?7Rr0r; zo7LsD$r6nQy*5j&MWSp%3!`Y)^3J8%Wg9esaNb$*u+iVwNW;q}5 zyQg1@K`>!X7;#f`zM%Ip2q2Jlid;Mju`N)V>?ud z6$T*b=Wz=K+-uMwaSoz@!Fgyc>IktI#jZrQY>NF8>-!OF46xF~9VNuy3FM z#9U^b12n`cVZW(;(}GKK{dTF|^%CCOH9}s-Mh07~E^U9Jh&B;=5oFNRij93F%Nl%* z+SQ(&J{$;lI!m}6sTXJ$6u9RsBcO+LxoEPlOaAIp<(v(-MI!a zpmun5@`FHuxan3#!sWHKHDXQITt(YLuWEjAXI)z^BD=!Nui$7O*OFawJOHYLV(^>5 zNiy{5V$68#&k4%g4BukZ5WS9jxFgK~a-1B2AO zJU-Bnz^8Eje%sv0NUM9DCN}Z0icw6Z+>8D3l{o%zneuz=HhQfsjE(QDNa-Z8`73)M zlG%%Jv}33=O$o7t^%HNWAdW{R%Tw=n-}4Zyl4v@f$8!4zYXhbIfTEBIgp0dAXa*LG zw!#OH9?KJVxte}^FRP5)unP!c~DJGU@8I)<`H+KRe2zquM0-PWP?;t6hp*$=6Y`_pcCxk$V8_SZcxDg?JihoSAU>s}!X6COp)ai>xu zCHWTULBO+0zEK+K56fy@=r^V+*vdWJVrK^xba``sP?bNhVI`&p)k( z28KUlZzUuMajLu=Z@|qBIQ>GnR9h{v7_A^%6i z89@2CDCjxg4V6=cG+9$~!_2{=D>;z;-g>Tk4;e$`kH@>(^lckDIv3GE#;bepx1eCZ zwX&O}dtEUQE4|ebz`t(DV6%tAJZ+o`2=B9!o7AF=afUCT1c(+8dZOhAl2wuUatkJP z(7Gd+r|Qn)PKI;Uvqva}Gxxuq_5rmdZ>OkxXI}>bWX1O`sF2VREAv0d>v4$qo)(wwNmAO)cDL7E?#2E5HF@BI^yq+f|g&_P;qFzr3E2NN7N<(^i1 zKiBH=kIs;@g^w|RPHy2+2v3a~s&3V48!flzOhzl3;33T7|B()$cpuw(A+Szt+s9T5 zoKKe)uo-*z#?n~A@3eUAEo=wqWLTKry=wXLqYvX-4%g?(A9O%!!@O1*?M;N&w7{pp zsZMRwmK+u)A^bbwkgb%f%qikhtTP#EiDY|4k)%YP&K_QZC1 zY_g7=94J+BCv2CFMtx5hy!xRWtyO521>7(8l#H3><_!DJRfWMsM?GMwmt|Pn{dP^- z!!4=KWG;{3l~)z?Is~FZ%A;9wvWp6dl5KOMmWvq(iuR=9P}olJFw+=MPh+4g4;yyX zIopd;ha#UO#^c{<(+4EMRnM&g3MKlB)7yxU1_Qg`?|bk1o_mGID<>NQi4B@-n0=md zcG1gC^OZ;OEDB}2gLa{mMfybr&3~-+LH7{MzH0Ik$S1ln&pq2Zx~nB7j%H|3jkyJ2@E|X6{_r|Iz#Q{rlIuhz=(G{&m+%2Pl zImTy-Kz*D$!TZsOjNOMlUUm=$eCCyVH=zag0pc#|oc(Hf6)#OjLA`v(Bp@!XI+LJ7tsA`kRv{cvccikA=s<88 z>8`e+K(nXN{sRF7HT&g8Drv=m1)k+|~(PV4z{u5W*>h z0k6E*V%dAi^RE$|Ux+mwP{bz%Ftz+#K5q;~##Ojq+MOt<+nfGg|6{P0iX><4``8^BPmOTGiCEIe_1 z>))nV2m`lVzGq)RL4<{^Z5p(D=p^^$>Ja_a@&l>9=%ZWZkn0oP?%Qwd179x0ei0Gi zGl(k6J)}p_E_cZ0~e>hSAVs=4MQBhu?Ka)Y>fSE+F zWU?R}bKGN)GXLw=&U*JS5Kk%B%@h4Em~4u8#QseD%8^@?x=x{iTh9QFIn{1J^U-WD z(!)I7y8QZyFr8l1H8uO!@%sWCzomRf>k`j;f-c@UC79k9T1-x?If0-57u>Z| zT=+kGb%c=`&#jdS;v-gIAJU2rR+GLYcC#ATRdQ+P8|q>6KNtH^-OHRbx^^>1J1>A5 zvD?_&*Y_NofAS4M|4d&db7C8AgvQfPK;is@HVrZWOzpPrk84jQ<|AI)+ZO<3PW)lu z(5w%>qa4j2Tvk?wM7}oi@bKQF!3NP7yc(!BsJ|9kZvUwVfwAl@d*S?l5(y_?Cq3(6 zt_Xv{Om+ux6QNBhA3$>=*SB|392u>imds3;yDst=h2y)UqobhHcf#qU;|-$w&gu65 zWV(JEFM1nBdaM5aMGg~KiI1B>OwDNOgRi4twQw+&Tz4JctJ}4fI{Ai-6B83enMV9^ zz2VE`x4K6*+aY0Zzf9O2u}sSQ_ogz1Nto+ptlw;>(GrjJMI8(>5MTT+X)|{knD{za zeF5UiT0;4xX_35HnjbMxfmmQt-8?Z^elnMI6;vdPQK z1Ln#uhb{3hvHy4!@sFwO%KFpUR%*L7!ae4b25LS&KH$LKH_ALDhENNtdcBJG-zIBf zv-GZCkBmB&pG4&~IGy8=k^4Y36T~(3q~(?YudlB^17u(zs2t$d&Xd<4m0J&F4_7#v zOW}siv(diiRZpqR-w;+Lp z{qzP%G7AgU=g-YP)zQ&8=sDh#%bXhI_rI2wm$&W=nV|7|?UB5x#l^)$H7ozG5$-xzy-1Y0C1qvua!qtP zhU!>55(vj>kF4)KeUz6gh+?oFM(z`IVv`=`a&qH7gtgwuNn`9fIPlcZ^}V;evJ${s zP$R_7uAQe(2j;WzWm}jyVYQgU%-(_-B3OIMT)sUe-u%+i5^`Z-p<*RFXFmk(z10PU z_6`nSu^G(Gau*}0nd~Qlm_K)ScSmoASth~V65J;}Eqa#o z-eJJFCD$ubCymG;*2FvaB~`Svv;=e4vR00sbkD^XEK1(HH?xl^2zBm}cGrAZ0S52U z1Dm9wH*!%&WdIMl2AqHc>~3~5``>qUH8eDGfx*Pio?o-szO=HE?Osme%X51FP9Q`S zzz>*l#PQ)q3zL1*%0Le2o1a9E*;Vtgv#(b!CRS{=^E%t&TV;ZtJa%?=c5!iODjhO5z~+-ew21k(o+JfC23BC%zIv@p zx9Fu3+E^$!IJnSzZ?ocHvjfaFxT&5}igh>^WzB?-CWWojm=y=)L zQz|PZh)aAuX>53Sn7$^@uu=#BD`o-?`9^WFAomX@(1%9o){ba_9`Ei9*~8`9P&Tin zWW%w#wX!j@ot1&!KYuh&MsG7w`(ArX&Wc3#2}MM1o6M|)NUkHfl%wYQa5e>~8y=*- zFMtGZZKgM2hNfYMh~|gZqUhbbEnsRHEE7Fn5hHwKuLmJ>g->4-I}L$6x>R3yobbaN zUC_JZ-L&8eHSnP;oJ~V=55hDd5c3ukev%0ay_x7S^SMV71pRCxY@Hal<5u{#rZVjx_%(qjj2XVL~&q zSZ0qmecQ;947pC};)A%>8nKzbkD;LmF|(mTuh2^nQ^U4mfOia||6`T;QQLh`qtvuC zF8;cMP2!fE1y}HRGg^|BEjo&j8OmnhuuU~#UXAC#9Ox{c0A*EZaGDMYAOeD2EC{$A({0_ zzXU^Qm0ye_y!mF_kBbhbX=JY!;xIewoB;Cl09=g}3U`Zhu(Kb{n;dabNpJrq3FR}9 z*@U~P-CO?dMNJQ(@&HNEaif`DLGC1q+rqdAE~xbM^onVJrkSD+{=h)~DsBM()&klP z2EVfoL9!D@X-_INWJLdZ^pE!yMSZowOgw`4LJ9G8d+`;Ei7+8H*x#Sz!?3W&q~>X`suGH>H$!d5NV$vN_CqmcSv|4cE|x!Gm? zy?>oO0F-1Q^~ladX-Qxh5~8xRzn7Mlt`;oy$Q~aM4K9$E^@?vehsFZ_m4=;l?v}`y zY&_>nIv6Kvv!C6~ky3EkPUK{hWvRiflkm}`kWCI>^8>F^X~OQ@GPJsk3UM?S3k^?K zP>E&i-FYb2laC73az0WNz5AG1s`}6R;7w)Ns0B|%%jLrIBq(&EKw;J6j@c0JotbZr z*3NSMU(!M|xDk?CL^d&07Mq>OECo3giQ6e#h1XjsA-TGRX2T|ZdAfxu ztHUXe1Buv0T$gtj_>nu9Aq4===vmBQ9_GRlF~ncLVczX|D{3>?)UPJX0#z^jXb5Im z>Tf+MU>LwQCK);hX`gUxWr24*8cHeGhXZ0`fzJ6@(;k2Qt-Hma0Y0wKD8kB~|q zsU~_R3gizK29pUR=r35L`2IwriF+e8hq1>sLSa@H)E?!8bVQULe^=;~;WC@lBW*q0 zvBzv_zHZ4s-zGqs1GgxRBy$xSd- znEc{nW(au=hNI-h#ulhTt6aBh+5>-g+uIT&^&|aviz2+lo*00tc{V-whImM)xXcwOrOxi(9ZX6D{e;a-UbGm&ynO z$lznmeUHUKWa3w7tBAMpe`vNxO#cH3#XKd$RT!%ahPmW6N z)CV#XWVt3L`xUh}j9d);;?~?ciyy{70A+oC8JAYx;&d$XYLSP6Cv&2q>Kl#tH zSK2q*{gc(!44F2DkFVB#>cR-cNoSVX$>59IVXe}IUQ>li{WeMd-K|exzt_g~_ayih zsSau|d#f@#Lr1f3lf=6C_(JvaqFKA_%!dY_BS?I+;hW(}xhq5wCRhfb7x8rW8Scm| z6wU!lDl@Jwi+WdJ^ysWMs_Y>9VEDnuIWhn4QYgR<0D);e8J*0#yQ|H24#tXgvsK0> z6AvAPGVFhHmx9)(Q9)A8>;6 z1W^M33I#Cw#x4*fh+9D`>!alu)kMAQ3dxtoO@Aav*~X&(T7L&9G&4sB4X0x9sIjtZ zQeqPbKK?+?kw{qn4V$1$n;&0E6oXG6vB^R{XB`VgL?wZaP~VLQkk;X%wKn8&jq_BY zm@$**l*sU(1*EyG;N57=@m}Z#n@ONY|K{qE>b(+8sCy@j14P@jUq$XE+srg665l(R zh6@6@?)1b7y9yTGU~=hd8W-0EsKSw5Q$vtNe3>-kMtckLs{xJ`5etDuw(@|Z?*I9s*K$(qsl1)h>OQN@3M&&iqqOK@4LZDTQ}1zU4ZGd+9#lZ;S@Q>qI}48#rhH3I%D6<{ z^(aK2_U6HKbjtEC8q5SAgv!)NK#EoE;E;Z%baC)8DCOQZsuE#^trmi&IxzNYXC0V# zsjRQ=dJb)+-M2C1iQ<`IZ+}$L@PM>+XVbnt`dfk&JOVdNnwfi2OEoBRvQ>#M2iDRV z(=#z%9?G4@F2-*VZbrF!rQ-iP7pLCm#rY>x-hR!h;i zSZE0gZo!M1HpbTu7(GaCt=jWw$S^v+%YgPHv)2AmKS3Hi`)gWqek#TTBoZuZL_GXS zQyVY))%a|fk0_n@Skf)D@cNRw4w~%#Q!l)?P?a{IX@3$Oq&BP^M$6sbr;(KyC<|J0H}O^d#Ct{&eKh^!)D} zBj5A)A+1d!YfH&&_A!P@K3&qqCDCIJacXS4d+RzJDY{2B06%5#F8@Y~@lo3&h>rn3 z^jqs80ji+GeoEr6^kKn#>(hOYrd~^GifRhb%gz2&mvv*17c+#8+Dh3pD86(DJi?cW z!O9-1;ravZUxp%DHlTq8+`;ad0;B+*2HXbTzXM?b`uF7Ic7^Zb>OlHb>Sw2dIq#Wk zgmRx#0g_M#UFwP+gRN&kTWi4cZ+Ea=GOWwU|8Dv51k!M%8$x6ckUk6p=Q?#02-kk}~ zM-G85Dcg~;L|8NTKQ6|jY{%rDqEi}!jQD3a~A{-qYLe(a;C@$0U^PTh8+Yc>uw!Nk4 zJ^glNUkc3Xhehh+nv7#t`+9B9GwgRKXbNrNP4NP4iGEMahYzirE>KgAo7m|qH{HSB zqUPoeChU=e?lB!PyOVK=gEG=EqRKt$Osv;1fTX}`!mOXN>&Y_u%cB-RKXQAahxLR4cf>f_@9WKy5g6DU3-b1GKN^t*)x?gn`pKKMQ zP?~vHpm#i9?e$N3*xKJ0zYG)?#=a^;^XHIYmP^eGC!hdUqB?W&aAMy*5cp3a2~) zGx~=IjIfDkXnN;bkisF1`!;`O1=2VAY^t=7UqvpHW8qR5 zAM8p9_!0_6wdc89igZ49S3?igxtDM{wq@1IgXPgAJ|&s?u%ok2AOVeE;G~L=yGS@l zV{A2^{31Vg!Afddr3uc|o+Ibx8tv0|*k=P(4QKDx*Tt%<8TMz$)ocxO`W(OK4EZWr zL|}nBqW#U936!(y_H=fHK@on5(n%D!2tze-0Un9lytvH!w1;Y9P$s&CSCX8JH%~#E zY6)DjN$)~9_!L~pYeiZ_sOE498Csk7nXyW`lq=Y>Obb!RLA)rk_=^0&YE~k5`xJ;4 z(*~lG`ZC5@u_@`;`1%z#Q9;8>j860JNQ;OM;ko8Nntiof)b;@tyLt0NrmM>nXzRbI zD*H!wjy5(#?!L(?dB0RoFtQS;Ym9F=f`bzZz9pKWWPA0Wln$09$^5x(l9Xo)5XQOp zWRJOOO|^xo8MLk6#@&r)_x69ds|pGt(00x9a|UPUP`VlYA7%5N!y@5e$KoR_NBT? z8BdTE%h+hf-~9taf|J~5*`>S$sb{^(3bmLX8(r+%JrdX&sllWTy*YC?s-!b$ys`W! zaZ(=(B|d(-LtIQ`AFJ_@&$k+VtAVN>@lW>@dowdifXYp z34n$=JDK0=ytjemta8gB#Yv3~u%uqSr<(NKS~jKRk2#;Y2Rgn3i`OvdQ(wl;3dl7x8r5%HBZMcOh_E3@JG)AUqbO^*qEygk_sM-)m;)2e9_D_>`I z+**EU<)9XKbTBrVeWIbj;Sjm?2^ZZzywS4M^K)uLQ~1bQ72MmwYM%$04MHL~uOM_X z2HXT|WK8zn{DBPagoWF_K%`rn&m-S5gxDZ2g?|Gmyxiq$gJYXX-4RzJ0xFng>vaXh(>!?GCc)iAMfw}kp=>>a7t1?|?cb@{N!$<<)Tq}5fF zljlb2!kgNsE~s|U0X18kvXY}u~kzBo5g39yI;N%ef=u{v_4_~#Db%t zqZZQUqRJc#s_sLyG`xq<_&5@~oELg!7CV&2K`{enTQXGDta-UH6woH$WZ+l~=8GJscc7id*jDNO}cYng_y!;UA z*)ha!KLXi<%K6NADG$ycZ2pRBmGD9%e0K)MG?Q;aH+u}rbgI}nG)Z@Ka*p$y*b^qg zk|s-qA>plm#l8t_=8G!Sk}p>#bFbf>b_TDeI4gV{gDRNGUq|K~m);Z>4B`IpFrz0l z`yIMjfonsj&IDPv8*Qc%Z%EOWErA`@Q#x4tcy)#selUsUWiy;Uk_<%`Lto)fRN@V(6^&H)`P_WKpQ%**Vkv4KfIk%vN{(sF+cDUmD~){ zjy4MPO9MEWM9`AoHrG>Rmw^q|+n6|6U#I$7QyypgqhLI~MQ45OQxD2!%F~kXHh^e+ zNOGQuVicYCHko5+-LOVsfYpl+*9wlE-tK&+^BLdCF+1p>v63pb#U9}JFYNY~(~+J1 zTIc@eDq`Pn6{e%Yk-xwA{PE(Hgt52ge87(WV39K%PkjYj?>e36o{@sRzu#hJf04M|?ObZx5M{ z2fqx@r-I`L*ZC_^x_3V3i;y1{6yqvIj7RjU>JJ!|UfnmMSP1|q{P+C$CxwWHfg@rX zqDE+S8m_xInJHxzt1{Hhw7@n8PG&{~LF20TpHc{fmx)z6O{m zjRF>kfRwbas5pdxq#!L_(j68UgbvbDQqtWFpa`S1bPfW-&^-(_aP|Yfzu*6y8|#10 z{jam`z0Xn>%slap-TSlm^Gz-WLq4+pvwPdpt9aQj;i`N6VIz>5blcV*@(*v!R|sBG zA%ESfpsZP~!;Us{Bqf?xF1p&>q`wbXq*tUpK;3 zhnNjuX&7$!s^ql~d0AbXAqzThfjk}_E(%dw;sh2c+RiO}l2(+VBOX&bmN{LRo62?! z^lUFdI!=9~-n3`RL`!$;YU*w$Ientx9#deUn*nm9@>Ru z37Q)#2F4et_tnPr7sZ{PJQ_{V8aR>Gm9$V{P5KaJ*WLcWd-;3P^!(z&Ss4{4L2(67 zFSCr|x37u`5^c_#HFcIAlfE^%UADJPxo{f-3E^4s_yuy&Tu9&?DIlXFP~MW(H5`{N zwtn9#(}OCvx(E}h%|S8fWH_zmQp+P*RIn(vuhK}gAhC4R1TlCb0Le)63kmzvTNR&Y zVL`&z4ZO{MqxGRukeS4m)p9p&MLn%F@p6%(tMo7(w>xl9%vVlsSk8`JqSD-nPN$@Z zM#9Z(e6UF(FJrSi(ug22_Tac0lQ0AR19|iP3yFABTZ0cOx@2N=+7Ss@1H-5F$@ur% zfu!KEV!DTJQ;lMLq-%F?UrC@(H*K9Kxv4o_S)QKDPU)cdNwU0LYrJK%T0-j{b9c&N zHP3(4j@#09ln_&p?Y>r*g}(&oRMhw9$Q)vGa(K3;o42ka84~qEi-)^;W+YX+s^+coEnxoR{C5ra^hfMQ+HnK0z1W% zhX;JQHrjqo7QN~Xsb*j(_RBwPb>pF(s7KvAp}_d6lJm0P=Em9gV%Cx`<;h~J_G{+4 z#a#;49X*-s6>M9M5@hmMAI?#nkE_@wsdKSQN7b1M?4%j6FmERHFgEzO*1@@p0Qtj!dS$5tC@u>VOd$6Aj9ldZ% zV~uG}PP)pFTSqeIBakSb(hONda+(PG|7_)IjSczjvz*i4r{9)`GJdqXhn2Gb6&c=! z`S_e;l`4|m+rYW8EjL7hx_4iDAEQ%0Bq||%y5(^QHS#F<2rgR!$$0}Vhc;%rvw66j zHvn)b-s~P*ni6kcwYnAO{0vp0vXGOL%W)-6u5J<}n9u6C+aO>X05FV14sIH`Lq<4Y zsYxUYuayuZv5mc@QqR#8!;@QOWNYy4eH)7gmCW$++Gt>4jdVIr#}9Pt+QNhqi*`?m z*G8*t_jsecSS{~+YD{ai4dU2DRR`sI%-&sRqL+IZM;^;`B^}n)p8`#{i)g5rf628< zx`6Vts|X4_&%8D7i$o<6fKPf~3+>x8O_@%i-g?OImh=Krw9AwymoalGdJ~$Ut1S9m=$ z+(5Omm>!e*w7sV3euSH(m3UV1^}<^{+GZ&3lY#^GN|1<$9(&B&3(N?hyh?mgeu*am zGO~Yg{2CJLMF>o2b@39OmQaqpKu3=oe4zd$c5?Pw?Lc5Yj!;R=tC-IyC~$a0LG{iT zZ+Ip2niid!mV?S8FEY`i{(&}<7i#41x(&H7Y?)9xrDpEF!0>~C+o)M^H5NA0SVaWQ zr+4(fl}q>hVgO&S_PvAC%*0l6(?^?~U!#vdnf{#5h3DaA)ppImW9c7KJV-nq{!{55 z%NA||eO0Vv(|8#SD}%N|nt428M_))@cVY6jMN+glMyGGVYT7+#E1(F+?9nCzCF-ag zO0c%yp-T%%xFLzvLdwVykL^n4_A;3&ZkYB+X4x!VusMJ?aB_kJr$e32%Nb$^7^>><)ro!&Q-w}5H^!8d^BG$EG%CczS4B!)(7lmA! z&G|{W5iVHBZyNwM!DhgrYqYcI=VD)IZs7LTA$0%p+=!b*g4-5vBd4-iIPF5Cgayr$ z=}|^g_lZk2Ao8c}q@ju=12vo2B~4~}gmv2b@zVLRlFbXX#^!s^s>(^*1|~uDtQ9Ly z7tgIDiwahuV#8{#P3PAfqIlT&;%3F6cSVNvAw*8eLnuG%t)q5+rhp{EF}Yn8uQFM@&VMrzo?%WC_{qgkq5EE1~4WydClUQbF=TB;}54K%7j8&%ip?? z4vjB8?+6fuhH&2Gxg|tn;kUO)Y7SNf+vtOR#0Heronhx2_om4hBBeL={(35X#J!@MyNj@f8lX}>sbmIq~UCK8l!X44v zD}#j^Mt3)VYGPJ#xVA^tX>xsafsF0PbJE-fv&0DRE+1j&#J&sYdq*&)Z&P=*U0ZNs z(k$h2iP-TmFtBl#%N!F&xtHGIJTCQlS#xe{yeDd+yp-2UKsMa*M;+4Yz&&n%LXgA!LkLEM1T zAS2{P>ahM~azP@KPIE*=#L9+F;Qa)bnSrcNUR92NB!%c~g%f!?g%6yJimO9XgQ~Bj zVmQY%I&#Oqvmvnx-{>o2bXAXMh=os7{WM7EuA z5W@&0b?f%&5oTuQRdrQwAxqmC%Z3=9Ck*De1uX5c1C>^@eG1!&GE26@C(z}~z2BV4 zenoRiV05h-9FqQg3k-^nu9GP_x?i3l;rT|D*NCLBz?TaNSmPPIwg_I@b3@!z?sIN~ z5O|mOTnvgoS@ESpqsU4Nxz1xq6B4VN<5CiDyf%uw=tC>puO^)klu+K1A%IN<9$B*! zW8Kf*EDnwaxB7nfbl3kl)FU>uov)^2S3Zv5)=JAjgBrX-QTZUs1VMm-9`PUF{DUIf z5Z|74s-#DX*_h54^aF~E>BNaSPZA)=sA*!;(l|o6beI72=b>{}4RCFd0+w%f)XqTP zB?&in&Lfg6(r#ZyX(NJD;}%J+=8379TM&#o&dDp~{KYeO<${R&M{Bvo)wex+z^^$1 z>%V#H6?9mt==}AI1WuZ4rk?+s5nk0)EJ1?e$wr&W%gOke;Hc5Lr!`U?E9+n##a`dT zpxn~YK|SZv?6#gN(j>kyeL~B)<_)z9oW7s;U8eYkVAdcz z&y!iPKDkf7`3;0rk|n-tOV1veYr6D3Lfp_EH}BP3_dJvqgr8RE*bR6*FP3Pr)x#n;t6^-w!iUq)E2+W!_5NG{@88 z{Mx?2BKz^|z47@Mh~GDEvn9#a4+|o#D@w-9H&<~I0mvuQs|c(>VrwCAO6<0GDj-CX zEJ}WC%vE~zUlSDipyqh@(ORIGAr5gL1h=!#i$59u?!}{Zj|J~CJ-($c!qI?izn~}g zwzuxYk7^ye^$$7Zx0`UC`#N*3WS6-_%klcNmsq2VZk^nx&DG~*D8XgE*2Yy{R@$;W zBQ;04>Pl{8O&y#ZlCy*2nD;KrJ&SccqWerBKJXgqa3m45q5(kKST$5L%F0B_7lLn)GORw5EO++y&V2YHD!)zTM`1D!j{%WXlmpmbI*ru_hK&4vF%1^!G#%pGe^7C8EjPV=sYKhosBqm9@opIb+LfGf% zhr{UG^$nLbpUr+r&XbJN3=Ix3pZ02;P?G-ACfLOF;iaU(PnoPc?!PyBNE?Wc1a7}3 z4NnOVM0n8srRfSpG84l`CINoLnI89E`o_wFxW0RE%9S(BV2mHLblcarH5c{6KXJpp zvE=1ye_8FAMA;kDZz|g##iAk7Nd5d5M1z<`U8XB5!M&I?-OM^m5&w9iH4y;-Eqd#l0T8 zRZwGImH37*OBfj)rO)m!I`3~9^ww~wIVTTOQDrn^XIh@i>+c)=`i6(+#KIac=7yuH zX*%F#=K%q2!D_esU zavVd@iC0Zx`Sy+a)D(JL*fR?`B5!gQ#d=6?3yO(IoH4;;BMnUX_AJp^r@6&svX1rJ zK=zkO=Dlssv0@NGz5@}M-lduLc#OKR$;1y$W=@!z(6a6&!7&kBM>$hoFTi51a7uX>Nt+=C9j{b2$!n;?& zbF^F7ZnuoeEf=1xO;Rr57cx%p=k>DkD#`V49^9HBaG+4SUJ82-#_NKJ23RwoRnKZW z>-CHvKix+;bY4T*0N~Eq4Dz37D8LhmOWx_BaqE+iJ{tb{{E*na4$iFbN&?Y zkWOJw>10pFXHUl&vuL|=`crE9WD3-2;H}tti$YRMx1K1Tl+o~^q6OXUw_POeFBJor z+Xu3&s#$U)q0OXkB4>}LS4~phVbQ-?wNTeoHv+*uHsnTYye!c@g``algnc#yj(TbH zQ)^@48weXF*|a?u+pvdR1CM@n$k3cqCxb)_{#2#cEtg~a& zW?u5Kn8l2|$49=J)UG$)zJC%zB8Xrbr)Bjb2QHVJ;RILt+o3MALhzWo7ZJbx3b9)_ z2YcP{{>M)9hVqI*#F3eNaX8ke6&EjbFhlAtm~b08q1tbYr?=0Hw7Z-j#C&A5%7S2O zS&Zz6v3&5Y^||fq{-*-JM^}b~^ZW|jfd$b~KT$|Dm<^AQfsU0!}_WB8TsWy_~v9LzIi0!^`_$$tI9oT5|jd)^q4gkLDm-o9;GnSh_?tcQ{4Bl2)#rU*xI_R(=LC?e)nE>?99P5qp&)kL*c zR#wlj-YL-<*zm%?NpZVFZXe-4hC)3#_ru!m$T>&qxmITTRmf*nIGHSB8+p5sJol|C8)MKDN{;R@Rf+K*?;Zx-~Jh&_YuEc=$QuLvQt}{#x19 zYh}~9#mlWSoD%TzBsfOi4bDnZVBJa$!GCf);O@D(fWrY_mNr`=!KsCq?X{SN33)FK z1TKf1|6y=mk^&L99nE56VFtE`8tCZhNv51<=1YLBNQrC@lW@B$lTrB zZ5<0MioEQoHkJ*|g2wFB8maAE`uYF6uSN1lx?GN0K{3IrS7AHw^qu{`=@0QUgBFM? zO%3dB?>|K>|6@tl&I0_;b!mEXlVioc3o4BO;{rKRn&;s2GlGX2keQhYq-)zo{5nFM z-HSTa9)g43-G2&?Akhdo4Oo2y^}Q3SnVyCUD%}{Q^9Kt{^y&r|@)8DF1?=E+q>cir zB6cdOcCPYPBn}<(y1~Mt?PjHgpnjl6scL^7xyNCl*Di5R0y`K46S*6Sgg8}z4R*zk zxhiMC#QI_H$RKL*9n~ea(-2>FNXyL)cBEUv_*ZM1c@c6H&p|LZr@{Mv5DV|}F_4sPJLWsNTS{&@f5#kqZKd!eYN#fEn!^-Zy&oKD}8riADuIZ8QpE>*(xEO-T4QIq}cvK&R9$_&ii(OM5lXRw6dpbdFSP8dCEP^r!~^i7FG9<)2a)h-wulDxlu4*N?ZU)z5{z zy|sT^4!*DYeUpNL`|fA&eJI^&ifuA^mh9E?>20M6(H@51f>+aS$r5~Y0lm29ZhM14 zRUXy@W#D}nN*STTHGS;>D!cC45pm{qJ4wms9Z;wU9ejqmGEwIaiEXWpU=kJ=Z4Hf# zG{kl~5>!7<9;Sq$Js2*#iMn@dsw*qBeK7aKPWKbIAFB4O#!fqVgPOQR9uAkm;2=nIk%uu@y5xZur)LOIZ@Jv-s~F=8P5Io_R%D5AR1l zP_khE;V`~wYO1QU!;^mWI|2*{nhkALq)BzqOJyGlvvYTb{yr<>1wXe5$H>E4S2Xze zRc6!UD%HXw34Dwa-IHxR)>(M#g&)=!9I+_u=y>}f=3T+~?P<*9-kT@cIXQ#>BYz)H zYCGGqY-n6Lc5>lhdsBoSD<&r7Q*)!N+TT6{ z^XhhLS@)NhU;4|TWq1YzOst}n?3O+Xw~rZ%2_oxs@7zvj5|quMd&2#Aj)@>gjGY~$ zPipb=3~@_|eoLbLrTvi!N0O3FhuYh-7sfKRXM{WB;~B9@)E0lk%pOrijuAvCamc+; zY)rc|V9VLeKdq%5aY9vZoJgD)WgUn+XMcGBOE#~-I_682iHfoRuraaGGi#qj*br4U zpXj#h81CP@WWUhsT=;y85A{(xI>%2FDne%2d2+G%2byXjYWW%Zt zX3XOECs;F^&(djA?{M}x;oWthk)(>Ww^B?U8@sEG+4%TLxg_r^v-Rv`2amP>zPwXn z9;$)Ybj z1u8`kQLP{s>gMituH_y|=(A+EPrS@olf>sMXX+T)E1tPxHZiLtvzMdN0&_h|fVylN zlMr3ueczt+WAKs#>A>S4zDr$k&9d@G%&(MW)VgyPeF_ZZRUf(h;xUjYRrKF3l{{h?EPh2ey*?va#OAQE@6f|| zt^unc5dcEH3ko^uN-o^kYqq>%#+P|T)+ zB=@6$hmB+HJJOVHntYZ=`zfW>AgiK@uWhaN8c74$+IZbYEvzdsKKiqzD5JncC09eh z>ZH7vhb(`F@`rUDO%=IhAL?(74TVz}+6hT*`TVXqg|3D1t$-GC0ovBMufSeI zquXw2^(ocsulJBu@7|RQer^K9tVp9XulSsZscC|`>Pj=f%j}Id<1Zz(Y*eHSg)G-6 z8A8vWGleaG9W4%A^P2AZog;$`0<>dS(9HR(>E&2f0p7mMdg(_zmLh`9DQ(whfbv8h z|3$brF({7lq4FB{JoC6)MI4t1JT$Yo941cK^3KOr)GK7r@HHBCeSGA5=DwT?A3GP7Z&qV+hV9PbhfVy4l<0&v6*;n5 zD9(#{j1+Cne4Q}$sWKx-4NR`BzFu&4;}^l5C=`gU5C3F-_VFD`j)Uef`KPDEv4g`$ z(nKR8r&``Tq>XVW+f)^;-Ap#+cAQVpIVis#JeqGhu$i8Xt0TBC_A^_M*-rZ_KXuy5 z=OZp3Sk|^%Ms?@~RVZLitkA8juP>A0$x~YteG%6C6!Q96DSu`%!TPc*$&cHZ5sqA9I< zW+<-Ltx>!qf8AlUe7^3hjB(;r&b}y~sHsXSSJne&V$V~*JZd`4dHD$ytsi9}wt{20 z*W|s1#WfMmf#Zj%R8_;wKD)ao)tWntSxNL~kRm+v{*HykvwI6=I5<76s|WCJVdoi_ zR#I`yuhiEN)AyXGyD=CJDBb=#Tc3lb+Bz}OnJZL1i*t$917_oY9cv0XBV|o4vRB}b z?CMI6IG;K;+3Ob=qjkE(L+`!0e!<@I@%(u=$LtQ{zXqR`y6tn#Eab3g7?oA@>}_Gz z^wnU^`tti@n~zPF7#{!1l1IdS4>{&JKD(|scH-gt=F#jQ3Rg<7;^yt`VtVPm=Uvpr@0$)9H1 zTHBI6aMeZOG0a%G;fj&u<b=5aN(laAyt#;!lWu_+(w12m&U2OGp_EYgHP7bSkU1v<>+gAdhWuau&Lg-&| z+9Ui;bv!!cFX`(ujRsb491Dh`l=ophDv`1djS0YLJ^V5dZPx=}6-*&2UTZjY| zV&311==^Kwt-r%7QiSU3l&xgJK29X@vWSVa1XGpAG5uXudCz+pscNk7T0+B5Qb?=_}7*9@o$ zuTPYB*7i*ybP)FaWLNx-1y>vH803)I!2b4rxbg++l4)UQ+i{1Q1HLS{Px}?$r^c*z z#nMa2?P;7H8vfe;$~=yeumAXuq^-I#{ZOr4)9Tose7-aYwNV^7xvZ{U*c#hV3fUsPiz zBHVK3!}@vuv4oVX4Zdvj^TuMXUgEq1ay)Nc;OGR9%?Zu-R2LL2)psP=?mH8`ZE$a5 zhkl_eZ3BoeUfu`|E?#zz>N@^a$fC7%c>c-vsj0RApV`lZzdlQdMnn>h((AmNYZviP zu2noG4R(W$i#R>HUn3%?xGC?S46c+z2hOqn1d*A)6hD7_ zCii4$1@^LLXsD4%O@qCMrDxLC#@FfW`HZ;gtV{SgKU2JsivBg@H*X%Dim%aU`4~P2 z=2>%>3#*Sc+&4b))2CYxA3g+FLX@zGNJcc3H`{e_PYT4Kt4at0Em4zxl+l8CA>Gz2 zJOA{EhV6``GBdVoS}9_{$i&#B&`}MHR7b`sMM*d7h7NN|#xYLzX7(p{Ep>z*aTq1Z zU<#RMnTFnr57EAKp|ZapmoxJ?Up4keYDJ^U7xG+4sSMs5RNqYA|2SrL)X- zqLWXFt6r^+e5s^#>da$m;{fdz14pjrn2@CKp4SqDuPG_<>yP}B)FiGS$QZSIWTR#W za?CvAVcuN~5J`JWi!Ou+*!Jwoa`dH3#GpX-fvxWu3=>v)2V{IRgbtNM`AUd+}5Xg(+22d169 zi>VI->vxl+l4;vO{W8fsZ$9V2yYXMmrF&O5o!uJx%s)R1O5h-z_zFRh=o<|A?++Xg zsHBG2LyrYn!XhOj!|=T$!b4U?DUYjM_5AVQr-CRXqnDCBT0?T&17zgAT2exy#oIhA zFmVx$AWF83biOSyEUnZ{P4T{X0xUZ=mWcR#IVQ7{DwdHt8<8H0T@m!o9`b5#1^TL` z=daos3)we@hr8xfX!_%|YjTG_%C#aE>e(c!hk9XuF@KzYDJJ-LXp?l8h+Oir=UaKj zMHNG#jmk@O<yPf1OplQh?|iXqmkJ2`>W_k22tJk$8&ya?eZv9ezJDDIwWJHDDpW1{~as zuyCfOh5PmS^m{Ya%iEl##jtxgMP`ERz`cw+Cco}bT%85p=p^NG)+qtj`pi}ascsjr zcYC!5#U6VTN%3Mn@7S~{XdS5^cRPS-igihs0+yk(jhV%JM`z8n3f)QZ;jRZu3V4gn zbZ|jQxMjF4rNX>Nr&wM-7=`e{ zbU7?^NK{CsVRB+xNt)Uv*LC}bzO?@K(}^M$(oWsCp7yM)Ut<)d#lNu&O~&ypi+X89 znEtv%lxTh~S$s9Q@%ZeWvaua0afj-~g>cmiNg@`u-KTlZi8!}%bvV&#>%as+Q^ip; zH&^yCD|kdoEPF;`LQWojz%0?C=gJx0G$iJPtl-_+Gk@)0ji#sBr_6VrsazX%j^~+I z44$~DEf>YpH#s3o^S)D(p3`WLUpTnvk}bR+1OtiVQMF1oDuModFX+L-%AzVF)s}mJ zV@*NP^y+-u6K8O(VdwDl3VXtK{WN{5I}me#Inq1&J!KG>IC6p3MlB9RyeTq0^@y=t z->CMlYKyRgbiiHy+`*aM>-j{FtdcO0d#rXVGhC#CZ^vGnxFEU-~$yOlTv3*e| zbgUu5QXzb4i`4n6u2P+FsvP$-T7<1uB6RfL@P->IY<$&)%KIr2=|iE87X=EtU8rGV z@V{NgRX9j%F)`70YR)M&om=I|Vw9q!pKgJAf*G0hP3Fq@oI2`b_;<7l`o*1YAt z{KztNY)shxZUwvs(sX>jzO9G;%;j*Qv6+te4UzoVD%utIW98dKOV5siHA$QcXzE4T z&Nq?4BMOb^%IU%_!nE$x{MXOwD|W_xtUj6GvI{Vew*vu!|9RW;lxucJGAR7^l@Ha} zofreF)K1v^+_eGho}E|>pX}PcRv7HEy z>R0eGpD7@+J5EUEjCr_!z-g zEu$vSvH#}4bJwe`9zVNu5lTS$$?qyI?iY8hKOc)-VGP6)f9q1vu4HGCidNGr_>hyT zE+h3p@YEX#A{Nznr@N}oC^aXD3yvb+qVDeb6MWONindeVkhALnX_4R31+$8xG2+;f zQ#WmQLpR>%oe$*4enYl8I^K|W^d#!lmuj_3cj9497WW{eY<+; z)fd{cd_gW>t~&)v;z2NxW;#1+ONAL-xt;A{>uLoRwkn{iyJ{ z_RTBzLGHy{c>!sG=LZgbP)z&o?J57<{<*|CFvZ&38Y>jaetZ%3*pu3i+)nr8pSkKS z9$fG8-C1Yd*wbm3kS})+S+?CL?)>#XBz(TnA!(iev;4(QTo^GGI{*i}dmKH5WFGz; z-uwT_;UgcM1fc0Z-~209x%0ufotoc2-~Hz=f&>6eZh3ViPzD2Oj^OZcQzTEYd)NSp zc(dhul3mdcEG;>ADFVLo>{qVjAWxU2dwZ5kRYfJ3&Ger{6Xa^RL{$Dlc`LR|k<6ix zsiRY8>&EGd;NW1>=4dfhc}f&_-Rc^%H_(SS&sT{m$W_Hd_G@%>H10SR2pwfr)g;Tl z!Udt@sEd0%w+`x_+sWDJ-r~4&dfWR&oHgbQTuB2{jCq;VlD4lgg><>4@ICa+B!YHI3~)KoL|jjoQ43AM^~mGLR) zOIMVdmX^1ki=3|e=#K=}SlQuGt zOfHQt6eXoRKX`0%v7Rf?O{a1&3tE`n$Jj453i{R}J+-7U0B{zrkV5$1`}|HE01_W6 z@ZugiI=Y=~FpV+rDRKBM7dtO6NajHg(!ip#Xq?2s0oSPv3|k=Xl)#RN`1i1jzeKj{ zywp)tJdf@zcd_fvd2}swM--)g{)`N;BNT>)LZRR8%9eBJQs`62hBh=b)W|dPA6kHp zbf44HuUcp#XL+C46$3X#oMx3_-fR=lnl`9=bq7cj$>YW~7@_`{Zp##@&A=D?d0*72ct7*F=ZhBUBv>_YmoglfJ9}nt(eoXvw zAdVFc?K^#a`o)X=aU(zBGZW%6vOwo1{-{E>&i3{MXpbw6fqA7jG&Gzi{b*=tA8U-f zfCfm4vXW9zN9c}7MZf$rnw&XkG>S>c&Ako|(8Vz_0Q%x{b91u|kV&G}chh23Y{*0` zdvfn!maFz1`#$vKTX|OXPzyAvJBRMgHGJzh+i$w7F>kj1p(gbAInq=eN7e_n46QO% zq-*R34g75T@8%gwfjk9`ypRnOhKLr}0o`Y=(BpA*!I=#Wo$ltc15fpLjVz3RImn#9 zOR(pze8cPPuS!rF|*JIiQXMM?42<-$Hjx z$vG@ZyS?ga$eaP$vl1E(ogx1^DDi7h7R(n@{~bXfvZ=x1{qE^dUjy%vg0T=8K7%IZ zv}6ju5>|d3v0aR7YJNj5H8u5ti%ZGMbdLcsA6l0DfDJXkJHp?GQdI43FtC~#Ab}jz zDN5=mRW#_8LGP5bG$r5_wuxEjK*zt-FjRDY@5MLObAl5qS({!M3<-M#^5-%ua|S>S z7>Yr`Jv5hV09$a63PA%TY}E;V6^tFMB1z6em)G4x5)x+T(7-D1*fL5+PeL?~E%=w) zCy4QQRu29PXh3ri6wnL3M!|Fap9~Y@Bn0{R)OT~_aF-Dj!ZV89jGIb3;|0nU-&8*F z=K=ptI_`Y%zo^LnJN;*?zT2?|xgn+oIt3>~5os~0?ANm+Y-q2orI_HLpi@hpdB)A1 z&}KKi!UA<@r}5y<0IG1dc6J5OVp?x*8+!8M3dqny)Qosx9}UI74IFm_b+1w8m{Dla z!-B}n#KT99oN^8LmD81}B}1g={(F~$kUMf$A?<4q|3Ku{z?`R`9u7e~O5!Sj3NtE{ zQSofZ7W_Hh$-<2sK&qiJP;B-Yx~9Hh=mL%k(X@KcX4#vMMnaZ4?11a|7lx+l9Q2Kj zudAzLLj&T6bkerrAhWvyQ=k;)*53@?um8v&xWD(`3{<`VTH`^J%?oGxOYCmrrlzOc zA?9=e9Vuw7YGjlI(p&fRzlW}?|MSxwWSVRf2ulynF|XtR_|y^o0F(fT3ndX+-;RVr9rtZ$khR2@KLj{M7mUrJhFa}&LIPW+!Tz*Cn5F&NXsD(K8dZx> z729`Om$RSw2-B|ut;zGrlglyLt`WOS`Kk@Np)LdXTN%JBh)7=srBPcx*AyjE00BYt z;fyN>b%(*M<&NvNyx-U$%rQ%jD5VPbF%U>JF@oawtcd1cf{WNpWI+@ozB4_wnSZ>G}PhP@u=jkkv#|O+vG3_1?F95 zu#T!ahrM}V+jMWCi;O2eO>}+34yH-PC>WRVcx&>EXhuW}$z%Au>aItP3#A$#8=zmf zA%=~boS6BLmEpT9wo$r!ALg692Y^Kyr)J?eU=rJgs(pPQ)z73PM?XLeqY02^h3h9# zesMd-`Rm`rnD!Oc!10cF`SGgPQK^=0UG`pNo34{RhU5zO?>Z zsWpj%tDt+b9*I2y#ZWN0j-N+ka3i$W6_z&0NI;bhjZ|s54ctJD(8G)LE`IP{Usfb+ zU=m7KoFqq{cNw{*P4r~r8gD#!AcxaxdQ=d-sP2)nyC*aT5QPRMoCl^x)|)qnwcKV3 zPCPFto2$?SdWGm?+&QYM-^e?*Z@0AdrJNFzq8yPDN%OVg+r3_PKcJ!&LFTee0J@la zAPFoNPy?6*D1egM32@U_(ZH5^Uv^~jxZYm7XkuKT{dxNsMY}N~L6JlEgl}~m7<@Z= zn%HmGOj~&9fE_#0R5shs19=cy(b8<6TZa?{>npi8*D!e-7hl5Sq~zx#Toae$Hizw+G~JU;1G71ro4!gH zJob@sVIhNgOF3%m)FCnB2r(tK#x=!uOJte(9hk5C5faZ#rEfN;cJoWo226j(eYSK{ zn`81iKe@T|;H|@*A0#wk)Xp(U?0`}&U`>|-?Q8h0diK;+FIceF_yPZUSaU!86I&9 zs5GIgKtIsd$dR^d3ZSWAoJpr5m+%oRGQ`O``7njV9$vX3Yq8OvnRl0%M%#D^SK4^) z)W6C4IoY;-L4Wlk`fajyYQfT$+}lM72_w?3o~kuqs5wH*SBx0@BQcAL$@V`T31 zMGM6(LV@#SVqBJtU6ZPIFQ1s(_j1Os2Q#v!o_BVsU_1)1MR>|}8|<5tvg|91laNZS z(i9~=DADtOf$ONJSpFma)fP#yY*ta7NUw>WhVLdzu&pffO0L$s6A|InB^R`aX z02q5Jzkyd$&mbMyse-kD$fgW#kHV1q8>vYNa>wW;vYrG}6{uZ_6|bM=LhgO81gLrf zYV1|++<6JM&fUjQy9e1anh?22feC1dp@K%g?obLpj-a^Ex(P#(Y>Z}EZ`Pd~e+W_< zB$qV3a?6w(@MUSrNZEK7EoN`6-Y0{ud-Aw`^gCmR+m4e!69djczVm{9a7f6>iap*h z0gs5dIW=$3re$U}O-}f^!3ulVv`&Y!QVqiXDsIS6zbcipu1W^cP@URltMvBnXatqh zY}aywi=M$t+Psb)PkrU49e;?XatFBBu`QDrKzpa|n$CIL@-48jP(g3DO@exhEJL^N z#er;qKEdm)$o@x6*d*O0~0 z)dy4S$V+RbZDOBoQKgK1N> z*D;d!s=HgHHrN%QgW_Ki);*&fh==sc;7er?2Rr+!Ecf31 zU>EjPdR2BPdDmD-|1_2_6F6OgsFxji2D$61UtC^mGULrwMGy^!`*3%<@ALlsekDcd zj|~@P^OheR=Uni8Rg{&-3;V3vpkmXCXs>%B@Y}9s3?|v2LUtT`7OapdlP%1n>sn0{;NlG~WTAT(%91s9>+xK(9sX*WsNC`*WP;v_Vdx zC%3i1A%`fih`y|@--iz$z+sccAnF)MX$oA_c;8vJMHiAo+)V3i;pb`TN9-(AKApB2e;dJm9=RvC4gjKTvJp3lNNL z3Zne0if;kh)CWBNBtVA3P{8MwhK>QbuF^D;U-)-vRztg0BFa7}|-1Ih$+7J<% z4O^bwJZux7e{YN4HIw$~DAIex!O2;Gs0+Uo5a}R>8zG#q^AJhoAxNIkxS0tFK|rKM zRsP_aZoADpGazgBPPR?qq6I`fwTIYyEStgt9PZ8Vj_=%Z-M{J>eK^K)Y5YPGsuAhF{EvRudkx^yJ0{(V|U z^7dQR(yTzY!N+DD>L51*994b&4R7Q+Xb+_p2PnN8D_lpK{Ouf|SGo7dq9d((F+7*K zEH%2j5M@IAK)K~PU3t`CDfz0BwwX->E-V<^GFku6RS?pt+W$VrF=C<^=;=fLgq{IN zschHM1E3*$JBk~*w}9{zH5IA&E?BO=o4KJhL;D9U3b&9&-o$qCMeeg;pV&GpyUC9! zI)~}qfc{{T>Cu@flbwR?qt?gh>z_O}*V`f-?Q>k09|t{By$T{K3p1TpJ^K-qGuu2J)Wl9rT|n z2IC;fKr-Vz!S?qztj_S&k3*iRos{o(K7%+ro~65 zL;knfwHIR3T0iDh*MgV^Yn9K!TnQk86g~_0`i|j^vMr3CT1YG2^vIFewU&WIsKCPr z;|6AE1F`M10Oly(%vB(19#Ke5-^*^+WD0?zh_pI&^gC#>MQ8Knzo(|mCdCu@+>)-b zSJc{5?IZO8e|og9RSYc{)^yQ)&56}*S(*HK=~mazc8_~mOdc%y-2$sj)2rh=pzG+H zY&t$N(~ePFUi&f==%|{OT5|pL(WD+;2hX8U*4ZLh4h_()h-4&C4M-i|(H|h?zak`I zwW;dw}Dq68fsL{daymwyTM-1QZ z3f}7kUy9cbGjpjaQ}6CK3#l3Z_PBVOE*hTE8Et?`V2wIx{~60}e~cxH^+uK~?nBtv zN%Yl?(WEme#1F>mxScWRUeD`$V82vSPxOB&qx}2&*5bTRorH-wQ9CU;WkXFnrDLh? zYi)@5iXDG`k%kz*tU?-rvz5$|b(p?yaQY{CuKbfk7n4G$givVWmv48#`RE72$}bwt z>g`)p>#@9_*q3)J(1m=-S4FP_7EUf&(q`@w8vKsl2^anDuIv3CBIHZANaxQ;MkTj- z>8sn({vhr||GndSEU)ys*K`&1i{U0yP$OTTJsVcIOv=;hBfc%#0*%Q1Isx&+@4di# z%L6OKZJSu{764w1h-}unzk1+kTZW9933}mbTJlr$iya6)Lb>;BmzLhzPqk9}EZns& zb7V>hW>aBu)hQG6&4^~#eLWCe-K(&65ZzkWV@#(JE8SYy(Pciwx}6zfmDSN!!-llc z+da^;N)&CfxUAJIUv;&{TO3A>Z3bx-OzZ3U+r`zBSLAN&>pIo1p_ND(EFWpr)qjrbv+6D18b}a)k?By3&dM_D$+vRTTGZ38zaa4MsJYFS_S-8yh!)#6E@3 zrA@5v&5FaSNVreXRu}iU9ipN9ms|Yq_cgvl=N;W9Gom{aoQAlo&wslpF<|&v_bqN^ z-HhM0ue#Q`iCgtwA&hfBI4@tO+Hf^@fEZK6@^s

ZNDjB7y`RzTy7Ld{6Vu&L`*J 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

3tM9%a= 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 z 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ΝuERf$R!bSE% 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 diff --git a/docs/pictures/checkactivityv2.png b/docs/pictures/checkactivityv2.png index af0cd3120942cf77ca1be2b62300c16841475fca..f79d8706f889884ca613de63a780fe6864798b60 100644 GIT binary patch literal 37963 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 C90~{k literal 45894 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 diff --git a/docs/pictures/continueActivity.jpg b/docs/pictures/continueActivity.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3e9e4057fef5351ad3ec2e4ac221fa6e34345911 GIT binary patch literal 122460 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 K^3=fG+kXS=X0<8+ literal 0 HcmV?d00001 diff --git a/docs/pictures/continueActivity.png b/docs/pictures/continueActivity.png deleted file mode 100644 index 4142a34ced4b8b7e64866d5868e639c194d5e863..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 26649 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
  • ^j*t8WU>q2#E!QlRq-!e$JSa7QB% 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 literal 68277 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 D!Tyl3 From df450579291c1948c2fe9ced27cbb397775f7b95 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sat, 11 Apr 2020 19:56:54 +0800 Subject: [PATCH 397/415] Update UG diagrams --- docs/pictures/CleanCD.png | Bin 65086 -> 59543 bytes docs/pictures/startCD2.png | Bin 38035 -> 28389 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/pictures/CleanCD.png b/docs/pictures/CleanCD.png index fc69b07ba9a4c2b5ce5689f444afae0dbc08927b..790125ead936d391187c7e9ce1ebf9bafb74dd7c 100644 GIT binary patch literal 59543 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 z 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 O-O$w0$h&I!Dg^`r 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

    ZNDjB7y`RzTy7Ld{6Vu&L`*J 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 FP$wlNN#4BHvu_^n#+|>^ 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 BvZVk3 From 9b1ceeeec8750bf9f50d9794e2cedd3e9001727e Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 19:59:36 +0800 Subject: [PATCH 398/415] Update FindCommand.java --- src/main/java/jikan/command/FindCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index fa20ccd75..32601960b 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -56,7 +56,7 @@ public FindCommand(String parameters, boolean isFinal, boolean hasChaining) thro @Override public void executeCommand(ActivityList activityList) { // remove the magic number later - String[] tokenizedParameters = parameters.split(" ;", 2); + String[] tokenizedParameters = parameters.split(";", 2); try { checkForInvalidChaining(); } catch (MultipleDelimitersException e) { @@ -206,4 +206,4 @@ private boolean containsIgnoreCase(String str, String subString) { return str.toLowerCase().contains(subString.toLowerCase()); } -} \ No newline at end of file +} From e183381fdd08f01f72daa415fc8f3cb46cbbccb4 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 11 Apr 2020 20:57:49 +0800 Subject: [PATCH 399/415] Fix some bugs --- docs/team/btricec.md | 81 +++++++++++++++++++ src/main/java/jikan/command/EditCommand.java | 23 ++++-- src/main/java/jikan/command/GoalCommand.java | 3 +- src/main/java/jikan/command/GraphCommand.java | 4 + .../exception/ActivityIsRunningException.java | 5 ++ .../exception/ExistingNameException.java | 4 + 6 files changed, 114 insertions(+), 6 deletions(-) create mode 100644 src/main/java/jikan/exception/ActivityIsRunningException.java create mode 100644 src/main/java/jikan/exception/ExistingNameException.java diff --git a/docs/team/btricec.md b/docs/team/btricec.md index 3757d6043..fc217874d 100644 --- a/docs/team/btricec.md +++ b/docs/team/btricec.md @@ -31,6 +31,7 @@ * Provided syntax and usage examples for some commands (namely, start, end, continue, abort and delete) ### Contributions to the DG +* Drew command class diagram * Explained the implementation of the `continue` command (under section 3.5) using Sequence Diagrams * Explained the implementation of the `graph` command (under section 3.9) using Sequence Diagrams * Gave instructions for manual testing and included sample test cases for `list`, `continue` and `graph` commands. @@ -47,6 +48,86 @@ ## Contributions to the User Guide (extracts) + +## Usage +Jikan lets you record how much time you spend on various activities so that you can easily see what took up the most time today / this week / this month. +(In the example below, we use the example of a student tracking his/her schoolwork, but Jikan can be used for more than just that!) + +To start, record your first activity using the `start ACTIVITY_NAME` command. + +Add some tags to your activities to group similar activities together using `/t`. Tags help you group activities of the same type together, +in this example, we use the tags feature to label activities according to their module code. +**(Note that each activity can only store two tags at maximum.)** + +Add allocated time to your activities using `/a`. This allows users to set aside how much time they would like to spend on an activity and +keep track on whether they are spending too much or too little time for that particular activity. + +When you are done with the activity, or want to move onto something else, tell Jikan to `end` and the Activity time will be recorded and saved to your list. + +You can view all your activities using the `list` command. Or view all your activities over a period of time by using `list` with extra parameters. For example `list week` will return a list of all activities this current week, as shown below. + +![list week](./pictures/list_week.PNG) + +The list still looks very cluttered, we can reduce it further! Want to find everything you did for CS2113 this week? Filter out the activities you want to see using the `find` or `filter` command. This is our list after filtering out all our activities tagged as `2113`. (the -s flag tells Jikan to search our last shown list, i.e. the list of activities this week in this case) + +![Continue command sequence diagram](./pictures/filter.PNG) + +To easily see what took up the most of your time out of all the 2113 activities, use the `graph` command to view a chart of your activities. + +![Continue command sequence diagram](./pictures/graph.png) + +Curious about what module took up the most time this week? We can use the `graph tags` command on our weekly activity list to find out. + +![Continue command sequence diagram](./pictures/graphtags.PNG) + +Evidently, it was CS2105. + +Not done with an activity and want to continue on it? Use the `continue` command to continue recording time for a previously started activity. + +Finally, when you're done and want to close the app, simply say `bye` and Jikan will exit. + +This is just a quick overview of what Jikan can do for you. For more details on each individual command, read the command guide below. + +### Starting an activity: `start` +**Usage:** Starts recording the time for a new activity. + +**Format:** `start ACTIVITY_NAME /a ALLOCATED_TIME /t TAGS` + * `ACTIVITY_NAME` can contains spaces and must be less than 25 characters. +* `ACTIVITY_NAME` must also be unique (should the user start an already existing activity, the option to `continue` will be given). +* `ALLOCATED_TIME` should be of the format [HH:MM:SS] and cannot exceed 23:59:59. +* `TAGS` must be single spaced separated and a maximum of 2 tags can be stored. +* `ALLOCATED_TIME` and `TAGS` are optional. + +**Example:** +`start assignment /a 01:30:00 /t CS1010` +`start GER1000 quiz /t GER GEmod` +`start revision` + +### Continuing an activity: `continue` +**Usage:** Continues recording the time of an activity that you have previously started. + +**Format:** `continue ACTIVITY_NAME` +* `ACTIVITY_NAME` must be an existing activity in the activity list. + +**Example:** +`continue revision` + +### Ending an activity: `end` +**Usage:** Stops recording the time for an ongoing activity and stores it into the activity list. + +**Format:** `end` +* An activity must be started or continued before it can be ended. + +### Aborting an activity: `abort` +**Usage:** Aborts the current activity and does not save it to the activity list. + +**Format:** `abort` +* An activity must be started or continued before it can be ended. + +### Delete an activity: `delete` +**Usage:** Deletes an activity in the activity list. + +**Format:** `delete ACTIVITY_NAME` ## Contributions to the Developer Guide (extracts) ### 3.5 Continue Feature diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index 59eeb8db4..009066712 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -1,11 +1,7 @@ package jikan.command; import jikan.activity.ActivityList; -import jikan.exception.EmptyNameException; -import jikan.exception.InvalidEditFormatException; -import jikan.exception.InvalidTimeFrameException; -import jikan.exception.NegativeDurationException; -import jikan.exception.NoSuchActivityException; +import jikan.exception.*; import jikan.log.Log; import jikan.parser.Parser; import jikan.ui.Ui; @@ -29,6 +25,10 @@ public EditCommand(String parameters) { @Override public void executeCommand(ActivityList activityList) { try { + Log.makeInfoLog("Activity could not be edited as there is an ongoing activity"); + if (Parser.startTime != null) { + throw new ActivityIsRunningException(); + } int delimiter = parameters.indexOf("/en"); int allocDelim = parameters.indexOf("/ea"); @@ -44,6 +44,13 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider("New activity name cannot be empty."); throw new EmptyNameException(); } + if (newName.length() > 25) { + throw new NameTooLongException(); + } + // existing activity of the same name is found + if (activityList.findActivity(newName) != -1) { + throw new ExistingNameException(); + } //edit allocated time } else if (allocDelim != -1) { Parser.activityName = parameters.substring(0, allocDelim).strip(); @@ -104,6 +111,12 @@ public void executeCommand(ActivityList activityList) { } catch (NumberFormatException e) { Ui.printDivider("Please enter integers in the format HH:MM:SS."); Log.makeInfoLog("Edit command failed as an incorrect format for the target time was provided."); + } catch (NameTooLongException e) { + Ui.printDivider("Activity name must be shorter than 25 characters."); + } catch (ActivityIsRunningException e) { + Ui.printDivider("Cannot edit an activity if there is a current activity running."); + } catch (ExistingNameException e) { + Ui.printDivider("There is already an activity with that name. "); } } diff --git a/src/main/java/jikan/command/GoalCommand.java b/src/main/java/jikan/command/GoalCommand.java index 7eb2d3436..d5ba89240 100644 --- a/src/main/java/jikan/command/GoalCommand.java +++ b/src/main/java/jikan/command/GoalCommand.java @@ -106,7 +106,8 @@ public void executeCommand(ActivityList activityList) { Ui.printDivider("Invalid command format entered."); Log.makeInfoLog("Goal command failed as an incorrect format was provided."); } catch (IOException e) { - Ui.printDivider("Error reading the file."); + Ui.printDivider("Error reading the file.\n" + + "If the file was open, please close it and try again."); } catch (NoSuchTagException e) { Ui.printDivider("There is no such tag."); Log.makeInfoLog("Goal command failed as there was no such tag saved."); diff --git a/src/main/java/jikan/command/GraphCommand.java b/src/main/java/jikan/command/GraphCommand.java index b8a7b2fd8..a2d5568cf 100644 --- a/src/main/java/jikan/command/GraphCommand.java +++ b/src/main/java/jikan/command/GraphCommand.java @@ -4,6 +4,7 @@ import jikan.activity.ActivityList; import jikan.exception.ExtraParametersException; import jikan.exception.MissingParametersException; +import jikan.log.Log; import jikan.ui.Ui; import java.time.Duration; @@ -40,12 +41,15 @@ public void executeCommand(ActivityList activityList) { switch (inputs[0]) { case ALLOCATIONS: Ui.graphAllocation(lastShownList); + Log.makeInfoLog("Allocations was graphed"); break; case TAGS: graphTags(); + Log.makeInfoLog("Tags were graphed"); break; case ACTIVITIES: graphActivities(); + Log.makeInfoLog("Activities were graphed"); break; default: Ui.printDivider("Please specify whether you want to graph activities / tags / allocations."); diff --git a/src/main/java/jikan/exception/ActivityIsRunningException.java b/src/main/java/jikan/exception/ActivityIsRunningException.java new file mode 100644 index 000000000..dd9cb6277 --- /dev/null +++ b/src/main/java/jikan/exception/ActivityIsRunningException.java @@ -0,0 +1,5 @@ +package jikan.exception; + +public class ActivityIsRunningException extends Exception { +} + diff --git a/src/main/java/jikan/exception/ExistingNameException.java b/src/main/java/jikan/exception/ExistingNameException.java new file mode 100644 index 000000000..168ee626e --- /dev/null +++ b/src/main/java/jikan/exception/ExistingNameException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class ExistingNameException extends Exception { +} From b3865b62172490348f77ad83059f32d9102d265b Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sat, 11 Apr 2020 20:58:34 +0800 Subject: [PATCH 400/415] edit UG --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index f89f2543a..a4e6a1675 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -215,7 +215,7 @@ By using the following commands, users can get a visual representation of the ti The 3 types of graphs are : * *Activity time graph* - Total time spent on each activity: `graph activities SCALE` * *Tags time graph* - Total time spent on each tag: `graph tags SCALE` - * *Activity targets graph* - Progress of each activity in relation to its allocated time: `graph allocations` + * *Activity allocation graph* - Progress of each activity in relation to its allocated time: `graph allocations` Tip: Use `find`, `filter` and `list` commands to reduce clutter before graphing as the graphs are based on the last shown list of activities. From 10c276f73ffce00a2e630616aade20b4b8fcaa3a Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 11 Apr 2020 21:09:51 +0800 Subject: [PATCH 401/415] Fix style --- src/main/java/jikan/command/EditCommand.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/jikan/command/EditCommand.java b/src/main/java/jikan/command/EditCommand.java index 009066712..09981ac42 100644 --- a/src/main/java/jikan/command/EditCommand.java +++ b/src/main/java/jikan/command/EditCommand.java @@ -1,7 +1,14 @@ package jikan.command; import jikan.activity.ActivityList; -import jikan.exception.*; +import jikan.exception.NoSuchActivityException; +import jikan.exception.NameTooLongException; +import jikan.exception.ActivityIsRunningException; +import jikan.exception.InvalidTimeFrameException; +import jikan.exception.NegativeDurationException; +import jikan.exception.EmptyNameException; +import jikan.exception.InvalidEditFormatException; +import jikan.exception.ExistingNameException; import jikan.log.Log; import jikan.parser.Parser; import jikan.ui.Ui; From f2f2757a66995231507fc3a2c4654755e8447edf Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 21:18:39 +0800 Subject: [PATCH 402/415] Update UserGuide.md --- docs/UserGuide.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 736f81625..e8db4021e 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -109,7 +109,11 @@ This is just a quick overview of what Jikan can do for you. For more details on `start assignment /a 01:30:00 /t CS1010` `start GER1000 quiz /t GER GEmod` `start revision` - + +**Discouraged Activity Names:** + * The following strings are used as parameters for other commands, and hence should be avoided as it may interfere with Jikan running smoothly: + * `/`,`;`, `/a`, `/t`,`/a`,`-s`,`/en`,`/ea` + ### Continuing an activity: `continue` **Usage:** Continues recording the time of an activity that you have previously started. From 6398b8a2d5db512145115c8b1fae7415407bbfcc Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 21:21:18 +0800 Subject: [PATCH 403/415] Update UserGuide.md --- docs/UserGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index e8db4021e..6dc6c60c3 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -110,9 +110,9 @@ This is just a quick overview of what Jikan can do for you. For more details on `start GER1000 quiz /t GER GEmod` `start revision` -**Discouraged Activity Names:** +**Discouraged Names for Activity & Tags:** * The following strings are used as parameters for other commands, and hence should be avoided as it may interfere with Jikan running smoothly: - * `/`,`;`, `/a`, `/t`,`/a`,`-s`,`/en`,`/ea` + * `/`,`;`, `/a`, `/t`,`/a`,`-s`,`/en`,`/ea`, `/d`, `/n` ### Continuing an activity: `continue` **Usage:** Continues recording the time of an activity that you have previously started. From 52d45430e25acd852763fd1f3b175920ef81855d Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 21:22:06 +0800 Subject: [PATCH 404/415] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 6dc6c60c3..4ce21c340 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -110,7 +110,7 @@ This is just a quick overview of what Jikan can do for you. For more details on `start GER1000 quiz /t GER GEmod` `start revision` -**Discouraged Names for Activity & Tags:** +**Discouraged Names for Activities & Tags:** * The following strings are used as parameters for other commands, and hence should be avoided as it may interfere with Jikan running smoothly: * `/`,`;`, `/a`, `/t`,`/a`,`-s`,`/en`,`/ea`, `/d`, `/n` From ba40a4905db1b5eb036b53cea808d4a25164ac82 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 21:25:44 +0800 Subject: [PATCH 405/415] Update UserGuide.md --- docs/UserGuide.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 4ce21c340..bd6639e8f 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -110,8 +110,8 @@ This is just a quick overview of what Jikan can do for you. For more details on `start GER1000 quiz /t GER GEmod` `start revision` -**Discouraged Names for Activities & Tags:** - * The following strings are used as parameters for other commands, and hence should be avoided as it may interfere with Jikan running smoothly: +**Discouraged Names:** + * The following strings are used as parameters for other commands, and hence should be avoided in the `ACTIVITY_NAME` and `TAGS` as it may interfere with Jikan running smoothly: * `/`,`;`, `/a`, `/t`,`/a`,`-s`,`/en`,`/ea`, `/d`, `/n` ### Continuing an activity: `continue` From 9dd2d417e2e37309d947227696b2c8af3f9ba850 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 21:42:18 +0800 Subject: [PATCH 406/415] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index bd6639e8f..ab4d49698 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -112,7 +112,7 @@ This is just a quick overview of what Jikan can do for you. For more details on **Discouraged Names:** * The following strings are used as parameters for other commands, and hence should be avoided in the `ACTIVITY_NAME` and `TAGS` as it may interfere with Jikan running smoothly: - * `/`,`;`, `/a`, `/t`,`/a`,`-s`,`/en`,`/ea`, `/d`, `/n` + * `/`,`;`, `/a`, `/t`,`/a`,`-s`,`/en`,`/ea`, `/d`, `/n`, `/g` ### Continuing an activity: `continue` **Usage:** Continues recording the time of an activity that you have previously started. From b482f7000bcdf12b931190cb30b1a83ec1c3c8a4 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 11 Apr 2020 21:46:56 +0800 Subject: [PATCH 407/415] Remove redundant lines --- src/main/java/jikan/Jikan.java | 7 +++++-- src/main/java/jikan/activity/ActivityList.java | 5 ----- src/main/java/jikan/command/AbortCommand.java | 1 - src/main/java/jikan/command/ContinueCommand.java | 1 - 4 files changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/jikan/Jikan.java b/src/main/java/jikan/Jikan.java index 507313ede..749aa43a7 100644 --- a/src/main/java/jikan/Jikan.java +++ b/src/main/java/jikan/Jikan.java @@ -14,6 +14,8 @@ import java.io.IOException; import java.util.Scanner; +import static java.lang.System.exit; + /** * Represents the Jikan time tracker. */ @@ -58,9 +60,10 @@ public static void main(String[] args) { storageCleaner.storageAutoClean(); logCleaner.logAutoClean(); activityList = storage.createActivityList(); - //GoalCommand.createFile(TAG_FILE_PATH, tagFile); } catch (IOException e) { - Ui.printDivider("Error while preparing application."); + Ui.printDivider("Error while preparing application.\n" + + "If any data files are open, please close them and try again."); + exit(0); } lastShownList.activities.addAll(activityList.activities); diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index 2623f4c14..ed159bc19 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -118,11 +118,6 @@ public void updateName(int index, String newName) { fieldChangeUpdateFile(); } - public void updateTags(int index, Set newTags) { - activities.get(index).setTags(newTags); - fieldChangeUpdateFile(); - } - public void updateAlloc(int index, Duration newAllocTime) { activities.get(index).setAllocatedTime(newAllocTime); fieldChangeUpdateFile(); diff --git a/src/main/java/jikan/command/AbortCommand.java b/src/main/java/jikan/command/AbortCommand.java index 4b3b3c990..25ed797e5 100644 --- a/src/main/java/jikan/command/AbortCommand.java +++ b/src/main/java/jikan/command/AbortCommand.java @@ -21,7 +21,6 @@ public AbortCommand(String parameters) { @Override public void executeCommand(ActivityList activityList) { try { - // Parser.parseAbort(); if (Parser.startTime == null) { throw new NoSuchActivityException(); } else { diff --git a/src/main/java/jikan/command/ContinueCommand.java b/src/main/java/jikan/command/ContinueCommand.java index 20471ace7..3ae3a74f3 100644 --- a/src/main/java/jikan/command/ContinueCommand.java +++ b/src/main/java/jikan/command/ContinueCommand.java @@ -29,7 +29,6 @@ public void executeCommand(ActivityList activityList) { Log.makeInfoLog("Could not continue activity due to ongoing activity."); return; } - //Parser.parseContinue(activityList); int index = activityList.findActivity(parameters); if (index != -1) { // activity is found From c53d6a29ec064173ac4a92e83926ebd3ec489e12 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 13 Apr 2020 16:05:59 +0800 Subject: [PATCH 408/415] Update UG with missing instructions --- docs/UserGuide.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index ab4d49698..7aed9d42c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -49,9 +49,10 @@ This user guide will show you how to use the program effectively. ## Quick Start 1. Ensure that you have Java 11 or above installed. -2. Download the jar file of the latest version of `Jikan` from [here](https://github.com/AY1920S2-CS2113-T15-1/tp/releases). +2. Download the jar and tag.csv file of the latest version of `Jikan` from [here](https://github.com/AY1920S2-CS2113-T15-1/tp/releases). 3. Create an empty folder and put the Jikan.jar file inside. -4. Open command prompt and navigate to the folder. Run the jar file using `java -jar jikan.jar` +4. Within the folder, create a separate folder named `tag` and place the `tag.csv` file inside the tag folder. +5. Open command prompt and navigate to the folder. Run the jar file using `java -jar jikan.jar`. Features ======= From 4c2a44c8d6bcbc62d0a010e913b9091382f4c37f Mon Sep 17 00:00:00 2001 From: nigellenl Date: Mon, 13 Apr 2020 16:53:28 +0800 Subject: [PATCH 409/415] Update DG with missing instruction --- docs/DeveloperGuide.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 5c8bb92b3..1c5b0c159 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -574,9 +574,10 @@ Allow users to record their daily activities and track their time usage in a use ### Instructions for Manual Testing #### Launch and Shutdown - 1. Download the jar file and data.csv file. - 2. Copy both into an empty folder. + 1. Download the jar file, tag.csv file and data.csv file. + 2. Copy the files into an empty folder. 3. Create a folder named `data` and put the data.csv file into this folder. + 4. Within the `data` folder, create a `tag` folder and put the tag.csv file into this folder. 4. Ensure the folder `data` and `jikan.jar` are in the same folder. 5. Open command prompt and navigate to the folder. Run the jar file using `java -jar jikan.jar` From 373f1bb867aacb5d2ec1b7b894f4c17dd697c28a Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sat, 18 Apr 2020 23:11:09 +0800 Subject: [PATCH 410/415] Update DG numbering --- docs/DeveloperGuide.md | 64 ++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 1c5b0c159..3417c8e20 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -2,13 +2,15 @@ - [1. Setting Up](#1-setting-up) - [2. Design](#2-design) + - [2.1 High-Level Architecture](#21-high-level-architecture) + - [2.2 Class Diagram](#22-class-diagram) - [3. Implementation](#3-implementation) - [3.1 Start Feature](#31-start-feature) - [3.1.1 Current Implementation](#311-current-implementation) - [3.1.2 Additional Implementation](#312-additional-implementation) - [3.1.3 Design Considerations](#313-design-considerations) - [3.2 Clean Feature](#32-clean-feature) - - [3.2.1 Current Implementation](#311-current-implementation) + - [3.2.1 Current Implementation](#321-current-implementation) - [3.2.2 Additional Implementation](#322-additional-implementation) - [3.2.3 Design Considerations](#323-design-considerations) - [3.3 Storage feature](#33-storage-feature) @@ -17,32 +19,38 @@ - [3.5.1 Current Implementation](#351-current-implementation) - [3.5.2 Additional Implementations](#352-additional-implementations) - [3.5.3 Design Considerations](#353-design-considerations) + - [Current Design](#current-design) + - [Possible Design](#possible-design) - [3.6 Continue Feature](#36-continue-feature) - [3.6.1 Current Implementation](#361-current-implementation) - - [3.6.3 Additional Implementations](#362-additional-implementations) - - [3.6.2 Design Considerations](#363-design-considerations) + - [3.6.2 Additional Implementations](#362-additional-implementations) + - [3.6.3 Design Considerations](#363-design-considerations) - [3.7 List feature](#37-list-feature) - [3.7.1 Current implementation](#371-current-implementation) - - [3.8 Find and Filter Features](#38-find--filter-features) + - [3.8 Find & Filter Features](#38-find--filter-features) + - [Find Feature](#find-feature) + - [Filter Feature](#filter-feature) - [3.8.1 Design Considerations](#381-design-considerations) - [3.8.2a Current Implementation for Find](#382a-current-implementation-for-find) - [3.8.2b Current Implementation for Filter](#382b-current-implementation-for-filter) + - [3.8.3 Sequence Diagram](#383-sequence-diagram) + - [3.8.4 Additional features](#384-additional-features) - [3.9 Graph Feature](#39-graph-feature) - [3.9.1 Current Implementation](#391-current-implementation) - [3.9.2 Additional features](#392-additional-features) - [4. Appendix](#4-appendix) - - [Product Scope](#product-scope) - - [Target user profile](#target-user-profile) - - [Value proposition](#value-proposition) - - [User Stories](#user-stories) - - [Non-Functional Requirements](#non-functional-requirements) - - [Glossary](#glossary) - - [Instructions for Manual Testing](#instructions-for-manual-testing) - - [Launch and Shutdown](#launch-and-shutdown) - - [Listing activities](#listing-activities) - - [Continuing activities](#continuing-activities) - - [Graphing activities](#graphing-activities) - - [Setting tag goals](#setting-tag-goals) + - [4.1 Product Scope](#41-product-scope) + - [4.1.1 Target user profile](#411-target-user-profile) + - [4.1.2 Value proposition](#412-value-proposition) + - [4.2 User Stories](#42-user-stories) + - [4.3 Non-Functional Requirements](#43-non-functional-requirements) + - [4.4 Glossary](#44-glossary) + - [4.5 Instructions for Manual Testing](#45-instructions-for-manual-testing) + - [4.5.1 Launch and Shutdown](#451-launch-and-shutdown) + - [4.5.2 Listing activities](#452-listing-activities) + - [4.5.3 Continuing activities](#453-continuing-activities) + - [4.5.4 Graphing activities](#454-graphing-activities) + - [4.5.5 Setting tag goals](#455-setting-tag-goals) ## 1. Setting Up * Prerequisites @@ -534,18 +542,18 @@ As graph gets it's data based on the `lastShownList`, users can pair the `graph` ## 4. Appendix -### Product Scope -#### Target user profile +### 4.1 Product Scope +#### 4.1.1 Target user profile * University students with poor time management skills who are struggling to allocate time efficiently for the numerous deadlines/tasks. * Users who are reasonably comfortable using CLI apps. -#### Value proposition +#### 4.1.2 Value proposition Allow users to record their daily activities and track their time usage in a user-friendly manner. -### User Stories +### 4.2 User Stories |Version| As a ... | I want to ... | So that I can ...| |--------|----------|---------------|------------------| @@ -562,18 +570,18 @@ Allow users to record their daily activities and track their time usage in a use |v2.0|user|automate the deletion of old activities|keep a more concise log of activities| -### Non-Functional Requirements +### 4.3 Non-Functional Requirements * The program should be usable by a novice who has never used a time management application. * The program should work on most mainstream OSes. * The program should be portable to other systems. -### Glossary +### 4.4 Glossary * *Mainstream OSes:* Windows, MacOS, Linux -### Instructions for Manual Testing +### 4.5 Instructions for Manual Testing -#### Launch and Shutdown +#### 4.5.1 Launch and Shutdown 1. Download the jar file, tag.csv file and data.csv file. 2. Copy the files into an empty folder. 3. Create a folder named `data` and put the data.csv file into this folder. @@ -583,7 +591,7 @@ Allow users to record their daily activities and track their time usage in a use It is important to include the data.csv file to have data for testing! -#### Listing activities +#### 4.5.2 Listing activities Test case: `list month april` Expected: A list of activities completed in the month of April should be shown. @@ -592,7 +600,7 @@ Allow users to record their daily activities and track their time usage in a use Expected: A list of activities completed on 25th March 2020 should be shown. -#### Continuing activities +#### 4.5.3 Continuing activities Test case: `continue lab 4 ex2` Expected: Message "lab 4 ex2 was continued" will be displayed. @@ -602,7 +610,7 @@ Allow users to record their daily activities and track their time usage in a use Expected: Option to continue will be given. If 'yes' is typed, activity will be continued. -#### Graphing activities +#### 4.5.4 Graphing activities Test case: (to be done in succession) `find tutorial` then `graph 10` @@ -617,7 +625,7 @@ Test case: (to be done in succession) Expected: List of activities completed this week will be shown. Then a chart of the duration of the tags of these activities will be shown. -#### Setting tag goals +#### 4.5.5 Setting tag goals Test case: `goal core /g 24:00:00` Expected: Message "The goal for core has been added!" will be displayed. From 3d6808406f22caf9b8b5f4148b17dc522bbdbfd3 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sat, 18 Apr 2020 23:18:52 +0800 Subject: [PATCH 411/415] Update UG numbering --- docs/UserGuide.md | 146 +++++++++++++++++++++++----------------------- 1 file changed, 72 insertions(+), 74 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7aed9d42c..49863178c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,62 +1,60 @@ -# User Guide - -- [1. Target User Profile](#target-user-profile) -- [2. Introduction](#introduction) -- [3. Quick Start](#quick-start) -- [4. Features](#features) - - [4.1 Usage](#usage) - - [4.2 Basic Commands](#basic-commands) - - [4.2.1. Start Activity](#starting-an-activity-start) - - [4.2.2. Continue Activity](#continuing-an-activity-continue) - - [4.2.3. End Activity](#ending-an-activity-end) - - [4.2.4. Abort Activity](#aborting-an-activity-abort) - - [4.2.5. Delete Activity](#delete-an-activity-delete) - - [4.2.6. List Activities](#listing-activities-list) - - [4.2.7. Edit Activity](#editing-an-activity-edit) - - [4.3. Find and Filter Activity](#finding-and-filtering) - - [4.3.1. Find Activity by Name](#finding-activities-by-name-find) - - [4.3.2. Filter Activity by Tag](#filtering-activities-by-tags-filter) - - [4.3.3. Chaining Lists, Find and Filter](#chaining-finds--filters--s) - - [4.4. Graphs](#graphs) - - [4.4.1. Activity Time Graph](#activity-time-graph-graph-activities) - - [4.4.2. Tags Time Graph](#tags-time-graph-graph-tags) - - [4.4.3. Activity Allocation Graph](#activity-allocation-graph-graph-allocations) - - [4.4.4. Chaining List, Find, Filter with Graph](#chaining-list-find-and-filter-with-graph-command) - - [4.5. Tag Goals](#tag-goals) - - [4.5.1. Set Goal](#set-goal-goal-tag_name-g-duration) - - [4.5.2. Delete Goal](#delete-goal-goal-tag_name-d) - - [4.5.3. View Goal](#view-goals-goal) - - [4.6. Automated Cleaning](#automated-cleaning) - - [4.6.1. Activate Cleaning](#activate-cleaning-clean-on) - - [4.6.2. Deactivate Cleaning](#deactivate-cleaning-clean-off) - - [4.6.3. Set Number of Activities to Clean](#set-the-number-of-activities-to-clean-clean-n) - - [4.7. Automated Cleaning for Logs](#automated-cleaning-for-logs) - - [4.7.1. Activate Log Cleaning](#activate-log-cleaning-clean-log-on) - - [4.7.2. Deactivate Log Cleaning](#deactivate-log-cleaning-clean-log-off) - - [4.7.3. Set Number of Logs to Clean](#set-the-number-of-logs-to-clean-clean-log-n) -- [5. Command Guide](#command-guide) +# User Guide + +- [1. Target user profile](#1-target-user-profile) +- [2. Introduction](#2-introduction) +- [3. Quick Start](#3-quick-start) +- [4. Features and usage](#4-features-and-usage) +- [5. Basic Commands](#5-basic-commands) + - [5.1 Starting an activity: `start`](#51-starting-an-activity-start) + - [5.2 Continuing an activity: `continue`](#52-continuing-an-activity-continue) + - [5.3 Ending an activity: `end`](#53-ending-an-activity-end) + - [5.4 Aborting an activity: `abort`](#54-aborting-an-activity-abort) + - [5.5 Delete an activity: `delete`](#55-delete-an-activity-delete) + - [5.6 Listing activities: `list`](#56-listing-activities-list) + - [5.7 Editing an activity: `edit`](#57-editing-an-activity-edit) +- [6. Finding and Filtering](#6-finding-and-filtering) + - [6.1 Finding Activities by Name: `find`](#61-finding-activities-by-name-find) + - [6.2 Filtering Activities by Tags: `filter`](#62-filtering-activities-by-tags-filter) + - [6.3 Chaining Finds & Filters: `-s`](#63-chaining-finds--filters--s) + - [6.3.1 Single Input Chaining: `;`](#631-single-input-chaining) +- [7. Graphs](#7-graphs) + - [7.1 Activity time graph: `graph activities`](#71-activity-time-graph-graph-activities) + - [7.2 Tags time graph: `graph tags`](#72-tags-time-graph-graph-tags) + - [7.3 Activity allocation graph: `graph allocations`](#73-activity-allocation-graph-graph-allocations) + - [7.4 Chaining `list`, `find` and `filter` with `graph` command:](#74-chaining-list-find-and-filter-with-graph-command) +- [8. Tag Goals](#8-tag-goals) + - [8.1 Set goal: `goal TAG_NAME /g DURATION`](#81-set-goal-goal-tagname-g-duration) + - [8.2 Delete goal: `goal TAG_NAME /d`](#82-delete-goal-goal-tagname-d) + - [8.3 View goals: `goal`](#83-view-goals-goal) +- [9. Automated Cleaning](#9-automated-cleaning) + - [9.1 Activate cleaning: `clean on`](#91-activate-cleaning-clean-on) + - [9.2 Deactivate cleaning: `clean off`](#92-deactivate-cleaning-clean-off) + - [9.3 Set the number of activities to clean: `clean /n`](#93-set-the-number-of-activities-to-clean-clean-n) + - [9.4 Automated Cleaning for Logs:](#94-automated-cleaning-for-logs) + - [9.5 Activate log cleaning: `clean log on`](#95-activate-log-cleaning-clean-log-on) + - [9.6 Deactivate log cleaning: `clean log off`](#96-deactivate-log-cleaning-clean-log-off) + - [9.7 Set the number of logs to clean: `clean log /n`](#97-set-the-number-of-logs-to-clean-clean-log-n) +- [10. Command Guide](#10-command-guide) -## Target user profile +## 1. Target user profile University students with poor time management skills who are struggling to allocate time efficiently for the numerous deadlines/tasks. -## Introduction +## 2. Introduction Jikan is a CLI time management tool that allows you to track the amount of time that you spend on different activities so as to ensure that time is allocated more efficiently to the different activities (i.e spending too much/too little time on an activity) . This user guide will show you how to use the program effectively. -## Quick Start +## 3. Quick Start 1. Ensure that you have Java 11 or above installed. 2. Download the jar and tag.csv file of the latest version of `Jikan` from [here](https://github.com/AY1920S2-CS2113-T15-1/tp/releases). 3. Create an empty folder and put the Jikan.jar file inside. 4. Within the folder, create a separate folder named `tag` and place the `tag.csv` file inside the tag folder. 5. Open command prompt and navigate to the folder. Run the jar file using `java -jar jikan.jar`. -Features -======= -## Usage +## 4. Features and usage Jikan lets you record how much time you spend on various activities so that you can easily see what took up the most time today / this week / this month. (In the example below, we use the example of a student tracking his/her schoolwork, but Jikan can be used for more than just that!) @@ -95,8 +93,8 @@ Finally, when you're done and want to close the app, simply say `bye` and Jikan This is just a quick overview of what Jikan can do for you. For more details on each individual command, read the command guide below. -## Basic Commands -### Starting an activity: `start` +## 5. Basic Commands +### 5.1 Starting an activity: `start` **Usage:** Starts recording the time for a new activity. **Format:** `start ACTIVITY_NAME /a ALLOCATED_TIME /t TAGS` @@ -115,7 +113,7 @@ This is just a quick overview of what Jikan can do for you. For more details on * The following strings are used as parameters for other commands, and hence should be avoided in the `ACTIVITY_NAME` and `TAGS` as it may interfere with Jikan running smoothly: * `/`,`;`, `/a`, `/t`,`/a`,`-s`,`/en`,`/ea`, `/d`, `/n`, `/g` -### Continuing an activity: `continue` +### 5.2 Continuing an activity: `continue` **Usage:** Continues recording the time of an activity that you have previously started. **Format:** `continue ACTIVITY_NAME` @@ -124,24 +122,24 @@ This is just a quick overview of what Jikan can do for you. For more details on **Example:** `continue revision` -### Ending an activity: `end` +### 5.3 Ending an activity: `end` **Usage:** Stops recording the time for an ongoing activity and stores it into the activity list. **Format:** `end` * An activity must be started or continued before it can be ended. -### Aborting an activity: `abort` +### 5.4 Aborting an activity: `abort` **Usage:** Aborts the current activity and does not save it to the activity list. **Format:** `abort` * An activity must be started or continued before it can be ended. -### Delete an activity: `delete` +### 5.5 Delete an activity: `delete` **Usage:** Deletes an activity in the activity list. **Format:** `delete ACTIVITY_NAME` -### Listing activities: `list` +### 5.6 Listing activities: `list` **Usage:** Displays a list of the completed activities. **Format:** `list TIME_PERIOD` @@ -161,7 +159,7 @@ This is just a quick overview of what Jikan can do for you. For more details on * `list 01/01/2020` or `list 2020-01-01` lists all activities completed on 1 Jan 2020. * `list 01/01/2020 20/02/2020` lists all activities than fall within 1 Jan 2020 and 20 Feb 2020. -### Editing an activity: `edit` +### 5.7 Editing an activity: `edit` **Usage:** Edits the name or allocated time of an activity in the activity list. **Format** @@ -173,24 +171,24 @@ This is just a quick overview of what Jikan can do for you. For more details on `edit CS1010 assignment /en CS1010 assignment 2` Activity name is edited to `CS1010 assignment 2` `edit CS1010 assignment /ea 10:00:00` Allocated time for activity is edited to `10:00:00` -## Finding and Filtering +## 6. Finding and Filtering By using `find` and `filter` commands, the user can reduce clutter and zoom-in to specific activities containing certain keywords or tags. The sub-query flag `-s` allows chaining any combination of `find` and `filter` commands to further reduce clutter. These features are particularly useful when the visualisation of time spent with minimal clutter is required. -### Finding Activities by Name: `find` +### 6.1 Finding Activities by Name: `find` **Usage:** Users can request for a sub-list of activities that has names which contain any of the given keywords. If there are more than one keyword, each keyword should be separated with ` / `. **Format:** * `find KEYWORD` * `find KEYWORD1 / KEYWORD2 / KEYWORD3` -### Filtering Activities by Tags: `filter` +### 6.2 Filtering Activities by Tags: `filter` **Usage:** Users can request for a sub-list of activities that has specific tags. Each tag should be space separated. **Format:** * `filter TAGNAME` * `filter TAGNAME1 TAGNAME2` -### Chaining Finds & Filters: `-s` +### 6.3 Chaining Finds & Filters: `-s` **Usage:** Users can provide the `find` and `filter` command on the last shown list (also compatible after a `list` command) by providing the `-s` flag after each `find` or `filter` command. @@ -205,7 +203,7 @@ If we want to find all CS2106 tutorials, we can first use `filter 2106` to filte ![chain graph activities](./pictures/filter-find_chain.PNG) -#### Single Input Chaining: `;` +#### 6.3.1 Single Input Chaining: `;` **Usage:** Users can achieve the same outcome as multiple `-s` chaining with a single input. This is done by separating `find` and `filter` commands with ` ; `. @@ -215,7 +213,7 @@ If we want to find all CS2106 tutorials, we can first use `filter 2106` to filte Note: `-s` is only relevant in the first command of the entire input string, as subsequent commands are automatically chained. -## Graphs +## 7. Graphs By using the following commands, users can get a visual representation of the time spent on each activity and their current progress. The 3 types of graphs are : * *Activity time graph* - Total time spent on each activity: `graph activities SCALE` @@ -224,7 +222,7 @@ The 3 types of graphs are : Tip: Use `find`, `filter` and `list` commands to reduce clutter before graphing as the graphs are based on the last shown list of activities. -### Activity time graph: `graph activities` +### 7.1 Activity time graph: `graph activities` **Usage:** View a comparison of the absolute time spent on each activity in the last shown list. The parameter `SCALE` refers to the number of minutes represented by each point on the graph. @@ -235,7 +233,7 @@ Note: As the units of `SCALE` is minutes, if your activity is less than a minute **Example:** `graph activities 10` -### Tags time graph: `graph tags` +### 7.2 Tags time graph: `graph tags` **Usage:** View a comparison of the absolute time spent on each tag in the last shown list. ![graph tags](./pictures/graphtags_example.PNG) @@ -255,7 +253,7 @@ As tags can be used to group activities of a similar nature together (i.e. same **Example:** `graph tags 1` -### Activity allocation graph: `graph allocations` +### 7.3 Activity allocation graph: `graph allocations` **Usage:** View the progress of activities to see how much time was spent on the activity relative to the allocated time. Note: Only activities with an `ALLOCATED_TIME` will be shown. @@ -272,7 +270,7 @@ as shown in the graph) **Format:** `graph allocations` -### Chaining `list`, `find` and `filter` with `graph` command: +### 7.4 Chaining `list`, `find` and `filter` with `graph` command: Using `list`, `find` and `filter` commands you can sieve out the information you wish to be graphed. **Graph Activities Example:** @@ -293,11 +291,11 @@ Using `list`, `find` and `filter` commands you can sieve out the information you `find Lab` gives us all `Lab` activities, then we can use `graph allocations` to view the progress bar of each of the activities to see how much time was spent on the activity relative to the time that was allocated. -## Tag Goals +## 8. Tag Goals By using the `goal` command, users can set specific goals for how long they would like to spend on activities under a certain tags as well as view the amount of time they have spent in total for those activities as compared to their goal. -### Set goal: `goal TAG_NAME /g DURATION` +### 8.1 Set goal: `goal TAG_NAME /g DURATION` **Usage:** Sets a duration goal for a tag **Format:** `goal TAG_NAME /g DURATION` @@ -305,33 +303,33 @@ By using the `goal` command, users can set specific goals for how long they woul **Example:** `goal core /g 24:00:00` a goal of `24:00:00` is added for the tag `core` -### Delete goal: `goal TAG_NAME /d` +### 8.2 Delete goal: `goal TAG_NAME /d` **Usage:** Deletes the duration goal set for the tag. **Format:** `goal TAG_NAME /d` -### View goals: `goal` +### 8.3 View goals: `goal` **Usage:** Displays the tags with their goals, actual time spent on activities with these tags and the difference between the 2 timings. **Format:** `goal` ![goal display](./pictures/GoalDisplay.PNG) -## Automated Cleaning +## 9. Automated Cleaning Jikan provides a `clean` command where users can automate the cleaning of activities from the activity list at application startup. -### Activate cleaning: `clean on` +### 9.1 Activate cleaning: `clean on` **Usage:** Switch on automated cleaning. **Format:** `clean on` -### Deactivate cleaning: `clean off` +### 9.2 Deactivate cleaning: `clean off` **Usage:** Switch off automated cleaning. **Format:** `clean off` -### Set the number of activities to clean: `clean /n` +### 9.3 Set the number of activities to clean: `clean /n` **Usage:** Set a number of activities to clean. **Format:** `clean /n NUMBER` @@ -360,27 +358,27 @@ Upon the next startup, the automated cleaning will do its work and clean the 2 o Note that since the user specified to clean only 2 activities, only activity 6 and 7 are cleaned and activity 10 remains in the activity list. -### Automated Cleaning for Logs: +### 9.4 Automated Cleaning for Logs: Jikan also provides cleaning for log file which are used to record important information during program execution. This feature will be useful to users who are running this application on systems with limited hardware (small storage space). -### Activate log cleaning: `clean log on` +### 9.5 Activate log cleaning: `clean log on` **Usage:** Switch on automated cleaning. **Format:** `clean log on` -### Deactivate log cleaning: `clean log off` +### 9.6 Deactivate log cleaning: `clean log off` **Usage:** Switch off automated cleaning. **Format:** `clean log off` -### Set the number of logs to clean: `clean log /n` +### 9.7 Set the number of logs to clean: `clean log /n` **Usage:** Set number of lines of logs to clean. **Format:** `clean log /n NUMBER` -## Command Guide +## 10. Command Guide * Start an activity: `start ACTVITY_NAME` * optional: `start ACTIVITY_NAME /a ALLOCATED_TIME /t TAGS` From 421f778facd1e239b0bd9cca33632838afe1d1e5 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sun, 19 Apr 2020 15:21:18 +0800 Subject: [PATCH 412/415] Fix test --- src/test/java/jikan/command/EditCommandTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/jikan/command/EditCommandTest.java b/src/test/java/jikan/command/EditCommandTest.java index 89bbd161e..1c4b33b33 100644 --- a/src/test/java/jikan/command/EditCommandTest.java +++ b/src/test/java/jikan/command/EditCommandTest.java @@ -66,7 +66,7 @@ void executeEditName() { } @Test - void executeEditAllocatedTime() { + void executeEditAllocatedTime() throws NullPointerException { try { populateActivityList(); } catch (InvalidTimeFrameException e) { From f452667490935ddf29fbb5b4ac8946d295ce401b Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sun, 19 Apr 2020 15:24:10 +0800 Subject: [PATCH 413/415] Catch exceptions in test --- src/test/java/jikan/command/EditCommandTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/jikan/command/EditCommandTest.java b/src/test/java/jikan/command/EditCommandTest.java index 1c4b33b33..15f9bf332 100644 --- a/src/test/java/jikan/command/EditCommandTest.java +++ b/src/test/java/jikan/command/EditCommandTest.java @@ -58,7 +58,7 @@ void executeEditName() { Command command = new EditCommand(parameters); try { command.executeCommand(activities); - } catch (EmptyNameException | ExtraParametersException e) { + } catch (EmptyNameException | ExtraParametersException | NullPointerException e) { System.out.println("Field error."); } @@ -66,7 +66,7 @@ void executeEditName() { } @Test - void executeEditAllocatedTime() throws NullPointerException { + void executeEditAllocatedTime() { try { populateActivityList(); } catch (InvalidTimeFrameException e) { @@ -79,7 +79,7 @@ void executeEditAllocatedTime() throws NullPointerException { Command command = new EditCommand(parameters); try { command.executeCommand(activities); - } catch (EmptyNameException | ExtraParametersException e) { + } catch (EmptyNameException | ExtraParametersException | NullPointerException e) { System.out.println("Field error."); } From ce08e50cb2373a106b00bc35758182bf2249ace3 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sun, 19 Apr 2020 15:27:12 +0800 Subject: [PATCH 414/415] Fix test --- src/test/java/jikan/command/EditCommandTest.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/test/java/jikan/command/EditCommandTest.java b/src/test/java/jikan/command/EditCommandTest.java index 15f9bf332..50330a6ca 100644 --- a/src/test/java/jikan/command/EditCommandTest.java +++ b/src/test/java/jikan/command/EditCommandTest.java @@ -81,6 +81,7 @@ void executeEditAllocatedTime() { command.executeCommand(activities); } catch (EmptyNameException | ExtraParametersException | NullPointerException e) { System.out.println("Field error."); + return; } assertEquals(activities.get(1).getAllocatedTime(), Duration.parse("PT10H10M10S")); From 2c693971a96faee71c86a1a6ed25a59f8d7963ae Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sun, 19 Apr 2020 15:29:17 +0800 Subject: [PATCH 415/415] fix test --- src/test/java/jikan/command/EditCommandTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/jikan/command/EditCommandTest.java b/src/test/java/jikan/command/EditCommandTest.java index 50330a6ca..13ba3f0a4 100644 --- a/src/test/java/jikan/command/EditCommandTest.java +++ b/src/test/java/jikan/command/EditCommandTest.java @@ -60,6 +60,7 @@ void executeEditName() { command.executeCommand(activities); } catch (EmptyNameException | ExtraParametersException | NullPointerException e) { System.out.println("Field error."); + return; // Only needed for UNIX test } assertEquals(activities.get(1).getName(), "Activity4"); @@ -81,7 +82,7 @@ void executeEditAllocatedTime() { command.executeCommand(activities); } catch (EmptyNameException | ExtraParametersException | NullPointerException e) { System.out.println("Field error."); - return; + return; // Only needed for UNIX test } assertEquals(activities.get(1).getAllocatedTime(), Duration.parse("PT10H10M10S"));

  • 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 D!Tyl3 literal 0 HcmV?d00001 diff --git a/docs/pictures/startCD2.png b/docs/pictures/startCD2.png new file mode 100644 index 0000000000000000000000000000000000000000..ce79f85b0d2cf1f35ebefd514603462a68b4a5cd GIT binary patch literal 38035 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 FP$wlNN#4BHvu_^n#+|>^ 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 BvZVk3 literal 0 HcmV?d00001 From 326381a6de6835b69fad8ed20d1d5a9b5968bb93 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sat, 11 Apr 2020 01:51:42 +0800 Subject: [PATCH 350/415] Update DG --- docs/DeveloperGuide.md | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 3455b21fa..abc6354ed 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -325,31 +325,45 @@ The StorageHandler class functions as a support to the main Storage class, allow ### 3.5 Edit feature The edit feature allows the user to make changes to activities that have been saved in the activity list. This is to allow the user to rectify any mistakes that may have been made during the initial recording of the activity. - #### 3.5.1 Current Implementation The following sequence diagram shows how the edit feature works. The current implementation of the edit feature allows the user to edit the activity name as well as its allocated time. The following sequence diagram shows how the edit feature works for editing the activity name. The diagram for the editing of allocated time is omitted as the sequence is relatively similar. ![image_info](./pictures/EditSequenceDiagram.png) -The current implementation of the edit feature allows the user to edit only the name parameter of the activity. When the user wants to edit an activity using the edit command, the Parser creates a new EditCommand object. The `executeCommand()` method of the EditCommand object is called and the specified parameters are updated accordingly. +The current implementation of the edit feature allows the user to edit only the name and allocated time parameter of the activity. When the user wants to edit an activity using the edit command, a new EditCommand object is created. The `executeCommand()` method of the EditCommand object is called and the specified parameters are updated accordingly. -The order of method calls to edit the activity details is as follows if the specified activity exists (meaning `index >= 0`) else an exception is thrown: +The order of method calls to edit the activity details is as follows if the specified activity exists (meaning `index != -1`) else an exception is thrown: 1. The `updateName()` method of the ActivityList class is called, with the user-specified parameters of the activity index and new activity name 2. The `get()` method is self-invoked by the ActivityList class to obtain the activity at the given index 3. The `setName()` method of the Activity class is called to edit the activity name to the user-specified name -4. The activity with the updated name is returned to the activityList +4. The activity is updated with its new name in the activityList. +5. The `fieldChangeUpdateFile()` method of the StorageHandler class is called to update the data file with the new activity name. #### 3.5.2 Additional Implementations -The current implementation of the edit feature only allows the user to edit the activity name. Hence, additional implementations of the edit feature should allow the user to edit other parameters of the activity such as the tags and the start and end dates. +The current implementation of the edit feature only allows the user to edit the activity name and allocated time. Hence, additional implementations of the edit feature could allow the user to edit other parameters of the activity such as the tags and the start and end dates. This will require the implementation of more update methods in the ActivityList class to allow for the changes to be updated in the activityList after it has been edited. #### 3.5.3 Design Considerations -By letting the user edit the name and tags of the activity, it will allow them to correct any mistakes made during the data entry. This ensures that there is an accurate record of activities such as in cases where the user may be trying to record the same activity but has misspelled it, resulting in the program regarding it as a different activity where there would be multiple unnecessary new entries in the activity list, making the analysis of the time spent more tedious and inaccurate. - -However, by allowing the user to edit the start date and time, there may be potential inaccuracies in the actual activity recording. This is due to the fact that the time recorded in the program is based on the LocalDateTime. By introducing user input, the dates and time may be recorded incorrectly, defeating the purpose of the time tracking program. - +##### Current Design +The user is able to edit only the name and allocated time of the activity, which are user input data. +Pros: +* The user is able to correct any mistake made during the recording of the activity. +* The user is able to adjust their allocated time for the activity based on their needs. +* Ensures that the record of activities is accurate and consistent in order for more efficient analysis of the time spent. + +Cons: +* The user is only able to edit 2 parameters of the activity, which may be restrictive for them. + +##### Possible Design +The user is able to edit any parameters of the activity, including tags, start and end date/time. +Pros: +* The user has more flexibility in modifying the record of activities based on their needs. + +Cons: +* By allowing the user to edit the date and time, there may be potential inaccuracies in the record of activities, defeating the purpose of the time tracking program. +* By allowing the user to edit the tags, the tag goals command may become more complicated due to the need to keep track of the presence of the tags. ### 3.6 Continue Feature The continue feature allows the user to continue a previously ended activity. From 7fc4ebdba9b62dbbf66da5f1b7e527cb4ae9b610 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sat, 11 Apr 2020 01:58:00 +0800 Subject: [PATCH 351/415] Fix formatting for DG --- docs/DeveloperGuide.md | 9 ++++++--- docs/team/nigellenl.md | 41 ++++++++++++++++++++++++++++++++--------- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index abc6354ed..4ce6acca1 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -347,23 +347,26 @@ This will require the implementation of more update methods in the ActivityList #### 3.5.3 Design Considerations ##### Current Design -The user is able to edit only the name and allocated time of the activity, which are user input data. +The user is able to edit only the name and allocated time of the activity, which are user input data. + Pros: * The user is able to correct any mistake made during the recording of the activity. * The user is able to adjust their allocated time for the activity based on their needs. * Ensures that the record of activities is accurate and consistent in order for more efficient analysis of the time spent. Cons: -* The user is only able to edit 2 parameters of the activity, which may be restrictive for them. +* The user is only able to edit 2 parameters of the activity, which may be restrictive for them. ##### Possible Design -The user is able to edit any parameters of the activity, including tags, start and end date/time. +The user is able to edit any parameters of the activity, including tags, start and end date/time. + Pros: * The user has more flexibility in modifying the record of activities based on their needs. Cons: * By allowing the user to edit the date and time, there may be potential inaccuracies in the record of activities, defeating the purpose of the time tracking program. * By allowing the user to edit the tags, the tag goals command may become more complicated due to the need to keep track of the presence of the tags. + ### 3.6 Continue Feature The continue feature allows the user to continue a previously ended activity. diff --git a/docs/team/nigellenl.md b/docs/team/nigellenl.md index 5c66a1029..eeef5fca3 100644 --- a/docs/team/nigellenl.md +++ b/docs/team/nigellenl.md @@ -77,26 +77,49 @@ By using the `goal` command, users can set specific goals for how long they woul ## Contributions to the Developer Guide (extracts) -### Edit feature +### 3.5 Edit feature +The edit feature allows the user to make changes to activities that have been saved in the activity list. This is to allow the user to rectify any mistakes that may have been made during the initial recording of the activity. + +#### 3.5.1 Current Implementation +The following sequence diagram shows how the edit feature works. The current implementation of the edit feature allows the user to edit the activity name as well as its allocated time. The following sequence diagram shows how the edit feature works for editing the activity name. The diagram for the editing of allocated time is omitted as the sequence is relatively similar. -*[The sequence diagram has been omitted in this section]* +_[The sequence diagram has been omitted in this section]_ -The current implementation of the edit feature allows the user to edit only the name parameter of the activity. When the user wants to edit an activity using the edit command, the Parser creates a new EditCommand object. The `executeCommand()` method of the EditCommand object is called and the specified parameters are updated accordingly. +The current implementation of the edit feature allows the user to edit only the name and allocated time parameter of the activity. When the user wants to edit an activity using the edit command, a new EditCommand object is created. The `executeCommand()` method of the EditCommand object is called and the specified parameters are updated accordingly. -The order of method calls to edit the activity details is as follows if the specified activity exists (meaning `index >= 0`) else an exception is thrown: +The order of method calls to edit the activity details is as follows if the specified activity exists (meaning `index != -1`) else an exception is thrown: 1. The `updateName()` method of the ActivityList class is called, with the user-specified parameters of the activity index and new activity name 2. The `get()` method is self-invoked by the ActivityList class to obtain the activity at the given index 3. The `setName()` method of the Activity class is called to edit the activity name to the user-specified name -4. The activity with the updated name is returned to the activityList +4. The activity is updated with its new name in the activityList. +5. The `fieldChangeUpdateFile()` method of the StorageHandler class is called to update the data file with the new activity name. + -#### 3.4.2 Additional Implementations +#### 3.5.2 Additional Implementations The current implementation of the edit feature only allows the user to edit the activity name and allocated time. Hence, additional implementations of the edit feature could allow the user to edit other parameters of the activity such as the tags and the start and end dates. This will require the implementation of more update methods in the ActivityList class to allow for the changes to be updated in the activityList after it has been edited. -#### 3.4.3 Design Considerations -By letting the user edit the name and allocated time of the activity, it will allow them to correct any mistakes made during the data entry as well as allowing them to update their allocated time for the activity. This ensures that there is an accurate record of activities such as in cases where the user may be trying to record the same activity but has misspelled it, resulting in the program regarding it as a different activity where there would be multiple unnecessary new entries in the activity list, making the analysis of the time spent more tedious and inaccurate. +#### 3.5.3 Design Considerations +##### Current Design +The user is able to edit only the name and allocated time of the activity, which are user input data. + +Pros: +* The user is able to correct any mistake made during the recording of the activity. +* The user is able to adjust their allocated time for the activity based on their needs. +* Ensures that the record of activities is accurate and consistent in order for more efficient analysis of the time spent. + +Cons: +* The user is only able to edit 2 parameters of the activity, which may be restrictive for them. + +##### Possible Design +The user is able to edit any parameters of the activity, including tags, start and end date/time. + +Pros: +* The user has more flexibility in modifying the record of activities based on their needs. -However, by allowing the user to edit the start date and time, there may be potential inaccuracies in the actual activity recording. This is due to the fact that the time recorded in the program is based on the LocalDateTime. By introducing user input, the dates and time may be recorded incorrectly, defeating the purpose of the time tracking program. +Cons: +* By allowing the user to edit the date and time, there may be potential inaccuracies in the record of activities, defeating the purpose of the time tracking program. +* By allowing the user to edit the tags, the tag goals command may become more complicated due to the need to keep track of the presence of the tags. From 45a41d48869994b724706c0dae2f2d9d04d1e1c5 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sat, 11 Apr 2020 02:02:49 +0800 Subject: [PATCH 352/415] Fix table of contents for DG --- docs/DeveloperGuide.md | 44 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 4ce6acca1..cf298f570 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -3,30 +3,30 @@ - [1. Setting Up](#1-setting-up) - [2. Design](#2-design) - [3. Implementation](#3-implementation) - - [3.1 Start Feature]() - - [3.1.1 Current Implementation]() - - [3.1.2 Additional Implementation]() - - [3.1.3 Design Considerations]() + - [3.1 Start Feature](#31-start-feature) + - [3.1.1 Current Implementation](#311-current-implementation) + - [3.1.2 Additional Implementation](#312-additional-implementation) + - [3.1.3 Design Considerations](#313-design-considerations) - [3.2 Clean Feature](#31-automated-storage-cleanup-feature) - [3.2.1 Current Implementation](#311-current-implementation) - - [3.2.2 Additional Implementation]() - - [3.2.3 Design Considerations]() - - [3.3 Storage feature](#32-storage-feature) - - [3.4 Storage handler](#33-storage-handler) - - [3.5 Edit feature](#34-edit-feature) - - [3.5.1 Current Implementation](#341-current-implementation) - - [3.5.2 Additional Implementations](#342-additional-implementations) - - [3.5.3 Design Considerations](#343-design-considerations) - - [3.6 Continue Feature](#35-continue-feature) - - [3.6.1 Current Implementation](#351-current-implementation) - - [3.6.2 Design Considerations](#352-design-considerations) - - [3.6.3 Additional Features](#353-additional-features) - - [3.7 List feature](#35-list-feature) - - [3.7.1 Current implementation](#351-current-implementation-1) - - [3.8 Find Feature](#36-find-feature) - - [3.8.1 Current Implementation](#361-current-implementation) - - [3.9 Filter Feature](#37-filter-feature) - - [3.9.1 Current Implementation](#371-current-implementation) + - [3.2.2 Additional Implementation](#322-additional-implementation) + - [3.2.3 Design Considerations](#323-design-considerations) + - [3.3 Storage feature](#33-storage-feature) + - [3.4 Storage handler](#34-storage-handler) + - [3.5 Edit feature](#35-edit-feature) + - [3.5.1 Current Implementation](#351-current-implementation) + - [3.5.2 Additional Implementations](#352-additional-implementations) + - [3.5.3 Design Considerations](#353-design-considerations) + - [3.6 Continue Feature](#36-continue-feature) + - [3.6.1 Current Implementation](#361-current-implementation) + - [3.6.2 Design Considerations](#362-design-considerations) + - [3.6.3 Additional Features](#363-additional-features) + - [3.7 List feature](#37-list-feature) + - [3.7.1 Current implementation](#371-current-implementation-1) + - [3.8 Find Feature](#38-find-feature) + - [3.8.1 Current Implementation](#381-current-implementation) + - [3.9 Filter Feature](#39-filter-feature) + - [3.9.1 Current Implementation](#391-current-implementation) - [4. Appendix](#4-appendix) - [Product Scope](#product-scope) - [Target user profile](#target-user-profile) From 20f7604573bdc830f188973ab027306de478205f Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sat, 11 Apr 2020 02:03:11 +0800 Subject: [PATCH 353/415] added functionality --- src/main/java/jikan/command/FindCommand.java | 66 +++++++++++++++++++- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index 656368b7c..e443a6bbf 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -2,7 +2,9 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; import jikan.exception.EmptyQueryException; +import jikan.exception.ExtraParametersException; import jikan.ui.Ui; import static jikan.Jikan.lastShownList; @@ -12,11 +14,15 @@ * Represents a command to find activities by name. */ public class FindCommand extends Command { + boolean isFinalCommand; + private static final String FILTER = "filter"; + private static final String FIND = "find"; /** * Constructor to create a new find command. */ public FindCommand(String parameters) { super(parameters.trim()); + isFinalCommand = true; } /** @@ -25,6 +31,25 @@ public FindCommand(String parameters) { */ @Override public void executeCommand(ActivityList activityList) { + parameters = parameters.replaceAll("\\s+", " "); + parameters = parameters.trim(); + // remove the magic number later + String[] tokenizedParameters = parameters.split(" ;", 2); + + if (tokenizedParameters.length > 1) { + String nextCommand = tokenizedParameters[1].trim(); + isFinalCommand = false; + parameters = tokenizedParameters[0]; + findSubList(); + callNextCommand(nextCommand, activityList); + } else { + isFinalCommand = true; + executeSingleCommand(activityList); + } + } + + + private void executeSingleCommand(ActivityList activityList) { if (parameters.contains("-s")) { findSubList(); } else { @@ -32,6 +57,37 @@ public void executeCommand(ActivityList activityList) { } } + private void callNextCommand(String userInput, ActivityList activityList) { + String[] tokenizedInputs = userInput.split(" ", 2); + String instruction = tokenizedInputs[0]; + System.out.println("we here"); + Command command = null; + switch (instruction) { + case FIND: + try { + command = new FindCommand(tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException e) { + Ui.printDivider("No keyword was given."); + } + break; + case FILTER: + try { + command = new FilterCommand(tokenizedInputs[1]); + } catch (ArrayIndexOutOfBoundsException e) { + Ui.printDivider("No keyword was given."); + } + break; + default: + Ui.printDivider("Please chain find or filter commands only"); + } + + try { + command.executeCommand(activityList); + } catch (EmptyNameException | ExtraParametersException e) { + Ui.printDivider("Error parsing command. Please try again."); + } + } + /** * Find activities which has names containing the keywords from the entire list. * @param activityList full like of activities @@ -46,7 +102,7 @@ private void findFullList(ActivityList activityList) { for (String keyword : keywords) { populateLastShownList(keyword, activityList.activities); } - Ui.printResults(lastShownList); + callPrintResults(); } } catch (EmptyQueryException e) { Ui.printDivider("No keyword was given."); @@ -70,12 +126,18 @@ private void findSubList() { populateLastShownList(keyword, prevList); } } - Ui.printResults(lastShownList); + callPrintResults(); } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { Ui.printDivider("No keyword was given."); } } + private void callPrintResults() { + if (isFinalCommand = true) { + Ui.printResults(lastShownList); + } + } + /** * Fills the last shown list with the results from matching names of activities to a keyword. * @param keyword the keyword to match against From d4c626a1b44e623592424340e6126a588f04eb23 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sat, 11 Apr 2020 02:12:43 +0800 Subject: [PATCH 354/415] Create Junit for clean command --- src/main/java/jikan/command/CleanCommand.java | 8 +- .../java/jikan/command/CleanCommandTest.java | 93 +++++++++++++++++++ 2 files changed, 97 insertions(+), 4 deletions(-) create mode 100644 src/test/java/jikan/command/CleanCommandTest.java diff --git a/src/main/java/jikan/command/CleanCommand.java b/src/main/java/jikan/command/CleanCommand.java index 067fb1d7f..976d838d4 100644 --- a/src/main/java/jikan/command/CleanCommand.java +++ b/src/main/java/jikan/command/CleanCommand.java @@ -43,7 +43,7 @@ public void executeCommand(ActivityList activityList) { * Method to check if user input is empty for clean command. * @return true if is empty and false otherwise. */ - private boolean isParameterEmpty() { + public boolean isParameterEmpty() { String parametersTrimmed = this.parameters.trim(); return parametersTrimmed.isEmpty(); } @@ -79,7 +79,7 @@ private void continueExecution() { * @param line a string representing a line of information. * @return the first word of the line. */ - private String getFirstWord(String line) { + public String getFirstWord(String line) { int delimiter = line.indexOf(" "); String word; if (delimiter == -1) { @@ -95,7 +95,7 @@ private String getFirstWord(String line) { * @param word a word to remove. * @return a this.parameters string without the word. */ - private String getRemainingParameter(String word) { + public String getRemainingParameter(String word) { int index = this.parameters.indexOf(word); int number = word.length(); String remainingParameter = this.parameters.substring(index + number); @@ -339,7 +339,7 @@ private void setValueForLogs(String remainingParameter) throws InvalidCleanComma * @throws InvalidCleanCommandException when the format of user input is wrong. * @throws NegativeNumberException when the numberString is negative. */ - private int getNumber(String numberString) throws InvalidCleanCommandException, NegativeNumberException { + public int getNumber(String numberString) throws InvalidCleanCommandException, NegativeNumberException { try { int value = Integer.parseInt(numberString); if (value < 0) { diff --git a/src/test/java/jikan/command/CleanCommandTest.java b/src/test/java/jikan/command/CleanCommandTest.java new file mode 100644 index 000000000..5f361a5a3 --- /dev/null +++ b/src/test/java/jikan/command/CleanCommandTest.java @@ -0,0 +1,93 @@ +package jikan.command; + +import jikan.cleaner.LogCleaner; +import jikan.cleaner.StorageCleaner; +import jikan.exception.InvalidCleanCommandException; +import jikan.exception.NegativeNumberException; +import jikan.storage.Storage; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class CleanCommandTest { + + Storage storage = new Storage("data/test.csv"); + StorageCleaner storageCleaner = new StorageCleaner(storage); + LogCleaner logCleaner = new LogCleaner(); + + @Test + void checkIfParameterEmpty() { + CleanCommand cleanCommand = new CleanCommand("", storageCleaner, logCleaner); + boolean isEmpty = cleanCommand.isParameterEmpty(); + assertEquals(isEmpty,true); + cleanCommand = new CleanCommand(" ", storageCleaner, logCleaner); + isEmpty = cleanCommand.isParameterEmpty(); + assertEquals(isEmpty, true); + cleanCommand = new CleanCommand(" abc", storageCleaner, logCleaner); + isEmpty = cleanCommand.isParameterEmpty(); + assertEquals(isEmpty, false); + cleanCommand = new CleanCommand("abc ", storageCleaner, logCleaner); + isEmpty = cleanCommand.isParameterEmpty(); + assertEquals(isEmpty, false); + cleanCommand = new CleanCommand(" abc ", storageCleaner, logCleaner); + isEmpty = cleanCommand.isParameterEmpty(); + assertEquals(isEmpty, false); + } + + @Test + void checkGetFirstWord() { + CleanCommand cleanCommand = new CleanCommand("", storageCleaner, logCleaner); + String firstWord = cleanCommand.getFirstWord(""); + assertEquals(firstWord,""); + firstWord = cleanCommand.getFirstWord("abc"); + assertEquals(firstWord, "abc"); + firstWord = cleanCommand.getFirstWord("abc def geh"); + assertEquals(firstWord, "abc"); + firstWord = cleanCommand.getFirstWord("ab c"); + assertEquals(firstWord, "ab"); + } + + @Test + void checkGetRemainingParameter() { + CleanCommand cleanCommand = new CleanCommand("log on", storageCleaner, logCleaner); + String remainingParameter = cleanCommand.getRemainingParameter("log"); + assertEquals(remainingParameter, "on"); + cleanCommand = new CleanCommand("log on", storageCleaner, logCleaner); + remainingParameter = cleanCommand.getRemainingParameter("log"); + assertEquals(remainingParameter, "on"); + cleanCommand = new CleanCommand("log on /n", storageCleaner, logCleaner); + remainingParameter = cleanCommand.getRemainingParameter("log"); + assertEquals(remainingParameter, "on /n"); + cleanCommand = new CleanCommand("log on 123 ", storageCleaner, logCleaner); + remainingParameter = cleanCommand.getRemainingParameter("log"); + assertEquals(remainingParameter, "on 123"); + cleanCommand = new CleanCommand("log", storageCleaner, logCleaner); + remainingParameter = cleanCommand.getRemainingParameter("log"); + assertEquals(remainingParameter, ""); + } + + @Test + void checkGetNumber() { + CleanCommand cleanCommand = new CleanCommand("", storageCleaner, logCleaner); + Assertions.assertThrows(InvalidCleanCommandException.class, () -> { + cleanCommand.getNumber("123 "); + }); + Assertions.assertThrows(NegativeNumberException.class, () -> { + cleanCommand.getNumber("-123"); + }); + try { + int number = cleanCommand.getNumber("123"); + assertEquals(number, 123); + } catch (InvalidCleanCommandException | NegativeNumberException e) { + // Should not reach here + } + try { + int number = cleanCommand.getNumber("0"); + assertEquals(number, 0); + } catch (InvalidCleanCommandException | NegativeNumberException e) { + // Should not reach here + } + } +} From 04220ef1479c6dddd31ae0156a78a96aad7e7e0d Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sat, 11 Apr 2020 02:34:53 +0800 Subject: [PATCH 355/415] added the semi colon feature --- .../java/jikan/command/FilterCommand.java | 71 +++++++++++++++++-- src/main/java/jikan/command/FindCommand.java | 22 ++++-- 2 files changed, 84 insertions(+), 9 deletions(-) diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index ad78a29c1..184e6bd01 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -2,7 +2,9 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; +import jikan.exception.EmptyNameException; import jikan.exception.EmptyQueryException; +import jikan.exception.ExtraParametersException; import jikan.ui.Ui; import java.util.ArrayList; @@ -15,7 +17,10 @@ * Represents a command to filter activities by specified tags. */ public class FilterCommand extends Command { - + boolean isFinalCommand; + boolean isChained; + private static final String FILTER = "filter"; + private static final String FIND = "find"; /** * Constructor to create a new filter command. */ @@ -23,19 +28,72 @@ public FilterCommand(String parameters) { super(parameters); } + public FilterCommand(String parameters, boolean isFinal, boolean hasChaining) { + super(parameters.trim()); + isFinalCommand = isFinal; + isChained = hasChaining; + } /** * Shows the user all past activities that has tags which match the one or more keywords queried by the user. * @param activityList the activity list to search for matching activities */ @Override public void executeCommand(ActivityList activityList) { - if (parameters.contains("-s")) { + parameters = parameters.replaceAll("\\s+", " "); + parameters = parameters.trim(); + // remove the magic number later + String[] tokenizedParameters = parameters.split(" ;", 2); + + if (tokenizedParameters.length > 1) { + String nextCommand = tokenizedParameters[1].trim(); + isFinalCommand = false; + parameters = tokenizedParameters[0]; + filterSubList(); + callNextCommand(nextCommand, activityList); + } else { + isFinalCommand = true; + executeSingleCommand(activityList); + } + } + + private void executeSingleCommand(ActivityList activityList) { + if (parameters.contains("-s") || isChained == true) { filterSubList(); } else { filterFullList(activityList); } } + private void callNextCommand(String userInput, ActivityList activityList) { + String[] tokenizedInputs = userInput.split(" ", 2); + String instruction = tokenizedInputs[0]; + Command command = null; + switch (instruction) { + case FIND: + try { + command = new FindCommand(tokenizedInputs[1], false, true); + } catch (ArrayIndexOutOfBoundsException e) { + Ui.printDivider("No keyword was given."); + } + break; + case FILTER: + try { + command = new FilterCommand(tokenizedInputs[1], false, true); + } catch (ArrayIndexOutOfBoundsException e) { + Ui.printDivider("No keyword was given."); + } + break; + default: + Ui.printDivider("Please chain find or filter commands only"); + } + + try { + command.executeCommand(activityList); + } catch (EmptyNameException | ExtraParametersException e) { + Ui.printDivider("Error parsing command. Please try again."); + } + } + /** * Filters activities by tags from the entire list of activities. * @param activityList the full list of activities @@ -56,7 +114,7 @@ private void filterFullList(ActivityList activityList) { for (String keyword : keywords) { populateLastShownList(activityList, lastShownList, keyword); } - Ui.printResults(lastShownList); + callPrintResults(); } } catch (EmptyQueryException e) { Ui.printDivider("No keyword was given."); @@ -82,13 +140,18 @@ private void filterSubList() { for (String keyword : keywords) { populateLastShownList(prevList, lastShownList, keyword); } - Ui.printResults(lastShownList); + callPrintResults(); } } catch (ArrayIndexOutOfBoundsException | EmptyQueryException e) { Ui.printDivider("No keyword was given."); } } + private void callPrintResults() { + if (isFinalCommand == true) { + Ui.printResults(lastShownList); + } + } private void populateLastShownList(ActivityList targetList, ActivityList lastShownList, String keyword) { for (Activity i : targetList.activities) { // if (!lastShownList.activities.contains(i) && i.getTags().contains(keyword)) { diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index e443a6bbf..ca70f766d 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -15,6 +15,7 @@ */ public class FindCommand extends Command { boolean isFinalCommand; + boolean isChained; private static final String FILTER = "filter"; private static final String FIND = "find"; /** @@ -25,6 +26,13 @@ public FindCommand(String parameters) { isFinalCommand = true; } + public FindCommand(String parameters, boolean isFinal, boolean hasChaining) { + super(parameters.trim()); + isFinalCommand = isFinal; + isChained = hasChaining; + } + + /** * Shows the user all past activities that has names which match the keyword queried by the user. * @param activityList the activity list to search for matching activities @@ -37,11 +45,16 @@ public void executeCommand(ActivityList activityList) { String[] tokenizedParameters = parameters.split(" ;", 2); if (tokenizedParameters.length > 1) { + if (tokenizedParameters[1].length() == 0) { + System.out.println("screw you"); + // throw exception here; to do tmr: reduce duplicate code, add jUnit test and docs for this feature + } String nextCommand = tokenizedParameters[1].trim(); isFinalCommand = false; parameters = tokenizedParameters[0]; findSubList(); callNextCommand(nextCommand, activityList); + } else { isFinalCommand = true; executeSingleCommand(activityList); @@ -50,7 +63,7 @@ public void executeCommand(ActivityList activityList) { private void executeSingleCommand(ActivityList activityList) { - if (parameters.contains("-s")) { + if (parameters.contains("-s") || isChained == true) { findSubList(); } else { findFullList(activityList); @@ -60,19 +73,18 @@ private void executeSingleCommand(ActivityList activityList) { private void callNextCommand(String userInput, ActivityList activityList) { String[] tokenizedInputs = userInput.split(" ", 2); String instruction = tokenizedInputs[0]; - System.out.println("we here"); Command command = null; switch (instruction) { case FIND: try { - command = new FindCommand(tokenizedInputs[1]); + command = new FindCommand(tokenizedInputs[1], false, true); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("No keyword was given."); } break; case FILTER: try { - command = new FilterCommand(tokenizedInputs[1]); + command = new FilterCommand(tokenizedInputs[1], false, true); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("No keyword was given."); } @@ -133,7 +145,7 @@ private void findSubList() { } private void callPrintResults() { - if (isFinalCommand = true) { + if (isFinalCommand == true) { Ui.printResults(lastShownList); } } From bff537ac778d28079d0d3f92252633df46a43ea4 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sat, 11 Apr 2020 10:10:11 +0800 Subject: [PATCH 356/415] Completed Piping Feature --- .../java/jikan/command/FilterCommand.java | 23 +++++++++++----- src/main/java/jikan/command/FindCommand.java | 27 +++++++++++-------- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index 184e6bd01..50e3c54bf 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -26,6 +26,7 @@ public class FilterCommand extends Command { */ public FilterCommand(String parameters) { super(parameters); + isFinalCommand = true; } public FilterCommand(String parameters, boolean isFinal, boolean hasChaining) { @@ -45,22 +46,32 @@ public void executeCommand(ActivityList activityList) { String[] tokenizedParameters = parameters.split(" ;", 2); if (tokenizedParameters.length > 1) { + executeChainedCommand(activityList, tokenizedParameters); + } else { + isFinalCommand = true; + executeSingleCommand(activityList); + } + } + + private void executeChainedCommand(ActivityList activityList, String[] tokenizedParameters) { + if (tokenizedParameters[1].length() > 0) { String nextCommand = tokenizedParameters[1].trim(); isFinalCommand = false; parameters = tokenizedParameters[0]; - filterSubList(); + executeSingleCommand(activityList); callNextCommand(nextCommand, activityList); } else { isFinalCommand = true; - executeSingleCommand(activityList); + parameters = tokenizedParameters[0]; + searchSubList(); } } private void executeSingleCommand(ActivityList activityList) { if (parameters.contains("-s") || isChained == true) { - filterSubList(); + searchSubList(); } else { - filterFullList(activityList); + searchFullList(activityList); } } @@ -98,7 +109,7 @@ private void callNextCommand(String userInput, ActivityList activityList) { * Filters activities by tags from the entire list of activities. * @param activityList the full list of activities */ - private void filterFullList(ActivityList activityList) { + private void searchFullList(ActivityList activityList) { try { String query = parameters; if (query.length() < 1) { @@ -124,7 +135,7 @@ private void filterFullList(ActivityList activityList) { /** * Filter activities by tags based on the last shown list. */ - private void filterSubList() { + private void searchSubList() { try { String query = parameters.replace("-s ", ""); ActivityList prevList = new ActivityList(); diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index ca70f766d..37122253b 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -45,28 +45,33 @@ public void executeCommand(ActivityList activityList) { String[] tokenizedParameters = parameters.split(" ;", 2); if (tokenizedParameters.length > 1) { - if (tokenizedParameters[1].length() == 0) { - System.out.println("screw you"); - // throw exception here; to do tmr: reduce duplicate code, add jUnit test and docs for this feature - } + executeChainedCommand(activityList, tokenizedParameters); + } else { + isFinalCommand = true; + executeSingleCommand(activityList); + } + } + + private void executeChainedCommand(ActivityList activityList, String[] tokenizedParameters) { + if (tokenizedParameters[1].length() > 0) { String nextCommand = tokenizedParameters[1].trim(); isFinalCommand = false; parameters = tokenizedParameters[0]; - findSubList(); + executeSingleCommand(activityList); callNextCommand(nextCommand, activityList); - } else { isFinalCommand = true; - executeSingleCommand(activityList); + parameters = tokenizedParameters[0]; + searchSubList(); } } private void executeSingleCommand(ActivityList activityList) { if (parameters.contains("-s") || isChained == true) { - findSubList(); + searchSubList(); } else { - findFullList(activityList); + searchFullList(activityList); } } @@ -104,7 +109,7 @@ private void callNextCommand(String userInput, ActivityList activityList) { * Find activities which has names containing the keywords from the entire list. * @param activityList full like of activities */ - private void findFullList(ActivityList activityList) { + private void searchFullList(ActivityList activityList) { try { if (parameters.length() < 1) { throw new EmptyQueryException(); @@ -124,7 +129,7 @@ private void findFullList(ActivityList activityList) { /** * Find activities which has names containing the keywords from the last shown list. */ - private void findSubList() { + private void searchSubList() { try { String query = parameters.replace("-s ", ""); ArrayList prevList = new ArrayList<>(); From 04cd3dbe0c625470e231eef51b909571d819d6f3 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sat, 11 Apr 2020 10:17:58 +0800 Subject: [PATCH 357/415] fixed style violations --- src/main/java/jikan/command/FilterCommand.java | 8 +++++++- src/main/java/jikan/command/FindCommand.java | 6 +++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index 50e3c54bf..285f0c28d 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -21,6 +21,7 @@ public class FilterCommand extends Command { boolean isChained; private static final String FILTER = "filter"; private static final String FIND = "find"; + /** * Constructor to create a new filter command. */ @@ -29,11 +30,15 @@ public FilterCommand(String parameters) { isFinalCommand = true; } + /** + * Constructor to create a new filter command with chaining. + */ public FilterCommand(String parameters, boolean isFinal, boolean hasChaining) { super(parameters.trim()); isFinalCommand = isFinal; isChained = hasChaining; } + /** * Shows the user all past activities that has tags which match the one or more keywords queried by the user. * @param activityList the activity list to search for matching activities @@ -55,10 +60,10 @@ public void executeCommand(ActivityList activityList) { private void executeChainedCommand(ActivityList activityList, String[] tokenizedParameters) { if (tokenizedParameters[1].length() > 0) { - String nextCommand = tokenizedParameters[1].trim(); isFinalCommand = false; parameters = tokenizedParameters[0]; executeSingleCommand(activityList); + String nextCommand = tokenizedParameters[1].trim(); callNextCommand(nextCommand, activityList); } else { isFinalCommand = true; @@ -163,6 +168,7 @@ private void callPrintResults() { Ui.printResults(lastShownList); } } + private void populateLastShownList(ActivityList targetList, ActivityList lastShownList, String keyword) { for (Activity i : targetList.activities) { // if (!lastShownList.activities.contains(i) && i.getTags().contains(keyword)) { diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index 37122253b..09bc6d41f 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -18,6 +18,7 @@ public class FindCommand extends Command { boolean isChained; private static final String FILTER = "filter"; private static final String FIND = "find"; + /** * Constructor to create a new find command. */ @@ -26,6 +27,9 @@ public FindCommand(String parameters) { isFinalCommand = true; } + /** + * Constructor to create a new find command that has chaining. + */ public FindCommand(String parameters, boolean isFinal, boolean hasChaining) { super(parameters.trim()); isFinalCommand = isFinal; @@ -54,10 +58,10 @@ public void executeCommand(ActivityList activityList) { private void executeChainedCommand(ActivityList activityList, String[] tokenizedParameters) { if (tokenizedParameters[1].length() > 0) { - String nextCommand = tokenizedParameters[1].trim(); isFinalCommand = false; parameters = tokenizedParameters[0]; executeSingleCommand(activityList); + String nextCommand = tokenizedParameters[1].trim(); callNextCommand(nextCommand, activityList); } else { isFinalCommand = true; From fe25e2d0454166be366dd516971ef69cc5b5432d Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sat, 11 Apr 2020 10:49:21 +0800 Subject: [PATCH 358/415] Fixed PPP broken link and added to own PPP --- docs/AboutUs.md | 10 +- docs/DeveloperGuide.md | 2 +- docs/UserGuide.md | 2 +- docs/team/siuhian.md | 313 ++++++++++++++++++++++++++++++++++------- 4 files changed, 269 insertions(+), 58 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 4b1337965..f11b110d3 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,9 +2,9 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Ng Siu Hian | [Github](https://github.com/siuhian) | [Portfolio](docs/team/siuhian.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ananda Lye | [Github](https://github.com/ananda-lye) | [Portfolio](docs/team/ananda-lye.md) -![](https://via.placeholder.com/100.png?text=Photo) | Beatrice Chan | [Github](https://github.com/btricec) | [Portfolio](docs/team/btricec.md) -![](https://via.placeholder.com/100.png?text=Photo) | Nigelle Leo | [Github](https://github.com/nigellenl) | [Portfolio](docs/team/nigellenl.md) -![](https://via.placeholder.com/100.png?text=Photo) | Riccardo Di Maio | [Github](https://github.com/rdimaio) | [Portfolio](docs/team/rdimaio.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ng Siu Hian | [Github](https://github.com/siuhian) | [Portfolio](./team/siuhian.md) +![](https://via.placeholder.com/100.png?text=Photo) | Ananda Lye | [Github](https://github.com/ananda-lye) | [Portfolio](./team/ananda-lye.md) +![](https://via.placeholder.com/100.png?text=Photo) | Beatrice Chan | [Github](https://github.com/btricec) | [Portfolio](./team/btricec.md) +![](https://via.placeholder.com/100.png?text=Photo) | Nigelle Leo | [Github](https://github.com/nigellenl) | [Portfolio](./team/nigellenl.md) +![](https://via.placeholder.com/100.png?text=Photo) | Riccardo Di Maio | [Github](https://github.com/rdimaio) | [Portfolio](./team/rdimaio.md) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index cf298f570..201525eae 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -193,7 +193,7 @@ undesirable. Jikan provides a `clean` command where users can automate the cleaning of done activities (i.e activities with duration > allocation) and logging data at application startup. -![StartCD](./pictures/CleanCD.png) +![CleanCD](./pictures/CleanCD.png) With Jikan as the main entry for our application, diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 8c0df2b51..36e98c105 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -243,7 +243,7 @@ As tags can be used to group activities of a similar nature together (i.e. same **Example:** `graph tags 1` -### Activity targets graph: `graph allocations` +### Activity allocation graph: `graph allocations` **Usage:** View the progress of activities to see how much time was spent on the activity relative to the allocated time. Note: Only activities with an `ALLOCATED_TIME` will be shown. diff --git a/docs/team/siuhian.md b/docs/team/siuhian.md index 24476ab09..0a307ff3b 100644 --- a/docs/team/siuhian.md +++ b/docs/team/siuhian.md @@ -1,6 +1,6 @@ # Project Portfolio Page (PPP) ## Project overview -**Jikan** is a CLI time-tracker built in Java that aims to help manage tasks and projects. +**Jikan** is a CLI time-tracker built in Java that aims to help manage tasks and projects. Users can set tags and goals for their entries, ultimately being able to keep track of what's left to do and maintain an overview of how time was spent. @@ -15,6 +15,7 @@ ultimately being able to keep track of what's left to do and maintain an overvie * Fix bugs in the `start` command with inputs from the peer testing results. * Added more flexibility to the `start` command, `start cs2113 /a 10:30:00 /t tP` now works the same way as `start cs2113 /t tP /a 10:30:00` meaning the positions of /a and /t flags can now be used interchangeably. + * Added some more test cases to the Junit for StartCommand. * User interface * Sourced and implemented the existing Jikan logo that greets the user upon execution @@ -29,6 +30,7 @@ ultimately being able to keep track of what's left to do and maintain an overvie * Implemented `clean` command which allows the user to switch on/off the automated cleaner. * Allows the user to specify how much completed activities/logs to delete for each round of automated cleaning. This is done through the /n flag in the clean command. + * Did a Junit for CleanCommand to further test and improve the reliability of `clean` command. * Graph allocations * Provides the user with a graphical representation on the progress of all the activities. @@ -39,8 +41,8 @@ ultimately being able to keep track of what's left to do and maintain an overvie * Edited the command summary and usage section to ensure consistency with the features under my implementation. ### Contributions to the DG -* Explained the implementation of the automated cleaning feature (Under Section 3.1) using a mixture of sequence diagram -with flowcharts. +* Explained the implementation of the start feature (Under Section 3.1) using a mixture of sequence diagrams with class diagrams +* Explained the implementation of the clean feature (Under Section 3.2) using a mixture of sequence diagram with class diagrams. ### Contributions to team-based tasks * Generated ideas with the team on the set of features for the Jikan application. @@ -48,8 +50,9 @@ with flowcharts. * Enabled assertions in the build.gradle file. * Created the project repository and set up the team organization. * Helped create the Parser and Ui class to make the code more OOP. -* Documenting the target user profile. +* Documented the target user profile for UG and DG. * Helped out in resolving the text-ui-issues (date sensitive need to update everyday) that caused many commits to fail the checks. +* Fixed the bug that made our PPP links broken. ### Review/mentoring contributions * Provided feedback to peers on how certain features can be improved (e.g progress message for activities, @@ -63,83 +66,291 @@ with flowcharts. ### Contributions to the User Guide (Extracts) -#### Usage of Automated Cleaning +### Activity allocation graph: `graph allocations` +**Usage:** View the progress of activities to see how much time was spent on the activity relative to the allocated time. -As Jikan is a time tracker application which works with various data files (data file for activities, log files for execution history -etc.), over time it can be a mess to deal with these data files especially when they get too big. Thus, Jikan provides automated cleaning -services for such situations. +Note: Only activities with an `ALLOCATED_TIME` will be shown. -#### Activating the automated cleaning: `clean on | clean log on` -At runtime, users can switch on the automated cleaning services. Once the automated cleaning is activated, the application will -do an auto cleanup of files at the start of every execution until this services is switch off. Do note that the cleaning will only start from the next execution. -(i.e no cleaning will be done for the current execution which activated auto cleaning). +(Diagram omitted) -Note: \ -`clean on` activates the cleaning of data files where activities are stored. \ -`clean log on` activates the cleaning of log files where application execution history is stored. +For example, if we `graph allocations` for the activity list above, we will get the following graph: -#### Deactivating the automated cleaning: `clean off | clean log off` -At runtime, users can switch off the automated cleaning services. Once deactivated, the application will -stop doing an auto cleanup of files at the start of every execution. Similarly, the changes only applies to the next execution. +(Diagram omitted) -Note:\ -When the application is executed for the first time, the automated cleaning is deactivated by default and will remain so until it is activated by the user. +`activity 3` and `activity 5` does not have an allocated time, thus they do not appear in the graph. +The percentage shown in the graph represents the activity's progress relative to their allocated time. (`activity 4` have a duration of 2 seconds while its allocated time was 5 seconds, 2/5 * 100% = 40%. Thus the progress of `activity 4` is 40% +as shown in the graph) -#### Specifying how much data to clean: `clean /n NUMBER | clean log /n NUMBER` -At runtime, the user can manually set the amount of data to clean using these commands where `NUMBER` is an integer based on user input. -Thus, `clean /n 5` will automatically clean the top 5 oldest activities from the activity list upon every startup (assuming automated cleaning -is activated). +**Format:** +`graph allocations` -Note:\ -Default `NUMBER` value for data files : 3\ -Default `NUMBER` value for log files : 10 +## Automated Cleaning + +Jikan provides a `clean` command where users can automate the cleaning of activities from the activity list at application startup. + +### Activate cleaning: `clean on` +**Usage:** Switch on automated cleaning. + +**Format:** `clean on` + +### Deactivate cleaning: `clean off` +**Usage:** Switch off automated cleaning. + +**Format:** `clean off` + +### Set the number of activities to clean: `clean /n` +**Usage:** Set a number of activities to clean. + +**Format:** `clean /n NUMBER` + +Note: Once cleaning is switched on, the automated cleaning persists (i.e cleaning will be done at every application startup) until it is switched off. + +**Example:** + +(Diagram omitted) + +Taking a look at this cluttered activity list, we can see that there are some activities which are done (i.e duration > allocation). +Thus, to reduce clutter, we would like to get rid of these done activities. + +However, since the list is so huge, it would be troublesome to use the delete function as users will have to manually navigate through +the list to identify the done activities and delete them. + +This is where the `clean` command would be useful. See that activity 6, 7 and 10 are done. + +(Diagram omitted) + +By using the `clean` command. Users can choose how much of these done activities to clean, for the example here, the number is set to 2. + +(Diagram omitted) + +Upon the next startup, the automated cleaning will do its work and clean the 2 oldest done activities (i.e oldest here is based on date). + +Note that since the user specified to clean only 2 activities, only activity 6 and 7 are cleaned and activity 10 remains in the activity list. + +### Automated Cleaning for Logs: + +Jikan also provides cleaning for log file which are used to record important information during program execution. This feature will be useful +to users who are running this application on systems with limited hardware (small storage space). + +### Activate log cleaning: `clean log on` +**Usage:** Switch on automated cleaning. + +**Format:** `clean log on` + +### Deactivate log cleaning: `clean log off` +**Usage:** Switch off automated cleaning. + +**Format:** `clean log off` + +### Set the number of logs to clean: `clean log /n` +**Usage:** Set number of lines of logs to clean. + +**Format:** `clean log /n NUMBER` ### Contributions to the Developer Guide (Extracts) -#### 3.1 Automated Storage Cleanup feature +### 3.1 Start Feature + +#### 3.1.1 Current Implementation + +(Diagram omitted) + +With Jikan as the main entry point for our application, + +1. Jikan will receive user input and pass it to the Parser class to get the corresponding command. +2. The Parser class will initialise and return a Command class object based on the command in user input. +3. In this case, Parser will return a StartCommand class object to Jikan. +4. Then, Jikan will call the StartCommand#executeCommand method to start an activity. + +Additionally, StartCommand also implements the following operations: + +* **StartCommand#checkActivity** Checks if the activity already exists in the activity list. +* **StartCommand#checkTime** Checks if the allocated time provided is valid. +* **StartCommand#continueActivity** Continue on an existing activity. + +**checkActivity** + +(Diagram omitted) + +The diagram above shows how the StartCommand#checkActivity function works. This function is used to check +if the activity to be started exists in the activity list. If the activity exists in the list, that activity will be +continued and this way the user cannot start duplicate activities. + +1. When checkActivity() is called, it will make a call to the ActivityList#findActivity method. +2. Once the findActivity() method finishes execution, it will return an integer index back to checkActivity(). +3. If the index is not equals to -1, the activity to be started exists in the activity list and continueActivity() will be called. +4. Else, the activity to be started is a brand new activity and addActivityToList() will be called. + +**checkTime** + +(Diagram omitted) + +The diagram above shows how the StartCommand#checkTime function works. This function is used to check the validity of +the allocated time provided by the user input. If the allocated time is valid, the activity will be added to activity +list. + +1. When checkTime() is called, it will initialise two LocalTime objects called endTime and startTime respectively. +2. startTime will be initialised to time 00:00:00 while endTime will be calculated based on the user input to the start +command (i.e `start activity name /a HH:MM:SS /t tags`) +3. Then, the method Duration.between() will be used to get a Duration object that holds the time difference between startTime +and endTime. +4. If this Duration object is non zero (i.e user gave a valid non zero allocated time), then the activity will be added to the activity list +using the addActivity() method. + +**continueActivity** + +(Diagram omitted) + +The diagram above shows how the StartCommand#continueActivity function works. This function is used when the current activity +to be started already exists in the activity list. Thus, this function will check with the user whether to continue on that activity +and prevent duplicate activities from being started. + +1. When continueActivity() is called, it will make a call to the Scanner object to read in the next line of user input. +2. If the user input is "yes", information about the activity (activity name, tags etc.) will be forwarded to parser and the parser +will update the activity list (i.e when continue is used, activity duration is added on and needs to be updated). +3. Else, if the user input is "no", continueActivity() will notify the parser to read in the next line of user input. + +#### 3.1.2 Additional Implementation + +1. `start` command have the ability to continue an activity if the activity to be started exists in activity list as discussed above. However, the second +start command's tags and allocated time parameters will not be captured if the activity originally did have tags or allocated time. + * `start activity 1` + * `start activity 1 /a HH:MM:SS /t tags` (this command will continue activity 1 but won't add the tags and allocated time to it) + + Thus, it would be best for `start` command to address this issue and allow the second `start` command to not only continue the +activity but also edit the fields of the activity. + +2. Allows two activities to start at the same time. As a user, sometimes the activity we are doing may be linked to another activity (i.e activities like +revising CS2106 and doing CS2106 Labs are similar as doing the labs can serve like a revision too). + + Thus, it would be good if more than one activity can be started at a particular time. + +#### 3.1.3 Design Considerations + +The current design is centred around the Parser Class as all the relevant activity information (activity startTime, endTime, name, tags, +allocated time) are stored inside Parser. + +Since Parser is a public class. There are some benefits to this design. +* All the command classes have access to activity information. +* Makes the classes more lightweight as there is no need for local variables to store activity informations. +* Reduces coupling between the commands as they interact through Parser. + +However, there are some drawbacks to this design too. +* Since all the activity information are public, every class in Jikan can access/modify activity information which is +undesirable. +* This creates a lot of dependencies between Commands and Parser which makes unit testing harder to implement. +* As more commands is created to accommodate new features , Parser will be overloaded with new variables and classes. + +### 3.2 Clean Feature + +#### 3.2.1 Current Implementation + +Jikan provides a `clean` command where users can automate the cleaning of done activities (i.e activities with duration > allocation) and logging data +at application startup. + +(Diagram omitted) + +With Jikan as the main entry for our application, + +1. Upon startup, Jikan will initialise a LogCleaner and StorageCleaner object. +2. Jikan will call upon LogCleaner#autoClean() and StorageCleaner#autoClean() functions. +3. These two functions will check if the Storage and Log Cleaner are enabled respectively before cleaning. +4. Thus, by the time the user can interact with Jikan (i.e send commands to Jikan), the activity list and log files would already be cleaned. +5. Using the `clean` command, users would be able to manage the cleaner's behaviour (switching it on/off, set number of done activities/logging data to clean). + +The cleanup mechanism is stored internally as a StorageCleaner and LogCleaner class. + +These two classes have access to the data files of activity list and logs respectively and thus they are able to +directly manipulate the activity list and logging data. + +A status.txt file is initialised to keep track of the status (on/off) of the two cleaners and contains information on +the number of done activities/logging data for cleaning. + +Moreover, the CleanCommand also implements the following operation: -##### 3.1.1 Current Implementation +* **CleanCommand#setStatus** Switch on/off the two cleaners respectively. +* **CleanCommand#setValue** Set a value for the number of done activities/logging data to be cleaned. +* Note: The two cleaners are independent, setting a value/status for one of the cleaner will not affect the other cleaner. -The storage cleanup mechanism is stored internally as a StorageCleaner class. The StorageCleaner class has an association with the Storage class and thus it is able to access and edit the datafile which contains the list of activities. +**setStatus** -Additionally, when the StorageCleaner class is first initialised, it will create two files, namely a status file and a data file in the “recycled” folder under the “data” folder. The status file keeps track of the activation status of the storage cleaner while the data file serves as a recycle bin for deleted data. +(Diagram omitted) -Moreover, the class also implements the following operations: +The diagram above shows how CleanCommand#setStatus function works. This function is a generalized function that is used to +switch on or off the cleaners by checking the parameters to the `clean` command. Thus, based on the return value of getStatus() and +getCleaner(), there are four possible scenarios. -`StorageCleaner#initialiseCleaner - Loads up the status file to decide whether to activate/deactivate the automated cleaner.` +1. When setStatus() is called, the method will call its own class method getStatus() to check what is the status to set to. +2. There are two valid return values for getStatus() method which is "on" and "off". The diagram shows the former. +3. Upon receiving a valid return value from getStatus() which is "on" in the diagram, the setStatus() method will self invoke another +of its own class method getCleaner(). +4. The return result of the getCleaner() together with getStatus() will then be used to determine which cleaner are we setting and what is +the status to set to. +5. In other words, result of getCleaner() is used to determine whether are we calling StorageCleaner#setStatus or LogCleaner#setStatus while +the result of getStatus() determines the parameter to setStatus(). (e.g "on" will call setStatus("true") while "off" will call setStatus("false")). -`StorageCleaner#setStatus - Gives the user the freedom to activate/de-activate the cleaner using commands during application runtime.` +**setValue** -`StorageCleaner#autoClean - This operation is called whenever the application is executed. Storage cleaning will only be done if the cleaner is activated.` +The diagram of setValue is omitted as it is similar to setStatus diagram. This function is a generalized function that is used to +set a value for the number of done activities or the number of lines of logging data to be cleaned for the two cleaners respectively. -Given below is the example scenario of how the operations work. +1. When setValue() is called, the method will call its own class method getNumber() that will return an integer value corresponding to the number +to set to. +2. Upon receiving a valid return value (non negative), the setValue() method will self invoke another of its own class method getCleaner(). +3. The return result of the getCleaner() together with getNumber() will then be used to determine which cleaner are we setting and what is +the value to set to. +4. In other words, result of getCleaner() is used to determine whether are we calling StorageCleaner#setNumberOfActivitiesToClean or LogCleaner#setNumberOfLogsToClean +while the result of getNumber determines the parameter to these two functions. -###### initialiseCleaner +Note that steps 2-4 of setValue() are similar to steps 3-5 of setStatus(). -Step 1. Loads up the status file for reading. If the status file is not found, create a new status file and write the character ‘0’ to the first line of the status file. +On the other hand, the Storage/Log Cleaner class implements the following core operation of `clean` command. -Step 2. Read the first line of the status file, if a character ‘0’ is found, deactivate the automated cleanup. Else if a character ‘1’ is found, activate the automated cleanup. +* **Cleaner#autoClean** This operation is called whenever Jikan is executed. Cleaning will only be done to the activity list/logging data if +the two cleaners are enabled respectively. -###### setStatus +**autoClean** -Step 1. Read the boolean parameter `status`. +(Diagram omitted) -Step 2a. If `status` is equal to true, activate the automated cleanup and write the character ‘1’ to the first line of the status file. (overwrite any existing value at the first line). +The diagram above shows how Cleaner#autoClean function works. This function is called whenever Jikan executes Jikan#main and is used to +perform cleaning of the activity list and logging data if Storage Cleaner and Log Cleaner are enabled respectively. The number of done activities and +lines of logging data to clean is set to 5 at default if user did not specify a value for both cleaners. -Step 2b. If `status` is equal to false, deactivate the automated cleanup and write the character ‘0’ to the first line of the status file. +1. When main() is called, Jikan will first initialise both the StorageCleaner and LogCleaner object using StorageCleaner() and +LogCleaner(). +2. Once both objects are initialised, Jikan will first call storageAutoClean() method of the StorageCleaner class. +3. This method will invoke another method under the StorageCleaner class called checkStatus() which will return a boolean toClean variable. +4. If toClean == true, the storageAutoClean() method will proceed and clean up the activity list before returning control back to main(). +5. Else, the storageAutoClean() will not do any clean up and will immediately return control back to main(). +6. Steps 2 to 5 will then be repeated when Jikan call logAutoClean() method of the LogCleaner class. -###### autoClean +#### 3.2.2 Additional Implementation -Step 1. Check activation status of StorageCleaner through the class level attribute boolean `toClean`. +1. Currently, the data that is cleaned up by this command is sent to a recycled folder similar to how Windows recycle bin works. -Step 2a. If the attribute `toClean` is equal to `false`, return the operation and give control back to the caller. + Thus, it would be good to have a feature to restore the data deleted in the event the user wishes to recover some of the activities/logs. + + On a similar note, it would also be good to have a permanent delete feature built into the recycled folder so that items that are too old (> 6 months old) will + deleted away for good. + +2. The automated cleaning does not have a lot of flexibility as the current implementation only cleans up done activities starting from the oldest. -Step 2b. If the attribute `toClean` is equal to `true`, access the storage data file and remove some of the activities starting from the oldest. Put these deleted activities into the data file under the ‘recycled’ folder. + Thus, it would be good if the `clean` command is expanded to allow users more freedom in specifying what activities to clean. + + * `clean /n 3 /t CS2113` does cleaning on the 3 oldest done activities with CS2113 tag. + * `clean /n 5 /i 1/4/2020 3/4/2020` does cleaning on the 5 oldest done activities with dates between 1 April 2020 and 3 April 2020. + -##### 3.1.2 Additional Implementation (proposed) +#### 3.2.3 Design Considerations -`StorageCleaner#setDeleteQuota - Allows the user to manipulate how much activity is deleted when auto cleanup is activated. Currently only delete the oldest 3 activities.` +The current design uses the abstract cleaner class to create dedicated cleaners (i.e Storage and Log Cleaners) to perform +cleaning for various data files (e.g activity list data file, logging data file). -`StorageCleaner#setTimeFrame - Set a particular time frame for auto cleanup to activate. (i.e auto cleanup after every 2 weeks etc).` +There are some benefits to this design. +* Creating an abstract class reduces the amount of repetitive code as common methods between cleaners are abstracted out. +* Abstract classes produce a more OOP solution as different cleaners will handle different parts of the data. -`StorageCleaner#initialiseLogCleaner - Gives the storage cleaner an added functionality of being able to clear log files too.` +However there are drawbacks to this design too. +* There are some very similar methods with key differences that cannot be abstracted out (for e.g different parameters, different printing). +* This causes the CleanCommand class to have similar and repetitive methods to handle this difference. (for e.g setStorageCleanerOn(), setLogCleanerOn() etc). \ No newline at end of file From 84e774850786bc89c6a0021c823c0ba9337106b9 Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Sat, 11 Apr 2020 11:24:17 +0800 Subject: [PATCH 359/415] Added product intro in docs README --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index bbcc99c1e..f8ef49202 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,6 +1,6 @@ # Duke -{Give product intro here} +**Jikan** is a CLI time-tracker built in Java that aims to help manage tasks and projects. Users can set tags and goals for their entries, ultimately being able to keep track of what's left to do and maintain an overview of how time was spent. Useful links: * [User Guide](UserGuide.md) From 4dbeba7b1f5d14c55e9be343c03022f0434ec63e Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Sat, 11 Apr 2020 11:30:50 +0800 Subject: [PATCH 360/415] Add links to github.io versions --- docs/README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/README.md b/docs/README.md index f8ef49202..f01998f4d 100644 --- a/docs/README.md +++ b/docs/README.md @@ -3,6 +3,6 @@ **Jikan** is a CLI time-tracker built in Java that aims to help manage tasks and projects. Users can set tags and goals for their entries, ultimately being able to keep track of what's left to do and maintain an overview of how time was spent. Useful links: -* [User Guide](UserGuide.md) -* [Developer Guide](DeveloperGuide.md) -* [About Us](AboutUs.md) +* [User Guide](UserGuide.md) | [Web version](https://ay1920s2-cs2113-t15-1.github.io/tp/UserGuide.html) +* [Developer Guide](DeveloperGuide.md) | [Web version](https://ay1920s2-cs2113-t15-1.github.io/tp/DeveloperGuide.html) +* [About Us](AboutUs.md) | [Web version](https://ay1920s2-cs2113-t15-1.github.io/tp/AboutUs.html) From d9718f7f1e72be2b5558af0a7d9e3fbac9317cac Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Sat, 11 Apr 2020 11:32:14 +0800 Subject: [PATCH 361/415] Remove photo column from AboutUs --- docs/AboutUs.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index f11b110d3..05e816af6 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,10 +1,10 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Ng Siu Hian | [Github](https://github.com/siuhian) | [Portfolio](./team/siuhian.md) -![](https://via.placeholder.com/100.png?text=Photo) | Ananda Lye | [Github](https://github.com/ananda-lye) | [Portfolio](./team/ananda-lye.md) -![](https://via.placeholder.com/100.png?text=Photo) | Beatrice Chan | [Github](https://github.com/btricec) | [Portfolio](./team/btricec.md) -![](https://via.placeholder.com/100.png?text=Photo) | Nigelle Leo | [Github](https://github.com/nigellenl) | [Portfolio](./team/nigellenl.md) -![](https://via.placeholder.com/100.png?text=Photo) | Riccardo Di Maio | [Github](https://github.com/rdimaio) | [Portfolio](./team/rdimaio.md) +| Name | Github Profile | Portfolio +|:----:|:--------------:|:---------: +Ng Siu Hian | [Github](https://github.com/siuhian) | [Portfolio](./team/siuhian.md) +Ananda Lye | [Github](https://github.com/ananda-lye) | [Portfolio](./team/ananda-lye.md) +Beatrice Chan | [Github](https://github.com/btricec) | [Portfolio](./team/btricec.md) +Nigelle Leo | [Github](https://github.com/nigellenl) | [Portfolio](./team/nigellenl.md) +Riccardo Di Maio | [Github](https://github.com/rdimaio) | [Portfolio](./team/rdimaio.md) From e707d77b5e7ba510aab8997307351690916019a6 Mon Sep 17 00:00:00 2001 From: Riccardo Di Maio <35903974+rdimaio@users.noreply.github.com> Date: Sat, 11 Apr 2020 11:34:47 +0800 Subject: [PATCH 362/415] Added direct links to PPP web versions --- docs/AboutUs.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 05e816af6..a858ff949 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,10 +1,10 @@ # About us -| Name | Github Profile | Portfolio -|:----:|:--------------:|:---------: -Ng Siu Hian | [Github](https://github.com/siuhian) | [Portfolio](./team/siuhian.md) -Ananda Lye | [Github](https://github.com/ananda-lye) | [Portfolio](./team/ananda-lye.md) -Beatrice Chan | [Github](https://github.com/btricec) | [Portfolio](./team/btricec.md) -Nigelle Leo | [Github](https://github.com/nigellenl) | [Portfolio](./team/nigellenl.md) -Riccardo Di Maio | [Github](https://github.com/rdimaio) | [Portfolio](./team/rdimaio.md) +| Name | Github Profile | Portfolio | Portfolio (web link) +|:----:|:--------------:|:---------:|:--------------------: +Ng Siu Hian | [Github](https://github.com/siuhian) | [Portfolio](./team/siuhian.md) | [Portfolio (web link)](https://ay1920s2-cs2113-t15-1.github.io/tp/team/siuhian.html) +Ananda Lye | [Github](https://github.com/ananda-lye) | [Portfolio](./team/ananda-lye.md) | [Portfolio (web link)](https://ay1920s2-cs2113-t15-1.github.io/tp/team/ananda-lye.html) +Beatrice Chan | [Github](https://github.com/btricec) | [Portfolio](./team/btricec.md) | [Portfolio (web link)](https://ay1920s2-cs2113-t15-1.github.io/tp/team/btricec.html) +Nigelle Leo | [Github](https://github.com/nigellenl) | [Portfolio](./team/nigellenl.md) | [Portfolio (web link)](https://ay1920s2-cs2113-t15-1.github.io/tp/team/nigellenl.html) +Riccardo Di Maio | [Github](https://github.com/rdimaio) | [Portfolio](./team/rdimaio.md) | [Portfolio (web link)](https://ay1920s2-cs2113-t15-1.github.io/tp/team/rdimaio.html) From ba8e71116fd3bdc896f8588ebb82c698d669fd07 Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sat, 11 Apr 2020 11:38:08 +0800 Subject: [PATCH 363/415] Remove unused johndoe file --- docs/team/johndoe.md | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 docs/team/johndoe.md diff --git a/docs/team/johndoe.md b/docs/team/johndoe.md deleted file mode 100644 index ab75b391b..000000000 --- a/docs/team/johndoe.md +++ /dev/null @@ -1,6 +0,0 @@ -# John Doe - Project Portfolio Page - -## Overview - - -### Summary of Contributions From a9815a90097fd81683af496574cb194ccc22701e Mon Sep 17 00:00:00 2001 From: rdimaio Date: Sat, 11 Apr 2020 11:40:08 +0800 Subject: [PATCH 364/415] Add docstrings --- src/main/java/jikan/storage/Storage.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/jikan/storage/Storage.java b/src/main/java/jikan/storage/Storage.java index b399beb7e..1d8bbea8c 100644 --- a/src/main/java/jikan/storage/Storage.java +++ b/src/main/java/jikan/storage/Storage.java @@ -19,6 +19,7 @@ public class Storage { /** File object for current data file. */ public File dataFile; + /** Activity list linked to this storage file. */ public ActivityList activityList; /** From 446a1f4aea37c99317561128ab4d6a69ae51f256 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 11 Apr 2020 11:48:52 +0800 Subject: [PATCH 365/415] Update sequence diagrams for continue and graph --- docs/DeveloperGuide.md | 6 +++--- docs/pictures/continue.png | Bin 36949 -> 41926 bytes docs/pictures/end.png | Bin 38652 -> 40591 bytes docs/pictures/graph_seqDiag.png | Bin 0 -> 41607 bytes 4 files changed, 3 insertions(+), 3 deletions(-) create mode 100644 docs/pictures/graph_seqDiag.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 201525eae..d2cfc2751 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -83,10 +83,10 @@ _Fig 2.1. Architecture diagram of the Jikan program_ The high-level class diagram describes the structure of the components ![image_info](./pictures/Simplified_Class_Diagram.png) -_Fig 2.1. Class diagram of the Jikan program_ +_Fig 2.2. Class diagram of the Jikan program_ ![image_info](./pictures/Commands.png) -_Fig 2.2. Commands of Jikan (private methods omitted)_ +_Fig 2.3. Commands of Jikan (private methods omitted)_ All the commands inherit from the abstract `Command` class. Each command has a protected `parameters` attribute from it's Parent class `command` and an overridden method `executeCommand` which is called in `main` to execute the relevant command. @@ -499,7 +499,7 @@ This feature gives the user a visual representation of their activity duration a Graph can be used along with `list`, `find` and `filter` to sieve out the data to be graphed. #### 3.10.1 Current Implementation -![graph seq diagram](./pictures/graph.png) +![graph seq diagram](./pictures/graph_seqDiag.png) * This feature is called by the user when the `graph` command is entered into the command line. The user will then have to specify what he would like to graph (goals progress bar / tag duration / activity duration). * The Parser will create a GraphCommand object. * The GraphCommand will invoke its own `executeCommand()` method. diff --git a/docs/pictures/continue.png b/docs/pictures/continue.png index 0a02f70ac8145150029ae915d5ca47e7cb5afe2c..92e47988d5309c6bc71459d23ebc9dd58e6851b2 100644 GIT binary patch literal 41926 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∓?9zM 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 literal 38652 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 Bw@^UE&B|w?ns2w=U~hpgD#h#y}IC_ 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 diff --git a/docs/pictures/graph_seqDiag.png b/docs/pictures/graph_seqDiag.png new file mode 100644 index 0000000000000000000000000000000000000000..b0e6fddfd321ec2f0b7602a07cfc9da4d806ec9e GIT binary patch literal 41607 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 literal 0 HcmV?d00001 From 5d1035e9e860a10a77d01a427eb2a527e7833775 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sat, 11 Apr 2020 11:53:53 +0800 Subject: [PATCH 366/415] Added user guide and exceptions for single line chaining --- docs/UserGuide.md | 13 +++-- .../java/jikan/command/FilterCommand.java | 37 +++++++++----- src/main/java/jikan/command/FindCommand.java | 48 ++++++++++++++----- .../exception/InvalidCommandException.java | 4 ++ .../MultipleDelimitersException.java | 4 ++ src/main/java/jikan/parser/Parser.java | 5 ++ 6 files changed, 85 insertions(+), 26 deletions(-) create mode 100644 src/main/java/jikan/exception/InvalidCommandException.java create mode 100644 src/main/java/jikan/exception/MultipleDelimitersException.java diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 545806896..649378482 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -145,9 +145,9 @@ By using `find` and `filter` commands, the user can reduce clutter and zoom-in t * `filter TAGNAME` * `filter TAGNAME1 TAGNAME2` -### Chaining Lists, Finds & Filters: `-s` -**Usage:** Users can provide the `find` and `filter` command on the last shown list by providing the `-s` flag after each -`find` or `filter` command. +### Chaining Finds & Filters: `-s` +**Usage:** Users can provide the `find` and `filter` command on the last shown list (also compatible after a `list` +command) by providing the `-s` flag after each `find` or `filter` command. **Format:** * `find -s KEYWORD` @@ -159,6 +159,13 @@ By using `find` and `filter` commands, the user can reduce clutter and zoom-in t If we want to find all CS2106 tutorials, we can first use `filter 2106` to filter out all activities tagged `2106`, then use the find command with the flag, `find -s Tutorial` to get a list of all 2106 Tutorials. ![chain graph activities](./pictures/filter-find_chain.PNG) +#### Single Input Chaining: `;` +**Usage:** Users can achieve the same outcome as multiple `-s` chaining with a single input. This is done by separating +`find` and `filter` commands with ` ; `. + +**Examples:** +* `filter TAGNAME ; find KEYWORD1 ; find KEYWORD2` +* `filter -s TAGNAME ; find KEYWORD1 ; find KEYWORD2` ## Graphs By using the following commands, users can get a visual representation of the time spent on each activity and their current progress. diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index 285f0c28d..cb897f4ce 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -2,9 +2,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; -import jikan.exception.EmptyNameException; -import jikan.exception.EmptyQueryException; -import jikan.exception.ExtraParametersException; +import jikan.exception.*; import jikan.ui.Ui; import java.util.ArrayList; @@ -25,18 +23,28 @@ public class FilterCommand extends Command { /** * Constructor to create a new filter command. */ - public FilterCommand(String parameters) { + public FilterCommand(String parameters) throws MultipleDelimitersException { super(parameters); isFinalCommand = true; + this.parameters = parameters.replaceAll("\\s+", " "); + this.parameters = parameters.trim(); + if (parameters.contains(";;") || parameters.contains("; ;")) { + throw new MultipleDelimitersException(); + } } /** * Constructor to create a new filter command with chaining. */ - public FilterCommand(String parameters, boolean isFinal, boolean hasChaining) { + public FilterCommand(String parameters, boolean isFinal, boolean hasChaining) throws MultipleDelimitersException { super(parameters.trim()); isFinalCommand = isFinal; isChained = hasChaining; + this.parameters = parameters.replaceAll("\\s+", " "); + this.parameters = parameters.trim(); + if (parameters.contains(";;") || parameters.contains("; ;")) { + throw new MultipleDelimitersException(); + } } /** @@ -45,11 +53,8 @@ public FilterCommand(String parameters, boolean isFinal, boolean hasChaining) { */ @Override public void executeCommand(ActivityList activityList) { - parameters = parameters.replaceAll("\\s+", " "); - parameters = parameters.trim(); // remove the magic number later - String[] tokenizedParameters = parameters.split(" ;", 2); - + String[] tokenizedParameters = parameters.split(";", 2); if (tokenizedParameters.length > 1) { executeChainedCommand(activityList, tokenizedParameters); } else { @@ -64,7 +69,11 @@ private void executeChainedCommand(ActivityList activityList, String[] tokenized parameters = tokenizedParameters[0]; executeSingleCommand(activityList); String nextCommand = tokenizedParameters[1].trim(); - callNextCommand(nextCommand, activityList); + try { + callNextCommand(nextCommand, activityList); + } catch (InvalidCommandException e) { + Ui.printDivider("Please chain find or filter commands only"); + } } else { isFinalCommand = true; parameters = tokenizedParameters[0]; @@ -80,7 +89,7 @@ private void executeSingleCommand(ActivityList activityList) { } } - private void callNextCommand(String userInput, ActivityList activityList) { + private void callNextCommand(String userInput, ActivityList activityList) throws InvalidCommandException { String[] tokenizedInputs = userInput.split(" ", 2); String instruction = tokenizedInputs[0]; Command command = null; @@ -90,6 +99,8 @@ private void callNextCommand(String userInput, ActivityList activityList) { command = new FindCommand(tokenizedInputs[1], false, true); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("No keyword was given."); + } catch (MultipleDelimitersException e) { + Ui.printDivider("Please only use one ';' between each command."); } break; case FILTER: @@ -97,10 +108,12 @@ private void callNextCommand(String userInput, ActivityList activityList) { command = new FilterCommand(tokenizedInputs[1], false, true); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("No keyword was given."); + } catch (MultipleDelimitersException e) { + Ui.printDivider("Please only use one ';' between each command."); } break; default: - Ui.printDivider("Please chain find or filter commands only"); + throw new InvalidCommandException(); } try { diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index 09bc6d41f..d37146e58 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -2,9 +2,7 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; -import jikan.exception.EmptyNameException; -import jikan.exception.EmptyQueryException; -import jikan.exception.ExtraParametersException; +import jikan.exception.*; import jikan.ui.Ui; import static jikan.Jikan.lastShownList; @@ -22,18 +20,28 @@ public class FindCommand extends Command { /** * Constructor to create a new find command. */ - public FindCommand(String parameters) { + public FindCommand(String parameters) throws MultipleDelimitersException{ super(parameters.trim()); isFinalCommand = true; + this.parameters = parameters.replaceAll("\\s+", " "); + this.parameters = parameters.trim(); + if (parameters.contains(";;") || parameters.contains("; ;")) { + throw new MultipleDelimitersException(); + } } /** * Constructor to create a new find command that has chaining. */ - public FindCommand(String parameters, boolean isFinal, boolean hasChaining) { + public FindCommand(String parameters, boolean isFinal, boolean hasChaining) throws MultipleDelimitersException{ super(parameters.trim()); isFinalCommand = isFinal; isChained = hasChaining; + this.parameters = parameters.replaceAll("\\s+", " "); + this.parameters = parameters.trim(); + if (parameters.contains(";;") || parameters.contains("; ;")) { + throw new MultipleDelimitersException(); + } } @@ -43,10 +51,14 @@ public FindCommand(String parameters, boolean isFinal, boolean hasChaining) { */ @Override public void executeCommand(ActivityList activityList) { - parameters = parameters.replaceAll("\\s+", " "); - parameters = parameters.trim(); // remove the magic number later String[] tokenizedParameters = parameters.split(" ;", 2); + try { + checkForInvalidChaining(); + } catch (MultipleDelimitersException e) { + Ui.printDivider("Please only use one ';' between each command."); + return; + } if (tokenizedParameters.length > 1) { executeChainedCommand(activityList, tokenizedParameters); @@ -56,13 +68,23 @@ public void executeCommand(ActivityList activityList) { } } - private void executeChainedCommand(ActivityList activityList, String[] tokenizedParameters) { + private void checkForInvalidChaining() throws MultipleDelimitersException{ + if (parameters.contains(";;") || parameters.contains("; ;")) { + throw new MultipleDelimitersException(); + } + } + + private void executeChainedCommand (ActivityList activityList, String[] tokenizedParameters) { if (tokenizedParameters[1].length() > 0) { isFinalCommand = false; parameters = tokenizedParameters[0]; executeSingleCommand(activityList); String nextCommand = tokenizedParameters[1].trim(); - callNextCommand(nextCommand, activityList); + try { + callNextCommand(nextCommand, activityList); + } catch (InvalidCommandException e) { + Ui.printDivider("Please chain find or filter commands only"); + } } else { isFinalCommand = true; parameters = tokenizedParameters[0]; @@ -79,7 +101,7 @@ private void executeSingleCommand(ActivityList activityList) { } } - private void callNextCommand(String userInput, ActivityList activityList) { + private void callNextCommand(String userInput, ActivityList activityList) throws InvalidCommandException { String[] tokenizedInputs = userInput.split(" ", 2); String instruction = tokenizedInputs[0]; Command command = null; @@ -89,6 +111,8 @@ private void callNextCommand(String userInput, ActivityList activityList) { command = new FindCommand(tokenizedInputs[1], false, true); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("No keyword was given."); + } catch (MultipleDelimitersException e) { + Ui.printDivider("Please only use one ';' between each command."); } break; case FILTER: @@ -96,10 +120,12 @@ private void callNextCommand(String userInput, ActivityList activityList) { command = new FilterCommand(tokenizedInputs[1], false, true); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("No keyword was given."); + } catch (MultipleDelimitersException e) { + Ui.printDivider("Please only use one ';' between each command."); } break; default: - Ui.printDivider("Please chain find or filter commands only"); + throw new InvalidCommandException(); } try { diff --git a/src/main/java/jikan/exception/InvalidCommandException.java b/src/main/java/jikan/exception/InvalidCommandException.java new file mode 100644 index 000000000..67ebf4ee6 --- /dev/null +++ b/src/main/java/jikan/exception/InvalidCommandException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class InvalidCommandException extends Exception { +} diff --git a/src/main/java/jikan/exception/MultipleDelimitersException.java b/src/main/java/jikan/exception/MultipleDelimitersException.java new file mode 100644 index 000000000..55ef1153c --- /dev/null +++ b/src/main/java/jikan/exception/MultipleDelimitersException.java @@ -0,0 +1,4 @@ +package jikan.exception; + +public class MultipleDelimitersException extends Exception{ +} diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index c5e99de63..d59d450da 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -1,6 +1,7 @@ package jikan.parser; import jikan.exception.ExtraParametersException; +import jikan.exception.MultipleDelimitersException; import jikan.log.Log; import jikan.cleaner.StorageCleaner; import jikan.storage.Storage; @@ -131,6 +132,8 @@ public Command parseUserCommands(Scanner scanner) throws NullPointerException, command = new FindCommand(tokenizedInputs[1]); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("No keyword was given."); + } catch (MultipleDelimitersException e) { + Ui.printDivider("Please only use one ';' between each command."); } break; case FILTER: @@ -138,6 +141,8 @@ public Command parseUserCommands(Scanner scanner) throws NullPointerException, command = new FilterCommand(tokenizedInputs[1]); } catch (ArrayIndexOutOfBoundsException e) { Ui.printDivider("No keyword was given."); + } catch (MultipleDelimitersException e) { + Ui.printDivider("Please only use one ';' between each command."); } break; case EDIT: From ca83cd364373f7e451fc93d154338ac8f7743443 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sat, 11 Apr 2020 12:00:46 +0800 Subject: [PATCH 367/415] fixed style violations --- src/main/java/jikan/command/FilterCommand.java | 6 +++++- src/main/java/jikan/command/FindCommand.java | 14 +++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/jikan/command/FilterCommand.java b/src/main/java/jikan/command/FilterCommand.java index cb897f4ce..32197e723 100644 --- a/src/main/java/jikan/command/FilterCommand.java +++ b/src/main/java/jikan/command/FilterCommand.java @@ -2,7 +2,11 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; -import jikan.exception.*; +import jikan.exception.EmptyNameException; +import jikan.exception.ExtraParametersException; +import jikan.exception.InvalidCommandException; +import jikan.exception.MultipleDelimitersException; +import jikan.exception.EmptyQueryException; import jikan.ui.Ui; import java.util.ArrayList; diff --git a/src/main/java/jikan/command/FindCommand.java b/src/main/java/jikan/command/FindCommand.java index d37146e58..fa20ccd75 100644 --- a/src/main/java/jikan/command/FindCommand.java +++ b/src/main/java/jikan/command/FindCommand.java @@ -2,7 +2,11 @@ import jikan.activity.Activity; import jikan.activity.ActivityList; -import jikan.exception.*; +import jikan.exception.EmptyNameException; +import jikan.exception.ExtraParametersException; +import jikan.exception.InvalidCommandException; +import jikan.exception.MultipleDelimitersException; +import jikan.exception.EmptyQueryException; import jikan.ui.Ui; import static jikan.Jikan.lastShownList; @@ -20,7 +24,7 @@ public class FindCommand extends Command { /** * Constructor to create a new find command. */ - public FindCommand(String parameters) throws MultipleDelimitersException{ + public FindCommand(String parameters) throws MultipleDelimitersException { super(parameters.trim()); isFinalCommand = true; this.parameters = parameters.replaceAll("\\s+", " "); @@ -33,7 +37,7 @@ public FindCommand(String parameters) throws MultipleDelimitersException{ /** * Constructor to create a new find command that has chaining. */ - public FindCommand(String parameters, boolean isFinal, boolean hasChaining) throws MultipleDelimitersException{ + public FindCommand(String parameters, boolean isFinal, boolean hasChaining) throws MultipleDelimitersException { super(parameters.trim()); isFinalCommand = isFinal; isChained = hasChaining; @@ -68,13 +72,13 @@ public void executeCommand(ActivityList activityList) { } } - private void checkForInvalidChaining() throws MultipleDelimitersException{ + private void checkForInvalidChaining() throws MultipleDelimitersException { if (parameters.contains(";;") || parameters.contains("; ;")) { throw new MultipleDelimitersException(); } } - private void executeChainedCommand (ActivityList activityList, String[] tokenizedParameters) { + private void executeChainedCommand(ActivityList activityList, String[] tokenizedParameters) { if (tokenizedParameters[1].length() > 0) { isFinalCommand = false; parameters = tokenizedParameters[0]; From e23d2bee399652606a750aa8ab39022280fd0bc9 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sat, 11 Apr 2020 12:02:02 +0800 Subject: [PATCH 368/415] fixed more style violations --- src/main/java/jikan/activity/ActivityList.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/jikan/activity/ActivityList.java b/src/main/java/jikan/activity/ActivityList.java index ec9c8b618..2623f4c14 100644 --- a/src/main/java/jikan/activity/ActivityList.java +++ b/src/main/java/jikan/activity/ActivityList.java @@ -180,9 +180,9 @@ public void saveActivity() throws InvalidTimeFrameException, NameTooLongExceptio } Parser.continuedIndex = -1; Parser.resetInfo(); - assert(Parser.tags == null); - assert(Parser.activityName == null); - assert(Parser.startTime == null); + assert (Parser.tags == null); + assert (Parser.activityName == null); + assert (Parser.startTime == null); } else { Ui.printDivider(Parser.activityName + " was ended."); @@ -197,9 +197,9 @@ public void saveActivity() throws InvalidTimeFrameException, NameTooLongExceptio } // reset activity info Parser.resetInfo(); - assert(Parser.tags == null); - assert(Parser.activityName == null); - assert(Parser.startTime == null); + assert (Parser.tags == null); + assert (Parser.activityName == null); + assert (Parser.startTime == null); } } From 5a03806dd78f23fcef6f82bbed6fdbb81416e880 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 11 Apr 2020 12:03:51 +0800 Subject: [PATCH 369/415] Change Duke to Jikan in README --- docs/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/README.md b/docs/README.md index f01998f4d..e873beccf 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,4 @@ -# Duke +# Jikan **Jikan** is a CLI time-tracker built in Java that aims to help manage tasks and projects. Users can set tags and goals for their entries, ultimately being able to keep track of what's left to do and maintain an overview of how time was spent. From e3f5f1b20b2ab3b559c6919fbaadfe33b6b2ab09 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sat, 11 Apr 2020 12:07:20 +0800 Subject: [PATCH 370/415] fixed jUnit Style Violations --- src/test/java/jikan/command/FilterCommandTest.java | 3 +++ src/test/java/jikan/command/FindCommandTest.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/test/java/jikan/command/FilterCommandTest.java b/src/test/java/jikan/command/FilterCommandTest.java index f6803d60e..ba0073860 100644 --- a/src/test/java/jikan/command/FilterCommandTest.java +++ b/src/test/java/jikan/command/FilterCommandTest.java @@ -7,6 +7,7 @@ import jikan.exception.ExtraParametersException; import jikan.exception.InvalidTimeFrameException; import jikan.exception.NameTooLongException; +import jikan.exception.MultipleDelimitersException; import jikan.storage.Storage; import org.junit.jupiter.api.Test; @@ -111,6 +112,8 @@ void executeCommand() { } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { System.out.println("Field error."); + } catch (MultipleDelimitersException e) { + System.out.println("Multiple Delimiters"); } } } \ No newline at end of file diff --git a/src/test/java/jikan/command/FindCommandTest.java b/src/test/java/jikan/command/FindCommandTest.java index a282b254d..75bdbefe9 100644 --- a/src/test/java/jikan/command/FindCommandTest.java +++ b/src/test/java/jikan/command/FindCommandTest.java @@ -7,6 +7,7 @@ import jikan.exception.ExtraParametersException; import jikan.exception.InvalidTimeFrameException; import jikan.exception.NameTooLongException; +import jikan.exception.MultipleDelimitersException; import jikan.storage.Storage; import org.junit.jupiter.api.Test; @@ -110,6 +111,8 @@ void executeCommand() { } catch (InvalidTimeFrameException | EmptyNameException | ExtraParametersException | NameTooLongException e) { System.out.println("Field error."); + } catch (MultipleDelimitersException e) { + System.out.println("Multiple delimiters"); } } } \ No newline at end of file From 6369563189f20c1f57fea6b97304f10e78371b14 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 11 Apr 2020 12:11:23 +0800 Subject: [PATCH 371/415] Update list month in command summary --- docs/UserGuide.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 36e98c105..1f7b8d0c8 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -377,13 +377,13 @@ to users who are running this application on systems with limited hardware (smal * Stop an activity: `end` * Continue an activity: `continue ACTIVITY_NAME` * List all activities: `list` - * List today's activities: `list day` or `list daily` + * List today's activities: `list day` or `list daily` or `list today` + * List yesterday's activities: `list yesterday` * List this week's activities: `list week` or `list weekly` * List a specific week's activities by day: `list week DATE` or `list weekly DATE`, where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format * List this month's activities: `list month` or `list monthly` - * List a specific month's activities by day: `list month DATE` or `list monthly DATE`, - where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format + * List a specific month's activities by day: `list month MONTH_NAME` where `MONTH_NAME` must be spelled out in full * List a specific day's activities: `list DATE`, where `DATE` is in either `yyyy-MM-dd` or `dd/MM/yyyy` format * List activities within a time frame: `list DATE1 DATE2`, where both `DATE1` and `DATE2` are in either `yyyy-MM-dd` or `dd/MM/yyyy` format From 8d8a0ea34556b11e9e2e0f5c9723a8cc7d84113b Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sat, 11 Apr 2020 12:52:49 +0800 Subject: [PATCH 372/415] PPP Draft --- docs/team/ananda-lye.md | 57 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 docs/team/ananda-lye.md diff --git a/docs/team/ananda-lye.md b/docs/team/ananda-lye.md new file mode 100644 index 000000000..e77074fe4 --- /dev/null +++ b/docs/team/ananda-lye.md @@ -0,0 +1,57 @@ +# Project Portfolio Page (PPP) +## Project overview +**Jikan** is a CLI time-tracker built in Java that aims to help manage tasks and projects. +Users can set tags and goals for their entries, +ultimately being able to keep track of what's left to do and maintain an overview of how time was spent. + +## Summary of contributions +### Code contributed +[Link to tP Code Dashboard](https://nus-cs2113-ay1920s2.github.io/tp-dashboard/#search=ananda-lye) + +### Enhancements implemented +* Find and Filter Activities + * Developed the `find` and `filter` commands for users to view a sub-list of activities, matching for name and + tag keywords. + * Both commands allow for multiple keywords to be matched with `find` accepting `/` separated keywords and `filter` + accepting space-separated keywords. Activities which match either keyword will be included in the sub-list + * Both commands can be limited to searching within the last shown list of activities by including the `-s` flag. + This is particularly useful when used before graphing functions to omit undesired activities. + * This can also be included as a single-line user input, separating commands by `;` which reduces the + number of user input and printing required to achieve the same results. + +* Last Shown List Implementation + * Proposed and implemented the last shown list which is used in `list`, `find`, `filter` and `graph` commands. + * This proposal sets the direction for how the Jikan software is used, as all analysis done by the user revolves + around this functionality (combining `list` by date range, `find` and `filter` chaining, to allow `graph` to be + clutter-free). + +* Activity Progress and Ui + * Proposed and implemented the progress percentage based user messages, allowing for the progress bars in `end` and + `graph` commands. + + +### Contributions to documentation +* Implemented and de-conflicted the high-level flow of the User Guide, distinguishing from Basic to Advanced features for +improved format standardisation. +* Provided instructions and examples for `find` and `filter` commands and their multiple variations. + +### Contributions to the DG +* Drafted write-ups and diagrams in the design section, mainly the overall architecture diagram and class diagram. +* Drafted the `find` and `filter` sections, including the sequence diagram, design considerations, and proposed features. + +### Contributions to team-based tasks +* Generated ideas with the team on the set of features for the Jikan application. +* Made use of the issue tracker extensively to track enhancement and bugs found. +* Developed jUnit tests for `find`, `filter` and `list` commands. + +### Review/mentoring contributions +* Provided feedback to teammates before and after implementation to ensure that everyone is on the same page. + +### Contributions beyond the project team +* Provided feedback to the developer guide of another team. + * [Reviewing of DG on Week 11](https://github.com/nus-cs2113-AY1920S2/tp/pull/14) + +* Reported bugs in other team's product in PE dry run. + * [PED](https://github.com/ananda-lye/ped/issues) + +### Contributions to the User Guide (Extracts) From f0eface7fdda279c0a3d93eb2ddc185cd23c5070 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 12:59:26 +0800 Subject: [PATCH 373/415] Update ananda-lye.md --- docs/team/ananda-lye.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/team/ananda-lye.md b/docs/team/ananda-lye.md index e77074fe4..3d24098c9 100644 --- a/docs/team/ananda-lye.md +++ b/docs/team/ananda-lye.md @@ -11,13 +11,13 @@ ultimately being able to keep track of what's left to do and maintain an overvie ### Enhancements implemented * Find and Filter Activities * Developed the `find` and `filter` commands for users to view a sub-list of activities, matching for name and - tag keywords. + tag keywords respectively. * Both commands allow for multiple keywords to be matched with `find` accepting `/` separated keywords and `filter` - accepting space-separated keywords. Activities which match either keyword will be included in the sub-list - * Both commands can be limited to searching within the last shown list of activities by including the `-s` flag. - This is particularly useful when used before graphing functions to omit undesired activities. + accepting space-separated keywords. Activities which match either keyword will be included in the sub-list. + * Both commands can be limited to only searching activities in the last shown list by including the `-s` flag. + This is particularly helpful when used before graphing functions to omit undesired activities. * This can also be included as a single-line user input, separating commands by `;` which reduces the - number of user input and printing required to achieve the same results. + number of user inputs and printing calls required to achieve the same results. * Last Shown List Implementation * Proposed and implemented the last shown list which is used in `list`, `find`, `filter` and `graph` commands. From 193899f18059885c0b09d0ec66177e6d38d2e4da Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 13:02:18 +0800 Subject: [PATCH 374/415] Update UserGuide.md --- docs/UserGuide.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index b1ee32f0e..baee01b42 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -208,6 +208,8 @@ If we want to find all CS2106 tutorials, we can first use `filter 2106` to filte * `filter TAGNAME ; find KEYWORD1 ; find KEYWORD2` * `filter -s TAGNAME ; find KEYWORD1 ; find KEYWORD2` +Note: `-s` is only relevant in the first command of the entire input string, as subsequent values are automatically chained. + ## Graphs By using the following commands, users can get a visual representation of the time spent on each activity and their current progress. The 3 types of graphs are : From 46de225b3318dbaae775f3fd7dd71d07f4017fff Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 13:02:28 +0800 Subject: [PATCH 375/415] Update UserGuide.md From e267296b9945ed7e901f820b5a1aa7d536627ea3 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 13:02:30 +0800 Subject: [PATCH 376/415] Update UserGuide.md From 7a010d20ccd4839bf7605cb505c123aaada5c812 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 13:03:29 +0800 Subject: [PATCH 377/415] Update UserGuide.md --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index baee01b42..e67ab3913 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -208,7 +208,7 @@ If we want to find all CS2106 tutorials, we can first use `filter 2106` to filte * `filter TAGNAME ; find KEYWORD1 ; find KEYWORD2` * `filter -s TAGNAME ; find KEYWORD1 ; find KEYWORD2` -Note: `-s` is only relevant in the first command of the entire input string, as subsequent values are automatically chained. +Note: `-s` is only relevant in the first command of the entire input string, as subsequent commands are automatically chained. ## Graphs By using the following commands, users can get a visual representation of the time spent on each activity and their current progress. From 8b68d2c3a791e725375334f79d98549802d47457 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 13:04:02 +0800 Subject: [PATCH 378/415] included UG extracts --- docs/team/ananda-lye.md | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/docs/team/ananda-lye.md b/docs/team/ananda-lye.md index 3d24098c9..8ec8433a3 100644 --- a/docs/team/ananda-lye.md +++ b/docs/team/ananda-lye.md @@ -55,3 +55,42 @@ improved format standardisation. * [PED](https://github.com/ananda-lye/ped/issues) ### Contributions to the User Guide (Extracts) + +### Finding Activities by Name: `find` +**Usage:** Users can request for a sub-list of activities that has names which contain any of the given keywords. If there are more than one keyword, each keyword should be separated with ` / `. + +**Format:** +* `find KEYWORD` +* `find KEYWORD1 / KEYWORD2 / KEYWORD3` + +### Filtering Activities by Tags: `filter` +**Usage:** Users can request for a sub-list of activities that has specific tags. Each tag should be space separated. + +**Format:** +* `filter TAGNAME` +* `filter TAGNAME1 TAGNAME2` + +### Chaining Finds & Filters: `-s` +**Usage:** Users can provide the `find` and `filter` command on the last shown list (also compatible after a `list` +command) by providing the `-s` flag after each `find` or `filter` command. + +**Format:** +* `find -s KEYWORD` +* `filter -s TAGNAME` +* `filter -s TAGNAME1 TAGNAME2` +* `find -s KEYWORD1 / KEYWORD2 / KEYWORD3` + +**Example:** +If we want to find all CS2106 tutorials, we can first use `filter 2106` to filter out all activities tagged `2106`, then use the find command with the flag, `find -s Tutorial` to get a list of all 2106 Tutorials. + +![chain graph activities](./pictures/filter-find_chain.PNG) + +#### Single Input Chaining: `;` +**Usage:** Users can achieve the same outcome as multiple `-s` chaining with a single input. This is done by separating +`find` and `filter` commands with ` ; `. + +**Examples:** +* `filter TAGNAME ; find KEYWORD1 ; find KEYWORD2` +* `filter -s TAGNAME ; find KEYWORD1 ; find KEYWORD2` + +Note: `-s` is only relevant in the first command of the entire input string, as subsequent commands are automatically chained. From d4c0a67d47d0d8173e385c9535adada11a7e26b4 Mon Sep 17 00:00:00 2001 From: ananda_lye Date: Sat, 11 Apr 2020 13:32:12 +0800 Subject: [PATCH 379/415] updated DG --- docs/DeveloperGuide.md | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index cf298f570..9436cb54f 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -466,7 +466,15 @@ The string following the command are the parameters: * If `lastShownList` is not empty, it will print the matching activities. * Else, it will respond to the user that there are no tasks which match the given keyword. -![find seq diagram](https://imgur.com/Icg5rdB.png) +#### 3.7.3 Sequence Diagram +The following illustrates the execution sequence of a general use case. Due to the similarities between `find` and +`filter` sequences, the sequence diagram of `filter` is omitted. + +![image_info](./pictures/Find_Sequence_Diagram.png) +*Sequence Diagram for Find Command* + +![image_info](./pictures/Find_Reference_Frame.PNG) +*Reference frame for populating last shown list* ### 3.9 Filter Feature This feature accepts multiple space-separated keywords to search for activities with tags matching each keyword. @@ -483,9 +491,6 @@ This feature accepts multiple space-separated keywords to search for activities * If `lastShownList` is not empty, it will print the matching activities. * Else, it will respond to the user that there are no tasks which match the given keyword. -#### 3.7.3 Find Sequence Diagram -![image_info](./pictures/Find_Sequence_Diagram.png) -![image_info](./pictures/Find_Reference_Frame.PNG) #### 3.7.4 Additional features (Proposed) Developers may include the feature allowing users users to chain multiple queries and multiple commands From 67f98782239ca7ec30323b440cfba545aaee2957 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sat, 11 Apr 2020 15:00:54 +0800 Subject: [PATCH 380/415] Update DG and PPP --- docs/DeveloperGuide.md | 13 ++++++++----- docs/pictures/EditTagFlowChart.png | Bin 0 -> 21022 bytes docs/team/nigellenl.md | 25 ++++++++++++++++--------- 3 files changed, 24 insertions(+), 14 deletions(-) create mode 100644 docs/pictures/EditTagFlowChart.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index d2cfc2751..2e28f0e13 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -343,27 +343,30 @@ The order of method calls to edit the activity details is as follows if the spec #### 3.5.2 Additional Implementations The current implementation of the edit feature only allows the user to edit the activity name and allocated time. Hence, additional implementations of the edit feature could allow the user to edit other parameters of the activity such as the tags and the start and end dates. -This will require the implementation of more update methods in the ActivityList class to allow for the changes to be updated in the activityList after it has been edited. +This will require the implementation of more update methods in the ActivityList class to allow for the changes to be updated in the activityList after it has been edited. Additionally, there may be more updates required if the tags were to be edited due to the tag goals feature. + +The flowchart below shows the flow of activities if the feature of editing tags were to be implemented. +![image_info](./pictures/EditTagFlowChart.png) #### 3.5.3 Design Considerations ##### Current Design The user is able to edit only the name and allocated time of the activity, which are user input data. -Pros: +**Pros:** * The user is able to correct any mistake made during the recording of the activity. * The user is able to adjust their allocated time for the activity based on their needs. * Ensures that the record of activities is accurate and consistent in order for more efficient analysis of the time spent. -Cons: +**Cons:** * The user is only able to edit 2 parameters of the activity, which may be restrictive for them. ##### Possible Design The user is able to edit any parameters of the activity, including tags, start and end date/time. -Pros: +**Pros:** * The user has more flexibility in modifying the record of activities based on their needs. -Cons: +**Cons:** * By allowing the user to edit the date and time, there may be potential inaccuracies in the record of activities, defeating the purpose of the time tracking program. * By allowing the user to edit the tags, the tag goals command may become more complicated due to the need to keep track of the presence of the tags. diff --git a/docs/pictures/EditTagFlowChart.png b/docs/pictures/EditTagFlowChart.png new file mode 100644 index 0000000000000000000000000000000000000000..84b0e46f99c086834e697a9aa68c8cedd6230c07 GIT binary patch literal 21022 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 KS9<*Pg Date: Sat, 11 Apr 2020 15:59:33 +0800 Subject: [PATCH 381/415] Updated DG --- docs/DeveloperGuide.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 9436cb54f..4c4850816 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -492,12 +492,13 @@ This feature accepts multiple space-separated keywords to search for activities * Else, it will respond to the user that there are no tasks which match the given keyword. -#### 3.7.4 Additional features (Proposed) -Developers may include the feature allowing users users to chain multiple queries and multiple commands -in a single user input. Possibly "pipe-lining" the output of one query into the next query with the pipe symbol `|`. +#### 3.7.4 Additional features +`find` and `filter` command supports the limiting of searches to activities in the last shown list. This +is done in 2 ways: +* The `-s` flag following the command (eg. `find -s keyword`) +* The `;` delimiter for a combination of `find` and `filter` in a single input (eg. `find KEYWORD ; filter TAGNAME`) -**For example:** -* `list week | find -s KEYWORD | filter -s TAGNAME` + ### 3.10 Graph Feature This feature gives the user a visual representation of their activity duration and activity goals. From 23b6abbc3c0e3eb68eeebbc89bee30f6bcc763a6 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sat, 11 Apr 2020 16:28:51 +0800 Subject: [PATCH 382/415] Update UG --- docs/UserGuide.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index e67ab3913..f89f2543a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -407,6 +407,7 @@ to users who are running this application on systems with limited hardware (smal * optional: `filter TAG1 TAG2` for multiple tags * optional: `filter -s TAG_NAME` for more specific filter * Set a goal for tags: `goal TAG_NAME /g DURATION` +* Delete a goal for tags: `goal TAG_NAME /d` * View goals for tags: `goal` * Display graph by tags: `graph tags` * Display graph by duration: `graph INTERVAL` From e6e35648217c54821ccf1fa4500f8d4bdf432c43 Mon Sep 17 00:00:00 2001 From: nigellenl Date: Sat, 11 Apr 2020 18:06:36 +0800 Subject: [PATCH 383/415] Fix input processing for view goal --- src/main/java/jikan/parser/Parser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/jikan/parser/Parser.java b/src/main/java/jikan/parser/Parser.java index d59d450da..e4102bbdd 100644 --- a/src/main/java/jikan/parser/Parser.java +++ b/src/main/java/jikan/parser/Parser.java @@ -181,7 +181,7 @@ public Command parseUserCommands(Scanner scanner) throws NullPointerException, break; case GOAL: try { - if (tokenizedInputs.length == 1) { + if (tokenizedInputs.length == 1 || tokenizedInputs[1].isBlank() || tokenizedInputs[1] == null) { command = new ViewGoalsCommand(null, this.tagStorage); } else { command = new GoalCommand(tokenizedInputs[1], scanner, this.tagStorage); From 23290492418471f53c48b115c569f331c2e91212 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sat, 11 Apr 2020 19:02:38 +0800 Subject: [PATCH 384/415] Set theme jekyll-theme-slate --- docs/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index 3397c9a49..c74188174 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-architect \ No newline at end of file +theme: jekyll-theme-slate \ No newline at end of file From d7e314d4c7106849ad820698446a1c158a329683 Mon Sep 17 00:00:00 2001 From: btricec Date: Sat, 11 Apr 2020 19:16:45 +0800 Subject: [PATCH 385/415] Fix anchors --- docs/DeveloperGuide.md | 30 ++++++++++++++++-------------- docs/UserGuide.md | 37 +++++++++++++++++-------------------- 2 files changed, 33 insertions(+), 34 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 104a648ff..291c5964f 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -7,7 +7,7 @@ - [3.1.1 Current Implementation](#311-current-implementation) - [3.1.2 Additional Implementation](#312-additional-implementation) - [3.1.3 Design Considerations](#313-design-considerations) - - [3.2 Clean Feature](#31-automated-storage-cleanup-feature) + - [3.2 Clean Feature](#32-clean-feature) - [3.2.1 Current Implementation](#311-current-implementation) - [3.2.2 Additional Implementation](#322-additional-implementation) - [3.2.3 Design Considerations](#323-design-considerations) @@ -19,14 +19,17 @@ - [3.5.3 Design Considerations](#353-design-considerations) - [3.6 Continue Feature](#36-continue-feature) - [3.6.1 Current Implementation](#361-current-implementation) - - [3.6.2 Design Considerations](#362-design-considerations) - - [3.6.3 Additional Features](#363-additional-features) + - [3.6.3 Additional Implementations](#362-additional-implementations) + - [3.6.2 Design Considerations](#363-design-considerations) - [3.7 List feature](#37-list-feature) - - [3.7.1 Current implementation](#371-current-implementation-1) - - [3.8 Find Feature](#38-find-feature) - - [3.8.1 Current Implementation](#381-current-implementation) - - [3.9 Filter Feature](#39-filter-feature) + - [3.7.1 Current implementation](#371-current-implementation) + - [3.8 Find and Filter Features](#38-find--filter-features) + - [3.8.1 Design Considerations](#381-design-considerations) + - [3.8.2a Current Implementation for Find](#382a-current-implementation-for-find) + - [3.8.2b Current Implementation for Filter](#382b-current-implementation-for-filter) + - [3.9 Graph Feature](#39-graph-feature) - [3.9.1 Current Implementation](#391-current-implementation) + - [3.9.2 Additional features](#392-additional-features) - [4. Appendix](#4-appendix) - [Product Scope](#product-scope) - [Target user profile](#target-user-profile) @@ -38,7 +41,6 @@ - [Launch and Shutdown](#launch-and-shutdown) - [Listing activities](#listing-activities) - [Continuing activities](#continuing-activities) - - [Editing activities](#editing-activities) - [Graphing activities](#graphing-activities) - [Setting tag goals](#setting-tag-goals) @@ -391,7 +393,11 @@ The continue feature allows the user to continue a previously ended activity. * The elapsed time is added with the previous duration of the activity to get the `newDuration` using the `plus()` method of Duration class. * `updateDuration()` method is called to update the `duration` attribute of the continued activity in the `activityList` as well as the `data.csv` file. -#### 3.6.2 Design Considerations +#### 3.6.2 Additional Implementations +As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, they will be given the option to continue the stated activity. +![decision flowchart](./pictures/continue_flowchart.PNG) + +#### 3.6.3 Design Considerations **Execution:** * Continue by activity name (current implementation) @@ -404,10 +410,6 @@ The continue feature allows the user to continue a previously ended activity. Although the current implementation of the continue feature disallows users to have multiple activities with the same name, we felt that the versatility of this choice outweighed the cons. Firstly because if the activityList got too big, it would be hard for the user to get the index of the task they wanted to continue. Also, the index would constantly be changing when changes are made to the list. -#### 3.6.3 Additional Features -As users can only have activities with unique names, when a user wants to start an activity which already exists in the activityList, they will be given the option to continue the stated activity. -![decision flowchart](./pictures/continue_flowchart.PNG) - ### 3.7 List feature This feature is used to list activities within a range specified by the user. If no parameter is passed to the `list` command, then all the stored activities will be displayed. @@ -468,7 +470,7 @@ The string following the command are the parameters: * Else, it will respond to the user that there are no tasks which match the given keyword. -#### 3.8.2b Current Implementation +#### 3.8.2b Current Implementation for Filter * This feature is called by the user when the `filter` command is entered into the command line. The space separated strings following the command are the keywords to match activity tags with. * The Parser will create a FilterCommand object. * The FindCommand will invoke its own `executeCommand()` method. diff --git a/docs/UserGuide.md b/docs/UserGuide.md index f89f2543a..ae6ee3343 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -16,11 +16,11 @@ - [4.3. Find and Filter Activity](#finding-and-filtering) - [4.3.1. Find Activity by Name](#finding-activities-by-name-find) - [4.3.2. Filter Activity by Tag](#filtering-activities-by-tags-filter) - - [4.3.3. Chaining Lists, Find and Filter](#chaining-lists-finds--filters--s) + - [4.3.3. Chaining Lists, Find and Filter](#chaining-finds--filters--s) - [4.4. Graphs](#graphs) - [4.4.1. Activity Time Graph](#activity-time-graph-graph-activities) - [4.4.2. Tags Time Graph](#tags-time-graph-graph-tags) - - [4.4.3. Activity Targets Graph](#activity-targets-graph-graph-allocations) + - [4.4.3. Activity Allocation Graph](#activity-allocation-graph-graph-allocations) - [4.4.4. Chaining List, Find, Filter with Graph](#chaining-list-find-and-filter-with-graph-command) - [4.5. Tag Goals](#tag-goals) - [4.5.1. Set Goal](#set-goal-goal-tag_name-g-duration) @@ -49,10 +49,9 @@ This user guide will show you how to use the program effectively. ## Quick Start 1. Ensure that you have Java 11 or above installed. -1. Download the jar file of the latest version of `Jikan` from [here](https://github.com/AY1920S2-CS2113-T15-1/tp/releases). -3. Download the data.csv file. -4. Create an empty folder and put the Jikan.jar file inside. -6. Open command prompt and navigate to the folder. Run the jar file using `java -jar jikan.jar` +2. Download the jar file of the latest version of `Jikan` from [here](https://github.com/AY1920S2-CS2113-T15-1/tp/releases). +3. Create an empty folder and put the Jikan.jar file inside. +4. Open command prompt and navigate to the folder. Run the jar file using `java -jar jikan.jar` Features ======= @@ -148,13 +147,14 @@ This is just a quick overview of what Jikan can do for you. For more details on * `TIME_PERIOD` can either be a specific date or over a range. **Example:** -* `list` List all activities. -* `list month april` Lists all activities in April. -* `list week` or `list weekly` List all activities in the current week. +* `list` lists all activities. +* `list month april` lists all activities in April. +* `list week` or `list weekly` lists all activities in the current week. * `list week 01/01/2020` lists all activities in the week of 01/01/2020. -* `list day` or `list daily` List all activities in the current day. -* `list 01/01/2020` or `list 2020-01-01` List all activities on 1 Jan 2020. -* `list 01/01/2020 20/02/2020` List all activities than fall within 1 Jan 2020 and 20 Feb 2020. +* `list day` or `list daily` lists all activities in the current day. +* `list yesterday` lists all activities completed the day before. +* `list 01/01/2020` or `list 2020-01-01` lists all activities completed on 1 Jan 2020. +* `list 01/01/2020 20/02/2020` lists all activities than fall within 1 Jan 2020 and 20 Feb 2020. ### Editing an activity: `edit` **Usage:** Edits the name or allocated time of an activity in the activity list. @@ -225,8 +225,7 @@ The parameter `SCALE` refers to the number of minutes represented by each point Note: As the units of `SCALE` is minutes, if your activity is less than a minute, graph function will not show anything. -**Format:** -`graph activities SCALE` +**Format:** `graph activities SCALE` **Example:** `graph activities 10` @@ -246,8 +245,7 @@ Adding up the durations for each tag, we get 10 mins for `tag1` and 5 mins for ` As tags can be used to group activities of a similar nature together (i.e. same module), this feature can be used to easily see what type of activity took up the most time. -**Format:** -`graph tags SCALE` +**Format:** `graph tags SCALE` **Example:** `graph tags 1` @@ -267,8 +265,7 @@ For example, if we `graph allocations` for the activity list above, we will get The percentage shown in the graph represents the activity's progress relative to their allocated time. (`activity 4` have a duration of 2 seconds while its allocated time was 5 seconds, 2/5 * 100% = 40%. Thus the progress of `activity 4` is 40% as shown in the graph) -**Format:** -`graph allocations` +**Format:** `graph allocations` ### Chaining `list`, `find` and `filter` with `graph` command: Using `list`, `find` and `filter` commands you can sieve out the information you wish to be graphed. @@ -409,8 +406,8 @@ to users who are running this application on systems with limited hardware (smal * Set a goal for tags: `goal TAG_NAME /g DURATION` * Delete a goal for tags: `goal TAG_NAME /d` * View goals for tags: `goal` -* Display graph by tags: `graph tags` -* Display graph by duration: `graph INTERVAL` +* Display graph by tags: `graph tags INTERVAL` +* Display graph by duration: `graph activities INTERVAL` * Display graph by targets: `graph targets` * Clean data files: `clean [command]` * Activate auto data cleaner: `clean on` From 9e57f9e194433bf47b524c1196894f1465db6fdb Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 19:17:05 +0800 Subject: [PATCH 386/415] Update ananda-lye.md --- docs/team/ananda-lye.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/team/ananda-lye.md b/docs/team/ananda-lye.md index 8ec8433a3..59b403649 100644 --- a/docs/team/ananda-lye.md +++ b/docs/team/ananda-lye.md @@ -54,7 +54,7 @@ improved format standardisation. * Reported bugs in other team's product in PE dry run. * [PED](https://github.com/ananda-lye/ped/issues) -### Contributions to the User Guide (Extracts) +## Contributions to the User Guide (Extracts) ### Finding Activities by Name: `find` **Usage:** Users can request for a sub-list of activities that has names which contain any of the given keywords. If there are more than one keyword, each keyword should be separated with ` / `. From 15969a9713f009a6bb67b6d55d9c4d6e15365396 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sat, 11 Apr 2020 19:18:37 +0800 Subject: [PATCH 387/415] Set theme jekyll-theme-cayman --- docs/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index c74188174..c4192631f 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-slate \ No newline at end of file +theme: jekyll-theme-cayman \ No newline at end of file From 92d3be13f983dcbdf10a169b9ff6fb2b8bc9677d Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 19:26:08 +0800 Subject: [PATCH 388/415] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 291c5964f..c53c4b17e 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -79,16 +79,14 @@ by the executing `Commands`. even after the program terminates) state of all activities. It retrieves this permanent state and populates the `Activity List` at the start of each session. ![image_info](./pictures/Architecture_Diagram.png) -_Fig 2.1. Architecture diagram of the Jikan program_ + ### 2.2 Class Diagram The high-level class diagram describes the structure of the components ![image_info](./pictures/Simplified_Class_Diagram.png) -_Fig 2.2. Class diagram of the Jikan program_ ![image_info](./pictures/Commands.png) -_Fig 2.3. Commands of Jikan (private methods omitted)_ All the commands inherit from the abstract `Command` class. Each command has a protected `parameters` attribute from it's Parent class `command` and an overridden method `executeCommand` which is called in `main` to execute the relevant command. @@ -488,11 +486,11 @@ The following illustrates the execution sequence of a general use case. Note: Due to the sequence similarities between `find` and `filter`, the sequence diagram for `filter` is omitted. -![image_info](./pictures/Find_Sequence_Diagram.png) *Sequence Diagram for Find Command* +![image_info](./pictures/Find_Sequence_Diagram.png) +*Reference Frame for Populating List* ![image_info](./pictures/Find_Reference_Frame.PNG) -*Reference frame for populating last shown list* #### 3.8.4 Additional features From e2337fa20bc060dac8ccaf18a59251119f33d8a3 Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 19:27:15 +0800 Subject: [PATCH 389/415] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index c53c4b17e..fc1faf476 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -486,10 +486,8 @@ The following illustrates the execution sequence of a general use case. Note: Due to the sequence similarities between `find` and `filter`, the sequence diagram for `filter` is omitted. -*Sequence Diagram for Find Command* ![image_info](./pictures/Find_Sequence_Diagram.png) -*Reference Frame for Populating List* ![image_info](./pictures/Find_Reference_Frame.PNG) From 6c6c666c3cefd23bf1ed654a338f69d716f0bd7c Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sat, 11 Apr 2020 19:28:23 +0800 Subject: [PATCH 390/415] slight formatting issue in PPP --- docs/team/siuhian.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/team/siuhian.md b/docs/team/siuhian.md index 0a307ff3b..0f5b66a43 100644 --- a/docs/team/siuhian.md +++ b/docs/team/siuhian.md @@ -1,8 +1,7 @@ # Project Portfolio Page (PPP) ## Project overview **Jikan** is a CLI time-tracker built in Java that aims to help manage tasks and projects. -Users can set tags and goals for their entries, -ultimately being able to keep track of what's left to do and maintain an overview of how time was spent. +Users can set tags and goals for their entries, ultimately being able to keep track of what's left to do and maintain an overview of how time was spent. ## Summary of contributions ### Code contributed From b584cc172186588d6e7f2b14a780e5132e88d3ab Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 19:29:00 +0800 Subject: [PATCH 391/415] Update DeveloperGuide.md --- docs/DeveloperGuide.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index fc1faf476..c6381b6ca 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -498,7 +498,6 @@ is done in 2 ways: * The `;` delimiter for a combination of `find` and `filter` in a single input (eg. `find KEYWORD ; filter TAGNAME`) ![Chaining_Activity_Diagram](./pictures/Chaining_Activity_Diagram.png) - *Activity Diagram for Additional Features* ### 3.9 Graph Feature This feature gives the user a visual representation of their activity duration and activity goals. From 4ba224b20a5b34f7e75e664b7653b16e2a71fcf7 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sat, 11 Apr 2020 19:32:44 +0800 Subject: [PATCH 392/415] Fix PPP --- docs/team/siuhian.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/team/siuhian.md b/docs/team/siuhian.md index 0f5b66a43..16c16c601 100644 --- a/docs/team/siuhian.md +++ b/docs/team/siuhian.md @@ -40,7 +40,7 @@ Users can set tags and goals for their entries, ultimately being able to keep tr * Edited the command summary and usage section to ensure consistency with the features under my implementation. ### Contributions to the DG -* Explained the implementation of the start feature (Under Section 3.1) using a mixture of sequence diagrams with class diagrams +* Explained the implementation of the start feature (Under Section 3.1) using a mixture of sequence diagrams with class diagrams. * Explained the implementation of the clean feature (Under Section 3.2) using a mixture of sequence diagram with class diagrams. ### Contributions to team-based tasks From d84f3a8c6f86ba8ee5dc914378c74f201297471e Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 19:33:12 +0800 Subject: [PATCH 393/415] Update ananda-lye.md --- docs/team/ananda-lye.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/team/ananda-lye.md b/docs/team/ananda-lye.md index 59b403649..cf5c45c51 100644 --- a/docs/team/ananda-lye.md +++ b/docs/team/ananda-lye.md @@ -83,8 +83,6 @@ command) by providing the `-s` flag after each `find` or `filter` command. **Example:** If we want to find all CS2106 tutorials, we can first use `filter 2106` to filter out all activities tagged `2106`, then use the find command with the flag, `find -s Tutorial` to get a list of all 2106 Tutorials. -![chain graph activities](./pictures/filter-find_chain.PNG) - #### Single Input Chaining: `;` **Usage:** Users can achieve the same outcome as multiple `-s` chaining with a single input. This is done by separating `find` and `filter` commands with ` ; `. From 8df2edefe73cb6c64ac3a689d34292a9a279d30f Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sat, 11 Apr 2020 19:36:52 +0800 Subject: [PATCH 394/415] Fix some format issues --- docs/team/siuhian.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/team/siuhian.md b/docs/team/siuhian.md index 16c16c601..00f94529f 100644 --- a/docs/team/siuhian.md +++ b/docs/team/siuhian.md @@ -17,7 +17,7 @@ Users can set tags and goals for their entries, ultimately being able to keep tr * Added some more test cases to the Junit for StartCommand. * User interface - * Sourced and implemented the existing Jikan logo that greets the user upon execution + * Sourced and implemented the existing Jikan logo that greets the user upon execution. * Created a standard template to print lines to stdout. This feature is used to print error, acknowledgement and reply messages from Jikan to the user. * Implemented the `bye` command which makes use of Ui to exit from the application. @@ -55,7 +55,7 @@ Users can set tags and goals for their entries, ultimately being able to keep tr ### Review/mentoring contributions * Provided feedback to peers on how certain features can be improved (e.g progress message for activities, - store tag goals in separate data file so as to not overload the main data file for activities) + store tag goals in separate data file so as to not overload the main data file for activities). ### Contributions beyond the project team * Provided feedback to the developer guide of another team. From a72848681ab65648765c96fdc1ff0f7d8df4321f Mon Sep 17 00:00:00 2001 From: ananda-lye Date: Sat, 11 Apr 2020 19:37:21 +0800 Subject: [PATCH 395/415] Update ananda-lye.md --- docs/team/ananda-lye.md | 72 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/docs/team/ananda-lye.md b/docs/team/ananda-lye.md index cf5c45c51..446b5f064 100644 --- a/docs/team/ananda-lye.md +++ b/docs/team/ananda-lye.md @@ -92,3 +92,75 @@ If we want to find all CS2106 tutorials, we can first use `filter 2106` to filte * `filter -s TAGNAME ; find KEYWORD1 ; find KEYWORD2` Note: `-s` is only relevant in the first command of the entire input string, as subsequent commands are automatically chained. + +## Contributions to the Developer Guide (Extracts) +## 2. Design +The section provides a high-level explanation of how the Jikan software is designed. + +### 2.1 High-Level Architecture +The users interact with the Jikan software which modifies the local storage data file. + +Within the Jikan software, there are 5 main components: +* **Parser Component** - Parses the user inputs and calls the relevant `Command` object to execute the desired +command. +* **Ui Component** - Prints to the user the output of the desired `Commands`. +* **Commands Component** - Contains all the `Commands` to be called by the `Parser` based on user inputs. +* **Activities Component** - Maintains the non-permanent state of all `Activities` in the `Activity List` to be accessed +by the executing `Commands`. +* **Storage Component** - Interacts with and modifies the local storage file, which contains the permanent (lasting +even after the program terminates) state of all activities. It retrieves this permanent state and populates the `Activity List` at the start of each session. + +### 3.8 Find & Filter Features + +#### Find Feature +This command accepts keyword(s) and searches either the entire activity list or the last shown list for activities with +names containing each keyword. + +#### Filter Feature +This feature accepts space-separated keyword(s) to search either the entire list or the last shown list +for activities with tags matching each keyword. The keywords should be an exact-match with the tag names. + + +#### 3.8.1 Design Considerations +As the `find` and `filter` commands are important for the user to analyse and eventually graph time-spent on each +activity. The user should be allowed to query for all useful combinations of activities in the activity list. +This entails: +* The user should be allowed to match for multiple keywords at once. +* The user should be allowed to exclude certain activities by limiting his search to a previously shown list as + opposed to the entire activity list. + (chaining `list`, `find`, and `filter` commands). + + +#### 3.8.2a Current Implementation for Find +* This feature is called by the user when the `find` command is entered into the command line. +The string following the command are the parameters: + * `-s` flag indicates that the searching should be limited to activities previously shown to the user. + * The remaining parameters are a string of keywords separated by ` / `. +* The Parser will create a FindCommand object. +* The FindCommand will invoke its own `executeCommand()` method. + * The Parser's `lastShownList` will be cleared. + * Then it will loop through `activityList` to find activities with names that contain the keyword. + * If one is found, it will be added to `lastShownList`. + * `printResults()` of the Ui will be called: + * If `lastShownList` is not empty, it will print the matching activities. + * Else, it will respond to the user that there are no tasks which match the given keyword. + + +#### 3.8.2b Current Implementation for Filter +* This feature is called by the user when the `filter` command is entered into the command line. The space separated strings following the command are the keywords to match activity tags with. +* The Parser will create a FilterCommand object. +* The FindCommand will invoke its own `executeCommand()` method. +* The Parser's `lastShownList` will be cleared. +* For each keyword: + * Then it will loop through `activityList` to find activities with tags that contain the keyword. + * If one is found, it will be added to `lastShownList`. + * `printResults()` method of the Ui will be called + * If `lastShownList` is not empty, it will print the matching activities. + * Else, it will respond to the user that there are no tasks which match the given keyword. + +#### 3.8.4 Additional features +`find` and `filter` command supports the limiting of searches to activities in the last shown list. This +is done in 2 ways: +* The `-s` flag following the command (eg. `find -s keyword`) +* The `;` delimiter for a combination of `find` and `filter` in a single input (eg. `find KEYWORD ; filter TAGNAME`) + From 3816162a583cd3a59ccdb05b00ab8ee5d05e4be5 Mon Sep 17 00:00:00 2001 From: siuhian <42374522+siuhian@users.noreply.github.com> Date: Sat, 11 Apr 2020 19:51:16 +0800 Subject: [PATCH 396/415] Change diagram for DG --- docs/DeveloperGuide.md | 2 +- docs/pictures/ACSD.png | Bin 86907 -> 71245 bytes docs/pictures/checkTimev2.png | Bin 57597 -> 51171 bytes docs/pictures/checkactivityv2.png | Bin 45894 -> 37963 bytes docs/pictures/continueActivity.jpg | Bin 0 -> 122460 bytes docs/pictures/continueActivity.png | Bin 26649 -> 0 bytes docs/pictures/setStatusSD.png | Bin 68277 -> 53014 bytes 7 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 docs/pictures/continueActivity.jpg delete mode 100644 docs/pictures/continueActivity.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 104a648ff..d9621da3a 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -144,7 +144,7 @@ using the addActivity() method. **continueActivity** -![continueActivity](./pictures/continueActivity.png) +![continueActivity](./pictures/continueActivity.jpg) The diagram above shows how the StartCommand#continueActivity function works. This function is used when the current activity to be started already exists in the activity list. Thus, this function will check with the user whether to continue on that activity diff --git a/docs/pictures/ACSD.png b/docs/pictures/ACSD.png index 106fed9cde41b4a314608abebf641f995eaee2d4..f36ed5024830a323e637e9bfcdbb4f4f921716ac 100644 GIT binary patch literal 71245 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 diff --git a/docs/pictures/checkTimev2.png b/docs/pictures/checkTimev2.png index b9c421ff2959365cfcef501853767728672f37a9..591218645f1624274652ae5f3714514b5aad7e1b 100644 GIT binary patch literal 51171 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