From 926727ce5eac2a408d039671fa6fa6fdb528b0ce Mon Sep 17 00:00:00 2001 From: Tan Jun Hong <13333714+TanJunHong@users.noreply.github.com> Date: Thu, 1 Oct 2020 16:18:26 +0800 Subject: [PATCH 001/148] Set theme jekyll-theme-midnight --- 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 0000000000..18854876c6 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-midnight \ No newline at end of file From 6ec09fa6c1b4a9f0e95969c07a0a5fd50e0b438b Mon Sep 17 00:00:00 2001 From: randynyl <56857427+randynyl@users.noreply.github.com> Date: Thu, 1 Oct 2020 16:58:02 +0800 Subject: [PATCH 002/148] Edit AboutUs --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..c77e1e93d8 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) | Randy Ng | [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 38c2c160476e7a27e62c5621038082af3f4a08df Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Thu, 1 Oct 2020 16:58:11 +0800 Subject: [PATCH 003/148] Change John Doe to my name --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..532e85c1f0 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) | Tan Jun Hong | [Github](https://github.com/TanJunHong) | [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 0b8d195988efcb29c632d80fa3ef78d2b43931f5 Mon Sep 17 00:00:00 2001 From: randynyl <56857427+randynyl@users.noreply.github.com> Date: Thu, 1 Oct 2020 16:59:45 +0800 Subject: [PATCH 004/148] Edit AboutUsUs --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index c77e1e93d8..34433a18fd 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) | Randy Ng | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Randy Ng | [Github](https://github.com/randynyl/) | [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 773d6f43571c3160e5ccc219c076d037e228ae5d Mon Sep 17 00:00:00 2001 From: kiathwe97 Date: Thu, 1 Oct 2020 17:01:59 +0800 Subject: [PATCH 005/148] kiathwe-AboutUs --- docs/AboutUs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..51a612da64 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,10 @@ # About us + 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) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Tan Kiat Hwe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From 9a6d00949d0df640e16ff2c8c024ccd118556e16 Mon Sep 17 00:00:00 2001 From: ychong032 Date: Thu, 1 Oct 2020 21:36:38 +0800 Subject: [PATCH 006/148] Add Yow Lim to AboutUs --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 55ee51b20d..8ad64d7724 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) | Tan Jun Hong | [Github](https://github.com/TanJunHong) | [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) | Randy Ng | [Github](https://github.com/randynyl/) | [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) | Chong Yow Lim | [Github](https://github.com/ychong032) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Tan Kiat Hwe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From f40639cf87c838e17f31f560f6d8a98e4ad7e4e2 Mon Sep 17 00:00:00 2001 From: GoldenCorgi <42860714+GoldenCorgi@users.noreply.github.com> Date: Sat, 3 Oct 2020 23:53:54 +0800 Subject: [PATCH 007/148] Add Liew You Sheng to AboutUs --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 8ad64d7724..4dadf85a6f 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -4,7 +4,7 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | Tan Jun Hong | [Github](https://github.com/TanJunHong) | [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) | Liew You Sheng | [Github](https://github.com/GoldenCorgi) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Randy Ng | [Github](https://github.com/randynyl/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Chong Yow Lim | [Github](https://github.com/ychong032) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Tan Kiat Hwe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From 45042917888bf61b0a1c3fb35e60302586fb0e7f Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Mon, 5 Oct 2020 01:01:17 +0800 Subject: [PATCH 008/148] Rename project and testing files to Rex --- README.md | 28 ++++++++++--------- build.gradle | 4 +-- docs/README.md | 2 +- docs/UserGuide.md | 2 +- src/main/java/seedu/duke/Duke.java | 21 -------------- src/main/java/seedu/rex/Rex.java | 24 ++++++++++++++++ .../{duke/DukeTest.java => rex/RexTest.java} | 4 +-- text-ui-test/EXPECTED.TXT | 14 ++++++---- 8 files changed, 53 insertions(+), 46 deletions(-) delete mode 100644 src/main/java/seedu/duke/Duke.java create mode 100644 src/main/java/seedu/rex/Rex.java rename src/test/java/seedu/{duke/DukeTest.java => rex/RexTest.java} (82%) diff --git a/README.md b/README.md index 698b938529..e97e027b86 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Duke project template +# Hospitalsaurus ReX project template -This is a project template for a greenfield Java project. It's named after the Java mascot _Duke_. Given below are instructions on how to use it. +This is a project template for a greenfield Java project. Given below are instructions on how to use it. ## Setting up in Intellij @@ -8,20 +8,22 @@ Prerequisites: JDK 11 (use the exact version), update Intellij to the most recen 1. **Configure Intellij for JDK 11**, as described [here](https://se-education.org/guides/tutorials/intellijJdk.html). 1. **Import the project _as a Gradle project_**, as described [here](https://se-education.org/guides/tutorials/intellijImportGradleProject.html). -1. **Verify the set up**: After the importing is complete, locate the `src/main/java/seedu/duke/Duke.java` file, right-click it, and choose `Run Duke.main()`. If the setup is correct, you should see something like the below: +1. **Verify the set up**: After the importing is complete, locate the `src/main/java/seedu/rex/Rex.java` file, right-click it, and choose `Run Rex.main()`. If the setup is correct, you should see something like the below: ``` - > Task :compileJava + > Task :compileJava UP-TO-DATE > Task :processResources NO-SOURCE - > Task :classes + > Task :classes UP-TO-DATE - > Task :Duke.main() + > Task :Rex.main() Hello from - ____ _ - | _ \ _ _| | _____ - | | | | | | | |/ / _ \ - | |_| | |_| | < __/ - |____/ \__,_|_|\_\___| - + _ _ _ _ _ _____ __ __ + | | | | (_| | | | | __ \ \ \ / / + | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \ V / + | __ |/ _ \/ __| '_ \| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \ > < + | | | | (_) \__ | |_) | | || (_| | \__ | (_| | |_| | | | |_| \__ \ | | \ | __// . \ + |_| |_|\___/|___| .__/|_|\__\__,_|_|___/\__,_|\__,_|_| \__,_|___/ |_| \_\___/_/ \_\ + | | + |_| What is your name? ``` Type some word and press enter to let the execution proceed to the end. @@ -39,7 +41,7 @@ Prerequisites: JDK 11 (use the exact version), update Intellij to the most recen ### JUnit tests -* A skeleton JUnit test (`src/test/java/seedu/duke/DukeTest.java`) is provided with this project template. +* A skeleton JUnit test (`src/test/java/seedu/rex/RexTest.java`) is provided with this project template. * If you are new to JUnit, refer to the [JUnit Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/junit.html). ## Checkstyle diff --git a/build.gradle b/build.gradle index b0c5528fb5..c45338f280 100644 --- a/build.gradle +++ b/build.gradle @@ -29,11 +29,11 @@ test { } application { - mainClassName = "seedu.duke.Duke" + mainClassName = "seedu.rex.Rex" } shadowJar { - archiveBaseName = "duke" + archiveBaseName = "rex" archiveClassifier = null } diff --git a/docs/README.md b/docs/README.md index bbcc99c1e7..a15abec150 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,4 +1,4 @@ -# Duke +# Hospitalsaurus ReX {Give product intro here} diff --git a/docs/UserGuide.md b/docs/UserGuide.md index abd9fbe891..34b1e0432c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -9,7 +9,7 @@ {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. Down the latest version of `Hospitalsaurus ReX` from [here](https://github.com/AY2021S1-CS2113-T16-4/tp). ## Features diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java deleted file mode 100644 index 5c74e68d59..0000000000 --- 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()); - } -} diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java new file mode 100644 index 0000000000..62d4fad55f --- /dev/null +++ b/src/main/java/seedu/rex/Rex.java @@ -0,0 +1,24 @@ +package seedu.rex; + +import java.util.Scanner; + +public class Rex { + /** + * Main entry-point for the java.rex.Rex application. + */ + public static void main(String[] args) { + String logo = " _ _ _ _ _ _____ __ __\n" + + " | | | | (_| | | | | __ \\ \\ \\ / /\n" + + " | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \\ V / \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()); + } +} diff --git a/src/test/java/seedu/duke/DukeTest.java b/src/test/java/seedu/rex/RexTest.java similarity index 82% rename from src/test/java/seedu/duke/DukeTest.java rename to src/test/java/seedu/rex/RexTest.java index 2dda5fd651..26836177c7 100644 --- a/src/test/java/seedu/duke/DukeTest.java +++ b/src/test/java/seedu/rex/RexTest.java @@ -1,10 +1,10 @@ -package seedu.duke; +package seedu.rex; import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.Test; -class DukeTest { +class RexTest { @Test public void sampleTest() { assertTrue(true); diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 892cb6cae7..66c8f3e10e 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,9 +1,11 @@ Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - + _ _ _ _ _ _____ __ __ + | | | | (_| | | | | __ \ \ \ / / + | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \ V / + | __ |/ _ \/ __| '_ \| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \ > < + | | | | (_) \__ | |_) | | || (_| | \__ | (_| | |_| | | | |_| \__ \ | | \ | __// . \ + |_| |_|\___/|___| .__/|_|\__\__,_|_|___/\__,_|\__,_|_| \__,_|___/ |_| \_\___/_/ \_\ + | | + |_| What is your name? Hello James Gosling From c211ee659598d337d14a9006ff8fae06dcbc9ee6 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Mon, 5 Oct 2020 01:10:50 +0800 Subject: [PATCH 009/148] Fix checkstyle errors --- src/main/java/seedu/rex/Rex.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 62d4fad55f..3dcc86a285 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -7,14 +7,14 @@ public class Rex { * Main entry-point for the java.rex.Rex application. */ public static void main(String[] args) { - String logo = " _ _ _ _ _ _____ __ __\n" + - " | | | | (_| | | | | __ \\ \\ \\ / /\n" + - " | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \\ V / \n" + - " | __ |/ _ \\/ __| '_ \\| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \\ > < \n" + - " | | | | (_) \\__ | |_) | | || (_| | \\__ | (_| | |_| | | | |_| \\__ \\ | | \\ | __// . \\ \n" + - " |_| |_|\\___/|___| .__/|_|\\__\\__,_|_|___/\\__,_|\\__,_|_| \\__,_|___/ |_| \\_\\___/_/ \\_\\\n" + - " | | \n" + - " |_| "; + String logo = " _ _ _ _ _ _____ __ __\n" + + " | | | | (_| | | | | __ \\ \\ \\ / /\n" + + " | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \\ V / \n" + + " | __ |/ _ \\/ __| '_ \\| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \\ > < \n" + + " | | | | (_) \\__ | |_) | | || (_| | \\__ | (_| | |_| | | | |_| \\__ \\ | | \\ | __// . \\ \n" + + " |_| |_|\\___/|___| .__/|_|\\__\\__,_|_|___/\\__,_|\\__,_|_| \\__,_|___/ |_| \\_\\___/_/ \\_\\\n" + + " | | \n" + + " |_| "; System.out.println("Hello from\n" + logo); System.out.println("What is your name?"); From 16277ceb6be93c3dfe37ee55522f8cdd9b23749f Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 6 Oct 2020 14:05:03 +0800 Subject: [PATCH 010/148] Add necessary classes and packages --- src/main/java/seedu/rex/commands/Command.java | 43 ++++++++++ .../java/seedu/rex/commands/ExitCommand.java | 27 ++++++ src/main/java/seedu/rex/data/PatientList.java | 56 +++++++++++++ .../rex/data/exception/RexException.java | 18 ++++ .../java/seedu/rex/data/patient/Patient.java | 4 + src/main/java/seedu/rex/parser/Parser.java | 26 ++++++ src/main/java/seedu/rex/storage/Storage.java | 64 ++++++++++++++ src/main/java/seedu/rex/ui/Ui.java | 83 +++++++++++++++++++ 8 files changed, 321 insertions(+) create mode 100644 src/main/java/seedu/rex/commands/Command.java create mode 100644 src/main/java/seedu/rex/commands/ExitCommand.java create mode 100644 src/main/java/seedu/rex/data/PatientList.java create mode 100644 src/main/java/seedu/rex/data/exception/RexException.java create mode 100644 src/main/java/seedu/rex/data/patient/Patient.java create mode 100644 src/main/java/seedu/rex/parser/Parser.java create mode 100644 src/main/java/seedu/rex/storage/Storage.java create mode 100644 src/main/java/seedu/rex/ui/Ui.java diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java new file mode 100644 index 0000000000..e41941a30f --- /dev/null +++ b/src/main/java/seedu/rex/commands/Command.java @@ -0,0 +1,43 @@ +package seedu.rex.commands; + +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +/** + * Parent Command class. + */ +public abstract class Command { + + public static final String MESSAGE = Ui.LOGO + System.lineSeparator() + "How may i assist you?"; + public static final String COMMAND_ERROR = "I'm sorry, but I don't know what that means :-("; + + boolean isExit; + + /** + * Initializes command to execute and set exit status to false. + */ + public Command() { + isExit = false; + } + + /** + * Executes command. + * + * @param patients PatientList object. + * @param ui Ui object. + * @param storage Storage object. + * @throws RexException If there is issue executing command. + */ + public abstract void execute(PatientList patients, Ui ui, Storage storage) throws RexException; + + /** + * Returns Rex's exit status. + * + * @return Exit status. + */ + public boolean isExit() { + return isExit; + } +} diff --git a/src/main/java/seedu/rex/commands/ExitCommand.java b/src/main/java/seedu/rex/commands/ExitCommand.java new file mode 100644 index 0000000000..dc1f3ebac3 --- /dev/null +++ b/src/main/java/seedu/rex/commands/ExitCommand.java @@ -0,0 +1,27 @@ +package seedu.rex.commands; + +import seedu.rex.data.PatientList; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +/** + * Exits program. + */ +public class ExitCommand extends Command { + + public static final String COMMAND_WORD = "bye"; + public static final String MESSAGE = "Bye. Hope to see you again soon!"; + + /** + * Says goodbye to user and exits Rex. + * + * @param patients PatientList object. + * @param ui Ui object. + * @param storage Storage object. + */ + @Override + public void execute(PatientList patients, Ui ui, Storage storage) { + isExit = true; + ui.showExit(); + } +} diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java new file mode 100644 index 0000000000..9533074cd9 --- /dev/null +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -0,0 +1,56 @@ +package seedu.rex.data; + +import seedu.rex.data.patient.Patient; + +import java.util.ArrayList; + +public class PatientList { + + private static final String PATIENT_NUMBER_ERROR = "Invalid patient number."; + + private final ArrayList patients; + + /** + * Initializes patients ArrayList. + */ + public PatientList() { + patients = new ArrayList<>(); + } + + /** + * Initializes patients ArrayList using parameter. + * + * @param patients Patients list to use. + */ + public PatientList(ArrayList patients) { + this.patients = patients; + } + + /** + * Returns size of patients. + * + * @return Length of patients. + */ + public int getSize() { + return patients.size(); + } + + /** + * Returns patient using index. + * + * @param index Index of patient. + * @return patient at that index. + */ + public Patient getPatientUsingIndex(int index) { + return patients.get(index); + } + + /** + * Adds patient to patients ArrayList. + * + * @param patient patient to add. + */ + public void addPatient(Patient patient) { + patients.add(patient); + } +} diff --git a/src/main/java/seedu/rex/data/exception/RexException.java b/src/main/java/seedu/rex/data/exception/RexException.java new file mode 100644 index 0000000000..aecd982316 --- /dev/null +++ b/src/main/java/seedu/rex/data/exception/RexException.java @@ -0,0 +1,18 @@ +package seedu.rex.data.exception; + +/** + * Throws exceptions relating to Rex. + */ +public class RexException extends Exception { + + private static final String OOPS = "☹ OOPS!!! "; + + /** + * Initializes message to throw. + * + * @param message Exception message to show. + */ + public RexException(String message) { + super(OOPS + message); + } +} diff --git a/src/main/java/seedu/rex/data/patient/Patient.java b/src/main/java/seedu/rex/data/patient/Patient.java new file mode 100644 index 0000000000..2837b4d844 --- /dev/null +++ b/src/main/java/seedu/rex/data/patient/Patient.java @@ -0,0 +1,4 @@ +package seedu.rex.data.patient; + +public class Patient { +} diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java new file mode 100644 index 0000000000..445b41e1e7 --- /dev/null +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -0,0 +1,26 @@ +package seedu.rex.parser; + +import seedu.rex.commands.Command; +import seedu.rex.commands.ExitCommand; +import seedu.rex.data.patient.Patient; +import seedu.rex.data.exception.RexException; + +public class Parser { + public static Patient readPatient(String line) { + //to read patients from file + return null; + } + + public static Command parse(String fullCommand) throws RexException { + String commandWord = fullCommand.trim().toLowerCase(); + Command command; + switch (commandWord) { + case ExitCommand.COMMAND_WORD: + command = new ExitCommand(); + break; + default: + throw new RexException(Command.COMMAND_ERROR); + } + return command; + } +} diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java new file mode 100644 index 0000000000..9324fa9f4f --- /dev/null +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -0,0 +1,64 @@ +package seedu.rex.storage; + +import seedu.rex.data.patient.Patient; +import seedu.rex.data.exception.RexException; +import seedu.rex.parser.Parser; + +import java.io.BufferedReader; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; + +public class Storage { + public static final String LOAD_ERROR = "Error loading file."; + private static final String READ_ERROR = "Error reading file."; + private static final String DIRECTORY_ERROR = "Error creating directory."; + private static final String WRITE_ERROR = "Error writing file."; + + private final String folder; + private final String file; + + /** + * Initializes path of folder and file. + * + * @param filePath Full file path. + */ + public Storage(String filePath) { + int index = filePath.lastIndexOf("/"); + folder = filePath.substring(0, index); + file = filePath.substring(index + 1); + } + + /** + * Loads patients, stores them into ArrayList and returns the ArrayList. + * + * @return ArrayList of patients. + * @throws RexException If there is problem reading file. + */ + public ArrayList load() throws RexException { + Path path = Paths.get(folder, file); + ArrayList patients = new ArrayList<>(); + + if (Files.exists(path)) { + try { + BufferedReader bufferedReader = Files.newBufferedReader(path); + + while (true) { + String line = bufferedReader.readLine(); + if (line == null) { + break; + } + + Patient patient = Parser.readPatient(line); + patients.add(patient); + } + } catch (IOException e) { + throw new RexException(READ_ERROR); + } + } + + return patients; + } +} diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java new file mode 100644 index 0000000000..6a1c7c326c --- /dev/null +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -0,0 +1,83 @@ +package seedu.rex.ui; + +import seedu.rex.commands.Command; +import seedu.rex.commands.ExitCommand; +import seedu.rex.storage.Storage; + +import java.util.Scanner; + +/** + * Interacts with user. + */ +public class Ui { + + public static final String LOGO = + " _ _ _ _ _ _____ __ __\n" + + " | | | | (_| | | | | __ \\ \\ \\ / /\n" + + " | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \\ V / \n" + + " | __ |/ _ \\/ __| '_ \\| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \\ > < \n" + + " | | | | (_) \\__ | |_) | | || (_| | \\__ | (_| | |_| | | | |_| \\__ \\ | | \\ | __// . \\ \n" + + " |_| |_|\\___/|___| .__/|_|\\__\\__,_|_|___/\\__,_|\\__,_|_| \\__,_|___/ |_| \\_\\___/_/ \\_\\\n" + + " | | \n" + + " |_| "; + private static final String DOTTED_LINE = "____________________________________________________________"; + private final Scanner in = new Scanner(System.in); + + /** + * Prints string with indent. + * + * @param string String to print. + */ + private void printWithIndent(String string) { + System.out.println("\t " + string); + } + + /** + * Prints dotted line. + */ + public void showLine() { + System.out.println("\t" + DOTTED_LINE); + } + + /** + * Prints error message. + * + * @param message Error message to print. + */ + public void showError(String message) { + printWithIndent(message); + } + + /** + * Prints welcome message. + */ + public void showWelcome() { + showLine(); + printWithIndent(Command.MESSAGE); + showLine(); + } + + /** + * Prints loading error message. + */ + public void showLoadingError() { + showError(Storage.LOAD_ERROR); + } + + /** + * Prints exit message. + */ + public void showExit() { + printWithIndent(ExitCommand.MESSAGE); + } + + /** + * Reads command from user. + * + * @return String command from user. + */ + public String readCommand() { + System.out.println(); + return in.nextLine(); + } +} From ce74fa79a62c89115e60407d66032fabe164fd68 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 6 Oct 2020 14:16:18 +0800 Subject: [PATCH 011/148] Modify necessary classes --- src/main/java/seedu/rex/commands/Command.java | 3 +- src/main/java/seedu/rex/data/PatientList.java | 2 -- .../java/seedu/rex/data/patient/Patient.java | 3 ++ src/main/java/seedu/rex/parser/Parser.java | 2 +- src/main/java/seedu/rex/storage/Storage.java | 32 +++++++++++++++++++ src/main/java/seedu/rex/ui/Ui.java | 17 +++++----- 6 files changed, 47 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index e41941a30f..3b3d953dfc 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -10,7 +10,8 @@ */ public abstract class Command { - public static final String MESSAGE = Ui.LOGO + System.lineSeparator() + "How may i assist you?"; + public static final String MESSAGE = Ui.LOGO + "\n How may i assist you?" + .replace("\n",System.lineSeparator() + "\t"); public static final String COMMAND_ERROR = "I'm sorry, but I don't know what that means :-("; boolean isExit; diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index 9533074cd9..417c068e50 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -6,8 +6,6 @@ public class PatientList { - private static final String PATIENT_NUMBER_ERROR = "Invalid patient number."; - private final ArrayList patients; /** diff --git a/src/main/java/seedu/rex/data/patient/Patient.java b/src/main/java/seedu/rex/data/patient/Patient.java index 2837b4d844..ce900441ca 100644 --- a/src/main/java/seedu/rex/data/patient/Patient.java +++ b/src/main/java/seedu/rex/data/patient/Patient.java @@ -1,4 +1,7 @@ package seedu.rex.data.patient; +/** + * Patient class. + */ public class Patient { } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 445b41e1e7..c202f57dca 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -7,7 +7,7 @@ public class Parser { public static Patient readPatient(String line) { - //to read patients from file + // to read patients from file return null; } diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index 9324fa9f4f..b468857aa6 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -1,10 +1,13 @@ package seedu.rex.storage; +import seedu.rex.data.PatientList; import seedu.rex.data.patient.Patient; import seedu.rex.data.exception.RexException; import seedu.rex.parser.Parser; import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -61,4 +64,33 @@ public ArrayList load() throws RexException { return patients; } + + /** + * Saves patients into file. + * + * @param patients ArrayList of patients to save. + * @throws RexException If there is problem writing or saving file. + */ + public void save(PatientList patients) throws RexException { + StringBuilder fileContent = new StringBuilder(); + + for (int i = 0; i < patients.getSize(); i++) { + // Need to format tasks + fileContent.append(patients.getPatientUsingIndex(i)); + } + + Path folderPath = Paths.get(folder); + if (!Files.exists(folderPath) && !new File(folder).mkdir()) { + throw new RexException(DIRECTORY_ERROR); + } + + Path filePath = Paths.get(folder, file); + try { + BufferedWriter bufferedWriter = Files.newBufferedWriter(filePath); + bufferedWriter.write(fileContent.toString()); + bufferedWriter.close(); + } catch (IOException e) { + throw new RexException(WRITE_ERROR); + } + } } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 6a1c7c326c..21338ab3d8 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -12,14 +12,15 @@ public class Ui { public static final String LOGO = - " _ _ _ _ _ _____ __ __\n" - + " | | | | (_| | | | | __ \\ \\ \\ / /\n" - + " | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \\ V / \n" - + " | __ |/ _ \\/ __| '_ \\| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \\ > < \n" - + " | | | | (_) \\__ | |_) | | || (_| | \\__ | (_| | |_| | | | |_| \\__ \\ | | \\ | __// . \\ \n" - + " |_| |_|\\___/|___| .__/|_|\\__\\__,_|_|___/\\__,_|\\__,_|_| \\__,_|___/ |_| \\_\\___/_/ \\_\\\n" - + " | | \n" - + " |_| "; + " _ _ _ _ _ _____ __ __\n" + + "\t | | | | (_| | | | | __ \\ \\ \\ / /\n" + + "\t | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \\ V / \n" + + "\t | __ |/ _ \\/ __| '_ \\| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \\ > < \n" + + "\t | | | | (_) \\__ | |_) | | || (_| | \\__ | (_| | |_| | | | |_| \\__ \\ | | \\ | __// . \\ \n" + + "\t |_| |_|\\___/|___| .__/|_|\\__\\__,_|_|___/\\__,_|\\__,_|_| \\__,_|___/ |_| \\_\\___/_/ \\_\\\n" + + "\t | | \n" + + "\t |_| " + .replaceAll("\n", System.lineSeparator()); private static final String DOTTED_LINE = "____________________________________________________________"; private final Scanner in = new Scanner(System.in); From b7903420573a3b86cf5bf1e11ce3cf288550d226 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 6 Oct 2020 14:16:28 +0800 Subject: [PATCH 012/148] Modify main class --- src/main/java/seedu/rex/Rex.java | 65 +++++++++++++++++++++++++------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 3dcc86a285..887d51ed41 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -1,24 +1,61 @@ package seedu.rex; -import java.util.Scanner; +import seedu.rex.commands.Command; +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.parser.Parser; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; public class Rex { + + private final Storage storage; + private final Ui ui; + private PatientList patients; + /** - * Main entry-point for the java.rex.Rex application. + * Initializes chat bot. + * + * @param filePath Path to store and load patients. + */ + public Rex(String filePath) { + ui = new Ui(); + storage = new Storage(filePath); + try { + patients = new PatientList(storage.load()); + } catch (RexException e) { + ui.showLoadingError(); + patients = new PatientList(); + } + } + + /** + * Starts Rex. + * + * @param args Command line argument. */ public static void main(String[] args) { - String logo = " _ _ _ _ _ _____ __ __\n" - + " | | | | (_| | | | | __ \\ \\ \\ / /\n" - + " | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \\ V / \n" - + " | __ |/ _ \\/ __| '_ \\| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \\ > < \n" - + " | | | | (_) \\__ | |_) | | || (_| | \\__ | (_| | |_| | | | |_| \\__ \\ | | \\ | __// . \\ \n" - + " |_| |_|\\___/|___| .__/|_|\\__\\__,_|_|___/\\__,_|\\__,_|_| \\__,_|___/ |_| \\_\\___/_/ \\_\\\n" - + " | | \n" - + " |_| "; - System.out.println("Hello from\n" + logo); - System.out.println("What is your name?"); + new Rex("data/patients.txt").run(); + } - Scanner in = new Scanner(System.in); - System.out.println("Hello " + in.nextLine()); + /** + * Runs Rex. + */ + public void run() { + ui.showWelcome(); + boolean isExit = false; + while (!isExit) { + try { + String fullCommand = ui.readCommand(); + ui.showLine(); // show the divider line ("_______") + Command c = Parser.parse(fullCommand); + c.execute(patients, ui, storage); + isExit = c.isExit(); + } catch (RexException e) { + ui.showError(e.getMessage()); + } finally { + ui.showLine(); + } + } } } From b51caa28d9d64ff8fd99c8b0f26d0de78b52706d Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 6 Oct 2020 14:20:16 +0800 Subject: [PATCH 013/148] Modify testing files to test output --- text-ui-test/EXPECTED.TXT | 30 +++++++++++++++++++----------- text-ui-test/input.txt | 3 ++- 2 files changed, 21 insertions(+), 12 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 66c8f3e10e..9231557ce0 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,11 +1,19 @@ -Hello from - _ _ _ _ _ _____ __ __ - | | | | (_| | | | | __ \ \ \ / / - | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \ V / - | __ |/ _ \/ __| '_ \| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \ > < - | | | | (_) \__ | |_) | | || (_| | \__ | (_| | |_| | | | |_| \__ \ | | \ | __// . \ - |_| |_|\___/|___| .__/|_|\__\__,_|_|___/\__,_|\__,_|_| \__,_|___/ |_| \_\___/_/ \_\ - | | - |_| -What is your name? -Hello James Gosling + ____________________________________________________________ + _ _ _ _ _ _____ __ __ + | | | | (_| | | | | __ \ \ \ / / + | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \ V / + | __ |/ _ \/ __| '_ \| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \ > < + | | | | (_) \__ | |_) | | || (_| | \__ | (_| | |_| | | | |_| \__ \ | | \ | __// . \ + |_| |_|\___/|___| .__/|_|\__\__,_|_|___/\__,_|\__,_|_| \__,_|___/ |_| \_\___/_/ \_\ + | | + |_| + How may i assist you? + ____________________________________________________________ + + ____________________________________________________________ + ☹ OOPS!!! I'm sorry, but I don't know what that means :-( + ____________________________________________________________ + + ____________________________________________________________ + Bye. Hope to see you again soon! + ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index f6ec2e9f95..1329553ca2 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1 +1,2 @@ -James Gosling \ No newline at end of file +James Gosling +bye \ No newline at end of file From a0e6268fc1b19994440050a25535ef339fa5a6de Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 6 Oct 2020 14:33:25 +0800 Subject: [PATCH 014/148] Improve code quality --- src/main/java/seedu/rex/commands/Command.java | 8 ++++---- src/main/java/seedu/rex/commands/ExitCommand.java | 6 +++--- src/main/java/seedu/rex/parser/Parser.java | 2 +- src/main/java/seedu/rex/storage/Storage.java | 2 +- src/main/java/seedu/rex/ui/Ui.java | 14 +++++++------- src/test/java/seedu/rex/RexTest.java | 4 ++-- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index 3b3d953dfc..caf0b01712 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -11,7 +11,7 @@ public abstract class Command { public static final String MESSAGE = Ui.LOGO + "\n How may i assist you?" - .replace("\n",System.lineSeparator() + "\t"); + .replace("\n", System.lineSeparator() + "\t"); public static final String COMMAND_ERROR = "I'm sorry, but I don't know what that means :-("; boolean isExit; @@ -26,9 +26,9 @@ public Command() { /** * Executes command. * - * @param patients PatientList object. - * @param ui Ui object. - * @param storage Storage object. + * @param patients PatientList object. + * @param ui Ui object. + * @param storage Storage object. * @throws RexException If there is issue executing command. */ public abstract void execute(PatientList patients, Ui ui, Storage storage) throws RexException; diff --git a/src/main/java/seedu/rex/commands/ExitCommand.java b/src/main/java/seedu/rex/commands/ExitCommand.java index dc1f3ebac3..b74724820e 100644 --- a/src/main/java/seedu/rex/commands/ExitCommand.java +++ b/src/main/java/seedu/rex/commands/ExitCommand.java @@ -15,9 +15,9 @@ public class ExitCommand extends Command { /** * Says goodbye to user and exits Rex. * - * @param patients PatientList object. - * @param ui Ui object. - * @param storage Storage object. + * @param patients PatientList object. + * @param ui Ui object. + * @param storage Storage object. */ @Override public void execute(PatientList patients, Ui ui, Storage storage) { diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index c202f57dca..ae14317a7a 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -2,8 +2,8 @@ import seedu.rex.commands.Command; import seedu.rex.commands.ExitCommand; -import seedu.rex.data.patient.Patient; import seedu.rex.data.exception.RexException; +import seedu.rex.data.patient.Patient; public class Parser { public static Patient readPatient(String line) { diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index b468857aa6..f1b251cf69 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -1,8 +1,8 @@ package seedu.rex.storage; import seedu.rex.data.PatientList; -import seedu.rex.data.patient.Patient; import seedu.rex.data.exception.RexException; +import seedu.rex.data.patient.Patient; import seedu.rex.parser.Parser; import java.io.BufferedReader; diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 21338ab3d8..589757a3b1 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -13,13 +13,13 @@ public class Ui { public static final String LOGO = " _ _ _ _ _ _____ __ __\n" - + "\t | | | | (_| | | | | __ \\ \\ \\ / /\n" - + "\t | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \\ V / \n" - + "\t | __ |/ _ \\/ __| '_ \\| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \\ > < \n" - + "\t | | | | (_) \\__ | |_) | | || (_| | \\__ | (_| | |_| | | | |_| \\__ \\ | | \\ | __// . \\ \n" - + "\t |_| |_|\\___/|___| .__/|_|\\__\\__,_|_|___/\\__,_|\\__,_|_| \\__,_|___/ |_| \\_\\___/_/ \\_\\\n" - + "\t | | \n" - + "\t |_| " + + "\t | | | | (_| | | | | __ \\ \\ \\ / /\n" + + "\t | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \\ V / \n" + + "\t | __ |/ _ \\/ __| '_ \\| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \\ > < \n" + + "\t | | | | (_) \\__ | |_) | | || (_| | \\__ | (_| | |_| | | | |_| \\__ \\ | | \\ | __// . \\ \n" + + "\t |_| |_|\\___/|___| .__/|_|\\__\\__,_|_|___/\\__,_|\\__,_|_| \\__,_|___/ |_| \\_\\___/_/ \\_\\\n" + + "\t | | \n" + + "\t |_| " .replaceAll("\n", System.lineSeparator()); private static final String DOTTED_LINE = "____________________________________________________________"; private final Scanner in = new Scanner(System.in); diff --git a/src/test/java/seedu/rex/RexTest.java b/src/test/java/seedu/rex/RexTest.java index 26836177c7..56524a146d 100644 --- a/src/test/java/seedu/rex/RexTest.java +++ b/src/test/java/seedu/rex/RexTest.java @@ -1,9 +1,9 @@ package seedu.rex; -import static org.junit.jupiter.api.Assertions.assertTrue; - import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertTrue; + class RexTest { @Test public void sampleTest() { From 0507751da226114f7ae78f0c153a434420871dc9 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 6 Oct 2020 14:36:15 +0800 Subject: [PATCH 015/148] Fix checkstyle errors --- src/main/java/seedu/rex/ui/Ui.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 589757a3b1..a96c1051f3 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -16,8 +16,10 @@ public class Ui { + "\t | | | | (_| | | | | __ \\ \\ \\ / /\n" + "\t | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \\ V / \n" + "\t | __ |/ _ \\/ __| '_ \\| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \\ > < \n" - + "\t | | | | (_) \\__ | |_) | | || (_| | \\__ | (_| | |_| | | | |_| \\__ \\ | | \\ | __// . \\ \n" - + "\t |_| |_|\\___/|___| .__/|_|\\__\\__,_|_|___/\\__,_|\\__,_|_| \\__,_|___/ |_| \\_\\___/_/ \\_\\\n" + + "\t | | | | (_) \\__ | |_) | | || (_| | \\__ | (_| | |_| | | | |_| \\__ \\ | | \\ | __// . \\" + + " \n" + + "\t |_| |_|\\___/|___| .__/|_|\\__\\__,_|_|___/\\__,_|\\__,_|_| \\__,_|___/ |_| \\_\\___/_/ " + + "\\_\\\n" + "\t | | \n" + "\t |_| " .replaceAll("\n", System.lineSeparator()); From c914bc0d2ed6f1d4d9c74b79446c00cab2d9d47d Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 6 Oct 2020 14:56:56 +0800 Subject: [PATCH 016/148] Add some JUnit tests --- .../java/seedu/rex/parser/ParserTest.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 src/test/java/seedu/rex/parser/ParserTest.java diff --git a/src/test/java/seedu/rex/parser/ParserTest.java b/src/test/java/seedu/rex/parser/ParserTest.java new file mode 100644 index 0000000000..e5ac85fece --- /dev/null +++ b/src/test/java/seedu/rex/parser/ParserTest.java @@ -0,0 +1,20 @@ +package seedu.rex.parser; + +import org.junit.jupiter.api.Test; +import seedu.rex.commands.ExitCommand; +import seedu.rex.data.exception.RexException; + +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class ParserTest { + @Test + void parse_bye_returnsExitCommand() throws RexException { + assertTrue(Parser.parse("bye") instanceof ExitCommand); + } + + @Test + void parse_invalidInput_expectException() { + assertThrows(RexException.class, () -> Parser.parse("exit")); + } +} From bd7c0bac308892700559f304a23ed6c41bab1ef9 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Fri, 9 Oct 2020 18:11:01 +0800 Subject: [PATCH 017/148] Add JUnit test to Ui --- src/test/java/seedu/rex/ui/UiTest.java | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 src/test/java/seedu/rex/ui/UiTest.java diff --git a/src/test/java/seedu/rex/ui/UiTest.java b/src/test/java/seedu/rex/ui/UiTest.java new file mode 100644 index 0000000000..63824f4a62 --- /dev/null +++ b/src/test/java/seedu/rex/ui/UiTest.java @@ -0,0 +1,21 @@ +package seedu.rex.ui; + +import org.junit.jupiter.api.Test; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; + +import static org.junit.jupiter.api.Assertions.*; + +class UiTest { + + @Test + void readCommand_hello_returnsHelloString() { + + String input = "hello"; + InputStream in = new ByteArrayInputStream(input.getBytes()); + System.setIn(in); + + assertEquals("hello", new Ui().readCommand()); + } +} \ No newline at end of file From cb3783ba11cd6a61e2c18fe9963f2d55fcf9b20a Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Fri, 9 Oct 2020 18:13:39 +0800 Subject: [PATCH 018/148] Change syntax to adhere to coding standard --- src/test/java/seedu/rex/ui/UiTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/seedu/rex/ui/UiTest.java b/src/test/java/seedu/rex/ui/UiTest.java index 63824f4a62..219442805e 100644 --- a/src/test/java/seedu/rex/ui/UiTest.java +++ b/src/test/java/seedu/rex/ui/UiTest.java @@ -5,7 +5,7 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class UiTest { From 1b9ea653a951eef0d1feeef9b86ced392de4095b Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sat, 10 Oct 2020 17:25:22 +0800 Subject: [PATCH 019/148] Add more classes to Rex --- src/main/java/seedu/rex/data/DoctorList.java | 54 ++++++++++++++++ src/main/java/seedu/rex/data/PatientList.java | 2 +- .../seedu/rex/data/hospital/Appointment.java | 61 +++++++++++++++++++ .../java/seedu/rex/data/hospital/Doctor.java | 16 +++++ .../seedu/rex/data/hospital/Hospital.java | 35 +++++++++++ .../java/seedu/rex/data/hospital/Patient.java | 56 +++++++++++++++++ .../seedu/rex/data/hospital/Prescription.java | 22 +++++++ .../java/seedu/rex/data/patient/Patient.java | 7 --- src/main/java/seedu/rex/parser/Parser.java | 2 +- src/main/java/seedu/rex/storage/Storage.java | 2 +- 10 files changed, 247 insertions(+), 10 deletions(-) create mode 100644 src/main/java/seedu/rex/data/DoctorList.java create mode 100644 src/main/java/seedu/rex/data/hospital/Appointment.java create mode 100644 src/main/java/seedu/rex/data/hospital/Doctor.java create mode 100644 src/main/java/seedu/rex/data/hospital/Hospital.java create mode 100644 src/main/java/seedu/rex/data/hospital/Patient.java create mode 100644 src/main/java/seedu/rex/data/hospital/Prescription.java delete mode 100644 src/main/java/seedu/rex/data/patient/Patient.java diff --git a/src/main/java/seedu/rex/data/DoctorList.java b/src/main/java/seedu/rex/data/DoctorList.java new file mode 100644 index 0000000000..440fa83c0a --- /dev/null +++ b/src/main/java/seedu/rex/data/DoctorList.java @@ -0,0 +1,54 @@ +package seedu.rex.data; + +import seedu.rex.data.hospital.Doctor; + +import java.util.ArrayList; + +public class DoctorList { + + private final ArrayList doctors; + + /** + * Initializes doctors ArrayList. + */ + public DoctorList() { + doctors = new ArrayList<>(); + } + + /** + * Initializes doctors ArrayList using parameter. + * + * @param doctors Doctors list to use. + */ + public DoctorList(ArrayList doctors) { + this.doctors = doctors; + } + + /** + * Returns size of doctors. + * + * @return Length of doctors. + */ + public int getSize() { + return doctors.size(); + } + + /** + * Returns doctor using index. + * + * @param index Index of doctor. + * @return doctor at that index. + */ + public Doctor getDoctorUsingIndex(int index) { + return doctors.get(index); + } + + /** + * Adds doctor to doctors ArrayList. + * + * @param doctor doctor to add. + */ + public void addDoctor(Doctor doctor) { + doctors.add(doctor); + } +} diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index 417c068e50..0e0de1fd98 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -1,6 +1,6 @@ package seedu.rex.data; -import seedu.rex.data.patient.Patient; +import seedu.rex.data.hospital.Patient; import java.util.ArrayList; diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java new file mode 100644 index 0000000000..67cf826263 --- /dev/null +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -0,0 +1,61 @@ +package seedu.rex.data.hospital; + +import java.util.Date; + +public class Appointment { + + private Date date; + private String time; + private Patient patient; + private Doctor doctor; + private String notes; + private Prescription prescription; + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public String getTime() { + return time; + } + + public Patient getPatient() { + return patient; + } + + public void setPatient(Patient patient) { + this.patient = patient; + } + + public Doctor getDoctor() { + return doctor; + } + + public void setDoctor(Doctor doctor) { + this.doctor = doctor; + } + + public String getNotes() { + return notes; + } + + public void setNotes(String notes) { + this.notes = notes; + } + + public Prescription getPrescription() { + return prescription; + } + + public void setPrescription(Prescription prescription) { + this.prescription = prescription; + } + + public void setTime(String time) { + this.time = time; + } +} diff --git a/src/main/java/seedu/rex/data/hospital/Doctor.java b/src/main/java/seedu/rex/data/hospital/Doctor.java new file mode 100644 index 0000000000..4bf8b9463a --- /dev/null +++ b/src/main/java/seedu/rex/data/hospital/Doctor.java @@ -0,0 +1,16 @@ +package seedu.rex.data.hospital; + +public class Doctor { + private String name; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + private enum Departments {} + +} diff --git a/src/main/java/seedu/rex/data/hospital/Hospital.java b/src/main/java/seedu/rex/data/hospital/Hospital.java new file mode 100644 index 0000000000..2462d871a0 --- /dev/null +++ b/src/main/java/seedu/rex/data/hospital/Hospital.java @@ -0,0 +1,35 @@ +package seedu.rex.data.hospital; + +import seedu.rex.data.DoctorList; +import seedu.rex.data.PatientList; + +public class Hospital { + private String name; + private PatientList patients; + private DoctorList doctors; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public PatientList getPatients() { + return patients; + } + + public void setPatients(PatientList patients) { + this.patients = patients; + } + + public DoctorList getDoctors() { + return doctors; + } + + public void setDoctors(DoctorList doctors) { + this.doctors = doctors; + } + +} diff --git a/src/main/java/seedu/rex/data/hospital/Patient.java b/src/main/java/seedu/rex/data/hospital/Patient.java new file mode 100644 index 0000000000..f39877e4a6 --- /dev/null +++ b/src/main/java/seedu/rex/data/hospital/Patient.java @@ -0,0 +1,56 @@ +package seedu.rex.data.hospital; + +import java.util.Date; +import java.util.Vector; + +/** + * Patient class. + */ +public class Patient { + + private String name; + private String nric; + private Date dateOfBirth; + private Vector appointmentHistory; + + private enum Gender { + MALE, FEMALE + } + + Patient(String name, String nric, Date dateOfBirth) { + setName(name); + setNric(nric); + setDateOfBirth(dateOfBirth); + this.appointmentHistory = new Vector<>(); + + // will create an empty appt history + } + + public Date getDateOfBirth() { + return dateOfBirth; + } + + public void setDateOfBirth(Date dateOfBirth) { + this.dateOfBirth = dateOfBirth; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getNric() { + return nric; + } + + public void setNric(String nric) { + this.nric = nric; + } + + public Vector getAppointmentHistory() { + return appointmentHistory; + } +} diff --git a/src/main/java/seedu/rex/data/hospital/Prescription.java b/src/main/java/seedu/rex/data/hospital/Prescription.java new file mode 100644 index 0000000000..31c8951799 --- /dev/null +++ b/src/main/java/seedu/rex/data/hospital/Prescription.java @@ -0,0 +1,22 @@ +package seedu.rex.data.hospital; + +public class Prescription { + private String dosage; + private String frequency; + + public String getDosage() { + return dosage; + } + + public void setDosage(String dosage) { + this.dosage = dosage; + } + + public String getFrequency() { + return frequency; + } + + public void setFrequency(String frequency) { + this.frequency = frequency; + } +} diff --git a/src/main/java/seedu/rex/data/patient/Patient.java b/src/main/java/seedu/rex/data/patient/Patient.java deleted file mode 100644 index ce900441ca..0000000000 --- a/src/main/java/seedu/rex/data/patient/Patient.java +++ /dev/null @@ -1,7 +0,0 @@ -package seedu.rex.data.patient; - -/** - * Patient class. - */ -public class Patient { -} diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index ae14317a7a..f280d066ea 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -3,7 +3,7 @@ import seedu.rex.commands.Command; import seedu.rex.commands.ExitCommand; import seedu.rex.data.exception.RexException; -import seedu.rex.data.patient.Patient; +import seedu.rex.data.hospital.Patient; public class Parser { public static Patient readPatient(String line) { diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index f1b251cf69..84afe37282 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -2,7 +2,7 @@ import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.patient.Patient; +import seedu.rex.data.hospital.Patient; import seedu.rex.parser.Parser; import java.io.BufferedReader; From 84fd0cdec48c818a2e448deba355c9551f35fe0c Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sat, 10 Oct 2020 17:26:17 +0800 Subject: [PATCH 020/148] Improve code quality --- src/main/java/seedu/rex/data/hospital/Appointment.java | 8 ++++---- src/main/java/seedu/rex/data/hospital/Patient.java | 10 +++++----- src/test/java/seedu/rex/parser/ParserTest.java | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java index 67cf826263..4bc38c584f 100644 --- a/src/main/java/seedu/rex/data/hospital/Appointment.java +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -23,6 +23,10 @@ public String getTime() { return time; } + public void setTime(String time) { + this.time = time; + } + public Patient getPatient() { return patient; } @@ -54,8 +58,4 @@ public Prescription getPrescription() { public void setPrescription(Prescription prescription) { this.prescription = prescription; } - - public void setTime(String time) { - this.time = time; - } } diff --git a/src/main/java/seedu/rex/data/hospital/Patient.java b/src/main/java/seedu/rex/data/hospital/Patient.java index f39877e4a6..b43edbd55c 100644 --- a/src/main/java/seedu/rex/data/hospital/Patient.java +++ b/src/main/java/seedu/rex/data/hospital/Patient.java @@ -11,11 +11,7 @@ public class Patient { private String name; private String nric; private Date dateOfBirth; - private Vector appointmentHistory; - - private enum Gender { - MALE, FEMALE - } + private final Vector appointmentHistory; Patient(String name, String nric, Date dateOfBirth) { setName(name); @@ -53,4 +49,8 @@ public void setNric(String nric) { public Vector getAppointmentHistory() { return appointmentHistory; } + + private enum Gender { + MALE, FEMALE + } } diff --git a/src/test/java/seedu/rex/parser/ParserTest.java b/src/test/java/seedu/rex/parser/ParserTest.java index e5ac85fece..323724399b 100644 --- a/src/test/java/seedu/rex/parser/ParserTest.java +++ b/src/test/java/seedu/rex/parser/ParserTest.java @@ -4,8 +4,8 @@ import seedu.rex.commands.ExitCommand; import seedu.rex.data.exception.RexException; -import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; public class ParserTest { @Test From 20d5538f92562efb59fcb6409f384768fbd4d10e Mon Sep 17 00:00:00 2001 From: ychong032 Date: Sat, 10 Oct 2020 23:16:12 +0800 Subject: [PATCH 021/148] Add ability to add new patients --- .../java/seedu/rex/commands/AddCommand.java | 76 +++++++++++++++++++ src/main/java/seedu/rex/commands/Command.java | 24 +++++- src/main/java/seedu/rex/data/PatientList.java | 11 +++ .../seedu/rex/data/hospital/Appointment.java | 9 ++- .../java/seedu/rex/data/hospital/Patient.java | 22 ++++-- src/main/java/seedu/rex/parser/Parser.java | 29 +++++-- src/main/java/seedu/rex/storage/Storage.java | 1 + src/main/java/seedu/rex/ui/Ui.java | 44 +++++++++++ 8 files changed, 198 insertions(+), 18 deletions(-) create mode 100644 src/main/java/seedu/rex/commands/AddCommand.java diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java new file mode 100644 index 0000000000..94d5eb7d01 --- /dev/null +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -0,0 +1,76 @@ +package seedu.rex.commands; + +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +/** + * Adds a patient to the list of patients. + */ +public class AddCommand extends Command { + + public static final String COMMAND_WORD = "add"; + public String trimmedCommand; + + public AddCommand(String trimmedCommand) { + this.trimmedCommand = trimmedCommand; + } + + /** + * Adds a new patient to the patient list using details inputted by the user. + * @param patients List of patients. + * @param ui Ui object of the program. + * @param storage Storage object used for saving data to files. + * @throws RexException If there is an error in the NRIC inputted by the user, the data fails + * to save successfully, or the NRIC already exists in the patient list. + */ + @Override + public void execute(PatientList patients, Ui ui, Storage storage) throws RexException { + String nric = extractNric(); + if (isExistingPatient(patients, nric)) { + throw new RexException("A patient with this NRIC is already registered!"); + } + patients.addNewPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); + ui.showLine(); + ui.showPatientAdded(patients.getPatientUsingIndex(patients.getSize() - 1)); + storage.save(patients); + } + + /** + * Extracts the NRIC from the 'add' command inputted by the user. + * @return Patient's NRIC as a String. + * @throws RexException If the NRIC inputted by the user is invalid. + */ + public String extractNric() throws RexException { + String nric = trimmedCommand.replaceFirst("(?i)" + COMMAND_WORD, "").trim().toUpperCase(); + if (nric.isBlank()) { + throw new RexException("Please enter a valid NRIC after 'add'."); + } else if (nric.length() != LEGAL_NRIC_LENGTH) { + throw new RexException("Invalid NRIC length!"); + } else if (!LEGAL_NRIC_STATUSES.contains(nric.charAt(0))) { + throw new RexException("Beginning character of NRIC must be 'S', 'T', 'F', or 'G'!"); + } else if (!isNumeric(nric.substring(1, LEGAL_NRIC_LENGTH - 1))) { + throw new RexException("Number sequence of NRIC is invalid!"); + } else if (!Character.isLetter(nric.charAt(nric.length() - 1))) { + throw new RexException("Final character of NRIC must be an English alphabet!"); + } else { + return nric; + } + } + + /** + * Checks if the NRIC entered by the user already exists in the patient list. + * @param patients The list of patients. + * @param nric The NRIC entered by the user. + * @return true if NRIC already exists; false otherwise. + */ + public boolean isExistingPatient(PatientList patients, String nric) { + for (int i = 0; i < patients.getSize(); i++) { + if (patients.getPatientUsingIndex(i).getNric().equals(nric)) { + return true; + } + } + return false; + } +} diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index caf0b01712..f550e7c24e 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -5,14 +5,18 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +import java.util.Set; + /** * Parent Command class. */ public abstract class Command { - public static final String MESSAGE = Ui.LOGO + "\n How may i assist you?" + public static final String MESSAGE = Ui.LOGO + "\n How may I assist you?" .replace("\n", System.lineSeparator() + "\t"); public static final String COMMAND_ERROR = "I'm sorry, but I don't know what that means :-("; + public static final int LEGAL_NRIC_LENGTH = 9; + public static final Set LEGAL_NRIC_STATUSES = Set.of('S', 'T', 'F', 'G'); boolean isExit; @@ -41,4 +45,22 @@ public Command() { public boolean isExit() { return isExit; } + + /** + * Checks if a given String consists of only numeric characters. + * @param string The String to be checked. + * @return true if the string contains only numeric characters; false + * otherwise. + */ + public boolean isNumeric(String string) { + if (string == null) { + return false; + } + try { + double stringAsDouble = Double.parseDouble(string); + } catch (NumberFormatException e) { + return false; + } + return true; + } } diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index 0e0de1fd98..11e9fd2f12 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -2,6 +2,7 @@ import seedu.rex.data.hospital.Patient; +import java.time.LocalDate; import java.util.ArrayList; public class PatientList { @@ -51,4 +52,14 @@ public Patient getPatientUsingIndex(int index) { public void addPatient(Patient patient) { patients.add(patient); } + + /** + * Adds a new patient with given details to patients ArrayList. + * @param name Name of the patient. + * @param nric NRIC of the patient. + * @param dateOfBirth Patient's date of birth. + */ + public void addNewPatient(String name, String nric, LocalDate dateOfBirth) { + addPatient(new Patient(name, nric, dateOfBirth)); + } } diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java index 4bc38c584f..cce2540712 100644 --- a/src/main/java/seedu/rex/data/hospital/Appointment.java +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -1,21 +1,21 @@ package seedu.rex.data.hospital; -import java.util.Date; +import java.time.LocalDate; public class Appointment { - private Date date; + private LocalDate date; private String time; private Patient patient; private Doctor doctor; private String notes; private Prescription prescription; - public Date getDate() { + public LocalDate getDate() { return date; } - public void setDate(Date date) { + public void setDate(LocalDate date) { this.date = date; } @@ -58,4 +58,5 @@ public Prescription getPrescription() { public void setPrescription(Prescription prescription) { this.prescription = prescription; } + } diff --git a/src/main/java/seedu/rex/data/hospital/Patient.java b/src/main/java/seedu/rex/data/hospital/Patient.java index b43edbd55c..17ccdc3090 100644 --- a/src/main/java/seedu/rex/data/hospital/Patient.java +++ b/src/main/java/seedu/rex/data/hospital/Patient.java @@ -1,6 +1,7 @@ package seedu.rex.data.hospital; -import java.util.Date; +import java.time.LocalDate; +import java.time.format.DateTimeFormatter; import java.util.Vector; /** @@ -10,23 +11,23 @@ public class Patient { private String name; private String nric; - private Date dateOfBirth; + private LocalDate dateOfBirth; private final Vector appointmentHistory; - Patient(String name, String nric, Date dateOfBirth) { + public Patient(String name, String nric, LocalDate dateOfBirth) { setName(name); setNric(nric); setDateOfBirth(dateOfBirth); this.appointmentHistory = new Vector<>(); - // will create an empty appt history + // will create an empty appointment history } - public Date getDateOfBirth() { + public LocalDate getDateOfBirth() { return dateOfBirth; } - public void setDateOfBirth(Date dateOfBirth) { + public void setDateOfBirth(LocalDate dateOfBirth) { this.dateOfBirth = dateOfBirth; } @@ -53,4 +54,13 @@ public Vector getAppointmentHistory() { private enum Gender { MALE, FEMALE } + + /** + * Returns the Patient object as a String for printing or writing to a file. + * @return Patient's details as a String in a particular format. + */ + @Override + public String toString() { + return name + ", " + nric + ", " + dateOfBirth.format(DateTimeFormatter.ISO_DATE); + } } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index f280d066ea..b5d689fab0 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,26 +1,41 @@ package seedu.rex.parser; +import seedu.rex.commands.AddCommand; import seedu.rex.commands.Command; import seedu.rex.commands.ExitCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Patient; +import java.time.LocalDate; + public class Parser { public static Patient readPatient(String line) { - // to read patients from file - return null; + String name; + String nric; + LocalDate dateOfBirth; + StringBuilder record = new StringBuilder(line); + name = record.substring(0, record.indexOf(", ")); + // Deletes first comma separator. + record.delete(0, record.indexOf(", ") + 2); + nric = record.substring(0, record.indexOf(", ")); + // Deletes second comma separator. + record.delete(0, record.indexOf(", ") + 2); + dateOfBirth = LocalDate.parse(record.toString()); + return new Patient(name, nric, dateOfBirth); } public static Command parse(String fullCommand) throws RexException { - String commandWord = fullCommand.trim().toLowerCase(); + String trimmedCommand = fullCommand.trim().toLowerCase(); Command command; - switch (commandWord) { - case ExitCommand.COMMAND_WORD: + if (trimmedCommand.equals(ExitCommand.COMMAND_WORD)) { command = new ExitCommand(); - break; - default: + } else if (trimmedCommand.contains(AddCommand.COMMAND_WORD)) { + command = new AddCommand(trimmedCommand); + } else { throw new RexException(Command.COMMAND_ERROR); } return command; } + + } diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index 84afe37282..cab9913092 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -77,6 +77,7 @@ public void save(PatientList patients) throws RexException { for (int i = 0; i < patients.getSize(); i++) { // Need to format tasks fileContent.append(patients.getPatientUsingIndex(i)); + fileContent.append('\n'); } Path folderPath = Paths.get(folder); diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index a96c1051f3..818e71c6d4 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -3,8 +3,11 @@ import seedu.rex.commands.Command; import seedu.rex.commands.ExitCommand; import seedu.rex.storage.Storage; +import seedu.rex.data.hospital.Patient; +import java.time.format.DateTimeParseException; import java.util.Scanner; +import java.time.LocalDate; /** * Interacts with user. @@ -24,6 +27,7 @@ public class Ui { + "\t |_| " .replaceAll("\n", System.lineSeparator()); private static final String DOTTED_LINE = "____________________________________________________________"; + private static final String DATE_ERROR = "Error in date format."; private final Scanner in = new Scanner(System.in); /** @@ -74,6 +78,20 @@ public void showExit() { printWithIndent(ExitCommand.MESSAGE); } + public void showDateInputError() { + showError(DATE_ERROR); + } + + /** + * Prints a message to indicate successful addition of a patient. + * @param patient The newly added Patient. + */ + public void showPatientAdded(Patient patient) { + printWithIndent("Patient successfully added: "); + printWithIndent(patient.toString()); + } + + /** * Reads command from user. * @@ -83,4 +101,30 @@ public String readCommand() { System.out.println(); return in.nextLine(); } + + /** + * Reads the name of a new patient from the user. + * @return The name of the patient to be added. + */ + public String getPatientName() { + printWithIndent("Enter patient name: "); + return in.nextLine().trim(); + } + + /** + * Reads the date of birth of a new patient from the user. + * @return The date of birth of the patient. + */ + public LocalDate getPatientDateOfBirth() { + while (true) { + try { + printWithIndent("Enter patient date of birth (YYYY-MM-DD) including the dashes: "); + return LocalDate.parse(in.nextLine().trim()); + } catch (DateTimeParseException e) { + showLine(); + showDateInputError(); + showLine(); + } + } + } } From a2b71a1b7bf466489974b1bdc5992e14a08c0696 Mon Sep 17 00:00:00 2001 From: ychong032 Date: Sun, 11 Oct 2020 03:09:09 +0800 Subject: [PATCH 022/148] Correct checkstyle errors --- src/main/java/seedu/rex/commands/AddCommand.java | 2 +- src/main/java/seedu/rex/commands/Command.java | 2 +- src/main/java/seedu/rex/parser/Parser.java | 9 +++------ 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java index 94d5eb7d01..b25034f561 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -23,7 +23,7 @@ public AddCommand(String trimmedCommand) { * @param ui Ui object of the program. * @param storage Storage object used for saving data to files. * @throws RexException If there is an error in the NRIC inputted by the user, the data fails - * to save successfully, or the NRIC already exists in the patient list. + * to save successfully, or the NRIC already exists in the patient list. */ @Override public void execute(PatientList patients, Ui ui, Storage storage) throws RexException { diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index f550e7c24e..cea3c38810 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -50,7 +50,7 @@ public boolean isExit() { * Checks if a given String consists of only numeric characters. * @param string The String to be checked. * @return true if the string contains only numeric characters; false - * otherwise. + * otherwise. */ public boolean isNumeric(String string) { if (string == null) { diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index b5d689fab0..8e789bd112 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -10,17 +10,14 @@ public class Parser { public static Patient readPatient(String line) { - String name; - String nric; - LocalDate dateOfBirth; StringBuilder record = new StringBuilder(line); - name = record.substring(0, record.indexOf(", ")); + String name = record.substring(0, record.indexOf(", ")); // Deletes first comma separator. record.delete(0, record.indexOf(", ") + 2); - nric = record.substring(0, record.indexOf(", ")); + String nric = record.substring(0, record.indexOf(", ")); // Deletes second comma separator. record.delete(0, record.indexOf(", ") + 2); - dateOfBirth = LocalDate.parse(record.toString()); + LocalDate dateOfBirth = LocalDate.parse(record.toString()); return new Patient(name, nric, dateOfBirth); } From 5ceee76c956180411d8996efe6d905911bd0e715 Mon Sep 17 00:00:00 2001 From: ychong032 Date: Sun, 11 Oct 2020 03:12:15 +0800 Subject: [PATCH 023/148] Revert greeting message --- src/main/java/seedu/rex/commands/Command.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index cea3c38810..8c817c7b57 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -12,7 +12,7 @@ */ public abstract class Command { - public static final String MESSAGE = Ui.LOGO + "\n How may I assist you?" + public static final String MESSAGE = Ui.LOGO + "\n How may i assist you?" .replace("\n", System.lineSeparator() + "\t"); public static final String COMMAND_ERROR = "I'm sorry, but I don't know what that means :-("; public static final int LEGAL_NRIC_LENGTH = 9; From a1c673367ca68aa9c9e2c259f5eb750ef0fca957 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 11 Oct 2020 15:26:47 +0800 Subject: [PATCH 024/148] Add retrieve function to Rex --- .gitignore | 2 ++ .../seedu/rex/commands/RetrieveCommand.java | 34 +++++++++++++++++++ src/main/java/seedu/rex/parser/Parser.java | 3 ++ src/main/java/seedu/rex/ui/Ui.java | 5 +++ 4 files changed, 44 insertions(+) create mode 100644 src/main/java/seedu/rex/commands/RetrieveCommand.java diff --git a/.gitignore b/.gitignore index f69985ef1f..120eedb7d8 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,5 @@ bin/ /text-ui-test/ACTUAL.txt text-ui-test/EXPECTED-UNIX.TXT + +/data/ diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java new file mode 100644 index 0000000000..93592705d4 --- /dev/null +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -0,0 +1,34 @@ +package seedu.rex.commands; + +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +public class RetrieveCommand extends Command { + + public static final String COMMAND_WORD = "retrieve"; + private final String trimmedCommand; + + public RetrieveCommand(String trimmedCommand) { + this.trimmedCommand = trimmedCommand; + } + + /** + * Retrieves patient from patient list using details inputted by the user. + * + * @param patients PatientList object. + * @param ui Ui object. + * @param storage Storage object. + * @throws RexException If there is issue executing command. + */ + @Override + public void execute(PatientList patients, Ui ui, Storage storage) throws RexException { + String nric = extractNric(trimmedCommand, COMMAND_WORD); + int index = getExistingPatient(patients, nric); + if (index < 0) { + throw new RexException("No such patient!"); + } + ui.showPatient(patients.getPatientUsingIndex(index)); + } +} diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 8e789bd112..bdf600fa90 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -3,6 +3,7 @@ import seedu.rex.commands.AddCommand; import seedu.rex.commands.Command; import seedu.rex.commands.ExitCommand; +import seedu.rex.commands.RetrieveCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Patient; @@ -28,6 +29,8 @@ public static Command parse(String fullCommand) throws RexException { command = new ExitCommand(); } else if (trimmedCommand.contains(AddCommand.COMMAND_WORD)) { command = new AddCommand(trimmedCommand); + } else if (trimmedCommand.contains(RetrieveCommand.COMMAND_WORD)) { + command = new RetrieveCommand(trimmedCommand); } else { throw new RexException(Command.COMMAND_ERROR); } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 818e71c6d4..6f0ee19ba6 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -127,4 +127,9 @@ public LocalDate getPatientDateOfBirth() { } } } + + public void showPatient(Patient patient) { + printWithIndent("Patient Details: "); + printWithIndent(patient.toString()); + } } From 7fae2d130f9715ade48a6720b015370f708e12e6 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 11 Oct 2020 15:27:18 +0800 Subject: [PATCH 025/148] Modify add command --- .../java/seedu/rex/commands/AddCommand.java | 44 ++----------- src/main/java/seedu/rex/commands/Command.java | 62 +++++++++++++++++-- src/main/java/seedu/rex/data/PatientList.java | 26 ++++++++ 3 files changed, 89 insertions(+), 43 deletions(-) diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java index b25034f561..8441b6a6d2 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -11,7 +11,7 @@ public class AddCommand extends Command { public static final String COMMAND_WORD = "add"; - public String trimmedCommand; + private final String trimmedCommand; public AddCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; @@ -19,6 +19,7 @@ public AddCommand(String trimmedCommand) { /** * Adds a new patient to the patient list using details inputted by the user. + * * @param patients List of patients. * @param ui Ui object of the program. * @param storage Storage object used for saving data to files. @@ -27,50 +28,15 @@ public AddCommand(String trimmedCommand) { */ @Override public void execute(PatientList patients, Ui ui, Storage storage) throws RexException { - String nric = extractNric(); + String nric = extractNric(trimmedCommand, COMMAND_WORD); if (isExistingPatient(patients, nric)) { throw new RexException("A patient with this NRIC is already registered!"); } + patients.addNewPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); ui.showLine(); + ui.showPatientAdded(patients.getPatientUsingIndex(patients.getSize() - 1)); storage.save(patients); } - - /** - * Extracts the NRIC from the 'add' command inputted by the user. - * @return Patient's NRIC as a String. - * @throws RexException If the NRIC inputted by the user is invalid. - */ - public String extractNric() throws RexException { - String nric = trimmedCommand.replaceFirst("(?i)" + COMMAND_WORD, "").trim().toUpperCase(); - if (nric.isBlank()) { - throw new RexException("Please enter a valid NRIC after 'add'."); - } else if (nric.length() != LEGAL_NRIC_LENGTH) { - throw new RexException("Invalid NRIC length!"); - } else if (!LEGAL_NRIC_STATUSES.contains(nric.charAt(0))) { - throw new RexException("Beginning character of NRIC must be 'S', 'T', 'F', or 'G'!"); - } else if (!isNumeric(nric.substring(1, LEGAL_NRIC_LENGTH - 1))) { - throw new RexException("Number sequence of NRIC is invalid!"); - } else if (!Character.isLetter(nric.charAt(nric.length() - 1))) { - throw new RexException("Final character of NRIC must be an English alphabet!"); - } else { - return nric; - } - } - - /** - * Checks if the NRIC entered by the user already exists in the patient list. - * @param patients The list of patients. - * @param nric The NRIC entered by the user. - * @return true if NRIC already exists; false otherwise. - */ - public boolean isExistingPatient(PatientList patients, String nric) { - for (int i = 0; i < patients.getSize(); i++) { - if (patients.getPatientUsingIndex(i).getNric().equals(nric)) { - return true; - } - } - return false; - } } diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index 8c817c7b57..6cab2f54a3 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -47,20 +47,74 @@ public boolean isExit() { } /** - * Checks if a given String consists of only numeric characters. + * Checks if a given String consists of only integer characters. + * * @param string The String to be checked. - * @return true if the string contains only numeric characters; false + * @return true if the string contains only integer characters; false * otherwise. */ - public boolean isNumeric(String string) { + public boolean isInteger(String string) { if (string == null) { return false; } try { - double stringAsDouble = Double.parseDouble(string); + double stringAsInteger = Integer.parseInt(string); } catch (NumberFormatException e) { return false; } return true; } + + /** + * Extracts the NRIC from command inputted by the user. + * + * @param trimmedCommand String after command word. + * @param commandWord Command that was called. + * @return Patient's NRIC as a String. + * @throws RexException If the NRIC inputted by the user is invalid. + */ + public String extractNric(String trimmedCommand, String commandWord) throws RexException { + String nric = trimmedCommand.replaceFirst("(?i)" + commandWord, "").trim().toUpperCase(); + if (nric.isBlank()) { + throw new RexException("Please enter a valid NRIC after '" + commandWord + "'."); + } else if (nric.length() != LEGAL_NRIC_LENGTH) { + throw new RexException("Invalid NRIC length!"); + } else if (!LEGAL_NRIC_STATUSES.contains(nric.charAt(0))) { + throw new RexException("Beginning character of NRIC must be 'S', 'T', 'F', or 'G'!"); + } else if (!isInteger(nric.substring(1, LEGAL_NRIC_LENGTH - 1))) { + throw new RexException("Number sequence of NRIC is invalid!"); + } else if (!Character.isLetter(nric.charAt(nric.length() - 1))) { + throw new RexException("Final character of NRIC must be an English alphabet!"); + } else { + return nric; + } + } + + /** + * Checks if the NRIC entered by the user already exists in the patient list. + * + * @param patients The list of patients. + * @param nric The NRIC entered by the user. + * @return true if NRIC already exists; false otherwise. + */ + public boolean isExistingPatient(PatientList patients, String nric) { + return getExistingPatient(patients, nric) > -1; + } + + /** + * Finds NRIC entered by the user from the patient list. + * Returns -1 if not found. + * + * @param patients The list of patients. + * @param nric The NRIC entered by the user. + * @return index of the patient with the NRIC; -1 otherwise. + */ + public int getExistingPatient(PatientList patients, String nric) { + for (int i = 0; i < patients.getSize(); i++) { + if (patients.getPatientUsingIndex(i).getNric().equals(nric)) { + return i; + } + } + return -1; + } } diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index 11e9fd2f12..ac831e88ba 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -62,4 +62,30 @@ public void addPatient(Patient patient) { public void addNewPatient(String name, String nric, LocalDate dateOfBirth) { addPatient(new Patient(name, nric, dateOfBirth)); } + + /** + * Checks if the NRIC entered by the user already exists in the patient list. + * + * @param nric The NRIC entered by the user. + * @return true if NRIC already exists; false otherwise. + */ + public boolean isExistingPatient(String nric) { + return getExistingPatient(nric) > -1; + } + + /** + * Finds NRIC entered by the user from the patient list. + * Returns -1 if not found. + * + * @param nric The NRIC entered by the user. + * @return index of the patient with the NRIC; -1 otherwise. + */ + public int getExistingPatient(String nric) { + for (int i = 0; i < getSize(); i++) { + if (getPatientUsingIndex(i).getNric().equals(nric)) { + return i; + } + } + return -1; + } } From 8610fed7db3b2c611aa852d42a34a32b0e1837ef Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 11 Oct 2020 15:29:26 +0800 Subject: [PATCH 026/148] Improve code quality --- src/main/java/seedu/rex/commands/AddCommand.java | 2 +- src/main/java/seedu/rex/commands/Command.java | 9 ++++----- src/main/java/seedu/rex/data/PatientList.java | 5 +++-- src/main/java/seedu/rex/data/hospital/Patient.java | 11 ++++++----- src/main/java/seedu/rex/ui/Ui.java | 7 +++++-- 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java index 8441b6a6d2..3e65020e4f 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -24,7 +24,7 @@ public AddCommand(String trimmedCommand) { * @param ui Ui object of the program. * @param storage Storage object used for saving data to files. * @throws RexException If there is an error in the NRIC inputted by the user, the data fails - * to save successfully, or the NRIC already exists in the patient list. + * to save successfully, or the NRIC already exists in the patient list. */ @Override public void execute(PatientList patients, Ui ui, Storage storage) throws RexException { diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index 6cab2f54a3..e95af5591f 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -50,8 +50,7 @@ public boolean isExit() { * Checks if a given String consists of only integer characters. * * @param string The String to be checked. - * @return true if the string contains only integer characters; false - * otherwise. + * @return true if the string contains only integer characters; false otherwise. */ public boolean isInteger(String string) { if (string == null) { @@ -69,7 +68,7 @@ public boolean isInteger(String string) { * Extracts the NRIC from command inputted by the user. * * @param trimmedCommand String after command word. - * @param commandWord Command that was called. + * @param commandWord Command that was called. * @return Patient's NRIC as a String. * @throws RexException If the NRIC inputted by the user is invalid. */ @@ -94,7 +93,7 @@ public String extractNric(String trimmedCommand, String commandWord) throws RexE * Checks if the NRIC entered by the user already exists in the patient list. * * @param patients The list of patients. - * @param nric The NRIC entered by the user. + * @param nric The NRIC entered by the user. * @return true if NRIC already exists; false otherwise. */ public boolean isExistingPatient(PatientList patients, String nric) { @@ -106,7 +105,7 @@ public boolean isExistingPatient(PatientList patients, String nric) { * Returns -1 if not found. * * @param patients The list of patients. - * @param nric The NRIC entered by the user. + * @param nric The NRIC entered by the user. * @return index of the patient with the NRIC; -1 otherwise. */ public int getExistingPatient(PatientList patients, String nric) { diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index ac831e88ba..b1e5b81ca1 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -55,8 +55,9 @@ public void addPatient(Patient patient) { /** * Adds a new patient with given details to patients ArrayList. - * @param name Name of the patient. - * @param nric NRIC of the patient. + * + * @param name Name of the patient. + * @param nric NRIC of the patient. * @param dateOfBirth Patient's date of birth. */ public void addNewPatient(String name, String nric, LocalDate dateOfBirth) { diff --git a/src/main/java/seedu/rex/data/hospital/Patient.java b/src/main/java/seedu/rex/data/hospital/Patient.java index 17ccdc3090..25c8771156 100644 --- a/src/main/java/seedu/rex/data/hospital/Patient.java +++ b/src/main/java/seedu/rex/data/hospital/Patient.java @@ -9,10 +9,10 @@ */ public class Patient { + private final Vector appointmentHistory; private String name; private String nric; private LocalDate dateOfBirth; - private final Vector appointmentHistory; public Patient(String name, String nric, LocalDate dateOfBirth) { setName(name); @@ -51,16 +51,17 @@ public Vector getAppointmentHistory() { return appointmentHistory; } - private enum Gender { - MALE, FEMALE - } - /** * Returns the Patient object as a String for printing or writing to a file. + * * @return Patient's details as a String in a particular format. */ @Override public String toString() { return name + ", " + nric + ", " + dateOfBirth.format(DateTimeFormatter.ISO_DATE); } + + private enum Gender { + MALE, FEMALE + } } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 6f0ee19ba6..7e5ced2d36 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -2,12 +2,12 @@ import seedu.rex.commands.Command; import seedu.rex.commands.ExitCommand; -import seedu.rex.storage.Storage; import seedu.rex.data.hospital.Patient; +import seedu.rex.storage.Storage; +import java.time.LocalDate; import java.time.format.DateTimeParseException; import java.util.Scanner; -import java.time.LocalDate; /** * Interacts with user. @@ -84,6 +84,7 @@ public void showDateInputError() { /** * Prints a message to indicate successful addition of a patient. + * * @param patient The newly added Patient. */ public void showPatientAdded(Patient patient) { @@ -104,6 +105,7 @@ public String readCommand() { /** * Reads the name of a new patient from the user. + * * @return The name of the patient to be added. */ public String getPatientName() { @@ -113,6 +115,7 @@ public String getPatientName() { /** * Reads the date of birth of a new patient from the user. + * * @return The date of birth of the patient. */ public LocalDate getPatientDateOfBirth() { From 3a8be297d7ad2f26cc3440dc96e73acdeca15e7b Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 11 Oct 2020 15:44:54 +0800 Subject: [PATCH 027/148] Move patient list related methods to PatientList class --- .../java/seedu/rex/commands/AddCommand.java | 2 +- src/main/java/seedu/rex/commands/Command.java | 30 +------------------ .../seedu/rex/commands/RetrieveCommand.java | 2 +- 3 files changed, 3 insertions(+), 31 deletions(-) diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java index 3e65020e4f..92cb665661 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -29,7 +29,7 @@ public AddCommand(String trimmedCommand) { @Override public void execute(PatientList patients, Ui ui, Storage storage) throws RexException { String nric = extractNric(trimmedCommand, COMMAND_WORD); - if (isExistingPatient(patients, nric)) { + if (patients.isExistingPatient(nric)) { throw new RexException("A patient with this NRIC is already registered!"); } diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index e95af5591f..c7ba54d67f 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -57,7 +57,7 @@ public boolean isInteger(String string) { return false; } try { - double stringAsInteger = Integer.parseInt(string); + int stringAsInteger = Integer.parseInt(string); } catch (NumberFormatException e) { return false; } @@ -88,32 +88,4 @@ public String extractNric(String trimmedCommand, String commandWord) throws RexE return nric; } } - - /** - * Checks if the NRIC entered by the user already exists in the patient list. - * - * @param patients The list of patients. - * @param nric The NRIC entered by the user. - * @return true if NRIC already exists; false otherwise. - */ - public boolean isExistingPatient(PatientList patients, String nric) { - return getExistingPatient(patients, nric) > -1; - } - - /** - * Finds NRIC entered by the user from the patient list. - * Returns -1 if not found. - * - * @param patients The list of patients. - * @param nric The NRIC entered by the user. - * @return index of the patient with the NRIC; -1 otherwise. - */ - public int getExistingPatient(PatientList patients, String nric) { - for (int i = 0; i < patients.getSize(); i++) { - if (patients.getPatientUsingIndex(i).getNric().equals(nric)) { - return i; - } - } - return -1; - } } diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index 93592705d4..afc3965873 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -25,7 +25,7 @@ public RetrieveCommand(String trimmedCommand) { @Override public void execute(PatientList patients, Ui ui, Storage storage) throws RexException { String nric = extractNric(trimmedCommand, COMMAND_WORD); - int index = getExistingPatient(patients, nric); + int index = patients.getExistingPatient(nric); if (index < 0) { throw new RexException("No such patient!"); } From 4acf50e11f77eb0964c82a8d33dc47f46b7e64a8 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 11 Oct 2020 15:45:58 +0800 Subject: [PATCH 028/148] Update JavaDocs --- src/main/java/seedu/rex/Rex.java | 5 ++++- .../seedu/rex/commands/RetrieveCommand.java | 3 +++ src/main/java/seedu/rex/data/PatientList.java | 3 +++ src/main/java/seedu/rex/parser/Parser.java | 17 +++++++++++++++++ src/main/java/seedu/rex/storage/Storage.java | 3 +++ src/main/java/seedu/rex/ui/Ui.java | 5 +++++ 6 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 887d51ed41..551c19098c 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -7,6 +7,9 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +/** + * Main class. + */ public class Rex { private final Storage storage; @@ -14,7 +17,7 @@ public class Rex { private PatientList patients; /** - * Initializes chat bot. + * Initializes Rex. * * @param filePath Path to store and load patients. */ diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index afc3965873..9d46f43da7 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -5,6 +5,9 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +/** + * Retrieves patient details. + */ public class RetrieveCommand extends Command { public static final String COMMAND_WORD = "retrieve"; diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index b1e5b81ca1..41137b2d77 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -5,6 +5,9 @@ import java.time.LocalDate; import java.util.ArrayList; +/** + * Contains ArrayList of patients. + */ public class PatientList { private final ArrayList patients; diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index bdf600fa90..fe3c5cbc00 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -9,7 +9,17 @@ import java.time.LocalDate; +/** + * Makes sense of user command. + */ public class Parser { + + /** + * Reads inputted patient details and return the patient. + * + * @param line Input line to parse to patient details. + * @return Patient object with patient details. + */ public static Patient readPatient(String line) { StringBuilder record = new StringBuilder(line); String name = record.substring(0, record.indexOf(", ")); @@ -22,6 +32,13 @@ public static Patient readPatient(String line) { return new Patient(name, nric, dateOfBirth); } + /** + * Reads and parse command. + * + * @param fullCommand Input string. + * @return Command to be ran. + * @throws RexException if command does not exist. + */ public static Command parse(String fullCommand) throws RexException { String trimmedCommand = fullCommand.trim().toLowerCase(); Command command; diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index cab9913092..9b48f8a399 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -14,6 +14,9 @@ import java.nio.file.Paths; import java.util.ArrayList; +/** + * Loads and saves data to file. + */ public class Storage { public static final String LOAD_ERROR = "Error loading file."; private static final String READ_ERROR = "Error reading file."; diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 7e5ced2d36..70eb6a1cb7 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -131,6 +131,11 @@ public LocalDate getPatientDateOfBirth() { } } + /** + * Shows patient details. + * + * @param patient Patient to show. + */ public void showPatient(Patient patient) { printWithIndent("Patient Details: "); printWithIndent(patient.toString()); From bce0713e6496b926c9e7025fe65622df49e98fc8 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 11 Oct 2020 16:32:48 +0800 Subject: [PATCH 029/148] Update testing files to reflect new features --- src/main/java/seedu/rex/commands/Command.java | 2 +- .../java/seedu/rex/commands/CommandTest.java | 33 +++++++++++++++ text-ui-test/EXPECTED.TXT | 41 +++++++++++++++++++ text-ui-test/input.txt | 11 +++++ 4 files changed, 86 insertions(+), 1 deletion(-) create mode 100644 src/test/java/seedu/rex/commands/CommandTest.java diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index c7ba54d67f..fff24e3cb8 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -67,7 +67,7 @@ public boolean isInteger(String string) { /** * Extracts the NRIC from command inputted by the user. * - * @param trimmedCommand String after command word. + * @param trimmedCommand Command that was trimmed. * @param commandWord Command that was called. * @return Patient's NRIC as a String. * @throws RexException If the NRIC inputted by the user is invalid. diff --git a/src/test/java/seedu/rex/commands/CommandTest.java b/src/test/java/seedu/rex/commands/CommandTest.java new file mode 100644 index 0000000000..25c99799f1 --- /dev/null +++ b/src/test/java/seedu/rex/commands/CommandTest.java @@ -0,0 +1,33 @@ +package seedu.rex.commands; + +import org.junit.jupiter.api.Test; +import seedu.rex.data.exception.RexException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class CommandTest { + + @Test + void isInteger_456456_returnsTrue() { + RetrieveCommand retrieveCommand = new RetrieveCommand(""); + assertTrue(retrieveCommand.isInteger("456456")); + } + + @Test + void extractNric_retrieveS9123456D_returnsS9123456DString() { + RetrieveCommand retrieveCommand = new RetrieveCommand(""); + try { + assertEquals(retrieveCommand.extractNric("retrieve S9123456D", "retrieve"), "S9123456D"); + } catch (RexException e) { + e.printStackTrace(); + } + } + + @Test + void extractNric_retrieveS91D_expectException() { + RetrieveCommand retrieveCommand = new RetrieveCommand(""); + assertThrows(RexException.class, () -> retrieveCommand.extractNric("retrieve S91D", "retrieve")); + } +} \ No newline at end of file diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 9231557ce0..6282a0cb39 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -14,6 +14,47 @@ ☹ OOPS!!! I'm sorry, but I don't know what that means :-( ____________________________________________________________ + ____________________________________________________________ + ☹ OOPS!!! Please enter a valid NRIC after 'add'. + ____________________________________________________________ + + ____________________________________________________________ + ☹ OOPS!!! Invalid NRIC length! + ____________________________________________________________ + + ____________________________________________________________ + ☹ OOPS!!! Beginning character of NRIC must be 'S', 'T', 'F', or 'G'! + ____________________________________________________________ + + ____________________________________________________________ + ☹ OOPS!!! Number sequence of NRIC is invalid! + ____________________________________________________________ + + ____________________________________________________________ + ☹ OOPS!!! Number sequence of NRIC is invalid! + ____________________________________________________________ + + ____________________________________________________________ + Enter patient name: + Enter patient date of birth (YYYY-MM-DD) including the dashes: + ____________________________________________________________ + Error in date format. + ____________________________________________________________ + Enter patient date of birth (YYYY-MM-DD) including the dashes: + ____________________________________________________________ + Patient successfully added: + Trump, S9123456Z, 1960-06-14 + ____________________________________________________________ + + ____________________________________________________________ + ☹ OOPS!!! No such patient! + ____________________________________________________________ + + ____________________________________________________________ + Patient Details: + Trump, S9123456Z, 1960-06-14 + ____________________________________________________________ + ____________________________________________________________ Bye. Hope to see you again soon! ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 1329553ca2..365531fcfe 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,2 +1,13 @@ James Gosling +add +add S9Z +add B1234422B +add S123B422Z +add S123B4222 +add S9123456Z +Trump +06-06-1960 +1960-06-14 +retrieve S9993222A +retrieve S9123456Z bye \ No newline at end of file From 8835d0186639ae4a63f1b74fc7fa7ca1d205a11b Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 11 Oct 2020 16:34:35 +0800 Subject: [PATCH 030/148] Update build.gradle to enable assertions --- build.gradle | 1 + 1 file changed, 1 insertion(+) diff --git a/build.gradle b/build.gradle index c45338f280..1d57a64eab 100644 --- a/build.gradle +++ b/build.gradle @@ -43,4 +43,5 @@ checkstyle { run{ standardInput = System.in + enableAssertions = true } From baf83577c28633127ef18fad6f63b7cd7b5c5c48 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 11 Oct 2020 17:58:11 +0800 Subject: [PATCH 031/148] Improve user guide --- docs/UserGuide.md | 43 ++++++++++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 34b1e0432c..b71a534b00 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -2,41 +2,50 @@ ## Introduction -{Give a product intro} +Hospitalsaurus ReX is a program to help administrative staff to keep track of patients. ## Quick Start -{Give steps to get started quickly} - 1. Ensure that you have Java 11 or above installed. 1. Down the latest version of `Hospitalsaurus ReX` from [here](https://github.com/AY2021S1-CS2113-T16-4/tp). -## Features - -{Give detailed description of each feature} +## Features -### Adding a todo: `todo` -Adds a new item to the list of todo items. +### Adding a patient: `add` +Adds a patient to the database. -Format: `todo n/TODO_NAME d/DEADLINE` +Format: `add NRIC` -* The `DEADLINE` can be in a natural language format. -* The `TODO_NAME` cannot contain punctuation. +* The `NRIC` must be valid. +* Program will prompt name and date of birth to be entered. Example of usage: -`todo n/Write the rest of the User Guide d/next week` +`add S9922312D` + +`add S7423213Z` + +### Retrieve a patient: `retrieve` +Retrieves a patient to the database. + +Format: `retrieve NRIC` -`todo n/Refactor the User Guide to remove passive voice d/13/04/2020` +* The `NRIC` must be valid and in the database. +* Program will show name and date of birth of the patient. + +Example of usage: + +`retrieve S9922312D` + +`retrieve S7423213Z` ## FAQ **Q**: How do I transfer my data to another computer? -**A**: {your answer here} +**A**: Clone the program to the other computer, and copy the data folder over. ## Command Summary -{Give a 'cheat sheet' of commands here} - -* Add todo `todo n/TODO_NAME d/DEADLINE` +* Add patient `add NRIC` +* Retrieve patient `retrieve NRIC` \ No newline at end of file From 4a06f0a54f6a5533094c5fb00ca83065a1d21faf Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 11 Oct 2020 18:04:43 +0800 Subject: [PATCH 032/148] Update developer guide --- docs/DeveloperGuide.md | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 0ec3db103d..9ac78d1200 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -8,26 +8,30 @@ ## Product scope ### Target user profile -{Describe the target user profile} +Administrative staff of hospitals who are overworked from having various responsibilities with repetitive tasks relating to doctors and patients. ### Value proposition -{Describe the value proposition: what problem does it solve?} +Aim: To facilitate the role of the administrative staff and help them automate most of the mundane tasks that they have to do. This enables the admin staff to have a one stop application to handle appointments and fees across different specialised clinics in the hospital. Administrative staff will have more time to help patients or do things that are more meaningful, such as answering queries from patients or doctors. ## 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|admin|enter patient's details and store it|refer to them whenever I require them.| +|v1.0|admin|retrieve patient's details|use them to schedule appointments.| +|v1.0|admin|remove existing patient's details|remove unnecessary information.| +|v1.0|admin|view all appointments of a patient|remind patients of their appointments.| +|v1.0|admin|book an appointment for a patient|let them see the doctor.| ## Non-Functional Requirements -{Give non-functional requirements} +* The program must be easy for admins to use. +* The program must store patient's information. ## Glossary -* *glossary item* - Definition +* *Hospitalsarus Rex* - The name of the program ## Instructions for manual testing From ea120a923a90bb24133a142453f1cad5c5607d2f Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Mon, 12 Oct 2020 10:53:43 +0800 Subject: [PATCH 033/148] Add some assertions --- src/main/java/seedu/rex/Rex.java | 6 ++++++ src/main/java/seedu/rex/commands/RetrieveCommand.java | 5 +++++ src/main/java/seedu/rex/data/PatientList.java | 2 ++ src/main/java/seedu/rex/parser/Parser.java | 4 ++++ src/main/java/seedu/rex/storage/Storage.java | 4 ++++ src/main/java/seedu/rex/ui/Ui.java | 2 ++ 6 files changed, 23 insertions(+) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 551c19098c..67f3d15097 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -22,6 +22,8 @@ public class Rex { * @param filePath Path to store and load patients. */ public Rex(String filePath) { + assert filePath != null; + ui = new Ui(); storage = new Storage(filePath); try { @@ -45,6 +47,10 @@ public static void main(String[] args) { * Runs Rex. */ public void run() { + assert ui != null; + assert patients != null; + assert storage != null; + ui.showWelcome(); boolean isExit = false; while (!isExit) { diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index 9d46f43da7..09c51b8b7c 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -27,8 +27,13 @@ public RetrieveCommand(String trimmedCommand) { */ @Override public void execute(PatientList patients, Ui ui, Storage storage) throws RexException { + assert patients != null; + assert ui != null; + assert storage != null; + String nric = extractNric(trimmedCommand, COMMAND_WORD); int index = patients.getExistingPatient(nric); + assert index > -2; if (index < 0) { throw new RexException("No such patient!"); } diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index 41137b2d77..4f50b4c820 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -85,6 +85,8 @@ public boolean isExistingPatient(String nric) { * @return index of the patient with the NRIC; -1 otherwise. */ public int getExistingPatient(String nric) { + assert nric != null; + for (int i = 0; i < getSize(); i++) { if (getPatientUsingIndex(i).getNric().equals(nric)) { return i; diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index fe3c5cbc00..ae25bee7a3 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -21,6 +21,8 @@ public class Parser { * @return Patient object with patient details. */ public static Patient readPatient(String line) { + assert line != null; + StringBuilder record = new StringBuilder(line); String name = record.substring(0, record.indexOf(", ")); // Deletes first comma separator. @@ -40,6 +42,8 @@ public static Patient readPatient(String line) { * @throws RexException if command does not exist. */ public static Command parse(String fullCommand) throws RexException { + assert fullCommand != null; + String trimmedCommand = fullCommand.trim().toLowerCase(); Command command; if (trimmedCommand.equals(ExitCommand.COMMAND_WORD)) { diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index 9b48f8a399..29feff8dee 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -32,6 +32,8 @@ public class Storage { * @param filePath Full file path. */ public Storage(String filePath) { + assert filePath != null; + int index = filePath.lastIndexOf("/"); folder = filePath.substring(0, index); file = filePath.substring(index + 1); @@ -75,6 +77,8 @@ public ArrayList load() throws RexException { * @throws RexException If there is problem writing or saving file. */ public void save(PatientList patients) throws RexException { + assert patients != null; + StringBuilder fileContent = new StringBuilder(); for (int i = 0; i < patients.getSize(); i++) { diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 70eb6a1cb7..0408dd5ed6 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -137,6 +137,8 @@ public LocalDate getPatientDateOfBirth() { * @param patient Patient to show. */ public void showPatient(Patient patient) { + assert patient != null; + printWithIndent("Patient Details: "); printWithIndent(patient.toString()); } From f611779ad7615fb90d6eb4185fa3e9465cdaee1b Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Mon, 12 Oct 2020 11:09:51 +0800 Subject: [PATCH 034/148] Improve assertions --- src/main/java/seedu/rex/Rex.java | 8 ++++---- src/main/java/seedu/rex/commands/RetrieveCommand.java | 8 ++++---- src/main/java/seedu/rex/data/PatientList.java | 2 +- src/main/java/seedu/rex/parser/Parser.java | 4 ++-- src/main/java/seedu/rex/storage/Storage.java | 4 ++-- src/main/java/seedu/rex/ui/Ui.java | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 67f3d15097..d616db510d 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -22,7 +22,7 @@ public class Rex { * @param filePath Path to store and load patients. */ public Rex(String filePath) { - assert filePath != null; + assert filePath != null && !filePath.equals("") : "File path cannot be empty!"; ui = new Ui(); storage = new Storage(filePath); @@ -47,9 +47,9 @@ public static void main(String[] args) { * Runs Rex. */ public void run() { - assert ui != null; - assert patients != null; - assert storage != null; + assert ui != null : "ui is null"; + assert patients != null : "patient ArrayList is null"; + assert storage != null : "storage is null"; ui.showWelcome(); boolean isExit = false; diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index 09c51b8b7c..5628afd8d5 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -27,13 +27,13 @@ public RetrieveCommand(String trimmedCommand) { */ @Override public void execute(PatientList patients, Ui ui, Storage storage) throws RexException { - assert patients != null; - assert ui != null; - assert storage != null; + assert patients != null : "patient ArrayList is null"; + assert ui != null : "ui is null"; + assert storage != null : "storage is null"; String nric = extractNric(trimmedCommand, COMMAND_WORD); int index = patients.getExistingPatient(nric); - assert index > -2; + assert index > -2 : "Unexpected index!"; if (index < 0) { throw new RexException("No such patient!"); } diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index 4f50b4c820..9efe1b6aea 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -85,7 +85,7 @@ public boolean isExistingPatient(String nric) { * @return index of the patient with the NRIC; -1 otherwise. */ public int getExistingPatient(String nric) { - assert nric != null; + assert nric != null && !nric.equals("") : "Cannot get patient of null nric"; for (int i = 0; i < getSize(); i++) { if (getPatientUsingIndex(i).getNric().equals(nric)) { diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index ae25bee7a3..14e01ee22b 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -21,7 +21,7 @@ public class Parser { * @return Patient object with patient details. */ public static Patient readPatient(String line) { - assert line != null; + assert line != null && !line.equals("") : "No patients to read!"; StringBuilder record = new StringBuilder(line); String name = record.substring(0, record.indexOf(", ")); @@ -42,7 +42,7 @@ public static Patient readPatient(String line) { * @throws RexException if command does not exist. */ public static Command parse(String fullCommand) throws RexException { - assert fullCommand != null; + assert fullCommand != null && !fullCommand.equals("") : "No command to parse!"; String trimmedCommand = fullCommand.trim().toLowerCase(); Command command; diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index 29feff8dee..42a8635228 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -32,7 +32,7 @@ public class Storage { * @param filePath Full file path. */ public Storage(String filePath) { - assert filePath != null; + assert filePath != null && !filePath.equals("") : "Invalid filepath"; int index = filePath.lastIndexOf("/"); folder = filePath.substring(0, index); @@ -77,7 +77,7 @@ public ArrayList load() throws RexException { * @throws RexException If there is problem writing or saving file. */ public void save(PatientList patients) throws RexException { - assert patients != null; + assert patients != null : "Saving null patients ArrayList"; StringBuilder fileContent = new StringBuilder(); diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 0408dd5ed6..51e32816f1 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -137,7 +137,7 @@ public LocalDate getPatientDateOfBirth() { * @param patient Patient to show. */ public void showPatient(Patient patient) { - assert patient != null; + assert patient != null : "Cannot show null patient!"; printWithIndent("Patient Details: "); printWithIndent(patient.toString()); From a88c338b6e3be79c6f1f62c9d88cad70848dac0a Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 13 Oct 2020 00:45:49 +0800 Subject: [PATCH 035/148] Add basic logging --- src/main/java/seedu/rex/Rex.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index d616db510d..d2a2a4b1e4 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -7,6 +7,9 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +import java.util.logging.Level; +import java.util.logging.Logger; + /** * Main class. */ @@ -15,6 +18,7 @@ public class Rex { private final Storage storage; private final Ui ui; private PatientList patients; + private static Logger logger; /** * Initializes Rex. @@ -26,9 +30,13 @@ public Rex(String filePath) { ui = new Ui(); storage = new Storage(filePath); + logger = Logger.getLogger("Rex"); try { + logger.log(Level.INFO, "going to load patients"); patients = new PatientList(storage.load()); + logger.log(Level.INFO, "loaded patients"); } catch (RexException e) { + logger.log(Level.INFO, "patients loading error"); ui.showLoadingError(); patients = new PatientList(); } From c7ee508922370e1f7ff46bcc495e9d7d93852326 Mon Sep 17 00:00:00 2001 From: randynyl <56857427+randynyl@users.noreply.github.com> Date: Wed, 14 Oct 2020 03:51:16 +0800 Subject: [PATCH 036/148] Add create appointment function --- src/main/java/seedu/rex/Rex.java | 13 ++++++- .../java/seedu/rex/commands/AddCommand.java | 6 ++- .../java/seedu/rex/commands/BookCommand.java | 32 ++++++++++++++++ src/main/java/seedu/rex/commands/Command.java | 5 ++- .../commands/CreateAppointmentCommand.java | 37 +++++++++++++++++++ .../java/seedu/rex/commands/ExitCommand.java | 6 ++- .../seedu/rex/commands/RetrieveCommand.java | 6 ++- .../java/seedu/rex/data/AppointmentList.java | 26 +++++++++++++ .../seedu/rex/data/hospital/Appointment.java | 32 ++++++++++++++++ src/main/java/seedu/rex/parser/Parser.java | 9 +++-- src/main/java/seedu/rex/ui/Ui.java | 15 ++++++++ 11 files changed, 178 insertions(+), 9 deletions(-) create mode 100644 src/main/java/seedu/rex/commands/BookCommand.java create mode 100644 src/main/java/seedu/rex/commands/CreateAppointmentCommand.java create mode 100644 src/main/java/seedu/rex/data/AppointmentList.java diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index d2a2a4b1e4..c74d231f9c 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -1,12 +1,16 @@ package seedu.rex; import seedu.rex.commands.Command; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; import seedu.rex.parser.Parser; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +import java.io.IOException; +import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; @@ -18,6 +22,7 @@ public class Rex { private final Storage storage; private final Ui ui; private PatientList patients; + private ArrayList appointments; private static Logger logger; /** @@ -31,6 +36,7 @@ public Rex(String filePath) { ui = new Ui(); storage = new Storage(filePath); logger = Logger.getLogger("Rex"); + appointments = new ArrayList<>(); try { logger.log(Level.INFO, "going to load patients"); patients = new PatientList(storage.load()); @@ -66,7 +72,7 @@ public void run() { String fullCommand = ui.readCommand(); ui.showLine(); // show the divider line ("_______") Command c = Parser.parse(fullCommand); - c.execute(patients, ui, storage); + c.execute(patients, appointments, ui, storage); isExit = c.isExit(); } catch (RexException e) { ui.showError(e.getMessage()); @@ -74,5 +80,10 @@ public void run() { ui.showLine(); } } + try { + storage.saveAppointments(appointments); + } catch (IOException e) { + ui.showError(e.getMessage()); + } } } diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java index 92cb665661..83b7d8003d 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -1,10 +1,14 @@ package seedu.rex.commands; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +import java.util.ArrayList; + /** * Adds a patient to the list of patients. */ @@ -27,7 +31,7 @@ public AddCommand(String trimmedCommand) { * to save successfully, or the NRIC already exists in the patient list. */ @Override - public void execute(PatientList patients, Ui ui, Storage storage) throws RexException { + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { String nric = extractNric(trimmedCommand, COMMAND_WORD); if (patients.isExistingPatient(nric)) { throw new RexException("A patient with this NRIC is already registered!"); diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java new file mode 100644 index 0000000000..d913ce1d51 --- /dev/null +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -0,0 +1,32 @@ +package seedu.rex.commands; + +import seedu.rex.data.AppointmentList; +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +import java.util.ArrayList; + +public class BookCommand extends Command { + + public static final String COMMAND_WORD = "book"; + private final String trimmedCommand; + + public BookCommand(String trimmedCommand) { + this.trimmedCommand = trimmedCommand; + } + + @Override + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { + String nric = extractNric(trimmedCommand, COMMAND_WORD); + if (!patients.isExistingPatient(nric)) { + ui.printPatientNotFound(nric); + patients.addNewPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); + ui.showLine(); + } + + + } +} diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index fff24e3cb8..ffe47e4354 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -1,10 +1,13 @@ package seedu.rex.commands; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +import java.util.ArrayList; import java.util.Set; /** @@ -35,7 +38,7 @@ public Command() { * @param storage Storage object. * @throws RexException If there is issue executing command. */ - public abstract void execute(PatientList patients, Ui ui, Storage storage) throws RexException; + public abstract void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException; /** * Returns Rex's exit status. diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java new file mode 100644 index 0000000000..de3046967f --- /dev/null +++ b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java @@ -0,0 +1,37 @@ +package seedu.rex.commands; + +import seedu.rex.data.AppointmentList; +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import java.util.ArrayList; + +public class CreateAppointmentCommand extends Command { + + public static final String COMMAND_WORD = "create"; + private final String trimmedCommand; + + public CreateAppointmentCommand(String trimmedCommand) { + this.trimmedCommand = trimmedCommand; + } + + + @Override + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { + String date = ui.getNewAppointmentDate(); + try { + Appointment newAppointment = new Appointment(LocalDate.parse(date)); + appointments.add(newAppointment); + ui.showAppointmentCreatedMessage(); + + } catch (DateTimeParseException e) { + ui.showDateInputError(); + } + + } +} diff --git a/src/main/java/seedu/rex/commands/ExitCommand.java b/src/main/java/seedu/rex/commands/ExitCommand.java index b74724820e..a71ad74696 100644 --- a/src/main/java/seedu/rex/commands/ExitCommand.java +++ b/src/main/java/seedu/rex/commands/ExitCommand.java @@ -1,9 +1,13 @@ package seedu.rex.commands; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; +import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +import java.util.ArrayList; + /** * Exits program. */ @@ -20,7 +24,7 @@ public class ExitCommand extends Command { * @param storage Storage object. */ @Override - public void execute(PatientList patients, Ui ui, Storage storage) { + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) { isExit = true; ui.showExit(); } diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index 5628afd8d5..78acf97fd9 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -1,10 +1,14 @@ package seedu.rex.commands; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +import java.util.ArrayList; + /** * Retrieves patient details. */ @@ -26,7 +30,7 @@ public RetrieveCommand(String trimmedCommand) { * @throws RexException If there is issue executing command. */ @Override - public void execute(PatientList patients, Ui ui, Storage storage) throws RexException { + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; assert storage != null : "storage is null"; diff --git a/src/main/java/seedu/rex/data/AppointmentList.java b/src/main/java/seedu/rex/data/AppointmentList.java new file mode 100644 index 0000000000..9a16100e57 --- /dev/null +++ b/src/main/java/seedu/rex/data/AppointmentList.java @@ -0,0 +1,26 @@ +package seedu.rex.data; + +import seedu.rex.data.hospital.Appointment; +import seedu.rex.data.hospital.Patient; + +import java.util.ArrayList; + +public class AppointmentList { + + private final ArrayList appointments; + + public AppointmentList() { + appointments = new ArrayList<>(); + } + + /** + * Initializes patients ArrayList using parameter. + * + * @param appointments Appointments list to use. + */ + public AppointmentList(ArrayList appointments) { + this.appointments = appointments; + } + + +} diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java index cce2540712..d1468f55e3 100644 --- a/src/main/java/seedu/rex/data/hospital/Appointment.java +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -10,6 +10,12 @@ public class Appointment { private Doctor doctor; private String notes; private Prescription prescription; + private Boolean isBooked; + + public Appointment(LocalDate date) { + this.date = date; + isBooked = false; + } public LocalDate getDate() { return date; @@ -59,4 +65,30 @@ public void setPrescription(Prescription prescription) { this.prescription = prescription; } + public void book(Patient patient) { + this.patient = patient; + isBooked = true; + } + + public void removeBooking() { + this.patient = null; + isBooked = false; + } + + @Override + public String toString() { + String date = this.date.toString(); + String bookedStatus, patientNric; + if (isBooked) { + bookedStatus = "booked"; + } else { + bookedStatus = "available"; + } + if (patient != null) { + patientNric = patient.getNric(); + } else { + patientNric = null; + } + return date + ", " + bookedStatus + ", " + patientNric; + } } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 14e01ee22b..1b64033176 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,9 +1,6 @@ package seedu.rex.parser; -import seedu.rex.commands.AddCommand; -import seedu.rex.commands.Command; -import seedu.rex.commands.ExitCommand; -import seedu.rex.commands.RetrieveCommand; +import seedu.rex.commands.*; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Patient; @@ -52,6 +49,10 @@ public static Command parse(String fullCommand) throws RexException { command = new AddCommand(trimmedCommand); } else if (trimmedCommand.contains(RetrieveCommand.COMMAND_WORD)) { command = new RetrieveCommand(trimmedCommand); + } else if (trimmedCommand.contains(BookCommand.COMMAND_WORD)) { + command = new BookCommand(trimmedCommand); + } else if (trimmedCommand.contains(CreateAppointmentCommand.COMMAND_WORD)) { + command = new CreateAppointmentCommand(trimmedCommand); } else { throw new RexException(Command.COMMAND_ERROR); } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 51e32816f1..2c2d27e841 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -142,4 +142,19 @@ public void showPatient(Patient patient) { printWithIndent("Patient Details: "); printWithIndent(patient.toString()); } + + public void printPatientNotFound(String nric) { + printWithIndent("Patient " + nric + " not found in database!"); + } + + public String getNewAppointmentDate() { + printWithIndent("Please enter the date of appointment in YYYY-MM-DD."); + showLine(); + return in.nextLine(); + } + + public void showAppointmentCreatedMessage() { + showLine(); + printWithIndent("New appointment created!"); + } } From 31fda17b77cf07a92a7a066533aa9f2709aa824e Mon Sep 17 00:00:00 2001 From: randynyl <56857427+randynyl@users.noreply.github.com> Date: Wed, 14 Oct 2020 04:21:39 +0800 Subject: [PATCH 037/148] Add loading and storing of appointments --- src/main/java/seedu/rex/Rex.java | 14 ++++-- src/main/java/seedu/rex/data/PatientList.java | 2 + src/main/java/seedu/rex/parser/Parser.java | 14 ++++++ src/main/java/seedu/rex/storage/Storage.java | 44 +++++++++++++++---- 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index c74d231f9c..ec72dca79f 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -9,6 +9,7 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.logging.Level; @@ -21,7 +22,7 @@ public class Rex { private final Storage storage; private final Ui ui; - private PatientList patients; + private static PatientList patients; private ArrayList appointments; private static Logger logger; @@ -36,13 +37,14 @@ public Rex(String filePath) { ui = new Ui(); storage = new Storage(filePath); logger = Logger.getLogger("Rex"); - appointments = new ArrayList<>(); + try { logger.log(Level.INFO, "going to load patients"); patients = new PatientList(storage.load()); + appointments = storage.loadAppointments(); logger.log(Level.INFO, "loaded patients"); - } catch (RexException e) { - logger.log(Level.INFO, "patients loading error"); + } catch (RexException | FileNotFoundException e) { + logger.log(Level.INFO, "patients or appointments loading error"); ui.showLoadingError(); patients = new PatientList(); } @@ -86,4 +88,8 @@ public void run() { ui.showError(e.getMessage()); } } + + public static PatientList getPatients() { + return patients; + } } diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index 9efe1b6aea..88ce89c132 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -94,4 +94,6 @@ public int getExistingPatient(String nric) { } return -1; } + + } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 1b64033176..619e183e95 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,7 +1,9 @@ package seedu.rex.parser; +import seedu.rex.Rex; import seedu.rex.commands.*; import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; import java.time.LocalDate; @@ -31,6 +33,18 @@ public static Patient readPatient(String line) { return new Patient(name, nric, dateOfBirth); } + public static Appointment readAppointment(String line) { + String[] appointmentComponents = line.split(", "); + LocalDate date = LocalDate.parse(appointmentComponents[0]); + String bookedStatus = appointmentComponents[1]; + String nric = appointmentComponents[2]; + Appointment appointment = new Appointment(date); + if (bookedStatus.equals("booked")) { + appointment.book(Rex.getPatients().getPatientUsingIndex(Rex.getPatients().getExistingPatient(nric))); + } + return appointment; + } + /** * Reads and parse command. * diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index 42a8635228..4dd550359f 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -1,18 +1,20 @@ package seedu.rex.storage; +import seedu.rex.Rex; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; import seedu.rex.parser.Parser; -import java.io.BufferedReader; -import java.io.BufferedWriter; -import java.io.File; -import java.io.IOException; +import java.io.*; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; +import java.time.LocalDate; import java.util.ArrayList; +import java.util.Scanner; +import java.util.Vector; /** * Loads and saves data to file. @@ -25,6 +27,7 @@ public class Storage { private final String folder; private final String file; + private static final String APPOINTMENTS_FILE = "appointments.txt"; /** * Initializes path of folder and file. @@ -79,12 +82,13 @@ public ArrayList load() throws RexException { public void save(PatientList patients) throws RexException { assert patients != null : "Saving null patients ArrayList"; - StringBuilder fileContent = new StringBuilder(); + StringBuilder patientsFileContent = new StringBuilder(); for (int i = 0; i < patients.getSize(); i++) { // Need to format tasks - fileContent.append(patients.getPatientUsingIndex(i)); - fileContent.append('\n'); + patientsFileContent.append(patients.getPatientUsingIndex(i)); + patientsFileContent.append('\n'); + Vector patientAppointments = patients.getPatientUsingIndex(i).getAppointmentHistory(); } Path folderPath = Paths.get(folder); @@ -95,10 +99,34 @@ public void save(PatientList patients) throws RexException { Path filePath = Paths.get(folder, file); try { BufferedWriter bufferedWriter = Files.newBufferedWriter(filePath); - bufferedWriter.write(fileContent.toString()); + bufferedWriter.write(patientsFileContent.toString()); bufferedWriter.close(); } catch (IOException e) { throw new RexException(WRITE_ERROR); } } + + public void saveAppointments(ArrayList appointments) throws IOException { + StringBuilder textToWrite = new StringBuilder(); + for (Appointment appointment : appointments) { + textToWrite.append(appointment.toString()); + textToWrite.append(System.lineSeparator()); + } + String appointmentsFilePath = folder + "/" + APPOINTMENTS_FILE; + + FileWriter fw = new FileWriter(appointmentsFilePath); + fw.write(String.valueOf(textToWrite)); + fw.close(); + } + + public ArrayList loadAppointments() throws FileNotFoundException { + ArrayList appointments = new ArrayList<>(); + File appointmentsFile = new File(folder + "/" + APPOINTMENTS_FILE); + Scanner s = new Scanner(appointmentsFile); + while (s.hasNext()) { + Appointment appointment = Parser.readAppointment(s.nextLine()); + appointments.add(appointment); + } + return appointments; + } } From 76d29b85e66f556a00bc7477495a031462cbb6f8 Mon Sep 17 00:00:00 2001 From: randynyl <56857427+randynyl@users.noreply.github.com> Date: Wed, 14 Oct 2020 05:00:44 +0800 Subject: [PATCH 038/148] Add book functionality --- src/main/java/seedu/rex/Rex.java | 10 +++++--- .../java/seedu/rex/commands/BookCommand.java | 15 ++++++++++++ src/main/java/seedu/rex/data/PatientList.java | 9 ++++++++ .../seedu/rex/data/hospital/Appointment.java | 4 ++++ src/main/java/seedu/rex/ui/Ui.java | 23 +++++++++++++++++++ 5 files changed, 58 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index ec72dca79f..624d55d008 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -41,12 +41,16 @@ public Rex(String filePath) { try { logger.log(Level.INFO, "going to load patients"); patients = new PatientList(storage.load()); - appointments = storage.loadAppointments(); logger.log(Level.INFO, "loaded patients"); - } catch (RexException | FileNotFoundException e) { - logger.log(Level.INFO, "patients or appointments loading error"); + appointments = storage.loadAppointments(); + logger.log(Level.INFO, "loaded appointments"); + } catch (RexException e) { + logger.log(Level.INFO, "patients loading error"); ui.showLoadingError(); patients = new PatientList(); + } catch (FileNotFoundException e) { + logger.log(Level.INFO, "No appointments found. Creating new appointments list."); + appointments = new ArrayList<>(); } } diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index d913ce1d51..720c0b5652 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -7,6 +7,8 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +import java.time.LocalDate; +import java.time.format.DateTimeParseException; import java.util.ArrayList; public class BookCommand extends Command { @@ -24,8 +26,21 @@ public void execute(PatientList patients, ArrayList appointments, U if (!patients.isExistingPatient(nric)) { ui.printPatientNotFound(nric); patients.addNewPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); + ui.showPatientAdded(patients.getPatientUsingIndex(patients.getSize() - 1)); + storage.save(patients); ui.showLine(); } + String dateSelected = ui.getAppointmentToBook(appointments); + try { + for (Appointment appointment : appointments) { + if (appointment.getDate().equals(LocalDate.parse(dateSelected))) { + appointment.book(patients.getPatientFromNric(nric)); + ui.showAppointmentBookedMessage(appointment); + } + } + } catch (DateTimeParseException e) { + ui.showDateInputError(); + } } diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index 88ce89c132..91a95d4027 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -95,5 +95,14 @@ public int getExistingPatient(String nric) { return -1; } + public Patient getPatientFromNric(String nric) { + for (Patient patient : patients) { + if (patient.getNric().equals(nric)) { + return patient; + } + } + return null; + } + } diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java index d1468f55e3..9f79727a1b 100644 --- a/src/main/java/seedu/rex/data/hospital/Appointment.java +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -65,6 +65,10 @@ public void setPrescription(Prescription prescription) { this.prescription = prescription; } + public Boolean isBooked() { + return isBooked; + } + public void book(Patient patient) { this.patient = patient; isBooked = true; diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 2c2d27e841..abcf9ee8c5 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -2,11 +2,13 @@ import seedu.rex.commands.Command; import seedu.rex.commands.ExitCommand; +import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; import seedu.rex.storage.Storage; import java.time.LocalDate; import java.time.format.DateTimeParseException; +import java.util.ArrayList; import java.util.Scanner; /** @@ -157,4 +159,25 @@ public void showAppointmentCreatedMessage() { showLine(); printWithIndent("New appointment created!"); } + + public String getAppointmentToBook(ArrayList appointments) { + showLine(); + printWithIndent("Here are the list of available appointments."); + int counter = 1; + for (Appointment appointment : appointments) { + if (!appointment.isBooked()) { + printWithIndent(String.valueOf(counter) + ". " + appointment.getDate().toString()); + counter++; + } + } + printWithIndent("Please enter the date of appointment to book in YYYY-MM-DD"); + showLine(); + return in.nextLine(); + } + + public void showAppointmentBookedMessage(Appointment appointment) { + showLine(); + printWithIndent("Appointment on " + appointment.getDate().toString() + " booked!"); + + } } From 7e0b86db92fe2a0d6b7c7839b23016f54fed3f45 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 14 Oct 2020 10:35:22 +0800 Subject: [PATCH 039/148] Fix checkstyle errors --- src/main/java/seedu/rex/Rex.java | 13 ++++++------- src/main/java/seedu/rex/commands/AddCommand.java | 4 ++-- src/main/java/seedu/rex/commands/BookCommand.java | 4 ++-- src/main/java/seedu/rex/commands/Command.java | 4 ++-- .../rex/commands/CreateAppointmentCommand.java | 4 ++-- src/main/java/seedu/rex/commands/ExitCommand.java | 1 - .../java/seedu/rex/commands/RetrieveCommand.java | 4 ++-- src/main/java/seedu/rex/data/AppointmentList.java | 1 - .../java/seedu/rex/data/hospital/Appointment.java | 3 ++- src/main/java/seedu/rex/parser/Parser.java | 7 ++++++- src/main/java/seedu/rex/storage/Storage.java | 12 +++++++----- src/main/java/seedu/rex/ui/Ui.java | 2 +- 12 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 624d55d008..02fab1bf19 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -1,7 +1,6 @@ package seedu.rex; import seedu.rex.commands.Command; -import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -20,11 +19,11 @@ */ public class Rex { + private static PatientList patients; + private static Logger logger; private final Storage storage; private final Ui ui; - private static PatientList patients; private ArrayList appointments; - private static Logger logger; /** * Initializes Rex. @@ -63,6 +62,10 @@ public static void main(String[] args) { new Rex("data/patients.txt").run(); } + public static PatientList getPatients() { + return patients; + } + /** * Runs Rex. */ @@ -92,8 +95,4 @@ public void run() { ui.showError(e.getMessage()); } } - - public static PatientList getPatients() { - return patients; - } } diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java index 83b7d8003d..ee645ea9fd 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -1,6 +1,5 @@ package seedu.rex.commands; -import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -31,7 +30,8 @@ public AddCommand(String trimmedCommand) { * to save successfully, or the NRIC already exists in the patient list. */ @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + throws RexException { String nric = extractNric(trimmedCommand, COMMAND_WORD); if (patients.isExistingPatient(nric)) { throw new RexException("A patient with this NRIC is already registered!"); diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index 720c0b5652..db4262c2e0 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -1,6 +1,5 @@ package seedu.rex.commands; -import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -21,7 +20,8 @@ public BookCommand(String trimmedCommand) { } @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + throws RexException { String nric = extractNric(trimmedCommand, COMMAND_WORD); if (!patients.isExistingPatient(nric)) { ui.printPatientNotFound(nric); diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index ffe47e4354..4b10266a7d 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -1,6 +1,5 @@ package seedu.rex.commands; -import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -38,7 +37,8 @@ public Command() { * @param storage Storage object. * @throws RexException If there is issue executing command. */ - public abstract void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException; + public abstract void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + throws RexException; /** * Returns Rex's exit status. diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java index de3046967f..1a5fae91ef 100644 --- a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java @@ -1,6 +1,5 @@ package seedu.rex.commands; -import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -22,7 +21,8 @@ public CreateAppointmentCommand(String trimmedCommand) { @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + throws RexException { String date = ui.getNewAppointmentDate(); try { Appointment newAppointment = new Appointment(LocalDate.parse(date)); diff --git a/src/main/java/seedu/rex/commands/ExitCommand.java b/src/main/java/seedu/rex/commands/ExitCommand.java index a71ad74696..9e71350eb4 100644 --- a/src/main/java/seedu/rex/commands/ExitCommand.java +++ b/src/main/java/seedu/rex/commands/ExitCommand.java @@ -1,6 +1,5 @@ package seedu.rex.commands; -import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index 78acf97fd9..c5bb148e1c 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -1,6 +1,5 @@ package seedu.rex.commands; -import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -30,7 +29,8 @@ public RetrieveCommand(String trimmedCommand) { * @throws RexException If there is issue executing command. */ @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; assert storage != null : "storage is null"; diff --git a/src/main/java/seedu/rex/data/AppointmentList.java b/src/main/java/seedu/rex/data/AppointmentList.java index 9a16100e57..3ea64827ec 100644 --- a/src/main/java/seedu/rex/data/AppointmentList.java +++ b/src/main/java/seedu/rex/data/AppointmentList.java @@ -1,7 +1,6 @@ package seedu.rex.data; import seedu.rex.data.hospital.Appointment; -import seedu.rex.data.hospital.Patient; import java.util.ArrayList; diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java index 9f79727a1b..a8432257e2 100644 --- a/src/main/java/seedu/rex/data/hospital/Appointment.java +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -82,7 +82,8 @@ public void removeBooking() { @Override public String toString() { String date = this.date.toString(); - String bookedStatus, patientNric; + String bookedStatus; + String patientNric; if (isBooked) { bookedStatus = "booked"; } else { diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 619e183e95..a0a2ff5841 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,7 +1,12 @@ package seedu.rex.parser; import seedu.rex.Rex; -import seedu.rex.commands.*; +import seedu.rex.commands.AddCommand; +import seedu.rex.commands.BookCommand; +import seedu.rex.commands.Command; +import seedu.rex.commands.CreateAppointmentCommand; +import seedu.rex.commands.ExitCommand; +import seedu.rex.commands.RetrieveCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index 4dd550359f..770888bf67 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -1,17 +1,20 @@ package seedu.rex.storage; -import seedu.rex.Rex; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; import seedu.rex.parser.Parser; -import java.io.*; +import java.io.BufferedReader; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.time.LocalDate; import java.util.ArrayList; import java.util.Scanner; import java.util.Vector; @@ -24,10 +27,9 @@ public class Storage { private static final String READ_ERROR = "Error reading file."; private static final String DIRECTORY_ERROR = "Error creating directory."; private static final String WRITE_ERROR = "Error writing file."; - + private static final String APPOINTMENTS_FILE = "appointments.txt"; private final String folder; private final String file; - private static final String APPOINTMENTS_FILE = "appointments.txt"; /** * Initializes path of folder and file. diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index abcf9ee8c5..f304d97203 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -166,7 +166,7 @@ public String getAppointmentToBook(ArrayList appointments) { int counter = 1; for (Appointment appointment : appointments) { if (!appointment.isBooked()) { - printWithIndent(String.valueOf(counter) + ". " + appointment.getDate().toString()); + printWithIndent(counter + ". " + appointment.getDate().toString()); counter++; } } From a7a9fbef3839cecdce9c97eaba6c0caf9856f7b9 Mon Sep 17 00:00:00 2001 From: GoldenCorgi <42860714+GoldenCorgi@users.noreply.github.com> Date: Wed, 14 Oct 2020 13:05:19 +0800 Subject: [PATCH 040/148] added ability to edit patient details --- .../java/seedu/rex/commands/EditCommand.java | 45 +++++++++++++++++++ src/main/java/seedu/rex/data/PatientList.java | 17 +++++++ src/main/java/seedu/rex/parser/Parser.java | 9 ++-- src/main/java/seedu/rex/ui/Ui.java | 11 +++++ 4 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 src/main/java/seedu/rex/commands/EditCommand.java diff --git a/src/main/java/seedu/rex/commands/EditCommand.java b/src/main/java/seedu/rex/commands/EditCommand.java new file mode 100644 index 0000000000..0ce17d063d --- /dev/null +++ b/src/main/java/seedu/rex/commands/EditCommand.java @@ -0,0 +1,45 @@ +package seedu.rex.commands; + +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +import java.util.ArrayList; + +/** + * Edit a patient from the list of patients. + */ +public class EditCommand extends Command { + + public static final String COMMAND_WORD = "edit"; + private final String trimmedCommand; + + public EditCommand(String trimmedCommand) { + this.trimmedCommand = trimmedCommand; + } + + /** + * Edit an existing patient to the patient list using details inputted by the user. + * + * @param patients List of patients. + * @param ui Ui object of the program. + * @param storage Storage object used for saving data to files. + * @throws RexException If there is an error in the NRIC inputted by the user, the data fails + * to save successfully, or the NRIC already exists in the patient list. + */ + @Override + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + throws RexException { + String nric = extractNric(trimmedCommand, COMMAND_WORD); + if (!patients.isExistingPatient(nric)) { + throw new RexException("A patient with this NRIC has not been registered!"); + } + + int idx = patients.EditExistingPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); + ui.showLine(); + ui.showPatientEditted(patients.getPatientUsingIndex(idx)); + storage.save(patients); + } +} \ No newline at end of file diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index 91a95d4027..a690552635 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -67,6 +67,23 @@ public void addNewPatient(String name, String nric, LocalDate dateOfBirth) { addPatient(new Patient(name, nric, dateOfBirth)); } + /** + * Edit an existing patient with given details to patients ArrayList. + * + * @param name Name of the patient. + * @param nric NRIC of the patient. + * @param dateOfBirth Patient's date of birth. + */ + public int EditExistingPatient(String name, String nric, LocalDate dateOfBirth) { + int idx = getExistingPatient(nric); + patients.remove(idx); + Patient patient = (new Patient(name, nric, dateOfBirth)); + patients.add(idx,patient); + return idx; + } + + + /** * Checks if the NRIC entered by the user already exists in the patient list. * diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index a0a2ff5841..27b1840cd2 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,12 +1,7 @@ package seedu.rex.parser; import seedu.rex.Rex; -import seedu.rex.commands.AddCommand; -import seedu.rex.commands.BookCommand; -import seedu.rex.commands.Command; -import seedu.rex.commands.CreateAppointmentCommand; -import seedu.rex.commands.ExitCommand; -import seedu.rex.commands.RetrieveCommand; +import seedu.rex.commands.*; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; @@ -72,6 +67,8 @@ public static Command parse(String fullCommand) throws RexException { command = new BookCommand(trimmedCommand); } else if (trimmedCommand.contains(CreateAppointmentCommand.COMMAND_WORD)) { command = new CreateAppointmentCommand(trimmedCommand); + } else if (trimmedCommand.contains(EditCommand.COMMAND_WORD)) { + command = new EditCommand(trimmedCommand); } else { throw new RexException(Command.COMMAND_ERROR); } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index f304d97203..c2b052942c 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -94,6 +94,17 @@ public void showPatientAdded(Patient patient) { printWithIndent(patient.toString()); } + /** + * Prints a message to indicate successful editting of a patient. + * + * @param patient The newly editted Patient. + */ + + public void showPatientEditted(Patient patient) { + printWithIndent("Patient successfully editted: "); + printWithIndent(patient.toString()); + } + /** * Reads command from user. From 0217d8e7efc739efc14d7f1181d4ab61b4b6b4db Mon Sep 17 00:00:00 2001 From: GoldenCorgi <42860714+GoldenCorgi@users.noreply.github.com> Date: Wed, 14 Oct 2020 13:12:35 +0800 Subject: [PATCH 041/148] fixed checkstyle for editpatient functions --- src/main/java/seedu/rex/commands/EditCommand.java | 2 +- src/main/java/seedu/rex/data/PatientList.java | 2 +- src/main/java/seedu/rex/parser/Parser.java | 8 +++++++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/rex/commands/EditCommand.java b/src/main/java/seedu/rex/commands/EditCommand.java index 0ce17d063d..afb577a867 100644 --- a/src/main/java/seedu/rex/commands/EditCommand.java +++ b/src/main/java/seedu/rex/commands/EditCommand.java @@ -37,7 +37,7 @@ public void execute(PatientList patients, ArrayList appointments, U throw new RexException("A patient with this NRIC has not been registered!"); } - int idx = patients.EditExistingPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); + int idx = patients.editExistingPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); ui.showLine(); ui.showPatientEditted(patients.getPatientUsingIndex(idx)); storage.save(patients); diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index a690552635..753d0b38db 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -74,7 +74,7 @@ public void addNewPatient(String name, String nric, LocalDate dateOfBirth) { * @param nric NRIC of the patient. * @param dateOfBirth Patient's date of birth. */ - public int EditExistingPatient(String name, String nric, LocalDate dateOfBirth) { + public int editExistingPatient(String name, String nric, LocalDate dateOfBirth) { int idx = getExistingPatient(nric); patients.remove(idx); Patient patient = (new Patient(name, nric, dateOfBirth)); diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 27b1840cd2..1f4dc48440 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,7 +1,13 @@ package seedu.rex.parser; import seedu.rex.Rex; -import seedu.rex.commands.*; +import seedu.rex.commands.AddCommand; +import seedu.rex.commands.BookCommand; +import seedu.rex.commands.Command; +import seedu.rex.commands.CreateAppointmentCommand; +import seedu.rex.commands.EditCommand; +import seedu.rex.commands.ExitCommand; +import seedu.rex.commands.RetrieveCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; From 5f42b573d084fe710b9806a217299b3192f7928e Mon Sep 17 00:00:00 2001 From: kiathwe97 Date: Wed, 14 Oct 2020 18:40:11 +0800 Subject: [PATCH 042/148] Add delete patient capability --- src/main/java/seedu/rex/commands/Command.java | 1 + .../seedu/rex/commands/DeleteCommand.java | 44 +++++++++++++++++++ src/main/java/seedu/rex/data/PatientList.java | 16 +++++++ src/main/java/seedu/rex/parser/Parser.java | 10 ++--- src/main/java/seedu/rex/ui/Ui.java | 9 ++++ 5 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 src/main/java/seedu/rex/commands/DeleteCommand.java diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index 4b10266a7d..a1d6982ba0 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -33,6 +33,7 @@ public Command() { * Executes command. * * @param patients PatientList object. + * @param appointments ArrayList of Appointment * @param ui Ui object. * @param storage Storage object. * @throws RexException If there is issue executing command. diff --git a/src/main/java/seedu/rex/commands/DeleteCommand.java b/src/main/java/seedu/rex/commands/DeleteCommand.java new file mode 100644 index 0000000000..5d3c05ac7d --- /dev/null +++ b/src/main/java/seedu/rex/commands/DeleteCommand.java @@ -0,0 +1,44 @@ +package seedu.rex.commands; + +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; +import seedu.rex.data.hospital.Patient; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +import java.util.ArrayList; + +/** + * Deletes a Patient's data based on his NRIC + */ + +public class DeleteCommand extends Command{ + public static final String COMMAND_WORD = "delete"; + private final String trimmedCommand; + + public DeleteCommand(String trimmedCommand) { + this.trimmedCommand = trimmedCommand; + } + + @Override + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { + + String nric = extractNric(trimmedCommand, COMMAND_WORD); + if (patients.isExistingPatient(nric)){ + Patient deletedPatient = patients.deletePatient(nric); + ui.showPatientDeleted(deletedPatient); + int i = 0; + while (i< appointments.size()){ + String tempNric = appointments.get(i).getPatient().getNric(); + if (tempNric.contentEquals(nric)){ + appointments.remove(i); + }else { + i++; + } + } + }else { + ui.printPatientNotFound(nric); + } + } +} diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index 753d0b38db..f9b2b0602e 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -121,5 +121,21 @@ public Patient getPatientFromNric(String nric) { return null; } + /** + * Deletes Patient with the NRIC entered by the user + * + * @param nric NRIC entered by the user + * @return the deleted Patient Object + */ + public Patient deletePatient(String nric){ + int i; + for (i = 0; i < getSize(); i++){ + if (getPatientUsingIndex(i).getNric().equals(nric)) { + break; + } + } + return patients.remove(i); + } + } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 1f4dc48440..ebfaacb4a4 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,13 +1,7 @@ package seedu.rex.parser; import seedu.rex.Rex; -import seedu.rex.commands.AddCommand; -import seedu.rex.commands.BookCommand; -import seedu.rex.commands.Command; -import seedu.rex.commands.CreateAppointmentCommand; -import seedu.rex.commands.EditCommand; -import seedu.rex.commands.ExitCommand; -import seedu.rex.commands.RetrieveCommand; +import seedu.rex.commands.*; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; @@ -75,6 +69,8 @@ public static Command parse(String fullCommand) throws RexException { command = new CreateAppointmentCommand(trimmedCommand); } else if (trimmedCommand.contains(EditCommand.COMMAND_WORD)) { command = new EditCommand(trimmedCommand); + } else if (trimmedCommand.contains(DeleteCommand.COMMAND_WORD)){ + command = new DeleteCommand(trimmedCommand); } else { throw new RexException(Command.COMMAND_ERROR); } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index c2b052942c..261dbee3b0 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -104,6 +104,15 @@ public void showPatientEditted(Patient patient) { printWithIndent("Patient successfully editted: "); printWithIndent(patient.toString()); } + /** + * Prints a message to indicate successful deletion of a patient. + * + * @param patient The deleted Patient. + */ + public void showPatientDeleted(Patient patient) { + printWithIndent("Patient successfully deleted: "); + printWithIndent(patient.toString()); + } /** From e1897ca58b5990289930a6b91106ae92d9ff9ba2 Mon Sep 17 00:00:00 2001 From: kiathwe97 Date: Wed, 14 Oct 2020 18:50:40 +0800 Subject: [PATCH 043/148] Fixed CheckStyle issues --- .../java/seedu/rex/commands/DeleteCommand.java | 17 +++++++++-------- src/main/java/seedu/rex/data/PatientList.java | 6 +++--- src/main/java/seedu/rex/parser/Parser.java | 11 +++++++++-- src/main/java/seedu/rex/ui/Ui.java | 1 + 4 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/main/java/seedu/rex/commands/DeleteCommand.java b/src/main/java/seedu/rex/commands/DeleteCommand.java index 5d3c05ac7d..1b29c0c8b0 100644 --- a/src/main/java/seedu/rex/commands/DeleteCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteCommand.java @@ -10,10 +10,10 @@ import java.util.ArrayList; /** - * Deletes a Patient's data based on his NRIC + * Deletes a Patient's data based on his NRIC. */ -public class DeleteCommand extends Command{ +public class DeleteCommand extends Command { public static final String COMMAND_WORD = "delete"; private final String trimmedCommand; @@ -22,22 +22,23 @@ public DeleteCommand(String trimmedCommand) { } @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + throws RexException { String nric = extractNric(trimmedCommand, COMMAND_WORD); - if (patients.isExistingPatient(nric)){ + if (patients.isExistingPatient(nric)) { Patient deletedPatient = patients.deletePatient(nric); ui.showPatientDeleted(deletedPatient); int i = 0; - while (i< appointments.size()){ + while (i < appointments.size()) { String tempNric = appointments.get(i).getPatient().getNric(); - if (tempNric.contentEquals(nric)){ + if (tempNric.contentEquals(nric)) { appointments.remove(i); - }else { + } else { i++; } } - }else { + } else { ui.printPatientNotFound(nric); } } diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index f9b2b0602e..e7e7b96d79 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -122,14 +122,14 @@ public Patient getPatientFromNric(String nric) { } /** - * Deletes Patient with the NRIC entered by the user + * Deletes Patient with the NRIC entered by the user. * * @param nric NRIC entered by the user * @return the deleted Patient Object */ - public Patient deletePatient(String nric){ + public Patient deletePatient(String nric) { int i; - for (i = 0; i < getSize(); i++){ + for (i = 0; i < getSize(); i++) { if (getPatientUsingIndex(i).getNric().equals(nric)) { break; } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index ebfaacb4a4..dcc5a36c34 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,7 +1,14 @@ package seedu.rex.parser; import seedu.rex.Rex; -import seedu.rex.commands.*; +import seedu.rex.commands.AddCommand; +import seedu.rex.commands.BookCommand; +import seedu.rex.commands.Command; +import seedu.rex.commands.CreateAppointmentCommand; +import seedu.rex.commands.DeleteCommand; +import seedu.rex.commands.EditCommand; +import seedu.rex.commands.ExitCommand; +import seedu.rex.commands.RetrieveCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; @@ -69,7 +76,7 @@ public static Command parse(String fullCommand) throws RexException { command = new CreateAppointmentCommand(trimmedCommand); } else if (trimmedCommand.contains(EditCommand.COMMAND_WORD)) { command = new EditCommand(trimmedCommand); - } else if (trimmedCommand.contains(DeleteCommand.COMMAND_WORD)){ + } else if (trimmedCommand.contains(DeleteCommand.COMMAND_WORD)) { command = new DeleteCommand(trimmedCommand); } else { throw new RexException(Command.COMMAND_ERROR); diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 261dbee3b0..a8aa6f10ed 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -104,6 +104,7 @@ public void showPatientEditted(Patient patient) { printWithIndent("Patient successfully editted: "); printWithIndent(patient.toString()); } + /** * Prints a message to indicate successful deletion of a patient. * From fb83b42a8bd98b717f35879fae6822ea3cadc7f2 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 14 Oct 2020 19:32:43 +0800 Subject: [PATCH 044/148] Minor improvements to code --- src/main/java/seedu/rex/commands/BookCommand.java | 14 ++++++++++++-- src/main/java/seedu/rex/ui/Ui.java | 6 +++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index db4262c2e0..de7878b215 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -23,21 +23,31 @@ public BookCommand(String trimmedCommand) { public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { String nric = extractNric(trimmedCommand, COMMAND_WORD); + if (appointments.isEmpty()) { + throw new RexException("No appointment sessions!"); + } if (!patients.isExistingPatient(nric)) { ui.printPatientNotFound(nric); - patients.addNewPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); + ui.showCreatePatientMessage(nric); + /*patients.addNewPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); ui.showPatientAdded(patients.getPatientUsingIndex(patients.getSize() - 1)); - storage.save(patients); + storage.save(patients);*/ + new AddCommand("add " + nric).execute(patients, appointments, ui, storage); ui.showLine(); } String dateSelected = ui.getAppointmentToBook(appointments); try { + boolean isAppointment = false; for (Appointment appointment : appointments) { if (appointment.getDate().equals(LocalDate.parse(dateSelected))) { appointment.book(patients.getPatientFromNric(nric)); ui.showAppointmentBookedMessage(appointment); + isAppointment = true; } } + if (!isAppointment) { + throw new RexException("No such date available!"); + } } catch (DateTimeParseException e) { ui.showDateInputError(); } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index a8aa6f10ed..0a1183f846 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -122,7 +122,7 @@ public void showPatientDeleted(Patient patient) { * @return String command from user. */ public String readCommand() { - System.out.println(); + System.out.println("Enter command: "); return in.nextLine(); } @@ -201,4 +201,8 @@ public void showAppointmentBookedMessage(Appointment appointment) { printWithIndent("Appointment on " + appointment.getDate().toString() + " booked!"); } + + public void showCreatePatientMessage(String nric) { + printWithIndent("Creating patient " + nric); + } } From 5bf78eabaf22be404dd9abb65842f368adbfce85 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 14 Oct 2020 19:50:58 +0800 Subject: [PATCH 045/148] Add more minor improvements --- .../java/seedu/rex/commands/BookCommand.java | 27 ++++++------------- .../seedu/rex/commands/DeleteCommand.java | 1 + src/main/java/seedu/rex/ui/Ui.java | 16 ++++++++--- 3 files changed, 21 insertions(+), 23 deletions(-) diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index de7878b215..1dd44c47b1 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -5,9 +5,6 @@ import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; - -import java.time.LocalDate; -import java.time.format.DateTimeParseException; import java.util.ArrayList; public class BookCommand extends Command { @@ -29,27 +26,19 @@ public void execute(PatientList patients, ArrayList appointments, U if (!patients.isExistingPatient(nric)) { ui.printPatientNotFound(nric); ui.showCreatePatientMessage(nric); - /*patients.addNewPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); - ui.showPatientAdded(patients.getPatientUsingIndex(patients.getSize() - 1)); - storage.save(patients);*/ new AddCommand("add " + nric).execute(patients, appointments, ui, storage); ui.showLine(); } - String dateSelected = ui.getAppointmentToBook(appointments); + String indexSelected = ui.getAppointmentToBook(appointments); try { - boolean isAppointment = false; - for (Appointment appointment : appointments) { - if (appointment.getDate().equals(LocalDate.parse(dateSelected))) { - appointment.book(patients.getPatientFromNric(nric)); - ui.showAppointmentBookedMessage(appointment); - isAppointment = true; - } - } - if (!isAppointment) { - throw new RexException("No such date available!"); + int index = Integer.parseInt(indexSelected) - 1; + if (index < 0 || index >= appointments.size()) { + throw new RexException("Index error!"); } - } catch (DateTimeParseException e) { - ui.showDateInputError(); + appointments.get(index).book(patients.getPatientFromNric(nric)); + ui.showAppointmentBookedMessage(appointments.get(index)); + } catch (NumberFormatException e) { + throw new RexException("Index error!"); } diff --git a/src/main/java/seedu/rex/commands/DeleteCommand.java b/src/main/java/seedu/rex/commands/DeleteCommand.java index 1b29c0c8b0..1b5fb98d10 100644 --- a/src/main/java/seedu/rex/commands/DeleteCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteCommand.java @@ -41,5 +41,6 @@ public void execute(PatientList patients, ArrayList appointments, U } else { ui.printPatientNotFound(nric); } + storage.save(patients); } } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 0a1183f846..3266c827b9 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -2,6 +2,7 @@ import seedu.rex.commands.Command; import seedu.rex.commands.ExitCommand; +import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; import seedu.rex.storage.Storage; @@ -181,17 +182,20 @@ public void showAppointmentCreatedMessage() { printWithIndent("New appointment created!"); } - public String getAppointmentToBook(ArrayList appointments) { + public String getAppointmentToBook(ArrayList appointments) throws RexException { showLine(); printWithIndent("Here are the list of available appointments."); - int counter = 1; + int counter = 0; for (Appointment appointment : appointments) { if (!appointment.isBooked()) { - printWithIndent(counter + ". " + appointment.getDate().toString()); counter++; + printWithIndent(counter + ". " + appointment.getDate().toString()); } } - printWithIndent("Please enter the date of appointment to book in YYYY-MM-DD"); + if (counter == 0) { + throw new RexException("No appointments available!"); + } + printWithIndent("Please enter the index of appointment to book"); showLine(); return in.nextLine(); } @@ -205,4 +209,8 @@ public void showAppointmentBookedMessage(Appointment appointment) { public void showCreatePatientMessage(String nric) { printWithIndent("Creating patient " + nric); } + + public void showAppointmentError() { + printWithIndent("No such appointment!"); + } } From dd42612c346a09f8e214a77a8c31fef6b65c87a8 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 14 Oct 2020 19:54:58 +0800 Subject: [PATCH 046/148] Add logger --- src/main/java/seedu/rex/commands/RetrieveCommand.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index c5bb148e1c..b79104cd7b 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -7,6 +7,8 @@ import seedu.rex.ui.Ui; import java.util.ArrayList; +import java.util.logging.Level; +import java.util.logging.Logger; /** * Retrieves patient details. @@ -15,9 +17,11 @@ public class RetrieveCommand extends Command { public static final String COMMAND_WORD = "retrieve"; private final String trimmedCommand; + private static Logger logger; public RetrieveCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; + logger = Logger.getLogger("RetrieveCommand"); } /** @@ -34,13 +38,15 @@ public void execute(PatientList patients, ArrayList appointments, U assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; assert storage != null : "storage is null"; - + logger.log(Level.INFO, "going to extract NRIC"); String nric = extractNric(trimmedCommand, COMMAND_WORD); + logger.log(Level.INFO, "extracted NRIC"); int index = patients.getExistingPatient(nric); assert index > -2 : "Unexpected index!"; if (index < 0) { throw new RexException("No such patient!"); } + logger.log(Level.INFO, "show patients"); ui.showPatient(patients.getPatientUsingIndex(index)); } } From 022587dced6f9c79077921abe463985c36fbcd41 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 14 Oct 2020 20:03:21 +0800 Subject: [PATCH 047/148] Update docs --- docs/AboutUs.md | 2 +- docs/UserGuide.md | 59 ++++++++++++++++++++++++++++++++++++++++- docs/team/tanjunhong.md | 8 ++++++ 3 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 docs/team/tanjunhong.md diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 4dadf85a6f..a1296c0402 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) | Tan Jun Hong | [Github](https://github.com/TanJunHong) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Tan Jun Hong | [Github](https://github.com/TanJunHong) | [Portfolio](docs/team/tanjunhong.md) ![](https://via.placeholder.com/100.png?text=Photo) | Liew You Sheng | [Github](https://github.com/GoldenCorgi) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Randy Ng | [Github](https://github.com/randynyl/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Chong Yow Lim | [Github](https://github.com/ychong032) | [Portfolio](docs/team/johndoe.md) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index b71a534b00..78aa336401 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -39,6 +39,59 @@ Example of usage: `retrieve S7423213Z` +### Edit a patient: `edit` +Edits a patient to the database. + +Format: `edit NRIC` + +* The `NRIC` must be valid and in the database. +* Program will prompt name and date of birth to be edited. + +Example of usage: + +`edit S9922312D` + +`edit S7423213Z` + +### Delete a patient: `delete` +Deletes a patient to the database. + +Format: `delete NRIC` + +* The `NRIC` must be valid and in the database. +* Program will delete patient with nric as `NRIC`. + +Example of usage: + +`delete S9922312D` + +`delete S7423213Z` + +### Create an appointment: `create` +Creates an appointment date. + +Format: `create` + +* Program will prompt for date to be inputted. + +Example of usage: + +`create` + +### Create an appointment: `book` +Books an appointment date. + +Format: `book NRIC` + +* The `NRIC` should be valid and in the database, else `add` command will run +* Program will show a lists of available dates and prompt for which date to use. + +Example of usage: + +`book S9922312D` + +`book S7423213Z` + ## FAQ **Q**: How do I transfer my data to another computer? @@ -48,4 +101,8 @@ Example of usage: ## Command Summary * Add patient `add NRIC` -* Retrieve patient `retrieve NRIC` \ No newline at end of file +* Retrieve patient `retrieve NRIC` +* Edit patient `edit NRIC` +* Delete patient `delete NRIC` +* Create appointment `create` +* Book appointment `book NRIC` \ No newline at end of file diff --git a/docs/team/tanjunhong.md b/docs/team/tanjunhong.md new file mode 100644 index 0000000000..8796529a66 --- /dev/null +++ b/docs/team/tanjunhong.md @@ -0,0 +1,8 @@ +# Tan Jun Hong - Project Portfolio Page + +## Overview +Github T-shirt Winner + +### Summary of Contributions +* Bare-bones code +* Ability to retrieve patients information using NRIC From fced104217aa47425c9da1ad88e102a746080ed3 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 14 Oct 2020 20:10:31 +0800 Subject: [PATCH 048/148] Improve command logic --- .../java/seedu/rex/commands/AddCommand.java | 7 ++++--- .../java/seedu/rex/commands/BookCommand.java | 13 ++++++++++++ src/main/java/seedu/rex/commands/Command.java | 10 +++++----- .../commands/CreateAppointmentCommand.java | 20 +++++++++++-------- .../seedu/rex/commands/DeleteCommand.java | 10 +++++++++- .../java/seedu/rex/commands/EditCommand.java | 7 ++++--- .../java/seedu/rex/commands/ExitCommand.java | 7 ++++--- .../seedu/rex/commands/RetrieveCommand.java | 9 +++++---- src/main/java/seedu/rex/parser/Parser.java | 2 +- 9 files changed, 57 insertions(+), 28 deletions(-) diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java index ee645ea9fd..5f8de4f43b 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -23,9 +23,10 @@ public AddCommand(String trimmedCommand) { /** * Adds a new patient to the patient list using details inputted by the user. * - * @param patients List of patients. - * @param ui Ui object of the program. - * @param storage Storage object used for saving data to files. + * @param patients List of patients. + * @param ui Ui object of the program. + * @param appointments ArrayList of appointment. + * @param storage Storage object used for saving data to files. * @throws RexException If there is an error in the NRIC inputted by the user, the data fails * to save successfully, or the NRIC already exists in the patient list. */ diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index 1dd44c47b1..ab9d02b8f7 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -5,8 +5,12 @@ import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; + import java.util.ArrayList; +/** + * Book appointments. + */ public class BookCommand extends Command { public static final String COMMAND_WORD = "book"; @@ -16,6 +20,15 @@ public BookCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; } + /** + * Book appointment for patients. + * + * @param patients PatientList object. + * @param appointments ArrayList of appointment. + * @param ui Ui object. + * @param storage Storage object. + * @throws RexException If appointment cannot be booked. + */ @Override public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index a1d6982ba0..1d98a49cef 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -32,10 +32,10 @@ public Command() { /** * Executes command. * - * @param patients PatientList object. - * @param appointments ArrayList of Appointment - * @param ui Ui object. - * @param storage Storage object. + * @param patients PatientList object. + * @param appointments ArrayList of appointment. + * @param ui Ui object. + * @param storage Storage object. * @throws RexException If there is issue executing command. */ public abstract void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) @@ -61,7 +61,7 @@ public boolean isInteger(String string) { return false; } try { - int stringAsInteger = Integer.parseInt(string); + Integer.parseInt(string); } catch (NumberFormatException e) { return false; } diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java index 1a5fae91ef..97f18d3324 100644 --- a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java @@ -1,7 +1,6 @@ package seedu.rex.commands; import seedu.rex.data.PatientList; -import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; @@ -10,19 +9,24 @@ import java.time.format.DateTimeParseException; import java.util.ArrayList; +/** + * Create appointment. + */ public class CreateAppointmentCommand extends Command { public static final String COMMAND_WORD = "create"; - private final String trimmedCommand; - - public CreateAppointmentCommand(String trimmedCommand) { - this.trimmedCommand = trimmedCommand; - } + /** + * Create appointment using date given. + * + * @param patients PatientList object. + * @param appointments ArrayList of appointment. + * @param ui Ui object. + * @param storage Storage object. + */ @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) - throws RexException { + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) { String date = ui.getNewAppointmentDate(); try { Appointment newAppointment = new Appointment(LocalDate.parse(date)); diff --git a/src/main/java/seedu/rex/commands/DeleteCommand.java b/src/main/java/seedu/rex/commands/DeleteCommand.java index 1b5fb98d10..e23b4e1479 100644 --- a/src/main/java/seedu/rex/commands/DeleteCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteCommand.java @@ -12,7 +12,6 @@ /** * Deletes a Patient's data based on his NRIC. */ - public class DeleteCommand extends Command { public static final String COMMAND_WORD = "delete"; private final String trimmedCommand; @@ -21,6 +20,15 @@ public DeleteCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; } + /** + * Delete patients using NRIC. + * + * @param patients PatientList object. + * @param appointments ArrayList of appointment. + * @param ui Ui object. + * @param storage Storage object. + * @throws RexException If NRIC has issues. + */ @Override public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { diff --git a/src/main/java/seedu/rex/commands/EditCommand.java b/src/main/java/seedu/rex/commands/EditCommand.java index afb577a867..c555d5b241 100644 --- a/src/main/java/seedu/rex/commands/EditCommand.java +++ b/src/main/java/seedu/rex/commands/EditCommand.java @@ -23,9 +23,10 @@ public EditCommand(String trimmedCommand) { /** * Edit an existing patient to the patient list using details inputted by the user. * - * @param patients List of patients. - * @param ui Ui object of the program. - * @param storage Storage object used for saving data to files. + * @param patients List of patients. + * @param appointments ArrayList of appointment. + * @param ui Ui object of the program. + * @param storage Storage object used for saving data to files. * @throws RexException If there is an error in the NRIC inputted by the user, the data fails * to save successfully, or the NRIC already exists in the patient list. */ diff --git a/src/main/java/seedu/rex/commands/ExitCommand.java b/src/main/java/seedu/rex/commands/ExitCommand.java index 9e71350eb4..a6c745283a 100644 --- a/src/main/java/seedu/rex/commands/ExitCommand.java +++ b/src/main/java/seedu/rex/commands/ExitCommand.java @@ -18,9 +18,10 @@ public class ExitCommand extends Command { /** * Says goodbye to user and exits Rex. * - * @param patients PatientList object. - * @param ui Ui object. - * @param storage Storage object. + * @param patients PatientList object. + * @param appointments ArrayList of appointment. + * @param ui Ui object. + * @param storage Storage object. */ @Override public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) { diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index b79104cd7b..921a3bc559 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -16,8 +16,8 @@ public class RetrieveCommand extends Command { public static final String COMMAND_WORD = "retrieve"; - private final String trimmedCommand; private static Logger logger; + private final String trimmedCommand; public RetrieveCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; @@ -27,9 +27,10 @@ public RetrieveCommand(String trimmedCommand) { /** * Retrieves patient from patient list using details inputted by the user. * - * @param patients PatientList object. - * @param ui Ui object. - * @param storage Storage object. + * @param patients PatientList object. + * @param appointments ArrayList of appointment. + * @param ui Ui object. + * @param storage Storage object. * @throws RexException If there is issue executing command. */ @Override diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index dcc5a36c34..f0e6fc7863 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -73,7 +73,7 @@ public static Command parse(String fullCommand) throws RexException { } else if (trimmedCommand.contains(BookCommand.COMMAND_WORD)) { command = new BookCommand(trimmedCommand); } else if (trimmedCommand.contains(CreateAppointmentCommand.COMMAND_WORD)) { - command = new CreateAppointmentCommand(trimmedCommand); + command = new CreateAppointmentCommand(); } else if (trimmedCommand.contains(EditCommand.COMMAND_WORD)) { command = new EditCommand(trimmedCommand); } else if (trimmedCommand.contains(DeleteCommand.COMMAND_WORD)) { From ba3f5eb412ec96dcdc96a41cfe97917137560705 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 14 Oct 2020 20:24:49 +0800 Subject: [PATCH 049/148] Improve JavaDocs --- .../java/seedu/rex/commands/BookCommand.java | 4 +- .../commands/CreateAppointmentCommand.java | 4 +- .../seedu/rex/commands/DeleteCommand.java | 2 +- .../java/seedu/rex/commands/EditCommand.java | 4 +- .../java/seedu/rex/data/AppointmentList.java | 3 ++ src/main/java/seedu/rex/data/DoctorList.java | 3 ++ src/main/java/seedu/rex/data/PatientList.java | 11 +++-- .../seedu/rex/data/hospital/Appointment.java | 18 +++++++++ .../java/seedu/rex/data/hospital/Doctor.java | 3 ++ .../seedu/rex/data/hospital/Hospital.java | 3 ++ .../java/seedu/rex/data/hospital/Patient.java | 2 - .../seedu/rex/data/hospital/Prescription.java | 3 ++ src/main/java/seedu/rex/storage/Storage.java | 12 ++++++ src/main/java/seedu/rex/ui/Ui.java | 40 ++++++++++++++++--- 14 files changed, 94 insertions(+), 18 deletions(-) diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index ab9d02b8f7..c4adcfca74 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -9,7 +9,7 @@ import java.util.ArrayList; /** - * Book appointments. + * Books appointments. */ public class BookCommand extends Command { @@ -21,7 +21,7 @@ public BookCommand(String trimmedCommand) { } /** - * Book appointment for patients. + * Books appointment for patients. * * @param patients PatientList object. * @param appointments ArrayList of appointment. diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java index 97f18d3324..5068e96adc 100644 --- a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java @@ -10,7 +10,7 @@ import java.util.ArrayList; /** - * Create appointment. + * Creates appointment. */ public class CreateAppointmentCommand extends Command { @@ -18,7 +18,7 @@ public class CreateAppointmentCommand extends Command { /** - * Create appointment using date given. + * Creates appointment using date given. * * @param patients PatientList object. * @param appointments ArrayList of appointment. diff --git a/src/main/java/seedu/rex/commands/DeleteCommand.java b/src/main/java/seedu/rex/commands/DeleteCommand.java index e23b4e1479..2b2c7f607e 100644 --- a/src/main/java/seedu/rex/commands/DeleteCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteCommand.java @@ -21,7 +21,7 @@ public DeleteCommand(String trimmedCommand) { } /** - * Delete patients using NRIC. + * Deletes patients using NRIC. * * @param patients PatientList object. * @param appointments ArrayList of appointment. diff --git a/src/main/java/seedu/rex/commands/EditCommand.java b/src/main/java/seedu/rex/commands/EditCommand.java index c555d5b241..5fcb9de8b2 100644 --- a/src/main/java/seedu/rex/commands/EditCommand.java +++ b/src/main/java/seedu/rex/commands/EditCommand.java @@ -9,7 +9,7 @@ import java.util.ArrayList; /** - * Edit a patient from the list of patients. + * Edits a patient from the list of patients. */ public class EditCommand extends Command { @@ -21,7 +21,7 @@ public EditCommand(String trimmedCommand) { } /** - * Edit an existing patient to the patient list using details inputted by the user. + * Edits an existing patient to the patient list using details inputted by the user. * * @param patients List of patients. * @param appointments ArrayList of appointment. diff --git a/src/main/java/seedu/rex/data/AppointmentList.java b/src/main/java/seedu/rex/data/AppointmentList.java index 3ea64827ec..a7ea1db6d6 100644 --- a/src/main/java/seedu/rex/data/AppointmentList.java +++ b/src/main/java/seedu/rex/data/AppointmentList.java @@ -4,6 +4,9 @@ import java.util.ArrayList; +/** + * Contains ArrayList of appointments. + */ public class AppointmentList { private final ArrayList appointments; diff --git a/src/main/java/seedu/rex/data/DoctorList.java b/src/main/java/seedu/rex/data/DoctorList.java index 440fa83c0a..25be306f89 100644 --- a/src/main/java/seedu/rex/data/DoctorList.java +++ b/src/main/java/seedu/rex/data/DoctorList.java @@ -4,6 +4,9 @@ import java.util.ArrayList; +/** + * Contains ArrayList of doctors. + */ public class DoctorList { private final ArrayList doctors; diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index e7e7b96d79..31e44d5207 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -68,7 +68,7 @@ public void addNewPatient(String name, String nric, LocalDate dateOfBirth) { } /** - * Edit an existing patient with given details to patients ArrayList. + * Edits an existing patient with given details to patients ArrayList. * * @param name Name of the patient. * @param nric NRIC of the patient. @@ -78,12 +78,11 @@ public int editExistingPatient(String name, String nric, LocalDate dateOfBirth) int idx = getExistingPatient(nric); patients.remove(idx); Patient patient = (new Patient(name, nric, dateOfBirth)); - patients.add(idx,patient); + patients.add(idx, patient); return idx; } - /** * Checks if the NRIC entered by the user already exists in the patient list. * @@ -112,6 +111,12 @@ public int getExistingPatient(String nric) { return -1; } + /** + * Gets patient using NRIC. + * + * @param nric NRIC of patient. + * @return patient with given NRIC. + */ public Patient getPatientFromNric(String nric) { for (Patient patient : patients) { if (patient.getNric().equals(nric)) { diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java index a8432257e2..1011d17548 100644 --- a/src/main/java/seedu/rex/data/hospital/Appointment.java +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -2,6 +2,9 @@ import java.time.LocalDate; +/** + * Appointment class. + */ public class Appointment { private LocalDate date; @@ -65,10 +68,20 @@ public void setPrescription(Prescription prescription) { this.prescription = prescription; } + /** + * Checks if appointment is booked. + * + * @return If appointment is booked. + */ public Boolean isBooked() { return isBooked; } + /** + * Books an appointment for the patient. + * + * @param patient Patient to schedule appointment with. + */ public void book(Patient patient) { this.patient = patient; isBooked = true; @@ -79,6 +92,11 @@ public void removeBooking() { isBooked = false; } + /** + * Formats appointment to a string. + * + * @return String formatted. + */ @Override public String toString() { String date = this.date.toString(); diff --git a/src/main/java/seedu/rex/data/hospital/Doctor.java b/src/main/java/seedu/rex/data/hospital/Doctor.java index 4bf8b9463a..5659d4e178 100644 --- a/src/main/java/seedu/rex/data/hospital/Doctor.java +++ b/src/main/java/seedu/rex/data/hospital/Doctor.java @@ -1,5 +1,8 @@ package seedu.rex.data.hospital; +/** + * Doctor class. + */ public class Doctor { private String name; diff --git a/src/main/java/seedu/rex/data/hospital/Hospital.java b/src/main/java/seedu/rex/data/hospital/Hospital.java index 2462d871a0..a2ff921b63 100644 --- a/src/main/java/seedu/rex/data/hospital/Hospital.java +++ b/src/main/java/seedu/rex/data/hospital/Hospital.java @@ -3,6 +3,9 @@ import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; +/** + * Hospital class. + */ public class Hospital { private String name; private PatientList patients; diff --git a/src/main/java/seedu/rex/data/hospital/Patient.java b/src/main/java/seedu/rex/data/hospital/Patient.java index 25c8771156..321ca7ba6f 100644 --- a/src/main/java/seedu/rex/data/hospital/Patient.java +++ b/src/main/java/seedu/rex/data/hospital/Patient.java @@ -19,8 +19,6 @@ public Patient(String name, String nric, LocalDate dateOfBirth) { setNric(nric); setDateOfBirth(dateOfBirth); this.appointmentHistory = new Vector<>(); - - // will create an empty appointment history } public LocalDate getDateOfBirth() { diff --git a/src/main/java/seedu/rex/data/hospital/Prescription.java b/src/main/java/seedu/rex/data/hospital/Prescription.java index 31c8951799..362bbf2ef6 100644 --- a/src/main/java/seedu/rex/data/hospital/Prescription.java +++ b/src/main/java/seedu/rex/data/hospital/Prescription.java @@ -1,5 +1,8 @@ package seedu.rex.data.hospital; +/** + * Prescription class. + */ public class Prescription { private String dosage; private String frequency; diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index 770888bf67..c1040d10a8 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -108,6 +108,12 @@ public void save(PatientList patients) throws RexException { } } + /** + * Saves appointments into file. + * + * @param appointments ArrayList of appointments to save. + * @throws IOException If there is problem writing or saving file. + */ public void saveAppointments(ArrayList appointments) throws IOException { StringBuilder textToWrite = new StringBuilder(); for (Appointment appointment : appointments) { @@ -121,6 +127,12 @@ public void saveAppointments(ArrayList appointments) throws IOExcep fw.close(); } + /** + * Loads appointments, stores them into ArrayList and returns the ArrayList. + * + * @return ArrayList of appointments. + * @throws FileNotFoundException If file does not exist. + */ public ArrayList loadAppointments() throws FileNotFoundException { ArrayList appointments = new ArrayList<>(); File appointmentsFile = new File(folder + "/" + APPOINTMENTS_FILE); diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 3266c827b9..13b1d97650 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -81,6 +81,9 @@ public void showExit() { printWithIndent(ExitCommand.MESSAGE); } + /** + * Prints date error message. + */ public void showDateInputError() { showError(DATE_ERROR); } @@ -100,7 +103,6 @@ public void showPatientAdded(Patient patient) { * * @param patient The newly editted Patient. */ - public void showPatientEditted(Patient patient) { printWithIndent("Patient successfully editted: "); printWithIndent(patient.toString()); @@ -167,21 +169,41 @@ public void showPatient(Patient patient) { printWithIndent(patient.toString()); } + /** + * Prints patient not found message. + * + * @param nric NRIC inputted. + */ public void printPatientNotFound(String nric) { printWithIndent("Patient " + nric + " not found in database!"); } + /** + * Gets appointment date from user. + * + * @return User input string. + */ public String getNewAppointmentDate() { printWithIndent("Please enter the date of appointment in YYYY-MM-DD."); showLine(); return in.nextLine(); } + /** + * Prints appointment creation message. + */ public void showAppointmentCreatedMessage() { showLine(); printWithIndent("New appointment created!"); } + /** + * Gets appointment to be booked. + * + * @param appointments Arraylist of appointments. + * @return User input. + * @throws RexException If no appointments are available. + */ public String getAppointmentToBook(ArrayList appointments) throws RexException { showLine(); printWithIndent("Here are the list of available appointments."); @@ -200,17 +222,23 @@ public String getAppointmentToBook(ArrayList appointments) throws R return in.nextLine(); } + /** + * Shows appointment booking message. + * + * @param appointment appointment that was booked. + */ public void showAppointmentBookedMessage(Appointment appointment) { showLine(); - printWithIndent("Appointment on " + appointment.getDate().toString() + " booked!"); + printWithIndent("Appointment on " + appointment.getDate() + " booked!"); } + /** + * Prints patient creation message. + * + * @param nric Patient's NRIC. + */ public void showCreatePatientMessage(String nric) { printWithIndent("Creating patient " + nric); } - - public void showAppointmentError() { - printWithIndent("No such appointment!"); - } } From 5dbb3ed3bebde0dc49166b3efbae377d2955aff7 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 14 Oct 2020 20:34:41 +0800 Subject: [PATCH 050/148] Update testing code --- text-ui-test/EXPECTED.TXT | 91 ++++++++++++++++++++++++++++++++++----- text-ui-test/input.txt | 19 ++++++++ 2 files changed, 100 insertions(+), 10 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 6282a0cb39..c6ed3fb25a 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -9,31 +9,31 @@ |_| How may i assist you? ____________________________________________________________ - +Enter command: ____________________________________________________________ ☹ OOPS!!! I'm sorry, but I don't know what that means :-( ____________________________________________________________ - +Enter command: ____________________________________________________________ ☹ OOPS!!! Please enter a valid NRIC after 'add'. ____________________________________________________________ - +Enter command: ____________________________________________________________ ☹ OOPS!!! Invalid NRIC length! ____________________________________________________________ - +Enter command: ____________________________________________________________ ☹ OOPS!!! Beginning character of NRIC must be 'S', 'T', 'F', or 'G'! ____________________________________________________________ - +Enter command: ____________________________________________________________ ☹ OOPS!!! Number sequence of NRIC is invalid! ____________________________________________________________ - +Enter command: ____________________________________________________________ ☹ OOPS!!! Number sequence of NRIC is invalid! ____________________________________________________________ - +Enter command: ____________________________________________________________ Enter patient name: Enter patient date of birth (YYYY-MM-DD) including the dashes: @@ -45,16 +45,87 @@ Patient successfully added: Trump, S9123456Z, 1960-06-14 ____________________________________________________________ - +Enter command: ____________________________________________________________ ☹ OOPS!!! No such patient! ____________________________________________________________ - +Enter command: ____________________________________________________________ Patient Details: Trump, S9123456Z, 1960-06-14 ____________________________________________________________ - +Enter command: + ____________________________________________________________ + ☹ OOPS!!! A patient with this NRIC has not been registered! + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Enter patient name: + Enter patient date of birth (YYYY-MM-DD) including the dashes: + ____________________________________________________________ + Patient successfully editted: + Donald, S9123456Z, 1962-06-14 + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Enter patient name: + Enter patient date of birth (YYYY-MM-DD) including the dashes: + ____________________________________________________________ + Patient successfully added: + John, S9993222A, 1985-06-14 + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Patient S9992222A not found in database! + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Patient successfully deleted: + John, S9993222A, 1985-06-14 + ____________________________________________________________ +Enter command: + ____________________________________________________________ + ☹ OOPS!!! No appointment sessions! + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Please enter the date of appointment in YYYY-MM-DD. + ____________________________________________________________ + Error in date format. + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Please enter the date of appointment in YYYY-MM-DD. + ____________________________________________________________ + ____________________________________________________________ + New appointment created! + ____________________________________________________________ +Enter command: + ____________________________________________________________ + ____________________________________________________________ + Here are the list of available appointments. + 1. 2020-10-10 + Please enter the index of appointment to book + ____________________________________________________________ + ☹ OOPS!!! Index error! + ____________________________________________________________ +Enter command: + ____________________________________________________________ + ____________________________________________________________ + Here are the list of available appointments. + 1. 2020-10-10 + Please enter the index of appointment to book + ____________________________________________________________ + ____________________________________________________________ + Appointment on 2020-10-10 booked! + ____________________________________________________________ +Enter command: + ____________________________________________________________ + ____________________________________________________________ + Here are the list of available appointments. + ☹ OOPS!!! No appointments available! + ____________________________________________________________ +Enter command: ____________________________________________________________ Bye. Hope to see you again soon! ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 365531fcfe..7d011314ec 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -10,4 +10,23 @@ Trump 1960-06-14 retrieve S9993222A retrieve S9123456Z +edit S9992222A +edit S9123456Z +Donald +1962-06-14 +add S9993222A +John +1985-06-14 +delete S9992222A +delete S9993222A +book S9123456Z +create +2020-10-40 +create +2020-10-10 +book S9123456Z +0 +book S9123456Z +1 +book S9123456Z bye \ No newline at end of file From dc7270649549c8cb76b6c230cae1ddd0ecfb6854 Mon Sep 17 00:00:00 2001 From: Tan Jun Hong <13333714+TanJunHong@users.noreply.github.com> Date: Wed, 14 Oct 2020 21:20:22 +0800 Subject: [PATCH 051/148] Update README.md --- README.md | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index e97e027b86..572fc17380 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# Hospitalsaurus ReX project template +# Hospitalsaurus ReX project -This is a project template for a greenfield Java project. Given below are instructions on how to use it. +This is a Hospitalsaurus ReX project. Given below are instructions on how to use it. ## Setting up in Intellij @@ -15,16 +15,18 @@ Prerequisites: JDK 11 (use the exact version), update Intellij to the most recen > Task :classes UP-TO-DATE > Task :Rex.main() - Hello from - _ _ _ _ _ _____ __ __ - | | | | (_| | | | | __ \ \ \ / / - | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \ V / - | __ |/ _ \/ __| '_ \| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \ > < - | | | | (_) \__ | |_) | | || (_| | \__ | (_| | |_| | | | |_| \__ \ | | \ | __// . \ - |_| |_|\___/|___| .__/|_|\__\__,_|_|___/\__,_|\__,_|_| \__,_|___/ |_| \_\___/_/ \_\ - | | - |_| - What is your name? + ____________________________________________________________ + _ _ _ _ _ _____ __ __ + | | | | (_| | | | | __ \ \ \ / / + | |__| | ___ ___ _ __ _| |_ __ _| |___ __ _ _ _ _ __ _ _ ___ | |__) |___ \ V / + | __ |/ _ \/ __| '_ \| | __/ _` | / __|/ _` | | | | '__| | | / __| | _ // _ \ > < + | | | | (_) \__ | |_) | | || (_| | \__ | (_| | |_| | | | |_| \__ \ | | \ | __// . \ + |_| |_|\___/|___| .__/|_|\__\__,_|_|___/\__,_|\__,_|_| \__,_|___/ |_| \_\___/_/ \_\ + | | + |_| + How may i assist you? + ____________________________________________________________ + Enter command: ``` Type some word and press enter to let the execution proceed to the end. From be37f6a4ea15956fee739d209561e81d6fc6226f Mon Sep 17 00:00:00 2001 From: randynyl <56857427+randynyl@users.noreply.github.com> Date: Thu, 15 Oct 2020 04:30:12 +0800 Subject: [PATCH 052/148] Add list appointments under patient functionality --- .../rex/commands/ListAppointmentsCommand.java | 50 +++++++++++++++++++ src/main/java/seedu/rex/parser/Parser.java | 11 ++-- src/main/java/seedu/rex/ui/Ui.java | 24 +++++++++ 3 files changed, 77 insertions(+), 8 deletions(-) create mode 100644 src/main/java/seedu/rex/commands/ListAppointmentsCommand.java diff --git a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java new file mode 100644 index 0000000000..e0d0cff5b5 --- /dev/null +++ b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java @@ -0,0 +1,50 @@ +package seedu.rex.commands; + +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; +import seedu.rex.data.hospital.Patient; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +import java.util.ArrayList; + +public class ListAppointmentsCommand extends Command { + + public static final String COMMAND_WORD = "appointments"; + private final String trimmedCommand; + + public ListAppointmentsCommand(String trimmedCommand) { + this.trimmedCommand = trimmedCommand; + } + + /** + * Lists appointments of a patient + * + * @param patients PatientList object. + * @param appointments ArrayList of appointment. + * @param ui Ui object. + * @param storage Storage object. + * @throws RexException If the input NRIC does not exist in system + */ + @Override + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + throws RexException { + String nric = extractNric(trimmedCommand, COMMAND_WORD); + if (!patients.isExistingPatient(nric)) { + throw new RexException("A patient with this NRIC has not been registered!"); + } + Patient targetPatient = patients.getPatientFromNric(nric); + ui.showAppointmentsListHeader(nric); + int counter = 0; + for (Appointment appointment : appointments) { + if (appointment.getPatient() == targetPatient) { + counter++; + ui.showAppointmentLine(appointment, counter); + } + } + if (counter == 0) { + ui.showNoBookedAppointmentsMessage(); + } + } +} diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index f0e6fc7863..f798b011ac 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,14 +1,7 @@ package seedu.rex.parser; import seedu.rex.Rex; -import seedu.rex.commands.AddCommand; -import seedu.rex.commands.BookCommand; -import seedu.rex.commands.Command; -import seedu.rex.commands.CreateAppointmentCommand; -import seedu.rex.commands.DeleteCommand; -import seedu.rex.commands.EditCommand; -import seedu.rex.commands.ExitCommand; -import seedu.rex.commands.RetrieveCommand; +import seedu.rex.commands.*; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; @@ -78,6 +71,8 @@ public static Command parse(String fullCommand) throws RexException { command = new EditCommand(trimmedCommand); } else if (trimmedCommand.contains(DeleteCommand.COMMAND_WORD)) { command = new DeleteCommand(trimmedCommand); + } else if (trimmedCommand.contains(ListAppointmentsCommand.COMMAND_WORD)) { + command = new ListAppointmentsCommand(trimmedCommand); } else { throw new RexException(Command.COMMAND_ERROR); } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 13b1d97650..8bd140b6e9 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -241,4 +241,28 @@ public void showAppointmentBookedMessage(Appointment appointment) { public void showCreatePatientMessage(String nric) { printWithIndent("Creating patient " + nric); } + + /** + * Prints patient's appointment list header + * @param nric Patient's NRIC + */ + public void showAppointmentsListHeader(String nric) { + printWithIndent("Listing appointments for patient " + nric + ": ") ; + } + + /** + * Prints details of patient's appointment + * @param appointment appointment to be printed + * @param counter appointment counter under patient + */ + public void showAppointmentLine(Appointment appointment, int counter) { + printWithIndent(counter + ". " + appointment.getDate()); + } + + /** + * Prints message if patient has no booked appointments + */ + public void showNoBookedAppointmentsMessage() { + printWithIndent("No booked appointments found!"); + } } From 01a6b791fbd2c102faa4184cd5afd362991acf1b Mon Sep 17 00:00:00 2001 From: randynyl <56857427+randynyl@users.noreply.github.com> Date: Thu, 15 Oct 2020 17:30:22 +0800 Subject: [PATCH 053/148] fix checkstyle errors --- .../seedu/rex/commands/ListAppointmentsCommand.java | 2 +- src/main/java/seedu/rex/parser/Parser.java | 10 +++++++++- src/main/java/seedu/rex/ui/Ui.java | 8 ++++---- 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java index e0d0cff5b5..aec766ccc9 100644 --- a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java +++ b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java @@ -19,7 +19,7 @@ public ListAppointmentsCommand(String trimmedCommand) { } /** - * Lists appointments of a patient + * Lists appointments of a patient. * * @param patients PatientList object. * @param appointments ArrayList of appointment. diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index f798b011ac..e666108bc1 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,7 +1,15 @@ package seedu.rex.parser; import seedu.rex.Rex; -import seedu.rex.commands.*; +import seedu.rex.commands.AddCommand; +import seedu.rex.commands.BookCommand; +import seedu.rex.commands.Command; +import seedu.rex.commands.CreateAppointmentCommand; +import seedu.rex.commands.DeleteCommand; +import seedu.rex.commands.EditCommand; +import seedu.rex.commands.ExitCommand; +import seedu.rex.commands.ListAppointmentsCommand; +import seedu.rex.commands.RetrieveCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 8bd140b6e9..19022c5c6a 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -243,15 +243,15 @@ public void showCreatePatientMessage(String nric) { } /** - * Prints patient's appointment list header + * Prints patient's appointment list header. * @param nric Patient's NRIC */ public void showAppointmentsListHeader(String nric) { - printWithIndent("Listing appointments for patient " + nric + ": ") ; + printWithIndent("Listing appointments for patient " + nric + ": "); } /** - * Prints details of patient's appointment + * Prints details of patient's appointment. * @param appointment appointment to be printed * @param counter appointment counter under patient */ @@ -260,7 +260,7 @@ public void showAppointmentLine(Appointment appointment, int counter) { } /** - * Prints message if patient has no booked appointments + * Prints message if patient has no booked appointments. */ public void showNoBookedAppointmentsMessage() { printWithIndent("No booked appointments found!"); From 25eed3b7fceddfe14211ed82304b0b05a994d7fb Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 18 Oct 2020 02:02:55 +0800 Subject: [PATCH 054/148] Add minor improvements --- src/main/java/seedu/rex/Rex.java | 5 ---- .../java/seedu/rex/commands/BookCommand.java | 4 +++ .../seedu/rex/data/hospital/Appointment.java | 9 ------- .../java/seedu/rex/data/hospital/Doctor.java | 2 -- .../seedu/rex/data/hospital/Prescription.java | 25 ----------------- src/main/java/seedu/rex/parser/Parser.java | 27 ++++++++++++------- 6 files changed, 21 insertions(+), 51 deletions(-) delete mode 100644 src/main/java/seedu/rex/data/hospital/Prescription.java diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 02fab1bf19..aaa593f7fc 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -89,10 +89,5 @@ public void run() { ui.showLine(); } } - try { - storage.saveAppointments(appointments); - } catch (IOException e) { - ui.showError(e.getMessage()); - } } } diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index c4adcfca74..40e1b7ea07 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -6,6 +6,7 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +import java.io.IOException; import java.util.ArrayList; /** @@ -48,10 +49,13 @@ public void execute(PatientList patients, ArrayList appointments, U if (index < 0 || index >= appointments.size()) { throw new RexException("Index error!"); } + storage.saveAppointments(appointments); appointments.get(index).book(patients.getPatientFromNric(nric)); ui.showAppointmentBookedMessage(appointments.get(index)); } catch (NumberFormatException e) { throw new RexException("Index error!"); + } catch (IOException e) { + throw new RexException("File Write Error"); } diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java index 1011d17548..9765265f92 100644 --- a/src/main/java/seedu/rex/data/hospital/Appointment.java +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -12,7 +12,6 @@ public class Appointment { private Patient patient; private Doctor doctor; private String notes; - private Prescription prescription; private Boolean isBooked; public Appointment(LocalDate date) { @@ -60,14 +59,6 @@ public void setNotes(String notes) { this.notes = notes; } - public Prescription getPrescription() { - return prescription; - } - - public void setPrescription(Prescription prescription) { - this.prescription = prescription; - } - /** * Checks if appointment is booked. * diff --git a/src/main/java/seedu/rex/data/hospital/Doctor.java b/src/main/java/seedu/rex/data/hospital/Doctor.java index 5659d4e178..b698eaf205 100644 --- a/src/main/java/seedu/rex/data/hospital/Doctor.java +++ b/src/main/java/seedu/rex/data/hospital/Doctor.java @@ -14,6 +14,4 @@ public void setName(String name) { this.name = name; } - private enum Departments {} - } diff --git a/src/main/java/seedu/rex/data/hospital/Prescription.java b/src/main/java/seedu/rex/data/hospital/Prescription.java deleted file mode 100644 index 362bbf2ef6..0000000000 --- a/src/main/java/seedu/rex/data/hospital/Prescription.java +++ /dev/null @@ -1,25 +0,0 @@ -package seedu.rex.data.hospital; - -/** - * Prescription class. - */ -public class Prescription { - private String dosage; - private String frequency; - - public String getDosage() { - return dosage; - } - - public void setDosage(String dosage) { - this.dosage = dosage; - } - - public String getFrequency() { - return frequency; - } - - public void setFrequency(String frequency) { - this.frequency = frequency; - } -} diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index e666108bc1..6bf6494e35 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -65,23 +65,30 @@ public static Command parse(String fullCommand) throws RexException { String trimmedCommand = fullCommand.trim().toLowerCase(); Command command; - if (trimmedCommand.equals(ExitCommand.COMMAND_WORD)) { + String[] words = trimmedCommand.split(" "); + switch (words[0]) { + case ExitCommand.COMMAND_WORD: command = new ExitCommand(); - } else if (trimmedCommand.contains(AddCommand.COMMAND_WORD)) { + break; + case AddCommand.COMMAND_WORD: command = new AddCommand(trimmedCommand); - } else if (trimmedCommand.contains(RetrieveCommand.COMMAND_WORD)) { - command = new RetrieveCommand(trimmedCommand); - } else if (trimmedCommand.contains(BookCommand.COMMAND_WORD)) { + break; + case BookCommand.COMMAND_WORD: command = new BookCommand(trimmedCommand); - } else if (trimmedCommand.contains(CreateAppointmentCommand.COMMAND_WORD)) { + break; + case CreateAppointmentCommand.COMMAND_WORD: command = new CreateAppointmentCommand(); - } else if (trimmedCommand.contains(EditCommand.COMMAND_WORD)) { + break; + case EditCommand.COMMAND_WORD: command = new EditCommand(trimmedCommand); - } else if (trimmedCommand.contains(DeleteCommand.COMMAND_WORD)) { + break; + case DeleteCommand.COMMAND_WORD: command = new DeleteCommand(trimmedCommand); - } else if (trimmedCommand.contains(ListAppointmentsCommand.COMMAND_WORD)) { + break; + case ListAppointmentsCommand.COMMAND_WORD: command = new ListAppointmentsCommand(trimmedCommand); - } else { + break; + default: throw new RexException(Command.COMMAND_ERROR); } return command; From 7758b7485b4525cefcc2bf7d2f3510d36b888ad5 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 18 Oct 2020 02:17:07 +0800 Subject: [PATCH 055/148] Improve code quality --- src/main/java/seedu/rex/Rex.java | 3 +-- src/main/java/seedu/rex/commands/BookCommand.java | 6 ++++-- src/main/java/seedu/rex/commands/DeleteCommand.java | 7 +++---- src/main/java/seedu/rex/commands/EditCommand.java | 4 ++-- .../seedu/rex/commands/ListAppointmentsCommand.java | 12 ++++++------ .../java/seedu/rex/commands/RetrieveCommand.java | 10 ++++------ src/main/java/seedu/rex/data/hospital/Patient.java | 4 ---- src/main/java/seedu/rex/parser/Parser.java | 1 - src/main/java/seedu/rex/ui/Ui.java | 4 +++- 9 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index aaa593f7fc..39c5ea6b31 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -9,7 +9,6 @@ import seedu.rex.ui.Ui; import java.io.FileNotFoundException; -import java.io.IOException; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; @@ -20,7 +19,7 @@ public class Rex { private static PatientList patients; - private static Logger logger; + public static Logger logger; private final Storage storage; private final Ui ui; private ArrayList appointments; diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index 40e1b7ea07..38e600749c 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -37,21 +37,23 @@ public void execute(PatientList patients, ArrayList appointments, U if (appointments.isEmpty()) { throw new RexException("No appointment sessions!"); } + if (!patients.isExistingPatient(nric)) { ui.printPatientNotFound(nric); ui.showCreatePatientMessage(nric); new AddCommand("add " + nric).execute(patients, appointments, ui, storage); ui.showLine(); } - String indexSelected = ui.getAppointmentToBook(appointments); + try { + String indexSelected = ui.getAppointmentToBook(appointments); int index = Integer.parseInt(indexSelected) - 1; if (index < 0 || index >= appointments.size()) { throw new RexException("Index error!"); } - storage.saveAppointments(appointments); appointments.get(index).book(patients.getPatientFromNric(nric)); ui.showAppointmentBookedMessage(appointments.get(index)); + storage.saveAppointments(appointments); } catch (NumberFormatException e) { throw new RexException("Index error!"); } catch (IOException e) { diff --git a/src/main/java/seedu/rex/commands/DeleteCommand.java b/src/main/java/seedu/rex/commands/DeleteCommand.java index 2b2c7f607e..ef62321f11 100644 --- a/src/main/java/seedu/rex/commands/DeleteCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteCommand.java @@ -37,13 +37,12 @@ public void execute(PatientList patients, ArrayList appointments, U if (patients.isExistingPatient(nric)) { Patient deletedPatient = patients.deletePatient(nric); ui.showPatientDeleted(deletedPatient); - int i = 0; - while (i < appointments.size()) { + + for (int i = 0; i < appointments.size(); i++) { String tempNric = appointments.get(i).getPatient().getNric(); if (tempNric.contentEquals(nric)) { appointments.remove(i); - } else { - i++; + break; } } } else { diff --git a/src/main/java/seedu/rex/commands/EditCommand.java b/src/main/java/seedu/rex/commands/EditCommand.java index 5fcb9de8b2..3a765e2447 100644 --- a/src/main/java/seedu/rex/commands/EditCommand.java +++ b/src/main/java/seedu/rex/commands/EditCommand.java @@ -38,9 +38,9 @@ public void execute(PatientList patients, ArrayList appointments, U throw new RexException("A patient with this NRIC has not been registered!"); } - int idx = patients.editExistingPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); + int index = patients.editExistingPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); ui.showLine(); - ui.showPatientEditted(patients.getPatientUsingIndex(idx)); + ui.showPatientEditted(patients.getPatientUsingIndex(index)); storage.save(patients); } } \ No newline at end of file diff --git a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java index aec766ccc9..4bc4a7bb5a 100644 --- a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java +++ b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java @@ -36,14 +36,14 @@ public void execute(PatientList patients, ArrayList appointments, U } Patient targetPatient = patients.getPatientFromNric(nric); ui.showAppointmentsListHeader(nric); - int counter = 0; - for (Appointment appointment : appointments) { - if (appointment.getPatient() == targetPatient) { - counter++; - ui.showAppointmentLine(appointment, counter); + + int i; + for (i = 0; i < appointments.size(); i++) { + if (appointments.get(i).getPatient().equals(targetPatient)) { + ui.showAppointmentLine(appointments.get(i), i + 1); } } - if (counter == 0) { + if (i == 0) { ui.showNoBookedAppointmentsMessage(); } } diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index 921a3bc559..ac041385b0 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -1,5 +1,6 @@ package seedu.rex.commands; +import seedu.rex.Rex; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -8,7 +9,6 @@ import java.util.ArrayList; import java.util.logging.Level; -import java.util.logging.Logger; /** * Retrieves patient details. @@ -16,12 +16,10 @@ public class RetrieveCommand extends Command { public static final String COMMAND_WORD = "retrieve"; - private static Logger logger; private final String trimmedCommand; public RetrieveCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; - logger = Logger.getLogger("RetrieveCommand"); } /** @@ -39,15 +37,15 @@ public void execute(PatientList patients, ArrayList appointments, U assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; assert storage != null : "storage is null"; - logger.log(Level.INFO, "going to extract NRIC"); + Rex.logger.log(Level.INFO, "going to extract NRIC"); String nric = extractNric(trimmedCommand, COMMAND_WORD); - logger.log(Level.INFO, "extracted NRIC"); + Rex.logger.log(Level.INFO, "extracted NRIC"); int index = patients.getExistingPatient(nric); assert index > -2 : "Unexpected index!"; if (index < 0) { throw new RexException("No such patient!"); } - logger.log(Level.INFO, "show patients"); + Rex.logger.log(Level.INFO, "show patients"); ui.showPatient(patients.getPatientUsingIndex(index)); } } diff --git a/src/main/java/seedu/rex/data/hospital/Patient.java b/src/main/java/seedu/rex/data/hospital/Patient.java index 321ca7ba6f..7852666ee7 100644 --- a/src/main/java/seedu/rex/data/hospital/Patient.java +++ b/src/main/java/seedu/rex/data/hospital/Patient.java @@ -58,8 +58,4 @@ public Vector getAppointmentHistory() { public String toString() { return name + ", " + nric + ", " + dateOfBirth.format(DateTimeFormatter.ISO_DATE); } - - private enum Gender { - MALE, FEMALE - } } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 6bf6494e35..b947cb2a37 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -9,7 +9,6 @@ import seedu.rex.commands.EditCommand; import seedu.rex.commands.ExitCommand; import seedu.rex.commands.ListAppointmentsCommand; -import seedu.rex.commands.RetrieveCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 19022c5c6a..e77e7c024a 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -244,6 +244,7 @@ public void showCreatePatientMessage(String nric) { /** * Prints patient's appointment list header. + * * @param nric Patient's NRIC */ public void showAppointmentsListHeader(String nric) { @@ -252,8 +253,9 @@ public void showAppointmentsListHeader(String nric) { /** * Prints details of patient's appointment. + * * @param appointment appointment to be printed - * @param counter appointment counter under patient + * @param counter appointment counter under patient */ public void showAppointmentLine(Appointment appointment, int counter) { printWithIndent(counter + ". " + appointment.getDate()); From d820072b078888e4de84cda970fc2cd4171ce4cd Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 18 Oct 2020 02:27:40 +0800 Subject: [PATCH 056/148] Add list patients function to Rex --- .../rex/commands/ListPatientsCommand.java | 30 +++++++++++++++++++ src/main/java/seedu/rex/data/PatientList.java | 3 ++ src/main/java/seedu/rex/parser/Parser.java | 4 +++ src/main/java/seedu/rex/ui/Ui.java | 16 ++++++++++ 4 files changed, 53 insertions(+) create mode 100644 src/main/java/seedu/rex/commands/ListPatientsCommand.java diff --git a/src/main/java/seedu/rex/commands/ListPatientsCommand.java b/src/main/java/seedu/rex/commands/ListPatientsCommand.java new file mode 100644 index 0000000000..e50228c092 --- /dev/null +++ b/src/main/java/seedu/rex/commands/ListPatientsCommand.java @@ -0,0 +1,30 @@ +package seedu.rex.commands; + +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +import java.util.ArrayList; + +public class ListPatientsCommand extends Command { + + public static final String COMMAND_WORD = "list"; + + /** + * List patients. + * + * @param patients PatientList object. + * @param appointments ArrayList of appointment. + * @param ui Ui object. + * @param storage Storage object. + * @throws RexException If there is issue executing command. + */ + @Override + public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + throws RexException { + + ui.listPatients(patients); + } +} diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index 31e44d5207..837d75ee22 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -142,5 +142,8 @@ public Patient deletePatient(String nric) { return patients.remove(i); } + public ArrayList getPatients() { + return patients; + } } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index b947cb2a37..59098e03d2 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -9,6 +9,7 @@ import seedu.rex.commands.EditCommand; import seedu.rex.commands.ExitCommand; import seedu.rex.commands.ListAppointmentsCommand; +import seedu.rex.commands.ListPatientsCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; @@ -87,6 +88,9 @@ public static Command parse(String fullCommand) throws RexException { case ListAppointmentsCommand.COMMAND_WORD: command = new ListAppointmentsCommand(trimmedCommand); break; + case ListPatientsCommand.COMMAND_WORD: + command = new ListPatientsCommand(); + break; default: throw new RexException(Command.COMMAND_ERROR); } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index e77e7c024a..9c5c70759e 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -2,6 +2,7 @@ import seedu.rex.commands.Command; import seedu.rex.commands.ExitCommand; +import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; @@ -267,4 +268,19 @@ public void showAppointmentLine(Appointment appointment, int counter) { public void showNoBookedAppointmentsMessage() { printWithIndent("No booked appointments found!"); } + + /** + * Prints all patients. + * + * @param patients Patients to print. + */ + public void listPatients(PatientList patients) { + printWithIndent("List of patients (" + patients.getPatients().size() + " in total):"); + for (Patient patient: patients.getPatients()) { + printWithIndent(""); + printWithIndent("Name: " + patient.getName()); + printWithIndent("NRIC: " + patient.getNric()); + printWithIndent("DOB: " + patient.getDateOfBirth()); + } + } } From 808f12348ea1370a555cbf1bff3cd10fcf97449f Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Sun, 18 Oct 2020 02:45:57 +0800 Subject: [PATCH 057/148] Update code to pass test --- src/main/java/seedu/rex/commands/AddCommand.java | 10 ++++++++++ src/main/java/seedu/rex/commands/BookCommand.java | 12 ++++++++++++ .../rex/commands/CreateAppointmentCommand.java | 6 ++++++ src/main/java/seedu/rex/commands/DeleteCommand.java | 10 +++++++++- src/main/java/seedu/rex/commands/EditCommand.java | 8 ++++++++ .../seedu/rex/commands/ListAppointmentsCommand.java | 8 ++++++++ .../java/seedu/rex/commands/RetrieveCommand.java | 3 +-- src/main/java/seedu/rex/parser/Parser.java | 4 ++++ text-ui-test/EXPECTED.TXT | 13 +++++++++++++ text-ui-test/input.txt | 2 ++ 10 files changed, 73 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java index 5f8de4f43b..9f83ade629 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -1,5 +1,6 @@ package seedu.rex.commands; +import seedu.rex.Rex; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -7,6 +8,7 @@ import seedu.rex.ui.Ui; import java.util.ArrayList; +import java.util.logging.Level; /** * Adds a patient to the list of patients. @@ -33,15 +35,23 @@ public AddCommand(String trimmedCommand) { @Override public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { + assert patients != null : "patient ArrayList is null"; + assert ui != null : "ui is null"; + assert storage != null : "storage is null"; + Rex.logger.log(Level.INFO, "going to extract NRIC"); String nric = extractNric(trimmedCommand, COMMAND_WORD); + if (patients.isExistingPatient(nric)) { throw new RexException("A patient with this NRIC is already registered!"); } + Rex.logger.log(Level.INFO, "adding patient..."); patients.addNewPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); ui.showLine(); ui.showPatientAdded(patients.getPatientUsingIndex(patients.getSize() - 1)); + + assert !patients.getPatients().isEmpty() : "No patients!"; storage.save(patients); } } diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index 38e600749c..f0b0204a04 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -1,5 +1,6 @@ package seedu.rex.commands; +import seedu.rex.Rex; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -8,6 +9,7 @@ import java.io.IOException; import java.util.ArrayList; +import java.util.logging.Level; /** * Books appointments. @@ -33,7 +35,13 @@ public BookCommand(String trimmedCommand) { @Override public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { + + assert patients != null : "patient ArrayList is null"; + assert ui != null : "ui is null"; + assert storage != null : "storage is null"; + Rex.logger.log(Level.INFO, "going to extract NRIC"); String nric = extractNric(trimmedCommand, COMMAND_WORD); + if (appointments.isEmpty()) { throw new RexException("No appointment sessions!"); } @@ -41,6 +49,7 @@ public void execute(PatientList patients, ArrayList appointments, U if (!patients.isExistingPatient(nric)) { ui.printPatientNotFound(nric); ui.showCreatePatientMessage(nric); + Rex.logger.log(Level.INFO, "going to add patient..."); new AddCommand("add " + nric).execute(patients, appointments, ui, storage); ui.showLine(); } @@ -51,8 +60,11 @@ public void execute(PatientList patients, ArrayList appointments, U if (index < 0 || index >= appointments.size()) { throw new RexException("Index error!"); } + Rex.logger.log(Level.INFO, "booking appointment for patient..."); appointments.get(index).book(patients.getPatientFromNric(nric)); ui.showAppointmentBookedMessage(appointments.get(index)); + + assert !appointments.isEmpty() : "No appointments!"; storage.saveAppointments(appointments); } catch (NumberFormatException e) { throw new RexException("Index error!"); diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java index 5068e96adc..4d396ca15d 100644 --- a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java @@ -1,5 +1,6 @@ package seedu.rex.commands; +import seedu.rex.Rex; import seedu.rex.data.PatientList; import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; @@ -8,6 +9,7 @@ import java.time.LocalDate; import java.time.format.DateTimeParseException; import java.util.ArrayList; +import java.util.logging.Level; /** * Creates appointment. @@ -27,6 +29,10 @@ public class CreateAppointmentCommand extends Command { */ @Override public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) { + assert patients != null : "patient ArrayList is null"; + assert ui != null : "ui is null"; + assert storage != null : "storage is null"; + Rex.logger.log(Level.INFO, "going to create appointment"); String date = ui.getNewAppointmentDate(); try { Appointment newAppointment = new Appointment(LocalDate.parse(date)); diff --git a/src/main/java/seedu/rex/commands/DeleteCommand.java b/src/main/java/seedu/rex/commands/DeleteCommand.java index ef62321f11..6aa397d5e1 100644 --- a/src/main/java/seedu/rex/commands/DeleteCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteCommand.java @@ -1,5 +1,6 @@ package seedu.rex.commands; +import seedu.rex.Rex; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -8,6 +9,7 @@ import seedu.rex.ui.Ui; import java.util.ArrayList; +import java.util.logging.Level; /** * Deletes a Patient's data based on his NRIC. @@ -32,10 +34,16 @@ public DeleteCommand(String trimmedCommand) { @Override public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { - + assert patients != null : "patient ArrayList is null"; + assert ui != null : "ui is null"; + assert storage != null : "storage is null"; + Rex.logger.log(Level.INFO, "going to extract NRIC"); String nric = extractNric(trimmedCommand, COMMAND_WORD); + if (patients.isExistingPatient(nric)) { Patient deletedPatient = patients.deletePatient(nric); + assert deletedPatient != null : "Deleted patient is null!"; + ui.showPatientDeleted(deletedPatient); for (int i = 0; i < appointments.size(); i++) { diff --git a/src/main/java/seedu/rex/commands/EditCommand.java b/src/main/java/seedu/rex/commands/EditCommand.java index 3a765e2447..f1c5dd6aef 100644 --- a/src/main/java/seedu/rex/commands/EditCommand.java +++ b/src/main/java/seedu/rex/commands/EditCommand.java @@ -1,5 +1,6 @@ package seedu.rex.commands; +import seedu.rex.Rex; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -7,6 +8,7 @@ import seedu.rex.ui.Ui; import java.util.ArrayList; +import java.util.logging.Level; /** * Edits a patient from the list of patients. @@ -33,12 +35,18 @@ public EditCommand(String trimmedCommand) { @Override public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { + assert patients != null : "patient ArrayList is null"; + assert ui != null : "ui is null"; + assert storage != null : "storage is null"; + Rex.logger.log(Level.INFO, "going to extract NRIC"); String nric = extractNric(trimmedCommand, COMMAND_WORD); + if (!patients.isExistingPatient(nric)) { throw new RexException("A patient with this NRIC has not been registered!"); } int index = patients.editExistingPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); + assert index > -1 : "Invalid index!"; ui.showLine(); ui.showPatientEditted(patients.getPatientUsingIndex(index)); storage.save(patients); diff --git a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java index 4bc4a7bb5a..57b663ed1a 100644 --- a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java +++ b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java @@ -1,5 +1,6 @@ package seedu.rex.commands; +import seedu.rex.Rex; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -8,6 +9,7 @@ import seedu.rex.ui.Ui; import java.util.ArrayList; +import java.util.logging.Level; public class ListAppointmentsCommand extends Command { @@ -30,11 +32,17 @@ public ListAppointmentsCommand(String trimmedCommand) { @Override public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) throws RexException { + assert patients != null : "patient ArrayList is null"; + assert ui != null : "ui is null"; + assert storage != null : "storage is null"; + Rex.logger.log(Level.INFO, "going to extract NRIC"); String nric = extractNric(trimmedCommand, COMMAND_WORD); + if (!patients.isExistingPatient(nric)) { throw new RexException("A patient with this NRIC has not been registered!"); } Patient targetPatient = patients.getPatientFromNric(nric); + assert targetPatient != null : "Null target patient!"; ui.showAppointmentsListHeader(nric); int i; diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index ac041385b0..cf46928a10 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -39,13 +39,12 @@ public void execute(PatientList patients, ArrayList appointments, U assert storage != null : "storage is null"; Rex.logger.log(Level.INFO, "going to extract NRIC"); String nric = extractNric(trimmedCommand, COMMAND_WORD); - Rex.logger.log(Level.INFO, "extracted NRIC"); + int index = patients.getExistingPatient(nric); assert index > -2 : "Unexpected index!"; if (index < 0) { throw new RexException("No such patient!"); } - Rex.logger.log(Level.INFO, "show patients"); ui.showPatient(patients.getPatientUsingIndex(index)); } } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 59098e03d2..503c46ec41 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -10,6 +10,7 @@ import seedu.rex.commands.ExitCommand; import seedu.rex.commands.ListAppointmentsCommand; import seedu.rex.commands.ListPatientsCommand; +import seedu.rex.commands.RetrieveCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; @@ -91,6 +92,9 @@ public static Command parse(String fullCommand) throws RexException { case ListPatientsCommand.COMMAND_WORD: command = new ListPatientsCommand(); break; + case RetrieveCommand.COMMAND_WORD: + command = new RetrieveCommand(trimmedCommand); + break; default: throw new RexException(Command.COMMAND_ERROR); } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index c6ed3fb25a..e393757a41 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -125,6 +125,19 @@ Enter command: Here are the list of available appointments. ☹ OOPS!!! No appointments available! ____________________________________________________________ +Enter command: + ____________________________________________________________ + Listing appointments for patient S9123456Z: + 1. 2020-10-10 + ____________________________________________________________ +Enter command: + ____________________________________________________________ + List of patients (1 in total): + + Name: Donald + NRIC: S9123456Z + DOB: 1962-06-14 + ____________________________________________________________ Enter command: ____________________________________________________________ Bye. Hope to see you again soon! diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 7d011314ec..00492444b2 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -29,4 +29,6 @@ book S9123456Z book S9123456Z 1 book S9123456Z +appointments S9123456Z +list bye \ No newline at end of file From 9e0bb7af7d033f2704438db9fbf7c958b5aa6f3a Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 10:58:02 +0800 Subject: [PATCH 058/148] Add initial doctor code --- src/main/java/seedu/rex/Rex.java | 27 +++- .../java/seedu/rex/commands/AddCommand.java | 2 +- .../java/seedu/rex/commands/BookCommand.java | 3 - .../seedu/rex/commands/DeleteCommand.java | 2 +- .../java/seedu/rex/commands/EditCommand.java | 2 +- src/main/java/seedu/rex/parser/Parser.java | 7 + src/main/java/seedu/rex/storage/Storage.java | 126 +++++++++++++----- 7 files changed, 122 insertions(+), 47 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 39c5ea6b31..a48e284159 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -1,6 +1,7 @@ package seedu.rex; import seedu.rex.commands.Command; +import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -19,6 +20,7 @@ public class Rex { private static PatientList patients; + private static DoctorList doctors; public static Logger logger; private final Storage storage; private final Ui ui; @@ -38,16 +40,31 @@ public Rex(String filePath) { try { logger.log(Level.INFO, "going to load patients"); - patients = new PatientList(storage.load()); + patients = new PatientList(storage.loadPatients()); logger.log(Level.INFO, "loaded patients"); + } catch (RexException e) { + logger.log(Level.INFO, "No patients found. Creating new patients list."); + ui.showLoadingError(); + patients = new PatientList(); + } + + try { + logger.log(Level.INFO, "going to load appointments"); appointments = storage.loadAppointments(); logger.log(Level.INFO, "loaded appointments"); } catch (RexException e) { - logger.log(Level.INFO, "patients loading error"); + logger.log(Level.INFO, "No appointments found. Creating new appointments list."); ui.showLoadingError(); - patients = new PatientList(); - } catch (FileNotFoundException e) { + appointments = new ArrayList<>(); + } + + try { + logger.log(Level.INFO, "going to load doctors"); + doctors = new DoctorList(storage.loadDoctors()); + logger.log(Level.INFO, "loaded doctors"); + } catch (RexException e) { logger.log(Level.INFO, "No appointments found. Creating new appointments list."); + ui.showLoadingError(); appointments = new ArrayList<>(); } } @@ -58,7 +75,7 @@ public Rex(String filePath) { * @param args Command line argument. */ public static void main(String[] args) { - new Rex("data/patients.txt").run(); + new Rex("data").run(); } public static PatientList getPatients() { diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java index 9f83ade629..aad0d88142 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -52,6 +52,6 @@ public void execute(PatientList patients, ArrayList appointments, U ui.showPatientAdded(patients.getPatientUsingIndex(patients.getSize() - 1)); assert !patients.getPatients().isEmpty() : "No patients!"; - storage.save(patients); + storage.savePatients(patients); } } diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index f0b0204a04..375da34141 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -7,7 +7,6 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.io.IOException; import java.util.ArrayList; import java.util.logging.Level; @@ -68,8 +67,6 @@ public void execute(PatientList patients, ArrayList appointments, U storage.saveAppointments(appointments); } catch (NumberFormatException e) { throw new RexException("Index error!"); - } catch (IOException e) { - throw new RexException("File Write Error"); } diff --git a/src/main/java/seedu/rex/commands/DeleteCommand.java b/src/main/java/seedu/rex/commands/DeleteCommand.java index 6aa397d5e1..95eb8e983d 100644 --- a/src/main/java/seedu/rex/commands/DeleteCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteCommand.java @@ -56,6 +56,6 @@ public void execute(PatientList patients, ArrayList appointments, U } else { ui.printPatientNotFound(nric); } - storage.save(patients); + storage.savePatients(patients); } } diff --git a/src/main/java/seedu/rex/commands/EditCommand.java b/src/main/java/seedu/rex/commands/EditCommand.java index f1c5dd6aef..e554497000 100644 --- a/src/main/java/seedu/rex/commands/EditCommand.java +++ b/src/main/java/seedu/rex/commands/EditCommand.java @@ -49,6 +49,6 @@ public void execute(PatientList patients, ArrayList appointments, U assert index > -1 : "Invalid index!"; ui.showLine(); ui.showPatientEditted(patients.getPatientUsingIndex(index)); - storage.save(patients); + storage.savePatients(patients); } } \ No newline at end of file diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 503c46ec41..e595e9a1ec 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -13,6 +13,7 @@ import seedu.rex.commands.RetrieveCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; +import seedu.rex.data.hospital.Doctor; import seedu.rex.data.hospital.Patient; import java.time.LocalDate; @@ -102,4 +103,10 @@ public static Command parse(String fullCommand) throws RexException { } + public static Doctor readDoctor(String line) { + assert line != null && !line.equals("") : "No doctors to read!"; + + String name = line.trim(); + return new Doctor(name); + } } diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index c1040d10a8..54e8a028d6 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -3,6 +3,7 @@ import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; +import seedu.rex.data.hospital.Doctor; import seedu.rex.data.hospital.Patient; import seedu.rex.parser.Parser; @@ -28,20 +29,17 @@ public class Storage { private static final String DIRECTORY_ERROR = "Error creating directory."; private static final String WRITE_ERROR = "Error writing file."; private static final String APPOINTMENTS_FILE = "appointments.txt"; + private static final String PATIENTS_FILE = "patients.txt"; + private static final String DOCTORS_FILE = "doctors.txt"; private final String folder; - private final String file; /** * Initializes path of folder and file. * - * @param filePath Full file path. + * @param folderPath Full folder path. */ - public Storage(String filePath) { - assert filePath != null && !filePath.equals("") : "Invalid filepath"; - - int index = filePath.lastIndexOf("/"); - folder = filePath.substring(0, index); - file = filePath.substring(index + 1); + public Storage(String folderPath) { + folder = folderPath; } /** @@ -50,8 +48,8 @@ public Storage(String filePath) { * @return ArrayList of patients. * @throws RexException If there is problem reading file. */ - public ArrayList load() throws RexException { - Path path = Paths.get(folder, file); + public ArrayList loadPatients() throws RexException { + Path path = Paths.get(folder, PATIENTS_FILE); ArrayList patients = new ArrayList<>(); if (Files.exists(path)) { @@ -81,7 +79,7 @@ public ArrayList load() throws RexException { * @param patients ArrayList of patients to save. * @throws RexException If there is problem writing or saving file. */ - public void save(PatientList patients) throws RexException { + public void savePatients(PatientList patients) throws RexException { assert patients != null : "Saving null patients ArrayList"; StringBuilder patientsFileContent = new StringBuilder(); @@ -90,9 +88,39 @@ public void save(PatientList patients) throws RexException { // Need to format tasks patientsFileContent.append(patients.getPatientUsingIndex(i)); patientsFileContent.append('\n'); - Vector patientAppointments = patients.getPatientUsingIndex(i).getAppointmentHistory(); } + writeToFile(patientsFileContent, PATIENTS_FILE); + } + + /** + * Saves appointments into file. + * + * @param appointments ArrayList of appointments to save. + * @throws RexException If there is problem writing or saving file. + */ + public void saveAppointments(ArrayList appointments) throws RexException { + assert appointments != null : "Saving null appointments ArrayList"; + + StringBuilder appointmentsFileContent = new StringBuilder(); + + for (Appointment appointment : appointments) { + // Need to format tasks + appointmentsFileContent.append(appointment); + appointmentsFileContent.append(System.lineSeparator()); + } + + writeToFile(appointmentsFileContent, APPOINTMENTS_FILE); + } + + /** + * Writes content to file. + * + * @param fileContent String content to write. + * @param file Filename to write to. + * @throws RexException If there is problem writing files. + */ + private void writeToFile(StringBuilder fileContent, String file) throws RexException { Path folderPath = Paths.get(folder); if (!Files.exists(folderPath) && !new File(folder).mkdir()) { throw new RexException(DIRECTORY_ERROR); @@ -101,7 +129,7 @@ public void save(PatientList patients) throws RexException { Path filePath = Paths.get(folder, file); try { BufferedWriter bufferedWriter = Files.newBufferedWriter(filePath); - bufferedWriter.write(patientsFileContent.toString()); + bufferedWriter.write(fileContent.toString()); bufferedWriter.close(); } catch (IOException e) { throw new RexException(WRITE_ERROR); @@ -109,38 +137,64 @@ public void save(PatientList patients) throws RexException { } /** - * Saves appointments into file. + * Loads appointments, stores them into ArrayList and returns the ArrayList. * - * @param appointments ArrayList of appointments to save. - * @throws IOException If there is problem writing or saving file. + * @return ArrayList of appointments. + * @throws RexException If there is problem reading file. */ - public void saveAppointments(ArrayList appointments) throws IOException { - StringBuilder textToWrite = new StringBuilder(); - for (Appointment appointment : appointments) { - textToWrite.append(appointment.toString()); - textToWrite.append(System.lineSeparator()); + public ArrayList loadAppointments() throws RexException { + Path path = Paths.get(folder, APPOINTMENTS_FILE); + ArrayList appointments = new ArrayList<>(); + + if (Files.exists(path)) { + try { + BufferedReader bufferedReader = Files.newBufferedReader(path); + + while (true) { + String line = bufferedReader.readLine(); + if (line == null) { + break; + } + + Appointment appointment = Parser.readAppointment(line); + appointments.add(appointment); + } + } catch (IOException e) { + throw new RexException(READ_ERROR); + } } - String appointmentsFilePath = folder + "/" + APPOINTMENTS_FILE; - FileWriter fw = new FileWriter(appointmentsFilePath); - fw.write(String.valueOf(textToWrite)); - fw.close(); + return appointments; } /** - * Loads appointments, stores them into ArrayList and returns the ArrayList. + * Loads doctors, stores them into ArrayList and returns the ArrayList. * - * @return ArrayList of appointments. - * @throws FileNotFoundException If file does not exist. + * @return ArrayList of doctors. + * @throws RexException If there is problem reading file. */ - public ArrayList loadAppointments() throws FileNotFoundException { - ArrayList appointments = new ArrayList<>(); - File appointmentsFile = new File(folder + "/" + APPOINTMENTS_FILE); - Scanner s = new Scanner(appointmentsFile); - while (s.hasNext()) { - Appointment appointment = Parser.readAppointment(s.nextLine()); - appointments.add(appointment); + public ArrayList loadDoctors() throws RexException { + Path path = Paths.get(folder, DOCTORS_FILE); + ArrayList doctors = new ArrayList<>(); + + if (Files.exists(path)) { + try { + BufferedReader bufferedReader = Files.newBufferedReader(path); + + while (true) { + String line = bufferedReader.readLine(); + if (line == null) { + break; + } + + Doctor doctor = Parser.readDoctor(line); + doctors.add(doctor); + } + } catch (IOException e) { + throw new RexException(READ_ERROR); + } } - return appointments; + + return doctors; } } From 7dddd4cc6ec280f9b62fc502afc01e72c08ce3f9 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 10:58:44 +0800 Subject: [PATCH 059/148] Add doctor constructor --- src/main/java/seedu/rex/data/hospital/Doctor.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/seedu/rex/data/hospital/Doctor.java b/src/main/java/seedu/rex/data/hospital/Doctor.java index b698eaf205..f098d71813 100644 --- a/src/main/java/seedu/rex/data/hospital/Doctor.java +++ b/src/main/java/seedu/rex/data/hospital/Doctor.java @@ -6,6 +6,10 @@ public class Doctor { private String name; + public Doctor(String name) { + this.name = name; + } + public String getName() { return name; } From 23574901d72136e69c4c5d9f3136838d8390f99a Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 10:59:51 +0800 Subject: [PATCH 060/148] Improve code quality --- src/main/java/seedu/rex/Rex.java | 3 +-- src/main/java/seedu/rex/commands/RetrieveCommand.java | 2 +- src/main/java/seedu/rex/storage/Storage.java | 6 +----- src/main/java/seedu/rex/ui/Ui.java | 2 +- 4 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index a48e284159..2eea0ab3a6 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -9,7 +9,6 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.io.FileNotFoundException; import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; @@ -19,9 +18,9 @@ */ public class Rex { + public static Logger logger; private static PatientList patients; private static DoctorList doctors; - public static Logger logger; private final Storage storage; private final Ui ui; private ArrayList appointments; diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index cf46928a10..6127535148 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -39,7 +39,7 @@ public void execute(PatientList patients, ArrayList appointments, U assert storage != null : "storage is null"; Rex.logger.log(Level.INFO, "going to extract NRIC"); String nric = extractNric(trimmedCommand, COMMAND_WORD); - + int index = patients.getExistingPatient(nric); assert index > -2 : "Unexpected index!"; if (index < 0) { diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index 54e8a028d6..3075efa7eb 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -10,15 +10,11 @@ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileWriter; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; -import java.util.Scanner; -import java.util.Vector; /** * Loads and saves data to file. @@ -117,7 +113,7 @@ public void saveAppointments(ArrayList appointments) throws RexExce * Writes content to file. * * @param fileContent String content to write. - * @param file Filename to write to. + * @param file Filename to write to. * @throws RexException If there is problem writing files. */ private void writeToFile(StringBuilder fileContent, String file) throws RexException { diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 9c5c70759e..21e837241f 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -276,7 +276,7 @@ public void showNoBookedAppointmentsMessage() { */ public void listPatients(PatientList patients) { printWithIndent("List of patients (" + patients.getPatients().size() + " in total):"); - for (Patient patient: patients.getPatients()) { + for (Patient patient : patients.getPatients()) { printWithIndent(""); printWithIndent("Name: " + patient.getName()); printWithIndent("NRIC: " + patient.getNric()); From 3139bd332ae9100cb9b9737438fd81fe8c5a3db2 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 11:01:37 +0800 Subject: [PATCH 061/148] Fix bug --- src/main/java/seedu/rex/Rex.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 2eea0ab3a6..860d41329a 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -62,9 +62,9 @@ public Rex(String filePath) { doctors = new DoctorList(storage.loadDoctors()); logger.log(Level.INFO, "loaded doctors"); } catch (RexException e) { - logger.log(Level.INFO, "No appointments found. Creating new appointments list."); + logger.log(Level.INFO, "No doctors found. Creating new doctors list."); ui.showLoadingError(); - appointments = new ArrayList<>(); + doctors = new DoctorList(); } } From ce9401a9ba790435235ef6396a98ae9bc4a756fb Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 11:12:17 +0800 Subject: [PATCH 062/148] Change appointments ArrayList to reside under AppointmentList --- src/main/java/seedu/rex/Rex.java | 7 +++--- .../java/seedu/rex/commands/AddCommand.java | 7 +++--- .../java/seedu/rex/commands/BookCommand.java | 13 +++++----- src/main/java/seedu/rex/commands/Command.java | 7 +++--- .../commands/CreateAppointmentCommand.java | 9 ++++--- .../seedu/rex/commands/DeleteCommand.java | 11 ++++----- .../java/seedu/rex/commands/EditCommand.java | 5 ++-- .../java/seedu/rex/commands/ExitCommand.java | 9 +++---- .../rex/commands/ListAppointmentsCommand.java | 11 ++++----- .../rex/commands/ListPatientsCommand.java | 6 ++--- .../seedu/rex/commands/RetrieveCommand.java | 5 ++-- .../java/seedu/rex/data/AppointmentList.java | 24 +++++++++++++++++++ src/main/java/seedu/rex/storage/Storage.java | 5 ++-- src/main/java/seedu/rex/ui/Ui.java | 5 ++-- 14 files changed, 69 insertions(+), 55 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 860d41329a..ffbe262702 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -1,6 +1,7 @@ package seedu.rex; import seedu.rex.commands.Command; +import seedu.rex.data.AppointmentList; import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; @@ -23,7 +24,7 @@ public class Rex { private static DoctorList doctors; private final Storage storage; private final Ui ui; - private ArrayList appointments; + private AppointmentList appointments; /** * Initializes Rex. @@ -49,12 +50,12 @@ public Rex(String filePath) { try { logger.log(Level.INFO, "going to load appointments"); - appointments = storage.loadAppointments(); + appointments = new AppointmentList(storage.loadAppointments()); logger.log(Level.INFO, "loaded appointments"); } catch (RexException e) { logger.log(Level.INFO, "No appointments found. Creating new appointments list."); ui.showLoadingError(); - appointments = new ArrayList<>(); + appointments = new AppointmentList(); } try { diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java index aad0d88142..30441f7bbc 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -1,13 +1,12 @@ package seedu.rex.commands; import seedu.rex.Rex; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.util.ArrayList; import java.util.logging.Level; /** @@ -26,14 +25,14 @@ public AddCommand(String trimmedCommand) { * Adds a new patient to the patient list using details inputted by the user. * * @param patients List of patients. + * @param appointments AppointmentList object. * @param ui Ui object of the program. - * @param appointments ArrayList of appointment. * @param storage Storage object used for saving data to files. * @throws RexException If there is an error in the NRIC inputted by the user, the data fails * to save successfully, or the NRIC already exists in the patient list. */ @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index 375da34141..80128866cb 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -1,13 +1,12 @@ package seedu.rex.commands; import seedu.rex.Rex; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.util.ArrayList; import java.util.logging.Level; /** @@ -26,13 +25,13 @@ public BookCommand(String trimmedCommand) { * Books appointment for patients. * * @param patients PatientList object. - * @param appointments ArrayList of appointment. + * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. * @throws RexException If appointment cannot be booked. */ @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; @@ -56,12 +55,12 @@ public void execute(PatientList patients, ArrayList appointments, U try { String indexSelected = ui.getAppointmentToBook(appointments); int index = Integer.parseInt(indexSelected) - 1; - if (index < 0 || index >= appointments.size()) { + if (index < 0 || index >= appointments.getSize()) { throw new RexException("Index error!"); } Rex.logger.log(Level.INFO, "booking appointment for patient..."); - appointments.get(index).book(patients.getPatientFromNric(nric)); - ui.showAppointmentBookedMessage(appointments.get(index)); + appointments.getAppointmentByIndex(index).book(patients.getPatientFromNric(nric)); + ui.showAppointmentBookedMessage(appointments.getAppointmentByIndex(index)); assert !appointments.isEmpty() : "No appointments!"; storage.saveAppointments(appointments); diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index 1d98a49cef..6d8b72688a 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -1,12 +1,11 @@ package seedu.rex.commands; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.util.ArrayList; import java.util.Set; /** @@ -33,12 +32,12 @@ public Command() { * Executes command. * * @param patients PatientList object. - * @param appointments ArrayList of appointment. + * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. * @throws RexException If there is issue executing command. */ - public abstract void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + public abstract void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) throws RexException; /** diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java index 4d396ca15d..ff1c11b113 100644 --- a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java @@ -1,6 +1,7 @@ package seedu.rex.commands; import seedu.rex.Rex; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; @@ -8,7 +9,6 @@ import java.time.LocalDate; import java.time.format.DateTimeParseException; -import java.util.ArrayList; import java.util.logging.Level; /** @@ -21,14 +21,13 @@ public class CreateAppointmentCommand extends Command { /** * Creates appointment using date given. - * * @param patients PatientList object. - * @param appointments ArrayList of appointment. + * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. */ @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) { + public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; assert storage != null : "storage is null"; @@ -36,7 +35,7 @@ public void execute(PatientList patients, ArrayList appointments, U String date = ui.getNewAppointmentDate(); try { Appointment newAppointment = new Appointment(LocalDate.parse(date)); - appointments.add(newAppointment); + appointments.addAppointment(newAppointment); ui.showAppointmentCreatedMessage(); } catch (DateTimeParseException e) { diff --git a/src/main/java/seedu/rex/commands/DeleteCommand.java b/src/main/java/seedu/rex/commands/DeleteCommand.java index 95eb8e983d..43409809ee 100644 --- a/src/main/java/seedu/rex/commands/DeleteCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteCommand.java @@ -1,14 +1,13 @@ package seedu.rex.commands; import seedu.rex.Rex; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.util.ArrayList; import java.util.logging.Level; /** @@ -32,7 +31,7 @@ public DeleteCommand(String trimmedCommand) { * @throws RexException If NRIC has issues. */ @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; @@ -46,10 +45,10 @@ public void execute(PatientList patients, ArrayList appointments, U ui.showPatientDeleted(deletedPatient); - for (int i = 0; i < appointments.size(); i++) { - String tempNric = appointments.get(i).getPatient().getNric(); + for (int i = 0; i < appointments.getSize(); i++) { + String tempNric = appointments.getAppointmentByIndex(i).getPatient().getNric(); if (tempNric.contentEquals(nric)) { - appointments.remove(i); + appointments.removeAppointmentByIndex(i); break; } } diff --git a/src/main/java/seedu/rex/commands/EditCommand.java b/src/main/java/seedu/rex/commands/EditCommand.java index e554497000..1ff603bb6a 100644 --- a/src/main/java/seedu/rex/commands/EditCommand.java +++ b/src/main/java/seedu/rex/commands/EditCommand.java @@ -1,13 +1,12 @@ package seedu.rex.commands; import seedu.rex.Rex; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.util.ArrayList; import java.util.logging.Level; /** @@ -33,7 +32,7 @@ public EditCommand(String trimmedCommand) { * to save successfully, or the NRIC already exists in the patient list. */ @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; diff --git a/src/main/java/seedu/rex/commands/ExitCommand.java b/src/main/java/seedu/rex/commands/ExitCommand.java index a6c745283a..e0fc186e82 100644 --- a/src/main/java/seedu/rex/commands/ExitCommand.java +++ b/src/main/java/seedu/rex/commands/ExitCommand.java @@ -1,12 +1,10 @@ package seedu.rex.commands; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; -import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.util.ArrayList; - /** * Exits program. */ @@ -17,14 +15,13 @@ public class ExitCommand extends Command { /** * Says goodbye to user and exits Rex. - * - * @param patients PatientList object. + * @param patients PatientList object. * @param appointments ArrayList of appointment. * @param ui Ui object. * @param storage Storage object. */ @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) { + public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) { isExit = true; ui.showExit(); } diff --git a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java index 57b663ed1a..753300807f 100644 --- a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java +++ b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java @@ -1,14 +1,13 @@ package seedu.rex.commands; import seedu.rex.Rex; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Patient; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.util.ArrayList; import java.util.logging.Level; public class ListAppointmentsCommand extends Command { @@ -30,7 +29,7 @@ public ListAppointmentsCommand(String trimmedCommand) { * @throws RexException If the input NRIC does not exist in system */ @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; @@ -46,9 +45,9 @@ public void execute(PatientList patients, ArrayList appointments, U ui.showAppointmentsListHeader(nric); int i; - for (i = 0; i < appointments.size(); i++) { - if (appointments.get(i).getPatient().equals(targetPatient)) { - ui.showAppointmentLine(appointments.get(i), i + 1); + for (i = 0; i < appointments.getSize(); i++) { + if (appointments.getAppointmentByIndex(i).getPatient().equals(targetPatient)) { + ui.showAppointmentLine(appointments.getAppointmentByIndex(i), i + 1); } } if (i == 0) { diff --git a/src/main/java/seedu/rex/commands/ListPatientsCommand.java b/src/main/java/seedu/rex/commands/ListPatientsCommand.java index e50228c092..04dfd518e9 100644 --- a/src/main/java/seedu/rex/commands/ListPatientsCommand.java +++ b/src/main/java/seedu/rex/commands/ListPatientsCommand.java @@ -1,13 +1,11 @@ package seedu.rex.commands; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.util.ArrayList; - public class ListPatientsCommand extends Command { public static final String COMMAND_WORD = "list"; @@ -22,7 +20,7 @@ public class ListPatientsCommand extends Command { * @throws RexException If there is issue executing command. */ @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) throws RexException { ui.listPatients(patients); diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index 6127535148..948a33fc7f 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -1,13 +1,12 @@ package seedu.rex.commands; import seedu.rex.Rex; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.util.ArrayList; import java.util.logging.Level; /** @@ -32,7 +31,7 @@ public RetrieveCommand(String trimmedCommand) { * @throws RexException If there is issue executing command. */ @Override - public void execute(PatientList patients, ArrayList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; diff --git a/src/main/java/seedu/rex/data/AppointmentList.java b/src/main/java/seedu/rex/data/AppointmentList.java index a7ea1db6d6..dd65c596ec 100644 --- a/src/main/java/seedu/rex/data/AppointmentList.java +++ b/src/main/java/seedu/rex/data/AppointmentList.java @@ -1,6 +1,7 @@ package seedu.rex.data; import seedu.rex.data.hospital.Appointment; +import seedu.rex.data.hospital.Patient; import java.util.ArrayList; @@ -24,5 +25,28 @@ public AppointmentList(ArrayList appointments) { this.appointments = appointments; } + public ArrayList getAppointments() { + return appointments; + } + + + public boolean isEmpty() { + return appointments.isEmpty(); + } + + public int getSize() { + return appointments.size(); + } + public Appointment getAppointmentByIndex(int index) { + return appointments.get(index); + } + + public void addAppointment(Appointment appointment) { + appointments.add(appointment); + } + + public void removeAppointmentByIndex(int i) { + appointments.remove(i); + } } diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index 3075efa7eb..c03bcb7151 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -1,5 +1,6 @@ package seedu.rex.storage; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -95,12 +96,12 @@ public void savePatients(PatientList patients) throws RexException { * @param appointments ArrayList of appointments to save. * @throws RexException If there is problem writing or saving file. */ - public void saveAppointments(ArrayList appointments) throws RexException { + public void saveAppointments(AppointmentList appointments) throws RexException { assert appointments != null : "Saving null appointments ArrayList"; StringBuilder appointmentsFileContent = new StringBuilder(); - for (Appointment appointment : appointments) { + for (Appointment appointment : appointments.getAppointments()) { // Need to format tasks appointmentsFileContent.append(appointment); appointmentsFileContent.append(System.lineSeparator()); diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 21e837241f..35bce4ba72 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -2,6 +2,7 @@ import seedu.rex.commands.Command; import seedu.rex.commands.ExitCommand; +import seedu.rex.data.AppointmentList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -205,11 +206,11 @@ public void showAppointmentCreatedMessage() { * @return User input. * @throws RexException If no appointments are available. */ - public String getAppointmentToBook(ArrayList appointments) throws RexException { + public String getAppointmentToBook(AppointmentList appointments) throws RexException { showLine(); printWithIndent("Here are the list of available appointments."); int counter = 0; - for (Appointment appointment : appointments) { + for (Appointment appointment : appointments.getAppointments()) { if (!appointment.isBooked()) { counter++; printWithIndent(counter + ". " + appointment.getDate().toString()); From e83eea18afebec5f275b81c331df36324139db6e Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 11:12:49 +0800 Subject: [PATCH 063/148] Improve code quality --- src/main/java/seedu/rex/Rex.java | 2 -- src/main/java/seedu/rex/commands/CreateAppointmentCommand.java | 1 + src/main/java/seedu/rex/commands/ExitCommand.java | 3 ++- src/main/java/seedu/rex/data/AppointmentList.java | 1 - src/main/java/seedu/rex/ui/Ui.java | 1 - 5 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index ffbe262702..7ca987885c 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -5,12 +5,10 @@ import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.hospital.Appointment; import seedu.rex.parser.Parser; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.util.ArrayList; import java.util.logging.Level; import java.util.logging.Logger; diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java index ff1c11b113..219a61465f 100644 --- a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java @@ -21,6 +21,7 @@ public class CreateAppointmentCommand extends Command { /** * Creates appointment using date given. + * * @param patients PatientList object. * @param appointments AppointmentList object. * @param ui Ui object. diff --git a/src/main/java/seedu/rex/commands/ExitCommand.java b/src/main/java/seedu/rex/commands/ExitCommand.java index e0fc186e82..59077380f7 100644 --- a/src/main/java/seedu/rex/commands/ExitCommand.java +++ b/src/main/java/seedu/rex/commands/ExitCommand.java @@ -15,7 +15,8 @@ public class ExitCommand extends Command { /** * Says goodbye to user and exits Rex. - * @param patients PatientList object. + * + * @param patients PatientList object. * @param appointments ArrayList of appointment. * @param ui Ui object. * @param storage Storage object. diff --git a/src/main/java/seedu/rex/data/AppointmentList.java b/src/main/java/seedu/rex/data/AppointmentList.java index dd65c596ec..e6f5589bb0 100644 --- a/src/main/java/seedu/rex/data/AppointmentList.java +++ b/src/main/java/seedu/rex/data/AppointmentList.java @@ -1,7 +1,6 @@ package seedu.rex.data; import seedu.rex.data.hospital.Appointment; -import seedu.rex.data.hospital.Patient; import java.util.ArrayList; diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 35bce4ba72..ddc1ce18d1 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -11,7 +11,6 @@ import java.time.LocalDate; import java.time.format.DateTimeParseException; -import java.util.ArrayList; import java.util.Scanner; /** From 7b5e1d94fbc3e75422a962fddcdfd4b0be686d31 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 11:16:36 +0800 Subject: [PATCH 064/148] Add DoctorList object into execute parameter --- src/main/java/seedu/rex/Rex.java | 3 ++- src/main/java/seedu/rex/commands/AddCommand.java | 6 ++++-- src/main/java/seedu/rex/commands/BookCommand.java | 6 ++++-- src/main/java/seedu/rex/commands/Command.java | 4 +++- .../seedu/rex/commands/CreateAppointmentCommand.java | 7 ++++--- src/main/java/seedu/rex/commands/DeleteCommand.java | 6 ++++-- src/main/java/seedu/rex/commands/EditCommand.java | 8 +++++--- src/main/java/seedu/rex/commands/ExitCommand.java | 9 +++++---- .../seedu/rex/commands/ListAppointmentsCommand.java | 6 ++++-- .../java/seedu/rex/commands/ListPatientsCommand.java | 12 +++++------- .../java/seedu/rex/commands/RetrieveCommand.java | 6 ++++-- 11 files changed, 44 insertions(+), 29 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 7ca987885c..ac10d2b34f 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -86,6 +86,7 @@ public static PatientList getPatients() { public void run() { assert ui != null : "ui is null"; assert patients != null : "patient ArrayList is null"; + assert doctors != null : "patient ArrayList is null"; assert storage != null : "storage is null"; ui.showWelcome(); @@ -95,7 +96,7 @@ public void run() { String fullCommand = ui.readCommand(); ui.showLine(); // show the divider line ("_______") Command c = Parser.parse(fullCommand); - c.execute(patients, appointments, ui, storage); + c.execute(patients, doctors, appointments, ui, storage); isExit = c.isExit(); } catch (RexException e) { ui.showError(e.getMessage()); diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java index 30441f7bbc..2f23bb19a2 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -2,6 +2,7 @@ import seedu.rex.Rex; import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.storage.Storage; @@ -24,7 +25,8 @@ public AddCommand(String trimmedCommand) { /** * Adds a new patient to the patient list using details inputted by the user. * - * @param patients List of patients. + * @param patients PatientList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object of the program. * @param storage Storage object used for saving data to files. @@ -32,7 +34,7 @@ public AddCommand(String trimmedCommand) { * to save successfully, or the NRIC already exists in the patient list. */ @Override - public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index 80128866cb..0e6a1d1f69 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -2,6 +2,7 @@ import seedu.rex.Rex; import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.storage.Storage; @@ -25,13 +26,14 @@ public BookCommand(String trimmedCommand) { * Books appointment for patients. * * @param patients PatientList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. * @throws RexException If appointment cannot be booked. */ @Override - public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; @@ -48,7 +50,7 @@ public void execute(PatientList patients, AppointmentList appointments, Ui ui, S ui.printPatientNotFound(nric); ui.showCreatePatientMessage(nric); Rex.logger.log(Level.INFO, "going to add patient..."); - new AddCommand("add " + nric).execute(patients, appointments, ui, storage); + new AddCommand("add " + nric).execute(patients, doctors, appointments, ui, storage); ui.showLine(); } diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index 6d8b72688a..16a7d975cd 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -1,6 +1,7 @@ package seedu.rex.commands; import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.storage.Storage; @@ -32,12 +33,13 @@ public Command() { * Executes command. * * @param patients PatientList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. * @throws RexException If there is issue executing command. */ - public abstract void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) + public abstract void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) throws RexException; /** diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java index 219a61465f..6cc29f5d94 100644 --- a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java @@ -2,6 +2,7 @@ import seedu.rex.Rex; import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; @@ -21,14 +22,14 @@ public class CreateAppointmentCommand extends Command { /** * Creates appointment using date given. - * - * @param patients PatientList object. + * @param patients PatientList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. */ @Override - public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) { + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; assert storage != null : "storage is null"; diff --git a/src/main/java/seedu/rex/commands/DeleteCommand.java b/src/main/java/seedu/rex/commands/DeleteCommand.java index 43409809ee..8f581236d6 100644 --- a/src/main/java/seedu/rex/commands/DeleteCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteCommand.java @@ -2,6 +2,7 @@ import seedu.rex.Rex; import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Patient; @@ -25,13 +26,14 @@ public DeleteCommand(String trimmedCommand) { * Deletes patients using NRIC. * * @param patients PatientList object. - * @param appointments ArrayList of appointment. + * @param doctors DoctorList object. + * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. * @throws RexException If NRIC has issues. */ @Override - public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; diff --git a/src/main/java/seedu/rex/commands/EditCommand.java b/src/main/java/seedu/rex/commands/EditCommand.java index 1ff603bb6a..21eb8cd001 100644 --- a/src/main/java/seedu/rex/commands/EditCommand.java +++ b/src/main/java/seedu/rex/commands/EditCommand.java @@ -2,6 +2,7 @@ import seedu.rex.Rex; import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.storage.Storage; @@ -24,15 +25,16 @@ public EditCommand(String trimmedCommand) { /** * Edits an existing patient to the patient list using details inputted by the user. * - * @param patients List of patients. - * @param appointments ArrayList of appointment. + * @param patients PatientList object. + * @param doctors DoctorList object. + * @param appointments AppointmentList object. * @param ui Ui object of the program. * @param storage Storage object used for saving data to files. * @throws RexException If there is an error in the NRIC inputted by the user, the data fails * to save successfully, or the NRIC already exists in the patient list. */ @Override - public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; diff --git a/src/main/java/seedu/rex/commands/ExitCommand.java b/src/main/java/seedu/rex/commands/ExitCommand.java index 59077380f7..85cde8ea08 100644 --- a/src/main/java/seedu/rex/commands/ExitCommand.java +++ b/src/main/java/seedu/rex/commands/ExitCommand.java @@ -1,6 +1,7 @@ package seedu.rex.commands; import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; @@ -15,14 +16,14 @@ public class ExitCommand extends Command { /** * Says goodbye to user and exits Rex. - * - * @param patients PatientList object. - * @param appointments ArrayList of appointment. + * @param patients PatientList object. + * @param doctors AppointmentList object. + * @param appointments DoctorList object. * @param ui Ui object. * @param storage Storage object. */ @Override - public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) { + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) { isExit = true; ui.showExit(); } diff --git a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java index 753300807f..ffda6785e4 100644 --- a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java +++ b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java @@ -2,6 +2,7 @@ import seedu.rex.Rex; import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Patient; @@ -23,13 +24,14 @@ public ListAppointmentsCommand(String trimmedCommand) { * Lists appointments of a patient. * * @param patients PatientList object. - * @param appointments ArrayList of appointment. + * @param doctors DoctorList object. + * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. * @throws RexException If the input NRIC does not exist in system */ @Override - public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; diff --git a/src/main/java/seedu/rex/commands/ListPatientsCommand.java b/src/main/java/seedu/rex/commands/ListPatientsCommand.java index 04dfd518e9..623b1c28a9 100644 --- a/src/main/java/seedu/rex/commands/ListPatientsCommand.java +++ b/src/main/java/seedu/rex/commands/ListPatientsCommand.java @@ -1,8 +1,8 @@ package seedu.rex.commands; import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; -import seedu.rex.data.exception.RexException; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; @@ -12,16 +12,14 @@ public class ListPatientsCommand extends Command { /** * List patients. - * - * @param patients PatientList object. - * @param appointments ArrayList of appointment. + * @param patients PatientList object. + * @param doctors DoctorList object. + * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. - * @throws RexException If there is issue executing command. */ @Override - public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) - throws RexException { + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) { ui.listPatients(patients); } diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index 948a33fc7f..4c9777e99f 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -2,6 +2,7 @@ import seedu.rex.Rex; import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.storage.Storage; @@ -25,13 +26,14 @@ public RetrieveCommand(String trimmedCommand) { * Retrieves patient from patient list using details inputted by the user. * * @param patients PatientList object. - * @param appointments ArrayList of appointment. + * @param doctors DoctorList object. + * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. * @throws RexException If there is issue executing command. */ @Override - public void execute(PatientList patients, AppointmentList appointments, Ui ui, Storage storage) + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; From 851780153e61c87fc48017c4567f9a577f848677 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 11:19:08 +0800 Subject: [PATCH 065/148] Improve JavaDocs --- src/main/java/seedu/rex/commands/AddCommand.java | 2 +- src/main/java/seedu/rex/commands/BookCommand.java | 2 +- src/main/java/seedu/rex/commands/Command.java | 6 +++--- .../java/seedu/rex/commands/CreateAppointmentCommand.java | 8 +++++--- src/main/java/seedu/rex/commands/DeleteCommand.java | 2 +- src/main/java/seedu/rex/commands/EditCommand.java | 2 +- src/main/java/seedu/rex/commands/ExitCommand.java | 8 +++++--- .../java/seedu/rex/commands/ListAppointmentsCommand.java | 2 +- src/main/java/seedu/rex/commands/ListPatientsCommand.java | 8 +++++--- src/main/java/seedu/rex/commands/RetrieveCommand.java | 2 +- 10 files changed, 24 insertions(+), 18 deletions(-) diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddCommand.java index 2f23bb19a2..f9546202c9 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddCommand.java @@ -26,7 +26,7 @@ public AddCommand(String trimmedCommand) { * Adds a new patient to the patient list using details inputted by the user. * * @param patients PatientList object. - * @param doctors DoctorList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object of the program. * @param storage Storage object used for saving data to files. diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index 0e6a1d1f69..f30206d7c9 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -26,7 +26,7 @@ public BookCommand(String trimmedCommand) { * Books appointment for patients. * * @param patients PatientList object. - * @param doctors DoctorList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. diff --git a/src/main/java/seedu/rex/commands/Command.java b/src/main/java/seedu/rex/commands/Command.java index 16a7d975cd..47e77a52e5 100644 --- a/src/main/java/seedu/rex/commands/Command.java +++ b/src/main/java/seedu/rex/commands/Command.java @@ -33,14 +33,14 @@ public Command() { * Executes command. * * @param patients PatientList object. - * @param doctors DoctorList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. * @throws RexException If there is issue executing command. */ - public abstract void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) - throws RexException; + public abstract void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, + Storage storage) throws RexException; /** * Returns Rex's exit status. diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java index 6cc29f5d94..328df57e54 100644 --- a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java @@ -22,14 +22,16 @@ public class CreateAppointmentCommand extends Command { /** * Creates appointment using date given. - * @param patients PatientList object. - * @param doctors DoctorList object. + * + * @param patients PatientList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. */ @Override - public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) { + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, + Storage storage) { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; assert storage != null : "storage is null"; diff --git a/src/main/java/seedu/rex/commands/DeleteCommand.java b/src/main/java/seedu/rex/commands/DeleteCommand.java index 8f581236d6..174d232835 100644 --- a/src/main/java/seedu/rex/commands/DeleteCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteCommand.java @@ -26,7 +26,7 @@ public DeleteCommand(String trimmedCommand) { * Deletes patients using NRIC. * * @param patients PatientList object. - * @param doctors DoctorList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. diff --git a/src/main/java/seedu/rex/commands/EditCommand.java b/src/main/java/seedu/rex/commands/EditCommand.java index 21eb8cd001..7b0524d320 100644 --- a/src/main/java/seedu/rex/commands/EditCommand.java +++ b/src/main/java/seedu/rex/commands/EditCommand.java @@ -26,7 +26,7 @@ public EditCommand(String trimmedCommand) { * Edits an existing patient to the patient list using details inputted by the user. * * @param patients PatientList object. - * @param doctors DoctorList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object of the program. * @param storage Storage object used for saving data to files. diff --git a/src/main/java/seedu/rex/commands/ExitCommand.java b/src/main/java/seedu/rex/commands/ExitCommand.java index 85cde8ea08..6bd2423b63 100644 --- a/src/main/java/seedu/rex/commands/ExitCommand.java +++ b/src/main/java/seedu/rex/commands/ExitCommand.java @@ -16,14 +16,16 @@ public class ExitCommand extends Command { /** * Says goodbye to user and exits Rex. - * @param patients PatientList object. - * @param doctors AppointmentList object. + * + * @param patients PatientList object. + * @param doctors AppointmentList object. * @param appointments DoctorList object. * @param ui Ui object. * @param storage Storage object. */ @Override - public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) { + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, + Storage storage) { isExit = true; ui.showExit(); } diff --git a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java index ffda6785e4..ed26636c6c 100644 --- a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java +++ b/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java @@ -24,7 +24,7 @@ public ListAppointmentsCommand(String trimmedCommand) { * Lists appointments of a patient. * * @param patients PatientList object. - * @param doctors DoctorList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. diff --git a/src/main/java/seedu/rex/commands/ListPatientsCommand.java b/src/main/java/seedu/rex/commands/ListPatientsCommand.java index 623b1c28a9..ffc1eed872 100644 --- a/src/main/java/seedu/rex/commands/ListPatientsCommand.java +++ b/src/main/java/seedu/rex/commands/ListPatientsCommand.java @@ -12,14 +12,16 @@ public class ListPatientsCommand extends Command { /** * List patients. - * @param patients PatientList object. - * @param doctors DoctorList object. + * + * @param patients PatientList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. */ @Override - public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) { + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, + Storage storage) { ui.listPatients(patients); } diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrieveCommand.java index 4c9777e99f..34b68cfef9 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrieveCommand.java @@ -26,7 +26,7 @@ public RetrieveCommand(String trimmedCommand) { * Retrieves patient from patient list using details inputted by the user. * * @param patients PatientList object. - * @param doctors DoctorList object. + * @param doctors DoctorList object. * @param appointments AppointmentList object. * @param ui Ui object. * @param storage Storage object. From 6c9b822046eaf81ebaa396ea8fe4f44c22f447bd Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 11:27:49 +0800 Subject: [PATCH 066/148] Add subtle improvements --- .../seedu/rex/commands/CreateAppointmentCommand.java | 9 +++++++++ src/main/java/seedu/rex/data/DoctorList.java | 4 ++++ src/main/java/seedu/rex/ui/Ui.java | 5 +++++ 3 files changed, 18 insertions(+) diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java index 328df57e54..b975eaee48 100644 --- a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java @@ -5,6 +5,7 @@ import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.hospital.Appointment; +import seedu.rex.data.hospital.Doctor; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; @@ -37,8 +38,16 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap assert storage != null : "storage is null"; Rex.logger.log(Level.INFO, "going to create appointment"); String date = ui.getNewAppointmentDate(); + String doctorName = ui.getDoctorName(); try { Appointment newAppointment = new Appointment(LocalDate.parse(date)); + for (Doctor doctor: doctors.getDoctors()) { + if (doctor.getName().equals(doctorName)) { + newAppointment.setDoctor(doctor); + break; + } + + } appointments.addAppointment(newAppointment); ui.showAppointmentCreatedMessage(); diff --git a/src/main/java/seedu/rex/data/DoctorList.java b/src/main/java/seedu/rex/data/DoctorList.java index 25be306f89..8ab0352574 100644 --- a/src/main/java/seedu/rex/data/DoctorList.java +++ b/src/main/java/seedu/rex/data/DoctorList.java @@ -54,4 +54,8 @@ public Doctor getDoctorUsingIndex(int index) { public void addDoctor(Doctor doctor) { doctors.add(doctor); } + + public ArrayList getDoctors() { + return doctors; + } } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index ddc1ce18d1..922d0b9770 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -283,4 +283,9 @@ public void listPatients(PatientList patients) { printWithIndent("DOB: " + patient.getDateOfBirth()); } } + + public String getDoctorName() { + printWithIndent("Enter doctor name: "); + return in.nextLine().trim(); + } } From cfcc52e3a261888e763f18ca307d1bc978114a15 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 13:09:32 +0800 Subject: [PATCH 067/148] Add ability to load doctors --- src/main/java/seedu/rex/Rex.java | 5 ++++ .../java/seedu/rex/commands/BookCommand.java | 11 ++++++-- .../commands/CreateAppointmentCommand.java | 8 ------ src/main/java/seedu/rex/data/DoctorList.java | 24 ++++++++++++++++++ .../seedu/rex/data/hospital/Appointment.java | 25 ++++++++----------- src/main/java/seedu/rex/parser/Parser.java | 6 ++++- src/main/java/seedu/rex/storage/Storage.java | 2 +- 7 files changed, 55 insertions(+), 26 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index ac10d2b34f..4c64ea8248 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -5,6 +5,7 @@ import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Doctor; import seedu.rex.parser.Parser; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; @@ -80,6 +81,10 @@ public static PatientList getPatients() { return patients; } + public static DoctorList getDoctors() { + return doctors; + } + /** * Runs Rex. */ diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index f30206d7c9..c86c20ad00 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -46,6 +46,12 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap throw new RexException("No appointment sessions!"); } + Rex.logger.log(Level.INFO, "going to get doctor's name"); + String doctorName = ui.getDoctorName(); + if (!doctors.isExistingDoctor(doctorName)) { + throw new RexException("No such doctor!"); + } + if (!patients.isExistingPatient(nric)) { ui.printPatientNotFound(nric); ui.showCreatePatientMessage(nric); @@ -60,8 +66,9 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap if (index < 0 || index >= appointments.getSize()) { throw new RexException("Index error!"); } - Rex.logger.log(Level.INFO, "booking appointment for patient..."); - appointments.getAppointmentByIndex(index).book(patients.getPatientFromNric(nric)); + Rex.logger.log(Level.INFO, "booking appointment for patient and doctor..."); + appointments.getAppointmentByIndex(index).bookPatient(patients.getPatientFromNric(nric)); + appointments.getAppointmentByIndex(index).bookDoctor(doctors.getDoctorFromName(doctorName)); ui.showAppointmentBookedMessage(appointments.getAppointmentByIndex(index)); assert !appointments.isEmpty() : "No appointments!"; diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java index b975eaee48..d7c584f904 100644 --- a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java @@ -38,16 +38,8 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap assert storage != null : "storage is null"; Rex.logger.log(Level.INFO, "going to create appointment"); String date = ui.getNewAppointmentDate(); - String doctorName = ui.getDoctorName(); try { Appointment newAppointment = new Appointment(LocalDate.parse(date)); - for (Doctor doctor: doctors.getDoctors()) { - if (doctor.getName().equals(doctorName)) { - newAppointment.setDoctor(doctor); - break; - } - - } appointments.addAppointment(newAppointment); ui.showAppointmentCreatedMessage(); diff --git a/src/main/java/seedu/rex/data/DoctorList.java b/src/main/java/seedu/rex/data/DoctorList.java index 8ab0352574..e7426440ea 100644 --- a/src/main/java/seedu/rex/data/DoctorList.java +++ b/src/main/java/seedu/rex/data/DoctorList.java @@ -58,4 +58,28 @@ public void addDoctor(Doctor doctor) { public ArrayList getDoctors() { return doctors; } + + public boolean isExistingDoctor(String name) { + return getExistingDoctor(name) > -1; + } + + public int getExistingDoctor(String name) { + assert name != null && !name.equals("") : "Cannot get doctor of null name"; + + for (int i = 0; i < getSize(); i++) { + if (getDoctorUsingIndex(i).getName().equals(name)) { + return i; + } + } + return -1; + } + + public Doctor getDoctorFromName(String name) { + for (Doctor doctor : doctors) { + if (doctor.getName().equals(name)) { + return doctor; + } + } + return null; + } } diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java index 9765265f92..a6f1b5d8bd 100644 --- a/src/main/java/seedu/rex/data/hospital/Appointment.java +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -73,7 +73,7 @@ public Boolean isBooked() { * * @param patient Patient to schedule appointment with. */ - public void book(Patient patient) { + public void bookPatient(Patient patient) { this.patient = patient; isBooked = true; } @@ -91,18 +91,15 @@ public void removeBooking() { @Override public String toString() { String date = this.date.toString(); - String bookedStatus; - String patientNric; - if (isBooked) { - bookedStatus = "booked"; - } else { - bookedStatus = "available"; - } - if (patient != null) { - patientNric = patient.getNric(); - } else { - patientNric = null; - } - return date + ", " + bookedStatus + ", " + patientNric; + + String bookedStatus = isBooked ? "booked" : "available"; + String patientNric = patient == null ? null : patient.getNric(); + String doctorName = doctor == null ? null : doctor.getName(); + + return date + ", " + bookedStatus + ", " + patientNric + ", " + doctorName; + } + + public void bookDoctor(Doctor doctor) { + this.doctor = doctor; } } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index e595e9a1ec..94c0fda84f 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -48,9 +48,13 @@ public static Appointment readAppointment(String line) { LocalDate date = LocalDate.parse(appointmentComponents[0]); String bookedStatus = appointmentComponents[1]; String nric = appointmentComponents[2]; + String doctorName = appointmentComponents[3]; Appointment appointment = new Appointment(date); if (bookedStatus.equals("booked")) { - appointment.book(Rex.getPatients().getPatientUsingIndex(Rex.getPatients().getExistingPatient(nric))); + appointment.bookPatient(Rex.getPatients().getPatientFromNric(nric)); + } + if (doctorName != null && !doctorName.equals("null")) { + appointment.setDoctor(Rex.getDoctors().getDoctorFromName(doctorName)); } return appointment; } diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index c03bcb7151..1e979bff8c 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -84,7 +84,7 @@ public void savePatients(PatientList patients) throws RexException { for (int i = 0; i < patients.getSize(); i++) { // Need to format tasks patientsFileContent.append(patients.getPatientUsingIndex(i)); - patientsFileContent.append('\n'); + patientsFileContent.append(System.lineSeparator()); } writeToFile(patientsFileContent, PATIENTS_FILE); From bbc3934b9da4204120e69e7d15e719d1fa5c3305 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 13:10:06 +0800 Subject: [PATCH 068/148] Add doctors list --- data/doctors.txt | 1 + 1 file changed, 1 insertion(+) create mode 100644 data/doctors.txt diff --git a/data/doctors.txt b/data/doctors.txt new file mode 100644 index 0000000000..c92fd2ec88 --- /dev/null +++ b/data/doctors.txt @@ -0,0 +1 @@ +tan \ No newline at end of file From e424154794ab58cc381b78b423a770045de732d5 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 13:11:13 +0800 Subject: [PATCH 069/148] Improve code quality --- src/main/java/seedu/rex/Rex.java | 1 - src/main/java/seedu/rex/commands/CreateAppointmentCommand.java | 1 - src/main/java/seedu/rex/data/DoctorList.java | 2 +- 3 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 4c64ea8248..640338db58 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -5,7 +5,6 @@ import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.hospital.Doctor; import seedu.rex.parser.Parser; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java index d7c584f904..328df57e54 100644 --- a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java @@ -5,7 +5,6 @@ import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.hospital.Appointment; -import seedu.rex.data.hospital.Doctor; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; diff --git a/src/main/java/seedu/rex/data/DoctorList.java b/src/main/java/seedu/rex/data/DoctorList.java index e7426440ea..43198fe606 100644 --- a/src/main/java/seedu/rex/data/DoctorList.java +++ b/src/main/java/seedu/rex/data/DoctorList.java @@ -65,7 +65,7 @@ public boolean isExistingDoctor(String name) { public int getExistingDoctor(String name) { assert name != null && !name.equals("") : "Cannot get doctor of null name"; - + for (int i = 0; i < getSize(); i++) { if (getDoctorUsingIndex(i).getName().equals(name)) { return i; From f73045a5a2d96ff2e423544f59b418473227a3bf Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 14:00:49 +0800 Subject: [PATCH 070/148] Improve code --- data/doctors.txt | 2 +- src/main/java/seedu/rex/Rex.java | 20 +++---- .../seedu/rex/commands/AddDoctorCommand.java | 46 ++++++++++++++++ .../java/seedu/rex/commands/BookCommand.java | 5 +- .../rex/commands/RemoveDoctorCommand.java | 54 +++++++++++++++++++ src/main/java/seedu/rex/data/DoctorList.java | 11 ++++ .../java/seedu/rex/data/hospital/Doctor.java | 7 +++ src/main/java/seedu/rex/parser/Parser.java | 8 +++ src/main/java/seedu/rex/storage/Storage.java | 15 ++++++ src/main/java/seedu/rex/ui/Ui.java | 16 +++++- text-ui-test/EXPECTED.TXT | 20 +++++-- text-ui-test/input.txt | 7 ++- 12 files changed, 191 insertions(+), 20 deletions(-) create mode 100644 src/main/java/seedu/rex/commands/AddDoctorCommand.java create mode 100644 src/main/java/seedu/rex/commands/RemoveDoctorCommand.java diff --git a/data/doctors.txt b/data/doctors.txt index c92fd2ec88..00b40c13aa 100644 --- a/data/doctors.txt +++ b/data/doctors.txt @@ -1 +1 @@ -tan \ No newline at end of file +TAN diff --git a/src/main/java/seedu/rex/Rex.java b/src/main/java/seedu/rex/Rex.java index 640338db58..cee636f778 100644 --- a/src/main/java/seedu/rex/Rex.java +++ b/src/main/java/seedu/rex/Rex.java @@ -46,16 +46,6 @@ public Rex(String filePath) { patients = new PatientList(); } - try { - logger.log(Level.INFO, "going to load appointments"); - appointments = new AppointmentList(storage.loadAppointments()); - logger.log(Level.INFO, "loaded appointments"); - } catch (RexException e) { - logger.log(Level.INFO, "No appointments found. Creating new appointments list."); - ui.showLoadingError(); - appointments = new AppointmentList(); - } - try { logger.log(Level.INFO, "going to load doctors"); doctors = new DoctorList(storage.loadDoctors()); @@ -65,6 +55,16 @@ public Rex(String filePath) { ui.showLoadingError(); doctors = new DoctorList(); } + + try { + logger.log(Level.INFO, "going to load appointments"); + appointments = new AppointmentList(storage.loadAppointments()); + logger.log(Level.INFO, "loaded appointments"); + } catch (RexException e) { + logger.log(Level.INFO, "No appointments found. Creating new appointments list."); + ui.showLoadingError(); + appointments = new AppointmentList(); + } } /** diff --git a/src/main/java/seedu/rex/commands/AddDoctorCommand.java b/src/main/java/seedu/rex/commands/AddDoctorCommand.java new file mode 100644 index 0000000000..58542556eb --- /dev/null +++ b/src/main/java/seedu/rex/commands/AddDoctorCommand.java @@ -0,0 +1,46 @@ +package seedu.rex.commands; + +import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Doctor; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +public class AddDoctorCommand extends Command { + public static final String COMMAND_WORD = "doctor"; + private final String trimmedCommand; + + public AddDoctorCommand(String trimmedCommand) { + this.trimmedCommand = trimmedCommand; + } + + /** + * Executes command. + * + * @param patients PatientList object. + * @param doctors DoctorList object. + * @param appointments AppointmentList object. + * @param ui Ui object. + * @param storage Storage object. + * @throws RexException If there is issue executing command. + */ + @Override + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) + throws RexException { + + String doctorName = trimmedCommand.replaceFirst("(?i)" + COMMAND_WORD, "").trim().toUpperCase(); + + if (doctors.isExistingDoctor(doctorName)) { + throw new RexException("A doctor with this name is already registered!"); + } + + Doctor newDoctor = new Doctor(doctorName); + doctors.addDoctor(newDoctor); + + ui.showDoctorAdded(newDoctor); + + storage.saveDoctors(doctors); + } +} diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index c86c20ad00..67b1c9d720 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -39,13 +39,14 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; assert storage != null : "storage is null"; - Rex.logger.log(Level.INFO, "going to extract NRIC"); - String nric = extractNric(trimmedCommand, COMMAND_WORD); if (appointments.isEmpty()) { throw new RexException("No appointment sessions!"); } + Rex.logger.log(Level.INFO, "going to extract NRIC"); + String nric = extractNric(trimmedCommand, COMMAND_WORD); + Rex.logger.log(Level.INFO, "going to get doctor's name"); String doctorName = ui.getDoctorName(); if (!doctors.isExistingDoctor(doctorName)) { diff --git a/src/main/java/seedu/rex/commands/RemoveDoctorCommand.java b/src/main/java/seedu/rex/commands/RemoveDoctorCommand.java new file mode 100644 index 0000000000..ed178afe83 --- /dev/null +++ b/src/main/java/seedu/rex/commands/RemoveDoctorCommand.java @@ -0,0 +1,54 @@ +package seedu.rex.commands; + +import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Doctor; +import seedu.rex.data.hospital.Patient; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +public class RemoveDoctorCommand extends Command { + public static final String COMMAND_WORD = "nodoctor"; + private final String trimmedCommand; + + public RemoveDoctorCommand(String trimmedCommand) { + this.trimmedCommand = trimmedCommand; + } + + /** + * Executes command. + * + * @param patients PatientList object. + * @param doctors DoctorList object. + * @param appointments AppointmentList object. + * @param ui Ui object. + * @param storage Storage object. + * @throws RexException If there is issue executing command. + */ + @Override + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) + throws RexException { + + String doctorName = trimmedCommand.replaceFirst("(?i)" + COMMAND_WORD, "").trim().toUpperCase(); + + if (doctors.isExistingDoctor(doctorName)) { + Doctor deletedDoctor = doctors.deleteDoctor(doctorName); + assert deletedDoctor != null : "Deleted doctor is null!"; + + ui.showDoctorDeleted(deletedDoctor); + + for (int i = 0; i < appointments.getSize(); i++) { + String tempName = appointments.getAppointmentByIndex(i).getDoctor().getName(); + if (tempName.equals(doctorName)) { + appointments.getAppointmentByIndex(i).setDoctor(null); + break; + } + } + } else { + ui.printDoctorNotFound(doctorName); + } + storage.saveDoctors(doctors); + } +} diff --git a/src/main/java/seedu/rex/data/DoctorList.java b/src/main/java/seedu/rex/data/DoctorList.java index 43198fe606..a4a4d42c2c 100644 --- a/src/main/java/seedu/rex/data/DoctorList.java +++ b/src/main/java/seedu/rex/data/DoctorList.java @@ -1,6 +1,7 @@ package seedu.rex.data; import seedu.rex.data.hospital.Doctor; +import seedu.rex.data.hospital.Patient; import java.util.ArrayList; @@ -82,4 +83,14 @@ public Doctor getDoctorFromName(String name) { } return null; } + + public Doctor deleteDoctor(String doctorName) { + int i; + for (i = 0; i < getSize(); i++) { + if (getDoctorUsingIndex(i).getName().equals(doctorName)) { + break; + } + } + return doctors.remove(i); + } } diff --git a/src/main/java/seedu/rex/data/hospital/Doctor.java b/src/main/java/seedu/rex/data/hospital/Doctor.java index f098d71813..e73a96315b 100644 --- a/src/main/java/seedu/rex/data/hospital/Doctor.java +++ b/src/main/java/seedu/rex/data/hospital/Doctor.java @@ -1,5 +1,7 @@ package seedu.rex.data.hospital; +import java.time.format.DateTimeFormatter; + /** * Doctor class. */ @@ -18,4 +20,9 @@ public void setName(String name) { this.name = name; } + + @Override + public String toString() { + return name; + } } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 94c0fda84f..bfab2f6574 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -2,6 +2,7 @@ import seedu.rex.Rex; import seedu.rex.commands.AddCommand; +import seedu.rex.commands.AddDoctorCommand; import seedu.rex.commands.BookCommand; import seedu.rex.commands.Command; import seedu.rex.commands.CreateAppointmentCommand; @@ -10,6 +11,7 @@ import seedu.rex.commands.ExitCommand; import seedu.rex.commands.ListAppointmentsCommand; import seedu.rex.commands.ListPatientsCommand; +import seedu.rex.commands.RemoveDoctorCommand; import seedu.rex.commands.RetrieveCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -100,6 +102,12 @@ public static Command parse(String fullCommand) throws RexException { case RetrieveCommand.COMMAND_WORD: command = new RetrieveCommand(trimmedCommand); break; + case AddDoctorCommand.COMMAND_WORD: + command = new AddDoctorCommand(trimmedCommand); + break; + case RemoveDoctorCommand.COMMAND_WORD: + command = new RemoveDoctorCommand(trimmedCommand); + break; default: throw new RexException(Command.COMMAND_ERROR); } diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index 1e979bff8c..c0ba156cbc 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -1,6 +1,7 @@ package seedu.rex.storage; import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -194,4 +195,18 @@ public ArrayList loadDoctors() throws RexException { return doctors; } + + public void saveDoctors(DoctorList doctors) throws RexException { + assert doctors != null : "Saving null doctors ArrayList"; + + StringBuilder doctorsFileContent = new StringBuilder(); + + for (int i = 0; i < doctors.getSize(); i++) { + // Need to format tasks + doctorsFileContent.append(doctors.getDoctorUsingIndex(i)); + doctorsFileContent.append(System.lineSeparator()); + } + + writeToFile(doctorsFileContent, DOCTORS_FILE); + } } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 922d0b9770..295db0a22f 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -6,6 +6,7 @@ import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; +import seedu.rex.data.hospital.Doctor; import seedu.rex.data.hospital.Patient; import seedu.rex.storage.Storage; @@ -286,6 +287,19 @@ public void listPatients(PatientList patients) { public String getDoctorName() { printWithIndent("Enter doctor name: "); - return in.nextLine().trim(); + return in.nextLine().toUpperCase().trim(); + } + + public void showDoctorAdded(Doctor newDoctor) { + printWithIndent("Doctor added: " + newDoctor.getName()); + } + + public void showDoctorDeleted(Doctor deletedDoctor) { + printWithIndent("Doctor successfully deleted: "); + printWithIndent(deletedDoctor.toString()); + } + + public void printDoctorNotFound(String doctorName) { + printWithIndent("Patient " + doctorName + " not found in database!"); } } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index e393757a41..37948b6d95 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -102,6 +102,16 @@ Enter command: ____________________________________________________________ Enter command: ____________________________________________________________ + Doctor added: TAN + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Enter doctor name: + ☹ OOPS!!! No such doctor! + ____________________________________________________________ +Enter command: + ____________________________________________________________ + Enter doctor name: ____________________________________________________________ Here are the list of available appointments. 1. 2020-10-10 @@ -111,6 +121,7 @@ Enter command: ____________________________________________________________ Enter command: ____________________________________________________________ + Enter doctor name: ____________________________________________________________ Here are the list of available appointments. 1. 2020-10-10 @@ -121,14 +132,13 @@ Enter command: ____________________________________________________________ Enter command: ____________________________________________________________ - ____________________________________________________________ - Here are the list of available appointments. - ☹ OOPS!!! No appointments available! + Listing appointments for patient S9123456Z: + 1. 2020-10-10 ____________________________________________________________ Enter command: ____________________________________________________________ - Listing appointments for patient S9123456Z: - 1. 2020-10-10 + Doctor successfully deleted: + TAN ____________________________________________________________ Enter command: ____________________________________________________________ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 00492444b2..fd348304f0 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -24,11 +24,16 @@ create 2020-10-40 create 2020-10-10 +doctor tan book S9123456Z +t +book S9123456Z +tan 0 book S9123456Z +tan 1 -book S9123456Z appointments S9123456Z +nodoctor tan list bye \ No newline at end of file From 59f33282c27d1d2ba7c56f2fe34e9346dc4a4f53 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 14:01:30 +0800 Subject: [PATCH 071/148] Improve code --- src/main/java/seedu/rex/commands/RemoveDoctorCommand.java | 5 ++--- src/main/java/seedu/rex/data/DoctorList.java | 1 - src/main/java/seedu/rex/data/hospital/Doctor.java | 2 -- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/rex/commands/RemoveDoctorCommand.java b/src/main/java/seedu/rex/commands/RemoveDoctorCommand.java index ed178afe83..7b403e5478 100644 --- a/src/main/java/seedu/rex/commands/RemoveDoctorCommand.java +++ b/src/main/java/seedu/rex/commands/RemoveDoctorCommand.java @@ -5,7 +5,6 @@ import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Doctor; -import seedu.rex.data.hospital.Patient; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; @@ -16,7 +15,7 @@ public class RemoveDoctorCommand extends Command { public RemoveDoctorCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; } - + /** * Executes command. * @@ -30,7 +29,7 @@ public RemoveDoctorCommand(String trimmedCommand) { @Override public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, Storage storage) throws RexException { - + String doctorName = trimmedCommand.replaceFirst("(?i)" + COMMAND_WORD, "").trim().toUpperCase(); if (doctors.isExistingDoctor(doctorName)) { diff --git a/src/main/java/seedu/rex/data/DoctorList.java b/src/main/java/seedu/rex/data/DoctorList.java index a4a4d42c2c..6bdd38f231 100644 --- a/src/main/java/seedu/rex/data/DoctorList.java +++ b/src/main/java/seedu/rex/data/DoctorList.java @@ -1,7 +1,6 @@ package seedu.rex.data; import seedu.rex.data.hospital.Doctor; -import seedu.rex.data.hospital.Patient; import java.util.ArrayList; diff --git a/src/main/java/seedu/rex/data/hospital/Doctor.java b/src/main/java/seedu/rex/data/hospital/Doctor.java index e73a96315b..28098a9712 100644 --- a/src/main/java/seedu/rex/data/hospital/Doctor.java +++ b/src/main/java/seedu/rex/data/hospital/Doctor.java @@ -1,7 +1,5 @@ package seedu.rex.data.hospital; -import java.time.format.DateTimeFormatter; - /** * Doctor class. */ From 9fbea94c3f545f34bb2bc5f4bfc41a2d4e419797 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 14:37:45 +0800 Subject: [PATCH 072/148] Update docs --- docs/DeveloperGuide.md | 4 +++ docs/UserGuide.md | 58 +++++++++++++++++++++++++++++++++++++++-- docs/team/tanjunhong.md | 3 +++ 3 files changed, 63 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 9ac78d1200..d168ad45fc 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -23,11 +23,15 @@ Aim: To facilitate the role of the administrative staff and help them automate m |v1.0|admin|remove existing patient's details|remove unnecessary information.| |v1.0|admin|view all appointments of a patient|remind patients of their appointments.| |v1.0|admin|book an appointment for a patient|let them see the doctor.| +|v2.0|admin|add doctor|link doctor to appointment.| +|v2.0|admin|remove existing doctor's details|remove unnecessary information.| +|v2.0|admin|list patients|view patients.| ## Non-Functional Requirements * The program must be easy for admins to use. * The program must store patient's information. +* The program must store doctor's information. ## Glossary diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 78aa336401..efa7b430d8 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -78,7 +78,7 @@ Example of usage: `create` -### Create an appointment: `book` +### Book an appointment: `book` Books an appointment date. Format: `book NRIC` @@ -92,6 +92,56 @@ Example of usage: `book S7423213Z` +### Add a doctor: `doctor` +Adds a doctor. + +Format: `doctor NAME` + +* The `NAME` should not already be inside the list. + +Example of usage: + +`doctor tan` + +`doctor trump` + +### Remove a doctor: `doctor` +Remove a doctor. + +Format: `nodoctor NAME` + +* The `NAME` should be in the list. + +Example of usage: + +`nodoctor tan` + +`nodoctor trump` + +### View patient's appointments: `appointments` +View patient's appointments + +Format: `appointments NRIC` + +* The `NRIC` should be valid and in the list. + +Example of usage: + +`appointments S2233445D` + +`appointments S1234556F` + +### List patients: `list` +View patient's appointments + +Format: `list` + +* The patient list should not be empty. + +Example of usage: + +`list` + ## FAQ **Q**: How do I transfer my data to another computer? @@ -105,4 +155,8 @@ Example of usage: * Edit patient `edit NRIC` * Delete patient `delete NRIC` * Create appointment `create` -* Book appointment `book NRIC` \ No newline at end of file +* Book appointment `book NRIC` +* Add doctor `doctor NAME` +* Remove doctor `nodoctor NAME` +* View appointments of a patient `appointments NRIC` +* List patients `list` \ No newline at end of file diff --git a/docs/team/tanjunhong.md b/docs/team/tanjunhong.md index 8796529a66..3cbfd3dc67 100644 --- a/docs/team/tanjunhong.md +++ b/docs/team/tanjunhong.md @@ -6,3 +6,6 @@ Github T-shirt Winner ### Summary of Contributions * Bare-bones code * Ability to retrieve patients information using NRIC +* JUnit, Logging and Assertions +* Add and remove doctor +* Code cleanup From b202c2d1b527137cc43c91b2f35cdbc6fb259410 Mon Sep 17 00:00:00 2001 From: GoldenCorgi <42860714+GoldenCorgi@users.noreply.github.com> Date: Tue, 20 Oct 2020 18:58:40 +0800 Subject: [PATCH 073/148] edit appointments --- .../java/seedu/rex/commands/BookCommand.java | 2 +- .../rex/commands/EditAppointmentCommand.java | 76 +++++++++++++++++++ src/main/java/seedu/rex/parser/Parser.java | 20 ++--- src/main/java/seedu/rex/ui/Ui.java | 23 ++++++ 4 files changed, 107 insertions(+), 14 deletions(-) create mode 100644 src/main/java/seedu/rex/commands/EditAppointmentCommand.java diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index 67b1c9d720..80fe65c0f5 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -10,7 +10,7 @@ import java.util.logging.Level; -/** +/**a * Books appointments. */ public class BookCommand extends Command { diff --git a/src/main/java/seedu/rex/commands/EditAppointmentCommand.java b/src/main/java/seedu/rex/commands/EditAppointmentCommand.java new file mode 100644 index 0000000000..e602b88693 --- /dev/null +++ b/src/main/java/seedu/rex/commands/EditAppointmentCommand.java @@ -0,0 +1,76 @@ +package seedu.rex.commands; + +import seedu.rex.Rex; +import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import java.util.logging.Level; + +/** + * Edit appointment. + */ +public class EditAppointmentCommand extends Command { + + public static final String COMMAND_WORD = "editappt"; + private final String trimmedCommand; + + + + public EditAppointmentCommand(String trimmedCommand) { + this.trimmedCommand = trimmedCommand; + } + + /** + * Edit appointment using NRIC given. + * + * @param patients PatientList object. + * @param doctors DoctorList object. + * @param appointments AppointmentList object. + * @param ui Ui object. + * @param storage Storage object. + * @throws RexException If the input NRIC does not exist in system + */ + @Override + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, + Storage storage) throws RexException { + assert patients != null : "patient ArrayList is null"; + assert ui != null : "ui is null"; + assert storage != null : "storage is null"; + Rex.logger.log(Level.INFO, "going to extract NRIC"); + String nric = extractNric(trimmedCommand, COMMAND_WORD); + + if (!patients.isExistingPatient(nric)) { + throw new RexException("A patient with this NRIC has not been registered!"); + } + + try { + String indexSelected = ui.getAppointmentToEdit(appointments); + int index = Integer.parseInt(indexSelected) - 1; + if (index < 0 || index >= appointments.getSize()) { + throw new RexException("Index error!"); + } + Rex.logger.log(Level.INFO, "going to get doctor's name"); + String doctorName = ui.getDoctorName(); + if (!doctors.isExistingDoctor(doctorName)) { + throw new RexException("No such doctor!"); + } + + appointments.getAppointmentByIndex(index).bookPatient(patients.getPatientFromNric(nric)); + appointments.getAppointmentByIndex(index).bookDoctor(doctors.getDoctorFromName(doctorName)); + ui.showAppointmentBookedMessage(appointments.getAppointmentByIndex(index)); + + assert !appointments.isEmpty() : "No appointments!"; + storage.saveAppointments(appointments); + } catch (NumberFormatException e) { + throw new RexException("Index error!"); + } + + } +} diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index bfab2f6574..b712323742 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,18 +1,7 @@ package seedu.rex.parser; import seedu.rex.Rex; -import seedu.rex.commands.AddCommand; -import seedu.rex.commands.AddDoctorCommand; -import seedu.rex.commands.BookCommand; -import seedu.rex.commands.Command; -import seedu.rex.commands.CreateAppointmentCommand; -import seedu.rex.commands.DeleteCommand; -import seedu.rex.commands.EditCommand; -import seedu.rex.commands.ExitCommand; -import seedu.rex.commands.ListAppointmentsCommand; -import seedu.rex.commands.ListPatientsCommand; -import seedu.rex.commands.RemoveDoctorCommand; -import seedu.rex.commands.RetrieveCommand; +import seedu.rex.commands.*; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Doctor; @@ -108,7 +97,12 @@ public static Command parse(String fullCommand) throws RexException { case RemoveDoctorCommand.COMMAND_WORD: command = new RemoveDoctorCommand(trimmedCommand); break; - default: + + case EditAppointmentCommand.COMMAND_WORD: + command = new EditAppointmentCommand(trimmedCommand); + break; + + default: throw new RexException(Command.COMMAND_ERROR); } return command; diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 295db0a22f..9e59b16687 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -223,6 +223,29 @@ public String getAppointmentToBook(AppointmentList appointments) throws RexExcep showLine(); return in.nextLine(); } + /** + * Gets appointment to be Editted. + * + * @param appointments Arraylist of appointments. + * @return User input. + * @throws RexException If no appointments are available. + */ + public String getAppointmentToEdit(AppointmentList appointments) throws RexException { + showLine(); + printWithIndent("Here are the list of available appointments."); + int counter = 0; + for (Appointment appointment : appointments.getAppointments()) { + counter++; + printWithIndent(counter + ". " + appointment.getDate().toString()); + + } + if (counter == 0) { + throw new RexException("No appointments available!"); + } + printWithIndent("Please enter the index of appointment to edit"); + showLine(); + return in.nextLine(); + } /** * Shows appointment booking message. From c05fe3b89b7146f22234e7ae1f36dcdd1402dce2 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 23:04:48 +0800 Subject: [PATCH 074/148] Fix checkstyle errors --- .../java/seedu/rex/commands/BookCommand.java | 2 +- .../rex/commands/EditAppointmentCommand.java | 4 ---- src/main/java/seedu/rex/parser/Parser.java | 22 ++++++++++++++----- src/main/java/seedu/rex/ui/Ui.java | 9 ++++---- 4 files changed, 23 insertions(+), 14 deletions(-) diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookCommand.java index 80fe65c0f5..67b1c9d720 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookCommand.java @@ -10,7 +10,7 @@ import java.util.logging.Level; -/**a +/** * Books appointments. */ public class BookCommand extends Command { diff --git a/src/main/java/seedu/rex/commands/EditAppointmentCommand.java b/src/main/java/seedu/rex/commands/EditAppointmentCommand.java index e602b88693..f55a8244ac 100644 --- a/src/main/java/seedu/rex/commands/EditAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/EditAppointmentCommand.java @@ -5,12 +5,9 @@ import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -import java.time.LocalDate; -import java.time.format.DateTimeParseException; import java.util.logging.Level; /** @@ -22,7 +19,6 @@ public class EditAppointmentCommand extends Command { private final String trimmedCommand; - public EditAppointmentCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index b712323742..b9b3d3f2ac 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,7 +1,19 @@ package seedu.rex.parser; import seedu.rex.Rex; -import seedu.rex.commands.*; +import seedu.rex.commands.AddCommand; +import seedu.rex.commands.AddDoctorCommand; +import seedu.rex.commands.BookCommand; +import seedu.rex.commands.Command; +import seedu.rex.commands.CreateAppointmentCommand; +import seedu.rex.commands.DeleteCommand; +import seedu.rex.commands.EditAppointmentCommand; +import seedu.rex.commands.EditCommand; +import seedu.rex.commands.ExitCommand; +import seedu.rex.commands.ListAppointmentsCommand; +import seedu.rex.commands.ListPatientsCommand; +import seedu.rex.commands.RemoveDoctorCommand; +import seedu.rex.commands.RetrieveCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Doctor; @@ -98,11 +110,11 @@ public static Command parse(String fullCommand) throws RexException { command = new RemoveDoctorCommand(trimmedCommand); break; - case EditAppointmentCommand.COMMAND_WORD: - command = new EditAppointmentCommand(trimmedCommand); - break; + case EditAppointmentCommand.COMMAND_WORD: + command = new EditAppointmentCommand(trimmedCommand); + break; - default: + default: throw new RexException(Command.COMMAND_ERROR); } return command; diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 9e59b16687..3b42a3984c 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -103,10 +103,10 @@ public void showPatientAdded(Patient patient) { /** * Prints a message to indicate successful editting of a patient. * - * @param patient The newly editted Patient. + * @param patient The newly edited Patient. */ - public void showPatientEditted(Patient patient) { - printWithIndent("Patient successfully editted: "); + public void showPatientEdited(Patient patient) { + printWithIndent("Patient successfully edited: "); printWithIndent(patient.toString()); } @@ -223,8 +223,9 @@ public String getAppointmentToBook(AppointmentList appointments) throws RexExcep showLine(); return in.nextLine(); } + /** - * Gets appointment to be Editted. + * Gets appointment to be edited. * * @param appointments Arraylist of appointments. * @return User input. From 929e8a83b8647380c4ca32fbbff4f1aca84964f3 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 23:05:46 +0800 Subject: [PATCH 075/148] Fix bugs --- src/main/java/seedu/rex/commands/EditCommand.java | 2 +- text-ui-test/EXPECTED.TXT | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/rex/commands/EditCommand.java b/src/main/java/seedu/rex/commands/EditCommand.java index 7b0524d320..e3ccb91d1a 100644 --- a/src/main/java/seedu/rex/commands/EditCommand.java +++ b/src/main/java/seedu/rex/commands/EditCommand.java @@ -49,7 +49,7 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap int index = patients.editExistingPatient(ui.getPatientName(), nric, ui.getPatientDateOfBirth()); assert index > -1 : "Invalid index!"; ui.showLine(); - ui.showPatientEditted(patients.getPatientUsingIndex(index)); + ui.showPatientEdited(patients.getPatientUsingIndex(index)); storage.savePatients(patients); } } \ No newline at end of file diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 37948b6d95..a6ba63e852 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -63,7 +63,7 @@ Enter command: Enter patient name: Enter patient date of birth (YYYY-MM-DD) including the dashes: ____________________________________________________________ - Patient successfully editted: + Patient successfully edited: Donald, S9123456Z, 1962-06-14 ____________________________________________________________ Enter command: From da0a216ce0af19f498b96ec17b871e9daf7e92bf Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Tue, 20 Oct 2020 23:26:57 +0800 Subject: [PATCH 076/148] Rename classes --- ...AddCommand.java => AddPatientCommand.java} | 4 +- ...{BookCommand.java => BookApptCommand.java} | 10 ++-- ...entCommand.java => CreateApptCommand.java} | 2 +- ...Command.java => DeletePatientCommand.java} | 4 +- ...tmentCommand.java => EditApptCommand.java} | 16 +++++- ...itCommand.java => EditPatientCommand.java} | 4 +- ...mentsCommand.java => ListApptCommand.java} | 4 +- ...tsCommand.java => ListPatientCommand.java} | 2 +- ...mmand.java => RetrievePatientCommand.java} | 4 +- src/main/java/seedu/rex/parser/Parser.java | 54 +++++++++---------- .../java/seedu/rex/commands/CommandTest.java | 12 ++--- 11 files changed, 62 insertions(+), 54 deletions(-) rename src/main/java/seedu/rex/commands/{AddCommand.java => AddPatientCommand.java} (95%) rename src/main/java/seedu/rex/commands/{BookCommand.java => BookApptCommand.java} (87%) rename src/main/java/seedu/rex/commands/{CreateAppointmentCommand.java => CreateApptCommand.java} (96%) rename src/main/java/seedu/rex/commands/{DeleteCommand.java => DeletePatientCommand.java} (94%) rename src/main/java/seedu/rex/commands/{EditAppointmentCommand.java => EditApptCommand.java} (80%) rename src/main/java/seedu/rex/commands/{EditCommand.java => EditPatientCommand.java} (94%) rename src/main/java/seedu/rex/commands/{ListAppointmentsCommand.java => ListApptCommand.java} (94%) rename src/main/java/seedu/rex/commands/{ListPatientsCommand.java => ListPatientCommand.java} (93%) rename src/main/java/seedu/rex/commands/{RetrieveCommand.java => RetrievePatientCommand.java} (93%) diff --git a/src/main/java/seedu/rex/commands/AddCommand.java b/src/main/java/seedu/rex/commands/AddPatientCommand.java similarity index 95% rename from src/main/java/seedu/rex/commands/AddCommand.java rename to src/main/java/seedu/rex/commands/AddPatientCommand.java index f9546202c9..5245509771 100644 --- a/src/main/java/seedu/rex/commands/AddCommand.java +++ b/src/main/java/seedu/rex/commands/AddPatientCommand.java @@ -13,12 +13,12 @@ /** * Adds a patient to the list of patients. */ -public class AddCommand extends Command { +public class AddPatientCommand extends Command { public static final String COMMAND_WORD = "add"; private final String trimmedCommand; - public AddCommand(String trimmedCommand) { + public AddPatientCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; } diff --git a/src/main/java/seedu/rex/commands/BookCommand.java b/src/main/java/seedu/rex/commands/BookApptCommand.java similarity index 87% rename from src/main/java/seedu/rex/commands/BookCommand.java rename to src/main/java/seedu/rex/commands/BookApptCommand.java index 67b1c9d720..171e807ad2 100644 --- a/src/main/java/seedu/rex/commands/BookCommand.java +++ b/src/main/java/seedu/rex/commands/BookApptCommand.java @@ -13,12 +13,12 @@ /** * Books appointments. */ -public class BookCommand extends Command { +public class BookApptCommand extends Command { public static final String COMMAND_WORD = "book"; private final String trimmedCommand; - public BookCommand(String trimmedCommand) { + public BookApptCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; } @@ -54,11 +54,7 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap } if (!patients.isExistingPatient(nric)) { - ui.printPatientNotFound(nric); - ui.showCreatePatientMessage(nric); - Rex.logger.log(Level.INFO, "going to add patient..."); - new AddCommand("add " + nric).execute(patients, doctors, appointments, ui, storage); - ui.showLine(); + throw new RexException("Patient " + nric + " not found in database!"); } try { diff --git a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java b/src/main/java/seedu/rex/commands/CreateApptCommand.java similarity index 96% rename from src/main/java/seedu/rex/commands/CreateAppointmentCommand.java rename to src/main/java/seedu/rex/commands/CreateApptCommand.java index 328df57e54..e0c92a7130 100644 --- a/src/main/java/seedu/rex/commands/CreateAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/CreateApptCommand.java @@ -15,7 +15,7 @@ /** * Creates appointment. */ -public class CreateAppointmentCommand extends Command { +public class CreateApptCommand extends Command { public static final String COMMAND_WORD = "create"; diff --git a/src/main/java/seedu/rex/commands/DeleteCommand.java b/src/main/java/seedu/rex/commands/DeletePatientCommand.java similarity index 94% rename from src/main/java/seedu/rex/commands/DeleteCommand.java rename to src/main/java/seedu/rex/commands/DeletePatientCommand.java index 174d232835..838ebcc68f 100644 --- a/src/main/java/seedu/rex/commands/DeleteCommand.java +++ b/src/main/java/seedu/rex/commands/DeletePatientCommand.java @@ -14,11 +14,11 @@ /** * Deletes a Patient's data based on his NRIC. */ -public class DeleteCommand extends Command { +public class DeletePatientCommand extends Command { public static final String COMMAND_WORD = "delete"; private final String trimmedCommand; - public DeleteCommand(String trimmedCommand) { + public DeletePatientCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; } diff --git a/src/main/java/seedu/rex/commands/EditAppointmentCommand.java b/src/main/java/seedu/rex/commands/EditApptCommand.java similarity index 80% rename from src/main/java/seedu/rex/commands/EditAppointmentCommand.java rename to src/main/java/seedu/rex/commands/EditApptCommand.java index f55a8244ac..bc9e60d0a3 100644 --- a/src/main/java/seedu/rex/commands/EditAppointmentCommand.java +++ b/src/main/java/seedu/rex/commands/EditApptCommand.java @@ -5,6 +5,7 @@ import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; @@ -13,13 +14,13 @@ /** * Edit appointment. */ -public class EditAppointmentCommand extends Command { +public class EditApptCommand extends Command { public static final String COMMAND_WORD = "editappt"; private final String trimmedCommand; - public EditAppointmentCommand(String trimmedCommand) { + public EditApptCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; } @@ -47,6 +48,17 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap } try { + boolean hasAppointment = false; + for (Appointment appointment : appointments.getAppointments()) { + if (appointment.getPatient() != null && appointment.getPatient().getNric().equals(nric)) { + hasAppointment = true; + break; + } + } + if (!hasAppointment) { + throw new RexException("Patient has no appointment!"); + } + String indexSelected = ui.getAppointmentToEdit(appointments); int index = Integer.parseInt(indexSelected) - 1; if (index < 0 || index >= appointments.getSize()) { diff --git a/src/main/java/seedu/rex/commands/EditCommand.java b/src/main/java/seedu/rex/commands/EditPatientCommand.java similarity index 94% rename from src/main/java/seedu/rex/commands/EditCommand.java rename to src/main/java/seedu/rex/commands/EditPatientCommand.java index e3ccb91d1a..dd6d95579b 100644 --- a/src/main/java/seedu/rex/commands/EditCommand.java +++ b/src/main/java/seedu/rex/commands/EditPatientCommand.java @@ -13,12 +13,12 @@ /** * Edits a patient from the list of patients. */ -public class EditCommand extends Command { +public class EditPatientCommand extends Command { public static final String COMMAND_WORD = "edit"; private final String trimmedCommand; - public EditCommand(String trimmedCommand) { + public EditPatientCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; } diff --git a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java b/src/main/java/seedu/rex/commands/ListApptCommand.java similarity index 94% rename from src/main/java/seedu/rex/commands/ListAppointmentsCommand.java rename to src/main/java/seedu/rex/commands/ListApptCommand.java index ed26636c6c..5a2efbea84 100644 --- a/src/main/java/seedu/rex/commands/ListAppointmentsCommand.java +++ b/src/main/java/seedu/rex/commands/ListApptCommand.java @@ -11,12 +11,12 @@ import java.util.logging.Level; -public class ListAppointmentsCommand extends Command { +public class ListApptCommand extends Command { public static final String COMMAND_WORD = "appointments"; private final String trimmedCommand; - public ListAppointmentsCommand(String trimmedCommand) { + public ListApptCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; } diff --git a/src/main/java/seedu/rex/commands/ListPatientsCommand.java b/src/main/java/seedu/rex/commands/ListPatientCommand.java similarity index 93% rename from src/main/java/seedu/rex/commands/ListPatientsCommand.java rename to src/main/java/seedu/rex/commands/ListPatientCommand.java index ffc1eed872..61f250f488 100644 --- a/src/main/java/seedu/rex/commands/ListPatientsCommand.java +++ b/src/main/java/seedu/rex/commands/ListPatientCommand.java @@ -6,7 +6,7 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -public class ListPatientsCommand extends Command { +public class ListPatientCommand extends Command { public static final String COMMAND_WORD = "list"; diff --git a/src/main/java/seedu/rex/commands/RetrieveCommand.java b/src/main/java/seedu/rex/commands/RetrievePatientCommand.java similarity index 93% rename from src/main/java/seedu/rex/commands/RetrieveCommand.java rename to src/main/java/seedu/rex/commands/RetrievePatientCommand.java index 34b68cfef9..b838cbaa37 100644 --- a/src/main/java/seedu/rex/commands/RetrieveCommand.java +++ b/src/main/java/seedu/rex/commands/RetrievePatientCommand.java @@ -13,12 +13,12 @@ /** * Retrieves patient details. */ -public class RetrieveCommand extends Command { +public class RetrievePatientCommand extends Command { public static final String COMMAND_WORD = "retrieve"; private final String trimmedCommand; - public RetrieveCommand(String trimmedCommand) { + public RetrievePatientCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index b9b3d3f2ac..19e2efd194 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,19 +1,19 @@ package seedu.rex.parser; import seedu.rex.Rex; -import seedu.rex.commands.AddCommand; +import seedu.rex.commands.AddPatientCommand; import seedu.rex.commands.AddDoctorCommand; -import seedu.rex.commands.BookCommand; +import seedu.rex.commands.BookApptCommand; import seedu.rex.commands.Command; -import seedu.rex.commands.CreateAppointmentCommand; -import seedu.rex.commands.DeleteCommand; -import seedu.rex.commands.EditAppointmentCommand; -import seedu.rex.commands.EditCommand; +import seedu.rex.commands.CreateApptCommand; +import seedu.rex.commands.DeletePatientCommand; +import seedu.rex.commands.EditApptCommand; +import seedu.rex.commands.EditPatientCommand; import seedu.rex.commands.ExitCommand; -import seedu.rex.commands.ListAppointmentsCommand; -import seedu.rex.commands.ListPatientsCommand; +import seedu.rex.commands.ListApptCommand; +import seedu.rex.commands.ListPatientCommand; import seedu.rex.commands.RemoveDoctorCommand; -import seedu.rex.commands.RetrieveCommand; +import seedu.rex.commands.RetrievePatientCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.data.hospital.Doctor; @@ -79,29 +79,29 @@ public static Command parse(String fullCommand) throws RexException { case ExitCommand.COMMAND_WORD: command = new ExitCommand(); break; - case AddCommand.COMMAND_WORD: - command = new AddCommand(trimmedCommand); + case AddPatientCommand.COMMAND_WORD: + command = new AddPatientCommand(trimmedCommand); break; - case BookCommand.COMMAND_WORD: - command = new BookCommand(trimmedCommand); + case BookApptCommand.COMMAND_WORD: + command = new BookApptCommand(trimmedCommand); break; - case CreateAppointmentCommand.COMMAND_WORD: - command = new CreateAppointmentCommand(); + case CreateApptCommand.COMMAND_WORD: + command = new CreateApptCommand(); break; - case EditCommand.COMMAND_WORD: - command = new EditCommand(trimmedCommand); + case EditPatientCommand.COMMAND_WORD: + command = new EditPatientCommand(trimmedCommand); break; - case DeleteCommand.COMMAND_WORD: - command = new DeleteCommand(trimmedCommand); + case DeletePatientCommand.COMMAND_WORD: + command = new DeletePatientCommand(trimmedCommand); break; - case ListAppointmentsCommand.COMMAND_WORD: - command = new ListAppointmentsCommand(trimmedCommand); + case ListApptCommand.COMMAND_WORD: + command = new ListApptCommand(trimmedCommand); break; - case ListPatientsCommand.COMMAND_WORD: - command = new ListPatientsCommand(); + case ListPatientCommand.COMMAND_WORD: + command = new ListPatientCommand(); break; - case RetrieveCommand.COMMAND_WORD: - command = new RetrieveCommand(trimmedCommand); + case RetrievePatientCommand.COMMAND_WORD: + command = new RetrievePatientCommand(trimmedCommand); break; case AddDoctorCommand.COMMAND_WORD: command = new AddDoctorCommand(trimmedCommand); @@ -110,8 +110,8 @@ public static Command parse(String fullCommand) throws RexException { command = new RemoveDoctorCommand(trimmedCommand); break; - case EditAppointmentCommand.COMMAND_WORD: - command = new EditAppointmentCommand(trimmedCommand); + case EditApptCommand.COMMAND_WORD: + command = new EditApptCommand(trimmedCommand); break; default: diff --git a/src/test/java/seedu/rex/commands/CommandTest.java b/src/test/java/seedu/rex/commands/CommandTest.java index 25c99799f1..adcbd7a381 100644 --- a/src/test/java/seedu/rex/commands/CommandTest.java +++ b/src/test/java/seedu/rex/commands/CommandTest.java @@ -11,15 +11,15 @@ class CommandTest { @Test void isInteger_456456_returnsTrue() { - RetrieveCommand retrieveCommand = new RetrieveCommand(""); - assertTrue(retrieveCommand.isInteger("456456")); + RetrievePatientCommand retrievePatientCommand = new RetrievePatientCommand(""); + assertTrue(retrievePatientCommand.isInteger("456456")); } @Test void extractNric_retrieveS9123456D_returnsS9123456DString() { - RetrieveCommand retrieveCommand = new RetrieveCommand(""); + RetrievePatientCommand retrievePatientCommand = new RetrievePatientCommand(""); try { - assertEquals(retrieveCommand.extractNric("retrieve S9123456D", "retrieve"), "S9123456D"); + assertEquals(retrievePatientCommand.extractNric("retrieve S9123456D", "retrieve"), "S9123456D"); } catch (RexException e) { e.printStackTrace(); } @@ -27,7 +27,7 @@ void extractNric_retrieveS9123456D_returnsS9123456DString() { @Test void extractNric_retrieveS91D_expectException() { - RetrieveCommand retrieveCommand = new RetrieveCommand(""); - assertThrows(RexException.class, () -> retrieveCommand.extractNric("retrieve S91D", "retrieve")); + RetrievePatientCommand retrievePatientCommand = new RetrievePatientCommand(""); + assertThrows(RexException.class, () -> retrievePatientCommand.extractNric("retrieve S91D", "retrieve")); } } \ No newline at end of file From a32964c4d9a56c9543641b6c4f70a2383727b7f2 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 21 Oct 2020 00:07:33 +0800 Subject: [PATCH 077/148] Update test cases --- docs/DeveloperGuide.md | 15 ++++++++++++- docs/UserGuide.md | 16 +++++++++++++- ...rCommand.java => DeleteDoctorCommand.java} | 4 ++-- .../seedu/rex/commands/EditApptCommand.java | 7 ++++--- .../seedu/rex/data/hospital/Appointment.java | 1 + src/main/java/seedu/rex/parser/Parser.java | 6 +++--- src/main/java/seedu/rex/ui/Ui.java | 13 ++++++++++++ text-ui-test/EXPECTED.TXT | 21 ++++++++++++++++++- text-ui-test/input.txt | 5 +++++ 9 files changed, 77 insertions(+), 11 deletions(-) rename src/main/java/seedu/rex/commands/{RemoveDoctorCommand.java => DeleteDoctorCommand.java} (94%) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index d168ad45fc..5c4109ed25 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -26,12 +26,14 @@ Aim: To facilitate the role of the administrative staff and help them automate m |v2.0|admin|add doctor|link doctor to appointment.| |v2.0|admin|remove existing doctor's details|remove unnecessary information.| |v2.0|admin|list patients|view patients.| +|v2.0|admin|edit appointments|update them.| ## Non-Functional Requirements * The program must be easy for admins to use. * The program must store patient's information. * The program must store doctor's information. +* The program should run on any system running Java 11. ## Glossary @@ -39,4 +41,15 @@ Aim: To facilitate the role of the administrative staff and help them automate m ## 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} +### Initial setup +1. Download the jar file and copy it into an empty directory +2. Open command prompt, and point it to that directory +3. Type in `java -jar Rex.jar` to run the file +### Deleting a patient +There must a patient in the list. +1. `delete 1` - Deletes the patient at the first index +2. `delete 0` - It should throw error and not delete a patient. +### Adding a patient +1. `add S9999999D` - Adds a patient with NRIC `S9999999D` to the list. +2. `add S9999999D` - It should not add a patient and throw error as patient already exists. +3. `add cat` - It should throw error and not add patients as it is invalid NRIC. \ No newline at end of file diff --git a/docs/UserGuide.md b/docs/UserGuide.md index efa7b430d8..7369888787 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -142,6 +142,19 @@ Example of usage: `list` +### Edit patient's appointment: `editappt` +Edit patient's appointment + +Format: `editapp NRIC` + +* The patient with `NRIC` should already exist. +* The program will prompt for appointment date and + +Example of usage: + +`editapp S9900999D` +`editapp S9900299D` + ## FAQ **Q**: How do I transfer my data to another computer? @@ -159,4 +172,5 @@ Example of usage: * Add doctor `doctor NAME` * Remove doctor `nodoctor NAME` * View appointments of a patient `appointments NRIC` -* List patients `list` \ No newline at end of file +* List patients `list` +* Edit patient's appointment `editappt` \ No newline at end of file diff --git a/src/main/java/seedu/rex/commands/RemoveDoctorCommand.java b/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java similarity index 94% rename from src/main/java/seedu/rex/commands/RemoveDoctorCommand.java rename to src/main/java/seedu/rex/commands/DeleteDoctorCommand.java index 7b403e5478..a6e8e33cf4 100644 --- a/src/main/java/seedu/rex/commands/RemoveDoctorCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java @@ -8,11 +8,11 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; -public class RemoveDoctorCommand extends Command { +public class DeleteDoctorCommand extends Command { public static final String COMMAND_WORD = "nodoctor"; private final String trimmedCommand; - public RemoveDoctorCommand(String trimmedCommand) { + public DeleteDoctorCommand(String trimmedCommand) { this.trimmedCommand = trimmedCommand; } diff --git a/src/main/java/seedu/rex/commands/EditApptCommand.java b/src/main/java/seedu/rex/commands/EditApptCommand.java index bc9e60d0a3..070c606dcc 100644 --- a/src/main/java/seedu/rex/commands/EditApptCommand.java +++ b/src/main/java/seedu/rex/commands/EditApptCommand.java @@ -5,7 +5,6 @@ import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; -import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; @@ -49,8 +48,10 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap try { boolean hasAppointment = false; - for (Appointment appointment : appointments.getAppointments()) { - if (appointment.getPatient() != null && appointment.getPatient().getNric().equals(nric)) { + for (int i = 0; i < appointments.getSize(); i++) { + if (appointments.getAppointmentByIndex(i).getPatient() != null + && appointments.getAppointmentByIndex(i).getPatient().getNric().equals(nric)) { + appointments.getAppointmentByIndex(i).removeBooking(); hasAppointment = true; break; } diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java index a6f1b5d8bd..b877544011 100644 --- a/src/main/java/seedu/rex/data/hospital/Appointment.java +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -80,6 +80,7 @@ public void bookPatient(Patient patient) { public void removeBooking() { this.patient = null; + this.doctor = null; isBooked = false; } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 19e2efd194..065765d2e0 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -12,7 +12,7 @@ import seedu.rex.commands.ExitCommand; import seedu.rex.commands.ListApptCommand; import seedu.rex.commands.ListPatientCommand; -import seedu.rex.commands.RemoveDoctorCommand; +import seedu.rex.commands.DeleteDoctorCommand; import seedu.rex.commands.RetrievePatientCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; @@ -106,8 +106,8 @@ public static Command parse(String fullCommand) throws RexException { case AddDoctorCommand.COMMAND_WORD: command = new AddDoctorCommand(trimmedCommand); break; - case RemoveDoctorCommand.COMMAND_WORD: - command = new RemoveDoctorCommand(trimmedCommand); + case DeleteDoctorCommand.COMMAND_WORD: + command = new DeleteDoctorCommand(trimmedCommand); break; case EditApptCommand.COMMAND_WORD: diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 3b42a3984c..b20d24e2d8 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -326,4 +326,17 @@ public void showDoctorDeleted(Doctor deletedDoctor) { public void printDoctorNotFound(String doctorName) { printWithIndent("Patient " + doctorName + " not found in database!"); } + + public LocalDate getAppointmentDate() { + while (true) { + try { + printWithIndent("Enter appointment date (YYYY-MM-DD) including the dashes: "); + return LocalDate.parse(in.nextLine().trim()); + } catch (DateTimeParseException e) { + showLine(); + showDateInputError(); + showLine(); + } + } + } } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index a6ba63e852..59200c5077 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -63,7 +63,7 @@ Enter command: Enter patient name: Enter patient date of birth (YYYY-MM-DD) including the dashes: ____________________________________________________________ - Patient successfully edited: + Patient successfully edited: Donald, S9123456Z, 1962-06-14 ____________________________________________________________ Enter command: @@ -135,6 +135,25 @@ Enter command: Listing appointments for patient S9123456Z: 1. 2020-10-10 ____________________________________________________________ +Enter command: + ____________________________________________________________ + Please enter the date of appointment in YYYY-MM-DD. + ____________________________________________________________ + ____________________________________________________________ + New appointment created! + ____________________________________________________________ +Enter command: + ____________________________________________________________ + ____________________________________________________________ + Here are the list of available appointments. + 1. 2020-10-10 + 2. 2020-12-12 + Please enter the index of appointment to edit + ____________________________________________________________ + Enter doctor name: + ____________________________________________________________ + Appointment on 2020-10-10 booked! + ____________________________________________________________ Enter command: ____________________________________________________________ Doctor successfully deleted: diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index fd348304f0..976e4cc2c1 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -34,6 +34,11 @@ book S9123456Z tan 1 appointments S9123456Z +create +2020-12-12 +editappt S9123456Z +1 +tan nodoctor tan list bye \ No newline at end of file From b8f1d1c2c25c7cd55fe281603b2845faa25911d2 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 21 Oct 2020 00:08:00 +0800 Subject: [PATCH 078/148] Remove doctors.txt --- data/doctors.txt | 1 - 1 file changed, 1 deletion(-) delete mode 100644 data/doctors.txt diff --git a/data/doctors.txt b/data/doctors.txt deleted file mode 100644 index 00b40c13aa..0000000000 --- a/data/doctors.txt +++ /dev/null @@ -1 +0,0 @@ -TAN From 90ea6747d577fddb9196db1d9319d478f162807d Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 21 Oct 2020 01:03:22 +0800 Subject: [PATCH 079/148] Add tests and documentation --- docs/DeveloperGuide.md | 24 +++++++++++++++++ docs/pictures/UML.png | Bin 0 -> 25041 bytes docs/team/tanjunhong.md | 2 +- src/main/java/seedu/rex/parser/Parser.java | 4 +-- .../seedu/rex/data/AppointmentListTest.java | 25 ++++++++++++++++++ .../java/seedu/rex/data/PatientListTest.java | 17 ++++++++++++ 6 files changed, 69 insertions(+), 3 deletions(-) create mode 100644 docs/pictures/UML.png create mode 100644 src/test/java/seedu/rex/data/AppointmentListTest.java create mode 100644 src/test/java/seedu/rex/data/PatientListTest.java diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 5c4109ed25..2058606de8 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -4,6 +4,30 @@ {Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} +The app was mainly inspired by [addressbook-level2](https://github.com/se-edu/addressbook-level2). + +### Design +The App consists of a few main components. + +* UI: The UI that deals with getting user input and displaying output. +* Command: Command to be executed. +* Parser: Parse user input and make sense of it. +* Storage: Reads data from, and writes data to, the hard disk. +* Rex: The main class that initialize the app and starts running. + +The rest are just objects that the app requires. + +The diagram below shows the basic design. +![image info](./pictures/UML.png) + +### Implementation +Retrieve Command +The flow is for retrieve command is as follows {Replace with sequence diagram} +1. User calls retrieve command with NRIC +2. Ui receives the command, returns it to Main and Main calls parser to parse +3. Parser returns with retrieve command, and Main executes retrieve command +4. Retrieve command extracts NRIC using parser, searches through the patients list and returns the patient +5. Ui receives the patient and prints it. ## Product scope ### Target user profile diff --git a/docs/pictures/UML.png b/docs/pictures/UML.png new file mode 100644 index 0000000000000000000000000000000000000000..831ff90bf2d68245461ba389b6b353079322d751 GIT binary patch literal 25041 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μv(P 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 ktvq@Dzdy%<$NCkjgU1f2WU)UzvAtlmGw# literal 0 HcmV?d00001 diff --git a/docs/team/tanjunhong.md b/docs/team/tanjunhong.md index 3cbfd3dc67..6b7188ae68 100644 --- a/docs/team/tanjunhong.md +++ b/docs/team/tanjunhong.md @@ -6,6 +6,6 @@ Github T-shirt Winner ### Summary of Contributions * Bare-bones code * Ability to retrieve patients information using NRIC -* JUnit, Logging and Assertions * Add and remove doctor +* JUnit, Logging and Assertions * Code cleanup diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 065765d2e0..3923d7cbdd 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -1,18 +1,18 @@ package seedu.rex.parser; import seedu.rex.Rex; -import seedu.rex.commands.AddPatientCommand; import seedu.rex.commands.AddDoctorCommand; +import seedu.rex.commands.AddPatientCommand; import seedu.rex.commands.BookApptCommand; import seedu.rex.commands.Command; import seedu.rex.commands.CreateApptCommand; +import seedu.rex.commands.DeleteDoctorCommand; import seedu.rex.commands.DeletePatientCommand; import seedu.rex.commands.EditApptCommand; import seedu.rex.commands.EditPatientCommand; import seedu.rex.commands.ExitCommand; import seedu.rex.commands.ListApptCommand; import seedu.rex.commands.ListPatientCommand; -import seedu.rex.commands.DeleteDoctorCommand; import seedu.rex.commands.RetrievePatientCommand; import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; diff --git a/src/test/java/seedu/rex/data/AppointmentListTest.java b/src/test/java/seedu/rex/data/AppointmentListTest.java new file mode 100644 index 0000000000..304f0c4263 --- /dev/null +++ b/src/test/java/seedu/rex/data/AppointmentListTest.java @@ -0,0 +1,25 @@ +package seedu.rex.data; + +import org.junit.jupiter.api.Test; +import seedu.rex.data.hospital.Appointment; + +import java.time.LocalDate; +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.*; + +class AppointmentListTest { + + @Test + void isEmpty_empty_true() { + AppointmentList appointmentList = new AppointmentList(); + assertTrue(appointmentList.isEmpty()); + } + + @Test + void isEmpty_1Appointment_false() { + AppointmentList appointmentList = new AppointmentList(); + appointmentList.addAppointment(new Appointment(LocalDate.now())); + assertFalse(appointmentList.isEmpty()); + } +} \ No newline at end of file diff --git a/src/test/java/seedu/rex/data/PatientListTest.java b/src/test/java/seedu/rex/data/PatientListTest.java new file mode 100644 index 0000000000..ca5c0b42c2 --- /dev/null +++ b/src/test/java/seedu/rex/data/PatientListTest.java @@ -0,0 +1,17 @@ +package seedu.rex.data; + +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PatientListTest { + + @Test + void getSize_onePatient_1() { + PatientList patientList = new PatientList(); + patientList.addNewPatient("test", "S9911444D", LocalDate.now()); + assertEquals(patientList.getSize(), 1); + } +} \ No newline at end of file From 783f744a0a4111b65cf23ca8bf1f1c93eecad343 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 21 Oct 2020 01:06:12 +0800 Subject: [PATCH 080/148] Fix checkstyle errors --- src/test/java/seedu/rex/data/AppointmentListTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/rex/data/AppointmentListTest.java b/src/test/java/seedu/rex/data/AppointmentListTest.java index 304f0c4263..3965247fd8 100644 --- a/src/test/java/seedu/rex/data/AppointmentListTest.java +++ b/src/test/java/seedu/rex/data/AppointmentListTest.java @@ -4,9 +4,9 @@ import seedu.rex.data.hospital.Appointment; import java.time.LocalDate; -import java.util.ArrayList; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; class AppointmentListTest { From ad8ae1e1d5fb351f8b4f97a26cd6369371899740 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Wed, 21 Oct 2020 01:26:12 +0800 Subject: [PATCH 081/148] Fix minor bugs --- src/main/java/seedu/rex/commands/DeleteDoctorCommand.java | 3 +++ src/main/java/seedu/rex/commands/DeletePatientCommand.java | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java b/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java index a6e8e33cf4..7eb3038576 100644 --- a/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java @@ -41,6 +41,8 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap for (int i = 0; i < appointments.getSize(); i++) { String tempName = appointments.getAppointmentByIndex(i).getDoctor().getName(); if (tempName.equals(doctorName)) { + appointments.getAppointmentByIndex(i).setPatient(null); + appointments.getAppointmentByIndex(i).removeBooking(); appointments.getAppointmentByIndex(i).setDoctor(null); break; } @@ -48,6 +50,7 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap } else { ui.printDoctorNotFound(doctorName); } + storage.saveAppointments(appointments); storage.saveDoctors(doctors); } } diff --git a/src/main/java/seedu/rex/commands/DeletePatientCommand.java b/src/main/java/seedu/rex/commands/DeletePatientCommand.java index 838ebcc68f..61d86d96f6 100644 --- a/src/main/java/seedu/rex/commands/DeletePatientCommand.java +++ b/src/main/java/seedu/rex/commands/DeletePatientCommand.java @@ -50,7 +50,9 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap for (int i = 0; i < appointments.getSize(); i++) { String tempNric = appointments.getAppointmentByIndex(i).getPatient().getNric(); if (tempNric.contentEquals(nric)) { - appointments.removeAppointmentByIndex(i); + appointments.getAppointmentByIndex(i).setPatient(null); + appointments.getAppointmentByIndex(i).removeBooking(); + appointments.getAppointmentByIndex(i).setDoctor(null); break; } } @@ -58,5 +60,6 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap ui.printPatientNotFound(nric); } storage.savePatients(patients); + storage.saveAppointments(appointments); } } From 59071a50f4e2744e12abb302977560a4ae3409e8 Mon Sep 17 00:00:00 2001 From: kiathwe97 Date: Wed, 21 Oct 2020 19:48:14 +0800 Subject: [PATCH 082/148] Add previously viewed list --- .../seedu/rex/commands/BookApptCommand.java | 14 +++++----- .../java/seedu/rex/data/AppointmentList.java | 1 - .../seedu/rex/data/hospital/Appointment.java | 7 +++-- src/main/java/seedu/rex/parser/Parser.java | 12 +++++++-- src/main/java/seedu/rex/ui/Ui.java | 27 +++++++++++++++++++ 5 files changed, 50 insertions(+), 11 deletions(-) diff --git a/src/main/java/seedu/rex/commands/BookApptCommand.java b/src/main/java/seedu/rex/commands/BookApptCommand.java index 171e807ad2..cda8fc6fc6 100644 --- a/src/main/java/seedu/rex/commands/BookApptCommand.java +++ b/src/main/java/seedu/rex/commands/BookApptCommand.java @@ -5,6 +5,7 @@ import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; @@ -58,15 +59,16 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap } try { - String indexSelected = ui.getAppointmentToBook(appointments); - int index = Integer.parseInt(indexSelected) - 1; + System.out.println("Here are the list of available appointments: "); + /*int index = Integer.parseInt(indexSelected) - 1; if (index < 0 || index >= appointments.getSize()) { throw new RexException("Index error!"); - } + }*/ Rex.logger.log(Level.INFO, "booking appointment for patient and doctor..."); - appointments.getAppointmentByIndex(index).bookPatient(patients.getPatientFromNric(nric)); - appointments.getAppointmentByIndex(index).bookDoctor(doctors.getDoctorFromName(doctorName)); - ui.showAppointmentBookedMessage(appointments.getAppointmentByIndex(index)); + Appointment chosenAppointment = ui.getItemOfArrayList(appointments.getAppointments()); + chosenAppointment.bookPatient(patients.getPatientFromNric(nric)); + chosenAppointment.bookDoctor(doctors.getDoctorFromName(doctorName)); + ui.showAppointmentBookedMessage(chosenAppointment); assert !appointments.isEmpty() : "No appointments!"; storage.saveAppointments(appointments); diff --git a/src/main/java/seedu/rex/data/AppointmentList.java b/src/main/java/seedu/rex/data/AppointmentList.java index e6f5589bb0..0410533843 100644 --- a/src/main/java/seedu/rex/data/AppointmentList.java +++ b/src/main/java/seedu/rex/data/AppointmentList.java @@ -8,7 +8,6 @@ * Contains ArrayList of appointments. */ public class AppointmentList { - private final ArrayList appointments; public AppointmentList() { diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java index b877544011..af330f4661 100644 --- a/src/main/java/seedu/rex/data/hospital/Appointment.java +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -6,7 +6,6 @@ * Appointment class. */ public class Appointment { - private LocalDate date; private String time; private Patient patient; @@ -97,7 +96,11 @@ public String toString() { String patientNric = patient == null ? null : patient.getNric(); String doctorName = doctor == null ? null : doctor.getName(); - return date + ", " + bookedStatus + ", " + patientNric + ", " + doctorName; + if (bookedStatus.contentEquals("booked")) { + return date + ", " + bookedStatus + ", " + patientNric + ", " + doctorName; + } else { + return date + ", " + bookedStatus; + } } public void bookDoctor(Doctor doctor) { diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 3923d7cbdd..ad699ff0c3 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -50,8 +50,16 @@ public static Appointment readAppointment(String line) { String[] appointmentComponents = line.split(", "); LocalDate date = LocalDate.parse(appointmentComponents[0]); String bookedStatus = appointmentComponents[1]; - String nric = appointmentComponents[2]; - String doctorName = appointmentComponents[3]; + String nric; + String doctorName; + if (bookedStatus.contentEquals("booked")){ + nric = appointmentComponents[2]; + doctorName = appointmentComponents[3]; + } else { + nric = null; + doctorName = null; + } + Appointment appointment = new Appointment(date); if (bookedStatus.equals("booked")) { appointment.bookPatient(Rex.getPatients().getPatientFromNric(nric)); diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index b20d24e2d8..3cb0e48393 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -12,6 +12,7 @@ import java.time.LocalDate; import java.time.format.DateTimeParseException; +import java.util.ArrayList; import java.util.Scanner; /** @@ -339,4 +340,30 @@ public LocalDate getAppointmentDate() { } } } + + public int displayArrayList(ArrayList list) { + int i; + for (i = 0; i < list.size(); i++) { + String iString = String.valueOf(i + 1); + System.out.println(iString + ". " + list.get(i)); + } + return list.size(); + } + + public void indexOutOfBoundsMessage(int maxAllowableInput) { + System.out.print("Index out of bounds! Input should be between 1 to " + maxAllowableInput + "."); + } + + public T getItemOfArrayList(ArrayList list) { + int maxIndex = displayArrayList(list); + System.out.println("Enter the index you want: "); + String inputString = in.nextLine(); + int input = Integer.parseInt(inputString); + try { + return list.get(input - 1); + } catch (IndexOutOfBoundsException e) { + indexOutOfBoundsMessage(maxIndex); + return null; + } + } } From 8566f75342896996255f19be025d937d43855e29 Mon Sep 17 00:00:00 2001 From: kiathwe97 Date: Wed, 21 Oct 2020 20:13:47 +0800 Subject: [PATCH 083/148] Add selective display capability --- .../seedu/rex/commands/BookApptCommand.java | 10 ++++- src/main/java/seedu/rex/ui/Ui.java | 37 ++++++++++++++++--- 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/rex/commands/BookApptCommand.java b/src/main/java/seedu/rex/commands/BookApptCommand.java index cda8fc6fc6..1b73589e1c 100644 --- a/src/main/java/seedu/rex/commands/BookApptCommand.java +++ b/src/main/java/seedu/rex/commands/BookApptCommand.java @@ -9,6 +9,7 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +import java.util.ArrayList; import java.util.logging.Level; /** @@ -65,7 +66,14 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap throw new RexException("Index error!"); }*/ Rex.logger.log(Level.INFO, "booking appointment for patient and doctor..."); - Appointment chosenAppointment = ui.getItemOfArrayList(appointments.getAppointments()); + ArrayList indicesToShow = new ArrayList(); + for (int i = 0; i < appointments.getSize(); i++){ + Appointment appointment = appointments.getAppointments().get(i); + if (!appointment.isBooked()){ + indicesToShow.add(i); + } + } + Appointment chosenAppointment = ui.getItemOfArrayList(appointments.getAppointments(), indicesToShow); chosenAppointment.bookPatient(patients.getPatientFromNric(nric)); chosenAppointment.bookDoctor(doctors.getDoctorFromName(doctorName)); ui.showAppointmentBookedMessage(chosenAppointment); diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 3cb0e48393..e7ac3a5442 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -341,26 +341,51 @@ public LocalDate getAppointmentDate() { } } - public int displayArrayList(ArrayList list) { + /** + * Displays only the Objects in ArrayList that is required to be shown + * + * @param list Generic ArrayList + * @param indicesToShow ArrayList containing Integers corresponding to the indices of list that you want to display + * @param + * @return Object in ArrayList + */ + public int displayArrayList(ArrayList list, ArrayList indicesToShow) { int i; - for (i = 0; i < list.size(); i++) { + for (i = 0; i < indicesToShow.size(); i++) { String iString = String.valueOf(i + 1); - System.out.println(iString + ". " + list.get(i)); + int indexToShow = indicesToShow.get(i); + System.out.println(iString + ". " + list.get(indexToShow)); } return list.size(); } + /** + * Alerts user that there is a maximum allowable input. + * @param maxAllowableInput maximum allowable input + */ public void indexOutOfBoundsMessage(int maxAllowableInput) { System.out.print("Index out of bounds! Input should be between 1 to " + maxAllowableInput + "."); } - public T getItemOfArrayList(ArrayList list) { - int maxIndex = displayArrayList(list); + /** Gets object of Arraylist corresponding to user selection. + * + * @param list Generic ArrayList + * @param indicesToShow ArrayList containing Integers corresponding to the indices of list that you want to display + * @param + * @return Object in ArrayList + */ + public T getItemOfArrayList(ArrayList list, ArrayList indicesToShow) { + int maxIndex = displayArrayList(list, indicesToShow); + if (maxIndex < 1){ + System.out.println("There are no available appointments to book."); + return null; + } System.out.println("Enter the index you want: "); String inputString = in.nextLine(); int input = Integer.parseInt(inputString); try { - return list.get(input - 1); + int index = indicesToShow.get(input-1); + return list.get(index); } catch (IndexOutOfBoundsException e) { indexOutOfBoundsMessage(maxIndex); return null; From eff747ae395900ae4dba8ca3bc08eb1bb007fc02 Mon Sep 17 00:00:00 2001 From: kiathwe97 Date: Wed, 21 Oct 2020 20:21:46 +0800 Subject: [PATCH 084/148] Code refactor --- .../seedu/rex/commands/BookApptCommand.java | 6 +++--- src/main/java/seedu/rex/parser/Parser.java | 2 +- src/main/java/seedu/rex/ui/Ui.java | 18 +++++++++--------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/main/java/seedu/rex/commands/BookApptCommand.java b/src/main/java/seedu/rex/commands/BookApptCommand.java index 1b73589e1c..04cafaa544 100644 --- a/src/main/java/seedu/rex/commands/BookApptCommand.java +++ b/src/main/java/seedu/rex/commands/BookApptCommand.java @@ -66,10 +66,10 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap throw new RexException("Index error!"); }*/ Rex.logger.log(Level.INFO, "booking appointment for patient and doctor..."); - ArrayList indicesToShow = new ArrayList(); - for (int i = 0; i < appointments.getSize(); i++){ + ArrayList indicesToShow = new ArrayList(); + for (int i = 0; i < appointments.getSize(); i++) { Appointment appointment = appointments.getAppointments().get(i); - if (!appointment.isBooked()){ + if (!appointment.isBooked()) { indicesToShow.add(i); } } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index ad699ff0c3..899c0268f2 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -52,7 +52,7 @@ public static Appointment readAppointment(String line) { String bookedStatus = appointmentComponents[1]; String nric; String doctorName; - if (bookedStatus.contentEquals("booked")){ + if (bookedStatus.contentEquals("booked")) { nric = appointmentComponents[2]; doctorName = appointmentComponents[3]; } else { diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index e7ac3a5442..dac48908b0 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -342,19 +342,19 @@ public LocalDate getAppointmentDate() { } /** - * Displays only the Objects in ArrayList that is required to be shown + * Displays only the Objects in ArrayList that is required to be shown. * * @param list Generic ArrayList * @param indicesToShow ArrayList containing Integers corresponding to the indices of list that you want to display - * @param + * @param Generic class * @return Object in ArrayList */ - public int displayArrayList(ArrayList list, ArrayList indicesToShow) { + public int displayArrayList(ArrayList list, ArrayList indicesToShow) { int i; for (i = 0; i < indicesToShow.size(); i++) { - String iString = String.valueOf(i + 1); + String indexString = String.valueOf(i + 1); int indexToShow = indicesToShow.get(i); - System.out.println(iString + ". " + list.get(indexToShow)); + System.out.println(indexString + ". " + list.get(indexToShow)); } return list.size(); } @@ -371,12 +371,12 @@ public void indexOutOfBoundsMessage(int maxAllowableInput) { * * @param list Generic ArrayList * @param indicesToShow ArrayList containing Integers corresponding to the indices of list that you want to display - * @param + * @param Generic class * @return Object in ArrayList */ - public T getItemOfArrayList(ArrayList list, ArrayList indicesToShow) { + public T getItemOfArrayList(ArrayList list, ArrayList indicesToShow) { int maxIndex = displayArrayList(list, indicesToShow); - if (maxIndex < 1){ + if (maxIndex < 1) { System.out.println("There are no available appointments to book."); return null; } @@ -384,7 +384,7 @@ public T getItemOfArrayList(ArrayList list, ArrayList indicesT String inputString = in.nextLine(); int input = Integer.parseInt(inputString); try { - int index = indicesToShow.get(input-1); + int index = indicesToShow.get(input - 1); return list.get(index); } catch (IndexOutOfBoundsException e) { indexOutOfBoundsMessage(maxIndex); From 8df1f6646e2f50bfefc579a6a0699da660b7489b Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Thu, 22 Oct 2020 00:31:24 +0800 Subject: [PATCH 085/148] Fix input and output tests --- .../seedu/rex/commands/BookApptCommand.java | 8 +-- src/main/java/seedu/rex/ui/Ui.java | 19 ++--- text-ui-test/EXPECTED.TXT | 72 +++++++++---------- 3 files changed, 47 insertions(+), 52 deletions(-) diff --git a/src/main/java/seedu/rex/commands/BookApptCommand.java b/src/main/java/seedu/rex/commands/BookApptCommand.java index 04cafaa544..73d9a7bfab 100644 --- a/src/main/java/seedu/rex/commands/BookApptCommand.java +++ b/src/main/java/seedu/rex/commands/BookApptCommand.java @@ -60,13 +60,9 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap } try { - System.out.println("Here are the list of available appointments: "); - /*int index = Integer.parseInt(indexSelected) - 1; - if (index < 0 || index >= appointments.getSize()) { - throw new RexException("Index error!"); - }*/ + ui.showAvailableAppointmentsMessage(); Rex.logger.log(Level.INFO, "booking appointment for patient and doctor..."); - ArrayList indicesToShow = new ArrayList(); + ArrayList indicesToShow = new ArrayList<>(); for (int i = 0; i < appointments.getSize(); i++) { Appointment appointment = appointments.getAppointments().get(i); if (!appointment.isBooked()) { diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index dac48908b0..b327f47392 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -128,7 +128,7 @@ public void showPatientDeleted(Patient patient) { * @return String command from user. */ public String readCommand() { - System.out.println("Enter command: "); + printWithIndent("Enter command: "); return in.nextLine(); } @@ -354,7 +354,7 @@ public int displayArrayList(ArrayList list, ArrayList indicesToS for (i = 0; i < indicesToShow.size(); i++) { String indexString = String.valueOf(i + 1); int indexToShow = indicesToShow.get(i); - System.out.println(indexString + ". " + list.get(indexToShow)); + printWithIndent(indexString + ". " + list.get(indexToShow)); } return list.size(); } @@ -363,8 +363,8 @@ public int displayArrayList(ArrayList list, ArrayList indicesToS * Alerts user that there is a maximum allowable input. * @param maxAllowableInput maximum allowable input */ - public void indexOutOfBoundsMessage(int maxAllowableInput) { - System.out.print("Index out of bounds! Input should be between 1 to " + maxAllowableInput + "."); + public void indexOutOfBoundsMessage(int maxAllowableInput) throws RexException { + throw new RexException("Index out of bounds! Input should be between 1 to " + maxAllowableInput + "."); } /** Gets object of Arraylist corresponding to user selection. @@ -374,13 +374,12 @@ public void indexOutOfBoundsMessage(int maxAllowableInput) { * @param Generic class * @return Object in ArrayList */ - public T getItemOfArrayList(ArrayList list, ArrayList indicesToShow) { + public T getItemOfArrayList(ArrayList list, ArrayList indicesToShow) throws RexException { int maxIndex = displayArrayList(list, indicesToShow); if (maxIndex < 1) { - System.out.println("There are no available appointments to book."); - return null; + throw new RexException("There are no available appointments to book."); } - System.out.println("Enter the index you want: "); + printWithIndent("Enter the index you want: "); String inputString = in.nextLine(); int input = Integer.parseInt(inputString); try { @@ -391,4 +390,8 @@ public T getItemOfArrayList(ArrayList list, ArrayList indicesToS return null; } } + + public void showAvailableAppointmentsMessage() { + printWithIndent("Here are the list of available appointments: "); + } } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 59200c5077..0b34a06d0d 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -9,31 +9,31 @@ |_| How may i assist you? ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ ☹ OOPS!!! I'm sorry, but I don't know what that means :-( ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ ☹ OOPS!!! Please enter a valid NRIC after 'add'. ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ ☹ OOPS!!! Invalid NRIC length! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ ☹ OOPS!!! Beginning character of NRIC must be 'S', 'T', 'F', or 'G'! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ ☹ OOPS!!! Number sequence of NRIC is invalid! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ ☹ OOPS!!! Number sequence of NRIC is invalid! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Enter patient name: Enter patient date of birth (YYYY-MM-DD) including the dashes: @@ -45,20 +45,20 @@ Enter command: Patient successfully added: Trump, S9123456Z, 1960-06-14 ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ ☹ OOPS!!! No such patient! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Patient Details: Trump, S9123456Z, 1960-06-14 ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ ☹ OOPS!!! A patient with this NRIC has not been registered! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Enter patient name: Enter patient date of birth (YYYY-MM-DD) including the dashes: @@ -66,7 +66,7 @@ Enter command: Patient successfully edited: Donald, S9123456Z, 1962-06-14 ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Enter patient name: Enter patient date of birth (YYYY-MM-DD) including the dashes: @@ -74,75 +74,71 @@ Enter command: Patient successfully added: John, S9993222A, 1985-06-14 ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Patient S9992222A not found in database! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Patient successfully deleted: John, S9993222A, 1985-06-14 ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ ☹ OOPS!!! No appointment sessions! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Please enter the date of appointment in YYYY-MM-DD. ____________________________________________________________ Error in date format. ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Please enter the date of appointment in YYYY-MM-DD. ____________________________________________________________ ____________________________________________________________ New appointment created! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Doctor added: TAN ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Enter doctor name: ☹ OOPS!!! No such doctor! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Enter doctor name: + Here are the list of available appointments: + 1. 2020-10-10, available + Enter the index you want: + ☹ OOPS!!! Index out of bounds! Input should be between 1 to 1. ____________________________________________________________ - Here are the list of available appointments. - 1. 2020-10-10 - Please enter the index of appointment to book - ____________________________________________________________ - ☹ OOPS!!! Index error! - ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Enter doctor name: - ____________________________________________________________ - Here are the list of available appointments. - 1. 2020-10-10 - Please enter the index of appointment to book - ____________________________________________________________ + Here are the list of available appointments: + 1. 2020-10-10, available + Enter the index you want: ____________________________________________________________ Appointment on 2020-10-10 booked! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Listing appointments for patient S9123456Z: 1. 2020-10-10 ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Please enter the date of appointment in YYYY-MM-DD. ____________________________________________________________ ____________________________________________________________ New appointment created! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ ____________________________________________________________ Here are the list of available appointments. @@ -154,12 +150,12 @@ Enter command: ____________________________________________________________ Appointment on 2020-10-10 booked! ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Doctor successfully deleted: TAN ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ List of patients (1 in total): @@ -167,7 +163,7 @@ Enter command: NRIC: S9123456Z DOB: 1962-06-14 ____________________________________________________________ -Enter command: + Enter command: ____________________________________________________________ Bye. Hope to see you again soon! ____________________________________________________________ From e197af828351b183492caeb6d0fee2f6c5e4b62d Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Thu, 22 Oct 2020 00:32:06 +0800 Subject: [PATCH 086/148] Improve code quality --- src/main/java/seedu/rex/ui/Ui.java | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index b327f47392..69b0f35167 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -344,9 +344,9 @@ public LocalDate getAppointmentDate() { /** * Displays only the Objects in ArrayList that is required to be shown. * - * @param list Generic ArrayList + * @param list Generic ArrayList * @param indicesToShow ArrayList containing Integers corresponding to the indices of list that you want to display - * @param Generic class + * @param Generic class * @return Object in ArrayList */ public int displayArrayList(ArrayList list, ArrayList indicesToShow) { @@ -361,17 +361,19 @@ public int displayArrayList(ArrayList list, ArrayList indicesToS /** * Alerts user that there is a maximum allowable input. + * * @param maxAllowableInput maximum allowable input */ public void indexOutOfBoundsMessage(int maxAllowableInput) throws RexException { throw new RexException("Index out of bounds! Input should be between 1 to " + maxAllowableInput + "."); } - /** Gets object of Arraylist corresponding to user selection. + /** + * Gets object of Arraylist corresponding to user selection. * - * @param list Generic ArrayList + * @param list Generic ArrayList * @param indicesToShow ArrayList containing Integers corresponding to the indices of list that you want to display - * @param Generic class + * @param Generic class * @return Object in ArrayList */ public T getItemOfArrayList(ArrayList list, ArrayList indicesToShow) throws RexException { From 851433c2ee236e97db5e73431f6aa9dca6ff4601 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Thu, 22 Oct 2020 01:17:02 +0800 Subject: [PATCH 087/148] Add delete appointment function --- .../seedu/rex/commands/AddDoctorCommand.java | 6 +- .../seedu/rex/commands/BookApptCommand.java | 2 +- .../seedu/rex/commands/CreateApptCommand.java | 5 +- .../seedu/rex/commands/DeleteApptCommand.java | 71 +++++++++++++++++++ .../rex/commands/DeleteDoctorCommand.java | 3 + .../seedu/rex/commands/EditApptCommand.java | 15 ++-- .../java/seedu/rex/data/AppointmentList.java | 5 ++ .../seedu/rex/data/hospital/Appointment.java | 2 + .../java/seedu/rex/data/hospital/Patient.java | 8 +-- src/main/java/seedu/rex/parser/Parser.java | 6 +- src/main/java/seedu/rex/storage/Storage.java | 1 - src/main/java/seedu/rex/ui/Ui.java | 62 ++++++---------- text-ui-test/input.txt | 3 + 13 files changed, 131 insertions(+), 58 deletions(-) create mode 100644 src/main/java/seedu/rex/commands/DeleteApptCommand.java diff --git a/src/main/java/seedu/rex/commands/AddDoctorCommand.java b/src/main/java/seedu/rex/commands/AddDoctorCommand.java index 58542556eb..041d77cf58 100644 --- a/src/main/java/seedu/rex/commands/AddDoctorCommand.java +++ b/src/main/java/seedu/rex/commands/AddDoctorCommand.java @@ -8,6 +8,9 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +/** + * Adds doctor to DoctorList + */ public class AddDoctorCommand extends Command { public static final String COMMAND_WORD = "doctor"; private final String trimmedCommand; @@ -17,7 +20,7 @@ public AddDoctorCommand(String trimmedCommand) { } /** - * Executes command. + * Adds doctor with name. * * @param patients PatientList object. * @param doctors DoctorList object. @@ -41,6 +44,7 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap ui.showDoctorAdded(newDoctor); + assert !patients.getPatients().isEmpty() : "No doctors!"; storage.saveDoctors(doctors); } } diff --git a/src/main/java/seedu/rex/commands/BookApptCommand.java b/src/main/java/seedu/rex/commands/BookApptCommand.java index 73d9a7bfab..cc8227d66d 100644 --- a/src/main/java/seedu/rex/commands/BookApptCommand.java +++ b/src/main/java/seedu/rex/commands/BookApptCommand.java @@ -69,7 +69,7 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap indicesToShow.add(i); } } - Appointment chosenAppointment = ui.getItemOfArrayList(appointments.getAppointments(), indicesToShow); + Appointment chosenAppointment = ui.getItemOfArrayList(appointments.getAvailableAppointments()); chosenAppointment.bookPatient(patients.getPatientFromNric(nric)); chosenAppointment.bookDoctor(doctors.getDoctorFromName(doctorName)); ui.showAppointmentBookedMessage(chosenAppointment); diff --git a/src/main/java/seedu/rex/commands/CreateApptCommand.java b/src/main/java/seedu/rex/commands/CreateApptCommand.java index e0c92a7130..c08b053cd8 100644 --- a/src/main/java/seedu/rex/commands/CreateApptCommand.java +++ b/src/main/java/seedu/rex/commands/CreateApptCommand.java @@ -4,6 +4,7 @@ import seedu.rex.data.AppointmentList; import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; @@ -31,7 +32,7 @@ public class CreateApptCommand extends Command { */ @Override public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, - Storage storage) { + Storage storage) throws RexException { assert patients != null : "patient ArrayList is null"; assert ui != null : "ui is null"; assert storage != null : "storage is null"; @@ -45,6 +46,6 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap } catch (DateTimeParseException e) { ui.showDateInputError(); } - + storage.saveAppointments(appointments); } } diff --git a/src/main/java/seedu/rex/commands/DeleteApptCommand.java b/src/main/java/seedu/rex/commands/DeleteApptCommand.java new file mode 100644 index 0000000000..b8b0a0a21b --- /dev/null +++ b/src/main/java/seedu/rex/commands/DeleteApptCommand.java @@ -0,0 +1,71 @@ +package seedu.rex.commands; + +import seedu.rex.Rex; +import seedu.rex.data.AppointmentList; +import seedu.rex.data.DoctorList; +import seedu.rex.data.PatientList; +import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; +import seedu.rex.storage.Storage; +import seedu.rex.ui.Ui; + +import java.util.ArrayList; +import java.util.logging.Level; + +/** + * Deletes appointment. + */ +public class DeleteApptCommand extends Command { + + public static final String COMMAND_WORD = "deleteappt"; + private final String trimmedCommand; + + + public DeleteApptCommand(String trimmedCommand) { + this.trimmedCommand = trimmedCommand; + } + + /** + * Deletes appointment using NRIC given. + * + * @param patients PatientList object. + * @param doctors DoctorList object. + * @param appointments AppointmentList object. + * @param ui Ui object. + * @param storage Storage object. + * @throws RexException If the input NRIC does not exist in system + */ + @Override + public void execute(PatientList patients, DoctorList doctors, AppointmentList appointments, Ui ui, + Storage storage) throws RexException { + assert patients != null : "patient ArrayList is null"; + assert ui != null : "ui is null"; + assert storage != null : "storage is null"; + Rex.logger.log(Level.INFO, "going to extract NRIC"); + String nric = extractNric(trimmedCommand, COMMAND_WORD); + + if (!patients.isExistingPatient(nric)) { + throw new RexException("A patient with this NRIC has not been registered!"); + } + + try { + ArrayList patientAppointments = new ArrayList<>(); + for (int i = 0; i < appointments.getSize(); i++) { + if (appointments.getAppointmentByIndex(i).getPatient() != null + && appointments.getAppointmentByIndex(i).getPatient().getNric().equals(nric)) { + patientAppointments.add(appointments.getAppointmentByIndex(i)); + } + } + ui.showDeleteAppointmentMessage(); + Appointment AppointmentToEdit = ui.getItemOfArrayList(patientAppointments); + ui.showDeleteAppointmentMessage(AppointmentToEdit); + AppointmentToEdit.removeBooking(); + + assert !appointments.isEmpty() : "No appointments!"; + storage.saveAppointments(appointments); + } catch (NumberFormatException e) { + throw new RexException("Index error!"); + } + + } +} diff --git a/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java b/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java index 7eb3038576..7b6322e807 100644 --- a/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java @@ -39,6 +39,9 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap ui.showDoctorDeleted(deletedDoctor); for (int i = 0; i < appointments.getSize(); i++) { + if (appointments.getAppointmentByIndex(i).getDoctor() == null) { + continue; + } String tempName = appointments.getAppointmentByIndex(i).getDoctor().getName(); if (tempName.equals(doctorName)) { appointments.getAppointmentByIndex(i).setPatient(null); diff --git a/src/main/java/seedu/rex/commands/EditApptCommand.java b/src/main/java/seedu/rex/commands/EditApptCommand.java index 070c606dcc..6a0f6520e0 100644 --- a/src/main/java/seedu/rex/commands/EditApptCommand.java +++ b/src/main/java/seedu/rex/commands/EditApptCommand.java @@ -5,9 +5,11 @@ import seedu.rex.data.DoctorList; import seedu.rex.data.PatientList; import seedu.rex.data.exception.RexException; +import seedu.rex.data.hospital.Appointment; import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +import java.util.ArrayList; import java.util.logging.Level; /** @@ -47,18 +49,17 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap } try { - boolean hasAppointment = false; + ArrayList patientAppointments = new ArrayList<>(); for (int i = 0; i < appointments.getSize(); i++) { if (appointments.getAppointmentByIndex(i).getPatient() != null && appointments.getAppointmentByIndex(i).getPatient().getNric().equals(nric)) { - appointments.getAppointmentByIndex(i).removeBooking(); - hasAppointment = true; - break; + patientAppointments.add(appointments.getAppointmentByIndex(i)); } } - if (!hasAppointment) { - throw new RexException("Patient has no appointment!"); - } + ui.showEditAppointmentMessage(); + Appointment AppointmentToEdit = ui.getItemOfArrayList(patientAppointments); + ui.showDeleteAppointmentMessage(AppointmentToEdit); + AppointmentToEdit.removeBooking(); String indexSelected = ui.getAppointmentToEdit(appointments); int index = Integer.parseInt(indexSelected) - 1; diff --git a/src/main/java/seedu/rex/data/AppointmentList.java b/src/main/java/seedu/rex/data/AppointmentList.java index 0410533843..73a798c30a 100644 --- a/src/main/java/seedu/rex/data/AppointmentList.java +++ b/src/main/java/seedu/rex/data/AppointmentList.java @@ -3,6 +3,7 @@ import seedu.rex.data.hospital.Appointment; import java.util.ArrayList; +import java.util.stream.Collectors; /** * Contains ArrayList of appointments. @@ -47,4 +48,8 @@ public void addAppointment(Appointment appointment) { public void removeAppointmentByIndex(int i) { appointments.remove(i); } + + public ArrayList getAvailableAppointments() { + return (ArrayList) appointments.stream().filter((a)-> !a.isBooked()).collect(Collectors.toList()); + } } diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java index af330f4661..9fbd6e1fef 100644 --- a/src/main/java/seedu/rex/data/hospital/Appointment.java +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -75,9 +75,11 @@ public Boolean isBooked() { public void bookPatient(Patient patient) { this.patient = patient; isBooked = true; + //this.patient.getAppointmentHistory().add(this); } public void removeBooking() { + //patient.getAppointmentHistory().remove(this); this.patient = null; this.doctor = null; isBooked = false; diff --git a/src/main/java/seedu/rex/data/hospital/Patient.java b/src/main/java/seedu/rex/data/hospital/Patient.java index 7852666ee7..6ff6faa667 100644 --- a/src/main/java/seedu/rex/data/hospital/Patient.java +++ b/src/main/java/seedu/rex/data/hospital/Patient.java @@ -2,14 +2,14 @@ import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.util.Vector; +import java.util.ArrayList; /** * Patient class. */ public class Patient { - private final Vector appointmentHistory; + private final ArrayList appointmentHistory; private String name; private String nric; private LocalDate dateOfBirth; @@ -18,7 +18,7 @@ public Patient(String name, String nric, LocalDate dateOfBirth) { setName(name); setNric(nric); setDateOfBirth(dateOfBirth); - this.appointmentHistory = new Vector<>(); + this.appointmentHistory = new ArrayList<>(); } public LocalDate getDateOfBirth() { @@ -45,7 +45,7 @@ public void setNric(String nric) { this.nric = nric; } - public Vector getAppointmentHistory() { + public ArrayList getAppointmentHistory() { return appointmentHistory; } diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 899c0268f2..54fd0eb9f8 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -6,6 +6,7 @@ import seedu.rex.commands.BookApptCommand; import seedu.rex.commands.Command; import seedu.rex.commands.CreateApptCommand; +import seedu.rex.commands.DeleteApptCommand; import seedu.rex.commands.DeleteDoctorCommand; import seedu.rex.commands.DeletePatientCommand; import seedu.rex.commands.EditApptCommand; @@ -117,11 +118,12 @@ public static Command parse(String fullCommand) throws RexException { case DeleteDoctorCommand.COMMAND_WORD: command = new DeleteDoctorCommand(trimmedCommand); break; - case EditApptCommand.COMMAND_WORD: command = new EditApptCommand(trimmedCommand); break; - + case DeleteApptCommand.COMMAND_WORD: + command = new DeleteApptCommand(trimmedCommand); + break; default: throw new RexException(Command.COMMAND_ERROR); } diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index c0ba156cbc..173195ca78 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -103,7 +103,6 @@ public void saveAppointments(AppointmentList appointments) throws RexException { StringBuilder appointmentsFileContent = new StringBuilder(); for (Appointment appointment : appointments.getAppointments()) { - // Need to format tasks appointmentsFileContent.append(appointment); appointmentsFileContent.append(System.lineSeparator()); } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 69b0f35167..5a1a2b0375 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -200,31 +200,6 @@ public void showAppointmentCreatedMessage() { printWithIndent("New appointment created!"); } - /** - * Gets appointment to be booked. - * - * @param appointments Arraylist of appointments. - * @return User input. - * @throws RexException If no appointments are available. - */ - public String getAppointmentToBook(AppointmentList appointments) throws RexException { - showLine(); - printWithIndent("Here are the list of available appointments."); - int counter = 0; - for (Appointment appointment : appointments.getAppointments()) { - if (!appointment.isBooked()) { - counter++; - printWithIndent(counter + ". " + appointment.getDate().toString()); - } - } - if (counter == 0) { - throw new RexException("No appointments available!"); - } - printWithIndent("Please enter the index of appointment to book"); - showLine(); - return in.nextLine(); - } - /** * Gets appointment to be edited. * @@ -236,7 +211,7 @@ public String getAppointmentToEdit(AppointmentList appointments) throws RexExcep showLine(); printWithIndent("Here are the list of available appointments."); int counter = 0; - for (Appointment appointment : appointments.getAppointments()) { + for (Appointment appointment : appointments.getAvailableAppointments()) { counter++; printWithIndent(counter + ". " + appointment.getDate().toString()); @@ -244,7 +219,7 @@ public String getAppointmentToEdit(AppointmentList appointments) throws RexExcep if (counter == 0) { throw new RexException("No appointments available!"); } - printWithIndent("Please enter the index of appointment to edit"); + printWithIndent("Please enter the index of appointment to change to"); showLine(); return in.nextLine(); } @@ -345,16 +320,13 @@ public LocalDate getAppointmentDate() { * Displays only the Objects in ArrayList that is required to be shown. * * @param list Generic ArrayList - * @param indicesToShow ArrayList containing Integers corresponding to the indices of list that you want to display * @param Generic class * @return Object in ArrayList */ - public int displayArrayList(ArrayList list, ArrayList indicesToShow) { + public int displayArrayList(ArrayList list) { int i; - for (i = 0; i < indicesToShow.size(); i++) { - String indexString = String.valueOf(i + 1); - int indexToShow = indicesToShow.get(i); - printWithIndent(indexString + ". " + list.get(indexToShow)); + for (i = 0; i < list.size(); i++) { + printWithIndent((i + 1) + ". " + list.get(i)); } return list.size(); } @@ -372,21 +344,19 @@ public void indexOutOfBoundsMessage(int maxAllowableInput) throws RexException { * Gets object of Arraylist corresponding to user selection. * * @param list Generic ArrayList - * @param indicesToShow ArrayList containing Integers corresponding to the indices of list that you want to display * @param Generic class * @return Object in ArrayList */ - public T getItemOfArrayList(ArrayList list, ArrayList indicesToShow) throws RexException { - int maxIndex = displayArrayList(list, indicesToShow); + public T getItemOfArrayList(ArrayList list) throws RexException { + int maxIndex = displayArrayList(list); if (maxIndex < 1) { - throw new RexException("There are no available appointments to book."); + throw new RexException("There are no available appointments to choose."); } - printWithIndent("Enter the index you want: "); + printWithIndent("Enter the index: "); String inputString = in.nextLine(); int input = Integer.parseInt(inputString); try { - int index = indicesToShow.get(input - 1); - return list.get(index); + return list.get(input - 1); } catch (IndexOutOfBoundsException e) { indexOutOfBoundsMessage(maxIndex); return null; @@ -396,4 +366,16 @@ public T getItemOfArrayList(ArrayList list, ArrayList indicesToS public void showAvailableAppointmentsMessage() { printWithIndent("Here are the list of available appointments: "); } + + public void showEditAppointmentMessage() { + printWithIndent("Here are the appointments. Choose one to edit"); + } + + public void showDeleteAppointmentMessage(Appointment appointment) { + printWithIndent("Deleted appointment: " + appointment); + } + + public void showDeleteAppointmentMessage() { + printWithIndent("Choose appointment to delete: "); + } } diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 976e4cc2c1..9d92207070 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -38,7 +38,10 @@ create 2020-12-12 editappt S9123456Z 1 +1 tan +deleteappt S9123456Z +1 nodoctor tan list bye \ No newline at end of file From ffe7ef6d96a6a8687bec32df477af06e17413db7 Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Thu, 22 Oct 2020 01:18:41 +0800 Subject: [PATCH 088/148] Improve code quality and update testing --- .../java/seedu/rex/data/AppointmentList.java | 2 +- src/main/java/seedu/rex/ui/Ui.java | 8 ++++---- text-ui-test/EXPECTED.TXT | 17 ++++++++++++++--- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/rex/data/AppointmentList.java b/src/main/java/seedu/rex/data/AppointmentList.java index 73a798c30a..bc2f13be94 100644 --- a/src/main/java/seedu/rex/data/AppointmentList.java +++ b/src/main/java/seedu/rex/data/AppointmentList.java @@ -50,6 +50,6 @@ public void removeAppointmentByIndex(int i) { } public ArrayList getAvailableAppointments() { - return (ArrayList) appointments.stream().filter((a)-> !a.isBooked()).collect(Collectors.toList()); + return (ArrayList) appointments.stream().filter((a) -> !a.isBooked()).collect(Collectors.toList()); } } diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index 5a1a2b0375..d08872a3fc 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -319,8 +319,8 @@ public LocalDate getAppointmentDate() { /** * Displays only the Objects in ArrayList that is required to be shown. * - * @param list Generic ArrayList - * @param Generic class + * @param list Generic ArrayList + * @param Generic class * @return Object in ArrayList */ public int displayArrayList(ArrayList list) { @@ -343,8 +343,8 @@ public void indexOutOfBoundsMessage(int maxAllowableInput) throws RexException { /** * Gets object of Arraylist corresponding to user selection. * - * @param list Generic ArrayList - * @param Generic class + * @param list Generic ArrayList + * @param Generic class * @return Object in ArrayList */ public T getItemOfArrayList(ArrayList list) throws RexException { diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 0b34a06d0d..6102d7d217 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -114,7 +114,7 @@ Enter doctor name: Here are the list of available appointments: 1. 2020-10-10, available - Enter the index you want: + Enter the index: ☹ OOPS!!! Index out of bounds! Input should be between 1 to 1. ____________________________________________________________ Enter command: @@ -122,7 +122,7 @@ Enter doctor name: Here are the list of available appointments: 1. 2020-10-10, available - Enter the index you want: + Enter the index: ____________________________________________________________ Appointment on 2020-10-10 booked! ____________________________________________________________ @@ -140,17 +140,28 @@ ____________________________________________________________ Enter command: ____________________________________________________________ + Here are the appointments. Choose one to edit + 1. 2020-10-10, booked, S9123456Z, TAN + Enter the index: + Deleted appointment: 2020-10-10, booked, S9123456Z, TAN ____________________________________________________________ Here are the list of available appointments. 1. 2020-10-10 2. 2020-12-12 - Please enter the index of appointment to edit + Please enter the index of appointment to change to ____________________________________________________________ Enter doctor name: ____________________________________________________________ Appointment on 2020-10-10 booked! ____________________________________________________________ Enter command: + ____________________________________________________________ + Choose appointment to delete: + 1. 2020-10-10, booked, S9123456Z, TAN + Enter the index: + Deleted appointment: 2020-10-10, booked, S9123456Z, TAN + ____________________________________________________________ + Enter command: ____________________________________________________________ Doctor successfully deleted: TAN From d6df4939a39304b34693d60f0156d376399c486f Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Thu, 22 Oct 2020 01:38:35 +0800 Subject: [PATCH 089/148] Add JavaDoc --- .../seedu/rex/commands/AddDoctorCommand.java | 2 +- .../seedu/rex/commands/DeleteApptCommand.java | 6 +- .../rex/commands/DeleteDoctorCommand.java | 3 + .../seedu/rex/commands/EditApptCommand.java | 10 ++-- .../rex/commands/ListPatientCommand.java | 3 + .../java/seedu/rex/data/AppointmentList.java | 30 ++++++++-- src/main/java/seedu/rex/data/DoctorList.java | 29 ++++++++++ src/main/java/seedu/rex/data/PatientList.java | 5 ++ .../seedu/rex/data/hospital/Appointment.java | 34 +++-------- .../java/seedu/rex/data/hospital/Doctor.java | 12 ++-- .../java/seedu/rex/data/hospital/Patient.java | 7 --- src/main/java/seedu/rex/parser/Parser.java | 12 ++++ src/main/java/seedu/rex/storage/Storage.java | 6 ++ src/main/java/seedu/rex/ui/Ui.java | 56 +++++++++++-------- 14 files changed, 142 insertions(+), 73 deletions(-) diff --git a/src/main/java/seedu/rex/commands/AddDoctorCommand.java b/src/main/java/seedu/rex/commands/AddDoctorCommand.java index 041d77cf58..cf5b69a180 100644 --- a/src/main/java/seedu/rex/commands/AddDoctorCommand.java +++ b/src/main/java/seedu/rex/commands/AddDoctorCommand.java @@ -9,7 +9,7 @@ import seedu.rex.ui.Ui; /** - * Adds doctor to DoctorList + * Adds doctor to DoctorList. */ public class AddDoctorCommand extends Command { public static final String COMMAND_WORD = "doctor"; diff --git a/src/main/java/seedu/rex/commands/DeleteApptCommand.java b/src/main/java/seedu/rex/commands/DeleteApptCommand.java index b8b0a0a21b..3a13163e32 100644 --- a/src/main/java/seedu/rex/commands/DeleteApptCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteApptCommand.java @@ -57,9 +57,9 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap } } ui.showDeleteAppointmentMessage(); - Appointment AppointmentToEdit = ui.getItemOfArrayList(patientAppointments); - ui.showDeleteAppointmentMessage(AppointmentToEdit); - AppointmentToEdit.removeBooking(); + Appointment appointmentToEdit = ui.getItemOfArrayList(patientAppointments); + ui.showDeleteAppointmentMessage(appointmentToEdit); + appointmentToEdit.removeBooking(); assert !appointments.isEmpty() : "No appointments!"; storage.saveAppointments(appointments); diff --git a/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java b/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java index 7b6322e807..9bd8a947e6 100644 --- a/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java +++ b/src/main/java/seedu/rex/commands/DeleteDoctorCommand.java @@ -8,6 +8,9 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +/** + * Deletes doctor. + */ public class DeleteDoctorCommand extends Command { public static final String COMMAND_WORD = "nodoctor"; private final String trimmedCommand; diff --git a/src/main/java/seedu/rex/commands/EditApptCommand.java b/src/main/java/seedu/rex/commands/EditApptCommand.java index 6a0f6520e0..ece122eb20 100644 --- a/src/main/java/seedu/rex/commands/EditApptCommand.java +++ b/src/main/java/seedu/rex/commands/EditApptCommand.java @@ -13,7 +13,7 @@ import java.util.logging.Level; /** - * Edit appointment. + * Edits appointment. */ public class EditApptCommand extends Command { @@ -26,7 +26,7 @@ public EditApptCommand(String trimmedCommand) { } /** - * Edit appointment using NRIC given. + * Edits appointment using NRIC given. * * @param patients PatientList object. * @param doctors DoctorList object. @@ -57,9 +57,9 @@ public void execute(PatientList patients, DoctorList doctors, AppointmentList ap } } ui.showEditAppointmentMessage(); - Appointment AppointmentToEdit = ui.getItemOfArrayList(patientAppointments); - ui.showDeleteAppointmentMessage(AppointmentToEdit); - AppointmentToEdit.removeBooking(); + Appointment appointmentToEdit = ui.getItemOfArrayList(patientAppointments); + ui.showDeleteAppointmentMessage(appointmentToEdit); + appointmentToEdit.removeBooking(); String indexSelected = ui.getAppointmentToEdit(appointments); int index = Integer.parseInt(indexSelected) - 1; diff --git a/src/main/java/seedu/rex/commands/ListPatientCommand.java b/src/main/java/seedu/rex/commands/ListPatientCommand.java index 61f250f488..2ab2660288 100644 --- a/src/main/java/seedu/rex/commands/ListPatientCommand.java +++ b/src/main/java/seedu/rex/commands/ListPatientCommand.java @@ -6,6 +6,9 @@ import seedu.rex.storage.Storage; import seedu.rex.ui.Ui; +/** + * Lists patients. + */ public class ListPatientCommand extends Command { public static final String COMMAND_WORD = "list"; diff --git a/src/main/java/seedu/rex/data/AppointmentList.java b/src/main/java/seedu/rex/data/AppointmentList.java index bc2f13be94..c0197147bb 100644 --- a/src/main/java/seedu/rex/data/AppointmentList.java +++ b/src/main/java/seedu/rex/data/AppointmentList.java @@ -29,26 +29,48 @@ public ArrayList getAppointments() { } + /** + * Returns if ArrayList is empty. + * + * @return True if empty, false if not. + */ public boolean isEmpty() { return appointments.isEmpty(); } + /** + * Returns size of ArrayList. + * + * @return Size of ArrayList. + */ public int getSize() { return appointments.size(); } + /** + * Returns appointment of given index. + * + * @param index Index of appointment. + * @return Appointment at that index. + */ public Appointment getAppointmentByIndex(int index) { return appointments.get(index); } + /** + * Adds appointment to the ArrayList. + * + * @param appointment Appointment to add. + */ public void addAppointment(Appointment appointment) { appointments.add(appointment); } - public void removeAppointmentByIndex(int i) { - appointments.remove(i); - } - + /** + * Returns ArrayList of available appointments. + * + * @return Appointments that are not booked. + */ public ArrayList getAvailableAppointments() { return (ArrayList) appointments.stream().filter((a) -> !a.isBooked()).collect(Collectors.toList()); } diff --git a/src/main/java/seedu/rex/data/DoctorList.java b/src/main/java/seedu/rex/data/DoctorList.java index 6bdd38f231..3476b4d12b 100644 --- a/src/main/java/seedu/rex/data/DoctorList.java +++ b/src/main/java/seedu/rex/data/DoctorList.java @@ -55,14 +55,31 @@ public void addDoctor(Doctor doctor) { doctors.add(doctor); } + /** + * Returns list of doctors. + * + * @return List of doctors. + */ public ArrayList getDoctors() { return doctors; } + /** + * Checks if doctor exists. + * + * @param name Name of doctor. + * @return True if doctor already exist, false otherwise. + */ public boolean isExistingDoctor(String name) { return getExistingDoctor(name) > -1; } + /** + * Gets index of existing doctor. + * + * @param name Name of doctor. + * @return Index of doctor, -1 if doctor doesn't exist. + */ public int getExistingDoctor(String name) { assert name != null && !name.equals("") : "Cannot get doctor of null name"; @@ -74,6 +91,12 @@ public int getExistingDoctor(String name) { return -1; } + /** + * Gets doctor using name. + * + * @param name Name of doctor. + * @return Doctor with that naem. + */ public Doctor getDoctorFromName(String name) { for (Doctor doctor : doctors) { if (doctor.getName().equals(name)) { @@ -83,6 +106,12 @@ public Doctor getDoctorFromName(String name) { return null; } + /** + * Deletes doctor with given name. + * + * @param doctorName Name of doctor. + * @return Removed doctor. + */ public Doctor deleteDoctor(String doctorName) { int i; for (i = 0; i < getSize(); i++) { diff --git a/src/main/java/seedu/rex/data/PatientList.java b/src/main/java/seedu/rex/data/PatientList.java index 837d75ee22..dc99cfbf88 100644 --- a/src/main/java/seedu/rex/data/PatientList.java +++ b/src/main/java/seedu/rex/data/PatientList.java @@ -142,6 +142,11 @@ public Patient deletePatient(String nric) { return patients.remove(i); } + /** + * Returns list of patients. + * + * @return Patients list. + */ public ArrayList getPatients() { return patients; } diff --git a/src/main/java/seedu/rex/data/hospital/Appointment.java b/src/main/java/seedu/rex/data/hospital/Appointment.java index 9fbd6e1fef..6158052107 100644 --- a/src/main/java/seedu/rex/data/hospital/Appointment.java +++ b/src/main/java/seedu/rex/data/hospital/Appointment.java @@ -6,11 +6,9 @@ * Appointment class. */ public class Appointment { - private LocalDate date; - private String time; + private final LocalDate date; private Patient patient; private Doctor doctor; - private String notes; private Boolean isBooked; public Appointment(LocalDate date) { @@ -22,18 +20,6 @@ public LocalDate getDate() { return date; } - public void setDate(LocalDate date) { - this.date = date; - } - - public String getTime() { - return time; - } - - public void setTime(String time) { - this.time = time; - } - public Patient getPatient() { return patient; } @@ -50,14 +36,6 @@ public void setDoctor(Doctor doctor) { this.doctor = doctor; } - public String getNotes() { - return notes; - } - - public void setNotes(String notes) { - this.notes = notes; - } - /** * Checks if appointment is booked. * @@ -75,11 +53,12 @@ public Boolean isBooked() { public void bookPatient(Patient patient) { this.patient = patient; isBooked = true; - //this.patient.getAppointmentHistory().add(this); } + /** + * Removes booking. + */ public void removeBooking() { - //patient.getAppointmentHistory().remove(this); this.patient = null; this.doctor = null; isBooked = false; @@ -105,6 +84,11 @@ public String toString() { } } + /** + * Books doctor to appointment. + * + * @param doctor Doctor to book. + */ public void bookDoctor(Doctor doctor) { this.doctor = doctor; } diff --git a/src/main/java/seedu/rex/data/hospital/Doctor.java b/src/main/java/seedu/rex/data/hospital/Doctor.java index 28098a9712..0a4a269e0c 100644 --- a/src/main/java/seedu/rex/data/hospital/Doctor.java +++ b/src/main/java/seedu/rex/data/hospital/Doctor.java @@ -4,7 +4,7 @@ * Doctor class. */ public class Doctor { - private String name; + private final String name; public Doctor(String name) { this.name = name; @@ -14,11 +14,11 @@ public String getName() { return name; } - public void setName(String name) { - this.name = name; - } - - + /** + * Returns doctor's name. + * + * @return Doctor's name in String + */ @Override public String toString() { return name; diff --git a/src/main/java/seedu/rex/data/hospital/Patient.java b/src/main/java/seedu/rex/data/hospital/Patient.java index 6ff6faa667..d4de1d49cf 100644 --- a/src/main/java/seedu/rex/data/hospital/Patient.java +++ b/src/main/java/seedu/rex/data/hospital/Patient.java @@ -2,14 +2,12 @@ import java.time.LocalDate; import java.time.format.DateTimeFormatter; -import java.util.ArrayList; /** * Patient class. */ public class Patient { - private final ArrayList appointmentHistory; private String name; private String nric; private LocalDate dateOfBirth; @@ -18,7 +16,6 @@ public Patient(String name, String nric, LocalDate dateOfBirth) { setName(name); setNric(nric); setDateOfBirth(dateOfBirth); - this.appointmentHistory = new ArrayList<>(); } public LocalDate getDateOfBirth() { @@ -45,10 +42,6 @@ public void setNric(String nric) { this.nric = nric; } - public ArrayList getAppointmentHistory() { - return appointmentHistory; - } - /** * Returns the Patient object as a String for printing or writing to a file. * diff --git a/src/main/java/seedu/rex/parser/Parser.java b/src/main/java/seedu/rex/parser/Parser.java index 54fd0eb9f8..3e45053c11 100644 --- a/src/main/java/seedu/rex/parser/Parser.java +++ b/src/main/java/seedu/rex/parser/Parser.java @@ -47,6 +47,12 @@ public static Patient readPatient(String line) { return new Patient(name, nric, dateOfBirth); } + /** + * Reads in appointment and returns Appointment object. + * + * @param line Line to parse. + * @return Appointment object. + */ public static Appointment readAppointment(String line) { String[] appointmentComponents = line.split(", "); LocalDate date = LocalDate.parse(appointmentComponents[0]); @@ -131,6 +137,12 @@ public static Command parse(String fullCommand) throws RexException { } + /** + * Parses and reads doctor. + * + * @param line Line to parse. + * @return Doctor object. + */ public static Doctor readDoctor(String line) { assert line != null && !line.equals("") : "No doctors to read!"; diff --git a/src/main/java/seedu/rex/storage/Storage.java b/src/main/java/seedu/rex/storage/Storage.java index 173195ca78..a11617e0c9 100644 --- a/src/main/java/seedu/rex/storage/Storage.java +++ b/src/main/java/seedu/rex/storage/Storage.java @@ -195,6 +195,12 @@ public ArrayList loadDoctors() throws RexException { return doctors; } + /** + * Saves doctor to text file. + * + * @param doctors Doctors list. + * @throws RexException If there is error writing file. + */ public void saveDoctors(DoctorList doctors) throws RexException { assert doctors != null : "Saving null doctors ArrayList"; diff --git a/src/main/java/seedu/rex/ui/Ui.java b/src/main/java/seedu/rex/ui/Ui.java index d08872a3fc..9dcd10d9f2 100644 --- a/src/main/java/seedu/rex/ui/Ui.java +++ b/src/main/java/seedu/rex/ui/Ui.java @@ -235,15 +235,6 @@ public void showAppointmentBookedMessage(Appointment appointment) { } - /** - * Prints patient creation message. - * - * @param nric Patient's NRIC. - */ - public void showCreatePatientMessage(String nric) { - printWithIndent("Creating patient " + nric); - } - /** * Prints patient's appointment list header. * @@ -285,37 +276,44 @@ public void listPatients(PatientList patients) { } } + /** + * Gets doctor name from user. + * + * @return Doctor's name. + */ public String getDoctorName() { printWithIndent("Enter doctor name: "); return in.nextLine().toUpperCase().trim(); } + /** + * Shows the doctor added. + * + * @param newDoctor Doctor added. + */ public void showDoctorAdded(Doctor newDoctor) { printWithIndent("Doctor added: " + newDoctor.getName()); } + /** + * Shows deleted doctor. + * + * @param deletedDoctor Deleted doctor. + */ public void showDoctorDeleted(Doctor deletedDoctor) { printWithIndent("Doctor successfully deleted: "); printWithIndent(deletedDoctor.toString()); } + /** + * Shows doctor not found message. + * + * @param doctorName Name of doctor. + */ public void printDoctorNotFound(String doctorName) { printWithIndent("Patient " + doctorName + " not found in database!"); } - public LocalDate getAppointmentDate() { - while (true) { - try { - printWithIndent("Enter appointment date (YYYY-MM-DD) including the dashes: "); - return LocalDate.parse(in.nextLine().trim()); - } catch (DateTimeParseException e) { - showLine(); - showDateInputError(); - showLine(); - } - } - } - /** * Displays only the Objects in ArrayList that is required to be shown. * @@ -363,18 +361,32 @@ public T getItemOfArrayList(ArrayList list) throws RexException { } } + /** + * Shows available appointments message. + */ public void showAvailableAppointmentsMessage() { printWithIndent("Here are the list of available appointments: "); } + /** + * Shows edit appointment message. + */ public void showEditAppointmentMessage() { printWithIndent("Here are the appointments. Choose one to edit"); } + /** + * Shows deleted appointment. + * + * @param appointment Deleted appointment. + */ public void showDeleteAppointmentMessage(Appointment appointment) { printWithIndent("Deleted appointment: " + appointment); } + /** + * Shows delete appointment message. + */ public void showDeleteAppointmentMessage() { printWithIndent("Choose appointment to delete: "); } From 24ba802e7d783901617a802602fe34c15aacfaab Mon Sep 17 00:00:00 2001 From: TanJunHong Date: Thu, 22 Oct 2020 02:02:51 +0800 Subject: [PATCH 090/148] Add more JUnit tests --- .../rex/data/hospital/AppointmentTest.java | 106 ++++++++++++++++++ .../seedu/rex/data/hospital/DoctorTest.java | 20 ++++ .../seedu/rex/data/hospital/PatientTest.java | 55 +++++++++ 3 files changed, 181 insertions(+) create mode 100644 src/test/java/seedu/rex/data/hospital/AppointmentTest.java create mode 100644 src/test/java/seedu/rex/data/hospital/DoctorTest.java create mode 100644 src/test/java/seedu/rex/data/hospital/PatientTest.java diff --git a/src/test/java/seedu/rex/data/hospital/AppointmentTest.java b/src/test/java/seedu/rex/data/hospital/AppointmentTest.java new file mode 100644 index 0000000000..9d2a4b1aee --- /dev/null +++ b/src/test/java/seedu/rex/data/hospital/AppointmentTest.java @@ -0,0 +1,106 @@ +package seedu.rex.data.hospital; + +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class AppointmentTest { + + @Test + void getDate_todayDate_todayDate() { + Appointment appointment = new Appointment(LocalDate.now()); + assertEquals(LocalDate.now(), appointment.getDate()); + } + + @Test + void getPatient_samplePatient_samplePatient() { + Appointment appointment = new Appointment(LocalDate.now()); + Patient patient = new Patient(null, null, null); + appointment.setPatient(patient); + assertEquals(patient, appointment.getPatient()); + } + + @Test + void setPatient_samplePatient_samplePatient() { + Appointment appointment = new Appointment(LocalDate.now()); + Patient patient = new Patient(null, null, null); + appointment.setPatient(patient); + assertEquals(patient, appointment.getPatient()); + } + + @Test + void getDoctor_sampleDoctor_sampleDoctor() { + Appointment appointment = new Appointment(LocalDate.now()); + Doctor doctor = new Doctor("hi"); + appointment.setDoctor(doctor); + assertEquals(doctor, appointment.getDoctor()); + } + + @Test + void setDoctor_sampleDoctor_sampleDoctor() { + Appointment appointment = new Appointment(LocalDate.now()); + Doctor doctor = new Doctor("hi"); + appointment.setDoctor(doctor); + assertEquals(doctor, appointment.getDoctor()); + } + + @Test + void isBooked_booked_true() { + Appointment appointment = new Appointment(LocalDate.now()); + appointment.bookPatient(new Patient(null, null, null)); + assertTrue(appointment.isBooked()); + } + + @Test + void isBooked_notBooked_false() { + Appointment appointment = new Appointment(LocalDate.now()); + assertFalse(appointment.isBooked()); + } + + @Test + void bookPatient_samplePatient_isBookedTrueAndSamplePatient() { + Appointment appointment = new Appointment(LocalDate.now()); + Patient patient = new Patient(null, null, null); + appointment.bookPatient(patient); + assertEquals(patient, appointment.getPatient()); + assertTrue(appointment.isBooked()); + } + + @Test + void removeBooking_removed_nullPatientAndIsBookedFalse() { + Appointment appointment = new Appointment(LocalDate.now()); + Patient patient = new Patient(null, null, null); + appointment.bookPatient(patient); + appointment.removeBooking(); + assertFalse(appointment.isBooked()); + assertNull(appointment.getPatient()); + assertNull(appointment.getDoctor()); + } + + @Test + void testToString_bookedAppointment_correctString() { + Appointment appointment = new Appointment(LocalDate.now()); + Patient patient = new Patient(null, null, null); + appointment.bookPatient(patient); + assertEquals(LocalDate.now() + ", booked, null, null", appointment.toString()); + } + + @Test + void testToString_notBookedAppointment_correctString() { + Appointment appointment = new Appointment(LocalDate.now()); + assertEquals(LocalDate.now() + ", available", appointment.toString()); + } + + @Test + void bookDoctor_sampleDoctor_sampleDoctor() { + Appointment appointment = new Appointment(LocalDate.now()); + Doctor doctor = new Doctor("test"); + appointment.bookDoctor(doctor); + assertEquals(doctor, appointment.getDoctor()); + } +} \ No newline at end of file diff --git a/src/test/java/seedu/rex/data/hospital/DoctorTest.java b/src/test/java/seedu/rex/data/hospital/DoctorTest.java new file mode 100644 index 0000000000..8b7b99815e --- /dev/null +++ b/src/test/java/seedu/rex/data/hospital/DoctorTest.java @@ -0,0 +1,20 @@ +package seedu.rex.data.hospital; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class DoctorTest { + + @Test + void getName_sam_sam() { + Doctor sam = new Doctor("Sam"); + assertEquals("Sam", sam.getName()); + } + + @Test + void testToString_sam_sam() { + Doctor sam = new Doctor("Sam"); + assertEquals("Sam", sam.toString()); + } +} \ No newline at end of file diff --git a/src/test/java/seedu/rex/data/hospital/PatientTest.java b/src/test/java/seedu/rex/data/hospital/PatientTest.java new file mode 100644 index 0000000000..5335a61358 --- /dev/null +++ b/src/test/java/seedu/rex/data/hospital/PatientTest.java @@ -0,0 +1,55 @@ +package seedu.rex.data.hospital; + +import org.junit.jupiter.api.Test; + +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class PatientTest { + + @Test + void getDateOfBirth_todayDate_todayDate() { + Patient patient = new Patient("a", "b", LocalDate.now()); + assertEquals(LocalDate.now(), patient.getDateOfBirth()); + } + + @Test + void setDateOfBirth_todayDate_todayDate() { + Patient patient = new Patient("a", "b", LocalDate.MIN); + patient.setDateOfBirth(LocalDate.now()); + assertEquals(LocalDate.now(), patient.getDateOfBirth()); + } + + @Test + void getName_a_a() { + Patient patient = new Patient("a", "b", LocalDate.MIN); + assertEquals("a", patient.getName()); + } + + @Test + void setName_a_a() { + Patient patient = new Patient("z", "b", LocalDate.MIN); + patient.setName("a"); + assertEquals("a", patient.getName()); + } + + @Test + void getNric_b_b() { + Patient patient = new Patient("z", "b", LocalDate.MIN); + assertEquals("b", patient.getNric()); + } + + @Test + void setNric_z_z() { + Patient patient = new Patient("z", "b", LocalDate.MIN); + patient.setNric("z"); + assertEquals("z", patient.getNric()); + } + + @Test + void testToString_zbTodayDate_zbTodayDate() { + Patient patient = new Patient("z", "b", LocalDate.now()); + assertEquals("z, b, " + LocalDate.now(), patient.toString()); + } +} \ No newline at end of file From da4b70e0c1c57c32225478b73041881be2501b1d Mon Sep 17 00:00:00 2001 From: Tan Jun Hong <13333714+TanJunHong@users.noreply.github.com> Date: Fri, 23 Oct 2020 18:05:09 +0800 Subject: [PATCH 091/148] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 572fc17380..a756537f16 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,7 @@ Prerequisites: JDK 11 (use the exact version), update Intellij to the most recen |_| How may i assist you? ____________________________________________________________ - Enter command: + Enter command: ``` Type some word and press enter to let the execution proceed to the end. From a1c56e3cc65ec930c7729b171a41b1be6d949067 Mon Sep 17 00:00:00 2001 From: randynyl <56857427+randynyl@users.noreply.github.com> Date: Tue, 27 Oct 2020 20:42:41 +0800 Subject: [PATCH 092/148] add class diagram to DG --- docs/DeveloperGuide.md | 3 +++ docs/pictures/classDiagram.PNG | Bin 0 -> 181306 bytes 2 files changed, 3 insertions(+) create mode 100644 docs/pictures/classDiagram.PNG diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 2058606de8..c19e8c04c6 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -20,6 +20,9 @@ The rest are just objects that the app requires. The diagram below shows the basic design. ![image info](./pictures/UML.png) +The complete class diagram is shown below. +![image info](./pictures/classDiagram.PNG) + ### Implementation Retrieve Command The flow is for retrieve command is as follows {Replace with sequence diagram} diff --git a/docs/pictures/classDiagram.PNG b/docs/pictures/classDiagram.PNG new file mode 100644 index 0000000000000000000000000000000000000000..dcdc065f55553a090d16b6a0977fda38c1621d55 GIT binary patch literal 181306 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