From 8bf8b62d1d8d595adcba128fa7226efb1c689019 Mon Sep 17 00:00:00 2001 From: Songyue Wang <98693645+songyuew@users.noreply.github.com> Date: Fri, 8 Mar 2024 15:22:55 +0800 Subject: [PATCH 001/334] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f82e2494b7..02cc72b324 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# Duke project template +# Player2113 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. From 172de6e743d9a7350ff20ff4b63cdc4e92154418 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Fri, 8 Mar 2024 15:37:37 +0800 Subject: [PATCH 002/334] Update AboutUs --- docs/AboutUs.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..c3fa2e6a6d 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:----:|:--------------:|:---------: +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) | 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) | Sean Ng | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From 70f400afcac29e5693c942aa7c91179d65f26f8a Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Fri, 8 Mar 2024 15:38:09 +0800 Subject: [PATCH 003/334] Change name --- docs/AboutUs.md | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..3c19560e8a 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,6 @@ # 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) +Display | Name | Github Profile | Portfolio +--------|:-----------:|:--------------:|:---------: +![](https://via.placeholder.com/100.png?text=Photo) | Hong Yi Jie | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) + From 8ff17519248f36308b24d8e1acc2e5b4743be6cc Mon Sep 17 00:00:00 2001 From: Songyue Wang Date: Fri, 8 Mar 2024 15:41:23 +0800 Subject: [PATCH 004/334] Songyue Wang personal info --- docs/AboutUs.md | 14 +++++++------- docs/team/img/songyuew.png | Bin 0 -> 19067 bytes docs/team/johndoe.md | 6 ------ 3 files changed, 7 insertions(+), 13 deletions(-) create mode 100644 docs/team/img/songyuew.png delete mode 100644 docs/team/johndoe.md diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..2e59818a88 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # 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) +Display | Name | Github Profile | Portfolio +--------|:------------:|:-------------------------------------:|:---------: +![Profile Photo](./team/img/songyuew.png) | Songyue Wang | [Github](https://github.com/songyuew) | [Portfolio](https://cidlab.ok.ubc.ca/developing-digital-passports-interface-in-bim-for-future-reuse-of-construction-materials/) +![](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) diff --git a/docs/team/img/songyuew.png b/docs/team/img/songyuew.png new file mode 100644 index 0000000000000000000000000000000000000000..005f9656b7ace6919d3f0829462f4acba780ee3c GIT binary patch literal 19067 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 literal 0 HcmV?d00001 diff --git a/docs/team/johndoe.md b/docs/team/johndoe.md deleted file mode 100644 index ab75b391b8..0000000000 --- a/docs/team/johndoe.md +++ /dev/null @@ -1,6 +0,0 @@ -# John Doe - Project Portfolio Page - -## Overview - - -### Summary of Contributions From 91d8f3f727ebca77995088114908bd9e2b2ab445 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Fri, 8 Mar 2024 15:42:18 +0800 Subject: [PATCH 005/334] AboutUs --- docs/AboutUs.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index c3fa2e6a6d..020c3b9504 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,8 +2,4 @@ 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) | Sean Ng | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From 76eb3b196ac8c2363a8d4dda0a98aa10956432f2 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Fri, 8 Mar 2024 15:45:39 +0800 Subject: [PATCH 006/334] Update About Us --- docs/AboutUs.md | 14 +++++++------- docs/team/{johndoe.md => jasonchan.md} | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) rename docs/team/{johndoe.md => jasonchan.md} (53%) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..41f5661cad 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # 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) +Display | Name | Github Profile | Portfolio +--------|:----------:|:---------------------------------------:|:---------: +![](https://via.placeholder.com/100.png?text=Photo) | Jason Chan | [Github](https://github.com/cyhjason29) | [Portfolio](docs/team/jasonchan.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) diff --git a/docs/team/johndoe.md b/docs/team/jasonchan.md similarity index 53% rename from docs/team/johndoe.md rename to docs/team/jasonchan.md index ab75b391b8..cd17a753af 100644 --- a/docs/team/johndoe.md +++ b/docs/team/jasonchan.md @@ -1,4 +1,4 @@ -# John Doe - Project Portfolio Page +# Jason Chan - Project Portfolio Page ## Overview From 84a882199a6a4d5fcc691f6cfd92a0e00185929e Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Fri, 8 Mar 2024 15:48:51 +0800 Subject: [PATCH 007/334] add details --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 3c19560e8a..656bab6d35 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,5 +2,5 @@ Display | Name | Github Profile | Portfolio --------|:-----------:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Hong Yi Jie | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Hong Yi Jie | [Github](https://github.com/hongyijie06) | [Portfolio](docs/team/hongyijie06.md) From 602336e6d34aa499fa4adbca425f49c96f8ae31d Mon Sep 17 00:00:00 2001 From: yuhengr Date: Fri, 8 Mar 2024 16:00:24 +0800 Subject: [PATCH 008/334] Edit AboutUs.md --- docs/AboutUs.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..eb708cc012 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # 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) +Display | Name | Github Profile | Portfolio +--------|:--------:|:--------------:|:---------: +![](https://via.placeholder.com/100.png?text=Photo) | Yuheng | [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) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From b2a8b44d0daba23da106e6c6be2484ad55b3a626 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Fri, 8 Mar 2024 16:12:44 +0800 Subject: [PATCH 009/334] Update AboutUs --- docs/AboutUs.md | 12 ++++++------ docs/team/hongyijie06.md | 6 ++++++ docs/team/seanng.md | 6 ++++++ docs/team/songyuew.md | 6 ++++++ docs/team/yuheng.md | 6 ++++++ 5 files changed, 30 insertions(+), 6 deletions(-) create mode 100644 docs/team/hongyijie06.md create mode 100644 docs/team/seanng.md create mode 100644 docs/team/songyuew.md create mode 100644 docs/team/yuheng.md diff --git a/docs/AboutUs.md b/docs/AboutUs.md index bc7ccb56b7..225f53e3ef 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -1,9 +1,9 @@ # About us -Display | Name | Github Profile | Portfolio ---------|:--------:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Yuheng | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](./team/img/songyuew.png) | Songyue Wang | [Github](https://github.com/songyuew) | [Portfolio](https://cidlab.ok.ubc.ca/developing-digital-passports-interface-in-bim-for-future-reuse-of-construction-materials/) -![](https://via.placeholder.com/100.png?text=Photo) | Jason Chan | [Github](https://github.com/cyhjason29) | [Portfolio](docs/team/jasonchan.md) +Display | Name | Github Profile | Portfolio +--------|:--------:|:----------------------------------------:|:---------: +![](https://via.placeholder.com/100.png?text=Photo) | Yuheng | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](./team/img/songyuew.png) | Songyue Wang | [Github](https://github.com/songyuew) | [Portfolio](https://cidlab.ok.ubc.ca/developing-digital-passports-interface-in-bim-for-future-reuse-of-construction-materials/) +![](https://via.placeholder.com/100.png?text=Photo) | Jason Chan | [Github](https://github.com/cyhjason29) | [Portfolio](docs/team/jasonchan.md) ![](https://via.placeholder.com/100.png?text=Photo) | Hong Yi Jie | [Github](https://github.com/hongyijie06) | [Portfolio](docs/team/hongyijie06.md) -![](https://via.placeholder.com/100.png?text=Photo) | Sean Ng | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) \ No newline at end of file +![](https://via.placeholder.com/100.png?text=Photo) | Sean Ng | [Github](https://github.com/NGXZS) | [Portfolio](docs/team/seanng.md) \ No newline at end of file diff --git a/docs/team/hongyijie06.md b/docs/team/hongyijie06.md new file mode 100644 index 0000000000..cd17a753af --- /dev/null +++ b/docs/team/hongyijie06.md @@ -0,0 +1,6 @@ +# Jason Chan - Project Portfolio Page + +## Overview + + +### Summary of Contributions diff --git a/docs/team/seanng.md b/docs/team/seanng.md new file mode 100644 index 0000000000..cd17a753af --- /dev/null +++ b/docs/team/seanng.md @@ -0,0 +1,6 @@ +# Jason Chan - Project Portfolio Page + +## Overview + + +### Summary of Contributions diff --git a/docs/team/songyuew.md b/docs/team/songyuew.md new file mode 100644 index 0000000000..cd17a753af --- /dev/null +++ b/docs/team/songyuew.md @@ -0,0 +1,6 @@ +# Jason Chan - Project Portfolio Page + +## Overview + + +### Summary of Contributions diff --git a/docs/team/yuheng.md b/docs/team/yuheng.md new file mode 100644 index 0000000000..cd17a753af --- /dev/null +++ b/docs/team/yuheng.md @@ -0,0 +1,6 @@ +# Jason Chan - Project Portfolio Page + +## Overview + + +### Summary of Contributions From 328dd898872a12deefef75019b104ae12722cb1b Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 14 Mar 2024 21:55:44 +0800 Subject: [PATCH 010/334] Create Results class --- src/main/java/seedu/duke/Results.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/duke/Results.java diff --git a/src/main/java/seedu/duke/Results.java b/src/main/java/seedu/duke/Results.java new file mode 100644 index 0000000000..e4d52f6718 --- /dev/null +++ b/src/main/java/seedu/duke/Results.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class Results { +} From 4982fbc69b9767a44df6302a9e23b6c9fcde1f33 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 14 Mar 2024 22:17:19 +0800 Subject: [PATCH 011/334] Add support to record score of each round --- src/main/java/seedu/duke/Results.java | 28 +++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/main/java/seedu/duke/Results.java b/src/main/java/seedu/duke/Results.java index e4d52f6718..dc871fab98 100644 --- a/src/main/java/seedu/duke/Results.java +++ b/src/main/java/seedu/duke/Results.java @@ -1,4 +1,32 @@ package seedu.duke; public class Results { + protected static int numberOfCorrectAnswers; + protected static int totalNumberOfQuestions; + protected static String score; + + private static final int HUNDRED_PERCENT = 100; + private static final int ZERO_QUESTIONS = 0; + + public Results() { + numberOfCorrectAnswers = ZERO_QUESTIONS; + totalNumberOfQuestions = ZERO_QUESTIONS; + } + + private static void calculateScore() { + int scorePercentage = numberOfCorrectAnswers / totalNumberOfQuestions * HUNDRED_PERCENT; + score = numberOfCorrectAnswers + "/" + totalNumberOfQuestions + " (" + scorePercentage + "%)"; + } + + public static String getScore() { + return score; + } + + public static void increaseCorrectAnswers() { + numberOfCorrectAnswers++; + } + + public static void increaseNumberOfQuestions() { + totalNumberOfQuestions++; + } } From d6ecc485e6cd2c74d7f7ee6d4029f2a0f0608c19 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 14 Mar 2024 22:24:57 +0800 Subject: [PATCH 012/334] Fix typo regarding private/public method --- src/main/java/seedu/duke/Results.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Results.java b/src/main/java/seedu/duke/Results.java index dc871fab98..e6649946b3 100644 --- a/src/main/java/seedu/duke/Results.java +++ b/src/main/java/seedu/duke/Results.java @@ -13,7 +13,7 @@ public Results() { totalNumberOfQuestions = ZERO_QUESTIONS; } - private static void calculateScore() { + public static void calculateScore() { int scorePercentage = numberOfCorrectAnswers / totalNumberOfQuestions * HUNDRED_PERCENT; score = numberOfCorrectAnswers + "/" + totalNumberOfQuestions + " (" + scorePercentage + "%)"; } From 740e58662f5c1e8535ac6757e024e57a847e5907 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 14 Mar 2024 22:25:21 +0800 Subject: [PATCH 013/334] Create ResultsList class --- src/main/java/seedu/duke/ResultsList.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/duke/ResultsList.java diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java new file mode 100644 index 0000000000..644797d9c1 --- /dev/null +++ b/src/main/java/seedu/duke/ResultsList.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class ResultsList { +} From 4d96b490e9f5a192e70fd3cb6330411204178b53 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 14 Mar 2024 22:40:42 +0800 Subject: [PATCH 014/334] Add support to record results from all rounds --- src/main/java/seedu/duke/ResultsList.java | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index 644797d9c1..07fb2f6df8 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -1,4 +1,24 @@ package seedu.duke; +import java.util.ArrayList; + public class ResultsList { + protected static ArrayList sessionResults; + + public ResultsList() { + sessionResults = new ArrayList<>(); + } + + public static void addResult(Results roundResults) { + sessionResults.add(roundResults); + } + + public static Results getSpecifiedResult(int index) { + return sessionResults.get(index); + } + + public static ArrayList getAllResults() { + return sessionResults; + } } + From 81b123c0e87787e60458bab49fa14808c42c22dc Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 14 Mar 2024 23:08:16 +0800 Subject: [PATCH 015/334] Fix type casting errors regarding score calculations --- src/main/java/seedu/duke/Results.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Results.java b/src/main/java/seedu/duke/Results.java index e6649946b3..9cea9bcd32 100644 --- a/src/main/java/seedu/duke/Results.java +++ b/src/main/java/seedu/duke/Results.java @@ -14,7 +14,7 @@ public Results() { } public static void calculateScore() { - int scorePercentage = numberOfCorrectAnswers / totalNumberOfQuestions * HUNDRED_PERCENT; + int scorePercentage = (int) ((double) numberOfCorrectAnswers / (double) totalNumberOfQuestions * HUNDRED_PERCENT); score = numberOfCorrectAnswers + "/" + totalNumberOfQuestions + " (" + scorePercentage + "%)"; } From 0cbd763da7d03292e041f6bfe52c4771a1274baf Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 14 Mar 2024 23:08:45 +0800 Subject: [PATCH 016/334] Test score calculation for a round --- src/test/java/seedu/duke/ResultsTest.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 src/test/java/seedu/duke/ResultsTest.java diff --git a/src/test/java/seedu/duke/ResultsTest.java b/src/test/java/seedu/duke/ResultsTest.java new file mode 100644 index 0000000000..950684ba51 --- /dev/null +++ b/src/test/java/seedu/duke/ResultsTest.java @@ -0,0 +1,17 @@ +package seedu.duke; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ResultsTest { + @Test + void testScoreCalculation() { + Results sessionResults = new Results(); + sessionResults.increaseNumberOfQuestions(); + sessionResults.increaseNumberOfQuestions(); + sessionResults.increaseCorrectAnswers(); + sessionResults.calculateScore(); + assertEquals("1/2 (50%)", sessionResults.getScore()); + } +} \ No newline at end of file From 6498d4729c974bb4a3bb8397e727fc8d63860bff Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Fri, 15 Mar 2024 01:36:29 +0800 Subject: [PATCH 017/334] Fix errors regarding static variables --- src/main/java/seedu/duke/Results.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/duke/Results.java b/src/main/java/seedu/duke/Results.java index 9cea9bcd32..c22b236be8 100644 --- a/src/main/java/seedu/duke/Results.java +++ b/src/main/java/seedu/duke/Results.java @@ -1,9 +1,9 @@ package seedu.duke; public class Results { - protected static int numberOfCorrectAnswers; - protected static int totalNumberOfQuestions; - protected static String score; + protected int numberOfCorrectAnswers; + protected int totalNumberOfQuestions; + protected String score; private static final int HUNDRED_PERCENT = 100; private static final int ZERO_QUESTIONS = 0; @@ -11,22 +11,23 @@ public class Results { public Results() { numberOfCorrectAnswers = ZERO_QUESTIONS; totalNumberOfQuestions = ZERO_QUESTIONS; + score = ""; } - public static void calculateScore() { + public void calculateScore() { int scorePercentage = (int) ((double) numberOfCorrectAnswers / (double) totalNumberOfQuestions * HUNDRED_PERCENT); score = numberOfCorrectAnswers + "/" + totalNumberOfQuestions + " (" + scorePercentage + "%)"; } - public static String getScore() { + public String getScore() { return score; } - public static void increaseCorrectAnswers() { + public void increaseCorrectAnswers() { numberOfCorrectAnswers++; } - public static void increaseNumberOfQuestions() { + public void increaseNumberOfQuestions() { totalNumberOfQuestions++; } } From 7cb2b43993690cdc2ef9a2d664c1fe9f66cee7b6 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Fri, 15 Mar 2024 01:37:01 +0800 Subject: [PATCH 018/334] Add toString method for ResultsList --- src/main/java/seedu/duke/ResultsList.java | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index 07fb2f6df8..42245b7832 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -3,22 +3,33 @@ import java.util.ArrayList; public class ResultsList { - protected static ArrayList sessionResults; + protected ArrayList sessionResults; + protected int count; public ResultsList() { sessionResults = new ArrayList<>(); + count = 0; } - public static void addResult(Results roundResults) { + public void addResult(Results roundResults) { sessionResults.add(roundResults); + count++; } - - public static Results getSpecifiedResult(int index) { + + public Results getSpecifiedResult(int index) { return sessionResults.get(index); } - public static ArrayList getAllResults() { + public ArrayList getAllResults() { return sessionResults; } + + public String toString() { + StringBuilder listOfResults = new StringBuilder(); + for (int i = 0; i < count; i++) { + listOfResults.append((i + 1)).append(". ").append(sessionResults.get(i).getScore()).append("\n"); + } + return listOfResults.toString(); + } } From 1de4e5e777133d10343bfd8d728dca62c8d0a9f5 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Fri, 15 Mar 2024 01:37:46 +0800 Subject: [PATCH 019/334] Cleanup code for ResultsTest --- src/test/java/seedu/duke/ResultsTest.java | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/test/java/seedu/duke/ResultsTest.java b/src/test/java/seedu/duke/ResultsTest.java index 950684ba51..3f236d21fc 100644 --- a/src/test/java/seedu/duke/ResultsTest.java +++ b/src/test/java/seedu/duke/ResultsTest.java @@ -5,13 +5,19 @@ import static org.junit.jupiter.api.Assertions.*; class ResultsTest { + Results roundResults; + + void createResult() { + roundResults = new Results(); + roundResults.increaseNumberOfQuestions(); + roundResults.increaseNumberOfQuestions(); + roundResults.increaseCorrectAnswers(); + roundResults.calculateScore(); + } + @Test void testScoreCalculation() { - Results sessionResults = new Results(); - sessionResults.increaseNumberOfQuestions(); - sessionResults.increaseNumberOfQuestions(); - sessionResults.increaseCorrectAnswers(); - sessionResults.calculateScore(); - assertEquals("1/2 (50%)", sessionResults.getScore()); + createResult(); + assertEquals("1/2 (50%)", roundResults.getScore()); } } \ No newline at end of file From c4ea946f08d0395304d50a0b74ed19df30beb06c Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Fri, 15 Mar 2024 01:38:11 +0800 Subject: [PATCH 020/334] Test listing of two results --- src/test/java/seedu/duke/ResultsListTest.java | 32 +++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 src/test/java/seedu/duke/ResultsListTest.java diff --git a/src/test/java/seedu/duke/ResultsListTest.java b/src/test/java/seedu/duke/ResultsListTest.java new file mode 100644 index 0000000000..a4904dbe02 --- /dev/null +++ b/src/test/java/seedu/duke/ResultsListTest.java @@ -0,0 +1,32 @@ +package seedu.duke; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ResultsListTest { + Results roundOneResults; + Results roundTwoResults; + ResultsList sessionsResults; + + void createResultList() { + roundOneResults = new Results(); + roundTwoResults = new Results(); + sessionsResults = new ResultsList(); + roundOneResults.increaseNumberOfQuestions(); + roundOneResults.increaseNumberOfQuestions(); + roundOneResults.increaseCorrectAnswers(); + roundOneResults.calculateScore(); + roundTwoResults.increaseNumberOfQuestions(); + roundTwoResults.increaseCorrectAnswers(); + roundTwoResults.calculateScore(); + sessionsResults.addResult(roundOneResults); + sessionsResults.addResult(roundTwoResults); + } + + @Test + void testStringConversion_twoRoundResults() { + createResultList(); + assertEquals("1. 1/2 (50%)\n2. 1/1 (100%)\n", sessionsResults.toString()); + } +} \ No newline at end of file From abf40be359262e28f855cf6d7c0fd4930436ec65 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Fri, 15 Mar 2024 01:48:55 +0800 Subject: [PATCH 021/334] Cleanup code --- src/main/java/seedu/duke/Results.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/duke/Results.java b/src/main/java/seedu/duke/Results.java index c22b236be8..1c0b10b437 100644 --- a/src/main/java/seedu/duke/Results.java +++ b/src/main/java/seedu/duke/Results.java @@ -1,13 +1,13 @@ package seedu.duke; public class Results { + private static final int HUNDRED_PERCENT = 100; + private static final int ZERO_QUESTIONS = 0; + protected int numberOfCorrectAnswers; protected int totalNumberOfQuestions; protected String score; - private static final int HUNDRED_PERCENT = 100; - private static final int ZERO_QUESTIONS = 0; - public Results() { numberOfCorrectAnswers = ZERO_QUESTIONS; totalNumberOfQuestions = ZERO_QUESTIONS; @@ -15,7 +15,8 @@ public Results() { } public void calculateScore() { - int scorePercentage = (int) ((double) numberOfCorrectAnswers / (double) totalNumberOfQuestions * HUNDRED_PERCENT); + int scorePercentage = (int) ((double) numberOfCorrectAnswers / (double) totalNumberOfQuestions * + HUNDRED_PERCENT); score = numberOfCorrectAnswers + "/" + totalNumberOfQuestions + " (" + scorePercentage + "%)"; } From 636c7c94a33056c619ebbedcd8cdb1c93a442155 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Fri, 15 Mar 2024 01:52:50 +0800 Subject: [PATCH 022/334] Cleanup code --- src/test/java/seedu/duke/ResultsListTest.java | 4 ++-- src/test/java/seedu/duke/ResultsTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/test/java/seedu/duke/ResultsListTest.java b/src/test/java/seedu/duke/ResultsListTest.java index a4904dbe02..f17bd8bfd7 100644 --- a/src/test/java/seedu/duke/ResultsListTest.java +++ b/src/test/java/seedu/duke/ResultsListTest.java @@ -2,7 +2,7 @@ import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class ResultsListTest { Results roundOneResults; @@ -29,4 +29,4 @@ void testStringConversion_twoRoundResults() { createResultList(); assertEquals("1. 1/2 (50%)\n2. 1/1 (100%)\n", sessionsResults.toString()); } -} \ No newline at end of file +} diff --git a/src/test/java/seedu/duke/ResultsTest.java b/src/test/java/seedu/duke/ResultsTest.java index 3f236d21fc..03b6edff24 100644 --- a/src/test/java/seedu/duke/ResultsTest.java +++ b/src/test/java/seedu/duke/ResultsTest.java @@ -2,7 +2,7 @@ import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; class ResultsTest { Results roundResults; @@ -20,4 +20,4 @@ void testScoreCalculation() { createResult(); assertEquals("1/2 (50%)", roundResults.getScore()); } -} \ No newline at end of file +} From ca365ba27dcce7fa1b9a13d987b275b6b610afb1 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Mon, 18 Mar 2024 12:49:36 +0800 Subject: [PATCH 023/334] Add comments to Results.java, ResultsList.java tests --- src/test/java/seedu/duke/ResultsListTest.java | 8 ++++---- src/test/java/seedu/duke/ResultsTest.java | 6 +++--- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/test/java/seedu/duke/ResultsListTest.java b/src/test/java/seedu/duke/ResultsListTest.java index f17bd8bfd7..858d1daf9e 100644 --- a/src/test/java/seedu/duke/ResultsListTest.java +++ b/src/test/java/seedu/duke/ResultsListTest.java @@ -16,12 +16,12 @@ void createResultList() { roundOneResults.increaseNumberOfQuestions(); roundOneResults.increaseNumberOfQuestions(); roundOneResults.increaseCorrectAnswers(); - roundOneResults.calculateScore(); + roundOneResults.calculateScore(); // 1 out of 2 correct roundTwoResults.increaseNumberOfQuestions(); roundTwoResults.increaseCorrectAnswers(); - roundTwoResults.calculateScore(); - sessionsResults.addResult(roundOneResults); - sessionsResults.addResult(roundTwoResults); + roundTwoResults.calculateScore(); // 1 out of 1 correct + sessionsResults.addResult(roundOneResults); // returns 1/2 (50%) + sessionsResults.addResult(roundTwoResults); // returns 1/1 (100%) } @Test diff --git a/src/test/java/seedu/duke/ResultsTest.java b/src/test/java/seedu/duke/ResultsTest.java index 03b6edff24..367b9c9a71 100644 --- a/src/test/java/seedu/duke/ResultsTest.java +++ b/src/test/java/seedu/duke/ResultsTest.java @@ -10,9 +10,9 @@ class ResultsTest { void createResult() { roundResults = new Results(); roundResults.increaseNumberOfQuestions(); - roundResults.increaseNumberOfQuestions(); - roundResults.increaseCorrectAnswers(); - roundResults.calculateScore(); + roundResults.increaseNumberOfQuestions(); // total 2 questions + roundResults.increaseCorrectAnswers(); // 1 correct answer + roundResults.calculateScore(); // returns 1/2 (50%) } @Test From 8ce0c1287665d2d3ffbf96bb3aa0b3af3e26338f Mon Sep 17 00:00:00 2001 From: ngxzs Date: Mon, 18 Mar 2024 15:47:59 +0800 Subject: [PATCH 024/334] Add Question, QuestionsList class and QuestionTest.java --- src/main/java/seedu/duke/Question.java | 23 ++++++++++++ src/main/java/seedu/duke/QuestionsList.java | 28 +++++++++++++++ src/test/java/seedu/duke/QuestionTest.java | 40 +++++++++++++++++++++ 3 files changed, 91 insertions(+) create mode 100644 src/main/java/seedu/duke/Question.java create mode 100644 src/main/java/seedu/duke/QuestionsList.java create mode 100644 src/test/java/seedu/duke/QuestionTest.java diff --git a/src/main/java/seedu/duke/Question.java b/src/main/java/seedu/duke/Question.java new file mode 100644 index 0000000000..0ff6c6e4bf --- /dev/null +++ b/src/main/java/seedu/duke/Question.java @@ -0,0 +1,23 @@ +package seedu.duke; + +public class Question { + private String question; + private String answer; + private String explanation; + + public Question(String question, String answer, String explanation){ + this.question = question; + this.answer = answer; + this.explanation = explanation; + } + + public String getExplanation() { + return explanation; + } + public String getQuestion() { + return question; + } + public String getAnswer() { + return answer; + } +} diff --git a/src/main/java/seedu/duke/QuestionsList.java b/src/main/java/seedu/duke/QuestionsList.java new file mode 100644 index 0000000000..07bb48ecd0 --- /dev/null +++ b/src/main/java/seedu/duke/QuestionsList.java @@ -0,0 +1,28 @@ +package seedu.duke; + +import java.util.ArrayList; + +public class QuestionsList { + private ArrayList questionsList; + + + public QuestionsList() { + questionsList = new ArrayList<>(); + + } + + public void addQuestion(Question question){ + questionsList.add(question); + } + + public void getAllExplanations(){ + for (Question question: questionsList) { + // UI stuff + int questionNum = questionsList.indexOf(question) + 1; // + 1 coz zero index + String header = "Explanation for question " + questionNum + ":" + System.lineSeparator(); + + System.out.println(header + question.getExplanation()); + } + } +} + diff --git a/src/test/java/seedu/duke/QuestionTest.java b/src/test/java/seedu/duke/QuestionTest.java new file mode 100644 index 0000000000..a81e694a36 --- /dev/null +++ b/src/test/java/seedu/duke/QuestionTest.java @@ -0,0 +1,40 @@ +package seedu.duke; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class QuestionTest { + + Question oneQuestion; + final String question1 = "question1"; + final String answer1 = "answer1"; + final String explanation1 = "explanation1"; + + private void setUpOneQuestion() { + oneQuestion = new Question(question1, answer1, explanation1); + } + + // 3 part format + // methodBeingTested_conditionToTest_expectedOutcome + @Test + void getExplanation_oneQuestion_expectExplanation() { + setUpOneQuestion(); + + assertEquals(explanation1, oneQuestion.getExplanation()); + } + + @Test + void getQuestion_oneQuestion_expectQuestion() { + setUpOneQuestion(); + + assertEquals(question1, oneQuestion.getQuestion()); + } + + @Test + void getAnswer_oneQuestion_expectAnswer() { + setUpOneQuestion(); + + assertEquals(answer1, oneQuestion.getAnswer()); + } +} From 41182681d43baf10e865a8a8f8ab38cf17723e33 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Mon, 18 Mar 2024 16:46:09 +0800 Subject: [PATCH 025/334] Add QuestionListTest.java, CustomException --- src/main/java/seedu/duke/QuestionsList.java | 20 +++++- .../duke/exceptions/CustomException.java | 7 +++ src/test/java/seedu/duke/QuestionTest.java | 9 +-- .../java/seedu/duke/QuestionsListTest.java | 61 +++++++++++++++++++ 4 files changed, 90 insertions(+), 7 deletions(-) create mode 100644 src/main/java/seedu/duke/exceptions/CustomException.java create mode 100644 src/test/java/seedu/duke/QuestionsListTest.java diff --git a/src/main/java/seedu/duke/QuestionsList.java b/src/main/java/seedu/duke/QuestionsList.java index 07bb48ecd0..e6b1508afe 100644 --- a/src/main/java/seedu/duke/QuestionsList.java +++ b/src/main/java/seedu/duke/QuestionsList.java @@ -1,5 +1,7 @@ package seedu.duke; +import seedu.duke.exceptions.CustomException; + import java.util.ArrayList; public class QuestionsList { @@ -15,14 +17,26 @@ public void addQuestion(Question question){ questionsList.add(question); } - public void getAllExplanations(){ + public int getSize() { + return questionsList.size(); + } + + public String getAllExplanations() throws CustomException { + if (questionsList.isEmpty()) { + throw new CustomException("No questions yet"); + } + StringBuilder allExplanations = new StringBuilder(); + for (Question question: questionsList) { - // UI stuff int questionNum = questionsList.indexOf(question) + 1; // + 1 coz zero index String header = "Explanation for question " + questionNum + ":" + System.lineSeparator(); + String explanationForOneQuestion = header + question.getExplanation() + System.lineSeparator(); - System.out.println(header + question.getExplanation()); + allExplanations.append(explanationForOneQuestion); + allExplanations.append(System.lineSeparator()); } + + return allExplanations.toString(); } } diff --git a/src/main/java/seedu/duke/exceptions/CustomException.java b/src/main/java/seedu/duke/exceptions/CustomException.java new file mode 100644 index 0000000000..e8c5d429d2 --- /dev/null +++ b/src/main/java/seedu/duke/exceptions/CustomException.java @@ -0,0 +1,7 @@ +package seedu.duke.exceptions; + +public class CustomException extends Exception{ + public CustomException(String errorMessage) { // constructor + super(errorMessage); // e.getMessage() to get this errorMessage + } +} diff --git a/src/test/java/seedu/duke/QuestionTest.java b/src/test/java/seedu/duke/QuestionTest.java index a81e694a36..d6083b9ea1 100644 --- a/src/test/java/seedu/duke/QuestionTest.java +++ b/src/test/java/seedu/duke/QuestionTest.java @@ -11,29 +11,30 @@ class QuestionTest { final String answer1 = "answer1"; final String explanation1 = "explanation1"; - private void setUpOneQuestion() { + void createQuestion() { oneQuestion = new Question(question1, answer1, explanation1); } // 3 part format // methodBeingTested_conditionToTest_expectedOutcome + @Test void getExplanation_oneQuestion_expectExplanation() { - setUpOneQuestion(); + createQuestion(); assertEquals(explanation1, oneQuestion.getExplanation()); } @Test void getQuestion_oneQuestion_expectQuestion() { - setUpOneQuestion(); + createQuestion(); assertEquals(question1, oneQuestion.getQuestion()); } @Test void getAnswer_oneQuestion_expectAnswer() { - setUpOneQuestion(); + createQuestion(); assertEquals(answer1, oneQuestion.getAnswer()); } diff --git a/src/test/java/seedu/duke/QuestionsListTest.java b/src/test/java/seedu/duke/QuestionsListTest.java new file mode 100644 index 0000000000..585180780a --- /dev/null +++ b/src/test/java/seedu/duke/QuestionsListTest.java @@ -0,0 +1,61 @@ +package seedu.duke; + +import org.junit.jupiter.api.Test; +import seedu.duke.exceptions.CustomException; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class QuestionsListTest { + QuestionsList questionList; + Question question1; + Question question2; + + void createQuestionList() { + questionList = new QuestionsList(); + } + + void createTwoQuestions() { + question1 = new Question("question1", "answer1", "explanation1"); + question2 = new Question("question2", "answer2", "explanation2"); + } + + // 3 part format + // methodBeingTested_conditionToTest_expectedOutcome + + @Test + void getSize_addTwoQuestions_twoQuestions() { + createQuestionList(); + createTwoQuestions(); + questionList.addQuestion(question1); + questionList.addQuestion(question2); + + assertEquals(2, questionList.getSize()); + } + + @Test + void getAllExplanations_twoQuestions_twoExplanations() throws CustomException { + createQuestionList(); + createTwoQuestions(); + questionList.addQuestion(question1); + questionList.addQuestion(question2); + + String expectedOutput = + "Explanation for question 1:" + System.lineSeparator() + + "explanation1" + System.lineSeparator() + + System.lineSeparator() + + "Explanation for question 2:" + System.lineSeparator() + + "explanation2" + System.lineSeparator() + + System.lineSeparator(); + + assertEquals(expectedOutput, questionList.getAllExplanations()); + } + + @Test + void getAllExplanations_noQuestions_customException() { + createQuestionList(); // empty question List + + assertThrows(CustomException.class, // expect Exception + () -> questionList.getAllExplanations()); + } +} From d164183ed35008d8327ec8087f021e9905aaf541 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Mon, 18 Mar 2024 17:28:48 +0800 Subject: [PATCH 026/334] feat(QuestionList): add getOneExplanation, getOneSolution, getAllSolutions --- src/main/java/seedu/duke/Question.java | 10 +++--- src/main/java/seedu/duke/QuestionsList.java | 31 ++++++++++++++----- src/test/java/seedu/duke/QuestionTest.java | 8 ++--- .../java/seedu/duke/QuestionsListTest.java | 20 ++++++------ 4 files changed, 42 insertions(+), 27 deletions(-) diff --git a/src/main/java/seedu/duke/Question.java b/src/main/java/seedu/duke/Question.java index 0ff6c6e4bf..8d35ba5e15 100644 --- a/src/main/java/seedu/duke/Question.java +++ b/src/main/java/seedu/duke/Question.java @@ -2,12 +2,12 @@ public class Question { private String question; - private String answer; + private String solution; private String explanation; - public Question(String question, String answer, String explanation){ + public Question(String question, String solution, String explanation){ this.question = question; - this.answer = answer; + this.solution = solution; this.explanation = explanation; } @@ -17,7 +17,7 @@ public String getExplanation() { public String getQuestion() { return question; } - public String getAnswer() { - return answer; + public String getSolution() { + return solution; } } diff --git a/src/main/java/seedu/duke/QuestionsList.java b/src/main/java/seedu/duke/QuestionsList.java index e6b1508afe..e39d7eff98 100644 --- a/src/main/java/seedu/duke/QuestionsList.java +++ b/src/main/java/seedu/duke/QuestionsList.java @@ -21,22 +21,37 @@ public int getSize() { return questionsList.size(); } - public String getAllExplanations() throws CustomException { + // user enters "explain 1" to get explanation for question1 + public String getOneExplanation(int questionNum) { + int questionIndex = questionNum - 1; // -1 coz zero index + Question question = questionsList.get(questionIndex); + return question.getExplanation(); + } + + // user enters "solution 1" to get solution for question1 + public String getOneSolution(int questionNum) { + int questionIndex = questionNum - 1; // -1 coz zero index + Question question = questionsList.get(questionIndex); + return question.getSolution(); + } + + // user enters "solution -all" to get ALL solutions + public String getAllSolutions() throws CustomException { if (questionsList.isEmpty()) { throw new CustomException("No questions yet"); } - StringBuilder allExplanations = new StringBuilder(); + StringBuilder allQuestions = new StringBuilder(); for (Question question: questionsList) { - int questionNum = questionsList.indexOf(question) + 1; // + 1 coz zero index - String header = "Explanation for question " + questionNum + ":" + System.lineSeparator(); - String explanationForOneQuestion = header + question.getExplanation() + System.lineSeparator(); + int questionNum = questionsList.indexOf(question) + 1; // +1 coz zero index + String header = "Solution for question " + questionNum + ":" + System.lineSeparator(); + String solutionForOneQuestion = header + question.getSolution() + System.lineSeparator(); - allExplanations.append(explanationForOneQuestion); - allExplanations.append(System.lineSeparator()); + allQuestions.append(solutionForOneQuestion); + allQuestions.append(System.lineSeparator()); } - return allExplanations.toString(); + return allQuestions.toString(); } } diff --git a/src/test/java/seedu/duke/QuestionTest.java b/src/test/java/seedu/duke/QuestionTest.java index d6083b9ea1..eca52d131c 100644 --- a/src/test/java/seedu/duke/QuestionTest.java +++ b/src/test/java/seedu/duke/QuestionTest.java @@ -8,11 +8,11 @@ class QuestionTest { Question oneQuestion; final String question1 = "question1"; - final String answer1 = "answer1"; + final String solution1 = "solution1"; final String explanation1 = "explanation1"; void createQuestion() { - oneQuestion = new Question(question1, answer1, explanation1); + oneQuestion = new Question(question1, solution1, explanation1); } // 3 part format @@ -33,9 +33,9 @@ void getQuestion_oneQuestion_expectQuestion() { } @Test - void getAnswer_oneQuestion_expectAnswer() { + void getSolution_oneQuestion_expectSolution() { createQuestion(); - assertEquals(answer1, oneQuestion.getAnswer()); + assertEquals(solution1, oneQuestion.getSolution()); } } diff --git a/src/test/java/seedu/duke/QuestionsListTest.java b/src/test/java/seedu/duke/QuestionsListTest.java index 585180780a..35359f1632 100644 --- a/src/test/java/seedu/duke/QuestionsListTest.java +++ b/src/test/java/seedu/duke/QuestionsListTest.java @@ -16,8 +16,8 @@ void createQuestionList() { } void createTwoQuestions() { - question1 = new Question("question1", "answer1", "explanation1"); - question2 = new Question("question2", "answer2", "explanation2"); + question1 = new Question("question1", "solution1", "explanation1"); + question2 = new Question("question2", "solution2", "explanation2"); } // 3 part format @@ -34,28 +34,28 @@ void getSize_addTwoQuestions_twoQuestions() { } @Test - void getAllExplanations_twoQuestions_twoExplanations() throws CustomException { + void getAllSolutions_twoQuestions_twoExplanations() throws CustomException { createQuestionList(); createTwoQuestions(); questionList.addQuestion(question1); questionList.addQuestion(question2); String expectedOutput = - "Explanation for question 1:" + System.lineSeparator() - + "explanation1" + System.lineSeparator() + "Solution for question 1:" + System.lineSeparator() + + "solution1" + System.lineSeparator() + System.lineSeparator() - + "Explanation for question 2:" + System.lineSeparator() - + "explanation2" + System.lineSeparator() + + "Solution for question 2:" + System.lineSeparator() + + "solution2" + System.lineSeparator() + System.lineSeparator(); - assertEquals(expectedOutput, questionList.getAllExplanations()); + assertEquals(expectedOutput, questionList.getAllSolutions()); } @Test - void getAllExplanations_noQuestions_customException() { + void getAllSolutions_noQuestions_customException() { createQuestionList(); // empty question List assertThrows(CustomException.class, // expect Exception - () -> questionList.getAllExplanations()); + () -> questionList.getAllSolutions()); } } From 5887b9a4b697cf62fe8cbabfa710f7a337e57352 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Tue, 19 Mar 2024 00:00:00 +0800 Subject: [PATCH 027/334] BREAKING CHANGE(Player2113)!: refactor duke class to player2113 class, changes to main code, add ui, parser classes: works with question class, have not integrated results class --- build.gradle | 4 +- src/main/java/seedu/duke/Duke.java | 21 ------ src/main/java/seedu/duke/Parser.java | 63 ++++++++++++++++ src/main/java/seedu/duke/Player2113.java | 30 ++++++++ src/main/java/seedu/duke/QuestionsList.java | 1 - src/main/java/seedu/duke/Ui.java | 71 +++++++++++++++++++ .../{DukeTest.java => Player2113Test.java} | 2 +- .../java/seedu/duke/QuestionsListTest.java | 18 ++--- 8 files changed, 176 insertions(+), 34 deletions(-) delete mode 100644 src/main/java/seedu/duke/Duke.java create mode 100644 src/main/java/seedu/duke/Parser.java create mode 100644 src/main/java/seedu/duke/Player2113.java create mode 100644 src/main/java/seedu/duke/Ui.java rename src/test/java/seedu/duke/{DukeTest.java => Player2113Test.java} (89%) diff --git a/build.gradle b/build.gradle index ea82051fab..6108c2907c 100644 --- a/build.gradle +++ b/build.gradle @@ -29,11 +29,11 @@ test { } application { - mainClass.set("seedu.duke.Duke") + mainClass.set("seedu.duke.Player2113") } shadowJar { - archiveBaseName.set("duke") + archiveBaseName.set("player2113") archiveClassifier.set("") } 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/duke/Parser.java b/src/main/java/seedu/duke/Parser.java new file mode 100644 index 0000000000..15aace4686 --- /dev/null +++ b/src/main/java/seedu/duke/Parser.java @@ -0,0 +1,63 @@ +package seedu.duke; + +import seedu.duke.exceptions.CustomException; + +public class Parser { + private static final int PARAMETER_INDEX = 1; + + public void parseCommand(String command, Ui ui, QuestionsList questionsList) throws CustomException { + String lowerCaseCommand = command.toLowerCase(); + + if (lowerCaseCommand.startsWith("bye")) { + ui.isPlaying = false; + } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { + processSolutionCommand(lowerCaseCommand, ui, questionsList); + } else { + throw new CustomException("-1 HP coz invalid command"); + } + } + + // user enters "solution 1" to get solution for question1 OR + // user enters "solution -all" to get ALL solutions + // also works for "explain 1" + private void processSolutionCommand(String lowerCaseCommand, Ui ui, QuestionsList questionsList) + throws CustomException { + boolean isSolutionCommand = lowerCaseCommand.startsWith("solution"); + String typeOfCommand = isSolutionCommand ? "solution" : "explain"; + + String[] commandParts = lowerCaseCommand.split(" "); + if (commandParts.length != 2) { + throw new CustomException("invalid " + typeOfCommand + " command"); + } + // check validity of parameter + String commandParameter = commandParts[PARAMETER_INDEX]; + try { + // if parameter is an Integer + int questionNum = Integer.parseInt(commandParameter); + // checks validity of parameter + if (questionNum < 1 || questionNum > questionsList.getSize() + 1) { + throw new CustomException("booo no such question"); + } + if (isSolutionCommand) { + String solution = questionsList.getOneSolution(questionNum); + ui.printOneSolution(questionNum, solution); + return; + } // only runs if explanation + String explanation = questionsList.getOneExplanation(questionNum); + ui.printOneSolution(questionNum, explanation); + + } catch (NumberFormatException e) { + // if parameter is a String + if (!commandParameter.contentEquals("-all")) { + throw new CustomException("invalid " + typeOfCommand + " parameter"); + } + if (!isSolutionCommand) { + throw new CustomException("There is no \"explain -all\" command"); + } + + String allSolutions = questionsList.getAllSolutions(); + ui.printAllSolutions(allSolutions); + } + } +} + diff --git a/src/main/java/seedu/duke/Player2113.java b/src/main/java/seedu/duke/Player2113.java new file mode 100644 index 0000000000..e9f5858cab --- /dev/null +++ b/src/main/java/seedu/duke/Player2113.java @@ -0,0 +1,30 @@ +package seedu.duke; + +public class Player2113 { + public static final String SOME_FILE_PATH = "something"; + private Ui ui; + private QuestionsList questionsList; + public Player2113(String someFilePath) { + questionsList = new QuestionsList(); + if (someFilePath.contentEquals("something")) { + // TODO: load data from file + // Add dummy data (for now) + Question question1 = new Question("question1", "solution1", "explanation1"); + Question question2 = new Question("question2", "solution2", "explanation2"); + questionsList.addQuestion(question1); + questionsList.addQuestion(question2); + } + + } + public void run() { + ui = new Ui(); + ui.sayHi(); + while (ui.isPlaying) { + ui.readCommands(ui, questionsList); + } + + } + public static void main(String[] args) { + new Player2113(SOME_FILE_PATH).run(); + } +} diff --git a/src/main/java/seedu/duke/QuestionsList.java b/src/main/java/seedu/duke/QuestionsList.java index e39d7eff98..d364441cd9 100644 --- a/src/main/java/seedu/duke/QuestionsList.java +++ b/src/main/java/seedu/duke/QuestionsList.java @@ -10,7 +10,6 @@ public class QuestionsList { public QuestionsList() { questionsList = new ArrayList<>(); - } public void addQuestion(Question question){ diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java new file mode 100644 index 0000000000..42f97f07d1 --- /dev/null +++ b/src/main/java/seedu/duke/Ui.java @@ -0,0 +1,71 @@ +package seedu.duke; + +import seedu.duke.exceptions.CustomException; + +import java.util.Scanner; + +public class Ui { + private static final int NEW_LINE = 48; + public boolean isPlaying = true; + + public void readCommands(Ui ui, QuestionsList questionsList) { + Parser parser = new Parser(); + Scanner in = new Scanner(System.in); + System.out.println("Hello " + in.nextLine()); + printLine(); + + while(isPlaying) { + ui.askForInput(); + String command = in.nextLine(); + try { + parser.parseCommand(command, ui, questionsList); + } catch (CustomException e) { + ui.handleException(e); + } + } + sayBye(); + } + + private void askForInput() { + System.out.println("Input a command player! // TODO: show possible commands"); // TODO + } + + public void printOneSolution(int questionNum, String solution) { + System.out.println("The solution for question " + questionNum + ": " + + System.lineSeparator() + solution); + } + public void printAllSolutions(String allSolutions) { + System.out.println("The solutions are : " + + System.lineSeparator() + allSolutions); + } + private void handleException(CustomException e) { + System.out.println(e.getMessage() + "TODO: show possible commands"); //TODO + } + public void printLine() { + for (int i = 0; i < NEW_LINE; i += 1) { + System.out.print("*"); + } + System.out.println(); + } + + public void sayHi() { + String logo = + "______ _ _____ __ __ _____ \n" + + "| ___ \\ | / __ \\/ | / | |____ |\n" + + "| |_/ / | __ _ _ _ ___ _ __`' / /'`| | `| | / /\n" + + "| __/| |/ _` | | | |/ _ \\ '__| / / | | | | \\ \\\n" + + "| | | | (_| | |_| | __/ | ./ /____| |__| |_.___/ /\n" + + "\\_| |_|\\__,_|\\__, |\\___|_| \\_____/\\___/\\___/\\____/ \n" + + " __/ | \n" + + " |___/ "; + + System.out.println("Hello from\n" + logo); + System.out.println("What is your name?"); + } + + public void sayBye() { + System.out.println("bye bye, get more sleep zzz"); + printLine(); + } + +} diff --git a/src/test/java/seedu/duke/DukeTest.java b/src/test/java/seedu/duke/Player2113Test.java similarity index 89% rename from src/test/java/seedu/duke/DukeTest.java rename to src/test/java/seedu/duke/Player2113Test.java index 2dda5fd651..1caff3a24c 100644 --- a/src/test/java/seedu/duke/DukeTest.java +++ b/src/test/java/seedu/duke/Player2113Test.java @@ -4,7 +4,7 @@ import org.junit.jupiter.api.Test; -class DukeTest { +class Player2113Test { @Test public void sampleTest() { assertTrue(true); diff --git a/src/test/java/seedu/duke/QuestionsListTest.java b/src/test/java/seedu/duke/QuestionsListTest.java index 35359f1632..2e29e82251 100644 --- a/src/test/java/seedu/duke/QuestionsListTest.java +++ b/src/test/java/seedu/duke/QuestionsListTest.java @@ -7,12 +7,12 @@ import static org.junit.jupiter.api.Assertions.assertThrows; class QuestionsListTest { - QuestionsList questionList; + QuestionsList questionsList; Question question1; Question question2; void createQuestionList() { - questionList = new QuestionsList(); + questionsList = new QuestionsList(); } void createTwoQuestions() { @@ -27,18 +27,18 @@ void createTwoQuestions() { void getSize_addTwoQuestions_twoQuestions() { createQuestionList(); createTwoQuestions(); - questionList.addQuestion(question1); - questionList.addQuestion(question2); + questionsList.addQuestion(question1); + questionsList.addQuestion(question2); - assertEquals(2, questionList.getSize()); + assertEquals(2, questionsList.getSize()); } @Test void getAllSolutions_twoQuestions_twoExplanations() throws CustomException { createQuestionList(); createTwoQuestions(); - questionList.addQuestion(question1); - questionList.addQuestion(question2); + questionsList.addQuestion(question1); + questionsList.addQuestion(question2); String expectedOutput = "Solution for question 1:" + System.lineSeparator() @@ -48,7 +48,7 @@ void getAllSolutions_twoQuestions_twoExplanations() throws CustomException { + "solution2" + System.lineSeparator() + System.lineSeparator(); - assertEquals(expectedOutput, questionList.getAllSolutions()); + assertEquals(expectedOutput, questionsList.getAllSolutions()); } @Test @@ -56,6 +56,6 @@ void getAllSolutions_noQuestions_customException() { createQuestionList(); // empty question List assertThrows(CustomException.class, // expect Exception - () -> questionList.getAllSolutions()); + () -> questionsList.getAllSolutions()); } } From 8c8c5e474a1e64490359e48ea3a887405694ca00 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Tue, 19 Mar 2024 00:35:22 +0800 Subject: [PATCH 028/334] fix(ui,text-ui-test): fix whitespaces issue that is causing github style checker ./runtest.bat, ./runtest.sh to fail --- src/main/java/seedu/duke/Ui.java | 12 ++++----- text-ui-test/EXPECTED.TXT | 43 ++++++++++++++++++++++++++------ text-ui-test/input.txt | 9 ++++++- 3 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 42f97f07d1..d886d876d5 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -31,11 +31,11 @@ private void askForInput() { } public void printOneSolution(int questionNum, String solution) { - System.out.println("The solution for question " + questionNum + ": " + System.out.println("The solution for question " + questionNum + ":" + System.lineSeparator() + solution); } public void printAllSolutions(String allSolutions) { - System.out.println("The solutions are : " + System.out.println("The solutions are :" + System.lineSeparator() + allSolutions); } private void handleException(CustomException e) { @@ -50,14 +50,14 @@ public void printLine() { public void sayHi() { String logo = - "______ _ _____ __ __ _____ \n" + + "______ _ _____ __ __ _____\n" + "| ___ \\ | / __ \\/ | / | |____ |\n" + "| |_/ / | __ _ _ _ ___ _ __`' / /'`| | `| | / /\n" + "| __/| |/ _` | | | |/ _ \\ '__| / / | | | | \\ \\\n" + "| | | | (_| | |_| | __/ | ./ /____| |__| |_.___/ /\n" + - "\\_| |_|\\__,_|\\__, |\\___|_| \\_____/\\___/\\___/\\____/ \n" + - " __/ | \n" + - " |___/ "; + "\\_| |_|\\__,_|\\__, |\\___|_| \\_____/\\___/\\___/\\____/\n" + + " __/ |\n" + + " |___/"; System.out.println("Hello from\n" + logo); System.out.println("What is your name?"); diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 892cb6cae7..15e7edbf9e 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,9 +1,38 @@ Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - +______ _ _____ __ __ _____ +| ___ \ | / __ \/ | / | |____ | +| |_/ / | __ _ _ _ ___ _ __`' / /'`| | `| | / / +| __/| |/ _` | | | |/ _ \ '__| / / | | | | \ \ +| | | | (_| | |_| | __/ | ./ /____| |__| |_.___/ / +\_| |_|\__,_|\__, |\___|_| \_____/\___/\___/\____/ + __/ | + |___/ What is your name? -Hello James Gosling +Hello CaiShenYe +************************************************ +Input a command player! // TODO: show possible commands +-1 HP coz invalid commandTODO: show possible commands +Input a command player! // TODO: show possible commands +The solution for question 1: +solution1 +Input a command player! // TODO: show possible commands +The solution for question 2: +solution2 +Input a command player! // TODO: show possible commands +The solutions are : +Solution for question 1: +solution1 + +Solution for question 2: +solution2 + + +Input a command player! // TODO: show possible commands +The solution for question 1: +explanation1 +Input a command player! // TODO: show possible commands +The solution for question 2: +explanation2 +Input a command player! // TODO: show possible commands +bye bye, get more sleep zzz +************************************************ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index f6ec2e9f95..e793dcf9f1 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1 +1,8 @@ -James Gosling \ No newline at end of file +CaiShenYe +invalidCommand +solution 1 +solution 2 +solution -all +explain 1 +explain 2 +bye \ No newline at end of file From 8b4dafc651e9e066a55afc09c3d334a7f1f4c1db Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Tue, 19 Mar 2024 09:54:35 +0800 Subject: [PATCH 029/334] Remove magic literals --- src/main/java/seedu/duke/ResultsList.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index 42245b7832..c578765fda 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -3,12 +3,14 @@ import java.util.ArrayList; public class ResultsList { + private static final int ZERO_RESULTS = 0; + protected ArrayList sessionResults; protected int count; public ResultsList() { sessionResults = new ArrayList<>(); - count = 0; + count = ZERO_RESULTS; } public void addResult(Results roundResults) { From abd121c03c8f381d9d1bf1279309c3c306b09786 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Tue, 19 Mar 2024 11:57:59 +0800 Subject: [PATCH 030/334] Add exception for ResultsList --- src/main/java/seedu/duke/ResultsList.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index c578765fda..d0d8d980f0 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -18,7 +18,7 @@ public void addResult(Results roundResults) { count++; } - public Results getSpecifiedResult(int index) { + public Results getSpecifiedResult(int index) throws IndexOutOfBoundsException { return sessionResults.get(index); } @@ -26,7 +26,7 @@ public ArrayList getAllResults() { return sessionResults; } - public String toString() { + public String toString(boolean includesQuestion) { StringBuilder listOfResults = new StringBuilder(); for (int i = 0; i < count; i++) { listOfResults.append((i + 1)).append(". ").append(sessionResults.get(i).getScore()).append("\n"); From 648220535308b93f4e562021bfd09104bdb570f4 Mon Sep 17 00:00:00 2001 From: Songyue Wang Date: Tue, 19 Mar 2024 14:08:30 +0800 Subject: [PATCH 031/334] Basic help/UG viewing function --- META-INF/MANIFEST.MF | 3 +++ build.gradle | 1 + src/main/java/seedu/duke/Command.java | 26 ++++++++++++++++++++++++ src/main/java/seedu/duke/Helper.java | 23 +++++++++++++++++++++ src/main/java/seedu/duke/Parser.java | 19 ++++++++++++++++- src/main/java/seedu/duke/Player2113.java | 4 +++- src/main/java/seedu/duke/Ui.java | 9 ++++++-- 7 files changed, 81 insertions(+), 4 deletions(-) create mode 100644 META-INF/MANIFEST.MF create mode 100644 src/main/java/seedu/duke/Command.java create mode 100644 src/main/java/seedu/duke/Helper.java diff --git a/META-INF/MANIFEST.MF b/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..7a152fdd8a --- /dev/null +++ b/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: seedu.duke.Player2113 + diff --git a/build.gradle b/build.gradle index 6108c2907c..6c6d37c702 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,7 @@ repositories { dependencies { testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.10.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.10.0' + implementation("com.jakewharton.fliptables:fliptables:1.1.1") } test { diff --git a/src/main/java/seedu/duke/Command.java b/src/main/java/seedu/duke/Command.java new file mode 100644 index 0000000000..ffb7b2bc6b --- /dev/null +++ b/src/main/java/seedu/duke/Command.java @@ -0,0 +1,26 @@ +package seedu.duke; + +public class Command { + private String commandName; + private String commandFunction; + private String commandUsage; + + public Command(String commandName, String commandFunction, String commandUsage) { + this.commandName = commandName; + this.commandFunction = commandFunction; + this.commandUsage = commandUsage; + } + + + public String getCommandName() { + return commandName; + } + + public String getCommandFunction() { + return commandFunction; + } + + public String getCommandUsage() { + return commandUsage; + } +} diff --git a/src/main/java/seedu/duke/Helper.java b/src/main/java/seedu/duke/Helper.java new file mode 100644 index 0000000000..ab55818217 --- /dev/null +++ b/src/main/java/seedu/duke/Helper.java @@ -0,0 +1,23 @@ +package seedu.duke; + +import java.util.ArrayList; + +public class Helper { + private static final ArrayList commandList = new ArrayList(); + + public Helper() { + commandList.add(new Command("bye", "Terminate the programme", "bye")); + commandList.add(new Command("help", "View available commands or check a specific command", "help, help [command]")); + commandList.add(new Command("solution", "View solution to the question", "solution [QUESTION_INDEX]")); + commandList.add(new Command("explain", "View explaination for the solution", "explain [QUESTION_INDEX]")); + } + + public static Object[][] listAllCommands() { + int commandNum = commandList.size(); + Object[][] tableData = new Object[commandNum][]; + for (int i = 0; i < commandNum; i++) { + tableData[i] = new Object[]{commandList.get(i).getCommandName(), commandList.get(i).getCommandFunction(), commandList.get(i).getCommandUsage()}; + } + return tableData; + } +} diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 15aace4686..843f701517 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -5,13 +5,15 @@ public class Parser { private static final int PARAMETER_INDEX = 1; - public void parseCommand(String command, Ui ui, QuestionsList questionsList) throws CustomException { + public void parseCommand(String command, Ui ui, QuestionsList questionsList, Helper helper) throws CustomException { String lowerCaseCommand = command.toLowerCase(); if (lowerCaseCommand.startsWith("bye")) { ui.isPlaying = false; } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { processSolutionCommand(lowerCaseCommand, ui, questionsList); + } else if (lowerCaseCommand.startsWith("help")) { + processHelpCommand(lowerCaseCommand, ui, helper); } else { throw new CustomException("-1 HP coz invalid command"); } @@ -59,5 +61,20 @@ private void processSolutionCommand(String lowerCaseCommand, Ui ui, QuestionsLis ui.printAllSolutions(allSolutions); } } + + private void processHelpCommand(String lowerCaseCommand, Ui ui, Helper helper) throws CustomException { + String[] commandParts = lowerCaseCommand.split(" "); + if (commandParts.length != 1 && commandParts.length != 2) { + throw new CustomException("invalid help command parameter"); + } + + if (commandParts.length == 1) { + Object[][] printData = helper.listAllCommands(); + String[] tableHeader = {"command", "function", "usage"}; + ui.printTable(tableHeader, printData); + } else { + // TODO: given a command, find and print the detailed usage for that command + } + } } diff --git a/src/main/java/seedu/duke/Player2113.java b/src/main/java/seedu/duke/Player2113.java index e9f5858cab..cab025e3f5 100644 --- a/src/main/java/seedu/duke/Player2113.java +++ b/src/main/java/seedu/duke/Player2113.java @@ -4,8 +4,10 @@ public class Player2113 { public static final String SOME_FILE_PATH = "something"; private Ui ui; private QuestionsList questionsList; + private Helper helper; public Player2113(String someFilePath) { questionsList = new QuestionsList(); + helper = new Helper(); if (someFilePath.contentEquals("something")) { // TODO: load data from file // Add dummy data (for now) @@ -20,7 +22,7 @@ public void run() { ui = new Ui(); ui.sayHi(); while (ui.isPlaying) { - ui.readCommands(ui, questionsList); + ui.readCommands(ui, questionsList, helper); } } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index d886d876d5..3aeab13e7c 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -1,5 +1,6 @@ package seedu.duke; +import com.jakewharton.fliptables.FlipTableConverters; import seedu.duke.exceptions.CustomException; import java.util.Scanner; @@ -8,7 +9,7 @@ public class Ui { private static final int NEW_LINE = 48; public boolean isPlaying = true; - public void readCommands(Ui ui, QuestionsList questionsList) { + public void readCommands(Ui ui, QuestionsList questionsList, Helper helper) { Parser parser = new Parser(); Scanner in = new Scanner(System.in); System.out.println("Hello " + in.nextLine()); @@ -18,7 +19,7 @@ public void readCommands(Ui ui, QuestionsList questionsList) { ui.askForInput(); String command = in.nextLine(); try { - parser.parseCommand(command, ui, questionsList); + parser.parseCommand(command, ui, questionsList, helper); } catch (CustomException e) { ui.handleException(e); } @@ -68,4 +69,8 @@ public void sayBye() { printLine(); } + public void printTable(String[] headers, Object[][] data) { + System.out.println(FlipTableConverters.fromObjects(headers, data)); + } + } From 0667e7afaa7c6e79e7c41f44977b697cb6d969fa Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Tue, 19 Mar 2024 16:43:54 +0800 Subject: [PATCH 032/334] add choose topic --- src/main/java/seedu/duke/Parser.java | 45 ++++++++++++++++++++---- src/main/java/seedu/duke/Player2113.java | 11 ++++++ src/main/java/seedu/duke/Topic.java | 29 +++++++++++++++ src/main/java/seedu/duke/TopicList.java | 26 ++++++++++++++ src/main/java/seedu/duke/Ui.java | 36 +++++++++++++++++-- 5 files changed, 138 insertions(+), 9 deletions(-) create mode 100644 src/main/java/seedu/duke/Topic.java create mode 100644 src/main/java/seedu/duke/TopicList.java diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 15aace4686..a20fe5d334 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -5,18 +5,49 @@ public class Parser { private static final int PARAMETER_INDEX = 1; + + + public void parseCommand(String command, Ui ui, QuestionsList questionsList) throws CustomException { String lowerCaseCommand = command.toLowerCase(); - - if (lowerCaseCommand.startsWith("bye")) { - ui.isPlaying = false; - } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { - processSolutionCommand(lowerCaseCommand, ui, questionsList); - } else { - throw new CustomException("-1 HP coz invalid command"); + if (ui.isPlaying) { + if (lowerCaseCommand.startsWith("bye")) { + ui.isPlaying = false; + } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { + processSolutionCommand(lowerCaseCommand, ui, questionsList); + } /*else if (lowerCaseCommand.startsWith("start")){ + processStartCommand(lowerCaseCommand, ui, topicList); + }*/ else { + throw new CustomException("-1 HP coz invalid command"); + } } + } + /*private void processStartCommand(String lowerCaseCommand, Ui ui, TopicList topicList) throws CustomException { + + String[] commandParts = lowerCaseCommand.split(" "); + if (commandParts.length != 2) { + throw new CustomException("invalid " + lowerCaseCommand + " command"); + } + String commandParameter = commandParts[PARAMETER_INDEX]; + /*try { + // if parameter is an Integer + int topicNum = Integer.parseInt(commandParameter); + // checks validity of parameter + if (topicNum < 1 || topicNum > topicList.getSize() + 1) { + throw new CustomException("booo no such topic"); + } + + } catch (NumberFormatException e) { + // if parameter is a String + if (!commandParameter.contentEquals("-all")) { + throw new CustomException("invalid " + typeOfCommand + " parameter"); + } + } + + }*/ + // user enters "solution 1" to get solution for question1 OR // user enters "solution -all" to get ALL solutions // also works for "explain 1" diff --git a/src/main/java/seedu/duke/Player2113.java b/src/main/java/seedu/duke/Player2113.java index e9f5858cab..ad6a7186ff 100644 --- a/src/main/java/seedu/duke/Player2113.java +++ b/src/main/java/seedu/duke/Player2113.java @@ -1,11 +1,16 @@ package seedu.duke; +import java.util.Scanner; + public class Player2113 { public static final String SOME_FILE_PATH = "something"; private Ui ui; private QuestionsList questionsList; + private TopicList topicList; + public Player2113(String someFilePath) { questionsList = new QuestionsList(); + topicList = new TopicList(); if (someFilePath.contentEquals("something")) { // TODO: load data from file // Add dummy data (for now) @@ -13,12 +18,18 @@ public Player2113(String someFilePath) { Question question2 = new Question("question2", "solution2", "explanation2"); questionsList.addQuestion(question1); questionsList.addQuestion(question2); + + Topic topic1 = new Topic("topic1", false); + Topic topic2 = new Topic("topic2", false); + topicList.addTopic(topic1); + topicList.addTopic(topic2); } } public void run() { ui = new Ui(); ui.sayHi(); + ui.printTopicList(topicList, ui); while (ui.isPlaying) { ui.readCommands(ui, questionsList); } diff --git a/src/main/java/seedu/duke/Topic.java b/src/main/java/seedu/duke/Topic.java new file mode 100644 index 0000000000..1a06b5669c --- /dev/null +++ b/src/main/java/seedu/duke/Topic.java @@ -0,0 +1,29 @@ +package seedu.duke; + +public class Topic { + protected String topicName; + protected boolean hasAttempted; + + public Topic(String topicName, boolean hasAttempted){ + this.topicName = topicName; + this.hasAttempted = hasAttempted; + } + + public String getStatus() { + if (hasAttempted) { + return "Attempted"; + } else { + return "Not attempted"; + } + } + + public void markAsAttempted() { + this.hasAttempted = true; + } + + + public String toString(){ + return "[" + getStatus() + "]" + topicName; + } + +} diff --git a/src/main/java/seedu/duke/TopicList.java b/src/main/java/seedu/duke/TopicList.java new file mode 100644 index 0000000000..94ca1d4bdb --- /dev/null +++ b/src/main/java/seedu/duke/TopicList.java @@ -0,0 +1,26 @@ +package seedu.duke; + + +import java.util.ArrayList; +import java.util.Scanner; + +public class TopicList { + private ArrayList topicList; + + public TopicList() { + topicList = new ArrayList<>(); + } + public void addTopic(Topic topic){ + topicList.add(topic); + } + + public String getTopic(int index){ + return topicList.get(index).topicName; + } + + public int getSize() { + //System.out.println(topicList.size()); + return topicList.size(); + } + +} diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index d886d876d5..f3c107370c 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -2,17 +2,24 @@ import seedu.duke.exceptions.CustomException; +import java.util.ArrayList; import java.util.Scanner; + + public class Ui { private static final int NEW_LINE = 48; public boolean isPlaying = true; + public boolean hasStartedGame = false; + public TopicList topicList; + public void readCommands(Ui ui, QuestionsList questionsList) { Parser parser = new Parser(); Scanner in = new Scanner(System.in); - System.out.println("Hello " + in.nextLine()); + //System.out.println("Hello " + in.nextLine()); printLine(); + //ui.printTopicList(topicList, ui); while(isPlaying) { ui.askForInput(); @@ -23,13 +30,33 @@ public void readCommands(Ui ui, QuestionsList questionsList) { ui.handleException(e); } } + sayBye(); } + /*public void startGame(int index) { + String chosenTopicName = topicList.getTopic(index - 1); + System.out.println(chosenTopicName); + System.out.println("There are 10 questions in this question set. Type in the correct answer and press enter to move on to the next question."); + }*/ + + + public void printMessage(String message){ + System.out.println(message); + } private void askForInput() { System.out.println("Input a command player! // TODO: show possible commands"); // TODO } + public void printTopicList(TopicList topicList, Ui ui){ + int topicListSize = topicList.getSize(); + System.out.println("Here are the topics in CS2113: "); + for (int index = 0; index < topicListSize; index++) { + System.out.println((index + 1) + ". " + topicList.getTopic(index)); + } + System.out.println("Please choose a topic to play: ");//input command in the form "start [INDEX] + } + public void printOneSolution(int questionNum, String solution) { System.out.println("The solution for question " + questionNum + ":" + System.lineSeparator() + solution); @@ -48,7 +75,7 @@ public void printLine() { System.out.println(); } - public void sayHi() { + public String sayHi() { String logo = "______ _ _____ __ __ _____\n" + "| ___ \\ | / __ \\/ | / | |____ |\n" + @@ -61,6 +88,11 @@ public void sayHi() { 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()); + printLine(); + String name = in.nextLine(); + return name; } public void sayBye() { From f68d8d82cb64a4ff0b5e971c699b702d3dcef92d Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Tue, 19 Mar 2024 18:02:15 +0800 Subject: [PATCH 033/334] add startGame --- src/main/java/seedu/duke/Parser.java | 18 ++++++++---------- src/main/java/seedu/duke/Player2113.java | 2 +- src/main/java/seedu/duke/Topic.java | 1 - src/main/java/seedu/duke/TopicList.java | 6 ++++++ src/main/java/seedu/duke/Ui.java | 24 +++++++----------------- 5 files changed, 22 insertions(+), 29 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index a20fe5d334..734646ae60 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -8,45 +8,43 @@ public class Parser { - public void parseCommand(String command, Ui ui, QuestionsList questionsList) throws CustomException { + public void parseCommand(String command, Ui ui, QuestionsList questionsList, TopicList topicList) throws CustomException { String lowerCaseCommand = command.toLowerCase(); if (ui.isPlaying) { if (lowerCaseCommand.startsWith("bye")) { ui.isPlaying = false; } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { processSolutionCommand(lowerCaseCommand, ui, questionsList); - } /*else if (lowerCaseCommand.startsWith("start")){ + } else if (lowerCaseCommand.startsWith("topic")){ processStartCommand(lowerCaseCommand, ui, topicList); - }*/ else { + } else { throw new CustomException("-1 HP coz invalid command"); } } } - /*private void processStartCommand(String lowerCaseCommand, Ui ui, TopicList topicList) throws CustomException { + private void processStartCommand(String lowerCaseCommand, Ui ui, TopicList topicList) throws CustomException { String[] commandParts = lowerCaseCommand.split(" "); if (commandParts.length != 2) { throw new CustomException("invalid " + lowerCaseCommand + " command"); } String commandParameter = commandParts[PARAMETER_INDEX]; - /*try { + try { // if parameter is an Integer int topicNum = Integer.parseInt(commandParameter); // checks validity of parameter if (topicNum < 1 || topicNum > topicList.getSize() + 1) { throw new CustomException("booo no such topic"); } + ui.printChosenTopic(topicNum, topicList); } catch (NumberFormatException e) { - // if parameter is a String - if (!commandParameter.contentEquals("-all")) { - throw new CustomException("invalid " + typeOfCommand + " parameter"); - } + throw new CustomException("invalid " + lowerCaseCommand + " parameter"); } - }*/ + } // user enters "solution 1" to get solution for question1 OR // user enters "solution -all" to get ALL solutions diff --git a/src/main/java/seedu/duke/Player2113.java b/src/main/java/seedu/duke/Player2113.java index ad6a7186ff..9a17cfc08d 100644 --- a/src/main/java/seedu/duke/Player2113.java +++ b/src/main/java/seedu/duke/Player2113.java @@ -31,7 +31,7 @@ public void run() { ui.sayHi(); ui.printTopicList(topicList, ui); while (ui.isPlaying) { - ui.readCommands(ui, questionsList); + ui.readCommands(ui, questionsList, topicList); } } diff --git a/src/main/java/seedu/duke/Topic.java b/src/main/java/seedu/duke/Topic.java index 1a06b5669c..823176a24c 100644 --- a/src/main/java/seedu/duke/Topic.java +++ b/src/main/java/seedu/duke/Topic.java @@ -21,7 +21,6 @@ public void markAsAttempted() { this.hasAttempted = true; } - public String toString(){ return "[" + getStatus() + "]" + topicName; } diff --git a/src/main/java/seedu/duke/TopicList.java b/src/main/java/seedu/duke/TopicList.java index 94ca1d4bdb..2cd43785c8 100644 --- a/src/main/java/seedu/duke/TopicList.java +++ b/src/main/java/seedu/duke/TopicList.java @@ -23,4 +23,10 @@ public int getSize() { return topicList.size(); } + public String getChosenTopic(int topicNum){ + int topicIndex = topicNum - 1; + Topic topic = topicList.get(topicIndex); + return topic.topicName; + } + } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index f3c107370c..c14494ede5 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -14,18 +14,16 @@ public class Ui { public boolean hasStartedGame = false; public TopicList topicList; - public void readCommands(Ui ui, QuestionsList questionsList) { + public void readCommands(Ui ui, QuestionsList questionsList, TopicList topicList) { Parser parser = new Parser(); Scanner in = new Scanner(System.in); - //System.out.println("Hello " + in.nextLine()); printLine(); - //ui.printTopicList(topicList, ui); while(isPlaying) { ui.askForInput(); String command = in.nextLine(); try { - parser.parseCommand(command, ui, questionsList); + parser.parseCommand(command, ui, questionsList, topicList); } catch (CustomException e) { ui.handleException(e); } @@ -33,17 +31,7 @@ public void readCommands(Ui ui, QuestionsList questionsList) { sayBye(); } - /*public void startGame(int index) { - String chosenTopicName = topicList.getTopic(index - 1); - System.out.println(chosenTopicName); - System.out.println("There are 10 questions in this question set. Type in the correct answer and press enter to move on to the next question."); - }*/ - - - public void printMessage(String message){ - System.out.println(message); - } private void askForInput() { System.out.println("Input a command player! // TODO: show possible commands"); // TODO } @@ -57,6 +45,10 @@ public void printTopicList(TopicList topicList, Ui ui){ System.out.println("Please choose a topic to play: ");//input command in the form "start [INDEX] } + public void printChosenTopic(int topicNum, TopicList topicList){ + System.out.println("Selected topic: " + topicList.getTopic(topicNum - 1)); + } + public void printOneSolution(int questionNum, String solution) { System.out.println("The solution for question " + questionNum + ":" + System.lineSeparator() + solution); @@ -75,7 +67,7 @@ public void printLine() { System.out.println(); } - public String sayHi() { + public void sayHi() { String logo = "______ _ _____ __ __ _____\n" + "| ___ \\ | / __ \\/ | / | |____ |\n" + @@ -91,8 +83,6 @@ public String sayHi() { Scanner in = new Scanner(System.in); System.out.println("Hello " + in.nextLine()); printLine(); - String name = in.nextLine(); - return name; } public void sayBye() { From 168bbfea2d737f687d257608a00b4086df644202 Mon Sep 17 00:00:00 2001 From: Songyue Wang Date: Tue, 19 Mar 2024 21:05:43 +0800 Subject: [PATCH 034/334] Refactored Helper.java code --- src/main/java/seedu/duke/Helper.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/Helper.java b/src/main/java/seedu/duke/Helper.java index ab55818217..15f90620d6 100644 --- a/src/main/java/seedu/duke/Helper.java +++ b/src/main/java/seedu/duke/Helper.java @@ -7,7 +7,7 @@ public class Helper { public Helper() { commandList.add(new Command("bye", "Terminate the programme", "bye")); - commandList.add(new Command("help", "View available commands or check a specific command", "help, help [command]")); + commandList.add(new Command("help", "View available commands or check a one", "help, help [command]")); commandList.add(new Command("solution", "View solution to the question", "solution [QUESTION_INDEX]")); commandList.add(new Command("explain", "View explaination for the solution", "explain [QUESTION_INDEX]")); } @@ -16,7 +16,11 @@ public static Object[][] listAllCommands() { int commandNum = commandList.size(); Object[][] tableData = new Object[commandNum][]; for (int i = 0; i < commandNum; i++) { - tableData[i] = new Object[]{commandList.get(i).getCommandName(), commandList.get(i).getCommandFunction(), commandList.get(i).getCommandUsage()}; + tableData[i] = new Object[]{ + commandList.get(i).getCommandName(), + commandList.get(i).getCommandFunction(), + commandList.get(i).getCommandUsage() + }; } return tableData; } From 793a4620f8d859d5d95881b8f0b4a2e142f82202 Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Tue, 19 Mar 2024 21:32:44 +0800 Subject: [PATCH 035/334] separate question sets by topic --- src/main/java/seedu/duke/Parser.java | 19 ++++++++----- src/main/java/seedu/duke/Player2113.java | 27 ++++++++++++++----- .../java/seedu/duke/QuestionListByTopic.java | 18 +++++++++++++ src/main/java/seedu/duke/QuestionsList.java | 24 ++++++++++------- src/main/java/seedu/duke/Topic.java | 4 ++- src/main/java/seedu/duke/Ui.java | 17 +++++++++--- 6 files changed, 83 insertions(+), 26 deletions(-) create mode 100644 src/main/java/seedu/duke/QuestionListByTopic.java diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 734646ae60..6c16576f6b 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -4,27 +4,34 @@ public class Parser { private static final int PARAMETER_INDEX = 1; + boolean hasChosenTopic = false; - public void parseCommand(String command, Ui ui, QuestionsList questionsList, TopicList topicList) throws CustomException { + public void parseCommand(String command, Ui ui, QuestionsList questionsList, TopicList topicList, QuestionListByTopic questionListByTopic) throws CustomException { String lowerCaseCommand = command.toLowerCase(); if (ui.isPlaying) { + + if (lowerCaseCommand.startsWith("topic") && !hasChosenTopic) { + processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic); + hasChosenTopic = true; + } else if (!hasChosenTopic) { + throw new CustomException("Please choose a topic in the format: topic [INDEX]"); + } + if (lowerCaseCommand.startsWith("bye")) { ui.isPlaying = false; } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { processSolutionCommand(lowerCaseCommand, ui, questionsList); - } else if (lowerCaseCommand.startsWith("topic")){ - processStartCommand(lowerCaseCommand, ui, topicList); - } else { + } else if (!lowerCaseCommand.startsWith("topic")) { throw new CustomException("-1 HP coz invalid command"); } } } - private void processStartCommand(String lowerCaseCommand, Ui ui, TopicList topicList) throws CustomException { + private void processStartCommand(String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) throws CustomException { String[] commandParts = lowerCaseCommand.split(" "); if (commandParts.length != 2) { @@ -38,7 +45,7 @@ private void processStartCommand(String lowerCaseCommand, Ui ui, TopicList topic if (topicNum < 1 || topicNum > topicList.getSize() + 1) { throw new CustomException("booo no such topic"); } - ui.printChosenTopic(topicNum, topicList); + ui.printChosenTopic(topicNum, topicList, questionListByTopic); } catch (NumberFormatException e) { throw new CustomException("invalid " + lowerCaseCommand + " parameter"); diff --git a/src/main/java/seedu/duke/Player2113.java b/src/main/java/seedu/duke/Player2113.java index 9a17cfc08d..46e83713c1 100644 --- a/src/main/java/seedu/duke/Player2113.java +++ b/src/main/java/seedu/duke/Player2113.java @@ -1,26 +1,39 @@ package seedu.duke; +import java.util.ArrayList; import java.util.Scanner; public class Player2113 { public static final String SOME_FILE_PATH = "something"; private Ui ui; private QuestionsList questionsList; + private QuestionsList questionsList1; + private QuestionsList questionsList2; private TopicList topicList; + private QuestionListByTopic questionListByTopic; public Player2113(String someFilePath) { - questionsList = new QuestionsList(); + questionsList1 = new QuestionsList(); + questionsList2 = new QuestionsList(); + questionListByTopic = new QuestionListByTopic(); topicList = new TopicList(); if (someFilePath.contentEquals("something")) { // TODO: load data from file // Add dummy data (for now) Question question1 = new Question("question1", "solution1", "explanation1"); Question question2 = new Question("question2", "solution2", "explanation2"); - questionsList.addQuestion(question1); - questionsList.addQuestion(question2); + questionsList1.addQuestion(question1); + questionsList1.addQuestion(question2); + questionListByTopic.addQuestionSet(questionsList1); - Topic topic1 = new Topic("topic1", false); - Topic topic2 = new Topic("topic2", false); + Question question3 = new Question("question3", "solution3", "explanation3"); + Question question4 = new Question("question4", "solution4", "explanation4"); + questionsList2.addQuestion(question3); + questionsList2.addQuestion(question4); + questionListByTopic.addQuestionSet(questionsList2); + + Topic topic1 = new Topic(questionsList1,"topic1", false); + Topic topic2 = new Topic(questionsList2,"topic2", false); topicList.addTopic(topic1); topicList.addTopic(topic2); } @@ -30,8 +43,10 @@ public void run() { ui = new Ui(); ui.sayHi(); ui.printTopicList(topicList, ui); + while (ui.isPlaying) { - ui.readCommands(ui, questionsList, topicList); + + ui.readCommands(ui, questionsList, topicList, questionListByTopic); } } diff --git a/src/main/java/seedu/duke/QuestionListByTopic.java b/src/main/java/seedu/duke/QuestionListByTopic.java new file mode 100644 index 0000000000..75cf84b66f --- /dev/null +++ b/src/main/java/seedu/duke/QuestionListByTopic.java @@ -0,0 +1,18 @@ +package seedu.duke; + +import java.util.ArrayList; + +public class QuestionListByTopic { + protected ArrayList questionListByTopic; + + public QuestionListByTopic(){ + questionListByTopic = new ArrayList<>(); + } + public void addQuestionSet(QuestionsList questionsList){ + questionListByTopic.add(questionsList); + } + + public QuestionsList getQuestionSet(int index){ + return questionListByTopic.get(index); + } +} diff --git a/src/main/java/seedu/duke/QuestionsList.java b/src/main/java/seedu/duke/QuestionsList.java index d364441cd9..6ec4dab8b1 100644 --- a/src/main/java/seedu/duke/QuestionsList.java +++ b/src/main/java/seedu/duke/QuestionsList.java @@ -5,44 +5,48 @@ import java.util.ArrayList; public class QuestionsList { - private ArrayList questionsList; - + private ArrayList chosenQuestionsList; public QuestionsList() { - questionsList = new ArrayList<>(); + chosenQuestionsList = new ArrayList<>(); + } public void addQuestion(Question question){ - questionsList.add(question); + chosenQuestionsList.add(question); + } + + public Question getQuestionUnit(int index){ + return chosenQuestionsList.get(index); } public int getSize() { - return questionsList.size(); + return chosenQuestionsList.size(); } // user enters "explain 1" to get explanation for question1 public String getOneExplanation(int questionNum) { int questionIndex = questionNum - 1; // -1 coz zero index - Question question = questionsList.get(questionIndex); + Question question = chosenQuestionsList.get(questionIndex); return question.getExplanation(); } // user enters "solution 1" to get solution for question1 public String getOneSolution(int questionNum) { int questionIndex = questionNum - 1; // -1 coz zero index - Question question = questionsList.get(questionIndex); + Question question = chosenQuestionsList.get(questionIndex); return question.getSolution(); } // user enters "solution -all" to get ALL solutions public String getAllSolutions() throws CustomException { - if (questionsList.isEmpty()) { + if (chosenQuestionsList.isEmpty()) { throw new CustomException("No questions yet"); } StringBuilder allQuestions = new StringBuilder(); - for (Question question: questionsList) { - int questionNum = questionsList.indexOf(question) + 1; // +1 coz zero index + for (Question question: chosenQuestionsList) { + int questionNum = chosenQuestionsList.indexOf(question) + 1; // +1 coz zero index String header = "Solution for question " + questionNum + ":" + System.lineSeparator(); String solutionForOneQuestion = header + question.getSolution() + System.lineSeparator(); diff --git a/src/main/java/seedu/duke/Topic.java b/src/main/java/seedu/duke/Topic.java index 823176a24c..ebd2ed5224 100644 --- a/src/main/java/seedu/duke/Topic.java +++ b/src/main/java/seedu/duke/Topic.java @@ -1,10 +1,12 @@ package seedu.duke; public class Topic { + protected QuestionsList chosenQuestionsList; protected String topicName; protected boolean hasAttempted; - public Topic(String topicName, boolean hasAttempted){ + public Topic(QuestionsList chosenQuestionsList, String topicName, boolean hasAttempted){ + this.chosenQuestionsList = chosenQuestionsList; this.topicName = topicName; this.hasAttempted = hasAttempted; } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index c14494ede5..cf2de2bdd1 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -13,8 +13,9 @@ public class Ui { public boolean hasStartedGame = false; public TopicList topicList; + public QuestionListByTopic questionListByTopic; - public void readCommands(Ui ui, QuestionsList questionsList, TopicList topicList) { + public void readCommands(Ui ui, QuestionsList questionsList, TopicList topicList, QuestionListByTopic questionListByTopic) { Parser parser = new Parser(); Scanner in = new Scanner(System.in); printLine(); @@ -23,7 +24,7 @@ public void readCommands(Ui ui, QuestionsList questionsList, TopicList topicList ui.askForInput(); String command = in.nextLine(); try { - parser.parseCommand(command, ui, questionsList, topicList); + parser.parseCommand(command, ui, questionsList, topicList, questionListByTopic); } catch (CustomException e) { ui.handleException(e); } @@ -45,10 +46,20 @@ public void printTopicList(TopicList topicList, Ui ui){ System.out.println("Please choose a topic to play: ");//input command in the form "start [INDEX] } - public void printChosenTopic(int topicNum, TopicList topicList){ + public void printChosenTopic(int topicNum, TopicList topicList, QuestionListByTopic questionListByTopic){ + QuestionsList qnList = new QuestionsList(); System.out.println("Selected topic: " + topicList.getTopic(topicNum - 1)); + System.out.println("Here are the questions: "); + qnList = questionListByTopic.getQuestionSet(topicNum - 1); + int numOfQns = qnList.getSize(); + Question questionUnit; + for (int index = 0; index < numOfQns; index ++){ + questionUnit = qnList.getQuestionUnit(index); + System.out.println(questionUnit.getQuestion()); + } } + public void printOneSolution(int questionNum, String solution) { System.out.println("The solution for question " + questionNum + ":" + System.lineSeparator() + solution); From d528dacaf7bde28784ac68c018b04b0965b2bb16 Mon Sep 17 00:00:00 2001 From: Songyue Wang Date: Tue, 19 Mar 2024 21:43:27 +0800 Subject: [PATCH 036/334] Changed TableBuilder --- build.gradle | 2 +- lib/btc-ascii-table-1.0.jar | Bin 0 -> 16444 bytes src/main/java/seedu/duke/Helper.java | 6 +++--- src/main/java/seedu/duke/Parser.java | 2 +- src/main/java/seedu/duke/Ui.java | 7 ++++--- 5 files changed, 9 insertions(+), 8 deletions(-) create mode 100644 lib/btc-ascii-table-1.0.jar diff --git a/build.gradle b/build.gradle index 6c6d37c702..8818eecfb3 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ repositories { dependencies { testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.10.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.10.0' - implementation("com.jakewharton.fliptables:fliptables:1.1.1") + implementation fileTree(dir: 'lib', includes: ['*.jar']) } test { diff --git a/lib/btc-ascii-table-1.0.jar b/lib/btc-ascii-table-1.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..59c0d72767715d6028f2444ececd0059bbc94b6a GIT binary patch literal 16444 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 Date: Tue, 19 Mar 2024 21:47:22 +0800 Subject: [PATCH 037/334] Changed variable names --- src/main/java/seedu/duke/Player2113.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/Player2113.java b/src/main/java/seedu/duke/Player2113.java index cab025e3f5..59caafbd5f 100644 --- a/src/main/java/seedu/duke/Player2113.java +++ b/src/main/java/seedu/duke/Player2113.java @@ -3,8 +3,8 @@ public class Player2113 { public static final String SOME_FILE_PATH = "something"; private Ui ui; - private QuestionsList questionsList; - private Helper helper; + private final QuestionsList questionsList; + private final Helper helper; public Player2113(String someFilePath) { questionsList = new QuestionsList(); helper = new Helper(); From ad7ca434e48e6d62fcb50c1724055b7afe370560 Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Tue, 19 Mar 2024 22:36:11 +0800 Subject: [PATCH 038/334] adhere to gradle checkstyle --- src/main/java/seedu/duke/Parser.java | 11 ++++++++--- src/main/java/seedu/duke/Player2113.java | 3 --- src/main/java/seedu/duke/TopicList.java | 1 - src/main/java/seedu/duke/Ui.java | 7 +++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 6c16576f6b..85618e952e 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -9,7 +9,10 @@ public class Parser { - public void parseCommand(String command, Ui ui, QuestionsList questionsList, TopicList topicList, QuestionListByTopic questionListByTopic) throws CustomException { + public void parseCommand( + String command, Ui ui, QuestionsList questionsList, + TopicList topicList, QuestionListByTopic questionListByTopic + ) throws CustomException { String lowerCaseCommand = command.toLowerCase(); if (ui.isPlaying) { @@ -31,7 +34,9 @@ public void parseCommand(String command, Ui ui, QuestionsList questionsList, Top } - private void processStartCommand(String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) throws CustomException { + private void processStartCommand ( + String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic + ) throws CustomException { String[] commandParts = lowerCaseCommand.split(" "); if (commandParts.length != 2) { @@ -48,7 +53,7 @@ private void processStartCommand(String lowerCaseCommand, Ui ui, TopicList topic ui.printChosenTopic(topicNum, topicList, questionListByTopic); } catch (NumberFormatException e) { - throw new CustomException("invalid " + lowerCaseCommand + " parameter"); + throw new CustomException("invalid " + lowerCaseCommand + " parameter"); } } diff --git a/src/main/java/seedu/duke/Player2113.java b/src/main/java/seedu/duke/Player2113.java index 46e83713c1..ad5f9486b9 100644 --- a/src/main/java/seedu/duke/Player2113.java +++ b/src/main/java/seedu/duke/Player2113.java @@ -1,8 +1,5 @@ package seedu.duke; -import java.util.ArrayList; -import java.util.Scanner; - public class Player2113 { public static final String SOME_FILE_PATH = "something"; private Ui ui; diff --git a/src/main/java/seedu/duke/TopicList.java b/src/main/java/seedu/duke/TopicList.java index 2cd43785c8..d6d99efc9e 100644 --- a/src/main/java/seedu/duke/TopicList.java +++ b/src/main/java/seedu/duke/TopicList.java @@ -2,7 +2,6 @@ import java.util.ArrayList; -import java.util.Scanner; public class TopicList { private ArrayList topicList; diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index cf2de2bdd1..9d5fa989b7 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -2,11 +2,8 @@ import seedu.duke.exceptions.CustomException; -import java.util.ArrayList; import java.util.Scanner; - - public class Ui { private static final int NEW_LINE = 48; public boolean isPlaying = true; @@ -15,7 +12,9 @@ public class Ui { public TopicList topicList; public QuestionListByTopic questionListByTopic; - public void readCommands(Ui ui, QuestionsList questionsList, TopicList topicList, QuestionListByTopic questionListByTopic) { + public void readCommands( + Ui ui, QuestionsList questionsList, TopicList topicList, QuestionListByTopic questionListByTopic + ) { Parser parser = new Parser(); Scanner in = new Scanner(System.in); printLine(); From aa72a2f2ed65acf31ed57ab9bb0ee40c244875bc Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Tue, 19 Mar 2024 23:14:50 +0800 Subject: [PATCH 039/334] add input answers for each question --- src/main/java/seedu/duke/Parser.java | 3 --- src/main/java/seedu/duke/Ui.java | 20 ++++++++++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 85618e952e..56eadf6ef8 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -6,9 +6,6 @@ public class Parser { private static final int PARAMETER_INDEX = 1; boolean hasChosenTopic = false; - - - public void parseCommand( String command, Ui ui, QuestionsList questionsList, TopicList topicList, QuestionListByTopic questionListByTopic diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 9d5fa989b7..d47cfac1f7 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -12,8 +12,11 @@ public class Ui { public TopicList topicList; public QuestionListByTopic questionListByTopic; + public String[] inputAnswers; + public void readCommands( - Ui ui, QuestionsList questionsList, TopicList topicList, QuestionListByTopic questionListByTopic + Ui ui, QuestionsList questionsList, TopicList topicList, + QuestionListByTopic questionListByTopic ) { Parser parser = new Parser(); Scanner in = new Scanner(System.in); @@ -36,6 +39,10 @@ private void askForInput() { System.out.println("Input a command player! // TODO: show possible commands"); // TODO } + private void askForAnswerInput(){ + System.out.print("Enter your answer: "); + } + public void printTopicList(TopicList topicList, Ui ui){ int topicListSize = topicList.getSize(); System.out.println("Here are the topics in CS2113: "); @@ -45,16 +52,25 @@ public void printTopicList(TopicList topicList, Ui ui){ System.out.println("Please choose a topic to play: ");//input command in the form "start [INDEX] } - public void printChosenTopic(int topicNum, TopicList topicList, QuestionListByTopic questionListByTopic){ + public void printChosenTopic( + int topicNum, TopicList topicList, QuestionListByTopic questionListByTopic + ){ QuestionsList qnList = new QuestionsList(); System.out.println("Selected topic: " + topicList.getTopic(topicNum - 1)); System.out.println("Here are the questions: "); qnList = questionListByTopic.getQuestionSet(topicNum - 1); int numOfQns = qnList.getSize(); Question questionUnit; + String[] inputAnswers = new String[numOfQns]; + String answer; for (int index = 0; index < numOfQns; index ++){ questionUnit = qnList.getQuestionUnit(index); System.out.println(questionUnit.getQuestion()); + askForAnswerInput(); + Parser parser = new Parser(); + Scanner in = new Scanner(System.in); + answer = in.nextLine(); + inputAnswers[index] = answer; } } From 952c42068de29fa58187c7b73edd51da5a1cd800 Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Wed, 20 Mar 2024 11:45:42 +0800 Subject: [PATCH 040/334] resolve bugs for solution and explanation --- src/main/java/seedu/duke/Parser.java | 45 +++++++++++++++++++--------- src/main/java/seedu/duke/Ui.java | 6 ++++ 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 56eadf6ef8..38abb3ac4b 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -23,7 +23,8 @@ public void parseCommand( if (lowerCaseCommand.startsWith("bye")) { ui.isPlaying = false; } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { - processSolutionCommand(lowerCaseCommand, ui, questionsList); + //System.out.println("ERROR"); + processSolutionCommand(lowerCaseCommand, ui, questionsList, topicList, questionListByTopic); } else if (!lowerCaseCommand.startsWith("topic")) { throw new CustomException("-1 HP coz invalid command"); } @@ -58,44 +59,60 @@ private void processStartCommand ( // user enters "solution 1" to get solution for question1 OR // user enters "solution -all" to get ALL solutions // also works for "explain 1" - private void processSolutionCommand(String lowerCaseCommand, Ui ui, QuestionsList questionsList) - throws CustomException { + private void processSolutionCommand( + String lowerCaseCommand, Ui ui, QuestionsList questionsList, + TopicList topicList, QuestionListByTopic questionListByTopic + ) throws CustomException { boolean isSolutionCommand = lowerCaseCommand.startsWith("solution"); String typeOfCommand = isSolutionCommand ? "solution" : "explain"; String[] commandParts = lowerCaseCommand.split(" "); - if (commandParts.length != 2) { - throw new CustomException("invalid " + typeOfCommand + " command"); + if (commandParts.length != 3) { + throw new CustomException("invalid " + typeOfCommand + " command. Format: solution TOPIC QUESTION_INDEX"); } + // check validity of parameter - String commandParameter = commandParts[PARAMETER_INDEX]; + String commandParameterTopic = commandParts[PARAMETER_INDEX]; + String commandParameterQn = commandParts[PARAMETER_INDEX + 1]; + try { // if parameter is an Integer - int questionNum = Integer.parseInt(commandParameter); + int topicNum = Integer.parseInt(commandParameterTopic); + int questionNum = Integer.parseInt(commandParameterQn); + // checks validity of parameter - if (questionNum < 1 || questionNum > questionsList.getSize() + 1) { - throw new CustomException("booo no such question"); + if ((topicNum < 1 || topicNum > topicList.getSize())) { + throw new CustomException("booo no such topic"); + } + + QuestionsList qnList = questionListByTopic.getQuestionSet(topicNum - 1); + if (questionNum < 1 || questionNum > qnList.getSize()) { + throw new CustomException(("booo no such question")); } + if (isSolutionCommand) { - String solution = questionsList.getOneSolution(questionNum); + String solution = qnList.getOneSolution(questionNum); ui.printOneSolution(questionNum, solution); return; } // only runs if explanation - String explanation = questionsList.getOneExplanation(questionNum); + + String explanation = qnList.getOneExplanation(questionNum); ui.printOneSolution(questionNum, explanation); } catch (NumberFormatException e) { // if parameter is a String - if (!commandParameter.contentEquals("-all")) { + if (!commandParameterQn.contentEquals("-all")) { throw new CustomException("invalid " + typeOfCommand + " parameter"); } if (!isSolutionCommand) { throw new CustomException("There is no \"explain -all\" command"); } - - String allSolutions = questionsList.getAllSolutions(); + int topicNum = Integer.parseInt(commandParameterTopic); + QuestionsList qnList = questionListByTopic.getQuestionSet(topicNum - 1); + String allSolutions = qnList.getAllSolutions(); ui.printAllSolutions(allSolutions); } + } } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index d47cfac1f7..57648fc3ac 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -79,6 +79,12 @@ public void printOneSolution(int questionNum, String solution) { System.out.println("The solution for question " + questionNum + ":" + System.lineSeparator() + solution); } + + public void printOneExplanation (int questionNum, String explanation) { + System.out.println("The explanation for question " + questionNum + ":" + + System.lineSeparator() + explanation); + } + public void printAllSolutions(String allSolutions) { System.out.println("The solutions are :" + System.lineSeparator() + allSolutions); From 3c850816a4c2495ce8d06772da928362e79f7346 Mon Sep 17 00:00:00 2001 From: yuhengr Date: Wed, 20 Mar 2024 20:00:19 +0800 Subject: [PATCH 041/334] Add class ProgressManager for clearing session results --- src/main/java/seedu/duke/ProgressManager.java | 15 +++++++++++++++ src/main/java/seedu/duke/ResultsList.java | 5 +++++ 2 files changed, 20 insertions(+) create mode 100644 src/main/java/seedu/duke/ProgressManager.java diff --git a/src/main/java/seedu/duke/ProgressManager.java b/src/main/java/seedu/duke/ProgressManager.java new file mode 100644 index 0000000000..dd1d917839 --- /dev/null +++ b/src/main/java/seedu/duke/ProgressManager.java @@ -0,0 +1,15 @@ +package seedu.duke; + + +public class ProgressManager { + + private ResultsList sessionResults; + + public ProgressManager(ResultsList sessionResults) { + this.sessionResults = sessionResults; + } + + public void clearProgress() { + sessionResults.clearResults(); + } +} diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index c578765fda..7c05f65424 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -33,5 +33,10 @@ public String toString() { } return listOfResults.toString(); } + + public void clearResults() { + sessionResults.clear(); + count = ZERO_RESULTS; + } } From 02c366da8d4285baac991896619b48cf3769cddd Mon Sep 17 00:00:00 2001 From: yuhengr Date: Wed, 20 Mar 2024 20:33:27 +0800 Subject: [PATCH 042/334] Add class ProgressManagerTest skeleton --- src/test/java/seedu/duke/ProgressManagerTest.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/test/java/seedu/duke/ProgressManagerTest.java diff --git a/src/test/java/seedu/duke/ProgressManagerTest.java b/src/test/java/seedu/duke/ProgressManagerTest.java new file mode 100644 index 0000000000..a3f1b040ce --- /dev/null +++ b/src/test/java/seedu/duke/ProgressManagerTest.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class ProgressManagerTest { +} From b78734f1942dca89debf1fa3d44603d7536a043b Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Wed, 20 Mar 2024 21:18:20 +0800 Subject: [PATCH 043/334] add comments on where to integrate results --- src/main/java/seedu/duke/Parser.java | 8 ++++++++ src/main/java/seedu/duke/Ui.java | 5 +++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 38abb3ac4b..43d8fd6807 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -114,5 +114,13 @@ private void processSolutionCommand( } } + + public void handleAnswerInputs(String[] inputAnswers, int index, String answer, Question questionUnit){ + inputAnswers[index] = answer; + String correctAnswer = questionUnit.getSolution(); + if (answer.equals(correctAnswer)){ + //increase score + } + } } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 57648fc3ac..3b2612d1b8 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -63,15 +63,16 @@ public void printChosenTopic( Question questionUnit; String[] inputAnswers = new String[numOfQns]; String answer; - for (int index = 0; index < numOfQns; index ++){ + for (int index = 0; index < numOfQns; index ++){//go through 1 question set questionUnit = qnList.getQuestionUnit(index); System.out.println(questionUnit.getQuestion()); askForAnswerInput(); Parser parser = new Parser(); Scanner in = new Scanner(System.in); answer = in.nextLine(); - inputAnswers[index] = answer; + parser.handleAnswerInputs(inputAnswers, index, answer, questionUnit); } + //add results to resultsList } From a832beb38783c5917ccc86263a5fd6558570e7ca Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Wed, 20 Mar 2024 21:34:08 +0800 Subject: [PATCH 044/334] Add support to view results with questions --- src/main/java/seedu/duke/QuestionsList.java | 19 +++++++++++++- src/main/java/seedu/duke/ResultsList.java | 16 ++++++++++-- src/test/java/seedu/duke/ResultsListTest.java | 26 ++++++++++++++++--- 3 files changed, 54 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/duke/QuestionsList.java b/src/main/java/seedu/duke/QuestionsList.java index d364441cd9..1af32bc6e9 100644 --- a/src/main/java/seedu/duke/QuestionsList.java +++ b/src/main/java/seedu/duke/QuestionsList.java @@ -52,5 +52,22 @@ public String getAllSolutions() throws CustomException { return allQuestions.toString(); } -} + public String getAllQuestions() throws CustomException { + if (questionsList.isEmpty()) { + throw new CustomException("No questions yet"); + } + StringBuilder allQuestions = new StringBuilder(); + + for (Question question : questionsList) { + int questionNum = questionsList.indexOf(question) + 1; // +1 coz zero index + String header = "Question " + questionNum + ":" + System.lineSeparator(); + String displayQuestion = header + question.getQuestion() + System.lineSeparator(); + + allQuestions.append(displayQuestion); + allQuestions.append(System.lineSeparator()); + } + + return allQuestions.toString(); + } +} diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index d0d8d980f0..b1f46d4135 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -1,20 +1,26 @@ package seedu.duke; +import seedu.duke.exceptions.CustomException; + import java.util.ArrayList; public class ResultsList { private static final int ZERO_RESULTS = 0; + private static final String MESSAGE_NO_RESULTS = "No results yet."; protected ArrayList sessionResults; + protected ArrayList sessionQuestions; protected int count; public ResultsList() { sessionResults = new ArrayList<>(); + sessionQuestions = new ArrayList<>(); count = ZERO_RESULTS; } - public void addResult(Results roundResults) { + public void addResultAndQuestions(Results roundResults, QuestionsList roundQuestions) { sessionResults.add(roundResults); + sessionQuestions.add(roundQuestions); count++; } @@ -26,10 +32,16 @@ public ArrayList getAllResults() { return sessionResults; } - public String toString(boolean includesQuestion) { + public String toString(boolean includesQuestion) throws CustomException { + if (sessionResults.isEmpty()) { + throw new CustomException(MESSAGE_NO_RESULTS); + } StringBuilder listOfResults = new StringBuilder(); for (int i = 0; i < count; i++) { listOfResults.append((i + 1)).append(". ").append(sessionResults.get(i).getScore()).append("\n"); + if (includesQuestion) { + listOfResults.append(sessionQuestions.get(i).getAllQuestions()); + } } return listOfResults.toString(); } diff --git a/src/test/java/seedu/duke/ResultsListTest.java b/src/test/java/seedu/duke/ResultsListTest.java index 858d1daf9e..af17216624 100644 --- a/src/test/java/seedu/duke/ResultsListTest.java +++ b/src/test/java/seedu/duke/ResultsListTest.java @@ -1,32 +1,50 @@ package seedu.duke; import org.junit.jupiter.api.Test; +import seedu.duke.exceptions.CustomException; import static org.junit.jupiter.api.Assertions.assertEquals; class ResultsListTest { Results roundOneResults; Results roundTwoResults; + Question roundOneQuestionOne; + Question roundOneQuestionTwo; + Question roundTwoQuestionOne; + QuestionsList roundOneQuestions; + QuestionsList roundTwoQuestions; ResultsList sessionsResults; void createResultList() { roundOneResults = new Results(); + roundOneQuestions = new QuestionsList(); roundTwoResults = new Results(); + roundTwoQuestions = new QuestionsList(); sessionsResults = new ResultsList(); + + + roundOneQuestionOne = new Question("question 1-1","solution 1-1","explanation 1-1"); + roundOneQuestions.addQuestion(roundOneQuestionOne); roundOneResults.increaseNumberOfQuestions(); + roundOneQuestionTwo = new Question("question 1-1","solution 1-1","explanation 1-1"); + roundOneQuestions.addQuestion(roundOneQuestionTwo); roundOneResults.increaseNumberOfQuestions(); roundOneResults.increaseCorrectAnswers(); roundOneResults.calculateScore(); // 1 out of 2 correct + + roundTwoQuestionOne = new Question("question 2-1","solution 2-1", "explanation 2-1"); + roundTwoQuestions.addQuestion(roundTwoQuestionOne); roundTwoResults.increaseNumberOfQuestions(); roundTwoResults.increaseCorrectAnswers(); roundTwoResults.calculateScore(); // 1 out of 1 correct - sessionsResults.addResult(roundOneResults); // returns 1/2 (50%) - sessionsResults.addResult(roundTwoResults); // returns 1/1 (100%) + + sessionsResults.addResultAndQuestions(roundOneResults, roundOneQuestions); // returns 1/2 (50%) + sessionsResults.addResultAndQuestions(roundTwoResults, roundTwoQuestions); // returns 1/1 (100%) } @Test - void testStringConversion_twoRoundResults() { + void testStringConversion_twoRoundResults() throws CustomException { createResultList(); - assertEquals("1. 1/2 (50%)\n2. 1/1 (100%)\n", sessionsResults.toString()); + assertEquals("1. 1/2 (50%)\n2. 1/1 (100%)\n", sessionsResults.toString(false)); } } From 1d963fc42050d85f1aecd34de8f139a3f0438baf Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Wed, 20 Mar 2024 21:34:27 +0800 Subject: [PATCH 045/334] Add Ui messages regarding results --- src/main/java/seedu/duke/Ui.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index d886d876d5..4de9e47819 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -38,6 +38,15 @@ public void printAllSolutions(String allSolutions) { System.out.println("The solutions are :" + System.lineSeparator() + allSolutions); } + + public void printOneResult(int roundNum, String score) { + System.out.println("Your results for Round " + roundNum + ":\n" + score); + } + + public void printAllResults(String allResults) { + System.out.println("These are all your results so far:\n" + allResults); + } + private void handleException(CustomException e) { System.out.println(e.getMessage() + "TODO: show possible commands"); //TODO } From e568a838aa3be3f1bf28fb4d55c545fb4549d331 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 00:48:05 +0800 Subject: [PATCH 046/334] Add recognition of results command --- src/main/java/seedu/duke/Parser.java | 59 +++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 43d8fd6807..e52dc460e6 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -4,11 +4,22 @@ public class Parser { private static final int PARAMETER_INDEX = 1; + + private static final int NO_PARAMETERS = 1; + private static final int ONE_PARAMETER = 2; + private static final int TWO_PARAMETERS = 3; + private static final int FIRST_PARAMETER = 1; + private static final int SECOND_PARAMETER = 2; + + private static final String QUESTION_PARAMETER = "questions"; + private static final String COMMAND_SPLITTER = " "; + + private static final boolean INCLUDES_QUESTION = true; boolean hasChosenTopic = false; public void parseCommand( String command, Ui ui, QuestionsList questionsList, - TopicList topicList, QuestionListByTopic questionListByTopic + TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults ) throws CustomException { String lowerCaseCommand = command.toLowerCase(); if (ui.isPlaying) { @@ -25,15 +36,50 @@ public void parseCommand( } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { //System.out.println("ERROR"); processSolutionCommand(lowerCaseCommand, ui, questionsList, topicList, questionListByTopic); - } else if (!lowerCaseCommand.startsWith("topic")) { + } else if (lowerCaseCommand.startsWith("results")) { + processResultsCommand(lowerCaseCommand, allResults, ui, questionListByTopic); + } else if (!lowerCaseCommand.startsWith("topic")) { throw new CustomException("-1 HP coz invalid command"); } } } + private void processResultsCommand(String lowerCaseCommand, ResultsList allResults, Ui ui, + QuestionListByTopic questionListByTopic) { + String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER, TWO_PARAMETERS); + switch (commandParts.length) { + case (NO_PARAMETERS): { + ui.printAllResults(!INCLUDES_QUESTION, allResults, questionListByTopic); + break; + } + case (ONE_PARAMETER): { + if (commandParts[PARAMETER_INDEX].equals(QUESTION_PARAMETER)) { + ui.printAllResults(INCLUDES_QUESTION, allResults, questionListByTopic); + } else { + int index = Integer.parseInt(commandParts[FIRST_PARAMETER]); + String score = allResults.getSpecifiedResult(index - 1).getScore(); + int topicNum = allResults.getTopicNum(index - 1); + ui.printOneResult(!INCLUDES_QUESTION, topicNum, score, questionListByTopic); + } + break; + } + case (TWO_PARAMETERS): { + int index = Integer.parseInt(commandParts[SECOND_PARAMETER]); + String score = allResults.getSpecifiedResult(index - 1).getScore(); + int topicNum = allResults.getTopicNum(index - 1); + ui.printOneResult(INCLUDES_QUESTION, topicNum, score, questionListByTopic); + break; + } + default: { + break; + } + } + } + private void processStartCommand ( - String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic + String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic, + ResultsList allResults ) throws CustomException { String[] commandParts = lowerCaseCommand.split(" "); @@ -48,7 +94,7 @@ private void processStartCommand ( if (topicNum < 1 || topicNum > topicList.getSize() + 1) { throw new CustomException("booo no such topic"); } - ui.printChosenTopic(topicNum, topicList, questionListByTopic); + ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults); } catch (NumberFormatException e) { throw new CustomException("invalid " + lowerCaseCommand + " parameter"); @@ -115,11 +161,12 @@ private void processSolutionCommand( } - public void handleAnswerInputs(String[] inputAnswers, int index, String answer, Question questionUnit){ + public void handleAnswerInputs(String[] inputAnswers, int index, String answer, Question questionUnit, + Results topicResults){ inputAnswers[index] = answer; String correctAnswer = questionUnit.getSolution(); if (answer.equals(correctAnswer)){ - //increase score + topicResults.increaseCorrectAnswers(); } } } From 234c5116ba2ed2af797da036d9e310b0cece6378 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 00:48:37 +0800 Subject: [PATCH 047/334] Comment out hasChosenTopic --- src/main/java/seedu/duke/Parser.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index e52dc460e6..fac22b96ba 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -25,9 +25,9 @@ public void parseCommand( if (ui.isPlaying) { if (lowerCaseCommand.startsWith("topic") && !hasChosenTopic) { - processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic); - hasChosenTopic = true; - } else if (!hasChosenTopic) { + processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, allResults); + //hasChosenTopic = true; + } else if (lowerCaseCommand.startsWith("topic") && hasChosenTopic) { throw new CustomException("Please choose a topic in the format: topic [INDEX]"); } From 1215d03335594df3ff56d447b5906009ba872cfc Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 00:50:40 +0800 Subject: [PATCH 048/334] Add feature to get all questions --- src/main/java/seedu/duke/QuestionsList.java | 9 ++--- src/main/java/seedu/duke/ResultsList.java | 38 ++++++--------------- 2 files changed, 14 insertions(+), 33 deletions(-) diff --git a/src/main/java/seedu/duke/QuestionsList.java b/src/main/java/seedu/duke/QuestionsList.java index 8b25b6955a..c8f4989316 100644 --- a/src/main/java/seedu/duke/QuestionsList.java +++ b/src/main/java/seedu/duke/QuestionsList.java @@ -57,14 +57,11 @@ public String getAllSolutions() throws CustomException { return allQuestions.toString(); } - public String getAllQuestions() throws CustomException { - if (questionsList.isEmpty()) { - throw new CustomException("No questions yet"); - } + public String getAllQuestions() { StringBuilder allQuestions = new StringBuilder(); - for (Question question : questionsList) { - int questionNum = questionsList.indexOf(question) + 1; // +1 coz zero index + for (Question question : chosenQuestionsList) { + int questionNum = chosenQuestionsList.indexOf(question) + 1; // +1 coz zero index String header = "Question " + questionNum + ":" + System.lineSeparator(); String displayQuestion = header + question.getQuestion() + System.lineSeparator(); diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index b1f46d4135..781a758d7e 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -1,49 +1,33 @@ package seedu.duke; -import seedu.duke.exceptions.CustomException; - import java.util.ArrayList; public class ResultsList { - private static final int ZERO_RESULTS = 0; - private static final String MESSAGE_NO_RESULTS = "No results yet."; - protected ArrayList sessionResults; - protected ArrayList sessionQuestions; - protected int count; + protected ArrayList topicsChosen; public ResultsList() { sessionResults = new ArrayList<>(); - sessionQuestions = new ArrayList<>(); - count = ZERO_RESULTS; + topicsChosen = new ArrayList<>(); } - public void addResultAndQuestions(Results roundResults, QuestionsList roundQuestions) { + public void addResults(Results roundResults) { sessionResults.add(roundResults); - sessionQuestions.add(roundQuestions); - count++; + } + + public void addQuestions(Integer topicNumber) { + topicsChosen.add(topicNumber); } public Results getSpecifiedResult(int index) throws IndexOutOfBoundsException { return sessionResults.get(index); } - public ArrayList getAllResults() { - return sessionResults; + public Integer getTopicNum(int index) throws IndexOutOfBoundsException { + return topicsChosen.get(index); } - public String toString(boolean includesQuestion) throws CustomException { - if (sessionResults.isEmpty()) { - throw new CustomException(MESSAGE_NO_RESULTS); - } - StringBuilder listOfResults = new StringBuilder(); - for (int i = 0; i < count; i++) { - listOfResults.append((i + 1)).append(". ").append(sessionResults.get(i).getScore()).append("\n"); - if (includesQuestion) { - listOfResults.append(sessionQuestions.get(i).getAllQuestions()); - } - } - return listOfResults.toString(); + public int getSizeOfAllResults() { + return sessionResults.size(); } } - From c45201c6927f261210301d296b638b0767082a55 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 00:51:12 +0800 Subject: [PATCH 049/334] Add ability to print results --- src/main/java/seedu/duke/Player2113.java | 4 ++- src/main/java/seedu/duke/Ui.java | 40 ++++++++++++++++++------ 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/src/main/java/seedu/duke/Player2113.java b/src/main/java/seedu/duke/Player2113.java index ad5f9486b9..57cd1a54b8 100644 --- a/src/main/java/seedu/duke/Player2113.java +++ b/src/main/java/seedu/duke/Player2113.java @@ -8,6 +8,7 @@ public class Player2113 { private QuestionsList questionsList2; private TopicList topicList; private QuestionListByTopic questionListByTopic; + private ResultsList allResults; public Player2113(String someFilePath) { questionsList1 = new QuestionsList(); @@ -37,13 +38,14 @@ public Player2113(String someFilePath) { } public void run() { + allResults = new ResultsList(); ui = new Ui(); ui.sayHi(); ui.printTopicList(topicList, ui); while (ui.isPlaying) { - ui.readCommands(ui, questionsList, topicList, questionListByTopic); + ui.readCommands(ui, questionsList, topicList, questionListByTopic, allResults); } } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index c9618167a9..0fb2a6e768 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -5,6 +5,8 @@ import java.util.Scanner; public class Ui { + private static final String HEADER_ALL_RESULTS = "These are all your results so far:\n"; + private static final int NEW_LINE = 48; public boolean isPlaying = true; @@ -16,7 +18,7 @@ public class Ui { public void readCommands( Ui ui, QuestionsList questionsList, TopicList topicList, - QuestionListByTopic questionListByTopic + QuestionListByTopic questionListByTopic, ResultsList allResults ) { Parser parser = new Parser(); Scanner in = new Scanner(System.in); @@ -26,7 +28,7 @@ public void readCommands( ui.askForInput(); String command = in.nextLine(); try { - parser.parseCommand(command, ui, questionsList, topicList, questionListByTopic); + parser.parseCommand(command, ui, questionsList, topicList, questionListByTopic, allResults); } catch (CustomException e) { ui.handleException(e); } @@ -53,26 +55,30 @@ public void printTopicList(TopicList topicList, Ui ui){ } public void printChosenTopic( - int topicNum, TopicList topicList, QuestionListByTopic questionListByTopic + int topicNum, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList alLResults ){ - QuestionsList qnList = new QuestionsList(); + Results topicResults = new Results(); + QuestionsList qnList; System.out.println("Selected topic: " + topicList.getTopic(topicNum - 1)); System.out.println("Here are the questions: "); qnList = questionListByTopic.getQuestionSet(topicNum - 1); + alLResults.addQuestions(topicNum - 1); int numOfQns = qnList.getSize(); Question questionUnit; String[] inputAnswers = new String[numOfQns]; String answer; for (int index = 0; index < numOfQns; index ++){//go through 1 question set questionUnit = qnList.getQuestionUnit(index); + topicResults.increaseNumberOfQuestions(); System.out.println(questionUnit.getQuestion()); askForAnswerInput(); Parser parser = new Parser(); Scanner in = new Scanner(System.in); answer = in.nextLine(); - parser.handleAnswerInputs(inputAnswers, index, answer, questionUnit); + parser.handleAnswerInputs(inputAnswers, index, answer, questionUnit, topicResults); } - //add results to resultsList + topicResults.calculateScore(); + alLResults.addResults(topicResults); } @@ -91,12 +97,26 @@ public void printAllSolutions(String allSolutions) { + System.lineSeparator() + allSolutions); } - public void printOneResult(int roundNum, String score) { - System.out.println("Your results for Round " + roundNum + ":\n" + score); + public void printOneResult(boolean includesQuestions, int topicNum, String score, + QuestionListByTopic questionListByTopic) { + System.out.println("Your results for Topic " + (topicNum + 1) + ":\n" + score + "\n"); + if (includesQuestions) { + System.out.println(questionListByTopic.getQuestionSet(topicNum).getAllQuestions()); + } } - public void printAllResults(String allResults) { - System.out.println("These are all your results so far:\n" + allResults); + public void printAllResults(boolean includesQuestions, ResultsList allResults, + QuestionListByTopic questionListByTopic) { + int numberOfResults = allResults.getSizeOfAllResults(); + System.out.println(HEADER_ALL_RESULTS); + for (int i = 0; i < numberOfResults; i++) { + int topicNum = allResults.getTopicNum(i); + System.out.println("Your results for Topic " + (topicNum + 1) + ":\n" + + allResults.getSpecifiedResult(i).getScore() + "\n"); + if (includesQuestions) { + System.out.println(questionListByTopic.getQuestionSet(topicNum).getAllQuestions()); + } + } } private void handleException(CustomException e) { From aec7587b5aca4a1fd367f785a5c566218fb97da8 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 00:51:26 +0800 Subject: [PATCH 050/334] Update test case --- src/test/java/seedu/duke/ResultsListTest.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/test/java/seedu/duke/ResultsListTest.java b/src/test/java/seedu/duke/ResultsListTest.java index af17216624..04c0b32691 100644 --- a/src/test/java/seedu/duke/ResultsListTest.java +++ b/src/test/java/seedu/duke/ResultsListTest.java @@ -38,13 +38,15 @@ void createResultList() { roundTwoResults.increaseCorrectAnswers(); roundTwoResults.calculateScore(); // 1 out of 1 correct - sessionsResults.addResultAndQuestions(roundOneResults, roundOneQuestions); // returns 1/2 (50%) - sessionsResults.addResultAndQuestions(roundTwoResults, roundTwoQuestions); // returns 1/1 (100%) + sessionsResults.addResults(roundOneResults); // returns 1/2 (50%) + sessionsResults.addResults(roundTwoResults); // returns 1/1 (100%) } @Test void testStringConversion_twoRoundResults() throws CustomException { createResultList(); - assertEquals("1. 1/2 (50%)\n2. 1/1 (100%)\n", sessionsResults.toString(false)); + assertEquals("1/2 (50%)\n1/1 (100%)\n", + sessionsResults.getSpecifiedResult(0).getScore() + +"\n"+ sessionsResults.getSpecifiedResult(1).getScore()+"\n"); } } From 3e1b18b1d2ecde0895bf408a00d85c9ce6656fff Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 01:24:49 +0800 Subject: [PATCH 051/334] Cleanup code --- src/main/java/seedu/duke/Parser.java | 2 +- src/main/java/seedu/duke/Player2113.java | 4 ++-- src/main/java/seedu/duke/Ui.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index f3f31c36d1..cc9bf1dd0b 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -19,7 +19,7 @@ public class Parser { public void parseCommand( String command, Ui ui, QuestionsList questionsList, - TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults + TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults, Helper helper ) throws CustomException { String lowerCaseCommand = command.toLowerCase(); if (ui.isPlaying) { diff --git a/src/main/java/seedu/duke/Player2113.java b/src/main/java/seedu/duke/Player2113.java index ccaec5aef4..adcef63cf1 100644 --- a/src/main/java/seedu/duke/Player2113.java +++ b/src/main/java/seedu/duke/Player2113.java @@ -16,6 +16,7 @@ public Player2113(String someFilePath) { questionsList2 = new QuestionsList(); questionListByTopic = new QuestionListByTopic(); topicList = new TopicList(); + allResults = new ResultsList(); helper = new Helper(); if (someFilePath.contentEquals("something")) { @@ -42,13 +43,12 @@ public Player2113(String someFilePath) { } public void run() { - allResults = new ResultsList(); ui = new Ui(); ui.sayHi(); ui.printTopicList(topicList, ui); while (ui.isPlaying) { - ui.readCommands(ui, questionsList, topicList, questionListByTopic, allResults); + ui.readCommands(ui, questionsList, topicList, questionListByTopic, allResults, helper); } } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 4e285c359e..32fd1fcd3b 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -20,7 +20,7 @@ public class Ui { public void readCommands( Ui ui, QuestionsList questionsList, TopicList topicList, - QuestionListByTopic questionListByTopic, ResultsList allResults + QuestionListByTopic questionListByTopic, ResultsList allResults, Helper helper ) { Parser parser = new Parser(); Scanner in = new Scanner(System.in); @@ -30,7 +30,7 @@ public void readCommands( ui.askForInput(); String command = in.nextLine(); try { - parser.parseCommand(command, ui, questionsList, topicList, questionListByTopic, allResults); + parser.parseCommand(command, ui, questionsList, topicList, questionListByTopic, allResults, helper); } catch (CustomException e) { ui.handleException(e); } From 71125a0a59a81061e09245f33e4dba5bb571c2c8 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 02:03:17 +0800 Subject: [PATCH 052/334] Edit text UI tests --- src/main/java/seedu/duke/Ui.java | 8 ++++---- text-ui-test/EXPECTED.TXT | 26 +++++--------------------- text-ui-test/input.txt | 5 ----- 3 files changed, 9 insertions(+), 30 deletions(-) diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 32fd1fcd3b..20dd8faafc 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -18,12 +18,13 @@ public class Ui { public String[] inputAnswers; + private static final Scanner in = new Scanner(System.in); + public void readCommands( Ui ui, QuestionsList questionsList, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults, Helper helper ) { Parser parser = new Parser(); - Scanner in = new Scanner(System.in); printLine(); while(isPlaying) { @@ -49,11 +50,11 @@ private void askForAnswerInput(){ public void printTopicList(TopicList topicList, Ui ui){ int topicListSize = topicList.getSize(); - System.out.println("Here are the topics in CS2113: "); + System.out.println("Here are the topics in CS2113:"); for (int index = 0; index < topicListSize; index++) { System.out.println((index + 1) + ". " + topicList.getTopic(index)); } - System.out.println("Please choose a topic to play: ");//input command in the form "start [INDEX] + System.out.println("Please choose a topic to play:");//input command in the form "start [INDEX] } public void printChosenTopic( @@ -144,7 +145,6 @@ public void sayHi() { 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()); printLine(); } diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 15e7edbf9e..3e22acc5bc 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -10,29 +10,13 @@ ______ _ _____ __ __ _____ What is your name? Hello CaiShenYe ************************************************ +Here are the topics in CS2113: +1. topic1 +2. topic2 +Please choose a topic to play: +************************************************ Input a command player! // TODO: show possible commands -1 HP coz invalid commandTODO: show possible commands Input a command player! // TODO: show possible commands -The solution for question 1: -solution1 -Input a command player! // TODO: show possible commands -The solution for question 2: -solution2 -Input a command player! // TODO: show possible commands -The solutions are : -Solution for question 1: -solution1 - -Solution for question 2: -solution2 - - -Input a command player! // TODO: show possible commands -The solution for question 1: -explanation1 -Input a command player! // TODO: show possible commands -The solution for question 2: -explanation2 -Input a command player! // TODO: show possible commands bye bye, get more sleep zzz ************************************************ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index e793dcf9f1..08fa3b921a 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,8 +1,3 @@ CaiShenYe invalidCommand -solution 1 -solution 2 -solution -all -explain 1 -explain 2 bye \ No newline at end of file From 51f2575637681fc711f4e0f530b56f8d46f41233 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 02:04:45 +0800 Subject: [PATCH 053/334] Cleanup code --- src/main/java/seedu/duke/Ui.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 20dd8faafc..72bcdae28a 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -7,6 +7,8 @@ import java.util.Scanner; public class Ui { + private static final Scanner in = new Scanner(System.in); + private static final String HEADER_ALL_RESULTS = "These are all your results so far:\n"; private static final int NEW_LINE = 48; @@ -18,8 +20,6 @@ public class Ui { public String[] inputAnswers; - private static final Scanner in = new Scanner(System.in); - public void readCommands( Ui ui, QuestionsList questionsList, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults, Helper helper From 1a97590fad2d7001a5a33b2a3c630f714125d67c Mon Sep 17 00:00:00 2001 From: yuhengr Date: Thu, 21 Mar 2024 09:27:13 +0800 Subject: [PATCH 054/334] Add test to clear session results --- src/main/java/seedu/duke/ResultsList.java | 4 +++ .../java/seedu/duke/ProgressManagerTest.java | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index 7c05f65424..a3f8bc1d78 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -38,5 +38,9 @@ public void clearResults() { sessionResults.clear(); count = ZERO_RESULTS; } + + public int getNumOfResults() { + return count; + } } diff --git a/src/test/java/seedu/duke/ProgressManagerTest.java b/src/test/java/seedu/duke/ProgressManagerTest.java index a3f1b040ce..1b5d45fe5f 100644 --- a/src/test/java/seedu/duke/ProgressManagerTest.java +++ b/src/test/java/seedu/duke/ProgressManagerTest.java @@ -1,4 +1,30 @@ package seedu.duke; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + public class ProgressManagerTest { + ResultsList sessionResults = new ResultsList(); + + void createResultList() { + + final int NUM_OF_RESULTS = 3; + Results[] results = new Results[NUM_OF_RESULTS]; + + for(int i = 0; i < NUM_OF_RESULTS; i++) { + results[i].increaseNumberOfQuestions(); + sessionResults.addResult(results[i]); + } + } + + + @Test + public void testClearProgress() { + + createResultList(); + ProgressManager pm = new ProgressManager(sessionResults); + pm.clearProgress(); + assertEquals(0, sessionResults.getNumOfResults()); + } } From 75eee6c23148f856923591d721f36b47491803e7 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 12:40:49 +0800 Subject: [PATCH 055/334] Add AnswerTracker class --- src/main/java/seedu/duke/AnswerTracker.java | 29 +++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/main/java/seedu/duke/AnswerTracker.java diff --git a/src/main/java/seedu/duke/AnswerTracker.java b/src/main/java/seedu/duke/AnswerTracker.java new file mode 100644 index 0000000000..6b3c5a3ce4 --- /dev/null +++ b/src/main/java/seedu/duke/AnswerTracker.java @@ -0,0 +1,29 @@ +package seedu.duke; + +import java.util.ArrayList; + +public class AnswerTracker { + protected ArrayList> userAnswers; + protected ArrayList> isCorrect; + + public AnswerTracker() { + userAnswers = new ArrayList<>(); + isCorrect = new ArrayList<>(); + } + + public String getUserAnswers(int index, int attemptNumber) { + return userAnswers.get(attemptNumber).get(index); + } + + public Boolean getIsCorrect(int index, int attemptNumber) { + return isCorrect.get(attemptNumber).get(index); + } + + public void addUserAnswers(ArrayList answers) { + userAnswers.add(answers); + } + + public void addUserCorrectness(ArrayList correctness) { + isCorrect.add(correctness); + } +} From 3fc408580ff72d9ee9a382861deb22876e440074 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 12:42:44 +0800 Subject: [PATCH 056/334] Add support to track user answers --- src/main/java/seedu/duke/Parser.java | 13 +++--- src/main/java/seedu/duke/Player2113.java | 4 +- src/main/java/seedu/duke/QuestionsList.java | 15 ------- src/main/java/seedu/duke/Ui.java | 44 +++++++++++++++------ 4 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index cc9bf1dd0b..2b406203f8 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -2,6 +2,8 @@ import seedu.duke.exceptions.CustomException; +import java.util.ArrayList; + public class Parser { private static final int PARAMETER_INDEX = 1; @@ -19,25 +21,24 @@ public class Parser { public void parseCommand( String command, Ui ui, QuestionsList questionsList, - TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults, Helper helper + TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults, Helper helper, + AnswerTracker userAnswers ) throws CustomException { String lowerCaseCommand = command.toLowerCase(); if (ui.isPlaying) { if (lowerCaseCommand.startsWith("topic") && !hasChosenTopic) { - processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, allResults); + processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, allResults, userAnswers); //hasChosenTopic = true; } else if (lowerCaseCommand.startsWith("topic") && hasChosenTopic) { throw new CustomException("Please choose a topic in the format: topic [INDEX]"); - } - - if (lowerCaseCommand.startsWith("bye")) { + } else if (lowerCaseCommand.startsWith("bye")) { ui.isPlaying = false; } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { //System.out.println("ERROR"); processSolutionCommand(lowerCaseCommand, ui, questionsList, topicList, questionListByTopic); } else if (lowerCaseCommand.startsWith("results")) { - processResultsCommand(lowerCaseCommand, allResults, ui, questionListByTopic); + processResultsCommand(lowerCaseCommand, allResults, ui, questionListByTopic, userAnswers); } else if (lowerCaseCommand.startsWith("help")) { processHelpCommand(lowerCaseCommand, ui, helper); } else { diff --git a/src/main/java/seedu/duke/Player2113.java b/src/main/java/seedu/duke/Player2113.java index adcef63cf1..8ccb5e4de5 100644 --- a/src/main/java/seedu/duke/Player2113.java +++ b/src/main/java/seedu/duke/Player2113.java @@ -9,6 +9,7 @@ public class Player2113 { private TopicList topicList; private QuestionListByTopic questionListByTopic; private ResultsList allResults; + private AnswerTracker userAnswers; private final Helper helper; public Player2113(String someFilePath) { @@ -17,6 +18,7 @@ public Player2113(String someFilePath) { questionListByTopic = new QuestionListByTopic(); topicList = new TopicList(); allResults = new ResultsList(); + userAnswers = new AnswerTracker(); helper = new Helper(); if (someFilePath.contentEquals("something")) { @@ -48,7 +50,7 @@ public void run() { ui.printTopicList(topicList, ui); while (ui.isPlaying) { - ui.readCommands(ui, questionsList, topicList, questionListByTopic, allResults, helper); + ui.readCommands(ui, questionsList, topicList, questionListByTopic, allResults, helper, userAnswers); } } diff --git a/src/main/java/seedu/duke/QuestionsList.java b/src/main/java/seedu/duke/QuestionsList.java index c8f4989316..1c4926061c 100644 --- a/src/main/java/seedu/duke/QuestionsList.java +++ b/src/main/java/seedu/duke/QuestionsList.java @@ -56,19 +56,4 @@ public String getAllSolutions() throws CustomException { return allQuestions.toString(); } - - public String getAllQuestions() { - StringBuilder allQuestions = new StringBuilder(); - - for (Question question : chosenQuestionsList) { - int questionNum = chosenQuestionsList.indexOf(question) + 1; // +1 coz zero index - String header = "Question " + questionNum + ":" + System.lineSeparator(); - String displayQuestion = header + question.getQuestion() + System.lineSeparator(); - - allQuestions.append(displayQuestion); - allQuestions.append(System.lineSeparator()); - } - - return allQuestions.toString(); - } } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 72bcdae28a..2a8ba35f8e 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -4,6 +4,7 @@ import com.bethecoder.ascii_table.ASCIITable; import seedu.duke.exceptions.CustomException; +import java.util.ArrayList; import java.util.Scanner; public class Ui { @@ -22,7 +23,7 @@ public class Ui { public void readCommands( Ui ui, QuestionsList questionsList, TopicList topicList, - QuestionListByTopic questionListByTopic, ResultsList allResults, Helper helper + QuestionListByTopic questionListByTopic, ResultsList allResults, Helper helper, AnswerTracker userAnswers ) { Parser parser = new Parser(); printLine(); @@ -31,7 +32,8 @@ public void readCommands( ui.askForInput(); String command = in.nextLine(); try { - parser.parseCommand(command, ui, questionsList, topicList, questionListByTopic, allResults, helper); + parser.parseCommand(command, ui, questionsList, topicList, questionListByTopic, allResults, helper, + userAnswers); } catch (CustomException e) { ui.handleException(e); } @@ -58,7 +60,8 @@ public void printTopicList(TopicList topicList, Ui ui){ } public void printChosenTopic( - int topicNum, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList alLResults + int topicNum, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList alLResults, + AnswerTracker userAnswers ){ Results topicResults = new Results(); QuestionsList qnList; @@ -70,18 +73,22 @@ public void printChosenTopic( Question questionUnit; String[] inputAnswers = new String[numOfQns]; String answer; + ArrayList allAnswers = new ArrayList<>(); + ArrayList answersCorrectness = new ArrayList<>(); for (int index = 0; index < numOfQns; index ++){//go through 1 question set questionUnit = qnList.getQuestionUnit(index); topicResults.increaseNumberOfQuestions(); System.out.println(questionUnit.getQuestion()); askForAnswerInput(); Parser parser = new Parser(); - Scanner in = new Scanner(System.in); answer = in.nextLine(); - parser.handleAnswerInputs(inputAnswers, index, answer, questionUnit, topicResults); + parser.handleAnswerInputs(inputAnswers, index, answer, questionUnit, topicResults, answersCorrectness); + allAnswers.add(answer); } topicResults.calculateScore(); alLResults.addResults(topicResults); + userAnswers.addUserAnswers(allAnswers); + userAnswers.addUserCorrectness(answersCorrectness); } @@ -100,28 +107,39 @@ public void printAllSolutions(String allSolutions) { + System.lineSeparator() + allSolutions); } - public void printOneResult(boolean includesQuestions, int topicNum, String score, - QuestionListByTopic questionListByTopic) { + public void printOneResult(boolean includesDetails, int topicNum, String score, + QuestionListByTopic questionListByTopic, AnswerTracker userAnswers, int index) { System.out.println("Your results for Topic " + (topicNum + 1) + ":\n" + score + "\n"); - if (includesQuestions) { - System.out.println(questionListByTopic.getQuestionSet(topicNum).getAllQuestions()); + if (includesDetails) { + printResultDetails(questionListByTopic, topicNum, index-1, userAnswers); } } - public void printAllResults(boolean includesQuestions, ResultsList allResults, - QuestionListByTopic questionListByTopic) { + public void printAllResults(boolean includesDetails, ResultsList allResults, + QuestionListByTopic questionListByTopic, AnswerTracker userAnswers) { int numberOfResults = allResults.getSizeOfAllResults(); System.out.println(HEADER_ALL_RESULTS); for (int i = 0; i < numberOfResults; i++) { int topicNum = allResults.getTopicNum(i); System.out.println("Your results for Topic " + (topicNum + 1) + ":\n" + allResults.getSpecifiedResult(i).getScore() + "\n"); - if (includesQuestions) { - System.out.println(questionListByTopic.getQuestionSet(topicNum).getAllQuestions()); + if (includesDetails) { + printResultDetails(questionListByTopic, topicNum, i, userAnswers); } } } + private void printResultDetails(QuestionListByTopic questionListByTopic, int topicNum, int index, + AnswerTracker userAnswers) { + QuestionsList listOfQuestions = questionListByTopic.getQuestionSet(topicNum); + for (int i = 0; i < listOfQuestions.getSize(); i++) { + Question questionUnit = listOfQuestions.getQuestionUnit(i); + boolean isCorrectAnswer = userAnswers.getIsCorrect (i,index); + System.out.println(questionUnit.getQuestion() + "\nYou answered:\n" + userAnswers.getUserAnswers(i, index) + + "\nYou got it " + ((isCorrectAnswer) ? "right!\n" : "wrong!\n")); + } + } + private void handleException(CustomException e) { System.out.println(e.getMessage() + "TODO: show possible commands"); //TODO } From ce553ec324eba34718294c4dc1e5366521579094 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 12:43:32 +0800 Subject: [PATCH 057/334] Add support to track user answers --- src/main/java/seedu/duke/Parser.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 2b406203f8..23ef889f79 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -82,7 +82,7 @@ private void processResultsCommand(String lowerCaseCommand, ResultsList allResul private void processStartCommand ( String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic, - ResultsList allResults + ResultsList allResults, AnswerTracker userAnswers ) throws CustomException { String[] commandParts = lowerCaseCommand.split(" "); @@ -97,7 +97,7 @@ private void processStartCommand ( if (topicNum < 1 || topicNum > topicList.getSize() + 1) { throw new CustomException("booo no such topic"); } - ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults); + ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults, userAnswers); } catch (NumberFormatException e) { throw new CustomException("invalid " + lowerCaseCommand + " parameter"); @@ -165,11 +165,14 @@ private void processSolutionCommand( } public void handleAnswerInputs(String[] inputAnswers, int index, String answer, Question questionUnit, - Results topicResults){ + Results topicResults, ArrayList correctness){ inputAnswers[index] = answer; String correctAnswer = questionUnit.getSolution(); if (answer.equals(correctAnswer)){ topicResults.increaseCorrectAnswers(); + correctness.add(IS_CORRECT_ANSWER); + } else { + correctness.add(!IS_CORRECT_ANSWER); } } From dfdd32c6641c4e83b9a05a16954b60af17815b6b Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 12:44:00 +0800 Subject: [PATCH 058/334] Add exceptions for Results feature --- src/main/java/seedu/duke/Parser.java | 59 ++++++++++++++++++++-------- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 23ef889f79..b5765a0772 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -13,10 +13,17 @@ public class Parser { private static final int FIRST_PARAMETER = 1; private static final int SECOND_PARAMETER = 2; - private static final String QUESTION_PARAMETER = "questions"; + private static final String DETAILS_PARAMETER = "details"; private static final String COMMAND_SPLITTER = " "; - private static final boolean INCLUDES_QUESTION = true; + private static final boolean INCLUDES_DETAILS = true; + private static final boolean IS_CORRECT_ANSWER = true; + private static final String MESSAGE_NO_RESULTS = "There are no results."; + private static final String MESSAGE_ERROR = "An error has occurred."; + private static final String MESSAGE_INVALID_PARAMETERS = "Invalid parameters."; + private static final int NO_RESULTS = 0; + private static final String MESSAGE_INDEX_OUT_OF_BOUNDS = "Index is out of bounds."; + private static final String MESSAGE_INVALID_INDEX = "Index must be an integer."; boolean hasChosenTopic = false; public void parseCommand( @@ -49,33 +56,53 @@ public void parseCommand( } private void processResultsCommand(String lowerCaseCommand, ResultsList allResults, Ui ui, - QuestionListByTopic questionListByTopic) { + QuestionListByTopic questionListByTopic, AnswerTracker userAnswers) + throws CustomException { + if (allResults.getSizeOfAllResults() == NO_RESULTS) { + throw new CustomException(MESSAGE_NO_RESULTS); + } String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER, TWO_PARAMETERS); + assert commandParts.length <= TWO_PARAMETERS; switch (commandParts.length) { case (NO_PARAMETERS): { - ui.printAllResults(!INCLUDES_QUESTION, allResults, questionListByTopic); + ui.printAllResults(!INCLUDES_DETAILS, allResults, questionListByTopic, userAnswers); break; } case (ONE_PARAMETER): { - if (commandParts[PARAMETER_INDEX].equals(QUESTION_PARAMETER)) { - ui.printAllResults(INCLUDES_QUESTION, allResults, questionListByTopic); + if (commandParts[PARAMETER_INDEX].equals(DETAILS_PARAMETER)) { + ui.printAllResults(INCLUDES_DETAILS, allResults, questionListByTopic, userAnswers); } else { - int index = Integer.parseInt(commandParts[FIRST_PARAMETER]); - String score = allResults.getSpecifiedResult(index - 1).getScore(); - int topicNum = allResults.getTopicNum(index - 1); - ui.printOneResult(!INCLUDES_QUESTION, topicNum, score, questionListByTopic); + try { + int index = Integer.parseInt(commandParts[FIRST_PARAMETER]); + String score = allResults.getSpecifiedResult(index - 1).getScore(); + int topicNum = allResults.getTopicNum(index - 1); + ui.printOneResult(!INCLUDES_DETAILS, topicNum, score, questionListByTopic, userAnswers, index); + } catch (NumberFormatException e) { + throw new CustomException(MESSAGE_INVALID_PARAMETERS); + } catch (IndexOutOfBoundsException e) { + throw new CustomException(MESSAGE_INDEX_OUT_OF_BOUNDS); + } } break; } case (TWO_PARAMETERS): { - int index = Integer.parseInt(commandParts[SECOND_PARAMETER]); - String score = allResults.getSpecifiedResult(index - 1).getScore(); - int topicNum = allResults.getTopicNum(index - 1); - ui.printOneResult(INCLUDES_QUESTION, topicNum, score, questionListByTopic); - break; + if (!commandParts[PARAMETER_INDEX].equals(DETAILS_PARAMETER)) { + throw new CustomException(MESSAGE_INVALID_PARAMETERS); + } + try { + int index = Integer.parseInt(commandParts[SECOND_PARAMETER]); + String score = allResults.getSpecifiedResult(index - 1).getScore(); + int topicNum = allResults.getTopicNum(index - 1); + ui.printOneResult(INCLUDES_DETAILS, topicNum, score, questionListByTopic, userAnswers, index); + break; + } catch (NumberFormatException e) { + throw new CustomException(MESSAGE_INVALID_INDEX); + } catch (IndexOutOfBoundsException e) { + throw new CustomException(MESSAGE_INDEX_OUT_OF_BOUNDS); + } } default: { - break; + throw new CustomException(MESSAGE_ERROR); } } } From aaad82fb783da2a536a9504f94bf2358f6f12fe5 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 12:44:18 +0800 Subject: [PATCH 059/334] Add assertions --- src/main/java/seedu/duke/Results.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/duke/Results.java b/src/main/java/seedu/duke/Results.java index 1c0b10b437..4be1f04302 100644 --- a/src/main/java/seedu/duke/Results.java +++ b/src/main/java/seedu/duke/Results.java @@ -17,6 +17,7 @@ public Results() { public void calculateScore() { int scorePercentage = (int) ((double) numberOfCorrectAnswers / (double) totalNumberOfQuestions * HUNDRED_PERCENT); + assert scorePercentage >= 0; score = numberOfCorrectAnswers + "/" + totalNumberOfQuestions + " (" + scorePercentage + "%)"; } From d9c0a7fef8ad1ad15640322f50402bbea7ba422c Mon Sep 17 00:00:00 2001 From: yuhengr Date: Thu, 21 Mar 2024 13:41:23 +0800 Subject: [PATCH 060/334] Fix undeclared int count bug --- src/main/java/seedu/duke/ResultsList.java | 2 ++ src/test/java/seedu/duke/ProgressManagerTest.java | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index a9394185e0..5113216d7b 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -5,6 +5,8 @@ public class ResultsList { protected ArrayList sessionResults; protected ArrayList topicsChosen; + static final int ZERO_RESULTS = 0; + protected int count = ZERO_RESULTS; public ResultsList() { sessionResults = new ArrayList<>(); diff --git a/src/test/java/seedu/duke/ProgressManagerTest.java b/src/test/java/seedu/duke/ProgressManagerTest.java index 1b5d45fe5f..41a54b3754 100644 --- a/src/test/java/seedu/duke/ProgressManagerTest.java +++ b/src/test/java/seedu/duke/ProgressManagerTest.java @@ -14,7 +14,7 @@ void createResultList() { for(int i = 0; i < NUM_OF_RESULTS; i++) { results[i].increaseNumberOfQuestions(); - sessionResults.addResult(results[i]); + sessionResults.addResults(results[i]); } } From eb7c8bf2894b38574d6f2b3930945c8a6c36f40a Mon Sep 17 00:00:00 2001 From: yuhengr Date: Thu, 21 Mar 2024 14:23:18 +0800 Subject: [PATCH 061/334] Modify name of test --- src/test/java/seedu/duke/ProgressManagerTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/seedu/duke/ProgressManagerTest.java b/src/test/java/seedu/duke/ProgressManagerTest.java index 41a54b3754..12c935d5aa 100644 --- a/src/test/java/seedu/duke/ProgressManagerTest.java +++ b/src/test/java/seedu/duke/ProgressManagerTest.java @@ -20,7 +20,7 @@ void createResultList() { @Test - public void testClearProgress() { + public void clearProgress_threeResults_emptyResultsList() { createResultList(); ProgressManager pm = new ProgressManager(sessionResults); From 72c7a1301e3ba6975879f2d1d04008cc80b70b5c Mon Sep 17 00:00:00 2001 From: yuhengr Date: Thu, 21 Mar 2024 14:26:15 +0800 Subject: [PATCH 062/334] Add assertion --- src/test/java/seedu/duke/ProgressManagerTest.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/java/seedu/duke/ProgressManagerTest.java b/src/test/java/seedu/duke/ProgressManagerTest.java index 12c935d5aa..c1dc63b5a8 100644 --- a/src/test/java/seedu/duke/ProgressManagerTest.java +++ b/src/test/java/seedu/duke/ProgressManagerTest.java @@ -26,5 +26,7 @@ public void clearProgress_threeResults_emptyResultsList() { ProgressManager pm = new ProgressManager(sessionResults); pm.clearProgress(); assertEquals(0, sessionResults.getNumOfResults()); + int numOfResults = sessionResults.getNumOfResults(); + assert numOfResults == 0 : "Number of results should be 0."; } } From 55d678f35e58122b8979d501e65f0aad6b4c1d87 Mon Sep 17 00:00:00 2001 From: yuhengr Date: Thu, 21 Mar 2024 14:35:39 +0800 Subject: [PATCH 063/334] Add loggers --- src/main/java/seedu/duke/ProgressManager.java | 5 +++++ src/test/java/seedu/duke/ProgressManagerTest.java | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/src/main/java/seedu/duke/ProgressManager.java b/src/main/java/seedu/duke/ProgressManager.java index dd1d917839..055bd1263e 100644 --- a/src/main/java/seedu/duke/ProgressManager.java +++ b/src/main/java/seedu/duke/ProgressManager.java @@ -1,15 +1,20 @@ package seedu.duke; +import java.util.logging.*; + public class ProgressManager { private ResultsList sessionResults; + private static Logger logger = Logger.getLogger("ProgressManagerLogger"); + public ProgressManager(ResultsList sessionResults) { this.sessionResults = sessionResults; } public void clearProgress() { + logger.log(Level.INFO, "Clearing session progress."); sessionResults.clearResults(); } } diff --git a/src/test/java/seedu/duke/ProgressManagerTest.java b/src/test/java/seedu/duke/ProgressManagerTest.java index c1dc63b5a8..6555192d2c 100644 --- a/src/test/java/seedu/duke/ProgressManagerTest.java +++ b/src/test/java/seedu/duke/ProgressManagerTest.java @@ -4,11 +4,17 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import java.util.logging.*; + public class ProgressManagerTest { ResultsList sessionResults = new ResultsList(); + private static Logger logger = Logger.getLogger("ProgressManagerTestLogger"); + void createResultList() { + logger.log(Level.INFO, "Creating dummy session results."); + final int NUM_OF_RESULTS = 3; Results[] results = new Results[NUM_OF_RESULTS]; @@ -23,6 +29,8 @@ void createResultList() { public void clearProgress_threeResults_emptyResultsList() { createResultList(); + + logger.log(Level.INFO, "Testing progress manager."); ProgressManager pm = new ProgressManager(sessionResults); pm.clearProgress(); assertEquals(0, sessionResults.getNumOfResults()); From 3a0359337c7d124827ca73206e6d8599cb55b8aa Mon Sep 17 00:00:00 2001 From: yuhengr Date: Thu, 21 Mar 2024 15:24:05 +0800 Subject: [PATCH 064/334] Attempt to fix checkstyle error --- src/main/java/seedu/duke/ProgressManager.java | 3 ++- src/main/java/seedu/duke/ResultsList.java | 2 +- src/test/java/seedu/duke/ProgressManagerTest.java | 5 +++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/duke/ProgressManager.java b/src/main/java/seedu/duke/ProgressManager.java index 055bd1263e..37e5b13524 100644 --- a/src/main/java/seedu/duke/ProgressManager.java +++ b/src/main/java/seedu/duke/ProgressManager.java @@ -1,6 +1,7 @@ package seedu.duke; -import java.util.logging.*; +import java.util.logging.Logger; +import java.util.logging.Level; public class ProgressManager { diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index 5113216d7b..ef15fe6398 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -5,7 +5,7 @@ public class ResultsList { protected ArrayList sessionResults; protected ArrayList topicsChosen; - static final int ZERO_RESULTS = 0; + final static int ZERO_RESULTS = 0; protected int count = ZERO_RESULTS; public ResultsList() { diff --git a/src/test/java/seedu/duke/ProgressManagerTest.java b/src/test/java/seedu/duke/ProgressManagerTest.java index 6555192d2c..8763d1a1fd 100644 --- a/src/test/java/seedu/duke/ProgressManagerTest.java +++ b/src/test/java/seedu/duke/ProgressManagerTest.java @@ -4,12 +4,13 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import java.util.logging.*; +import java.util.logging.Logger; +import java.util.logging.Level; public class ProgressManagerTest { ResultsList sessionResults = new ResultsList(); - private static Logger logger = Logger.getLogger("ProgressManagerTestLogger"); + static private Logger logger = Logger.getLogger("ProgressManagerTestLogger"); void createResultList() { From 340d5d903f00c0d50ef60b124a56235f70648be9 Mon Sep 17 00:00:00 2001 From: yuhengr Date: Thu, 21 Mar 2024 15:27:15 +0800 Subject: [PATCH 065/334] Try to fix checkstyle error again --- src/main/java/seedu/duke/ResultsList.java | 2 +- src/test/java/seedu/duke/ProgressManagerTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index ef15fe6398..f5bfbeae8b 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -5,7 +5,7 @@ public class ResultsList { protected ArrayList sessionResults; protected ArrayList topicsChosen; - final static int ZERO_RESULTS = 0; + final int ZERO_RESULTS = 0; protected int count = ZERO_RESULTS; public ResultsList() { diff --git a/src/test/java/seedu/duke/ProgressManagerTest.java b/src/test/java/seedu/duke/ProgressManagerTest.java index 8763d1a1fd..d1fc7a1b13 100644 --- a/src/test/java/seedu/duke/ProgressManagerTest.java +++ b/src/test/java/seedu/duke/ProgressManagerTest.java @@ -10,7 +10,7 @@ public class ProgressManagerTest { ResultsList sessionResults = new ResultsList(); - static private Logger logger = Logger.getLogger("ProgressManagerTestLogger"); + private Logger logger = Logger.getLogger("ProgressManagerTestLogger"); void createResultList() { From 4c68cd31f091880cacd6e5d2d73a1f11207b8601 Mon Sep 17 00:00:00 2001 From: yuhengr Date: Thu, 21 Mar 2024 15:29:24 +0800 Subject: [PATCH 066/334] Try to fix checkstyle error once again --- src/main/java/seedu/duke/ProgressManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/ProgressManager.java b/src/main/java/seedu/duke/ProgressManager.java index 37e5b13524..bab06898d1 100644 --- a/src/main/java/seedu/duke/ProgressManager.java +++ b/src/main/java/seedu/duke/ProgressManager.java @@ -8,7 +8,7 @@ public class ProgressManager { private ResultsList sessionResults; - private static Logger logger = Logger.getLogger("ProgressManagerLogger"); + private Logger logger = Logger.getLogger("ProgressManagerLogger"); public ProgressManager(ResultsList sessionResults) { this.sessionResults = sessionResults; From acba039db0875e2368f7c1156bb0523805d7bec3 Mon Sep 17 00:00:00 2001 From: yuhengr Date: Thu, 21 Mar 2024 15:36:41 +0800 Subject: [PATCH 067/334] Fix testing error --- src/main/java/seedu/duke/ProgressManager.java | 3 ++- src/test/java/seedu/duke/ProgressManagerTest.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/ProgressManager.java b/src/main/java/seedu/duke/ProgressManager.java index bab06898d1..000a1f17f9 100644 --- a/src/main/java/seedu/duke/ProgressManager.java +++ b/src/main/java/seedu/duke/ProgressManager.java @@ -14,8 +14,9 @@ public ProgressManager(ResultsList sessionResults) { this.sessionResults = sessionResults; } - public void clearProgress() { + public ResultsList clearProgress() { logger.log(Level.INFO, "Clearing session progress."); sessionResults.clearResults(); + return sessionResults; } } diff --git a/src/test/java/seedu/duke/ProgressManagerTest.java b/src/test/java/seedu/duke/ProgressManagerTest.java index d1fc7a1b13..f572f0f740 100644 --- a/src/test/java/seedu/duke/ProgressManagerTest.java +++ b/src/test/java/seedu/duke/ProgressManagerTest.java @@ -33,7 +33,7 @@ public void clearProgress_threeResults_emptyResultsList() { logger.log(Level.INFO, "Testing progress manager."); ProgressManager pm = new ProgressManager(sessionResults); - pm.clearProgress(); + sessionResults = pm.clearProgress(); assertEquals(0, sessionResults.getNumOfResults()); int numOfResults = sessionResults.getNumOfResults(); assert numOfResults == 0 : "Number of results should be 0."; From 2f067396ac3c317f1326503967fe3bb7290de26a Mon Sep 17 00:00:00 2001 From: yuhengr Date: Thu, 21 Mar 2024 15:49:32 +0800 Subject: [PATCH 068/334] Try to fix ProgressManagerTest --- .../java/seedu/duke/ProgressManagerTest.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/src/test/java/seedu/duke/ProgressManagerTest.java b/src/test/java/seedu/duke/ProgressManagerTest.java index f572f0f740..31c72befd2 100644 --- a/src/test/java/seedu/duke/ProgressManagerTest.java +++ b/src/test/java/seedu/duke/ProgressManagerTest.java @@ -16,13 +16,18 @@ void createResultList() { logger.log(Level.INFO, "Creating dummy session results."); - final int NUM_OF_RESULTS = 3; - Results[] results = new Results[NUM_OF_RESULTS]; - - for(int i = 0; i < NUM_OF_RESULTS; i++) { - results[i].increaseNumberOfQuestions(); - sessionResults.addResults(results[i]); - } + ResultsList sessionResults = new ResultsList(); + Results results = new Results(); + Question questionOne = new Question("Question 1", "Solution 1", "Explanation 1"); + Question questionTwo = new Question("Question 2", "Solution 2", "Explanation 2"); + QuestionsList questions = new QuestionsList(); + + questions.addQuestion(questionOne); + results.increaseNumberOfQuestions(); + questions.addQuestion(questionTwo); + results.increaseNumberOfQuestions(); + + sessionResults.addResults(results); } @@ -34,8 +39,8 @@ public void clearProgress_threeResults_emptyResultsList() { logger.log(Level.INFO, "Testing progress manager."); ProgressManager pm = new ProgressManager(sessionResults); sessionResults = pm.clearProgress(); - assertEquals(0, sessionResults.getNumOfResults()); int numOfResults = sessionResults.getNumOfResults(); + assertEquals(0, sessionResults.getNumOfResults()); assert numOfResults == 0 : "Number of results should be 0."; } } From 7ccedb04318fd5d35ce2170f1c733f7a8faeb2c7 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Thu, 21 Mar 2024 21:08:42 +0800 Subject: [PATCH 069/334] build(build.gradle): enable assertions --- build.gradle | 1 + src/main/java/seedu/duke/Parser.java | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index 8818eecfb3..881204c839 100644 --- a/build.gradle +++ b/build.gradle @@ -44,4 +44,5 @@ checkstyle { run{ standardInput = System.in + enableAssertions = true } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index b5765a0772..04ae90bcc2 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -157,7 +157,7 @@ private void processSolutionCommand( int questionNum = Integer.parseInt(commandParameterQn); // checks validity of parameter - if ((topicNum < 1 || topicNum > topicList.getSize())) { + if (topicNum < 1 || topicNum > topicList.getSize()) { throw new CustomException("booo no such topic"); } From 1b0fb5439f909311fe2ee301d5c10a2bb4a28177 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Thu, 21 Mar 2024 21:28:53 +0800 Subject: [PATCH 070/334] style: add assertions --- src/main/java/seedu/duke/Parser.java | 8 ++++---- src/main/java/seedu/duke/QuestionsList.java | 2 ++ 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 04ae90bcc2..be83c65d53 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -122,7 +122,7 @@ private void processStartCommand ( int topicNum = Integer.parseInt(commandParameter); // checks validity of parameter if (topicNum < 1 || topicNum > topicList.getSize() + 1) { - throw new CustomException("booo no such topic"); + throw new CustomException("No such topic"); } ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults, userAnswers); @@ -158,12 +158,12 @@ private void processSolutionCommand( // checks validity of parameter if (topicNum < 1 || topicNum > topicList.getSize()) { - throw new CustomException("booo no such topic"); + throw new CustomException("No such topic"); } QuestionsList qnList = questionListByTopic.getQuestionSet(topicNum - 1); if (questionNum < 1 || questionNum > qnList.getSize()) { - throw new CustomException(("booo no such question")); + throw new CustomException(("No such question")); } if (isSolutionCommand) { @@ -171,7 +171,7 @@ private void processSolutionCommand( ui.printOneSolution(questionNum, solution); return; } // only runs if explanation - + assert typeOfCommand.contentEquals("explain") : "typeOfCommand should be explain"; String explanation = qnList.getOneExplanation(questionNum); ui.printOneSolution(questionNum, explanation); diff --git a/src/main/java/seedu/duke/QuestionsList.java b/src/main/java/seedu/duke/QuestionsList.java index 1c4926061c..a1f994b380 100644 --- a/src/main/java/seedu/duke/QuestionsList.java +++ b/src/main/java/seedu/duke/QuestionsList.java @@ -26,6 +26,7 @@ public int getSize() { // user enters "explain 1" to get explanation for question1 public String getOneExplanation(int questionNum) { + assert questionNum > 0 : "questionNum should be more than 0"; int questionIndex = questionNum - 1; // -1 coz zero index Question question = chosenQuestionsList.get(questionIndex); return question.getExplanation(); @@ -33,6 +34,7 @@ public String getOneExplanation(int questionNum) { // user enters "solution 1" to get solution for question1 public String getOneSolution(int questionNum) { + assert questionNum > 0 : "questionNum should be more than 0"; int questionIndex = questionNum - 1; // -1 coz zero index Question question = chosenQuestionsList.get(questionIndex); return question.getSolution(); From b7c43a78cd79da4e902e345f190ff3a19bd7bbbd Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 21:47:22 +0800 Subject: [PATCH 071/334] Update Helper list of commands --- src/main/java/seedu/duke/Helper.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/duke/Helper.java b/src/main/java/seedu/duke/Helper.java index 1bc78235ac..bb7f0ac96e 100644 --- a/src/main/java/seedu/duke/Helper.java +++ b/src/main/java/seedu/duke/Helper.java @@ -6,10 +6,15 @@ public class Helper { private static final ArrayList commandList = new ArrayList(); public Helper() { - commandList.add(new Command("bye", "Terminate the programme", "bye")); - commandList.add(new Command("help", "View available commands or check a one", "help, help [command]")); + commandList.add(new Command("topic", "Start the round of questions for the chosen " + + "topic","topic [TOPIC_INDEX]")); + commandList.add(new Command("help", "View available commands or check one", "help, help [COMMAND]")); commandList.add(new Command("solution", "View solution to the question", "solution [QUESTION_INDEX]")); - commandList.add(new Command("explain", "View explaination for the solution", "explain [QUESTION_INDEX]")); + commandList.add(new Command("explain", "View explanation for the solution", + "explain [QUESTION_INDEX]")); + commandList.add(new Command("results", "View results for each topic played", + "results [details] [RESULTS_INDEX]")); + commandList.add(new Command("bye", "Terminate the program", "bye")); } public static String[][] listAllCommands() { From 914cd4ba27e9762306ed5413ff91efecb18a35a1 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 21:47:37 +0800 Subject: [PATCH 072/334] Remove duplicate code --- src/main/java/seedu/duke/ResultsList.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index f5bfbeae8b..21456c8bdf 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -5,8 +5,6 @@ public class ResultsList { protected ArrayList sessionResults; protected ArrayList topicsChosen; - final int ZERO_RESULTS = 0; - protected int count = ZERO_RESULTS; public ResultsList() { sessionResults = new ArrayList<>(); @@ -35,10 +33,5 @@ public int getSizeOfAllResults() { public void clearResults() { sessionResults.clear(); - count = ZERO_RESULTS; - } - - public int getNumOfResults() { - return count; } } From d0fbe43844618b8a0df359a7417acc9e04ac55e5 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 21:47:56 +0800 Subject: [PATCH 073/334] Remove duplicate code --- src/test/java/seedu/duke/ProgressManagerTest.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/seedu/duke/ProgressManagerTest.java b/src/test/java/seedu/duke/ProgressManagerTest.java index 31c72befd2..d6d9ac6a94 100644 --- a/src/test/java/seedu/duke/ProgressManagerTest.java +++ b/src/test/java/seedu/duke/ProgressManagerTest.java @@ -39,8 +39,8 @@ public void clearProgress_threeResults_emptyResultsList() { logger.log(Level.INFO, "Testing progress manager."); ProgressManager pm = new ProgressManager(sessionResults); sessionResults = pm.clearProgress(); - int numOfResults = sessionResults.getNumOfResults(); - assertEquals(0, sessionResults.getNumOfResults()); + int numOfResults = sessionResults.getSizeOfAllResults(); + assertEquals(0, sessionResults.getSizeOfAllResults()); assert numOfResults == 0 : "Number of results should be 0."; } } From 5d3a3d4ad5e3b774648fa25df2e7323c1cb43cd5 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Thu, 21 Mar 2024 22:02:39 +0800 Subject: [PATCH 074/334] style(QuestionsListTest): add logging --- src/main/java/seedu/duke/ProgressManager.java | 1 - .../java/seedu/duke/QuestionsListTest.java | 18 +++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/ProgressManager.java b/src/main/java/seedu/duke/ProgressManager.java index 000a1f17f9..8aa6cc7e17 100644 --- a/src/main/java/seedu/duke/ProgressManager.java +++ b/src/main/java/seedu/duke/ProgressManager.java @@ -3,7 +3,6 @@ import java.util.logging.Logger; import java.util.logging.Level; - public class ProgressManager { private ResultsList sessionResults; diff --git a/src/test/java/seedu/duke/QuestionsListTest.java b/src/test/java/seedu/duke/QuestionsListTest.java index 2e29e82251..46b417708b 100644 --- a/src/test/java/seedu/duke/QuestionsListTest.java +++ b/src/test/java/seedu/duke/QuestionsListTest.java @@ -3,10 +3,14 @@ import org.junit.jupiter.api.Test; import seedu.duke.exceptions.CustomException; +import java.util.logging.Level; +import java.util.logging.Logger; + import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertThrows; class QuestionsListTest { + private static final Logger LOGGER = Logger.getLogger("testLogger"); // for logging purposes QuestionsList questionsList; Question question1; Question question2; @@ -25,6 +29,9 @@ void createTwoQuestions() { @Test void getSize_addTwoQuestions_twoQuestions() { + LOGGER.log(Level.INFO, "startLog1"); + LOGGER.setLevel(Level.OFF); // disableLogs + createQuestionList(); createTwoQuestions(); questionsList.addQuestion(question1); @@ -35,6 +42,9 @@ void getSize_addTwoQuestions_twoQuestions() { @Test void getAllSolutions_twoQuestions_twoExplanations() throws CustomException { + LOGGER.log(Level.INFO, "This log will be ignored"); + LOGGER.setLevel(Level.ALL); // enableLogs + createQuestionList(); createTwoQuestions(); questionsList.addQuestion(question1); @@ -47,8 +57,14 @@ void getAllSolutions_twoQuestions_twoExplanations() throws CustomException { + "Solution for question 2:" + System.lineSeparator() + "solution2" + System.lineSeparator() + System.lineSeparator(); - + if (questionsList.getSize() != 0) { + LOGGER.log(Level.WARNING, "warningLog1"); + } + LOGGER.setLevel(Level.WARNING); + LOGGER.log(Level.INFO, "this log will be ignored"); + LOGGER.log(Level.WARNING, "but this log will not coz priority=WARNING"); assertEquals(expectedOutput, questionsList.getAllSolutions()); + LOGGER.log(Level.WARNING, "this log will be printed"); } @Test From 34d9a6dfa1b2456fc8994c48d83bd0676c25aaf8 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Thu, 21 Mar 2024 22:18:41 +0800 Subject: [PATCH 075/334] style(resultslist): fix checkstyle error for static final zero_results --- src/main/java/seedu/duke/ResultsList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/ResultsList.java b/src/main/java/seedu/duke/ResultsList.java index f5bfbeae8b..fc686eae8b 100644 --- a/src/main/java/seedu/duke/ResultsList.java +++ b/src/main/java/seedu/duke/ResultsList.java @@ -3,9 +3,9 @@ import java.util.ArrayList; public class ResultsList { + private static final int ZERO_RESULTS = 0; protected ArrayList sessionResults; protected ArrayList topicsChosen; - final int ZERO_RESULTS = 0; protected int count = ZERO_RESULTS; public ResultsList() { From 518676316bb07c0b42f3bbf7dfc846c3fbee83d4 Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 22:28:01 +0800 Subject: [PATCH 076/334] Add logging --- src/main/java/seedu/duke/Results.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/seedu/duke/Results.java b/src/main/java/seedu/duke/Results.java index 4be1f04302..c9551cc06e 100644 --- a/src/main/java/seedu/duke/Results.java +++ b/src/main/java/seedu/duke/Results.java @@ -1,9 +1,14 @@ package seedu.duke; +import java.util.logging.Logger; +import java.util.logging.Level; + public class Results { private static final int HUNDRED_PERCENT = 100; private static final int ZERO_QUESTIONS = 0; + private static Logger logger = Logger.getLogger("ResultsLogger"); + protected int numberOfCorrectAnswers; protected int totalNumberOfQuestions; protected String score; @@ -15,10 +20,12 @@ public Results() { } public void calculateScore() { + logger.log(Level.INFO, "going to start calculating score"); int scorePercentage = (int) ((double) numberOfCorrectAnswers / (double) totalNumberOfQuestions * HUNDRED_PERCENT); assert scorePercentage >= 0; score = numberOfCorrectAnswers + "/" + totalNumberOfQuestions + " (" + scorePercentage + "%)"; + logger.log(Level.INFO,"end of calculation"); } public String getScore() { From 75d7b0a6b59dc8a53d783f555163143cd503225c Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 21 Mar 2024 23:00:01 +0800 Subject: [PATCH 077/334] FIx logging --- src/main/java/seedu/duke/Results.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/seedu/duke/Results.java b/src/main/java/seedu/duke/Results.java index c9551cc06e..76c6f879a4 100644 --- a/src/main/java/seedu/duke/Results.java +++ b/src/main/java/seedu/duke/Results.java @@ -1,5 +1,6 @@ package seedu.duke; +import java.util.logging.LogManager; import java.util.logging.Logger; import java.util.logging.Level; @@ -20,6 +21,8 @@ public Results() { } public void calculateScore() { + LogManager.getLogManager().reset(); + logger.setLevel(Level.ALL); logger.log(Level.INFO, "going to start calculating score"); int scorePercentage = (int) ((double) numberOfCorrectAnswers / (double) totalNumberOfQuestions * HUNDRED_PERCENT); From 3b2d597b4ea7a86609dbd63b324659ca6fc83fad Mon Sep 17 00:00:00 2001 From: ngxzs Date: Thu, 21 Mar 2024 23:47:32 +0800 Subject: [PATCH 078/334] style(parser): add hasfinishedtopic flag and appropriate ui display --- src/main/java/seedu/duke/Helper.java | 2 +- src/main/java/seedu/duke/Parser.java | 2 ++ src/main/java/seedu/duke/Ui.java | 2 +- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/Helper.java b/src/main/java/seedu/duke/Helper.java index bb7f0ac96e..a8ab289359 100644 --- a/src/main/java/seedu/duke/Helper.java +++ b/src/main/java/seedu/duke/Helper.java @@ -17,7 +17,7 @@ public Helper() { commandList.add(new Command("bye", "Terminate the program", "bye")); } - public static String[][] listAllCommands() { + public String[][] listAllCommands() { int commandNum = commandList.size(); String[][] tableData = new String[commandNum][]; for (int i = 0; i < commandNum; i++) { diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index be83c65d53..485202ee14 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -125,6 +125,8 @@ private void processStartCommand ( throw new CustomException("No such topic"); } ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults, userAnswers); + System.out.println("You have finished the topic! What will be your next topic?"); + ui.printTopicList(topicList, ui); } catch (NumberFormatException e) { throw new CustomException("invalid " + lowerCaseCommand + " parameter"); diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 2a8ba35f8e..27fec5bca3 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -43,7 +43,7 @@ public void readCommands( } private void askForInput() { - System.out.println("Input a command player! // TODO: show possible commands"); // TODO + System.out.println("Input a command player! "); // TODO: show possible commands } private void askForAnswerInput(){ From b96683a6f5401795c7cfa71defee0b602936bbf3 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Fri, 22 Mar 2024 00:02:28 +0800 Subject: [PATCH 079/334] ci(ui): modify expected.txt to pass github checks --- src/main/java/seedu/duke/Ui.java | 2 +- text-ui-test/EXPECTED.TXT | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 27fec5bca3..3ef327a8e0 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -43,7 +43,7 @@ public void readCommands( } private void askForInput() { - System.out.println("Input a command player! "); // TODO: show possible commands + System.out.println("Input a command player!"); // TODO: show possible commands } private void askForAnswerInput(){ diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 3e22acc5bc..dd3c113b6e 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -15,8 +15,8 @@ Here are the topics in CS2113: 2. topic2 Please choose a topic to play: ************************************************ -Input a command player! // TODO: show possible commands +Input a command player! -1 HP coz invalid commandTODO: show possible commands -Input a command player! // TODO: show possible commands +Input a command player! bye bye, get more sleep zzz ************************************************ From 2eef84b35e972ee6fdee1d1235d9fb1880d59430 Mon Sep 17 00:00:00 2001 From: Songyue Wang Date: Fri, 22 Mar 2024 01:08:43 +0800 Subject: [PATCH 080/334] UG Readme --- README.md | 217 +++++++++++++++++++++------ img/ug_usage_help.png | Bin 0 -> 93729 bytes src/main/java/seedu/duke/Helper.java | 6 +- 3 files changed, 175 insertions(+), 48 deletions(-) create mode 100644 img/ug_usage_help.png diff --git a/README.md b/README.md index 02cc72b324..d0ae45e8ad 100644 --- a/README.md +++ b/README.md @@ -1,64 +1,191 @@ # Player2113 -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. +A CLI tool to help COMP2113 student revise conceptual questions in a gamification environment. -## Setting up in Intellij +## Getting Started -Prerequisites: JDK 11 (use the exact version), update Intellij to the most recent version. +Prerequisites: JDK 11, Player2113 release `JDK` file -1. **Ensure Intellij JDK 11 is defined as an SDK**, as described [here](https://www.jetbrains.com/help/idea/sdk.html#set-up-jdk) -- this step is not needed if you have used JDK 11 in a previous Intellij project. -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: - ``` - > Task :compileJava - > Task :processResources NO-SOURCE - > Task :classes - - > Task :Duke.main() - Hello from - ____ _ - | _ \ _ _| | _____ - | | | | | | | |/ / _ \ - | |_| | |_| | < __/ - |____/ \__,_|_|\_\___| - - What is your name? - ``` - Type some word and press enter to let the execution proceed to the end. +Start the programme with the following command: -## Build automation using Gradle +``` +java --jar Player2113.jar +``` -* This project uses Gradle for build automation and dependency management. It includes a basic build script as well (i.e. the `build.gradle` file). -* If you are new to Gradle, refer to the [Gradle Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/gradle.html). +You will see the welcome screen upon successful start-up: -## Testing +``` +Hello from +______ _ _____ __ __ _____ +| ___ \ | / __ \/ | / | |____ | +| |_/ / | __ _ _ _ ___ _ __`' / /'`| | `| | / / +| __/| |/ _` | | | |/ _ \ '__| / / | | | | \ \ +| | | | (_| | |_| | __/ | ./ /____| |__| |_.___/ / +\_| |_|\__,_|\__, |\___|_| \_____/\___/\___/\____/ + __/ | + |___/ +What is your name? +``` -### I/O redirection tests +## Features -* To run _I/O redirection_ tests (aka _Text UI tests_), navigate to the `text-ui-test` and run the `runtest(.bat/.sh)` script. +### Attempt Question Sets -### JUnit tests +You can select a topic from the menu and attempt the questions related to the topic you wish to revise. There are multiple question banks pre-configured in Player2113. -* A skeleton JUnit test (`src/test/java/seedu/duke/DukeTest.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). +### Result Statistics -## Checkstyle +You may check your answer accuracy after attempting a question set. The result is separated from practicing session for concentration consideration. -* A sample CheckStyle rule configuration is provided in this project. -* If you are new to Checkstyle, refer to the [Checkstyle Tutorial at se-education.org/guides](https://se-education.org/guides/tutorials/checkstyle.html). +### Solution -## CI using GitHub Actions +You may check the correct solution to a specific question in a certain question set. -The project uses [GitHub actions](https://github.com/features/actions) for CI. When you push a commit to this repo or PR against it, GitHub actions will run automatically to build and verify the code as updated by the commit/PR. +### Explaination -## Documentation +Detailed explaination is hidden unless invoked by the user for progressive learning and maximizing self-relection. -`/docs` folder contains a skeleton version of the project documentation. +### Help -Steps for publishing documentation to the public: -1. If you are using this project template for an individual project, go your fork on GitHub.
- If you are using this project template for a team project, go to the team fork on GitHub. -1. Click on the `settings` tab. -1. Scroll down to the `GitHub Pages` section. -1. Set the `source` as `master branch /docs folder`. -1. Optionally, use the `choose a theme` button to choose a theme for your documentation. +A in-app user guide is available for your reference in usage. + +## Usage + +> [!IMPORTANT] +> The current release of Player2113 is a MVP preview version with various proposed functions unimplemented. Please strictly follow this user's guide. + +### `topic` - Choose a topic to revise + +Example of usage: `topic [TOPIC_INDEX]` + +``` +topic 1 +``` + +The practice session for `topic 1` will be started: + +``` +topic 1 +Selected topic: topic1 +Here are the questions: +question1 +Enter your answer: +``` + +### `results` - View the accuracy for an attempt + +Example of usage: `results [TOPIC_INDEX]`. + +``` +results 1 +``` + +Sample output: + +``` +Your results for Topic 1: +0/2 (0%) +``` + +### `re` - Add a deadline + +Example of usage: `event [DEADLINE_NAME] /by [DUE_TIME]`. + +``` +deadline submit CS2113 iP /by 2024-03-08 23:59 +``` + +An acknowledgement message will be displayed after successful execution: + +``` +____________________________________________________________ + Got it. I've added this task: + [D][ ] submit CS2113 iP (by: Mar 8 2024 23:59) + Now you have 5 tasks in the list. +____________________________________________________________ +``` + +### `list` - List all tasks + +Example of usage: `list`. + +Sample output: + +``` +____________________________________________________________ + Here are all the entries in your task list: + 1. [D][ ] assignment 1 (by: Apr 23 2024) + 2. [D][ ] assignment 2 (by: May 21 2024 18:00) + 3. [T][ ] return book + 4. [D][ ] finish book reading report (by: Mar 9 2024) +____________________________________________________________ +``` + +### `find` - Search with keyword + +Example of usage: `find [KEYWORD]`. + +``` +find assignment +``` + +A list of matching entries will be displayed: + +``` +____________________________________________________________ + Here are the matching tasks in your list: + 1. [D][ ] assignment 1 (by: Apr 23 2024) + 2. [D][ ] assignment 2 (by: May 21 2024 18:00) +____________________________________________________________ +``` + +### `solutions` - View solution to a question + +Example of usage: `solutions [TOPIC_INDEX] [QUESTION_INDEX]`. + +``` +solutions 1 1 +``` + +Sample output: + +``` +The solution for question 1: +solution1 +``` + +### `explain` - View reasonings for a solution to a question + +Example of usage: `explain [TOPIC_INDEX] [QUESTION_INDEX]`. + +``` +explain 1 1 +``` + +Sample output: + +``` +The solution for question 1: +explanation1 +``` + +### `help` - View built-in user's guide + +Example of usage: `help` + +Sample output: + +![Help Sample Output](./img/ug_usage_help.png) + +### `bye` - Exit programme + +Example of usage: `bye`. + +A goodbye message will be displayed: + +``` +bye bye, get more sleep zzz +************************************************ +``` + +## Troubleshooting diff --git a/img/ug_usage_help.png b/img/ug_usage_help.png new file mode 100644 index 0000000000000000000000000000000000000000..3e2e4e82fbd51e50560a95a6aab55feb5b4f6bd2 GIT binary patch literal 93729 zcmeFZXIN9+x;Ba;Vnb{o9TgD)1*J#|cjZwZ}B@evTz-<&=Yxwh|3ZMa=mF8#-$J ztou_lPa2xri^s1MZ*1u}XlRb|)t@LC`B|+_(g$9%JM7xp$OD{weeGoS?Y9Fmch8)= zwQN=~iG#j)gqmvgA-)3ND$F2!1N$b(pr)8koKRZQ;M-v{e|+Qh&OT~Y=kXPZn;$1X zI?Hb)3Zh(nGSibC=93qa_t)?&YuLi1lhi)^U4n6E+z*dC^>+!*ym8~y-xca-E9%mv zf4|_D!#J^A=wH5!_O3ny;=dmS1UeCglo3d)LS{;eLIdGmjp z|L1u8KLVq?`ZNpxu=JAo=G?J@#kHe-3I3MipMX z{hu9f)kY$JK`gv-M>7*`$zyA|gqv#7KIM4o2N7!;| z*xy8Mcp}@4yV3H<(hx85G1KAqf|+t}%xv^Q$t?xcca-QhKI%Z0=RX`)=Ei46yDYNq z`;T72&$6A|H&%gWd^*0EdP?;_9*WN`^c?Ejw#PmE=LAv@pz~)`&!`W)4{CZwd69Nq z;Ed*K=}1C0d?!OYvijk|uTo6_q}V~;Y+068@9KY?K}nJtJ%^9tQ|%ONpiJxFx2*n)RGn*Ip)VC*lpKT^L=y!!Am&wnc6_tKnHi^dl# zz^nTJLU$x;xdo)Fw?czpF!@`c7rhC-^y@*AQ{v*1uTI#=+-esdV?AT(*G0r-b#7S&QY*=~%+>fRS&jKA{=+&%bFVUsD0|oRRqT%Z2;W zQ~!TVVKCw^m4+M%{KnK!i1~XZxbgf^RnRW6T(Qlh^>f~IA=jMx3S$=g6%=x|bYn1Y1!8K0 zuuFmGT3)i$n{RLVQT7W!JB2H5gFM2zqw`l(|EWo>|I&KUqUtL%-ESBqfYZ9{M!jBt z3zFbFZ>b~co>b8EAVi*qX0!eh9leY?Q%SIy&EK8Tjv9nRA~5T2yDa!7R|Wabcq?K* zflYxQ6HnwTV9lCO4|f{be7%h2H}iNnc<%f?6X?3D%XpoJro&Oz4^aSrVU-V3QM^yD znpH}JhkjQd96k!X%vq2%^muO08Pkc56muA=O{oCK$aU7>-*@-6+BCS#pqK3^ax39T z$JNA}(r&#fY*>DiZmZ&@BY$OXN(!&2lvM~+L3M#+T)pBoxypM?jIx2_cKYGU#}i(Q zhjm{7=5z5yjSN67(Kq>(9_nYG6FDD`l(evrEFH-)ixu-Ho?bH~jHATp7sD{FL%}x! z&g{{FU3zh1qD|>xAGpeX_1ao<}FD)c6TqF_*;CkKHxcE&}7oEjb ztO2}i6W<|k=h8p$hCg$uatTzeKzJbs!4(6Y7!{C2BpZ2ip<7-9DdBpqi=Bo>ty`=S z)Qk6B-g9hhE`PQ$xl?y%4t<#Ba+(qIGbl>mmz;*&;G=_a=hqh^g@=xpWtj zUUiz!6-AyYs4S)cea#J(+RQ=JVh(589YdBDzD#J=4yjVRV`a=~dq#m0Zo8Kq6 zu(aT$u$+i~Bm(+QOEXX>R(+`dTno?4_-IKwas!n9c09a(Nai}EI2m-#(kaO1G_TX5 zvF}Pvq^=&u=RNQ;EBs>?4c)0z{I~CERGeLln{ulQBRFNJ_dwAJvI`;T2Ry^#q#A`4 zERJBPVIZgy9xfpDK<~BE&2y2?*>8V)5gtL`k|b~i9gz|s{{Nx7=NE;iyrZgjo8j;2?Fhw`1)n*K-_dO0_V&Q<#t6Ped1CkQ7E%H_) zB+1zqQ%;63U76Cle^sWWCwN*K4$2z6Z(3rB zw(`;)%BuXJZxBq`)#^JEQtQI`*7k3V>s095m}HDfT)1fbMC%RKTh645;8t9AegU*{ zxV-IoUYEVBV%IA7>QI@g^~)qfW}67$r@WDtcCj1K$a%PHb~axg|B&m!npMsQ^jYyi z?#QK`-B|{j;D+}A-0%lOvL0Es*)S5B0T&PVR8}Yt2}>ITY!Uri9CM-jui!PtzWp)l zC7*a2?_v)F)-|*#Ht&fXJ65!v~ZXbtY{*iz!urys_hBOBGusJ0%~ar`v~&1kO- z|1Z`c`@q}|GjW8iij|W><6eO*4UJ<_T^Q9|>0E)B$UM09B)y*l)`*ZZZpQMNQZ#qP zU$uh~Hm6J>x5?)IZ?L|sc{a+@z@zPY^Hjs-K&+U74$c5ACBh6)K-%1j4 zbek^p$z7~B!;v57xV!}((Bb&A+$eN>r4IC|C8I(^1?|i(T9vM9x$7|LwO*kCx>{&I zO_XlLh~L64+xjfRq3vPCYL)5c6)$7AOV(^p(y+xI+qB(D<|2K}Y} ztbM<)R~#Q>bE?FjvEL0X$M}c66lm4YV}E+Sf` z_F2BwGNJU*ofI+r zoqc1dgEGssx@?aGupC4LR>H|KnG_F?P(0Tmi)=XaQ@ zrS`4l{B0T>Q~nEuG!KvNtF8(JFura=vd zW8B88_i}6Tm1FHmyG`4yAe{Trwph^cHA=t?eM&XdZT|tNASX_G=87fc$0gp=*p)^# z1-Ss&)L!4@VoA~VC0sJLB{!K!AvGLswK=;83 uzWm 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%0DRhBH} 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 Date: Fri, 22 Mar 2024 01:20:41 +0800 Subject: [PATCH 081/334] UG code refactored --- src/main/java/seedu/duke/Helper.java | 40 +++++++++++++++++++++------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/duke/Helper.java b/src/main/java/seedu/duke/Helper.java index 253ebdc8c7..d95908008a 100644 --- a/src/main/java/seedu/duke/Helper.java +++ b/src/main/java/seedu/duke/Helper.java @@ -6,15 +6,37 @@ public class Helper { private static final ArrayList commandList = new ArrayList(); public Helper() { - commandList.add(new Command("topic", "Start the round of questions for the chosen " + - "topic","topic [TOPIC_INDEX]")); - commandList.add(new Command("help", "View available commands or check one", "help, help [COMMAND]")); - commandList.add(new Command("solution", "View solution to the question", "solution [TOPIC_INDEX] [QUESTION_INDEX]")); - commandList.add(new Command("explain", "View explanation for the solution", - "explain [TOPIC_INDEX] [QUESTION_INDEX]")); - commandList.add(new Command("results", "View results for each topic played", - "results [RESULTS_INDEX]")); - commandList.add(new Command("bye", "Terminate the program", "bye")); + commandList.add( + new Command( + "topic", "Start the round of questions for the chosen " + + "topic","topic [TOPIC_INDEX]" + ) + ); + commandList.add( + new Command( + "help", "View available commands or check one", "help, help [COMMAND]" + ) + ); + commandList.add( + new Command( + "solution", "View solution to the question", "solution [TOPIC_INDEX] [QUESTION_INDEX]" + ) + ); + commandList.add( + new Command( + "explain", "View explanation for the solution", "explain [TOPIC_INDEX] [QUESTION_INDEX]" + ) + ); + commandList.add( + new Command( + "results", "View results for each topic played", "results [RESULTS_INDEX]" + ) + ); + commandList.add( + new Command( + "bye", "Terminate the program", "bye" + ) + ); } public String[][] listAllCommands() { From d6055a3d90ab4623066a8f5df7607e92614a79e8 Mon Sep 17 00:00:00 2001 From: Songyue Wang Date: Fri, 22 Mar 2024 01:40:56 +0800 Subject: [PATCH 082/334] list topic functions --- README.md | 51 ++++-------------------- src/main/java/seedu/duke/Helper.java | 5 +++ src/main/java/seedu/duke/Parser.java | 8 ++++ src/main/java/seedu/duke/Player2113.java | 4 +- src/main/java/seedu/duke/Topic.java | 5 ++- src/main/java/seedu/duke/TopicList.java | 14 +++++++ 6 files changed, 40 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index d0ae45e8ad..6524082e7c 100644 --- a/README.md +++ b/README.md @@ -87,56 +87,19 @@ Your results for Topic 1: 0/2 (0%) ``` -### `re` - Add a deadline - -Example of usage: `event [DEADLINE_NAME] /by [DUE_TIME]`. - -``` -deadline submit CS2113 iP /by 2024-03-08 23:59 -``` - -An acknowledgement message will be displayed after successful execution: - -``` -____________________________________________________________ - Got it. I've added this task: - [D][ ] submit CS2113 iP (by: Mar 8 2024 23:59) - Now you have 5 tasks in the list. -____________________________________________________________ -``` - -### `list` - List all tasks +### `list` - List all available topics and their summaries Example of usage: `list`. Sample output: ``` -____________________________________________________________ - Here are all the entries in your task list: - 1. [D][ ] assignment 1 (by: Apr 23 2024) - 2. [D][ ] assignment 2 (by: May 21 2024 18:00) - 3. [T][ ] return book - 4. [D][ ] finish book reading report (by: Mar 9 2024) -____________________________________________________________ -``` - -### `find` - Search with keyword - -Example of usage: `find [KEYWORD]`. - -``` -find assignment -``` - -A list of matching entries will be displayed: - -``` -____________________________________________________________ - Here are the matching tasks in your list: - 1. [D][ ] assignment 1 (by: Apr 23 2024) - 2. [D][ ] assignment 2 (by: May 21 2024 18:00) -____________________________________________________________ ++-------+--------+-------------------------------------------------+-----------+ +| index | topic | summary | attempted | ++-------+--------+-------------------------------------------------+-----------+ +| 1 | topic1 | Covers topic 1 notions mentioned in lecture 1-2 | false | +| 2 | topic2 | Covers topic 2 notions mentioned in lecture 3-4 | false | ++-------+--------+-------------------------------------------------+-----------+ ``` ### `solutions` - View solution to a question diff --git a/src/main/java/seedu/duke/Helper.java b/src/main/java/seedu/duke/Helper.java index d95908008a..a9761fab27 100644 --- a/src/main/java/seedu/duke/Helper.java +++ b/src/main/java/seedu/duke/Helper.java @@ -37,6 +37,11 @@ public Helper() { "bye", "Terminate the program", "bye" ) ); + commandList.add( + new Command( + "list", "list available topics and their summaries", "list" + ) + ); } public String[][] listAllCommands() { diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 485202ee14..3ffaea9365 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -48,6 +48,8 @@ public void parseCommand( processResultsCommand(lowerCaseCommand, allResults, ui, questionListByTopic, userAnswers); } else if (lowerCaseCommand.startsWith("help")) { processHelpCommand(lowerCaseCommand, ui, helper); + } else if (lowerCaseCommand.startsWith("list")){ + processListCommand(topicList, ui); } else { throw new CustomException("-1 HP coz invalid command"); } @@ -55,6 +57,12 @@ public void parseCommand( } + private void processListCommand(TopicList topicList, Ui ui) { + String[][] printData = topicList.listAllTopics(); + String[] tableHeader = {"index", "topic", "summary", "attempted"}; + ui.printTable(tableHeader, printData); + } + private void processResultsCommand(String lowerCaseCommand, ResultsList allResults, Ui ui, QuestionListByTopic questionListByTopic, AnswerTracker userAnswers) throws CustomException { diff --git a/src/main/java/seedu/duke/Player2113.java b/src/main/java/seedu/duke/Player2113.java index 8ccb5e4de5..995fafe5c3 100644 --- a/src/main/java/seedu/duke/Player2113.java +++ b/src/main/java/seedu/duke/Player2113.java @@ -36,8 +36,8 @@ public Player2113(String someFilePath) { questionsList2.addQuestion(question4); questionListByTopic.addQuestionSet(questionsList2); - Topic topic1 = new Topic(questionsList1,"topic1", false); - Topic topic2 = new Topic(questionsList2,"topic2", false); + Topic topic1 = new Topic(questionsList1,"topic1", false, "Covers topic 1 notions mentioned in lecture 1-2"); + Topic topic2 = new Topic(questionsList2,"topic2", false, "Covers topic 2 notions mentioned in lecture 3-4"); topicList.addTopic(topic1); topicList.addTopic(topic2); } diff --git a/src/main/java/seedu/duke/Topic.java b/src/main/java/seedu/duke/Topic.java index ebd2ed5224..213e90107c 100644 --- a/src/main/java/seedu/duke/Topic.java +++ b/src/main/java/seedu/duke/Topic.java @@ -5,10 +5,13 @@ public class Topic { protected String topicName; protected boolean hasAttempted; - public Topic(QuestionsList chosenQuestionsList, String topicName, boolean hasAttempted){ + protected String summary; + + public Topic(QuestionsList chosenQuestionsList, String topicName, boolean hasAttempted, String summary){ this.chosenQuestionsList = chosenQuestionsList; this.topicName = topicName; this.hasAttempted = hasAttempted; + this.summary = summary; } public String getStatus() { diff --git a/src/main/java/seedu/duke/TopicList.java b/src/main/java/seedu/duke/TopicList.java index d6d99efc9e..4383c015de 100644 --- a/src/main/java/seedu/duke/TopicList.java +++ b/src/main/java/seedu/duke/TopicList.java @@ -17,6 +17,20 @@ public String getTopic(int index){ return topicList.get(index).topicName; } + public String[][] listAllTopics() { + int commandNum = topicList.size(); + String[][] tableData = new String[commandNum][]; + for (int i = 0; i < commandNum; i++) { + tableData[i] = new String[]{ + String.valueOf(i + 1), + topicList.get(i).topicName, + topicList.get(i).summary, + String.valueOf(topicList.get(i).hasAttempted) + }; + } + return tableData; + } + public int getSize() { //System.out.println(topicList.size()); return topicList.size(); From f0786eef5600d86ffe9edfafe85d78320fcc1187 Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Sun, 24 Mar 2024 01:34:21 +0800 Subject: [PATCH 083/334] add topicListTest --- src/main/java/seedu/duke/TopicList.java | 7 ----- src/test/java/seedu/duke/TopicListTest.java | 35 +++++++++++++++++++++ 2 files changed, 35 insertions(+), 7 deletions(-) create mode 100644 src/test/java/seedu/duke/TopicListTest.java diff --git a/src/main/java/seedu/duke/TopicList.java b/src/main/java/seedu/duke/TopicList.java index 4383c015de..8d0e9a056d 100644 --- a/src/main/java/seedu/duke/TopicList.java +++ b/src/main/java/seedu/duke/TopicList.java @@ -32,14 +32,7 @@ public String[][] listAllTopics() { } public int getSize() { - //System.out.println(topicList.size()); return topicList.size(); } - public String getChosenTopic(int topicNum){ - int topicIndex = topicNum - 1; - Topic topic = topicList.get(topicIndex); - return topic.topicName; - } - } diff --git a/src/test/java/seedu/duke/TopicListTest.java b/src/test/java/seedu/duke/TopicListTest.java new file mode 100644 index 0000000000..4a66c2051f --- /dev/null +++ b/src/test/java/seedu/duke/TopicListTest.java @@ -0,0 +1,35 @@ +package seedu.duke; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +class TopicListTest { + Topic topicTest1; + Topic topicTest2; + QuestionsList qnList; + QuestionsList qnList2; + TopicList topicListTest; + + + void createTopicList(){ + topicTest1 = new Topic(qnList, "topicTest1", false, "covers topic 1" ); + topicTest2 = new Topic(qnList2, "topicTest1", false, "covers topic 2" ); + + topicListTest = new TopicList(); + + topicListTest.addTopic(topicTest1); + topicListTest.addTopic(topicTest2); + } + + @Test + void testGetTopic(){ + createTopicList(); + assertEquals("topicTest1",topicListTest.getTopic(1)); + } + + @Test + void testGetSize(){ + createTopicList(); + assertEquals(2, topicListTest.getSize()); + } +} From 6160b65e862ffc5eb62e3612becdb7c85ce6563a Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Tue, 26 Mar 2024 13:06:50 +0800 Subject: [PATCH 084/334] add access to solutions/ explanations only after attempting --- src/main/java/seedu/duke/Parser.java | 19 +++++++++++++++---- src/main/java/seedu/duke/TopicList.java | 4 ++++ src/main/java/seedu/duke/Ui.java | 1 + 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 3ffaea9365..f385e67829 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -26,11 +26,14 @@ public class Parser { private static final String MESSAGE_INVALID_INDEX = "Index must be an integer."; boolean hasChosenTopic = false; + public void parseCommand( + String command, Ui ui, QuestionsList questionsList, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults, Helper helper, AnswerTracker userAnswers ) throws CustomException { + String lowerCaseCommand = command.toLowerCase(); if (ui.isPlaying) { @@ -134,6 +137,7 @@ private void processStartCommand ( } ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults, userAnswers); System.out.println("You have finished the topic! What will be your next topic?"); + topicList.get(topicNum - 1).markAsAttempted(); ui.printTopicList(topicList, ui); } catch (NumberFormatException e) { @@ -175,15 +179,23 @@ private void processSolutionCommand( if (questionNum < 1 || questionNum > qnList.getSize()) { throw new CustomException(("No such question")); } - if (isSolutionCommand) { String solution = qnList.getOneSolution(questionNum); - ui.printOneSolution(questionNum, solution); + if (topicList.get(topicNum - 1).hasAttempted) { + ui.printOneSolution(questionNum, solution); + } else { + System.out.print ("Attempt the topic first!"); + } return; } // only runs if explanation assert typeOfCommand.contentEquals("explain") : "typeOfCommand should be explain"; String explanation = qnList.getOneExplanation(questionNum); - ui.printOneSolution(questionNum, explanation); + if (topicList.get(topicNum - 1).hasAttempted) { + ui.printOneSolution(questionNum, explanation); + } else { + System.out.print ("Attempt the topic first!"); + } + } catch (NumberFormatException e) { // if parameter is a String @@ -198,7 +210,6 @@ private void processSolutionCommand( String allSolutions = qnList.getAllSolutions(); ui.printAllSolutions(allSolutions); } - } public void handleAnswerInputs(String[] inputAnswers, int index, String answer, Question questionUnit, diff --git a/src/main/java/seedu/duke/TopicList.java b/src/main/java/seedu/duke/TopicList.java index 8d0e9a056d..be3d2ba825 100644 --- a/src/main/java/seedu/duke/TopicList.java +++ b/src/main/java/seedu/duke/TopicList.java @@ -35,4 +35,8 @@ public int getSize() { return topicList.size(); } + public Topic get(int index){ + return topicList.get(index); + } + } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 3ef327a8e0..74d1f1881b 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -27,6 +27,7 @@ public void readCommands( ) { Parser parser = new Parser(); printLine(); + //int[] solutionEnabled = new int[topicList.getSize()]; while(isPlaying) { ui.askForInput(); From c01d6bfbce7393ecb1ba5db62008159e09551a51 Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Tue, 26 Mar 2024 13:13:09 +0800 Subject: [PATCH 085/334] use more OOP --- src/main/java/seedu/duke/Parser.java | 4 ++-- src/main/java/seedu/duke/Ui.java | 9 +++------ 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index f385e67829..163f08d763 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -184,7 +184,7 @@ private void processSolutionCommand( if (topicList.get(topicNum - 1).hasAttempted) { ui.printOneSolution(questionNum, solution); } else { - System.out.print ("Attempt the topic first!"); + ui.printNoSolutionAccess(); } return; } // only runs if explanation @@ -193,7 +193,7 @@ private void processSolutionCommand( if (topicList.get(topicNum - 1).hasAttempted) { ui.printOneSolution(questionNum, explanation); } else { - System.out.print ("Attempt the topic first!"); + ui.printNoSolutionAccess(); } diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 74d1f1881b..d73563a704 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -27,7 +27,6 @@ public void readCommands( ) { Parser parser = new Parser(); printLine(); - //int[] solutionEnabled = new int[topicList.getSize()]; while(isPlaying) { ui.askForInput(); @@ -92,17 +91,15 @@ public void printChosenTopic( userAnswers.addUserCorrectness(answersCorrectness); } + public void printNoSolutionAccess(){ + System.out.println("Attempt the topic first!"); + } public void printOneSolution(int questionNum, String solution) { System.out.println("The solution for question " + questionNum + ":" + System.lineSeparator() + solution); } - public void printOneExplanation (int questionNum, String explanation) { - System.out.println("The explanation for question " + questionNum + ":" - + System.lineSeparator() + explanation); - } - public void printAllSolutions(String allSolutions) { System.out.println("The solutions are :" + System.lineSeparator() + allSolutions); From 3788af77b4d2436cb6f450473e97a6936ff2d0a0 Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Tue, 26 Mar 2024 13:44:16 +0800 Subject: [PATCH 086/334] add assertions --- src/main/java/seedu/duke/Parser.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 163f08d763..b4e9299517 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -24,7 +24,6 @@ public class Parser { private static final int NO_RESULTS = 0; private static final String MESSAGE_INDEX_OUT_OF_BOUNDS = "Index is out of bounds."; private static final String MESSAGE_INVALID_INDEX = "Index must be an integer."; - boolean hasChosenTopic = false; public void parseCommand( @@ -37,11 +36,8 @@ public void parseCommand( String lowerCaseCommand = command.toLowerCase(); if (ui.isPlaying) { - if (lowerCaseCommand.startsWith("topic") && !hasChosenTopic) { + if (lowerCaseCommand.startsWith("topic")) { processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, allResults, userAnswers); - //hasChosenTopic = true; - } else if (lowerCaseCommand.startsWith("topic") && hasChosenTopic) { - throw new CustomException("Please choose a topic in the format: topic [INDEX]"); } else if (lowerCaseCommand.startsWith("bye")) { ui.isPlaying = false; } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { @@ -182,6 +178,8 @@ private void processSolutionCommand( if (isSolutionCommand) { String solution = qnList.getOneSolution(questionNum); if (topicList.get(topicNum - 1).hasAttempted) { + assert (questionNum > 0 && questionNum <= qnList.getSize()): "question number out of range"; + assert (topicNum > 0 && topicNum <= topicList.getSize()): "topic number out of range"; ui.printOneSolution(questionNum, solution); } else { ui.printNoSolutionAccess(); @@ -191,6 +189,8 @@ private void processSolutionCommand( assert typeOfCommand.contentEquals("explain") : "typeOfCommand should be explain"; String explanation = qnList.getOneExplanation(questionNum); if (topicList.get(topicNum - 1).hasAttempted) { + assert (questionNum > 0 && questionNum <= qnList.getSize()): "question number out of range"; + assert (topicNum > 0 && topicNum <= topicList.getSize()): "topic number out of range"; ui.printOneSolution(questionNum, explanation); } else { ui.printNoSolutionAccess(); From 597c02e9509384e1af428a7e8a66e20717b1a1e5 Mon Sep 17 00:00:00 2001 From: Songyue Wang Date: Wed, 27 Mar 2024 19:22:44 +0800 Subject: [PATCH 087/334] Added JUnit --- src/main/java/seedu/duke/Helper.java | 4 ++++ src/test/java/seedu/duke/HelperTest.java | 15 +++++++++++++++ 2 files changed, 19 insertions(+) create mode 100644 src/test/java/seedu/duke/HelperTest.java diff --git a/src/main/java/seedu/duke/Helper.java b/src/main/java/seedu/duke/Helper.java index a9761fab27..5abf5c6a2b 100644 --- a/src/main/java/seedu/duke/Helper.java +++ b/src/main/java/seedu/duke/Helper.java @@ -56,4 +56,8 @@ public String[][] listAllCommands() { } return tableData; } + + public int getCommandsCount() { + return commandList.size(); + } } diff --git a/src/test/java/seedu/duke/HelperTest.java b/src/test/java/seedu/duke/HelperTest.java new file mode 100644 index 0000000000..bd76d7d89c --- /dev/null +++ b/src/test/java/seedu/duke/HelperTest.java @@ -0,0 +1,15 @@ +package seedu.duke; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class HelperTest { + + private final Helper helperTest = new Helper(); + + @Test + // check number of prompts in the helper's command list + public void dummyTest(){ + assertEquals(helperTest.getCommandsCount(), 7); + } +} \ No newline at end of file From 2ca70e395bd15ed477e450a47740aaeef0051408 Mon Sep 17 00:00:00 2001 From: Songyue Wang Date: Wed, 27 Mar 2024 19:30:02 +0800 Subject: [PATCH 088/334] Used assert in code --- src/main/java/seedu/duke/Helper.java | 3 +++ src/test/java/seedu/duke/HelperTest.java | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/Helper.java b/src/main/java/seedu/duke/Helper.java index 5abf5c6a2b..6cdf913079 100644 --- a/src/main/java/seedu/duke/Helper.java +++ b/src/main/java/seedu/duke/Helper.java @@ -45,6 +45,7 @@ public Helper() { } public String[][] listAllCommands() { + assert getCommandsCount() > 0 : "Available commands list is empty"; int commandNum = commandList.size(); String[][] tableData = new String[commandNum][]; for (int i = 0; i < commandNum; i++) { @@ -60,4 +61,6 @@ public String[][] listAllCommands() { public int getCommandsCount() { return commandList.size(); } + } + diff --git a/src/test/java/seedu/duke/HelperTest.java b/src/test/java/seedu/duke/HelperTest.java index bd76d7d89c..33bbb33e13 100644 --- a/src/test/java/seedu/duke/HelperTest.java +++ b/src/test/java/seedu/duke/HelperTest.java @@ -9,7 +9,7 @@ public class HelperTest { @Test // check number of prompts in the helper's command list - public void dummyTest(){ + public void helperCompletenessTest(){ assertEquals(helperTest.getCommandsCount(), 7); } -} \ No newline at end of file +} From 4c5f5230197a8bf6d54c451a11be5831a4aed860 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Wed, 27 Mar 2024 23:48:42 +0800 Subject: [PATCH 089/334] feat(ui):add random topic option in printchosentopic() --- src/main/java/seedu/duke/Parser.java | 4 +--- src/main/java/seedu/duke/Ui.java | 5 +++++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index b4e9299517..14cb5e9b53 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -142,9 +142,7 @@ private void processStartCommand ( } - // user enters "solution 1" to get solution for question1 OR - // user enters "solution -all" to get ALL solutions - // also works for "explain 1" + // solution and explain commands private void processSolutionCommand( String lowerCaseCommand, Ui ui, QuestionsList questionsList, TopicList topicList, QuestionListByTopic questionListByTopic diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index d73563a704..696b3eaa05 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -56,6 +56,7 @@ public void printTopicList(TopicList topicList, Ui ui){ for (int index = 0; index < topicListSize; index++) { System.out.println((index + 1) + ". " + topicList.getTopic(index)); } + System.out.println((topicListSize + 1) + ". " + "Randomly select a topic for me ;)"); System.out.println("Please choose a topic to play:");//input command in the form "start [INDEX] } @@ -63,6 +64,10 @@ public void printChosenTopic( int topicNum, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList alLResults, AnswerTracker userAnswers ){ + if (topicNum == topicList.getSize()) { + System.out.println("You reached here"); + return; + } Results topicResults = new Results(); QuestionsList qnList; System.out.println("Selected topic: " + topicList.getTopic(topicNum - 1)); From bbc9d1119d3f9927444b21b09d2ef15d721bd1f2 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Thu, 28 Mar 2024 00:19:08 +0800 Subject: [PATCH 090/334] feat(helper, parser, ui): add random-generated-topic feature --- src/main/java/seedu/duke/Helper.java | 6 ++++++ src/main/java/seedu/duke/Parser.java | 7 +++++++ src/main/java/seedu/duke/Ui.java | 6 +----- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/Helper.java b/src/main/java/seedu/duke/Helper.java index 6cdf913079..818a9a4f55 100644 --- a/src/main/java/seedu/duke/Helper.java +++ b/src/main/java/seedu/duke/Helper.java @@ -1,6 +1,7 @@ package seedu.duke; import java.util.ArrayList; +import java.util.Random; public class Helper { private static final ArrayList commandList = new ArrayList(); @@ -62,5 +63,10 @@ public int getCommandsCount() { return commandList.size(); } + // returns random number from 0 to upperLimit - 1 + public int generateRandomNumber(int upperLimit) { + Random random = new Random(); + return random.nextInt(upperLimit); + } } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 14cb5e9b53..8b36195866 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -131,6 +131,13 @@ private void processStartCommand ( if (topicNum < 1 || topicNum > topicList.getSize() + 1) { throw new CustomException("No such topic"); } + // checks if user wants a random topic num + final int RANDOM_TOPIC_NUM = topicList.getSize() + 1; + if (topicNum == RANDOM_TOPIC_NUM) { + Helper helper = new Helper(); + System.out.println("You reached here"); + topicNum = helper.generateRandomNumber(RANDOM_TOPIC_NUM); + } ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults, userAnswers); System.out.println("You have finished the topic! What will be your next topic?"); topicList.get(topicNum - 1).markAsAttempted(); diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 696b3eaa05..d90b73d4c1 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -64,10 +64,6 @@ public void printChosenTopic( int topicNum, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList alLResults, AnswerTracker userAnswers ){ - if (topicNum == topicList.getSize()) { - System.out.println("You reached here"); - return; - } Results topicResults = new Results(); QuestionsList qnList; System.out.println("Selected topic: " + topicList.getTopic(topicNum - 1)); @@ -144,7 +140,7 @@ private void printResultDetails(QuestionListByTopic questionListByTopic, int top } private void handleException(CustomException e) { - System.out.println(e.getMessage() + "TODO: show possible commands"); //TODO + System.out.println(e.getMessage()); //TODO } public void printLine() { for (int i = 0; i < NEW_LINE; i += 1) { From 32f4334dacbb8616b99b5a450e2b1da2c55ccfb1 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Thu, 28 Mar 2024 01:06:50 +0800 Subject: [PATCH 091/334] test(helper): add test casesfor generaterandomnumber() --- src/main/java/seedu/duke/Parser.java | 8 ++++---- src/test/java/seedu/duke/HelperTest.java | 17 ++++++++++++++--- 2 files changed, 18 insertions(+), 7 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 8b36195866..81ef59ac94 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -132,12 +132,12 @@ private void processStartCommand ( throw new CustomException("No such topic"); } // checks if user wants a random topic num - final int RANDOM_TOPIC_NUM = topicList.getSize() + 1; - if (topicNum == RANDOM_TOPIC_NUM) { + final int randomTopicNum = topicList.getSize() + 1; + if (topicNum == randomTopicNum) { Helper helper = new Helper(); - System.out.println("You reached here"); - topicNum = helper.generateRandomNumber(RANDOM_TOPIC_NUM); + topicNum = helper.generateRandomNumber(randomTopicNum); } + // prints questions ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults, userAnswers); System.out.println("You have finished the topic! What will be your next topic?"); topicList.get(topicNum - 1).markAsAttempted(); diff --git a/src/test/java/seedu/duke/HelperTest.java b/src/test/java/seedu/duke/HelperTest.java index 33bbb33e13..6834a433e0 100644 --- a/src/test/java/seedu/duke/HelperTest.java +++ b/src/test/java/seedu/duke/HelperTest.java @@ -5,11 +5,22 @@ public class HelperTest { - private final Helper helperTest = new Helper(); + private static final Helper helperTest = new Helper(); @Test // check number of prompts in the helper's command list - public void helperCompletenessTest(){ - assertEquals(helperTest.getCommandsCount(), 7); + public void getCommandsCount_correctNumOfCommandsInList_expect7(){ + assertEquals(7, helperTest.getCommandsCount()); + } + + @Test + void generateRandomNumber_noTopicToChooseFrom_expect0() { + int upperLimit = 1; + assertEquals(0, helperTest.generateRandomNumber(upperLimit)); + } + @Test + void generateRandomNumber_onlyOneTopicToChooseFrom_expect1() { + int upperLimit = 2; + assertEquals(1, helperTest.generateRandomNumber(upperLimit)); } } From c890c4a01b6801bd49f987eca2d1538c34c38378 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Thu, 28 Mar 2024 01:32:30 +0800 Subject: [PATCH 092/334] bug(helper): fix bug in generaterandomnumber() as it may return 0, which is invalid --- src/main/java/seedu/duke/Helper.java | 14 ++++++++++++-- src/main/java/seedu/duke/Parser.java | 4 ++++ src/test/java/seedu/duke/HelperTest.java | 9 ++------- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/duke/Helper.java b/src/main/java/seedu/duke/Helper.java index 818a9a4f55..1fdd621e6d 100644 --- a/src/main/java/seedu/duke/Helper.java +++ b/src/main/java/seedu/duke/Helper.java @@ -63,10 +63,20 @@ public int getCommandsCount() { return commandList.size(); } - // returns random number from 0 to upperLimit - 1 + // returns random topic number from 1 to upperLimit - 1 public int generateRandomNumber(int upperLimit) { + assert (upperLimit != 1) : "upperLimit == 1 means topicList.getSize() = 0"; Random random = new Random(); - return random.nextInt(upperLimit); + int randomNumber = 0; + boolean isCheckingValidTopicNum = true; + + while (isCheckingValidTopicNum) { //random.nextInt() may return 0, which is NOT a valid topicNum + randomNumber = random.nextInt(upperLimit); + if (randomNumber != 0) { + isCheckingValidTopicNum = false; + } + } + return randomNumber; } } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 81ef59ac94..74847fc6a5 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -118,6 +118,7 @@ private void processStartCommand ( String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults, AnswerTracker userAnswers ) throws CustomException { + assert (topicList.getSize() != 0) : "Size of topicList should never be 0"; String[] commandParts = lowerCaseCommand.split(" "); if (commandParts.length != 2) { @@ -137,6 +138,9 @@ private void processStartCommand ( Helper helper = new Helper(); topicNum = helper.generateRandomNumber(randomTopicNum); } + assert (topicNum != 0) : "topicNum should not be 0"; + assert (topicNum != randomTopicNum) : "topicNum should not be randomTopicNum"; + // prints questions ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults, userAnswers); System.out.println("You have finished the topic! What will be your next topic?"); diff --git a/src/test/java/seedu/duke/HelperTest.java b/src/test/java/seedu/duke/HelperTest.java index 6834a433e0..795ba956a9 100644 --- a/src/test/java/seedu/duke/HelperTest.java +++ b/src/test/java/seedu/duke/HelperTest.java @@ -13,14 +13,9 @@ public void getCommandsCount_correctNumOfCommandsInList_expect7(){ assertEquals(7, helperTest.getCommandsCount()); } - @Test - void generateRandomNumber_noTopicToChooseFrom_expect0() { - int upperLimit = 1; - assertEquals(0, helperTest.generateRandomNumber(upperLimit)); - } @Test void generateRandomNumber_onlyOneTopicToChooseFrom_expect1() { - int upperLimit = 2; - assertEquals(1, helperTest.generateRandomNumber(upperLimit)); + int upperLimitOneTopic = 2; + assertEquals(1, helperTest.generateRandomNumber(upperLimitOneTopic)); } } From b49caf366215d65f07690cd8ce73d6825d877220 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Thu, 28 Mar 2024 01:37:28 +0800 Subject: [PATCH 093/334] ci(expected.txt): update expected.txt to pass github checks --- text-ui-test/EXPECTED.TXT | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index dd3c113b6e..1bcd2cd0be 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -13,10 +13,11 @@ Hello CaiShenYe Here are the topics in CS2113: 1. topic1 2. topic2 +3. Randomly select a topic for me ;) Please choose a topic to play: ************************************************ Input a command player! --1 HP coz invalid commandTODO: show possible commands +-1 HP coz invalid command Input a command player! bye bye, get more sleep zzz ************************************************ From 84108c372113b0868789b33d1a54f3b401c80d96 Mon Sep 17 00:00:00 2001 From: Songyue Wang Date: Thu, 28 Mar 2024 14:11:48 +0800 Subject: [PATCH 094/334] Updated DG --- docs/DeveloperGuide.md | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 64e1f0ed2b..77f2297271 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,37 +1,44 @@ # Developer Guide -## Acknowledgements - -{list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} - ## Design & implementation {Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} - ## Product scope + ### Target user profile -{Describe the target user profile} +CS2113/2103 students who wish to have an efficient tool to help them revise relevant concepts. ### Value proposition -{Describe the value proposition: what problem does it solve?} +Integration of key notions and learning learning objectives for CS2113 course, self-adaptive testing for understanding and feedback. ## 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| +| Version | As a ... | I want to ... | So that I can ... | +| ------- | ------------ | ---------------------------------------------------- | ------------------------------------------------------------ | +| v1.0 | new user | see user guide in the app | refer to them if I am unfamiliar with the usage of a command | +| v2.0 | regular user | see a progress bar when answering MCQs | track my progress when attempting a question set | +| v2.0 | regular user | see a progress bar about all topics in the main menu | track my revision progress for the entire course | ## Non-Functional Requirements -{Give non-functional requirements} +Usability: the user is able to use the app without reading lenthy documentations. ## Glossary -* *glossary item* - Definition +- _glossary item_ - Definition + +## Acknowledgements + +### Libraries + +1. Display formatted tables in the CLI - [ASCII TABLES](https://bethecoder.com/applications/products/asciiTable.action) + +2. Topic selection menu and testing mode progress bar - [ProgressBar](https://github.com/ctongfei/progressbar) + +### References ## Instructions for manual testing From 6d6d6d04445fbcd6a1bfba93480bcf403cbf39b5 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Thu, 28 Mar 2024 22:31:22 +0800 Subject: [PATCH 095/334] style(parser): change static variables to local variables --- src/main/java/seedu/duke/Parser.java | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 74847fc6a5..202245381b 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -5,23 +5,18 @@ import java.util.ArrayList; public class Parser { - private static final int PARAMETER_INDEX = 1; - + private static final int NO_RESULTS = 0; private static final int NO_PARAMETERS = 1; private static final int ONE_PARAMETER = 2; private static final int TWO_PARAMETERS = 3; private static final int FIRST_PARAMETER = 1; private static final int SECOND_PARAMETER = 2; - private static final String DETAILS_PARAMETER = "details"; private static final String COMMAND_SPLITTER = " "; - private static final boolean INCLUDES_DETAILS = true; - private static final boolean IS_CORRECT_ANSWER = true; private static final String MESSAGE_NO_RESULTS = "There are no results."; private static final String MESSAGE_ERROR = "An error has occurred."; private static final String MESSAGE_INVALID_PARAMETERS = "Invalid parameters."; - private static final int NO_RESULTS = 0; private static final String MESSAGE_INDEX_OUT_OF_BOUNDS = "Index is out of bounds."; private static final String MESSAGE_INVALID_INDEX = "Index must be an integer."; @@ -65,6 +60,9 @@ private void processListCommand(TopicList topicList, Ui ui) { private void processResultsCommand(String lowerCaseCommand, ResultsList allResults, Ui ui, QuestionListByTopic questionListByTopic, AnswerTracker userAnswers) throws CustomException { + final String DETAILS_PARAMETER = "details"; + final boolean INCLUDES_DETAILS = true; + if (allResults.getSizeOfAllResults() == NO_RESULTS) { throw new CustomException(MESSAGE_NO_RESULTS); } @@ -76,7 +74,7 @@ private void processResultsCommand(String lowerCaseCommand, ResultsList allResul break; } case (ONE_PARAMETER): { - if (commandParts[PARAMETER_INDEX].equals(DETAILS_PARAMETER)) { + if (commandParts[FIRST_PARAMETER].equals(DETAILS_PARAMETER)) { ui.printAllResults(INCLUDES_DETAILS, allResults, questionListByTopic, userAnswers); } else { try { @@ -93,7 +91,7 @@ private void processResultsCommand(String lowerCaseCommand, ResultsList allResul break; } case (TWO_PARAMETERS): { - if (!commandParts[PARAMETER_INDEX].equals(DETAILS_PARAMETER)) { + if (!commandParts[FIRST_PARAMETER].equals(DETAILS_PARAMETER)) { throw new CustomException(MESSAGE_INVALID_PARAMETERS); } try { @@ -120,11 +118,11 @@ private void processStartCommand ( ) throws CustomException { assert (topicList.getSize() != 0) : "Size of topicList should never be 0"; - String[] commandParts = lowerCaseCommand.split(" "); + String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER); if (commandParts.length != 2) { throw new CustomException("invalid " + lowerCaseCommand + " command"); } - String commandParameter = commandParts[PARAMETER_INDEX]; + String commandParameter = commandParts[FIRST_PARAMETER]; try { // if parameter is an Integer int topicNum = Integer.parseInt(commandParameter); @@ -161,14 +159,14 @@ private void processSolutionCommand( boolean isSolutionCommand = lowerCaseCommand.startsWith("solution"); String typeOfCommand = isSolutionCommand ? "solution" : "explain"; - String[] commandParts = lowerCaseCommand.split(" "); + String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER); if (commandParts.length != 3) { throw new CustomException("invalid " + typeOfCommand + " command. Format: solution TOPIC QUESTION_INDEX"); } // check validity of parameter - String commandParameterTopic = commandParts[PARAMETER_INDEX]; - String commandParameterQn = commandParts[PARAMETER_INDEX + 1]; + String commandParameterTopic = commandParts[FIRST_PARAMETER]; + String commandParameterQn = commandParts[FIRST_PARAMETER + 1]; try { // if parameter is an Integer @@ -223,6 +221,8 @@ private void processSolutionCommand( public void handleAnswerInputs(String[] inputAnswers, int index, String answer, Question questionUnit, Results topicResults, ArrayList correctness){ + final boolean IS_CORRECT_ANSWER = true; + inputAnswers[index] = answer; String correctAnswer = questionUnit.getSolution(); if (answer.equals(correctAnswer)){ @@ -234,7 +234,7 @@ public void handleAnswerInputs(String[] inputAnswers, int index, String answer, } private void processHelpCommand(String lowerCaseCommand, Ui ui, Helper helper) throws CustomException { - String[] commandParts = lowerCaseCommand.split(" "); + String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER); if (commandParts.length != 1 && commandParts.length != 2) { throw new CustomException("invalid help command parameter"); } From a82d92caff55260075c85a3b4cac0d65a4a2d510 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Thu, 28 Mar 2024 23:10:22 +0800 Subject: [PATCH 096/334] style(parser): remove redundant lines of code in process solution command --- src/main/java/seedu/duke/Parser.java | 56 ++++++++++++------------ src/main/java/seedu/duke/Player2113.java | 3 +- src/main/java/seedu/duke/Topic.java | 19 ++++---- src/main/java/seedu/duke/TopicList.java | 2 +- src/main/java/seedu/duke/Ui.java | 4 +- 5 files changed, 39 insertions(+), 45 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 202245381b..870ff06579 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -6,9 +6,9 @@ public class Parser { private static final int NO_RESULTS = 0; - private static final int NO_PARAMETERS = 1; - private static final int ONE_PARAMETER = 2; - private static final int TWO_PARAMETERS = 3; + private static final int NO_PARAMETER_LENGTH = 1; + private static final int ONE_PARAMETER_LENGTH = 2; + private static final int TWO_PARAMETER_LENGTH = 3; private static final int FIRST_PARAMETER = 1; private static final int SECOND_PARAMETER = 2; @@ -23,9 +23,8 @@ public class Parser { public void parseCommand( - String command, Ui ui, QuestionsList questionsList, - TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults, Helper helper, - AnswerTracker userAnswers + String command, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic, + ResultsList allResults, Helper helper, AnswerTracker userAnswers ) throws CustomException { String lowerCaseCommand = command.toLowerCase(); @@ -36,8 +35,7 @@ public void parseCommand( } else if (lowerCaseCommand.startsWith("bye")) { ui.isPlaying = false; } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { - //System.out.println("ERROR"); - processSolutionCommand(lowerCaseCommand, ui, questionsList, topicList, questionListByTopic); + processSolutionCommand(lowerCaseCommand, ui, topicList, questionListByTopic); } else if (lowerCaseCommand.startsWith("results")) { processResultsCommand(lowerCaseCommand, allResults, ui, questionListByTopic, userAnswers); } else if (lowerCaseCommand.startsWith("help")) { @@ -66,14 +64,14 @@ private void processResultsCommand(String lowerCaseCommand, ResultsList allResul if (allResults.getSizeOfAllResults() == NO_RESULTS) { throw new CustomException(MESSAGE_NO_RESULTS); } - String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER, TWO_PARAMETERS); - assert commandParts.length <= TWO_PARAMETERS; + String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER, TWO_PARAMETER_LENGTH); + assert commandParts.length <= TWO_PARAMETER_LENGTH; switch (commandParts.length) { - case (NO_PARAMETERS): { + case (NO_PARAMETER_LENGTH): { ui.printAllResults(!INCLUDES_DETAILS, allResults, questionListByTopic, userAnswers); break; } - case (ONE_PARAMETER): { + case (ONE_PARAMETER_LENGTH): { if (commandParts[FIRST_PARAMETER].equals(DETAILS_PARAMETER)) { ui.printAllResults(INCLUDES_DETAILS, allResults, questionListByTopic, userAnswers); } else { @@ -90,7 +88,7 @@ private void processResultsCommand(String lowerCaseCommand, ResultsList allResul } break; } - case (TWO_PARAMETERS): { + case (TWO_PARAMETER_LENGTH): { if (!commandParts[FIRST_PARAMETER].equals(DETAILS_PARAMETER)) { throw new CustomException(MESSAGE_INVALID_PARAMETERS); } @@ -116,7 +114,7 @@ private void processStartCommand ( String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults, AnswerTracker userAnswers ) throws CustomException { - assert (topicList.getSize() != 0) : "Size of topicList should never be 0"; + assert (topicList.getSize() != NO_RESULTS) : "Size of topicList should never be 0"; String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER); if (commandParts.length != 2) { @@ -153,9 +151,11 @@ private void processStartCommand ( // solution and explain commands private void processSolutionCommand( - String lowerCaseCommand, Ui ui, QuestionsList questionsList, - TopicList topicList, QuestionListByTopic questionListByTopic - ) throws CustomException { + String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) + throws CustomException { + assert (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) + : "either solution or explain command"; + boolean isSolutionCommand = lowerCaseCommand.startsWith("solution"); String typeOfCommand = isSolutionCommand ? "solution" : "explain"; @@ -166,40 +166,38 @@ private void processSolutionCommand( // check validity of parameter String commandParameterTopic = commandParts[FIRST_PARAMETER]; - String commandParameterQn = commandParts[FIRST_PARAMETER + 1]; + String commandParameterQn = commandParts[SECOND_PARAMETER]; try { // if parameter is an Integer int topicNum = Integer.parseInt(commandParameterTopic); int questionNum = Integer.parseInt(commandParameterQn); - // checks validity of parameter + // checks validity of topicNum if (topicNum < 1 || topicNum > topicList.getSize()) { throw new CustomException("No such topic"); } - + // checks validity of questionNum QuestionsList qnList = questionListByTopic.getQuestionSet(topicNum - 1); if (questionNum < 1 || questionNum > qnList.getSize()) { throw new CustomException(("No such question")); } if (isSolutionCommand) { String solution = qnList.getOneSolution(questionNum); - if (topicList.get(topicNum - 1).hasAttempted) { - assert (questionNum > 0 && questionNum <= qnList.getSize()): "question number out of range"; - assert (topicNum > 0 && topicNum <= topicList.getSize()): "topic number out of range"; + if (topicList.get(topicNum - 1).hasAttempted()) { ui.printOneSolution(questionNum, solution); - } else { + } else { // has not attempted ui.printNoSolutionAccess(); } return; - } // only runs if explanation + } + // only runs code below if explain command assert typeOfCommand.contentEquals("explain") : "typeOfCommand should be explain"; + String explanation = qnList.getOneExplanation(questionNum); - if (topicList.get(topicNum - 1).hasAttempted) { - assert (questionNum > 0 && questionNum <= qnList.getSize()): "question number out of range"; - assert (topicNum > 0 && topicNum <= topicList.getSize()): "topic number out of range"; + if (topicList.get(topicNum - 1).hasAttempted()) { ui.printOneSolution(questionNum, explanation); - } else { + } else { // has not attempted ui.printNoSolutionAccess(); } diff --git a/src/main/java/seedu/duke/Player2113.java b/src/main/java/seedu/duke/Player2113.java index 995fafe5c3..f981ddf90b 100644 --- a/src/main/java/seedu/duke/Player2113.java +++ b/src/main/java/seedu/duke/Player2113.java @@ -3,7 +3,6 @@ public class Player2113 { public static final String SOME_FILE_PATH = "something"; private Ui ui; - private QuestionsList questionsList; private QuestionsList questionsList1; private QuestionsList questionsList2; private TopicList topicList; @@ -50,7 +49,7 @@ public void run() { ui.printTopicList(topicList, ui); while (ui.isPlaying) { - ui.readCommands(ui, questionsList, topicList, questionListByTopic, allResults, helper, userAnswers); + ui.readCommands(ui, topicList, questionListByTopic, allResults, helper, userAnswers); } } diff --git a/src/main/java/seedu/duke/Topic.java b/src/main/java/seedu/duke/Topic.java index 213e90107c..80c61e4dfb 100644 --- a/src/main/java/seedu/duke/Topic.java +++ b/src/main/java/seedu/duke/Topic.java @@ -3,31 +3,28 @@ public class Topic { protected QuestionsList chosenQuestionsList; protected String topicName; - protected boolean hasAttempted; + protected boolean hasAttemptedStatus; protected String summary; - public Topic(QuestionsList chosenQuestionsList, String topicName, boolean hasAttempted, String summary){ + public Topic(QuestionsList chosenQuestionsList, String topicName, boolean hasAttemptedStatus, String summary){ this.chosenQuestionsList = chosenQuestionsList; this.topicName = topicName; - this.hasAttempted = hasAttempted; + this.hasAttemptedStatus = hasAttemptedStatus; this.summary = summary; } - public String getStatus() { - if (hasAttempted) { - return "Attempted"; - } else { - return "Not attempted"; - } + public boolean hasAttempted() { + return this.hasAttemptedStatus; } public void markAsAttempted() { - this.hasAttempted = true; + this.hasAttemptedStatus = true; } public String toString(){ - return "[" + getStatus() + "]" + topicName; + String status = this.hasAttempted() ? "Attempted" : "Not attempted"; + return "[" + status + "]" + topicName; } } diff --git a/src/main/java/seedu/duke/TopicList.java b/src/main/java/seedu/duke/TopicList.java index be3d2ba825..cf2b9aea4c 100644 --- a/src/main/java/seedu/duke/TopicList.java +++ b/src/main/java/seedu/duke/TopicList.java @@ -25,7 +25,7 @@ public String[][] listAllTopics() { String.valueOf(i + 1), topicList.get(i).topicName, topicList.get(i).summary, - String.valueOf(topicList.get(i).hasAttempted) + String.valueOf(topicList.get(i).hasAttempted()) }; } return tableData; diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index d90b73d4c1..d986c5c0f7 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -22,7 +22,7 @@ public class Ui { public String[] inputAnswers; public void readCommands( - Ui ui, QuestionsList questionsList, TopicList topicList, + Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults, Helper helper, AnswerTracker userAnswers ) { Parser parser = new Parser(); @@ -32,7 +32,7 @@ public void readCommands( ui.askForInput(); String command = in.nextLine(); try { - parser.parseCommand(command, ui, questionsList, topicList, questionListByTopic, allResults, helper, + parser.parseCommand(command, ui, topicList, questionListByTopic, allResults, helper, userAnswers); } catch (CustomException e) { ui.handleException(e); From 680fe36ee71fcad92e889566c65134f1d6327b1a Mon Sep 17 00:00:00 2001 From: cyhjason29 Date: Thu, 28 Mar 2024 23:18:37 +0800 Subject: [PATCH 097/334] Update DG with results feature --- docs/DeveloperGuide.md | 39 ++++++++++++++++++ docs/team/img/Results.png | Bin 0 -> 48317 bytes docs/team/img/Results.puml | 82 +++++++++++++++++++++++++++++++++++++ 3 files changed, 121 insertions(+) create mode 100644 docs/team/img/Results.png create mode 100644 docs/team/img/Results.puml diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 77f2297271..1d53ae13be 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -4,6 +4,45 @@ {Describe the design and implementation of the product. Use UML diagrams and short code snippets where applicable.} +### Results feature + +The results feature is facilitated by `ResultsList` and +`AnswerTracker`. Both are used to display the results for +all question sets attempted by the user, including details +such as specific questions and their respective answer inputs +from the user. + +Given below is an example usage scenario and how the results +mechanism behaves at each step. + +Step 1. The user launches the application for the first time, +and proceeds to start a game with their chosen topic. + +The following sequence diagram shows how the `Results` for +one question set is added to the `ResultsList`: +![ResultsList sequence diagram](./team/img/Results.png) +> **Note:** The lifeline for Parser and Results should end +> at the destroy marker (X) but due to a limitation of PlantUML, +> the lifeline reaches the end of the diagram. + +Similarly, the following sequence diagram shows how the +`AnswerTracker` stores all the user answer inputs: +![AnswerTracker sequence diagram](https://via.placeholder.com/100.png?text=Photo) + +Step 2. The user may repeat Step 1 with other question sets. + +The sequence diagram for this step involving `ResultsList` +and `AnswerTracker` are the same as the ones shown in Step 1. + +Step 3. The user now wants to view their results by executing +the `results` command. +![Results command sequence diagram](https://via.placeholder.com/100.png?text=Photo) + +> **Note:** If the user uses the results feature before +> attempting any questions, the application will instead +> return an error to the user indicating that there are no +> results. + ## Product scope ### Target user profile diff --git a/docs/team/img/Results.png b/docs/team/img/Results.png new file mode 100644 index 0000000000000000000000000000000000000000..0ebb88fae445a72b6969d6327c4914208443d8f5 GIT binary patch literal 48317 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 Ui : printChosenTopic(topicNum: int) +activate Ui + +create Results +Ui -> Results : new Results() +activate Results +Results --> Ui +deactivate Results + +ref over Ui : get question set + +Ui -> ResultsList : addQuestions(topicNum-1: int) +activate ResultsList +ResultsList --> Ui +deactivate ResultsList + +loop until all questions + +Ui -> Results : increaseNumberOfQuestions() +activate Results +Results --> Ui +deactivate Results + +ref over Ui +ask question and +receive user input +end ref + +create Parser +Ui -> Parser : new Parser() +activate Parser +Parser --> Ui +deactivate Parser + +Ui -> Parser : handleAnswerInputs(answer: String) +activate Parser + +ref over Parser : get correct answer + +alt answer.equals(correctAnswer) +Parser -> Results : increaseCorrectAnswers() +activate Results +Results --> Parser +deactivate Results + +else else +end + +Parser --> Ui +deactivate Parser +end + +Ui -> Results : calculateScore() +activate Results +Results --> Ui +deactivate Results + +Ui -> ResultsList : addResults(topicResults: Results) +activate ResultsList +ResultsList --> Ui +deactivate ResultsList + +Ui -->[ + +destroy Results +destroy Parser + +@enduml \ No newline at end of file From 142c8481f7455cffb7bf3b9461e1c900fba2c128 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Fri, 29 Mar 2024 00:49:58 +0800 Subject: [PATCH 098/334] feat(parser)!: add get all explanations feature and tests --- src/main/java/seedu/duke/Parser.java | 134 +++++++++--------- src/main/java/seedu/duke/QuestionsList.java | 29 ++-- .../java/seedu/duke/QuestionsListTest.java | 44 ++++-- 3 files changed, 121 insertions(+), 86 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 870ff06579..a884c2005f 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -11,14 +11,19 @@ public class Parser { private static final int TWO_PARAMETER_LENGTH = 3; private static final int FIRST_PARAMETER = 1; private static final int SECOND_PARAMETER = 2; + private static final String DUMMY_QUESTION_PARAMETER = "1"; private static final String COMMAND_SPLITTER = " "; + private static final String DETAILS_PARAMETER = "details"; + private static final String MESSAGE_NO_RESULTS = "There are no results."; private static final String MESSAGE_ERROR = "An error has occurred."; private static final String MESSAGE_INVALID_PARAMETERS = "Invalid parameters."; private static final String MESSAGE_INDEX_OUT_OF_BOUNDS = "Index is out of bounds."; private static final String MESSAGE_INVALID_INDEX = "Index must be an integer."; + private static final boolean INCLUDES_DETAILS = true; + private static final boolean IS_CORRECT_ANSWER = true; public void parseCommand( @@ -30,17 +35,17 @@ public void parseCommand( String lowerCaseCommand = command.toLowerCase(); if (ui.isPlaying) { - if (lowerCaseCommand.startsWith("topic")) { + if (lowerCaseCommand.contentEquals("topic")) { processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, allResults, userAnswers); - } else if (lowerCaseCommand.startsWith("bye")) { + } else if (lowerCaseCommand.contentEquals("bye")) { ui.isPlaying = false; - } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { + } else if (lowerCaseCommand.contentEquals("solution") || lowerCaseCommand.contentEquals("explain")) { processSolutionCommand(lowerCaseCommand, ui, topicList, questionListByTopic); - } else if (lowerCaseCommand.startsWith("results")) { + } else if (lowerCaseCommand.contentEquals("results")) { processResultsCommand(lowerCaseCommand, allResults, ui, questionListByTopic, userAnswers); - } else if (lowerCaseCommand.startsWith("help")) { + } else if (lowerCaseCommand.contentEquals("help")) { processHelpCommand(lowerCaseCommand, ui, helper); - } else if (lowerCaseCommand.startsWith("list")){ + } else if (lowerCaseCommand.contentEquals("list")) { processListCommand(topicList, ui); } else { throw new CustomException("-1 HP coz invalid command"); @@ -58,8 +63,6 @@ private void processListCommand(TopicList topicList, Ui ui) { private void processResultsCommand(String lowerCaseCommand, ResultsList allResults, Ui ui, QuestionListByTopic questionListByTopic, AnswerTracker userAnswers) throws CustomException { - final String DETAILS_PARAMETER = "details"; - final boolean INCLUDES_DETAILS = true; if (allResults.getSizeOfAllResults() == NO_RESULTS) { throw new CustomException(MESSAGE_NO_RESULTS); @@ -67,11 +70,10 @@ private void processResultsCommand(String lowerCaseCommand, ResultsList allResul String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER, TWO_PARAMETER_LENGTH); assert commandParts.length <= TWO_PARAMETER_LENGTH; switch (commandParts.length) { - case (NO_PARAMETER_LENGTH): { + case (NO_PARAMETER_LENGTH): ui.printAllResults(!INCLUDES_DETAILS, allResults, questionListByTopic, userAnswers); break; - } - case (ONE_PARAMETER_LENGTH): { + case (ONE_PARAMETER_LENGTH): if (commandParts[FIRST_PARAMETER].equals(DETAILS_PARAMETER)) { ui.printAllResults(INCLUDES_DETAILS, allResults, questionListByTopic, userAnswers); } else { @@ -87,8 +89,7 @@ private void processResultsCommand(String lowerCaseCommand, ResultsList allResul } } break; - } - case (TWO_PARAMETER_LENGTH): { + case (TWO_PARAMETER_LENGTH): if (!commandParts[FIRST_PARAMETER].equals(DETAILS_PARAMETER)) { throw new CustomException(MESSAGE_INVALID_PARAMETERS); } @@ -103,14 +104,12 @@ private void processResultsCommand(String lowerCaseCommand, ResultsList allResul } catch (IndexOutOfBoundsException e) { throw new CustomException(MESSAGE_INDEX_OUT_OF_BOUNDS); } - } - default: { + default: throw new CustomException(MESSAGE_ERROR); } - } } - private void processStartCommand ( + private void processStartCommand( String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults, AnswerTracker userAnswers ) throws CustomException { @@ -153,77 +152,78 @@ private void processStartCommand ( private void processSolutionCommand( String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) throws CustomException { - assert (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) + assert (lowerCaseCommand.contentEquals("solution") || lowerCaseCommand.contentEquals("explain")) : "either solution or explain command"; - boolean isSolutionCommand = lowerCaseCommand.startsWith("solution"); + boolean isSolutionCommand = lowerCaseCommand.contentEquals("solution"); String typeOfCommand = isSolutionCommand ? "solution" : "explain"; String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER); - if (commandParts.length != 3) { - throw new CustomException("invalid " + typeOfCommand + " command. Format: solution TOPIC QUESTION_INDEX"); + int commandPartsLength = commandParts.length; + + // checks correct number of parameters (1 or 2 only) + if (commandPartsLength == NO_PARAMETER_LENGTH || commandPartsLength > TWO_PARAMETER_LENGTH) { + throw new CustomException(MESSAGE_INVALID_PARAMETERS); } + assert (commandPartsLength == ONE_PARAMETER_LENGTH || commandPartsLength == TWO_PARAMETER_LENGTH); - // check validity of parameter - String commandParameterTopic = commandParts[FIRST_PARAMETER]; - String commandParameterQn = commandParts[SECOND_PARAMETER]; + boolean hasTwoParameters = (commandPartsLength == TWO_PARAMETER_LENGTH); + String commandParameterTopic = commandParts[FIRST_PARAMETER]; + String commandParameterQn = hasTwoParameters ? commandParts[SECOND_PARAMETER] : DUMMY_QUESTION_PARAMETER; + int topicNum; + int questionNum; try { - // if parameter is an Integer - int topicNum = Integer.parseInt(commandParameterTopic); - int questionNum = Integer.parseInt(commandParameterQn); + topicNum = Integer.parseInt(commandParameterTopic); + questionNum = Integer.parseInt(commandParameterQn); + } catch (NumberFormatException e) { + throw new CustomException(MESSAGE_INVALID_PARAMETERS); + } + // checks validity of topicNum + if (topicNum < 1 || topicNum > topicList.getSize()) { + throw new CustomException("No such topic"); + } + QuestionsList qnList = questionListByTopic.getQuestionSet(topicNum - 1); - // checks validity of topicNum - if (topicNum < 1 || topicNum > topicList.getSize()) { - throw new CustomException("No such topic"); - } - // checks validity of questionNum - QuestionsList qnList = questionListByTopic.getQuestionSet(topicNum - 1); - if (questionNum < 1 || questionNum > qnList.getSize()) { - throw new CustomException(("No such question")); - } - if (isSolutionCommand) { - String solution = qnList.getOneSolution(questionNum); - if (topicList.get(topicNum - 1).hasAttempted()) { - ui.printOneSolution(questionNum, solution); - } else { // has not attempted - ui.printNoSolutionAccess(); - } + // checks validity of questionNum + if (questionNum < 1 || questionNum > qnList.getSize()) { + throw new CustomException(("No such question")); + } + + if (isSolutionCommand) { + if (!hasTwoParameters) { + // get all solutions + String allSolutions = qnList.getAllSolutions(); + ui.printAllSolutions(allSolutions); return; } - // only runs code below if explain command - assert typeOfCommand.contentEquals("explain") : "typeOfCommand should be explain"; - - String explanation = qnList.getOneExplanation(questionNum); - if (topicList.get(topicNum - 1).hasAttempted()) { - ui.printOneSolution(questionNum, explanation); - } else { // has not attempted - ui.printNoSolutionAccess(); + // get specific solution + String solution = qnList.getOneSolution(questionNum); + if (!topicList.get(topicNum - 1).hasAttempted()) { + ui.printNoSolutionAccess(); // has not attempted } + ui.printOneSolution(questionNum, solution); + return; + } + // only runs code below if explain command + assert typeOfCommand.contentEquals("explain"); + if (hasTwoParameters) { // explain command only has 1 valid parameter + throw new CustomException(MESSAGE_INVALID_PARAMETERS); + } - - } catch (NumberFormatException e) { - // if parameter is a String - if (!commandParameterQn.contentEquals("-all")) { - throw new CustomException("invalid " + typeOfCommand + " parameter"); - } - if (!isSolutionCommand) { - throw new CustomException("There is no \"explain -all\" command"); - } - int topicNum = Integer.parseInt(commandParameterTopic); - QuestionsList qnList = questionListByTopic.getQuestionSet(topicNum - 1); - String allSolutions = qnList.getAllSolutions(); - ui.printAllSolutions(allSolutions); + String explanation = qnList.getOneExplanation(questionNum); + if (!topicList.get(topicNum - 1).hasAttempted()) { + ui.printNoSolutionAccess(); // has not attempted } + ui.printOneSolution(questionNum, explanation); } public void handleAnswerInputs(String[] inputAnswers, int index, String answer, Question questionUnit, - Results topicResults, ArrayList correctness){ - final boolean IS_CORRECT_ANSWER = true; + Results topicResults, ArrayList correctness) { inputAnswers[index] = answer; String correctAnswer = questionUnit.getSolution(); - if (answer.equals(correctAnswer)){ + if (answer.equals(correctAnswer)) { topicResults.increaseCorrectAnswers(); correctness.add(IS_CORRECT_ANSWER); } else { diff --git a/src/main/java/seedu/duke/QuestionsList.java b/src/main/java/seedu/duke/QuestionsList.java index a1f994b380..e55b4071c7 100644 --- a/src/main/java/seedu/duke/QuestionsList.java +++ b/src/main/java/seedu/duke/QuestionsList.java @@ -9,7 +9,6 @@ public class QuestionsList { public QuestionsList() { chosenQuestionsList = new ArrayList<>(); - } public void addQuestion(Question question){ @@ -24,15 +23,30 @@ public int getSize() { return chosenQuestionsList.size(); } - // user enters "explain 1" to get explanation for question1 public String getOneExplanation(int questionNum) { assert questionNum > 0 : "questionNum should be more than 0"; int questionIndex = questionNum - 1; // -1 coz zero index Question question = chosenQuestionsList.get(questionIndex); return question.getExplanation(); } + public String getAllExplanations() throws CustomException { + if (chosenQuestionsList.isEmpty()) { + throw new CustomException("No questions yet"); + } + StringBuilder allExplanations = new StringBuilder(); + + for (Question question: chosenQuestionsList) { + int questionNum = chosenQuestionsList.indexOf(question) + 1; // +1 coz zero index + String header = "Explanation for question " + questionNum + ":" + System.lineSeparator(); + String explanationForOneQuestion = header + question.getExplanation() + System.lineSeparator(); + + allExplanations.append(explanationForOneQuestion); + allExplanations.append(System.lineSeparator()); + } + + return allExplanations.toString(); + } - // user enters "solution 1" to get solution for question1 public String getOneSolution(int questionNum) { assert questionNum > 0 : "questionNum should be more than 0"; int questionIndex = questionNum - 1; // -1 coz zero index @@ -40,22 +54,21 @@ public String getOneSolution(int questionNum) { return question.getSolution(); } - // user enters "solution -all" to get ALL solutions public String getAllSolutions() throws CustomException { if (chosenQuestionsList.isEmpty()) { throw new CustomException("No questions yet"); } - StringBuilder allQuestions = new StringBuilder(); + StringBuilder allSolutions = new StringBuilder(); for (Question question: chosenQuestionsList) { int questionNum = chosenQuestionsList.indexOf(question) + 1; // +1 coz zero index String header = "Solution for question " + questionNum + ":" + System.lineSeparator(); String solutionForOneQuestion = header + question.getSolution() + System.lineSeparator(); - allQuestions.append(solutionForOneQuestion); - allQuestions.append(System.lineSeparator()); + allSolutions.append(solutionForOneQuestion); + allSolutions.append(System.lineSeparator()); } - return allQuestions.toString(); + return allSolutions.toString(); } } diff --git a/src/test/java/seedu/duke/QuestionsListTest.java b/src/test/java/seedu/duke/QuestionsListTest.java index 46b417708b..96499f95e1 100644 --- a/src/test/java/seedu/duke/QuestionsListTest.java +++ b/src/test/java/seedu/duke/QuestionsListTest.java @@ -29,8 +29,11 @@ void createTwoQuestions() { @Test void getSize_addTwoQuestions_twoQuestions() { - LOGGER.log(Level.INFO, "startLog1"); + LOGGER.log(Level.INFO, "tests may not be in order!"); LOGGER.setLevel(Level.OFF); // disableLogs + LOGGER.log(Level.INFO, "This log will be ignored!"); + LOGGER.setLevel(Level.ALL); // enableLogs + LOGGER.log(Level.INFO, "logs are enabled for rest of this code"); createQuestionList(); createTwoQuestions(); @@ -41,9 +44,8 @@ void getSize_addTwoQuestions_twoQuestions() { } @Test - void getAllSolutions_twoQuestions_twoExplanations() throws CustomException { - LOGGER.log(Level.INFO, "This log will be ignored"); - LOGGER.setLevel(Level.ALL); // enableLogs + void getAllSolutions_twoQuestions_twoSolutions() throws CustomException { + LOGGER.log(Level.INFO, "Start Test for getAllSolutions/ getAllExplanations!"); createQuestionList(); createTwoQuestions(); @@ -57,14 +59,25 @@ void getAllSolutions_twoQuestions_twoExplanations() throws CustomException { + "Solution for question 2:" + System.lineSeparator() + "solution2" + System.lineSeparator() + System.lineSeparator(); - if (questionsList.getSize() != 0) { - LOGGER.log(Level.WARNING, "warningLog1"); - } - LOGGER.setLevel(Level.WARNING); - LOGGER.log(Level.INFO, "this log will be ignored"); - LOGGER.log(Level.WARNING, "but this log will not coz priority=WARNING"); + assertEquals(expectedOutput, questionsList.getAllSolutions()); - LOGGER.log(Level.WARNING, "this log will be printed"); + } + @Test + void getAllExplanations_twoQuestions_twoExplanations() throws CustomException { + createQuestionList(); + createTwoQuestions(); + questionsList.addQuestion(question1); + questionsList.addQuestion(question2); + + String expectedOutput = + "Explanation for question 1:" + System.lineSeparator() + + "explanation1" + System.lineSeparator() + + System.lineSeparator() + + "Explanation for question 2:" + System.lineSeparator() + + "explanation2" + System.lineSeparator() + + System.lineSeparator(); + + assertEquals(expectedOutput, questionsList.getAllExplanations()); } @Test @@ -74,4 +87,13 @@ void getAllSolutions_noQuestions_customException() { assertThrows(CustomException.class, // expect Exception () -> questionsList.getAllSolutions()); } + @Test + void getAllExplanations_noQuestions_customException() { + createQuestionList(); // empty question List + LOGGER.log(Level.INFO, "End Test for QuestionsListTest!"); + + assertThrows(CustomException.class, // expect Exception + () -> questionsList.getAllExplanations()); + + } } From 41971c2e5c9e2b4cc58085824f4b9a871d9bd6cf Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Fri, 29 Mar 2024 02:58:35 +0800 Subject: [PATCH 099/334] add topicsList feature (todo: add class diagrams) --- docs/DeveloperGuide.md | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 1d53ae13be..5503506f67 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -43,6 +43,24 @@ the `results` command. > return an error to the user indicating that there are no > results. +###Topics Feature + +The topics feature comprises `TopicList` and `QuestionListByTopic`. +`TopicList` is the list of topics for the users to attempt. +`QuestionListByTopic` stores the respective question set for each topic in an ArrayList. + +Given below is an example usage scenario and how the results +mechanism behaves at each step. + +Step 1. The user launches the application for the first time, +and proceeds to start a game with their chosen topic. + +Step 2. A question from the question set of the chosen topic is displayed. + The user inputs their answer. + +Step 3. Step 2 repeats until all the questions in the question set has been asked. + Step 1 executes and process repeats. + ## Product scope ### Target user profile @@ -55,15 +73,19 @@ Integration of key notions and learning learning objectives for CS2113 course, s ## User Stories -| Version | As a ... | I want to ... | So that I can ... | -| ------- | ------------ | ---------------------------------------------------- | ------------------------------------------------------------ | -| v1.0 | new user | see user guide in the app | refer to them if I am unfamiliar with the usage of a command | -| v2.0 | regular user | see a progress bar when answering MCQs | track my progress when attempting a question set | -| v2.0 | regular user | see a progress bar about all topics in the main menu | track my revision progress for the entire course | +| Version | As a ... | I want to ... | So that I can ... | +|---------|--------------------------------|------------------------------------------------------|------------------------------------------------------------------------| +| v1.0 | new user | see user guide in the app | refer to them if I am unfamiliar with the usage of a command | +| v1.0 | student new to Java | receive solutions with explanation after answering | be aware of the reasoning behind the correct answer | +| v2.0 | regular user | see a progress bar when answering MCQs | track my progress when attempting a question set | +| v2.0 | regular user | see a progress bar about all topics in the main menu | track my revision progress for the entire course | +| v2.0 | student going to take the exam | access timed modes in the game easily | train my thought process to quicken in preparation for tests | +| v2.0 | student new to Java | avoid memorization of specific question sets through randomly generated practice sets | I can ensure I understand the concepts rather than memorising answers | ## Non-Functional Requirements -Usability: the user is able to use the app without reading lenthy documentations. +Usability: the user is able to use the app without reading lengthy documentations. +Technical: the app should run on both macOS and Windows ## Glossary From fd99b5b7f2dd41c2efecb0779b7be42afd43cd96 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Fri, 29 Mar 2024 09:48:36 +0800 Subject: [PATCH 100/334] docs(developerguide): add solution feature in developer guide --- docs/DeveloperGuide.md | 23 +++++++++++++++++++++++ docs/team/img/Solution.png | Bin 0 -> 10079 bytes docs/team/img/Solution.puml | 10 ++++++++++ 3 files changed, 33 insertions(+) create mode 100644 docs/team/img/Solution.png create mode 100644 docs/team/img/Solution.puml diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 1d53ae13be..546f9217a9 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -43,6 +43,29 @@ the `results` command. > return an error to the user indicating that there are no > results. +### Solution feature + +The solution feature either prints the solution to 1 question or all solutions in 1 topic. + +The solution feature is facilitated by ```Parser#processSolutionCommand```, which is called by ```Parser#parseCommand``` + +Step 1: After user runs the program and keys in the user commands, the commands will be passed to +```Parser#parseCommand```. + +The command must contain the ```solution``` keyword before being passed into ```Parser#processSolutionCommand``` +![Solution sequence diagram](./team/img/Solution.png) + +Step 2: ```Parser#processSolutionCommand``` will first check number of parameters. +First, it will call ```QuestionsList``` class which contains all questions in a topic. +If there is 1 parameter, ```QuestionsList#getAllSolutions``` will be called to get all solutions in a topic. +If there are 2 parameters, ```QuestionsList#getOneSolution``` will be called to get one specific solution. + +Step 3: +To get all solutions, ```ui#printAllSolutions``` will be called to print all solutions +To get one specific solution, ```ui#printOneSolution``` will be called to print that one solution. + +### Explain feature + ## Product scope ### Target user profile diff --git a/docs/team/img/Solution.png b/docs/team/img/Solution.png new file mode 100644 index 0000000000000000000000000000000000000000..27491ec13a337628e798969cd8249dee06e474c1 GIT binary patch literal 10079 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 XBXfKw{V8M44p7NTDN1IEKX>~d$&v`! literal 0 HcmV?d00001 diff --git a/docs/team/img/Solution.puml b/docs/team/img/Solution.puml new file mode 100644 index 0000000000..c9d45c46e4 --- /dev/null +++ b/docs/team/img/Solution.puml @@ -0,0 +1,10 @@ +@startuml +'https://plantuml.com/sequence-diagram + +autonumber + +Player2113 -> Ui: readCommands() +Ui -> Parser: readCommand() +Parser -> Parser: processSolutionCommand() + +@enduml \ No newline at end of file From ed022fd1dd784f26e8c8e1274eae2512377f8c29 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Fri, 29 Mar 2024 09:54:14 +0800 Subject: [PATCH 101/334] docs(developerguide.md): add intended explain feature documentation --- docs/DeveloperGuide.md | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 546f9217a9..d74acf7b65 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -45,7 +45,7 @@ the `results` command. ### Solution feature -The solution feature either prints the solution to 1 question or all solutions in 1 topic. +The solution feature either prints the solution to 1 question or all questions in 1 topic. The solution feature is facilitated by ```Parser#processSolutionCommand```, which is called by ```Parser#parseCommand``` @@ -64,7 +64,24 @@ Step 3: To get all solutions, ```ui#printAllSolutions``` will be called to print all solutions To get one specific solution, ```ui#printOneSolution``` will be called to print that one solution. -### Explain feature +### [Intended] Explain feature +The explain feature either prints the explanation to 1 question or all questions in 1 topic. + +The explain feature is facilitated by ```Parser#processExplanationCommand```, which is called by ```Parser#parseCommand``` + +Step 1: After user runs the program and keys in the user commands, the commands will be passed to +```Parser#parseCommand```. + +The command must contain the ```explain``` keyword before being passed into ```Parser#processExplainCommand``` + +Step 2: ```Parser#processExplainCommand``` will first check number of parameters. +First, it will call ```QuestionsList``` class which contains all questions in a topic. +If there is 1 parameter, ```QuestionsList#getAllExplanations``` will be called to get all explanations in a topic. +If there are 2 parameters, ```QuestionsList#getOneExplanation``` will be called to get one specific explanation. + +Step 3: +To get all explanations, ```ui#printAllExplanation``` will be called to print all explanations +To get one specific explanation, ```ui#printOneExplanation``` will be called to print that one explanation. ## Product scope From 0b0de6b099207226d78c740f2ee3ea1fbe55a867 Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Fri, 29 Mar 2024 12:34:14 +0800 Subject: [PATCH 102/334] add class diagrams --- docs/DeveloperGuide.md | 6 ++++++ .../img/QuestionListByTopic_class_diagram.png | Bin 0 -> 129643 bytes .../team/img/TopicList_Topic_class_diagram.png | Bin 0 -> 67111 bytes 3 files changed, 6 insertions(+) create mode 100644 docs/team/img/QuestionListByTopic_class_diagram.png create mode 100644 docs/team/img/TopicList_Topic_class_diagram.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 5503506f67..ad30fc8af7 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -55,12 +55,18 @@ mechanism behaves at each step. Step 1. The user launches the application for the first time, and proceeds to start a game with their chosen topic. +The following shows the class diagram for `topicList`: +![TopicList class diagram](./team/img/TopicList_Topic_class_diagram.png) + Step 2. A question from the question set of the chosen topic is displayed. The user inputs their answer. Step 3. Step 2 repeats until all the questions in the question set has been asked. Step 1 executes and process repeats. +The following shows the class diagram for `QuestionListByTopic`: +![QuestionListByTopic](./team/img/QuestionListByTopic_class_diagram.png) + ## Product scope ### Target user profile diff --git a/docs/team/img/QuestionListByTopic_class_diagram.png b/docs/team/img/QuestionListByTopic_class_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..600ccc5cf41e0eaeaad9b8bed67deeb49b363dec GIT binary patch literal 129643 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�!!StH^veMRMz@%1+Qh{ zd9SrJ10QnOLdUqXJsdF%EE#;0w&|1i^<9gBhwECP2%ooD%pcLljIBrT|^HiFR+!EtWrzv_2p|A?&`Sicuf*!6n&2M z2?@oTyIeJ>(-iYXj$vy@aRpLJ=O^CUN^yb9UNg>m_kluhq4 ze&lO-8tC`ep>0w_y(AJwFqJYO?Dz@JhzO2WCnR`~wfS2;P1+(HO~$`MDAD3K!n+?b z2E5&v{zQ8BL>>T@;if*vqn^G3e}{qpp7?p0b-ZwTnDd~_5Aofu~0No2^$il_Y%@SR>=(zSaRAy{Jza- zrNVOpwOUlj8w`NkRlE0YTgPzarLZT`#-^@WwWRmLea8|6X_ucG#&fOM4@s~>V+iT* zy~NfGTVa}c*vUtpOoOG%6Wo&}wtd@s@DrPFbC>eVyt|E02z5V6WvuHmM;+)6?~eK8 zqX)nUHLR%yONbZ$V9VT~S!~2OPYZLhj%G*nhGn?kltHn;q2SHKMeF4}Tw&)PKYK2` zq<_0_JG)6=!&fKAJd#>fhqf_j^T^rD4e|=V`22%eWsCds$GTrAaT*(n;P5F4xqW=o zrr&nwhx{TdI%VI=D$Q^aiZ<}0wso<Nbw3`c zbS*>y>gZ&4;9P+Auu6SP!)bzzf$po7;QnL1$_EVC0+zQWkjtobqSNpNd(?g_`(AR) zTY?~~-mdlTruA<@P5TThE#z%Pho_x=axO~W{=@MNuxODtH z08b#M-pC+}(2pgxGFOUR2J(E8_ecH+`8dZijn!svVWXQ>F*rtwPCw^;p4(B)Pv(#;zGQRY?6ORaCRQHvvp%HX^YTsWWG!vj1y`qg{C`}7lBDE zxkgMF7TE3suL$vUwzCl=R@y;8x(fjoIsy4miI?djQ|Zw@eWgBq2?}8O#lW}+*&R{9 z!sr*Fc_jgS^WRQ@%Ghu6Ku`-v%Spwp$N>h>sS`h6HPaQynGH%w@S<7$b(atA@gS(Ma760Lb~ ziS~~9E+sceF#HUWlSrGmIbGu5s~>qiNu$v2w$0f{1?9l@2haLg#nFH_;P8%pptISX zf{m^NvNmQz4@EQpkZz-UZeA$g9YHr0_an<~Dbc6tP?EDKaaq;(wgz#Vt7~EKs@>YV zc^R2dMekrl3ruRM|{2flVPv+?z7bmmUV92 zBZ@xTdZjCM0)^FYdWQ=gv`%io%)eHvs%<4Qz>Vfx zUAMQn>(Dm|&-JKW(>;Cq<%=)p1)!SCHl9R!IZg}qWftQF)%RJc+8W3hpHL|qrDyBQZ@sp^8cQyD1@epLn9ir}=9YNMS@A!?G7rx;@xL=g} zp>(I8qf-dA#Lm(qfAX`fmB}*SW!GUP;FWZ1yLgj7FtXz0Giv$7w1!Rr=@73CdRZI_ zyWdQ_JDJ=VmWR>lc91LFZ7x$6&eMCy|+0B1z5-gMv<=&fiZimeA$PINV4N!qsJT>|j$ebNL zg6m8J$_#V2qS>)5ATRl8S}&ab^v=Y33Ed@eaNb4(6$Im_n9g{8VG43>`K1Xmgd|fu z>XiORfNxyhTqN?FDGFrBC)-!zQ`<6BX``y+_f)_yswkmB8(h5Qno!?HHQ(DE%fj+2 zIJ~f(XMIFeNV>;b4mmX!^x7zgauGH9M&|+B|c7f()pqvJ~jHz8os96m?EL3$L%V}K)3nXWVOiJes!(4 zj-#HS)as%*ygd?NWPoK}XC1zUrDJMg?@Is2GtUt02b9TDn%UG_Lm zLtTJ!PrC2Ih`~Cr2qtj2{LowNX^IaCn)8LOZyQX!p}BnBfk4b|0A95@*xT_^PJb zInr3CMO?fs80=rKT^M@PBL25O>cpz(S=_9F`a|6X4rX>k- zKJ~7YXOVG+3knMHyY|nVG=e&FbDtEmne~4eq|V2${hAUCRjeu{5d(?6tocHI1CB-n zdCrr5AI7>zIV+ep_Kl^COG()nP9>Hhl~e6v2U!_@>D`gs%#0|`2pN9-rT;vB_R9*X zI>`r!un%rt#Hx4Huhij)gru}_Zs=`p%FS2;zK_8uu0vg&=jFEGqiF9771 z8~;fM@~yNc^f~iI=2Xz;{jg2YzlygD5S=Qb!s&{Sv0XECAn|=_JB(iOKU~27g&%|w z)Mg@$n0GCcciwg!scP;XWd&@C^eczdbY}~iFExs( z{rE9D_-O0ncV@klE!Sm>M9UbPw}6#_ZMm2*W4f*roK|a}TL54N@DLck&~tfcRGn{H zEOw3(=1zr<-MIklAG|+HkH+Xpe_VL(f8Gjy^U8o`=%p{$612f#cenl=4Am8YK0vW& zSpzOV>W7jJEioat=5L!w<4-k@6q>TMl(}LAt?JxQ5;WuvPPFQ~L@xLF4LdRE@8(ZS zIttgf7;pz&tyjyqzcOGfgJ9YX3klz%Vs)zNz`GG4`W5p^Kq}(w-$l{V`DeAanH1=T z2bc8CY8J|-_kQ+V-a321=ELI1qccM{{djmsZbw&W@k~&xt9nFGR1F%Kb_YmL@NVX- zYgS-TPZ-eZw0s5-fF;-=5zoak`HI6f$3wpj%;qDQLP|pY_kzy~_^I@?*Ha)dOy-E< z!(TO*=Cd>PE+>CDrW+8Qws~!^dJU=tFdS?09a#NyQ*uMq^YOJ+Tc3}QC2qTJz({%z zN7FtZU-@Je)(!T!_k4MIN{nuOIt?5xsMPhw2N9fbOOU?HnXDIq49oYW)=x>yc|Yjw)qhk^^!!LZ8M7 zOT~tiwMD8q`;l>{)`k6zN^^ihR+$@tCJh%MO7)Oh*p^gUyW|MHnoXVfa2RDIB_$hOXC z{^G#HKQUn_OU66=Uzc>B6KLD1T|?L6y?3;u;Bu$BP0!HfGc2G4^~ zmnshEQI(%poWFjxFbFcttJv{FvpHG8%=w*M^VRRl$3NCu(9rAqz&qqdiilVhDZ z!#|8ML4mfTwPG!~juyBi@w7}jyee$NqTmfZs^gOAxaysv2aE2< z`XDYG7|Ue|4z46>`}7ek0Q9#bx3vJRdQtfS5Iwi0 zL{fhSmv($U;==J8iFki3ZDO|&)A9@aT9n40?)ia`CsI_TWNS(^#J>CWBmr_T9Q?K> zCORxucquIS8Nnp@p30OvJAPQD-&{y3zeE8XIFth56!`S(T3sbmTudz0<1xccN%gDE z&TL}3>dafUn)IjlCenA%LN$1clz8zW(i!s0>cI?e-Lv?dW%;^+C4(n;eRdjy{@&Zv zZ5B*`N>uM$%J}juB6c2Cl@OrNC84f2LvH95v|A?_c-q@jeHbH2=dzf-nrTnV_k-kS zx^*Awy9UN?6~*&Y(wE+KvPhhl5^g?nUbGgLc}U<|v=J62Z=JTCQ^Wht<1q)z*M;=$ zPYoF_t_$5ECcb?(?NtGr{|OV|LDLHcRKL^wv&j0-bc#1#AR?G~C=D0SE%=Zw%j95) z5w_yD-u0nG@JG>bE!8cpSL`6e*7eOr7nZEKI{|l;aC#koHCtaKO4wOZws>Dc?*+() zmFX2WGjy80!;o+{f|wRJ(E;~7xfH1;Dh&UrBYg6)r<~Vt@{`h!h3$voKXb?Q3RnEk zMltZ%l9`MFr&u{wrIo6;>z@0JHF>*%--X1HT9~5C3S05 ztLYT>`rTK}r+fg04m@EpJVDXE=uvF_aApHA1a744iZl+M;SE@GMrh@4v`go`@t~xH zyf#0fZi%|gs2^27ijc+-Z!5{IV?u}%^`gb8nw$#B4@L=te3SCvCP#T=V_Mb!TE8YxKBmR?Os! zX>HYvb|IyDdZM3f=6^Oyoe=pex$H7euwS&FW836FTDX*E6V~%P&-Yw-V5D=}CxL8S zztPyFYz6XF2cb%9+eF~ri>xo58gP}HaI?DQz1KHw>)&0r7UGzzyVgknvhlcJUfUjP zJb5c4LWe5z5O8wsp%Z4USEP9&{hag`dF}`QKIvXMWRxzY8kRk@X^6KG-aUIj&*9|g z1sPJY{qQkS*;JIMB%_TW-Q`C~2+WGr{R!?S6&j(&3aB{a`@f7o&VOLE`91x|Uy?Ho z6CI=K{cbcnzw^VZCOMpTOZx1gimB${SV1doh=QYR@Lemv;7*VJ@VwNksGFPI`tD6bOfv50d4tq?Y1BPzVrKx{(yL`~ zjbSSG7_@Nx0M3UWfrz?B;hjH^9WrY6{DeB=UeVIseM%TwY(0e{lRqxs40kmiG{Kg) z$DGoQz97Z&lC&KO5`COQgf!7Gf?)hOz9ymkG(imFQ>Uf+)1{LM2AGUJMZE*uAhQwQ z*uEEIsxngRo81Y+)+zL+7?ybn{~W&`^C|H84f0rjYnxa?T18lj_Rl$92Kh56>-;&wOQ`TW0!P#buu zuS?dRPda*$(AEE|Y&A^2OwEqpx>yICy6!{GoKn+|C%5g$ZrMfii;eP0Ki-0lvj{7j zPiEtuecJx+Zl$=3V89=QpSNe8=j^0x75>dLKalk5QL-?cd-z)No#6;V`aCfm{ty1W zRG1=g3olOti?@2U_1vxJhO5lI_@@IBu$8<|@kuHm<%5yWa$O4{yMgY{;Hb3rU*c^( z%z-}=t6Sb9nisE5V5x>i~@+%`Ffo#`L0p;Q=IsLeeSjSm73 zM`Uy|z#5!|rN&XK zrhetR%v(aXwu|kjSJY5#odDH=84`FHxP_hYm5~I#xxd&{&U-nCF|HMjpD_lVc`$&A%-};k8X1ySky7_-oVmf&)CyQ+>x}i93;Q{fe$JVvW|TE?n}cLN-Z;aLQM06@@|o;%hvbZmb-d~8V{u8YDq-9Nl!oL?SPHJ_r$ z4PixHa>#iz9LcWnTygJkr?owF*E+lB2juNR>3}L}S?alrb z6Kp&#jUDFfN`rcxU>cve%??)1`|82GtB#EbLy8G@lUvv=khQZ{K9N;~VDxbG=`4Go=N^>VAU$K>O;5K8 zE4VQqFnw!HG#|=!_Fs5@A`GItdB$i}N>?=XFMANa+ma9*RX>_>Kzv~}$Gc%ZHE#D| zuB?QY4aREtEwGf+xANpIxzzZ}hhUGNMV85*WMcD?RM&tuTLWb}y!>4m?-LGk=| zeC}lTR{Rc%s2e{x7EOlA71qI|{iA;4GTOaA)L^b|7;4}xc{cYH^aZ!vYV&yRiM54j z6If7>1o{l!bM_587v#5?vofTMHTz1LN2-E|g{<4%C^PAe?Ap>ge9_R#hYb~S74xuY zjD|Yh$b3m2_Lkkt`!LrDQ$f;(K6Z?zxB)#>tq4tHUkxX5)Pt8`RpB>HA z{k?fL1*wkqY@UxeeG~@1iCSZWy^IT@LZ&AJIzIMQkE|m*Y`7f4o~lzD(lc)hk506J z#CAoYhH+8-v;gd1-k`m^QgT9)(6Ax}gLEVNgkMw&c@35C#rMoMqii-xG`~nK=M^KE zVt7${j<)YV`QPIe8uuAQ&da@LyXgD9PHctfnyG1htCGITlN(n?Wq)H?K8^WlWz9}< zKPqe=>`(EJ-0sy-wZP>$A1X9VHqjC9mv-z!q%H1!9 z7o&xkw)OLoTc{cL(K3uL0c}3ce>@-gZ^K&lIYDQ3j0Y4&ZP0Q$^b0J>?=6AzSfWecUi^054gzw6ib_x?0d z5fIaw7mjw1qFLo0%>&e3ee&n2P;Cj>J|^unJNwbQnYFz}^CR)k8OPt(17e=8Um^RR zS%;3>lW*C44$7VeU#3*kKELP;h+yCkc0AnbL}zA36x#PzJ;r&h#rGqtZ3P3?X8-O^ zt3Zqo_5V@oX`7U!{7}BsA)~Plkv9_(NHs@RQ%X6uzoB3&`(qUfIJxjgL+1!X?^(rV z&X>x0WqFT8T|NGh)sEjqs%^c~ZR9eqwMYM*+$~z6uB142e~bk;9#H*=X;6~-6DuOpw#Ht*T5^x-SazR(P4MKCgkIg zH-R5mbO9$S$lCz!mc3%Ic=yad0!OChQ33ix`;gqYk!iHH}Sy-3xi{#>at23xBmjJ)PlogF86JE z8}vmtgbyUXO-R^@mMuEA#AGT9-K6NqksS-m?hKx~Rl3j*VEmDA8XAh}Ej{gfG&WRY zN!&fV;fvq~TDQx7(a{+q;Ii29S&5tR-sBaq+kRwlJs}UD4F9FgJz~<32udKtv-Flo zfxVYs)+%**R(qUO8OS|S8*DMi-{_?!xrW`;vUt2aCc4%YFfDC;R^vC4BbKV2+0?IQ z#bw<2mQP5_>x~f|x7;I#K^{lFHp?NB|LlTMmaWBOU)^voI%N5FB8{L{{m1zB6k0Cu zIMTlQ4X1_-YD}9a(#C=TItq&zJ=77 z48T_KLtTOX>5B+G(UH%MR);HdKjv*iM-76fU2(PKC2P{l-VbE3(k%fYu2TfUH^W!{ zhn$D;GYU<(7=zu1B%kN4fePQg8@&ed?`mx=SD0_UM%+qfh89ER9|4t@;v0}u*mk~C zG7kNp9uTTaSP-m&O#c2`GgyM&pm7rGU;|ajU3DV=x$R(|e66#vWc|rDHw;>&i?d=_ z43uRV_0(xW!kp}5paM?Pbp>n47mg) zl9KkE41IDd`5e9CPZc8W@ooNug}+5i^r9?*5@I${xP9R6x9|khJP3CkmO!^J2hojg zzY92_lredYB_V;fgz3lh1BEv#U?NT&i=~=SjNv#g3 z+P-s7_hkHwQt3@uBEWgNS}x85_K;v?GbuXG1740bTsx%tAH%P!xGnItI;h?x-u2j_ z9a7Tvn2u`t1>WW$_|oX_;_t<5*`pfJ2S_U9Qh8Rj=ZCkzMvO`6qF*W3Fz342m*Kd1 zYE|U-0CP+pFWoWJ(ATzQN_hER>Y^jff2qTwXKQWbMB6EbpalHR0khBcgOlJclJJ)R zduEH>tq0ECF61;wIHPNar%XD`G-eoNj1!t~}j^1E-RZCB&$-OH&KDpV(O zI${2>p&Ovl(Aq!P^1yZ;@;D>s5885Qim zwA^$A5TfXbNk4(_2upt3bh6b^vv4|&^ zz;x-<;WQObjNT$HO^%EwK^avFsaS_DZIks%j&O-u)l$XrD8Zcx5Ar2C(s?hZ8Px6}j6K_ZZ*2p>Yyy((`?huaE=QkE6Rz zI{fTXmP!b|EGW&fkWop*@{7H4E;7n@z+YBs{&ep6kta?$E}bw%Zw>a$d&M;Z&((cQ zd;AhDt80iL!7s%nakKN@3rf?r)4>i0GLNYW1yUPr1zB8>G0#?0T~K~t|dKwQRG8A|HmF#PCa`{ zmO`;q#(jR$W$<#{teUOghA5Kr2{V;1LO{UC5L2`}JJShsnbnZD3t)n=&sO%X(1!y` za(m^;{lG_`qFON?Hg1ocEWR)eh_LuaT>KABk=i(6$9t zfAQiOdDZBGHbg7>i@3w5n`3SPx^+v&z>0TL8UtM`Mhwsw^IqXxf3Q$FLq@>3qDG*wL3tosuh&Ljs@3V;K{I1R?HcGAG|ht2q|fm0EdE_J^Fm zGUI7&@CAG*;QdKxtbcs7ubEc2rAoXZ^!DgO%t9-4I*mFaM9iA5hzWRl)DSc;}K)=7hESz&fe^LvTod&zuK<-xs%Y)p_JPQ9d|^pZYfU zlQxrejgtGqZl&U`%X#xb$8tA15IPxn-Xfv=g$J-Cf5CpSOeEH%!aqy5IQ~2S4<@-2 zqRhIQ9jBKC5=Gorjctf2S-xr8bGjVfOee>&;c+j=3^Pb|b~le*M)7R7S!n3wQt^D(D06YWnR0(H}u?e=ymRNVryk-Zj=4yTL64?GVEqp?jY_XUKB=1P5+1VhCBu9~;Dsu&bEgt6j?a zYPk8K@hwNn-iviT2ezQce7{HXw7sO68Aau(?!Z|4V0ReHuPgQwP9P(_P2SGrtDtLn z5cu8Fgy8K$3yi#2+{z)7v}1f)AE;!#EYP zk`UdT1|xoIkgF0SxNPK_Uid9(d(jtWfofpdTPg&%qN^mu1#|n5SC$g*F`Pu_@lxG* z&Xr1=*6%FAC#jYnIZNxprf;tWsz4Kf#dZd#Wjt;|@%o7AlpyaY?N{$#;^e#n3<-{v zEm}SZEj#WmoYg1&79HgpR9pGYO$)Mi#b}{!>+omb$1=tApQDzn$nt^pq>-IsO<1WQ z>zVK?i^K( zI-I8`EHk6r@^|*;Si5$`L={L<&x1Dg`tb@9q{<9Rgcvcs#fyT9ocYWm81LvdH8|LF z2ZOLt`fBzUhs8fxc>gD@N-R1E{f;lyHw7k5R9nh6L|?ezDCh|wDKln=!W64 zb0N0Kf8Q|A`yvWQU+?vdexwCcA^yb!zN4eh5YWO;)ftNUS`mr*9?}XqgUG@Ujk`d6&JjV#dG|5!m=1r zgF3#lUZlpZ0do2BtCi}H)J92CH&h#*`gYT}y&dLatE1?Ojr!D7C&tvrW||1}xkX)V z^}5dJYksODxANB|ihXrE)_0^(#fpo%Qr2I!g*@Y<9d(Nz`5HAqBK05fYjqpHR!jXWOwd_fax9{}6=LfJ@_oDB>wW?!q>@Cr_QUShiLL7D6A6M8S zJm5c}re2Wi@&4dz@rb00upz zEb&z`$nhw&6i99u*^>=f?5ihbVosnJ3R8*O)~k{<763Y_Lx@0NWms}0a#>sxz@v@( zcDA7dtNq4M^+pt{iAtaNS#a$?60RBEAbuj2L$MH{=LK@=k!*E>8v>)yFR(JG+_y>R zHf$E3IYVJB8$9pz%Xj{o$Sa<6XoV$yuO1ZIYIP#dqqmG-g>#xde1jo>EPma_W=v#? z$!+Yo(b%ofgU;VAN$!w)90PM4(kVELi=Jw^4Sj)9N-_O!{VgmJQGJ0O&C(+#WY1^i z5}2|-fel2&ui~0hU(mpz$>QNDiZEPQZ$fZcO()~QhM{0)1Fp;gVd&uzwcP$&$nXF+ zHwJX!AA$dm zruPn{@_*d_Ngc|;!3*aYhl5aLkL-OYJ4N$d5ys$>|&E-3@Rz6Zr8KPm~%)k05ch)N!VdO#it=`i;BB`Eh z%k^JwCQti>>y({rQ>jq7?Cx8)Gf?}p!&R|av8HjM3Aj0xAyojf2uck3V@1Jwfb@= zj*EMfuOQgQJ5xNBOzl%7fyV(7KJlhxM9XdW?XTyG%ld+eDFV4M>+9 zYt@?f=X%z^{)vb*rfaZUn&}fD7qO?9g2N#an|!E4Xlp4346oVU@1dyyb=~^85B*W& z26&B;%2Z9d?BJJ&M@uipkUvZkV1{wAXY~$7jG!p zFTLureme&Weqd%{va1_=qLow^>4a1IO@MJ8zm?>w`FaRJs|P*HsY(93;#E^8v&zpV z%prEXe>xW0@r%}76?%L((Geg`bev(1%$DF|IK2?8MSD5@46fATLEh*E(&QS#^P`^h zrpW^NR!eLWm0FIc&bvu@Re3GHnT(l*AuY?b+o~UP_|gt{62fc41<#$xSc6pk@e{)_ zep7ov5;Wk0XHggg-dY@cEpk)N&X#)Al|zPZ44-fq|As8r3R1&RELo|+p%bBlVz-%c zm$S{kTl__JZFfxj=|=<@vl<*0m6;cC7c6JzRSln0jHHO9Q*#Un!`?sN;JR6Ozy0N) zQkx!|t&Xj;o7^26Ij+{%MaQnRFO&FDe60T+*2JqVf3_}DCvS7)5x)!mQjt9eQD5xi zq+FWn{ns59A3OX}!hg)9R&(Nva^hMeR!X4w-cb7MS|~KxxW|rf2X9|eJ^HNv-JkBT zb@072h@+&_SLQ4&6wTJbi6qo{l1Wb6W_11g!7z!+L}mkRoxSX-6_leklu_DSJm7Pi z^^(1e-JzQBtl}i8SgUTVN=#M|NfDKV*<)+c@Xr!*fOn-Lps>7~^>KUpG*LNBy6mZW z-v_f^Thp+C3{7riGKGX$pW8%c7k##~$9-0sRo9dp=>Iq@#Ia4SI>`r%xDQV7tix2 zem!LDzV9glu6xzt&o0ZBE5W|{*CQecQd1?CtZ=q@H$nY*`>itrE0Ch(m;4poW9_`J zjI$Plm$e=FOa@5S=cdUGcizJk(Qz+V&F^uENEhW#E43YCYy5>=3EyAarzJI7SOis!k5f6 z!D&UQVtW{28BLl=nq~Z}t zy$0gf&VFlNBL3amqM*8c{Q=Hcr(%aSIiiJo!}PYsjkA!KTobL(GHFXTZRa6#YCA+Q zPjFvAAPv^|?oPx zvJRLo%U4Mf4#RdS@#Pk^Vx=0taeWH(OO{(zx9p!k{N<|#|3y3U0nvWA{St%!&H6?~ z&_yfuZ;qkI7M~A}`BbL3Xn2V66a;Atx0s^5#3i>;?>>5wqJh&gCL$u`3I)GY8Zc>U z%c5$GwRhG8lEYpgjrMw7dDm5_ra1E^lw|dFt!Rib5tsP2je9rF?{X>cd1qTCNr$?d z=A?{Wh+XnWj(Da6qmvrzaRN=%l?1ZOt(A#aQKhDxzap7WYc&H3Cun^hJD>(1Y+sj2?4xJ=^%kIj`&LLV@%zNf(Dn$l zRjd%TQJgs{PDc#PdGE4C9Ug{^elKUUM)BpysyvrT9`&6v(3obkK|SoBd;7XicRd;9 zb)AVLJBd$z>z0p*J<&l9>){r)&>Ik!`Ma-4#2Ew|g2V=`Y4HS}uJS6Hd{KeJ!<}%I zI|?Rz;u^*nPS0ravbTV8{<`R6@~_j4JS$(m&_LQD!_hEt*gK=;jK)A!P(kQc=ufkS z_XWt~ZMK~JCcT%7G$bFe)s~WjTESFpOw2iT9XJ@Sc=bDU}jU$pCl!rYdZorK-tSa@J`Raz-YvM{qpEMs?Xo;P@1&{*CPAS46InVoH4f0>~(jVq6-A;Ss zwmqF6p^d7#482EZmlvQ6r(Kf85L9Ijth7PPY_IjjXn+G~I7%Fp$-Dg% zj@(&Kf^vfLXdT+R3Ss>^u@lYFKLX;~RO}P#?}1c?MTpZTAwYfJfqOU}@tI;RMucKB zANPSyVc%eT20_t44Hzt?vaw>iP?{b8}MQ*FiAqXnhNCTe64?81u( z;3mXSw}Z>HQJxhtaQfuvE*5HHk+GVakmVVWoXC$un*OE6cKzd|p-6#m{g|WBdnMeD>ncUk|al!+V+6a#XK(ee$yTAb3zvCq+8a?-KsQbe+MbhJ9c`WJ8-T#-V_1!W4&yi1a@}&*PG%AAH zU0=v*i@E8bRE=V@jji7G7%6qd9Jj#qHcblE=*>mmPoMr*%5>$rz6T&BP9T=Bi+ZXF zc6Z}!&y8r8mDPkYEeQE?2Dy-){ew{E_djAr*SM(876+e6fmrZ7tthie5x((H0gZ9{ z?wP?xf9q~EAPTm&g^N3uo$14QVEefj#vW*^7HdgpgJe(#UfsLAdgtIZ58DY(;h zO=dI>IF7e=bzDq;(~nH;UF}nX)bx+M=Ah!*y4t@E)KPhW>()#cA$|jIp{bWd8>`RD z>OW*VLD^#HPMM#x91M{`@8*m+vx)p1rx2i?$r?9Fkyk9Q7h!{+#4c!BZx@CY@sT=lmi0gLDg)m2X=$OP5cgf!aDGKHx)cxczq zM^i11pQyABy8a^L32vPBc*mUA*$m?eKEd)N>!_&*spKxTPxwrVd8(i#7lIET<{l{t zt(G|XmgzjRqA*1dz6&PQ_*K5`*w{91Ri7=;aBw||<*9e~e)#QjNHv+z>WWMMyZM>z zIr%0ogb>xjaO>ZuhN9`W(lO;1>tcE3lj5NGs$DC>8RMlaPKNF>;n5$SI=_6Kp@omC z)5aXRPxNr}VOnO79FNroP!R!CoKwk-MG8Ok_6X3R!q8;yvEJ1lAk0iQ&~ym*6^1%j&qbo_Fd05}&+axu zx{#dO86{h4`1fqLx(Byee~)YNVs+58X-;a)^{U*rX$<96dXzf}O7$7z=qcrjzuA|S zH|=NL(taK9=pQo(KNaaT5FC4`YW4^OG*IdhAzAOL^I-aAG%e5nd{Y__N%x>jV*>L2 zm_*%t!%aRJ8nWr@Wc>gcAtzhJ$r&aLFK-rK`gni1;Gi(Ex1^jt+5mbd0IE`gX$eL- zstJK_Pa!Rdl=P`iWgmVxhy96~iyCPcgT?-f_A--yx+cb_WQvQB>RV*#6_(k>u&Va& zLzTprELS@N%9&z1(&iylh4kx^G|!gOgiCvr;tY`UOD-HKJUAuCV-{;?yXx`F+!EtR z-V_p_OWM1>!hb*t7?(8relnNwqB<4`M;7$x#)W66lH~5VC;!1SABWV6G zmzgNRbO$WwFq9sc`}{vfiTAk_!YAN}(FM7;^eS#_uQ}qNeJmW~ly72hg?^embnXf` z;D89Gauk(E0C?<>zKGz+=!O}~)_IoW>6d=K-=drXV%8a}o=JJ$L%DY7&xTx)q7KoT zNjBgQkO~LcorMaBADm;t{U1gVeYU zS}8h7+&AZ<#AjCHG&n((PA%SKN@GyWJG35*bVqXdXz}jZq_%9`+oe+HT~HsYfMLc6Kkx^OUP)f9+6V^-yP)zkpVA> zit^GR;wCcYcYm1}$EbQhX6@u1m~=6RT5K4aJomX}ASQ7^xSuvRfqJ(s>7Ct!wC9P! zxjxS=J2a`{-2nWV-p%v=@Zb?Hgv_cet#vW3JFY<%w*mi*iPCQ!=MJH`nYE`Lr?S{R zx(lv9vPg&)X?qxm&8>s(a7Y91rU@fOIZNL@C>OO43Y^`dw2fyGnu-?X3lhjuehkc* zXujFe!NS7NB(Rf7-&v03{-fn!+M=WnlJpbciv73sMF~4UnE$uoT`dG;f)mscJ@`(= z2R_1n@F9FU$HtuKD*Wb3@&ll$fcwu4x`Ed>9$JR#(jc-sZp*uOAEFk$Mi5kM{%V0b zmldC!?eMIE3$UBJZ`uo(9O{;(htw59Sr*?|@jBV=109BnkD@$nhKW|Q_zD5b>NgN}J-ZU+h24$Kl6KM=tULql*sPWtwiB;9DwOG>=^6-|}+dee?7`d7ozwG*26uO+Oj5oUs;m=TYLV z^1hQPZMY}Oyfe;pI`Sou;en-`(CXw(Aefn^&!Z}MFEC%~nCIgA)|2dsd}*3W-IA)L z=sy`<7j^%#Iq2tLp}s=i;hj^ps%-w(3hCkvYCzBDfp|R`L*z{t7h|IkE(>?NO5yx` zG54qP_#!_~s_@{ciaOW5AvGotd#;aF>j|Svpe{=yX?S?#AtRiS_|S~`Aq{?lMj-2B zz7G48an$)%mxQ6nStTmqvpwc7z$!W|lOikLbRsMalQe_%)g5v4uF7gctOWX?B0cPL zfyi>T&@0QR$B_dY4Jk?L+7|;GX^E~=nB1o{;ncMsxzA|{=S`lHxAeDuTTbG2I%O<%<#xxr zmb(wwviaeHGRlfWeTV;v0%fYaI$L1d-6^;H4tXFuKZJK|h-94P0LToY+&?p7UGxaA zwy20@{JW3|E+O~)jDQB8NSd8G>696;Fp3N8VUXMJejYJR73Uj$65-3`84id zIMn}G1(^TK$lIuABf2INGCE+F+Mlyw`aHy^B~?H8vZKRxqU&5f*}s$W>%TdrD{JLQO|1=NpiG;8Kw=}>z0JXXHPhxAzqBvUcnYLR zH?|TAU+op{)z!shrZi*kG_Q{3*ORRX-t!qI3Xk>Wr_jPU6i>fo4p(jXZr@L~e#=Ww z^MxeJe59u{Oc|*}RB1V~E-4qjEj>u7V8&8E{tQwwe5pauQctVv(M(Hvkb9X7n# z{oZxsvPO3*`;6AFSZkh2h<*!E-K0pN6rv%sT9i#9U&dY&&Bt^pyu(Q;X{fX>$KdNG zyo5g1TW_*b7<%^?44+DN3dkrJC{-vlKX~?_*v6eio-a?bz^yHSdsSiLMse9MvRsB2 z>lw@_HPdh?u9dM?zj@huLck`)n|LDhJ1hXuD{phqxvS=IzJ{7B zZ>o1BmCk<)ce5`suG_SlHz^GQ{t1z$zMhk}b|0V-1Zk71$b3&SWXsIhl!lVRP>DQL zpgt{O{<|H?*S3L=e}7m09B~>f+$|$NF4#dWDg-hh3fV8?-Q1Ft6N0Fqaz9}X55Uxp zZ=Qt>uzz|Ruk^M%Lgsd)^nd?lOeh7suzR5%Yqwe4$0Zzk3e4+-wusoFqIy|##olMW z`YD4M?ZJx0j8Ok~_>3A+B5Wyls~bV*BoVp24)KU%9L37H_4Bn+08|RlUg3HlI zlB4-pn#kkla4M$kXXCM@KOt&b;Mr2`Hy?i9 zs5c|iC$l;MhF?8(PF!PiTo=$b3-Pg8J6H4(5lI~ zVb%|_kvMcVO21Xor^K^P1N_-aQCat>KfdVYh@lc4_%i>rxXkKi*x{ z_MBZmdRc}BGO|v{)5}emEJ67FywpiYo(?!b%2Im2JLDb8Q5-kORZlK*sxlftBV*)6 z6x^8?%RR$p=CnYtyZ_o!#a~TN;Fl1AR_76vf@L**vuIrF`zn1;YT`Hi*!&Npw|<5T zM5#`tYKly-QAai`PRLTVRhBuou&Y#X= z8W(EzQg{zWNj6uzGcX&#N8h$(E3;^3~uf4ITA%$u`{bblvYli|^TXt%#GTG!nqwzB*PZHC@r|d0XaXIc^F9*7Uc| zP56Uk=VHiUa{TVauKErn*~Q=Tt{PrG=I?q@&T3!`ma_ll$Be3n_9c6r-eMDd&2CKCMe+TJKTaFJUM!1Y)!s z+!y`hXIUvVMYAKwzaqqq+p}7xIQOe&f+cxPYWO4bXQLq?e=pjM`G!!44zL4J4N zldqpT8ggkg(=4Oh-F0oXGyu3v-FZZE8JPu+G7Igpk*_nTWlCWFA^uJ@_^WOiOS%;y z79Qwa<$tMa#x_K@*3P2I>WxEWR5qA76!J!ryQ{QvwqBsya29{%Z0lfAvIQ`B5!FRhtxiO|h>UZx)P@=uQ#wh>C`nOE(DX#*#l3mYU zJ2jB+=KY$byVRbWDydO8y_P|Y4$;KWq%FzMhu@Uog0Y$3&m8E7-b&lPFH@{vZP2!d z-sVs^F8wI{VLb~?x2!d0JD~fs1s>{hzT*g5do|8W5PGEbgGqy568Y2 zQF|1j`Ul^BsEcyyfr`8)GQ_As4z@&rTMx}3XKSy`8}~h|x2-}{l&=~M8s>^YJd*rI zP;bV)e=g>YOM|aIQ0yq}ZgK+_1)uP^h~CE(eqJ$axA`7UJ(bdIx}Z=R6qBI5A>gzr?{t0jpQWRc8)$gm;Sz~>y>(6%P4 zR-`BhMUbI;Vob>d)$ZiE53dl?EnTVcSv8ijmtvq7P zyKYZ^MB}b(vDtG};f}v;wrp}~fTn`f7x9_d2J35F!k@vvy~ij-jk;RWAr8I=h{CqSrT4+~>S5;RxMmG=>A?(SITa>|HAwRZ#z`;-oBp0|m#&xR9oWkcyCyw$Av&~<6 z0dMra3zYe+l^~L^^p9K7sB49X5{#gi6Sr9`?kW}nUnTFj_rGYu^*M*()L8>KPDUi0 zp5QRXoDP_S^ z15d-e0bUhp#?b^&OBuKWZi(F-bwQ8Z98uM z+LYUGjxFGIf%=TvZs=_r ztr+Y~SQ#b^*0MP(BTJ_O#%V*-Gl85E1=D$UfiJs?lejW-+vDq1Tt7b`H&wW(a~_|` zQH%*Mjv|Wutc#0PLH$DWyY}ELtWcywlnzo&N7qK;`WV*{7#%4Ly}d@4i*dTBGAH^b zcTqf2mPGXja8hvv*1UfGyTPk}G1{q2jx^@xa|9HL{S}g;u7IaIv0F?LF5D2&=7#p{ zmtE*6jA+8m0@hd~}g3%3Fv`)`L^7Fn`Vbakq=J7*uv zJwzjFYL&jFWuB$y1#emqG@n`ymBP8AUQU6jvs(&jteV3ws2UKNJ}(dHAAmuePml*v6M0Li!`|u2AQfV%erjq zFdsRNdmOwGm4Vc}DEM4UN{Bp{D-w!FPWzVJpfMCb zx5hEF!aNvKJfzye3+f3ndi@{}4CdOf{4MJgvsQtlSD6`wRv|Y4)RO{MabNuyoEc<3h zgJ8@x3k0aZ0W|%+w2brz-TiQBt#U~_hBkRyJ+(nqO`kQAqV#1`sGbL6^M zGHk;Rwv5=2v(q&VIQ!c7>s7^`5fXV5QWh&^ZwZJPsHwk#6Y?mOLp=_WygE^p> zH*}Q*nFrbyU)7C3f&jqr@0At8q-K(DYpvvuq5$2gUA)^_CW->r%cxAD7ATdj8T=cH z5I0*R2SE`BQJWPx7lh29Yp8O|bgOnKG&*?zf!Hr8;CPDjhC$i@^7+<1-X!vP`N zNq>Rs-+*V;GfSPhl#~yjBz-zb$nExRBdI2vuE&$A`WF|?*o zbm91hRqnqvU~0K)`z^O^dS*RtxJ;zG2FEzNzD_3Ah z(h{EmJZGN#HKKW=Yr5vi8!5R;5ilzD;zy0;=Kbx5GNXw%s?h2!#MDwdfk2}6riy7w zsZ~_vWp+#4A!+V=SAwawP(T&#d+SLL7gM4r1NY^Dk_EQp%|A`rKv#utrW%CEo__@I zpCs_*i>LOQU=R>XhedGQWy^M&cs51Inc0#{V1-fcm7DTS2kt}KljE@873nt9+xDIY zbIN`5cmY9q=lpp22#y%5__2r(HjgzHB zY*_rVFl2iGY333VMFg)--P+j7gU8_W#La*6?;52hg+G!7zf03~X14Q|$>PwcxY#9n zd)$X@ipRBESaS7wp;OQT`p8JtF@D#h@|4byUmBgX)Qu!VDm>f*XSOX!IAX!;>>2qf z=5eVXR8Y@dnh@FewK@s7y5qO6uet~lyuI{xvnVfqVKZ5{|OxQsmRt z_@(VadO3RHWOnns(Pb`)NTC44w(Tjf^RRm06VQZ6A-I$wffnvC zTr??0T#rl~zgN1S6~<78%if3=5O_qS&QsTD1q`Qr@g6_4;VBIbsHpuK0VPMltcQLAajLj{nP<&e72kjpRpduPfr z0cSoL=G546cj00c>TEYpsgH05bJ3)3em8wfLSQwx=^nr;f5_><L{ zKL9w~qm}e#>O;=oq!{P^s0*yWLP6PNH7CTtslRWu+x^TshtaM^6#EJzBbPFCAwrSd zpE+*k2%lIn>Q35_#jzcT+H3X(MdAi8@#(xp4oh@&anrSUc7CV?e}X%ti^4R%(wz8M z@bqq`stK(t)S!2z0d|&f&W74l>R69z=j3LOF)TAJo9EE5%+07izqd&D%1DyPQLSrz zgiTc@>w#C4O-CLf00qF$1Q!V)_V@N{@!g*JtiSH6Cq7g)cHD&qp!D zrwAccv68Q(!AHwYfgz2BCAh+kN zjay3ucj@9at^&?z|_Wz z{0|b-sARm&-H1^GS}HFrU*N`Y?}cb-i7e(=tIKO|0#1J!3W2x`gowTtmfM}a-gty3 zHupRKt??))Nc)EE7tJ%Td6NE9Dq!mV42>=Q2?FCWRfshWD?*&Y(ww90lS~xFP_=+l zj;~S9w(uW%&aYoHZgeq6IqxxkdmwdW?NuaSF4QvPSTA&fU-@rgA@-|Y|KgQA!2<_YM(fssyEB=>cOR8Mdos@Yn+kZBE<)oAao9*NK|5N zwHa$T*XcuiF02U#j`y*@1_h{2d&L$#Per^ztgGCufktqEJYlThpx@t=2QMzN#1#t` zGx;L^2`?%c`LqlrwO#C)91B?yf9@a@_GsvEvioo+pZwxBI?9+>5%$rHVEtEqUP zLD^OSte9+d90`7G%OHaLf<{Y>sfr1$y~_PbeJb%q{oSf^HHzZwsWv4P+uL~;rxy4( zvr#p>$p7@AA}7Oye=)o7I-6Cfl*20z-1;1LjtF=1ti$%+LhrGymaxS!UMQhamWvfjIU~i3K_nVzy7qoTX(xwpI_v; z=JGBn#xH5cd8(Vdz{y7fl5k((6=Z!f{E7(21{~PFk;s`hau4%;v!P`&v#m7|e4iD- zeQ-j8eE2^g>}DvC4;)!~%HE@yP44N^e&hanMPiXm&K?i0lVyLtrg_K%XRThY>+<69 zV=hkScCh!YCwK$x5T&<<$*4I`eWv;F1{|)n!fF#%b{FtW zH=eM;`1;Try7I?UEzofunoAIwf=|9>Y~5U(vic|T(0H{PTWiVjO&$n%?2Bx&-&}3? z#P~-WAJ$ws& z-v9ljwk*{tL$wA8;7;|>O5eK`Kb>VqI)~E(p}%Qz%;&(V(xY|VN?gdfTfI|ienc=F zdQf{0{JdW@Qe!rb#HP@6SEweOS3(=dX)0em@%TnVfc80(az#Hm!$1B+&7Zo9WNZz7 zFqz*QY+rxRT~85ji7qD=Z`6(&yeHq)k?(uIV=kNWnnF8|9C^5`@_M)X6}V0LrA7A1e9&G?+IRqnT8uevZ0IR>Y#3FRZ6@D`Z?rw# zW>X;Kc6)_WvFkXKFYEEnO#UcGe+z{gizOdy)dyHMn<@)GV|NXBnq~AmD>P`Pb^eJz zsn{j}$oi)YGzq%2PTS}zI8#8~OUF;;r7bx;bAMf(fZFfCzg~q|{x{ps3eZ;m*Pds0 zU3`NX*c{dF-A3)b##;$}?zf?y;fT#mB)Eq@@Z*pgn@9V4azyKT>YGndy-fkeKJ2jOpPsOjujB%*?v1+R#m`6?seYo47KdBPR@ z*@Pj)reNtu7dVOzE@Vc#(d~WsRA&)a zyn8#ez@+!5=e%9Oog*H3;+4YC&U-}%rKc(@k{8D8_9c1yo6*B)KYTI`V-u2bX6okYWvbP=fnpW$ zus%Zvy5QjiQYB7#uqyE1Q9-by)f5Ps!EP*?8uknhUNtAmM#5$Iud6PQC~)>Fw?IYZ z`e1ZkhB^!TEkeQ_>f(eC?x2;BN9UXa{g>ObLXUoblEK!T+`i2f_^dU_*UA8IRT$LJpdAFj#C;p5FPLr@B7oTrPZ_&Ves5Y@ltimEo9n;<75gkBr`j1O0%pFs(*4CgPR=Qknx&2$%251YOvp;2RCP=$LR}Ig zxbj_mSeSXaVfN-0BD$)P@SfQ|D#43&Js)QKJFVtH3(Af*bFT`Y{h2md6d~>nkZj`i zJ!F?}rwRWauj|Fvz6+ymQRw59J)2%PQb)2x4__KGa_LUwHZP4KBaF%)w@<>qK zGu|+z!6?nuJozvP_>>wv}r5FW>l>PmheLcNfkM)z|f{ z`U|#PG1-ON1ii`~RMvIpk*qT?y421cDy0VZLajnfF9ZLk8|s#y;`C0<&b4g4t*<_6 zqq1PvEGc^2P&?=EC4&?Jm!%@biDWnwF~|e;_sIj_dBpJkMN7P!zGw~N2E$sv_jXw>Ndq9z(2_pH#S^WbU=&131#UJs388>`Q- z$dhCZINH8l;lE8P7_koK=JW1+=cAsE69AH`JUc0uB?eKIvrUoWB|R^I&F7EM3ejI} zW@G|nl4RoU$}B7L$aB2Wun(u88ae8j7mvj$*PfrglcoTG^{9HU>Tv(>pOv5gwi)I) zjIPIG)UHFeGznD8#**jh{Mlzz^0K%EYNGJs#5~RY#jrY{()2Y>M}WY53*_qzV7DHfgO8 z#PfaV+^#da%y#XzT?rQ#y`@>O_i%fzGUl%%_Pf*6s8WP@)ceF)m@2!a^?v*Qt}|PS zNN@L7`@<~}@BQWP{5$<0mn1}F>`0d-NcJ;W;GC+*SF5kgk82Q!+eEH_C`i84JWaRy z-Jyr%1yTm28v%N93~?Ea!!T{zJ=1MVA&2QVXzl0|3_WO@Vv-AHG&o#JuggWgd;M zSh0+PYTwh%3$Qkz)rt1U8%O>J6GdX3dYT?4ld66AMYVh+Mb@dQ)|5c1&WiUFPo%RO zV$m?gfFD__L1khfH?@qRqkB&wa3M066+bdEn|%OD^LaEj%M~O2K!#3`J0bG<#!Y6D zKjxfxLq}0gZxH0>!91jesKS)7uzeGoiNxf7}LqF>es z`YFvyGnc%gjrJuCCxgtBQ014~tfZ+=T2?nf4byiX18J2C4xcic9}v)q-Mej%T|ilZe&XLMxIo2KayKsK+aiqDGC_vOGo!Rv!iSBG_%KGy0WXq!>05?C&fES1BJ zdxnzY$C)}@CBKTO(QNDWRriIOE%vLM*mnOvLcCK7x2>>e)enm4z>MJtc1uU_loC8w zgyYdhl3$$UqOk&M#~4=syujZCU_0+l$Dj7*jL zKBMR4VyZvu7^nYnfq;Dp*QC_?^GhN2r=ad}K(0M|cPQguLU z`S#N}w-?#GU+5WcEG}h{XBtBl&x+VVKqh(f>!qEL4GVCbqasOtEO{SK5qK}$g2 zMjP{Md z{WQsvjBm%gOT5%+8X(2Hltu>w8ULH=Sw{>5njAG8+FPlgB`*0ggQopuPjgt_nI3ak; zuK3I?)-fmPM$cA;ZjmMDqw%{nJ~^n@nn#?#b)reSA7gU7suP z7V#7Lylvj9ic2h@R9%+(>&QodN%ckspj*~gE9d1`v8uV=6qKCmTiKEIB+rmx2kEi; z?5h2nlT67k{T-fXdDUYB>E-N2n~gUir+%WnaXr2*N?%80u+?4a6&eduT=kQ7yinnI zl|Sm%Ad&yw+`^*i7hK^^>I~RlJlSrKR6D58>Q!<*Mk1LP!~CXQe&xOZ_isw7e9*DL z+}KVXsCY{|LXndi(j@uK{q<13-lf5R$WWJzFP&5Q^}hPR)!hZIj@DM7(00F_(pe;J zI+Y?*`Q#bdSX4N*-I(SZnspHl4V#6hr(d*e>)Ri8`v_Yx&I4~Ld0<_^G=Lk>Fgb(! zkq02r6|)487WY@U8I`LWvDl?oIWjZRTxo$*%+$9 z63SKwS(u1CQg60&{-h6#ev^tN#6zLJF6HFMi0c*9#j1)Z=jrBu*-8-2mrEs{Yssfh zzH_6h)B%h(DO!Jxj_=BHRec}QesTOPtRMuH8hRhw*QwlGPg@MTUTuM${D(7aeZ)g1 zS**3On~x!o7xGx)7}4cg?$Vq$M)|Y-pSAP58n8YpG;Hxn4E{=q?OQGe(C#0thJgoY^OpKc1-)s_Ie=O!`e@fg|P>DA!NndtT8Fyv>1~qPJS}0KXTOI0tEqy{kjO2e+<+?a zKc>=`2^T4*FVIWCrvEs^r-0_LV4`!x(%Qjzq-%j|%aJy(C+!qjs+d>ppMIb1go`0I z-v>34mcq%3MjVRV?*vd=Gd4;wJ75x=HAz8--L#B~IG<~Dcv2nAxs1~CSs2j5;Ln(T z_itJR77&e!!s@`F|J{+2o~j|bCTtsqs6#WgkK7#Ulnc&r?CySThOBlsPU~T=wCQ?3 z?qrH$li$X@4o1BKB3k5E`zbQQJp&0VB3tzon!L#O;3R)EEz6jO22D5ezwQhfsiO4^ zaIDjhz5kEB_Y8;ojiN;(5+sP0sL_TX(FvmWAcBbKj1nTc7-2>iJ$jFb5iJtEMjItU z^xmRJ8NH4=>V4;bo_o&ua-Zj(`}uwwj9-1r-fOSDmJIS;2YCq3GLjaGFsxj1ktItR zJdg^s*(1gu?t9BZzLJXvyns54fo3DydL=ArUp4W(Wpmc>eJ{6?=#@DNZo4GVAwbp< zco>PwWtCl{{~G%nMsQck%S$RD!vu*3y7qXO*FNhjWi2VPcNN_!{CduPn&=4o;{$iv1e zyzE-|7EMQpd6oQeTog1rowoVA){+u6dtoDasnlAVcge8@DUsBoVI50~d)742)YO9C zfwvs2G95-Yqvsszw<##z#gsFAs#Teb*gv3HkuLCEO}Y~Rts*|H{y63D-`Ig}fCX}* z!}U`~2uW7EmlQZ+#aC2zB1m`_M`$UW zwU{m& z)i$fuw=lP35+ac2T1dGi>)`r2eNj)gymG{!ilOSdzvAULR_`HL?z(c>kQ4Aviv&V$ zSiKl>V76lAXMC%3d5i+BehzPqCm)#xtCUE0sHZ0g6HvOX?7)+et6azjvOa$rCbJKc zOeKnxR+y|u$EIHk+&hNrNkcA|5iCvel-Li6={oNHaT=esuO_4HiT;}R$;pYQ9VUJ< z!BNb*UoFb+>%WM^r=Z-YCtMuA^|4dYZCB3iZO9)ik;UFM#5+_jAWhg$CWN=PDoQSy zo?6D5F-NL!5D-qXmwfTym)hJ=P`#Z>3V|OEdax1%pO!Utvx$`y?M!+O)vt$l631~3 zvg6wfn_q+l&{1O^0S+lm@V}m-d^u$BRq#Sk6a1UhFD1*TA5z+N7D*WdjJO`SQVD#z zt2qmd>+?OHe9s|P7=Rcrr!nG=ydn66;+YstUq$o_U&vrLpp}k$bC*Xc)3xXe+KJk{ zVU5^*6?7P+Nfl0a%e3F*$FB@gt{XfD>nOx?$CowwPl`lHWK_Qr`lRSbI2@Wv4CSr$ zUKjDKkPrL*>xDbZ;1y2Pvzfd^AW1i`?5`4gZ+b1 zYVxQrM^C`7AcErahk`qMo;I`IzD-#>;p3=inls*-Qf^I%AXn+{M7Fq3oBz-dleC<_ zYkhwNM0M8m4=#W=2eWQaO%r1zYX6h!^Ea#I(7+0nGMBV;l&iM3r4SqRY-AbHFm_-t zI9no_cqqMRH2=2#$<)T4XVgc^@J=xeY8;i-dhfAo76kY9Fz(7j;M~~2$^q|+EibJZ{^+hddNwcKnjr{NP&D-=(&*T z_;R;3O_k(!(6qyK*lK3zSP_-uQ90--O#&L{b-s^T6#K%JcGzC)gex)sdiC*;MCLYg z#-L)WyZc8{3-B16*}}!*R@qLzHteiJOm%qfSUCh_UPJ=JuATq>LbdzWXK9Y&D(zu; zN2{F{vk4&eHpH;cDrJ%RTW#_8RWx9i)AG_U`d9dT`cr7U(MkHt975n^EV$$1f9gKm zGKAIZxt%)X_P!=BI%e1bR^X=y`JBxwAoo$P3f|S}HPyp~2>xR3RG%oDL1mhvjEV!N z>|;;INB^YVVa<&T31FDe0Kt23P$?+8z2>;r22Re?(0i|K<17j)Tn8e&E|13j^k?8+ zvpnL!137pSl){T#7&Pj2$R^Fihi~Wx;7wTOu zGG7_cyu|)Hd&XV#>gU9pv}dT6KAb?YArOqnU$KuK@6$UH0HdiP9C!Dj7JGM{X;M$` zP7*LUypWy-w1=Nki*)_pnMz{VSr$merc2{@boEV>xW7<^GXaeg$Y3_0b5%N6+*44l z`59_r5qvK{&%Stk-q}l}r0MeX5D5hM3q3nU$6}vC;#PUt0c~3PHg}Ta&4;a<5j+ZA z{Jwh;-GDCqWGnir1=(9r(&#w>kj;&cD)El@!j60!0ca^8J`$p6P{I%`y|L5&6G;hxVq! z%X(*69VxBeb`f&uj3 z;c0J@XB}JjOCL|W{tF;XHuadP!r?CHlf{^f%fS!f*DRaB|8&>SU2MCy-P4csj2i*1 zG6xdl8)9*)2h=#qxc0R&h&-za^t*IIZ?Fz*kD2#}F#ndRceB^?!Dy-I5$fhS#EnsA+!%d|2h9=J&pD1yLFH^GNm0z3 zEY+^(7w9P*UvA+FJs4miT}p|0kYe((@#f+Zj;4l2Lk=N}JTRSW^AGQ*w9^G0KK_muJy$}Zyqzaa6#IjLf! z_Tf{Yjq~4MuPJm<>mo!t+sPcRYWgHLUXh(eIeWi01lPYY7B_AJ(@4Jp>)!=fJ(aQu z{mpylC%G1t`8~DM+eu@_pVI2_r|Cf7q*{N=0Au;$zp<=hF8d}T7kbh{Gv>Vgr&zb8 zr?I*o>`^JYdWN};8EN1q{+oVe*9RvvCY~~uc%!*PrymJ{7es@5L4wU3^zS}pyg!+u zj`3}eSeEIG)^|e zU)D-_cpAdsWDxyiA?&nzX92Q6r6pC?H+ngDbz#~|C1h>b!JtH(($D(CrWNU(&KGWwL6!ejvb*&=jb0CCb+n{K{##a;?gJw|a3iKl zU;+65_F*t@_lKMcxKe)HmHOPyAUA>aioo_Gm9qL{CG{Ur`g}Z*YXQz@#(rSV`Qesb zT;ByBM6nlaa=;>u0=IJhAAQJZ@j~tKfeZd0PsisYcX3S?6PQm;pxZ+A;9=}GI>ij? zO7`V{{syG?b)L9x4~75F_xV4c&S0JaSf|#(&;Lywr3}j`kufg&;#x3hlMTP6<9zM> z4KLHrdcnPi|Nr;?fAHS%#o7yMfb*LYV)qx}hVvJ7Tx{ea*nS_D2&9xNm;x&${QiX< z17w}sW6s9|3rc;^ZLnWs03=j^)WYE6s_g~weuSnWcp2*fL4-H)RZ!K_uIgB@XuoPO zWh=~+=FQ&1MOVVjd#Ql>*9GR4L9&5mc=><=u|~a6t)NTmS-06`xrr|pjn*yk)HQS{ zYa_5r#B~cb1OXF6r%3!bBan`fyXA=dp|boAmc% z0j@#+vlofL>0Q!z7%(U>OS(F~x->%^Rb)tSIb>zbr*BH`)KyITwr`<9jgRN}a(@={ zH#=rjzn#f%b5H2(enpD-@|SF;eOcILo$JdP{_=ki>+Ra*zK5YomK+PfXiWvX?a^cm zJzt5Ch;jHl+bHwP-Q(UvT0_o+I6v4ELnC2?t|@i^!vexjSFQ)dP==y z@;Mlk2z|U_0!z;8m)19YJ0IKyqxJ(&er+YmI>lGs@L(b$8M~ZbGAle)SfQaVjk7~k zL*e_g&vxQ5ZD(Ab=V4}ce5y_S7D>^A?aaLWMh?F)g~~KM#60D4sf%l{Wbr)47|1^r zrXnTpV@8jZdgrEs>HX?@?upabbBPjPUBkVb+{rg-3|x%X!R$9yU0}QhO7;AYM>&z+ zS-52gO{Ra9X#(3~?)Hh9F++;36k0dlT;cCGSxvRRwCOclHZ^Y)Y6lN$V&zMANNR98 zb4lh(d-uihwElL(Mg}^=LsRgtKUlL-)`>7$KEvfqvchO6|)YCNXS*q}D3-WL= z8vO^S1hf0~V87_r@;w^HWOw_T6kqO-S_eEp>OxU{>(*OhjroO`A>D46S*aCb`9nVs ztY1>=fvG^XWWRSm7cozzoT2MPZdX3P-~7ng_(Oi*(RJ(D;1zy-GY<{yrBQvNK{USyBqpE!a7wB|FJH{E zf9rz7nP@v*Y!q3?tw`7NoVB34Dl+N~Qavsad0s!WZ)zDBcn;=L^LLk&y+n*r5+|iO z)&4l&)R*PgH-(K>)`PigX$j)jRa=7w2j+3Ja|{i7eWREUCTou@Z&~L~w$}6YO?5n) z$X}6QI#DIK4&4s!PC-K}y;Hp|5nUyIS815;AG14wWYPvJiBzux@pPV(JsCm!^FCB# zpM->q4G!R-AXj-opauXLeRg9Y6mB6uIqM`Ywwuf|6ty%#mAmO5H`jgIj< ze~rBmY2rVg@tdoZq|9yu>Jl%CL9Xk%6sMA$9V1ic8@<2R&Ya;c5=U#Yl)tQ`wb(Uh zX2^&A^8oF9eA&Q*I)GS5y*I;TY@sI+bvnkFi{n}SOW&!v?zu}>FVoudfk3i*9vHh7 z&p*?{89tLdTHM@CR-@$uSyvY%sR&aBr}OhES?=RmUoFF>RN@p~v6=G1(rL`_HmxMw z7ogf^+?gOa^DDu>&ESno3DAc9o_e@6qWd;?;R|XgeEu}G5*o5&z&3&lDA7101w+7_ zpYnB4N=-Thwo>wpe;q(_0H*oMHWu@sE<)a9RBGc&qph-u@H#NPGRw#F{zVLZf!vF< zc`li@Dnd&J`8IcXRE;h$yRtL%9JTJ+*YouCG5wxiy>WSVh48CIYl)@IU2cw}^<_`2 zv4=7I{Q8%eF4wK3@nnYLOIR&py^7%y?sIYWZNrJD-)!xs_57a}o;Aqw#JBjcnUdm~ zO-%XZqk^P18e@kZtAL)QML?P_$;dfBs%|nR^zAwX4sMO-U@0%QFt~wkuxx$2gW4an z;hZeU;EFw#oWp8jaROb?gDjd+JVnWcTy-A@&~d^GHhoLp6j-w%6OwyOKU==YIt`~IE*?iIFt6R-_ zHj-eWTZM(;CnJ_qLHDObEY7d<0Cby%*TrM=3%U-)OwE`)F>!Stv8lwo0$b}kd;c!T zlAC6|jj?NDelLr!erI$gXh~`7c});^uiKYs>-ntNSx@LDbF1^!yFK_vxb0=WenF=3 zAmAmmZnnG2QYXCjUPYg%y~cjA+3yuIJG?_dGjw@6-UPio z$deu2NtRf-cJ}fL{DRL6MCrf^=vE8{>9zgP@8magmzLk@Fa`|krVuawrgO~aKF}^; ztT>I@U{S>04!qh8l`XW8ZQ5S>!NAjcv0GK*QV? z8>gNn8d}Llc0aCyPV<)6#OLjFWKkPe_Emtb3cbCP2lPt#~z0#CH1_?QAKx`<5f*VPt(bD>%Cl>5?JMy%gWp~kKf5C zSp1kT@}&-%1Fciq(IX-D$Vv5u1s{1K7l?E6? z+!mkbOl@{_n zt(_s26wDK2W_}l^_9At^T5+_p^}(iPk&+)+!x;zYju-H~I5-cQnW4hR|4PFIOVpne z2_t{VlF()>DEC4}sQpVVnMLch2ZK``FJO>Cw(ptCO|wuY_(?$dYP>?5R)#y;Z?9i+ z=i&JI^1AC)!*NPmvQbuH)0%xZEThTlf=i*fzHvEJ-{>_Ov!GwBo$NRN5ly%6!36IW z={M0CHbPAwH~S>9|G94QhKWT%K8N3Xo_NaBg6KLcAg|bso`6`T>HCtT9*YrFXaQ}A zvmt(Oz1MiQZA?>ozG)*{z}~H12wT*-MQM90bf3B!2&Fx9BE0V+H(?pU+Xd)fMrdN9 zq^30u=X_UZ&|xUDwHPf~%mhA7mF~|I9ZUl+E}>ng+;;#C7~8FPBfTCp9kh39FHAKMQ&^x-QRl%-n&E>9ac3`>8AIYfAh8j~YynBYKbCS&T`>exu|dtD<5; ztj=R%ejqnr>qw7ak>WeAVvcXVe;xI${q=+WO<0dMw6v=nZN1TiD!jOY>QbBJ?5j|` z$$&+FE{Rld@6i;)>07GnRiD;vfo(WTI<0VTQbs(2*LC1{9~NVTuXA_2|N~CEtz|6wOx-2UST^J`iG~0 zA)o#sOO#R;4Q^{!d!+zB$;6zzQk1S9_kXj2qCeVe&)_1PzLFDJhiM-6AggvO9=-c{ z9m^*(%2o{BnY2&D(s(ada$gZE@y~I7qjzClDU;*6OTiTpTmG7>rq78e6Z2{p_;b~ z*Q0L@0$)$c$Z!28tRZ>*7YCS1!%(~YtIL?U^fxvLlZugQkM=uC{AN~8N$;uyNL18O zs!^d_ZVrtGL?_Za2(1aAEttp5e9}zVWt*3-*O{6Z@vrw7@(Y&|hSZ@>rVU1^;{$rWieQdu6oYEHT$~rhdEe8Y6dv*)c<9r59h^>P_5Z zqi#vA=#?-=EM=;6H6b@QFR-f@*IT-ENcRGdWnPF4mb%uCzP1X>J?yXFe&}(Ic1F(= zG8f;Nxl#NrQcYqx)*(A3hfMXvPA7)=3@$%%q94!JfY1(7GPna6&J zJjbw$0kyqyoQpbWBU^kJ+NOt-QJir3O}cS`+0Bo?HxBlFA5*C|eCp`S!5H6HeNy{9 zbrQ9yVyVrw%h-AU`*Gh^5V=y@dQVDBwj(grSu?fGZ>^t!T^PVoS|2Qmc3$_1svwpE zLc0^R-0m>+T@~6SqxFq5rCvAMjPwdN`V3Zg6^+lmR24C$UNWOkmWLaGGFNW zTV#AZW~mzA`8e~8i3ipr(>{XN?5D31LqKq6nYrQ7(&!h1o{`(Gd#@U@*BeYDf)>(E zV2!?{H-ci*l)AYO>$I91sNe2=imSBmi_4s0HHpYsn`C8<$R0DaNq^RYv%p@5aF?tb zOfYH()yN9a$5V|_L!LG-JM*&JGqMZ@obxPv+>)XGjT!nuLGnsb&GW+-B@LJubiLW7d+idj8UNhHP<1z1<59!uSrm*9>3J!M#xP&z zPrF|9jxKK9K$ay9?MuI&EgyK5MN1s}Sy@)JS56a3b&69+m@^dddsx{+e017BVUuAx z7pxp|L=mG8Cui@UXh3Q0%tIb9eIM->%_Le-d?ST62tEghVD>EAbDkhaO&Yp(mge&! z8^@ol(rNEvi77Ba2qeJ`@*AX5Cx5;15zpo<3qJ`n-R{b9(3A7BnfSxB6kGD$|5xaE z`l|Bx=?0B>Ep`rkSNtgO`u1!hcbcwbOO|*lPg<1*LzH=us`|f692Jm${ z(MNuXQ%)!9hfdB7mt(Gr%+6fnrU=v8<#E67NCAG2Ol6wldLv%c3B*x4zy8wQrgpn} zJXv|!>^sl#2eh3R9dQe>G9PqLUR0_b9!&TS@;QPZsN~MyW7_!!G0xQM-+zJ#2p`hHeHI6loqc)mr=X?YqfQ3$Y@wUEOE3807f&y?p*+;F#Umem#Ww9b!&5?4AWHXm6O5YtekJdUvo9 z*s>NcEy?t=G82|7zY2>Z+>lFNwve{DDV(*(di{8^Dm;(Jj7calgJ)S?9olCNj^(YhSN9`wyFQ3jG z!+u@N&Q}$&?|8(uWtbw*K0Mesit8@=>1{Z#%$@2qTHTbA8&WCbiQg!V zsXCfhZaAOq7oqvbXN<;7ZDz`cK62~!!+2QqgZvlo(OQMTEhAK*kRdoowxIp2I{j_? zn5S|r#Zs@3MZf&9`s@#Q(_Va{QhwY)^sBSmU*31pODa@}F)ZbIrhThjoUXS<$Dg~) zX^t;hd5`5t2)?}Li4&`pW((rU7$`VPRB603TLe3he<~#W6G;Q9uBVZ%(Vui153=F8 zUm+f*{I-js&b34cE~;8v#5%vE3p~CyKR;%S}n4+g@)KP%ZROFlKTNB|=T>{5~;*P~c-D}`du}p8DoOf|%i(c<8el&iu{u#5=ekHwK zy5AI>!t9xIzTMu$J8t^UG1a5kCQ-le@Z+-&IE;}EcUOqr%fiMgqcQKDEMh*RZ4{On zZ8LYGR=YK6-2MB?`|V^p8==;5qvQ_n_|@epW?!A3`*`l1Gh&ufJ&AO##=_9I7QOLo z`hOulu_fb{DB`-)2s4vqq+>B=g}a!$+T^_sc8at*#cR8!Udp8(A3aFO%&R4HWQ854 zy866LdRB#AqKc8$uFiO@;yu3Qk=%5?Hs(5?>!oP8N=KZWQj8t??7N+u2q<&x znD<#qX1}}(r6U?*90|W=TwzwwJ06z}J)$cP)}7YLd=dOra6^~9;4TMPulDjMuV|sE zVH@rknS-~8&CK?$*E(ug=IV=vY2STEG{4xiL{j9HZnDWjEgH@5gYc0RmC=mNNmF$r z3p|m~rgYBYw{SLR97~Q+Jwf`->LAaL6VQ8p(%MW{$5iO>AE8YdpFDd`D-F9HDth$Z zq@7Bhjm&vUflBhf3hF}Q>e%AZ;TZ!}fYBm9vd`klQSK~#ShhE_G-mtb+Y$EH_m9-; z8(T??$U?JuJ4sPQaQj?eZfKfnj}-gfooisRVBUP~U}kf6c*^4cTc)LD=uXMXU!#E% zUSh`wt6|QA9H3b#bh`FY+^QmcM)lL*KUV}gQifi4LTxt2|J?1XcM7gNOK_tKZ|#x$ zf37dI%JCJSw(0=$CXr;P!yMlAsDcfQCx-b;CR z#-0;b8CjJU1@GxEKeMXQk~LWsF~KDy&p| zQbQ%&#WLY4ItO@*y|F$HH6WDTzlorife3VR(**ree4|Ifi<-FX~sLrL<%d*v7;T8}{T08k4pKO;hA z++;8Uid8y-TRQ>Q7O~?^msP%eeZ>#co73hkaJ9|%c?HZDt14)qIb?zD)bf4l3)atM z?h;h_G(aSh?%M!oI-%of*!YUK_Y4;2-##jdc_=ZJ6?OP}W3R|CqpTu#5@7kCGAh#K zPF`FBWdXg$%fpg!Ph3~ccv<5};OSRC{xkma4#;6b5P&8(;ed`{HwP+dZC#Y=Jc3)B zOP~zSux zU>$i3J}<$c{WQ`^%~4gY?F9R+*x}MqhL|Dp8XO zlT4qm8@U!1u*-T;7@=h8O{=uf`vS(W>rSzX1B}#C0%qQ%IdVLp z_fu+5CzEZcNSCzk1VwqTfSSZ-efrZ>LaRvcl?=a2_8IWB-z+7^Il2G`&e5BX!>H#S zfq02ED2taI3)h4t=UD|rH9VyOc;cF^56Jns0fzMhiGd;azu>4D8pkgIpfy{*_APB} zAK(yHwIJfo^BS}-s?yUKhdf%txZ+@*F`M*y9J-Y@d+@CsKn{A>cQ<$ZuFgFFnwZcg zhVqSU)x{oswl6kRiQVrJ)=J`)LSSb=s4mj_?2hZLv^ssbi3EU^EDSx@a_ukE&CQ$D zQOlq0*G(QbbOy>qLY489Zo}705WV(xwbS;+r~j3aL0u2I5s;oSsnd27UzXJ`{Swj3EbK zV0{n4(A9d7VC>vbMQB9k(HeUO$-+NhD#PR8rH|CzciFPLeg-}Zh)YBF_ zy&|I@1?!>nI^s6NJ`+D2(JA1;2oi1?T16KIH`5rH2Y51)Q`0r>MLCb)weHuYPZ@V=m!G(1t6z5&zO++ zy>XBumbHrD zT#~)klxF38Te-}qNeqcwTbBpHT3@Fo&b{pepGY%ci`6f$fB(5>)+e0fp4dnEW z?{WRQ^gf(aLV|)n=1v)F77li_o_RlB6o)6Y>lU{OK%n0I4NzikOl}xmR5p=Eb^KV{ zYn&%_{*D;V4)}nFM<+J`-UtU~`QY)BXh)9ze-JY5L=BfCo>+wJ zG(T?93Fj9SmUkVLI#XfHb7t)4?|d+Kp!i@9&;l&0em|?%JiRR|6#DrWzL4?@RhnOH zM?e$X>-6F>CE8`fMd0m#Vd3^Sd|MPi5ejXIXa>{H(XV3#sfp&EzWO&ccj^8Bmcv0N z5ufLMu0cqk7WUkS1@0=o<9Q#+s$T))=5NvEUoSQ^^F^ek%aIX0&msvkX0p01ZD62M zjagJ?7^w`D!qrnh+jOjn5UFH`JZ6PvLGehcM7tj zQ)XhMye)7PX55h=)~fzy1o7)~xvEORm!wFMEA`iVzZ~Ja@JJGoz+Uc!URFx>9%8G? zIH#c0V68aftffKv`z!?PYtfd_D_jvH`4q?kt(3SJ}6(u?RF{BVwv@f0P}mO-%n zE+7@U-!~X_`Y)YLO(J)0dAjkGNV>in+*10+4SalLeraP9qKinMsjFyf z;0IoGz%}Pu#sK=IJvV&=i{MialE14u*x>cf3{`dx!g#o(zn~~tEhrDC;N*fgfg*~C zHy4U-zZi#Q+pmtD&%>Kfglhz8B${okf7;ai!n8uwQR z283XZXOZ6I&kI1$eCFS=eYTqzrQ$oSuuJU9c$?EY8%}X2dn`&mHXzuQzBP=ARxVbX zF;%Sb-v{D+8#@`jNh&-~a^2mC?-Vxnt<6^iko8~9&E}aReuET&ABk)On*ayc^Uprm zF|OVg zgUo-!**KS`gWPCO<2w9FayVypDUGGEnk$k4Uy39WLlqIRpC$hNX#bUPH>vc*5$rq2 zMp}}Iy%w=4hYI>xLhjnQ>Hx~?NTSDwU%#Xue05494ftu#iL{M!da~ko+?|(H2xui& zkZ=!L0e=$C>!LAs+Wj~V8O`Qy81HRzJ1g2Ly3x36Yl7t(za@=SUvshKu-I4y-1y8= zA6sbuJKzh^XQ$XZ{na9OKQ19Y^zQcx{frMkgBSLmb#AaoX5ki#f|Myw)PDL-VUxn< zHfP$+XE@rO&(-Ag5APy#QC)L+or=bgVN*`7Ci&;9nN=t`vI90U^lD6wJt%&``6Cn)6}v^$o3)vR!pDIpdc#DX4NskMhL54HVyt$ zGiQDbA|q;FbxIBD~&!D=kgoahY`Uq*3}!-=cHUl^a}`q5dX+~ zl%CaKx~Mz{KIPV*4XBhuU?A8f%a+qs*$EibP>#*35d1U&c+yQZRtj#LU~Y<_z|hxa zN#vXh*017jLfi!!XSWU__0`Cg3T*!JvJenQ_e5aqI&)2kh{d_cAWoFlobfO8l$_f5 z6fzlX)dHh)qB=2EYT31zaWWazIo8KKheMP!}Ti0h^3AjU7_C6 zzt8l|h5%GmTB>;|w^GFLmMbRd9||F{wADSH@9}=QPAbVPNG?_GEEXvNsnC$OY^3dg z@S{sp)%GWpEQRFFXe&t{$HS+t{Sa{Nc=cM&9hz!!9z=}bQ*8+Algu;6DqjHorB_OhN7bT5~D^~F-TsJ3-rk+9s=>)=B z)0ow0S$4l7)}v`n1TdF0mOm9~c9`~ z)qwvX-UpX_#4A{w!U#R;_lGQ^?%VGs*JEkG#zGk$u0pwUEucNZn^)>TX!bZmW-TXS z-G+ps#N`J?p7=ab2}oxD<7G(738-+P?(fVRsagfZ--J^0rQ%nStAfEUa?}&gxj;T{K zD{!g=dMRj0@vhu!>(bGBy?;iGjx0hHImGjOM)LQWoa3Ev3F+R^V|X^|=?*?IX<9}) zoupYW30FPugQC)(6Ct}Nk$jT;GX$K}Unee}1(`QrR{$9sFX)sttSx33_gkHl?69-QnsI{=99n4i!=B`FMp ztO^u}<2D~3;Amcas+b|M-wwaxJzo8SJXrC$**+ayLLbH1^T=ms;!mHZ9s_9qxh!G6s0fD!&qc}NUb8d}_|82%w!haF?$KX>Vx=(-A02c1Ll3du-5RR|R5rbmeiRQx zHS+%Y%L}+E5O9djpAw+&s8rm%i`Mzz>^YpaZqDfu0n{X@K*d5-E>Sf8$zr5%esx>7 zWh6)x$&%TkpJd&48<4l2a;z>g<~35f%Y6NlDhr7#i`flwGpVkd&xG%|F-Ek+x~xk8 z#u?GlhLWRsaepW=Id4mabJ<1UOiU0(5&!((H-pG#)R5{1C<#MnVii;;WqL)IVv6Xt zMmHAm`-p9C2Vg$+as%}oBN0>RPq*OjTZbElD-JdN#8lVO!HBWYTlY)gZQS`Z?ZeCO z>iO8W8cZ_N41U~4dV34;Q15-1lU%-QjUp#c9nZ{thBMI5hhmhlc<`(^)79AP?FTB(p} z+%GIp3Mldhbh)C#ZSPG}(xd)aV860HH}vz9`svcp)0~)C(hu-%nJ)9~)bqa3^I836 zUP1+?{u9eMiTGsCk;c_$Ky7be_{A_&c&pVPmPXA)7|PNAg#3nciu?>902gRmb5ZcR z?rC2y>0~Kx~wjv((hlT%lYDfH|hx4rT+Jbyg*hq>K zAXW5_#;~@2DYFT#*8++yk0QK-+N2|TD6(pw!#)?|Te1d{*Wz7QV8LZ`jf&jtK>T@S zEWlr=nhnZs1$|2ImNR^E3P$B0Rb`~S()M8+E>8GWK&emdFad&E-IuD6)g_lUsk$3iw ze^l_rXR@Vri_IXJ3^XJBt~E@W#ZKVjw%M)H^_tn<8V0TPehl_6rKRz3f@^H7(44Sc z^4o!Z*`r)fDSh2c>*y(CU^vU1ocRi8YNEa9SdZaFbU5ox_H7uh|8(I9UU^rxi5eBvFnot*_p0}PKU|oEWEu=MJE0QpfF~YtB6m) ztSCT;BWsUqVd<(cmr23T{l6|njQDigMDYInUOq&&P-bb^0Q{Kn=zg+6*XRalr(>Ja z+tszCpqPS1mgO)GAndxsRlixT-q4pV(j2xWNcudoF_-@~=zK44+HE1`wtW_HzP_K! z?_>Kw6?ThLC4soU)6KdrE)W?hL>6gdYqqGP zDW2QE$_Xi$i0nIxjWrL0;BvRP)= z!~6JrCTzT|-NaT0aSvVPuB%d%olToe@A$1fmNgx})y4A&h=L|OUea*)>rOi+jN>2D zWdf$Ar%KF2KjT9CR_bdz>>vRn9hL&k33`9Nlc@+xP2aZC^hI({tcDbK{3qj@7E2_( zzl!)%#1g2gJmS1M&DupicQ@G#5DCv!7aZ}K9xC=`EBKS}m!l7fNX-E0Ok}B}Vgbt< zbq%649Vz7;krL^EkiT3O1WA@f7~NZB+!*2PRCQVmzDN zAN!K2=vRRD8*fR`mI_5Y`6r1nn_WS0_}-Ep!O}KU9mP*H79ri964OC5x2x>ivZJs? za5L;JaK+9#D=S_G%cz)X|i z8iC~YVdVEVrDRDEY4d@^>e|{~ALehN`TjyLYr+DdJV!}FT_PWEu7G>HB^IDK`>_DPYsS zfdG4QCum2y1I)Wv6oOFn7Rvjd^u&o3g>#mb5sHg@dT=F$VX2Bih*aGh)z6zG5}*Pq zut_4di)q0pQEfMW%`VhIJZMbnAW)9!;?^JfN|^SF#k}4D&sh>Bj{T`Vhp>%*hsu#0 zguX5~2Xumls;)Urf>WpUX&7>E!}m1p?F7h=oN@UPi$G48e{Z%C?Q7P!@elA;>YE1a z!c4zAPax{;2CPw;&8vjsY(zmrHztB3Oo8vD!Vq=9R?T9x^+r*3apo&q1ENDPDSi~6 zANnnAq-w57#!Sb$lF&}d(-)s5xpS*kbL*Qwxo}e;f77w^7IH9_*klUrBYhC)2KGa9 zmT-?qa*n(1R?q3qIBo?6SU>mr^%dd=a&2+B5GN-1SZdX~3@(Y!}uzAz7$VwXYhHvOPE2{-@YHW6!ei^*OQjj|~RFUTsCO_se z{4+-Gt$c`TgeI{6E#N7|!%qG+D&)4mbH31{n@MdFYC%8qcUE zRP&w=+_nlU?c~%d=MH@RglrDB?5-@y^Sr{Q`pCTR{w;g_r972_^r~P@3=lHA!M^ts zFR(VB#O-h0nN1@Idd+MQ2E-onBxCU$K? zuKz~k)oWvuj$b4ZhI?udCFW8E43J&lH_4foQwSqNK)3_R=Jg{=QKGHf2La&&c~T8; ztlrT#Oq70@mB8CG;@!H(f-Fx$4<%Fs3CWEO)h=@uc2if@xBcJA0y(+IB!5+OnX{&P zl#)LBjPbfMU>LlUIQ-}&jz<$P_5*Q&$-i8|5h?E3qVz8^M`bZd_;;Rs-5z$R=2~g^ zQvqhBz80_l{h<4Fc5CpR@v(#*&++=MUxdsiq*p!Ho%Ol?atn6sFC}R49ch(O5bTT= z2)6w3caaEwZVKBy_ZC=SW5%lTruEZ6oYK?_0XjJxKGobhI~LYii^Fzt`uS*_Uv#VW z-e++b@!#0joV)oHmA#KqGQp)q-(FhdUgp`k77G~0%RzcQn(Vr zV0OjYT;Jqf8@;>L2_uPT51s;CZAjE+?H)aY5`2t+J}iKc0QoM%=VQZS=iBP|bgzzi zrX3&1x835!iDm4y53$JfoDNM6XsXTquC@d=ngy!cN0H?D14T(wM4TNJ_YSB6NrVQ} zQN)EjL+;YsQQn9k>U_Ez1B~UIP3MS;OqJd0U&LCB4~d1j34MSaf#Oqqtbyq2jT>N^+)wZbT2Ct)MTk0L*h$EPY%v3+QyN6LF<-w&CPg~6W z24v!6Gner`h(BX>h4m?Pg9HVT74?|4N>w|yUzSmdgXcy`1zNvAIzfXqqP21wyBuCt z?S(<0nXlM1Bfhv6gRU+1Hzc5VPqa)EoKp028STl~o_C{Y`|x&Bo26(Qx#dp}S6u$U z!6e=;Dfe&B(|OchdiLQ_W6`?U979Ahk3R<2f-xfpj9oZH;HWazpwXtX$;sQM+zF&g z@t{nnWcdfM$8nbe+K~R&hw4xZ&9S5CpG8tQ=_5_;-&?$2PWT=AZTlSyegcs^{&9q( z#Focjmu9^bT>Yafmkk-acwH1$)!_CMNE#`Z_S`y*M(P)U`KdC z9CV%>GUfk%uP$OuzS`tEo6X}iOy0K_JuYPs6yj*aRQtMVS1wkdQP;HR`0IOMJHM4~PAU z9(Oq7_+re>Hna^?-Sv*X@3^F(q~Yz|zv&~|H|RojJLt20kPXI?)Yr8RWJcb@%YP$K zs$ZB_7 z3UTPNm0SGc+O6V?ah>t$MfsC#NkI{65j}CykI`o!2_JcUU)vr1f|)hVz8CW-;i5Qq zD-|AXazJ;C;8+hKDLQ5|nL?bNTX{eKy^kE`SX`vxRc5mD%2ZVJ>0w^_bovlDwrFsly}ov=#y z{1etPC8PG%;~~L71&x{aJ84j2PI*QvQ`T-SRM^N<3EEZ0SK_D%k27{%!iKO@d2UP z$XU9IOJf1U+^$H+08`MuPpVpj%0yg@Yy2-C9J-3dQGW;xIy&{g16pfQIgT%a_sMg- zXlXv1YT05YFM5O&;qz?B=JsoWT&G!_d_0+Mtcp0fV{Cc(1jg*@pui;gwk_DToi1?^_4)M^CdrqFiwyw9tFLXokb2Py=EFj`)C< zKjj|~`R5>bG~PV|C(q1g1GTyRNNI)Gl;11sw9@;(q?nFD9upLLFQfSN z7az^&<9Wp$l<1%FYt0QrV-;Z};=;v9Yj!#_;-=U~lyWWpe{&Y`F&#=qqJ6vKGNpEt zUt8Vd8`C$$m4@%2IGK-B9z_#{6Z=41UDZPii`!=VF(Rdp>nCM(Y�+0ekVrf;CsTLr*8Dw&P*8+Rn4So4-*1O zCWD2vn|Z{RtGZOq6AdR)U91CG9r%$zGk?`6p$l zY-XR3)VrQzQkn|6t2>`Ye`*Iz3=&PA8w-Q16iD839I?QDGE>&V0K-ap<1V|yfPW#m zwvMQhBFAYK)v0KQ9CAI%;ebsR!FsRmUs>F}A6#T^5U5pfAzIlClkFw()dnA8yLZCI zi2rcyB-iY{U1Nq*XXuxaPzik%e>c)Gr6=&3bu;87i(+>42#l5ifqAj!7$bee1!$-j zZv46z5d8s;#8jz1TNwK2K*KF=bmfxD}?8oOO-ksWm(j-juQ>o39Jgiaf~0-9;}IAV#j zET(A@{rk=LRZG_x329xCg4rBP5zlG6c1uIA|K1QM+=-i3)%2u){8CPDDN^e?gb+%} z|LnC2!M4p(+_HA+tH?{L6o^8+S?0qJqo$}~#wp8UYWsbPL!RQL zvVL~|H&1U;qp8)QY>4Y6c-GQo!yMb?TJp*km2(_p_cOm1 zT|k_QL|CH7b6JAdEu$U8wskSZ=~T5}+3@)SlRH#Q?TEjUicUp~irlp{{owvXrph!^ z5)-d+CSX88v4>R&{Nyh1mk2AR4#j_jj%&oTk!%3FcO1~uAdOs&W5<|V^*ZnAkwYk{ z6dn^EP4xTz^fW>R{9k;%cQl)S{QsTMq941I#9lQ@jo6#owP`7}T6ATHEQozzsvXcz0bMNxzD-tk8^NDa^wgR57V*cc7$sIU)GU^@l$s#f0<}%aOGF@dnm6I6x@{;pj=-Z&0=y<9i$e0guR< zEb~kvPyD+G)nnNmaq6Ul9N`XAOza|=D5-*hXRzuhFqK-9A5%iyL6&C49o(Bv=*w)( zPwQ31;AKgQgNaAkD2221?7MfBlbRm78<<0?RDDov*gBVVx?a?Iy7!3tlr z*$5`}5s|Q0sX6{=>g6u?0S0BaFor-xZ8n3U;Qz(HX(#ntuWmd=y zTleT|{*(pm<@nOw^gGi7GTX9Qz)D+n8yM6 zk8c5}?WZM%14?TFywX&q$`pw;r{s4$fUuo-F#k$<;-oLz{`x&K(^^0<4*_gtgzCKN zmvWL;>^qM?njofvY~F7D(2QJk5uZ_cq0S(;F46q*t)sms4NfEIM@~mrBt39&&YTua z53>6^K3PQ88x(3&$S8+2*;VWhwMHPt#C|M_PdO6 zug!x2#@#5Fk9B(Jcfh}Fi|+hQwD^rg3uberPA4ZC=`WoPzIS!N zuk#lYE0V=4jEze9`%~$;lwHw-A4U|a*aO{5Qw77=f2RHbycz|&L03Yn9IDES)~O6Lr;$v-_=I7}5?9O}($5g#LTW3zAB%=; z)+azK%p03s=&(n)#VYs1^hGZ-T~~!s*T;VfH2 zN?7l?y{8IX0_8WZxTh5R&xSpaiNMZ?;$~F#jm?NCK1`L?MEH5R>rvTcj6f!}?;PNT zaY=>A31nl&2M6|e-5%TAFSEon$#ne6fU?C5efsnDZ4b5Jj|;#zXgQxFuFw3!Cznt| z_7*zuewVAdA``LM9CFV4h2 zJ%KneF?$l3^gFX0Hi8C|?xfH=Ql!#%1=2XEeOZ-5BjId_TRJIG8j#e;D7kdD*08wq z@vx?Zufh%FtYo*+->$YyQE}wo?beWP=1?aldW5?dz{3wEOP}5G4>+(81^AT)M9yh{ zxk)WGW3u~MNsmS%m5D3s*!s_VxBaZw(%d#i9|^b{Kpzf__>!Rr_Wddh>cfn>3*;dN zQfr23)z7VJmE+s*Tuu)a)PKrqlJnWGj>zQ{3W#k2_J*ekf#P-G9n_u%ttJ8APdP@y zu2W$Xvb%2%{6?u7TYr?- zn3PX{i${KK^|vl7fQFvm<0llFx$OOn@@kbM{DRS1n>vHMMSSQxMAEJ!nMT-4W{j_jM1a#AtMkw5x2@|0v*Cw%eDQw^srS1} zrjLP|b$0TjMJJB^r0hy@V#5BW!h%b6tLRQurE4*Am}a0j&mIL8umKP!SjZB|MO90? zCZn!5J`W%1OG(6^E>T zP1#)tr~GgO&d3D#O)D|h7cVcFmI26s^p;CL&D#3JbI*r2`RNION5*jjp{&eEoM3K8@O;wCw!^c&3e!2CdeaW{fo<2&e zPJa*8Qx1#!t4A|JUIAXwB!J{qzTxpXAP{gPKM4D1iaiHndiLeNttK-<)QD%yWt*V} zpe!}BDcV6N&qI6Sl5ZQj%>b7b*wNSDxNm_W_P)#SF^#(1xtqxz9H4)X1p$&y&kUV9 z!BGf+g8u+u#XbuFAfg+-2X5eL2gr~;Zzt%l>|8dvC(mfXO=t2D}TG@qOuUVK5Gv5kTaAP6v2U*Rj41Z`{bz!0p2t ztd_untSIU_wwfsFk|>7cda$$8 zI|mPkLiWB0Lk4@=JZGgmYOz>qRgSAMQgIP(^;q?0uZH8f(1l>dqWM|`;#lGDKT)5P zY1jMu$I^o#pIpX2J>6`a_!QuBJ%6nm0wnJxZI0y%iYsp9q~Bh7H`N*3k<7l&HtCn0 zEkc10rA{`Gyzc=xTT?BLhkw~Y>Yhky`F2L=pzAZqH{B!#31Me@gP~Vde>gqi!lo38 z7rQ-OfP&2}*%04-a${u$xG1by7O%&jVs2vXx&sGP^-x7U(tJPEX?w2UXw)*;PA$NV zwBD;}jaIq|@Ps<;?-vN*=ragkg#uG7@%k*lyMVcAtmyG)VFq8|h%UMlW~cIFlNf(L zB8pocj|5h>wf!|K36-zmPYpR~BI`C%Pzd-Oh^f-!YvkA_5FQW5o-Urj0TV0<3;ujpsd zZ@}m}UvoWw(sEL>2X6+z6P{S59Oy5F-~l8IG=LJ{o=J-wBe$~#;tG<4r?qv>Te-xR za01AUBYf1aGWRdXz|FE+caji-TRl%`RYTxbO&zd@&eF8?(PMLG1AevI9~NwgEM*9k zq+LN>vjM;p{=s3rVq%4lVRw4s*c-Zr&o-^EXY3jnf;l;-%K&@*7V#|~v=?FK%qr@e z2nRmj>(i41TA0YyUVNyI6<`$axp_(lMByui^XWkePQj7a`j+|Kz=0XmUB9t8OAd-> z3nL3qN*q{V1RJn@L-1+b38WdiCBb)IeXoEncWpG6JG()SQ|30yRqnYj&C>{dMrV^?Q}gdK9>MV&U0bWQ+-%pxdjN?JHt|D zUViPi2FMv(A@u$K1|KS$MWs@%w$Wgv>j7cH{q*sU6X>YQ`T>kXq(Bz(gzd*{1CXY1YXZ$=0AfIIB8o^R<~|2 z;{EKpinXtFVVolHzPq!&g=aS1q~z7=+-}!LBYJeLrGl^2-C~;WFsV|1`^zCI^T=^G zTqAhYbXngcyQ7X@A`EpndND#jxUR@Dy7R*9@;G?4jFeA8%5cI&E?KF-Dd?UuH*E zRQtz!F>JVcSaah+oBATn`d$-Sm;VM0wQLqhrp%q8KaZkdFfVE2l?+pL@YW1l9+I;nvXBbdicDy`iU@9n46nV0UC%Ahcj@xZ_U({ zm4jP0Eq7dAd*!1dd7rH=0&oJ?Qo&pS4sOaM5uj$hT#+myaHLSE<@6<^9}yceY^}Fn za(?#eSiYcCXhZ(;aP&8<^Ty*M@#RLsjG+rdigDE6;EZ%VAs0#GSM)%a4L7k(g@AOz z0Z`I0i;GlLT?Oemyi+*lQ(M=Tv2%+()0O-)hAXlDbssJ|fY+n|5L!CV3yg`OPB~#G zrGp!jiiMtlkaRKw$a@}@g^{qxl;20egHN3@^$1YIYR z?}u~jOAcO&=1K3U3_d?L`EUj1s$3Gt1T5$7|CS7vO%K&Pvd8r=5nZx#!@!3PRsT&` zL%M%`65cI!v+c-=vfQ&_^y$Mhuqpg^|B`R`r&PX~gVsb9*o;Qk8tB?^15Aig8>cZK! zK^W0RJrs73XU>9yqCZZ5$uN&7!fbBo+U4qoaBwLVSY=oCvu~uTi`Z>Apn5D=RZxt} zMGA6(MDZwRESa!o7Goolrh~txl=8~q*=I&fOpFTk2>mc*VUiw7UAc$Sj8t&qA6yV$ zcAfP<+4lZ~V$7~_%sh%804q08y%d0oqFY)L>T6YrvDW}M!*#%Pe&R6+CBFQhfyb9M znakaEtEfH{Vf`=Oq0(;hoDH>&3BOV^na9&ed1&o^0Kho+!mX@4cr}Ru&T8UH4?h3V+FTlIf#+HnC|y=t7#dT5S_k! zDgnI}FNmlQkf#iP+q?#tpVd*>BB|=9qb$pV(nAXM0FcBw)dI2j?xFe0%6@TJWsj^n z6A=yF+IxzlSnyNUw&5J-PO6MkZZTVpZ4@z#j)NJK{ZC2`fqt}lB>Gq>YuHF%ALnAJ z7kc3?y$FD1J>Xu!tD-q)I~XAznB#Z1C+8P`73Xn1=%Fj4&TpavWNW1**)zC7J`PqT z2Kf>FII^_&wbCXW_U=7jAl4M1;H(rWA)LbnD)zM%+!hsBFY-fW#Cm}kDdklunF2&E zFd5bS{uEl4IETxO>+*D|^1P*xqK>(flIVkH6B_gV{CZV7@hu-!tg*OR znzOG$H<*I-*(s8RUyC;SeJS1Kn%-ZeLl3=w*ScevWqqsHW->=Lz#Wibjkt%+d6s#l2sVVOKTN&@iMhi!BI|(lec1I%evm;qU5c@y{lGxB!!S2A5Y!>}=Z;+-gFE%Rd z+k}86e=v4gH8?<TBHPfweoTJK*SZ~dMGJ^Pg6MS|8qW$7QO z3kEaFug5rL8IDlGcP~xmTNyX$wMX=NFGU|lk&7n5uThCGGmP=rCoPIXsE(Z$n9$_f^{O*i-V`bG_8r~t9)qehXrFh3H zkyA1*KjzC3T(re4ttEA|cSL_{vw}CZudCa8Ln2ZQzv?#3@4Qa^Tq(ahX@=+a#-s?A zgvtOmsGlKLrTIq*WFx{d(qkmAm*2Bu0JdqbD!!P>TaYv5dwemIYjgRNA=T&WlT{a^ z1bH;LVyfiMREfXJ_HvhNM9X9(A-A)0{OQn2kE2 z|0RyQnfEmru3DD|&}t_u6bDuC(A{TzX#LFO1iZyCt2YVa^iVFVFhgD~8yO_t8J*Dl z&4NvvEz3QNP72DnpzZJ_E-(Hr2!ad zTl-GmasK-)t8658Mg**Le3Kszixo>u+PZ<<(1|?9$frhG=nROQk*&bElz!RZ#qyx< zo!R=8cDJEw5eX>Y?b&J2ZNT-8+WdU{As+(GIiP|H6!FOG2Ktr;m^{L%D;OmpQE{6%a?Mz9uiJa@ z!04UQ*e#+tROZ;y?%ia~EdT6Bt|}SaO|J#mY%hE5>R$ZdhRQ7!1K_NwKiN|!HFY@M9W6~Gl=08zv6_w9oZ7a0MhOwz^w+<|J>2|P{997`;m!}w zCAlu|dsp(f!b)W2*TZAw6acB6M+Q;UzM6EiQXVt6|z0 zC*7ndq~^io2)8AjqJ+~(o5LX6)@$}(@79;6{OdDq!esc{$1T+J?E8fFv2Zjj<|`7U ze*65y5WK@{sKm!*)!JG<2oiBtjELXg+u&v0nQtf~7a2*D=mHthBoJg6n3WjE8JQQX zTw(=KfQ_{QC43p8H;QP>y3U z_443u?=2_eUb>tsJ(o0gPEtLvZPf%uP)W6xEd2Of=WT1zKd3pMZ{>vI#hG5{k@5BT zySl@)3k%Jhq*#jp+j{g{4cMe3@UEx}!SsuNmWgF1_(!9XcqB{J14NTDj(Z+b_X*Vd zA1n2e#~&um?xy+W>=o2#Tt2+)?%q!jN#m9b)$mZ*TYf*=ok)}W*^#nvc8Unb zDcfZJTe2ju-YmPPxJKk9vBkzhP+7@Z@)M)9N2tbrX*rX|izdkSYkFB8z8u~TJ$+fF z=9K@KwvMaV!3zd*DLwWjm8OhI#wq>!R+K%fESSO0TeH6Zm6<;GRdpdoq|Zta`_~QN zxqeEngF`52cFDruXkgTvPhoi%Ss%x*Gf9s8=Tz_T>T+Hhq>PncP3IO`Gu^##o?jJm z{WWdaJW*&FypWraVrmV!-T4emQF;Va%@vmWiBj3=nc%uX&s{l1mpgl+z1xOI6ps+h zs;%8AZV~89b?P}O3p*{=EkTKiQ(}m(?D@RC9J=Lm60$C9ztL~UgKyYv!I-Blu|Lln zG*`?k^H#F+dt#Qabl&kjRS)E;64jhkvxI(HxWt2WPecJJUfIFt>HM%9yx{rj$8e)2 z(lRUWgxMel*8OV9j@eaJwfQykN)sPrhxhVqk}}L)4xD#1)2%0t+|@^UYRNrUzn{_8 z50k#Vw(@17O8J*~_Eb#owH=N&|1FAzaOY)^F85;+h+2DF(q2iSp4MIW$0BJKf-D?^ zld59%5FMgFxcr6F1bj7jAvraL{Wu+)T{lFYX7YBmu3nITmJ;Izme^qL6RK4gL4+lu zRPx}ke`A+l5(0XdO!3xTVpw6|xY06<@9HieK6_6R8un!$fjO@IMe|I!JBkS+ zh50b-Yk&;c9c=qZ%DS=F0v}jsPV|)@{6>|RwlKr)eF7C&j`6G%HvyJu3N>Ml>g;mZ zQ>Z7hJvFh_i$j0etqI~)NUpAFy_8ubly?QSU8x}(RHdIKCace>Z0Qh<#16caeHNV4 z9d(8N=7{pkBy5bYag3}ob(doeu3_&zsAR`W(S<=+2N_(KasIZ-gFUfw>&Dm#BMsCi z{8}O$&w~k5Rq)=w5*e6aWFPT;2lvVj@{3yiv&;B9kxpZb>=n3|%XA>_Lw%D4hAXT4r&W1n+scuBuk5s=x*ge+Ch%BIUh>;Ro_eD1SEr`2u~W^;t>vZN|E!alfs^4Dx8{?;R(H zaeC#9 z%F84ji=3nh@3wyMf85VN9l_XpLr#=ahJw94yTrJ z(Z_6d?X6GYdp5IRwAQS?)O@MF;^#nTVpeW`!cEyr+d_!%;9*1&&){;Fi2XuyhnB;} zh|s=`!I&DI-I^%UW!9cs>ahrf7yFcT@2>v_k<1X*xZ^?%d(PF%s28~7z)4r$LO-|xFTLYM;=Ws z{L)QcpQl=x&S!pV#9KxUxCWJCzVMeZ)ek=pCVbmM>|~d}gI_8XvkwR)EdXhDY|AV_lQo%AtwL(VZW{_W((h#`nbkL| zoT!Db3iu-iP7~t;)@@f4ylg_Hj8`$&J+X7&h-ctS$yb3jk86c%9qAr&>`s{VYg4_; zzu+KM&oV4})zrW=Pa>7oCU(nvCF#X2s6@Vmhz@TK_h+qs1dK><%TN{bL+vd2AnQ(n z0AXHcASxN3Jj?>i8~1#Kn6vxu_7mgQ>+!(^qQlFI9DE-ngK9ev>jyS+cbS)WchSC< zmlY%H1$hOb8yj{j-0&b_aOeyJ=SBMANaUPnZO8BJ=Mg`?CrA<^L-$_^U6RIcI8t#O zB*4(Itu^l;{6Xx&ds!`OoElugca8>~Fc)&+Dc{cdGLD0HWaaP*%fsTVTaAPz+-v7ktxS9SblW^l|F+Ye|lyei1B-TFt@o zm!dPrWY99te<8ia!SEQ&-TI>g&W7~*E;@ue<&f0wqj?Z{z1ar4HC!|vi=%7l!*rMD zRH)RGpKqR7dEn#wJmCjTfu|FGp_`3fOuY{Wo#sXHQItXJWwr3ul#JS**zmg=PoxJm zJT{_c50hKK&yEr@0{%GCoB*rwOg6_K-ZDvM@8w#Z9L4E(2ejnOOSv}FQT5$-K?fw~ zT87ofoi+)LPI{|KT-^J!pF2S?w=e%Difoyv)@}aU65i1O$pj4fO*sE?98%+*8)PPo z@7F;?&%pX1O$nsBc}fsf_ztrLlE>TTnm~zmB`~Y^QjH_d)hDi_EsR4FL}9^Pe78B@ z)5oZ`U70-_&3u42`@s1jU+vc1&-7?lO%ArwM;b)t2TSbxNcz5bX|~Ro4-v_N+@29W zqBNW&RBlw2R*skB_U?LEwfA>5pBcxDYS2S98hWIAfah7@d*{47W#F-`6&)i0y|8n- z`_p_hCB#y%vvxXawlHV?!O@i}PEb*=I^0K8%y&#P8~S zQRCcP1f|TXJ{>8>sap%^CNTab2eyfS-&&zF9J~Ae=1V`E=y1QwDG5u8indE9GnsFgnq1Y4W5ZYnhU5@kv ze?-=O{P=NgAVsJGm!+GCL~qb?RNvM@%Qx;4D$e4J~KO zNzvf4GObUYK2mOKoGCHxcp1`yc`z%$HO^=6)<3LI^O*hlZ=nY=PfC#|Y;5X(@EAW5 z<~Wx>l(hrNWYRxkgQ_AwkGZM+W&& zHk9I7fW`^n&~}1J3@lC-Lw0iD0o}n5P0-bj7oU%&acYXp9~VX>=%dN2)aXjx*$_1q%6B8I|wRF;l(NF}b^k zXE6|!qlkM2$8dtrf1$nS#DQf`{hI22Ada%XEi}_`nSXvu%;|-+2pyLtPo2)^e_E2z_4S zf=WUW1Lk?WB`L}qBav5s?3JZzgWcI+?d<4v})3^T~+vxOxZtD8j3QQN7u4N{;R+x z?~N2|TaVUNGjhmYiU@9u`67H5mASdx3z=KVIR9*gQqaj$phY5;WK7QU4X5Lpem5F% z2*JPEE&S0jOTB^UgnjXoYL*oE@l^4W_=ld%qe>Agjl9t|25Veiyxod)Flc**-FTmq z6W*mLod6#3v+tL0f_TE2KO8}s*;U-pF@I}P8uFhzYy3IX3P$uo)=aHyowjQm%C8r~YBNuNKzMmLyxvoF z+-CaYopxbr`TD7LKbZVKryq`$Ie>2e&@vL@g8c^+NVuWtTb*axnGr8+Ao;{Bh+OEs zF7x*ZHF=?^4>`TwL36;TK~5SNpl66kQqNwuQ-%mjZ+@;yM|ZGl5IPAL;=#K|e7MGM zPei8^Zl`@egnDjk8^T#oS|d%-wHHi(T7u6RC~+?Y4!cC-ia8niJ{69J`RMVyyoiNP zL-=zyc70p%1K{B+FC-Niq9L&{d;Bd8vmvRR%}Alb37RMZI>)9w-#PZezEM=5>o$E|ro}#Z z)7#UZ25Nd<=i%NaNx9wyuy&;Cfi!8x)!BUpKDSCqI&3!tU+4-W7*>J3KIEw1h&jL% z4B{5a?DlVaVAH+~UET~v+$lIU8otEmBjN_;nggFdpR^7Q&d^>>tGwwhDRVqO-YWmR zSHg)?m%KpUneOs`8i@k^8Hsa?40%Ph9>JQmTc)>$W%P7w5SM6uKM^tYMonAXv{UvS zk`_rQ;TxB}X2s+u#u}fYEaF_Wz(ka7o&G{VZpZHhG&o{52A{9L0ud#`syd)RN)w3X zB0|yJ{}zfSRof6U4oDNG6c232(>~^vxl5!5dT4!AD zOfBnJH<;=3A0smXMGV_Bg;7nDaau({Uq!>Z?>K$Z&RUlY>7M@XL_?X$MS*NM()umE z%f^^_Xw4Ya2TpI;weOSL35A(dG%T3~T0Pk@{v8qhGedb)}pvVl{3dcA$3GS{NL;d_tgtI_yJ=$Hm+!c30k z*!-%HNqQk1p=t@bcD#K$FMfto(tdXXBOrRb{SH;L$N5|@k{>T%MC5@rt`0YCz1#?L zE~LbPaPo`^MP;}j%AAfi&N{QEbc!1&vh^f|QNt5h9E_-v0Q>6{O*z*+Rh3CMz;3xW z8auObZc<%a9YyU4-XTeQHS#iFDI%wRc}v!6KtD*UT*PA}1XU3A=+Jgaw9+?o|6^D+ z$uBI;!X1!KfSmAu9P-%sycgdgcUA=pTCQ`!zT(Sg(P6U4-} z==YY6nEs~-;~Y&=A(4jD#qYws_#*O^OQXB>1YnsZ*-F~=^{QAcd=LlIK1WH)2y-0`>&MYFk8w{A$)bM(4w^q$(Dh7~IySLM zDsg7mH0QKU@p2E<5ZQ(c4Pua;elI#8RnU{H@EoAe_4-FJ*+s2|1>*JNumemmtHbH( z_8CrVyp7d^&6denxsnhlUCv=Tp;Ej(QFoY?7cNnnomFOq=b(?&9#k2E5y~oYz1_5_ z5kt~cqw?adsv&p78rJRxW|1xeVngxmWTE@air7~!vbn>%x`pFVs5=5bXvA?RI#31- zlZZq#!$tph@HdMVMo#tr@jl^xkP2mHhF+bW3pso8!J618z;j`-+R}~r-gITWs*h=M zR0trMkaKBHtr>jaX8Tx_#zM+s10~}e>o;Z_e+s32A6boqF!KT5I4wZ~m zhpjvZ`#1greEH{wi`dX*_buqcjK@luIDd`O-;oEJXWWCwJ-f^Ymvu8vo7}f}BO&b&PNI?9 zw22CgoLHjVr~y2w!F%py+K(yJw-82-8+41&vxi`VJuzF}z>yYB@Pf!pCL!GBGXTRe3~-Vjja>4JMXrSMIW zQaLlR&{{<|NrL~tfgR0sV?^a(DheGd+otrWxewHR_3m`GFBVk)h z6){Np7o|YpyY;>Mng4}z$6p9KUgi*Ok)(`8RdtIjQw2ECmFA$-Qkg{cI3tOXOKK92 zZt2w?W-&cN^Y2gpdd)Dudaq@z#*4dS?fSEqlASKAw3VGE5st4wRZ&U+3tDIx>!O}$ zMbQ(JEi5V5=jR{g6Uks2cM7H_S!5t~lm%q3hpIL=R_<2n|FJQH4>d=*4wWIa_S(a0h?EAIy1M z*zi&=*Ortzl86Lk%BPUw0dX@Oscs7-p=A$RO!Fca>7F@e&NZ3fi6mN^5wkC4t0dkw zT1I)y0OfYnmuwor#I*UoIr77-dJJ=G5rgczL|g&Pq=+TzRzdil;xusrHp*&6cCZT# z=FWH7xrYC6P&;6^m+}fpF>$a5=6DZB!8lN+)4WX0p}TL}pf+B|F%o7$fld}s*^&D+ zs77Q*jEqguAIxa=`N*>p_RWj`fw|Cw1xq5`gWAXw=o5M*D9E=308N$)HQrPV)D{>& zc-HHie$vYHk_+MnnzC*RQFmGs0FktHoPt7|;B=}&+QVW{fk=q_*1z9%6=4Ew^vagO zN8|3M65)c6HPDL*)rv91_MkkUFaO?XKKZl<*wb7~4I8mxL{x|WT$KIF?-&eh2)+N03M`SRho*gtSSil0plwMlV@ zNse9F)>`svY6k|ueM01wTrieMNsAihAP?rxsD=b~I%$%>?}Nxti-dFifLL*m5cO51 zEnM1Jf7yHacJHHn&gF`gryMAj#MCE0^H{Cbs5So;V`2oF+epy)BpYt+BgDX6rD~=^ za94uG%(WxswLYI0K=ltwG#}e>4z}*4dO$p@W+_4E<>EFltiflq4!6Ba_4s-7>~QsQ zm!?=UuQu&%M9{HnsDOMz{oZl?6KiaDs*84p(o=PZkC?o|lA^bS6J_`1Fw7+*v%(G> zL7US|^2=p^q{NynOgTndW* z=*PWRAbfpP9&w1Fe!U3g1wCJGA6m-DV-2?^uc2K3__gghNm=*E6GE9v%%>%jkVp|Z<) zOe{T?^T<=N_r~^^IQ_=X=9dl^WB0e*KbN~cm!$nOsO|HX3B#PrddgVfHv4O}F2ReN zP@C=0JKgG?RQ$v*zn!^1OcJh#8>gNq39&eTJHR*JabYv>rS#f4?CQT=J%2T2L!YLi>w0C}VE>SCQK7jP5p_ zv0fyhp_M`h?^Y?wsr&w8qW2qgd@uv&_-_s%NC{Itu`qIe3d}I$3l@qCvuvzS`boNQ zTS5Y&_4Dygz(WlNi^D?qEjWql*(o}|GxCIWyZ{x5YQBcLSK8P$!46| zXQ>F;5bCJ#Bol#da1suXcyk2p+!GiqlLf>o=9=wIn!8zuY$iL1>aNxq_Qf!TzxKDy z#yu1D>Mbgw<>YRZ_bo^e0VLQb+GzR7f<|kPX=`OW@AQB3Wt{7Qu-E!e{w4FZX-iUF z?lE8Ws2_)25Liqs*4#er?sVVQrw&`N9UIpi3b>Cb) zdpOSV(DR?X62$|4YXrFJDe(3sIi$V*_Qj!DU}M3Y7AKtt@ILP``15TlANVOU$d z@@`L*=oQ&LmA}SGn0^gVmRA>Lfvu%T(@~1TlK!Pql-G|cPP(e|4tZSTI(`geTghipp^-4tI3384q5$nq_# z(xckbo<$0~0^PUPl~1xQYDk}qFYi!k5ME>Hg`dZpq=bwTRt^z2fX3h?(J)-^Fu`X8 z=`+kj7I&YK+LI?WTEtY%d96t99o0bsE7bud%?w1E3f*bCc?==aq@+GvXgO6OulvE^kaRFX?J(G;^z%6%quHWtYqp)$s8@rBphMG` z?siMnXinztdh=4>aQ;yqAUVpE`4dr-7uno`Ru(ctT`*b1g15VbWili%m^?=vi(dW` z!TF3+vY4LPz`s#|hb-CFZ7dvVgm_AC1uFPkLcQEU1q<4s7IETt9*6K?W0dKbU#UWb zFKxM+iO1vK zNXOt3ir`L3GjyHAUb(&(gTbj}oLy zOZ!I_*K=o$;Muk@t*Z(*&q4xT25?MXKi?nX$)#F23I|yYQV*Yip8MF4XudjS>U|m6 zq!YD9t#wD1AnAaeeCuhBSzE(LJFCA0Sg%7+byAf)vnF?!mStv2{!syN@Y0iwqa?GA zSU26;X7C?s9_G3hBqkMzi}8KV&yQsr$T_UkG`-dD^wW>->4+9_*%aiN;fz%Dn<9yR z*Mq4hUo+CxvD5HGH+i4T^t9_15ly5^gg$~zl7KU`V@KbNhd|tl5lN4 zH7IzGp!CR(Z0nE$FJ(U9F5>@_c^|ZXly91N^jxA%&}To<<3mrPL><<3Frt|VSvS(R zsh{j(1u}R3G>s*db%n|}E8Ieqt4&*A!l4qQINB}kMl+$LfMp9iPD4PH(_0lUnV|@# zcs-FL{U8&f|K~B>U=XIZpPLCw}i`` zPv&>0oD#YATPkS2!=K$w{Nghx#5tX7>;JMU!PM7HZl=c7RD0OmQSiZo^!Wb}lmsuk z%SHV)MwJQYc3N2U(N%`JX3Pi4AUnX+2(}!m z$j)N+hJ~+puPcCA2!mrssVSn(7iw z)(D*t03BH6#~Q@#cqhgi=TfZd8iJJPv(7e8{Ez-bKl4qcxHI%VAS`;vyBeqNffO-O zS_4uRaKZ+_YTwwb=U^P?|vN%uRE8F{7QSTJi;ZmZVgE_?^sVQ^y+nA7U7&V zU~s3q?f-Ykzc-Hg@I3~v`jUbmf#nt*aaHKJMw5~|L&e%#vfm-#tcil4I#WiPK@8oKs^~PNBq&*l&NsK00y|4q|w+_vMr{=Y#hH_L5u5 zes7w0SDl*Br>%6dr^wVe1_h)on=xmv$GfQ_#^Ox16L=F33M}noU&N{R-7#o;^4{#Z zl8_?>r#pmanS)vIH>glb{eY^a$8RuO{$V3KX7SQUBMDx~gx?V+-}h?DBVFSRrn)bC zH8dr&_D(D}0h4>yrvy%dPTl*R{y=>9BOFnZ%FT#J$ z@i4rq{Y*^IE~ECn1P|2vpckD3sNUQ~E5+&2@A4dX3q!*o%WWXx?;)1&&2(UAuREE1xT98q!Mkpe)ecYB@;wZYzIk>;l@7oabSM3@zhM6kyrX@PaZz=)}@`zktIWN=Int5 zJ_Mj~=y-fzj5wA&(=J%|??U3*a`avxoe?A7Snj>jwUh z|NT?*;MH0|d~LuwW>0d!ZmH!jQ@M)(SPYuM2`IbHa5k0Y4TZU$nL%C#A&PtQA4Fcw z7WvzFSONvkTk`M#NEYvmMd#JiPxT+ERX|d_Z;xbLooU0t=xsu`2|F;qN`C^|Fo*4r z1Q7+Y>I0v!R1%V1ktZNB1Ur#2uD3f{tcEl3CB(AD76E-`h_t?w=yDG#`f;Q}NjzdQ zJ;xU+jHQFz-zW4TEB{C~xYuaZ+5(astS>=z_n23PEb14oOj>>B6wSwP1Ukd*k=Y%R zZk@v#hTp|CL0g>_)zKg#s{?-7jeq9@?RVaVVp(|KhK3R{(C03Zof;DFi+EtEAq#vk z4ZQ0JBTcKRn+`N2h`@4dEk#6q<}cGLu5P(ud;PX{Kg0rW_t&@GYK(e>oEb&F_KdOv z;R*pJzpo^Swi&$_y7Dl`6l)v{Juh~dgYSn97~*CQ1OwUrt9_vz8q7ecE({y{;wV7; ziUiddXqO6%;n$JkHtwT_mwwi`aNd+7{XmT3rOSMZ~#^*!HGQuNN9qcO2WPQ>I**?vVcS%20%-A!Uv@PRv)|$BVD+4 z%g9SpEKg58ZgJ1s<0h|$yBVXU)b4e@im?I7AZ@;4^Fc(~_osanKxBow95xLwnXNT zI*Q-~-sHYPfRsAHlG~=p61JFtVvM|#8f|ma2_Rw8M!E)XswTV`vnT6*>LaO+O~Bm7 z#U@v3`p2~cV+(GfrrjTjZQ8(0L<0t8VucZTfHDv4bfls?0=iENF?udRL;vG#Cey$@ z4#kofjQANA@7*mYSY#P1G0c>YEHDM1qx-#Q+9fb03E5~t$Rn2EkUH8_ktGrY zLGNdK5jcn|We37Or)WUj%B0;uYmdp({)RQLSFFA;Vsm8USn=}Rd z8+Vkzgh8v%be+}N*aGV2rhbu=Y|4)K%@^%dk+swwlBO=AKmVVit~#p8?{RMg9<-7rL9z$od4(JiewLeVi$B&0+o94#e+;v{}ApYI>P``0~Z z@7{CoJ@2{k+$WBIODHGa1t*j2Y76T(3s}b(2efqCU&}s+fBO6ho?i@YJ`s za;YV4+9E5~rlmzyQ<2CcO|giZe@IEc5Gx~^r{Vu0Xe5{lU+?U2Kto_%8d`n zw_b$ic1@`3VvLdXrv*X;h#teZSw@R24DOMf9x0>^o)|P|xuqz6^^uY~q`yZ z-}Hij0Dv-7;KRa;d-4$jkEpJsZh}IorOLk zUhI1*Y(FIW{RQ1J21*`08~{U%w*Mw`f?|I{_DOP$GH*J86O?kc!eoPyH50?*Q@7~E z9uDo~qO~#hYfvq&p4Ls?y60hkwuKyzFX}XE*mrBZ{K_F93&QT(oT}ArwylOiCgPJb zX?}C^E)OPi;>;BsLgr?2jEhz=X{y57>aE0{>NS(f@lEDSH6Ui)EO7gx8;nnyl}-;Q z)jw2?&49y2wZ^a+Hj?W)2tgHQWjX!#G}^IJx|hM9FuU>>7AilOQHzA~LrYf7-||no zlkdz6JBdr2L&9v1!M=Dqk4X?*M8DT|I=yQ-r`k^fONbVo14LSAbwJA17i?oQB^Rt% z$>&0afJONx6Ts)0dO~2bRHN6EWmcS zqp1d4;b|b=a|w_RM|^fwtdTFZ?>FU70*QrPzlyb=(z%4*vY}JV}kC{}V^4O#iy- zSd7R(Uh}Z6S)$8`Y!6+pJ;AJb>c_6Yg-^nSgg3~jBAtz&p1syM&ho_Q4nskFWAh1$ zt**chhVYExu-*v6O#h0=-~>uW_;)T= z6vL*y+T#Z22zZbv6A&^b$1m*h2=S#(a{P0j<3=(SFT|Xo+Te8db}b>v`Ljv??%#=6 zjWr&SWt_^tVLcq-GDbsxB*G zry~%y`E=;O>zr{_mrV4RAcN0TK~_yx-RTweKJj*pEY)dzRnZQQ(0&@7KgZc*+tr-K z-I5}J!_+Nc7J7@3d5%{i4$<V99`u=jJOLopy56C0)@JANujl~_sgn3IrHJTN?5Lf zMG1G=s4K^N4$X>_9QiQO!Zo)+KNc8%v?&;T7Hu#dGW1dDkrj45IDX40{C4?(dGAvX z<r^Uraic8 ziObjV6qkGZfsb@$+DUq`Ts@bNa}=oR>DPmSp#9Mw1}HvqUwo-?0hP;k`X}e(>{}D- zd09e^-u&9K&8l;UGja$krRe?9hfxuD7gU*JBQQxL0dDQN+%<9Q5111QgQ!rG4tG@Aea98v_hRWTPNg7n^@U-Ps=HiqwZ@iT2&#XVT?HB1l zjcCiz!cr??feW4oUs|_o45^b9;WSUATtOFJhDt{K=@pP-E*i{tro{kkXKzF@0sQQz z^M^^Txs5+V39DWi=DLo9>`|O-I}Oj8yT(}~+jQm>6#p_5@5jk4_0Xf#)2P&cZZHZP z0GZG=>E;km(&w4|v6ED#2uhO%#*0A87ytQTtke;dpw>N06Q1T{*}0Ph@1C||;Csm~ z#wI(rRNho@nQ}{4{a_^3#eXP*ve07{@9X%FqEFn%M22nQ02jMMxRk7dLxE6e;s~gTk)c_~oPLR~|apNEDJuXae)24<6!;EST!bZ#qTF+XS%Xo@i`O;J|ICd3AK|U|K z!)>Bm{uoEmko$0=sDM$7a4V^(PV)hs92!lO(-nbxx|BF)uR9c6I(SxS(fKEgN(5tN zUvQ1E;mxmGF5x?xrLp)rh?pY4g0SjTXiLI~_5BHZy&-t21ltglLL|8D)P0X)-{o(i zaUfbFu{^$uo7IU7siJ)onj-=M8+ASk+_M&0o=I`-LFA{T==urclwtbt10-uvsmIi& zYoJ>CzoFlM(gFpv$)vG9^L;jNxYWV8ZP$is7X(K|Xhm80qd)OOybCAQVz9Ah(hP`< zF&!M#XP8(ml~o)q*%s+jiF!GTM6^W9dmX*tp*jHA8UX!O%8I(c1QZ)0E3D2s^sE17i*Y*xeub zty77LdBDlrHvL8;I%o^ap#Mtfo%gY=|BA-WH+6T9nzcyL(lt$F;M9|D36SToge-X? zHTU}ca%%B^C`pBvUjfz1O=Nv3Dx|M--Swb$qH|0@B&FaN92mjksLRDa?hajq#R zXlKCAfnBai=YgiG!wObus(8X^Ay)tCFF1R>W?>9?P@bM#cB zj{)i?`r2o&jY$Sgnl-(nXa=fo2Wk}j7?5<|K8sWjq^>ONhdwTNw6b3#TpZrg{r%Ej z^7ffVJ@V^3v1Is$f|5@l5LVGRcozJ4x|3&RfjMPzIw7}JW<{6=v z;+5S8JzyUP4z#I_YKKbU$+Rp<%Pb|F(MpW*N;-&-tiNx@ndflww~QB7f;dVbVtYX| zPkNHJsNFX04?D)*_+)Z)w@z*cxT*hhhEz!?&&gFqr8QuubH_+wU+cb&HLAD#PJYoW zUrC%&Z6tn9OPCdq+Y91jei`J%HM`g*+H`$bOiX1B?`YJ%r}07t_USdyRKeUV9aY(u z`;%G-I`00BLg(IVOD_hR(b^k~2)WV7rvpt>;eeNjcX1jIv0_i zRhT`_T@r-6r&)BIqjDjGPFaSp?_$XgU}{7B@qpiAXCzed`0N-N*Q6v^KBpyl&4%aN zf;tk|%`WI5`f{0BGwni_Gt*VKU%2=Ju^zW2dyn=8P4&1Yjs6Y(?TllOpTS_xF|0k@ z|2KwO>Gn#~*vS{?+U42n)c*G~i|27_WnngOZ%bX2Y_R|Egiu)lAyYjRemYxZCekuw7~3nG7SyVYTjID!eOh!Zm0ODCSF4oaI5sc?smLXL;!= zEIwTs(8ohEXu4|oPRH1IpVp%L^poeUXZL=&^EV(l^*DWyhQAUX6#;&Rzrz}Vk7#e{ z%(0fr5#b8^MFrtsLrT+$jypz`sfU zqr^-7z0HqiAfHzjqELiAxyKu+U6!4WIdAIRCU>lI_rJ(tya0HRp6)mbu(nYwpMMvtNu$8^WgO;Y91mGflVltEMc5ktX+P~F77K{!_2bjU_7q>%#+;

0USNUA?HcrsVrKOc-Fn$45Gv}Wn8 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 WI$m+U)$k4k6ayV2WaAB|$NvXYVK6oT literal 0 HcmV?d00001 diff --git a/docs/team/img/TopicList_Topic_class_diagram.png b/docs/team/img/TopicList_Topic_class_diagram.png new file mode 100644 index 0000000000000000000000000000000000000000..4d5c3baf71751d4b54917fb79833ae453a84fc37 GIT binary patch literal 67111 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�E* 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 Date: Fri, 29 Mar 2024 22:54:46 +0800 Subject: [PATCH 103/334] Add class CommandList to contain possible commands --- src/main/java/seedu/duke/CommandList.java | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/main/java/seedu/duke/CommandList.java diff --git a/src/main/java/seedu/duke/CommandList.java b/src/main/java/seedu/duke/CommandList.java new file mode 100644 index 0000000000..bb5e91f4c6 --- /dev/null +++ b/src/main/java/seedu/duke/CommandList.java @@ -0,0 +1,4 @@ +package seedu.duke; + +public class CommandList { +} From 3c199e518bb1582f826ba35f31a0441c20d65aa8 Mon Sep 17 00:00:00 2001 From: yuhengr Date: Fri, 29 Mar 2024 23:03:58 +0800 Subject: [PATCH 104/334] Add skeleton for class CommandList --- src/main/java/seedu/duke/CommandList.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/seedu/duke/CommandList.java b/src/main/java/seedu/duke/CommandList.java index bb5e91f4c6..3d3707fdf1 100644 --- a/src/main/java/seedu/duke/CommandList.java +++ b/src/main/java/seedu/duke/CommandList.java @@ -1,4 +1,16 @@ package seedu.duke; public class CommandList { + + public static String TOPIC = ""; + + public static String BYE = ""; + + public static String SOLUTION = ""; + + public static String EXPLANATION = ""; + + public static String HELP = ""; + + public static String RESULTS = ""; } From 1ee5b65a4cfebed370c4dda1ebc09422d370fef7 Mon Sep 17 00:00:00 2001 From: yuhengr Date: Fri, 29 Mar 2024 23:46:10 +0800 Subject: [PATCH 105/334] Add patterns to parse commands --- src/main/java/seedu/duke/CommandList.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/seedu/duke/CommandList.java b/src/main/java/seedu/duke/CommandList.java index 3d3707fdf1..36a7574cde 100644 --- a/src/main/java/seedu/duke/CommandList.java +++ b/src/main/java/seedu/duke/CommandList.java @@ -2,15 +2,15 @@ public class CommandList { - public static String TOPIC = ""; + public static String PATTERN_TOPIC = "(?i)topic\\s*(\\d+)"; - public static String BYE = ""; + public static String PATTERN_BYE = "(?i)bye"; - public static String SOLUTION = ""; + public static String PATTERN_SOLUTION = "(?i)solution\\s*(\\d+)\\s*(\\d+)"; - public static String EXPLANATION = ""; + public static String PATTERN_EXPLANATION = "(?i)explanation\\s*(\\d+)\\s*(\\d+)"; - public static String HELP = ""; + public static String PATTERN_HELP = "(?i)help\\s*(\\w*)"; - public static String RESULTS = ""; + public static String PATTERN_RESULTS = "(?i)results\\s*(\\d+)"; } From c2ab756a13e78769c3bd8b15167a98a624adcc56 Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Sat, 30 Mar 2024 01:24:43 +0800 Subject: [PATCH 106/334] add timer mode --- docs/DeveloperGuide.md | 3 +- src/main/java/seedu/duke/Parser.java | 22 +++++++---- src/main/java/seedu/duke/Ui.java | 58 +++++++++++++++++++++++++--- 3 files changed, 69 insertions(+), 14 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index ad30fc8af7..f55ba6b355 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -43,7 +43,7 @@ the `results` command. > return an error to the user indicating that there are no > results. -###Topics Feature +### Topics Feature The topics feature comprises `TopicList` and `QuestionListByTopic`. `TopicList` is the list of topics for the users to attempt. @@ -91,6 +91,7 @@ Integration of key notions and learning learning objectives for CS2113 course, s ## Non-Functional Requirements Usability: the user is able to use the app without reading lengthy documentations. + Technical: the app should run on both macOS and Windows ## Glossary diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index a884c2005f..5d3392a398 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -24,6 +24,7 @@ public class Parser { private static final String MESSAGE_INVALID_INDEX = "Index must be an integer."; private static final boolean INCLUDES_DETAILS = true; private static final boolean IS_CORRECT_ANSWER = true; + private boolean isTimedMode = false; public void parseCommand( @@ -34,20 +35,25 @@ public void parseCommand( String lowerCaseCommand = command.toLowerCase(); if (ui.isPlaying) { - - if (lowerCaseCommand.contentEquals("topic")) { - processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, allResults, userAnswers); + if (lowerCaseCommand.contentEquals("timed mode")){ + ui.printTimedModeSelected(); + isTimedMode = true; + } + if (lowerCaseCommand.startsWith("topic")) { + processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, + allResults, userAnswers, isTimedMode); + isTimedMode = false; } else if (lowerCaseCommand.contentEquals("bye")) { ui.isPlaying = false; - } else if (lowerCaseCommand.contentEquals("solution") || lowerCaseCommand.contentEquals("explain")) { + } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { processSolutionCommand(lowerCaseCommand, ui, topicList, questionListByTopic); - } else if (lowerCaseCommand.contentEquals("results")) { + } else if (lowerCaseCommand.startsWith("results")) { processResultsCommand(lowerCaseCommand, allResults, ui, questionListByTopic, userAnswers); } else if (lowerCaseCommand.contentEquals("help")) { processHelpCommand(lowerCaseCommand, ui, helper); } else if (lowerCaseCommand.contentEquals("list")) { processListCommand(topicList, ui); - } else { + } else if (!lowerCaseCommand.contentEquals("timed mode")){ throw new CustomException("-1 HP coz invalid command"); } } @@ -111,7 +117,7 @@ private void processResultsCommand(String lowerCaseCommand, ResultsList allResul private void processStartCommand( String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic, - ResultsList allResults, AnswerTracker userAnswers + ResultsList allResults, AnswerTracker userAnswers, boolean isTimedMode ) throws CustomException { assert (topicList.getSize() != NO_RESULTS) : "Size of topicList should never be 0"; @@ -137,7 +143,7 @@ private void processStartCommand( assert (topicNum != randomTopicNum) : "topicNum should not be randomTopicNum"; // prints questions - ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults, userAnswers); + ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults, userAnswers, isTimedMode); System.out.println("You have finished the topic! What will be your next topic?"); topicList.get(topicNum - 1).markAsAttempted(); ui.printTopicList(topicList, ui); diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index d986c5c0f7..e93373b3f3 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -6,6 +6,8 @@ import java.util.ArrayList; import java.util.Scanner; +import java.util.Timer; +import java.util.TimerTask; public class Ui { private static final Scanner in = new Scanner(System.in); @@ -62,10 +64,13 @@ public void printTopicList(TopicList topicList, Ui ui){ public void printChosenTopic( int topicNum, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList alLResults, - AnswerTracker userAnswers + AnswerTracker userAnswers, boolean isTimedMode ){ Results topicResults = new Results(); QuestionsList qnList; + boolean[] isTimesUp = {false}; + boolean[] hasCompletedSet = {false}; + System.out.println("Selected topic: " + topicList.getTopic(topicNum - 1)); System.out.println("Here are the questions: "); qnList = questionListByTopic.getQuestionSet(topicNum - 1); @@ -76,15 +81,46 @@ public void printChosenTopic( String answer; ArrayList allAnswers = new ArrayList<>(); ArrayList answersCorrectness = new ArrayList<>(); - for (int index = 0; index < numOfQns; index ++){//go through 1 question set - questionUnit = qnList.getQuestionUnit(index); + for (final int[] index = {0}; index[0] < numOfQns; index[0]++){//go through 1 question set + questionUnit = qnList.getQuestionUnit(index[0]); topicResults.increaseNumberOfQuestions(); System.out.println(questionUnit.getQuestion()); + + if (isTimedMode) { + Timer timer = new Timer(); + TimerTask task = new TimerTask() { + @Override + public void run() { + if (!hasCompletedSet[0]) { + printTimesUpMessage(); + isTimesUp[0] = true; + index[0] = numOfQns; + timer.cancel(); + } else{ + isTimesUp[0] = true; + timer.cancel(); + } + } + }; + timer.schedule(task, 5000); + if (isTimesUp[0]){ + break; + } + } + askForAnswerInput(); Parser parser = new Parser(); answer = in.nextLine(); - parser.handleAnswerInputs(inputAnswers, index, answer, questionUnit, topicResults, answersCorrectness); - allAnswers.add(answer); + + if (!isTimesUp[0]) { + parser.handleAnswerInputs(inputAnswers, index[0], answer, questionUnit, + topicResults, answersCorrectness); + if (index[0] == numOfQns - 1 && isTimedMode){ + printCongratulatoryMessage(); + hasCompletedSet[0] = true; + } + allAnswers.add(answer); + } } topicResults.calculateScore(); alLResults.addResults(topicResults); @@ -92,6 +128,18 @@ public void printChosenTopic( userAnswers.addUserCorrectness(answersCorrectness); } + public void printCongratulatoryMessage(){ + System.out.println("Congrats! You beat the timer!"); + } + + public void printTimesUpMessage(){ + System.out.println("Time is up!"); + System.out.println(" Press enter to go back to topic selection. "); + } + public void printTimedModeSelected(){ + System.out.println("Timed mode selected. Please enter the topic you would like to try. "); + } + public void printNoSolutionAccess(){ System.out.println("Attempt the topic first!"); } From a8111b5c28443a525b897012a43294f3c81b5c5a Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Sat, 30 Mar 2024 01:33:02 +0800 Subject: [PATCH 107/334] fix DG formatting --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 61264df673..f6f0fdd8f8 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -44,7 +44,7 @@ the `results` command. > results. -###Topics Feature +### Topics Feature The topics feature comprises `TopicList` and `QuestionListByTopic`. `TopicList` is the list of topics for the users to attempt. From 74f06d660de18f0a96d59be4a6a16c91c8f94fb5 Mon Sep 17 00:00:00 2001 From: hongyijie06 Date: Sat, 30 Mar 2024 01:54:18 +0800 Subject: [PATCH 108/334] fix timed mode bug --- src/main/java/seedu/duke/Ui.java | 35 +++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index e93373b3f3..40b20e6d24 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -87,24 +87,27 @@ public void printChosenTopic( System.out.println(questionUnit.getQuestion()); if (isTimedMode) { - Timer timer = new Timer(); - TimerTask task = new TimerTask() { - @Override - public void run() { - if (!hasCompletedSet[0]) { - printTimesUpMessage(); - isTimesUp[0] = true; - index[0] = numOfQns; - timer.cancel(); - } else{ - isTimesUp[0] = true; - timer.cancel(); + if (index[0] == 0) { + Timer timer = new Timer(); + + TimerTask task = new TimerTask() { + @Override + public void run() { + if (!hasCompletedSet[0]) { + printTimesUpMessage(); + isTimesUp[0] = true; + index[0] = numOfQns; + timer.cancel(); + } else { + isTimesUp[0] = true; + timer.cancel(); + } } + }; + timer.schedule(task, 5000); + if (isTimesUp[0]) { + break; } - }; - timer.schedule(task, 5000); - if (isTimesUp[0]){ - break; } } From f16d117f3d82b15ed4fd9b1e3adafcad6f3ff422 Mon Sep 17 00:00:00 2001 From: yuhengr Date: Sat, 30 Mar 2024 01:56:04 +0800 Subject: [PATCH 109/334] Add regex for topic command --- src/main/java/seedu/duke/CommandList.java | 47 +++++++++++++++++---- src/main/java/seedu/duke/Parser.java | 50 ++++++++++++++++++++++- 2 files changed, 88 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/duke/CommandList.java b/src/main/java/seedu/duke/CommandList.java index 36a7574cde..3a992c39a9 100644 --- a/src/main/java/seedu/duke/CommandList.java +++ b/src/main/java/seedu/duke/CommandList.java @@ -1,16 +1,49 @@ package seedu.duke; -public class CommandList { +public enum CommandList { - public static String PATTERN_TOPIC = "(?i)topic\\s*(\\d+)"; + TOPIC, HELP, SOLUTION, EXPLAIN, RESULTS, BYE, INVALID; - public static String PATTERN_BYE = "(?i)bye"; + private static final String PATTERN_TOPIC = "(?i)topic\\s*(\\d*)"; - public static String PATTERN_SOLUTION = "(?i)solution\\s*(\\d+)\\s*(\\d+)"; + private static final String PATTERN_BYE = "(?i)bye"; - public static String PATTERN_EXPLANATION = "(?i)explanation\\s*(\\d+)\\s*(\\d+)"; + private static final String PATTERN_SOLUTION = "(?i)solution\\s*(\\d+)\\s*(\\d+)"; - public static String PATTERN_HELP = "(?i)help\\s*(\\w*)"; + private static final String PATTERN_EXPLANATION = "(?i)explanation\\s*(\\d+)\\s*(\\d+)"; - public static String PATTERN_RESULTS = "(?i)results\\s*(\\d+)"; + private static final String PATTERN_HELP = "(?i)help\\s*(\\w*)"; + + private static final String PATTERN_RESULTS = "(?i)results\\s*(\\d+)"; + + public static String getTopicPattern() { + return PATTERN_TOPIC; + } + + public static CommandList getCommandToken(String command) { + String[] splitCommand = command.split(" "); + String mainCommand = splitCommand[0].toLowerCase(); + + if(mainCommand.contentEquals("topic")) { + return TOPIC; + } + else if(mainCommand.contentEquals("help")) { + return HELP; + } + else if(mainCommand.contentEquals("solution")) { + return SOLUTION; + } + else if(mainCommand.contentEquals("explanation")) { + return EXPLAIN; + } + else if(mainCommand.contentEquals("results")) { + return RESULTS; + } + else if(mainCommand.contentEquals("bye")) { + return BYE; + } + else { + return INVALID; + } + } } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index a884c2005f..4309c06cdf 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -3,6 +3,8 @@ import seedu.duke.exceptions.CustomException; import java.util.ArrayList; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class Parser { private static final int NO_RESULTS = 0; @@ -22,6 +24,11 @@ public class Parser { private static final String MESSAGE_INVALID_PARAMETERS = "Invalid parameters."; private static final String MESSAGE_INDEX_OUT_OF_BOUNDS = "Index is out of bounds."; private static final String MESSAGE_INVALID_INDEX = "Index must be an integer."; + + private static final String MESSAGE_INVALID_TOPICNUM = "Topic number is invalid."; + + private static final String MESSAGE_INVALID_TOPIC_COMMAND_FORMAT = "Topic command format is invalid."; + private static final boolean INCLUDES_DETAILS = true; private static final boolean IS_CORRECT_ANSWER = true; @@ -33,10 +40,13 @@ public void parseCommand( ) throws CustomException { String lowerCaseCommand = command.toLowerCase(); + CommandList commandToken = CommandList.getCommandToken(command); if (ui.isPlaying) { - if (lowerCaseCommand.contentEquals("topic")) { - processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, allResults, userAnswers); + if (commandToken == CommandList.TOPIC) { + // Still under testing. + beginStartCommand(command, ui, topicList, questionListByTopic, allResults, userAnswers); + // processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, allResults, userAnswers); } else if (lowerCaseCommand.contentEquals("bye")) { ui.isPlaying = false; } else if (lowerCaseCommand.contentEquals("solution") || lowerCaseCommand.contentEquals("explain")) { @@ -109,6 +119,42 @@ private void processResultsCommand(String lowerCaseCommand, ResultsList allResul } } + private void beginStartCommand( + String command, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic, + ResultsList allResults, AnswerTracker userAnswers + ) throws CustomException { + + Pattern topicPattern = Pattern.compile(CommandList.getTopicPattern()); + Matcher matcher = topicPattern.matcher(command); + boolean foundMatch = matcher.find(); + + if(!foundMatch) { + throw new CustomException("Can't find a match."); + } + + try { + int topicNum = Integer.parseInt(matcher.group(1)); + System.out.println("You've chosen topic number " + topicNum); + boolean validTopicNum = (topicNum <= topicList.getSize() + 1) && topicNum != 0; + + if(validTopicNum){ + ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults, userAnswers); + System.out.println("You've finished the topic. What will be your next topic?"); + topicList.get(topicNum - 1).markAsAttempted(); + ui.printTopicList(topicList, ui); + } + else { + throw new CustomException(MESSAGE_INVALID_TOPICNUM); + } + } + catch(NumberFormatException error) { + throw new CustomException(MESSAGE_INVALID_TOPIC_COMMAND_FORMAT); + } + catch(IllegalStateException error) { + throw new CustomException(MESSAGE_INVALID_TOPICNUM); + } + } + private void processStartCommand( String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic, ResultsList allResults, AnswerTracker userAnswers From 86cfc79df0cca7b954cf9b910075c38b3e7b5215 Mon Sep 17 00:00:00 2001 From: yuhengr Date: Sat, 30 Mar 2024 02:22:32 +0800 Subject: [PATCH 110/334] Fix check error --- src/main/java/seedu/duke/Parser.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index f9df379787..22b8c38087 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -51,7 +51,8 @@ public void parseCommand( if (commandToken == CommandList.TOPIC) { // Still under testing. beginStartCommand(command, ui, topicList, questionListByTopic, allResults, userAnswers); - // processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, allResults, userAnswers, isTimedMode); + /* processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, + allResults, userAnswers, isTimedMode); */ isTimedMode = false; } else if (lowerCaseCommand.contentEquals("bye")) { ui.isPlaying = false; From 3950a1b0957c0eaaeaace239f40078c7b9749b76 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Sun, 31 Mar 2024 00:55:41 +0800 Subject: [PATCH 111/334] Fix solution feature bug due to lowerCaseCommand.contentEquals() instead of commandParts[0].contentEquals(). Remove explain feature too --- src/main/java/seedu/duke/Parser.java | 68 +++++++++++++--------------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 22b8c38087..8801d1f463 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -41,10 +41,11 @@ public void parseCommand( ) throws CustomException { String lowerCaseCommand = command.toLowerCase(); + CommandList commandToken = CommandList.getCommandToken(command); if (ui.isPlaying) { - if(lowerCaseCommand.contentEquals("timed mode")){ + if (lowerCaseCommand.contentEquals("timed mode")) { ui.printTimedModeSelected(); isTimedMode = true; } @@ -64,7 +65,7 @@ public void parseCommand( processHelpCommand(lowerCaseCommand, ui, helper); } else if (lowerCaseCommand.contentEquals("list")) { processListCommand(topicList, ui); - } else if (!lowerCaseCommand.contentEquals("timed mode")){ + } else if (!lowerCaseCommand.contentEquals("timed mode")) { throw new CustomException("-1 HP coz invalid command"); } } @@ -135,7 +136,7 @@ private void beginStartCommand( Matcher matcher = topicPattern.matcher(command); boolean foundMatch = matcher.find(); - if(!foundMatch) { + if (!foundMatch) { throw new CustomException("Can't find a match."); } @@ -144,20 +145,17 @@ private void beginStartCommand( System.out.println("You've chosen topic number " + topicNum); boolean validTopicNum = (topicNum <= topicList.getSize() + 1) && topicNum != 0; - if(validTopicNum){ + if (validTopicNum) { ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults, userAnswers, isTimedMode); System.out.println("You've finished the topic. What will be your next topic?"); topicList.get(topicNum - 1).markAsAttempted(); ui.printTopicList(topicList, ui); - } - else { + } else { throw new CustomException(MESSAGE_INVALID_TOPIC_NUM); } - } - catch(NumberFormatException error) { + } catch (NumberFormatException error) { throw new CustomException(MESSAGE_INVALID_TOPIC_COMMAND_FORMAT); - } - catch(IllegalStateException error) { + } catch (IllegalStateException error) { throw new CustomException(MESSAGE_INVALID_TOPIC_NUM); } } @@ -205,20 +203,20 @@ private void processStartCommand( private void processSolutionCommand( String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) throws CustomException { - assert (lowerCaseCommand.contentEquals("solution") || lowerCaseCommand.contentEquals("explain")) - : "either solution or explain command"; - - boolean isSolutionCommand = lowerCaseCommand.contentEquals("solution"); - String typeOfCommand = isSolutionCommand ? "solution" : "explain"; + // parser command String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER); int commandPartsLength = commandParts.length; + String commandType = commandParts[0]; + + if (!commandType.contentEquals("solution")) { + throw new CustomException("Do you mean \"solution\" instead?"); + } // checks correct number of parameters (1 or 2 only) if (commandPartsLength == NO_PARAMETER_LENGTH || commandPartsLength > TWO_PARAMETER_LENGTH) { throw new CustomException(MESSAGE_INVALID_PARAMETERS); } - assert (commandPartsLength == ONE_PARAMETER_LENGTH || commandPartsLength == TWO_PARAMETER_LENGTH); boolean hasTwoParameters = (commandPartsLength == TWO_PARAMETER_LENGTH); @@ -243,32 +241,28 @@ private void processSolutionCommand( throw new CustomException(("No such question")); } - if (isSolutionCommand) { - if (!hasTwoParameters) { - // get all solutions - String allSolutions = qnList.getAllSolutions(); - ui.printAllSolutions(allSolutions); - return; - } + // checks if attempted topic before + if (!topicList.get(topicNum - 1).hasAttempted()) { + ui.printNoSolutionAccess(); // has not attempted + return; + } + + if (hasTwoParameters) { // get specific solution String solution = qnList.getOneSolution(questionNum); - if (!topicList.get(topicNum - 1).hasAttempted()) { - ui.printNoSolutionAccess(); // has not attempted - } ui.printOneSolution(questionNum, solution); - return; - } - // only runs code below if explain command - assert typeOfCommand.contentEquals("explain"); - if (hasTwoParameters) { // explain command only has 1 valid parameter - throw new CustomException(MESSAGE_INVALID_PARAMETERS); + } else { + // get all solutions + String allSolutions = qnList.getAllSolutions(); + ui.printAllSolutions(allSolutions); } - String explanation = qnList.getOneExplanation(questionNum); - if (!topicList.get(topicNum - 1).hasAttempted()) { - ui.printNoSolutionAccess(); // has not attempted - } - ui.printOneSolution(questionNum, explanation); + } + + private void processExplainCommand(String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) + throws CustomException { + + // no get all explanations } public void handleAnswerInputs(String[] inputAnswers, int index, String answer, Question questionUnit, From d49f9b793c1a5abdb51a7331ff3cb75447279ab4 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Sun, 31 Mar 2024 01:13:48 +0800 Subject: [PATCH 112/334] Extract explain feature from solution feature --- src/main/java/seedu/duke/Parser.java | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 8801d1f463..d548b5d770 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -55,12 +55,14 @@ public void parseCommand( /* processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, allResults, userAnswers, isTimedMode); */ isTimedMode = false; - } else if (lowerCaseCommand.contentEquals("bye")) { - ui.isPlaying = false; - } else if (lowerCaseCommand.startsWith("solution") || lowerCaseCommand.startsWith("explain")) { + } else if (lowerCaseCommand.startsWith("solution")) { processSolutionCommand(lowerCaseCommand, ui, topicList, questionListByTopic); + } else if (lowerCaseCommand.startsWith("explain")) { + processExplainCommand(lowerCaseCommand, ui, topicList, questionListByTopic); } else if (lowerCaseCommand.startsWith("results")) { processResultsCommand(lowerCaseCommand, allResults, ui, questionListByTopic, userAnswers); + } else if (lowerCaseCommand.contentEquals("bye")) { + ui.isPlaying = false; } else if (lowerCaseCommand.contentEquals("help")) { processHelpCommand(lowerCaseCommand, ui, helper); } else if (lowerCaseCommand.contentEquals("list")) { @@ -203,12 +205,12 @@ private void processStartCommand( private void processSolutionCommand( String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) throws CustomException { - - // parser command + // parse command String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER); int commandPartsLength = commandParts.length; String commandType = commandParts[0]; + // checks validity of command if (!commandType.contentEquals("solution")) { throw new CustomException("Do you mean \"solution\" instead?"); } @@ -241,6 +243,7 @@ private void processSolutionCommand( throw new CustomException(("No such question")); } + // checks if attempted topic before if (!topicList.get(topicNum - 1).hasAttempted()) { ui.printNoSolutionAccess(); // has not attempted From a937089f2f4281c14adc3de75aee9e3c5650521c Mon Sep 17 00:00:00 2001 From: ngxzs Date: Sun, 31 Mar 2024 01:42:36 +0800 Subject: [PATCH 113/334] Refactor processSolutionCommand() --- src/main/java/seedu/duke/Parser.java | 75 ++++++++++++++++------------ 1 file changed, 42 insertions(+), 33 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index d548b5d770..0c521de133 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -201,48 +201,37 @@ private void processStartCommand( } - // solution and explain commands - private void processSolutionCommand( - String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) - throws CustomException { - // parse command - String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER); - int commandPartsLength = commandParts.length; - String commandType = commandParts[0]; - - // checks validity of command - if (!commandType.contentEquals("solution")) { - throw new CustomException("Do you mean \"solution\" instead?"); - } + // gets topicNum from String[] + private int getTopicOrQuestionNum(String[] commandParts, String commandParameter, int maxSize) throws CustomException { - // checks correct number of parameters (1 or 2 only) - if (commandPartsLength == NO_PARAMETER_LENGTH || commandPartsLength > TWO_PARAMETER_LENGTH) { - throw new CustomException(MESSAGE_INVALID_PARAMETERS); - } - - boolean hasTwoParameters = (commandPartsLength == TWO_PARAMETER_LENGTH); - - String commandParameterTopic = commandParts[FIRST_PARAMETER]; - String commandParameterQn = hasTwoParameters ? commandParts[SECOND_PARAMETER] : DUMMY_QUESTION_PARAMETER; int topicNum; - int questionNum; try { - topicNum = Integer.parseInt(commandParameterTopic); - questionNum = Integer.parseInt(commandParameterQn); + topicNum = Integer.parseInt(commandParameter); } catch (NumberFormatException e) { throw new CustomException(MESSAGE_INVALID_PARAMETERS); } + // checks validity of topicNum - if (topicNum < 1 || topicNum > topicList.getSize()) { - throw new CustomException("No such topic"); + if (topicNum < 1 || topicNum > maxSize) { + throw new CustomException("No such topic or question"); } - QuestionsList qnList = questionListByTopic.getQuestionSet(topicNum - 1); + return topicNum; + } + // solution and explain commands + private void processSolutionCommand( + String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) + throws CustomException { + // process command + String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER); + boolean hasTwoParameters = checkIfTwoParameters(commandParts); - // checks validity of questionNum - if (questionNum < 1 || questionNum > qnList.getSize()) { - throw new CustomException(("No such question")); - } + // process parameters + String commandParameterTopic = commandParts[FIRST_PARAMETER]; + String commandParameterQn = hasTwoParameters ? commandParts[SECOND_PARAMETER] : DUMMY_QUESTION_PARAMETER; + int topicNum = getTopicOrQuestionNum(commandParts, commandParameterTopic, topicList.getSize()); + QuestionsList qnList = questionListByTopic.getQuestionSet(topicNum - 1); + int questionNum = getTopicOrQuestionNum(commandParts, commandParameterQn, qnList.getSize()); // checks if attempted topic before if (!topicList.get(topicNum - 1).hasAttempted()) { @@ -262,10 +251,30 @@ private void processSolutionCommand( } + // returns true if 2 parameters, else false (1 param only) + private static boolean checkIfTwoParameters(String[] commandParts) throws CustomException { + int commandPartsLength = commandParts.length; + String commandType = commandParts[0]; + + // checks validity of command + if (!commandType.contentEquals("solution")) { + throw new CustomException("Do you mean \"solution\" instead?"); + } + + // checks correct number of parameters (1 or 2 only) + if (commandPartsLength == NO_PARAMETER_LENGTH || commandPartsLength > TWO_PARAMETER_LENGTH) { + throw new CustomException(MESSAGE_INVALID_PARAMETERS); + } + + return (commandPartsLength == TWO_PARAMETER_LENGTH); + } + private void processExplainCommand(String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) throws CustomException { + // process command - // no get all explanations + // get 1 explanation + // or get all explanations (TODO) } public void handleAnswerInputs(String[] inputAnswers, int index, String answer, Question questionUnit, From 405a82e4942c0753e33089d20cc38af50a1fd919 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Sun, 31 Mar 2024 02:03:00 +0800 Subject: [PATCH 114/334] Add explain feature --- src/main/java/seedu/duke/Parser.java | 85 +++++++++++++++++----------- 1 file changed, 53 insertions(+), 32 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 0c521de133..6f16d0c590 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -18,6 +18,8 @@ public class Parser { private static final String COMMAND_SPLITTER = " "; private static final String DETAILS_PARAMETER = "details"; + private static final String SOLUTION_PARAMETER = "solution"; + private static final String EXPLAIN_PARAMETER = "explain"; private static final String MESSAGE_NO_RESULTS = "There are no results."; private static final String MESSAGE_ERROR = "An error has occurred."; @@ -201,37 +203,21 @@ private void processStartCommand( } - // gets topicNum from String[] - private int getTopicOrQuestionNum(String[] commandParts, String commandParameter, int maxSize) throws CustomException { - - int topicNum; - try { - topicNum = Integer.parseInt(commandParameter); - } catch (NumberFormatException e) { - throw new CustomException(MESSAGE_INVALID_PARAMETERS); - } - - // checks validity of topicNum - if (topicNum < 1 || topicNum > maxSize) { - throw new CustomException("No such topic or question"); - } - return topicNum; - } // solution and explain commands private void processSolutionCommand( String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) throws CustomException { // process command String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER); - boolean hasTwoParameters = checkIfTwoParameters(commandParts); + boolean hasTwoParameters = checkIfTwoParameters(SOLUTION_PARAMETER, commandParts); // process parameters String commandParameterTopic = commandParts[FIRST_PARAMETER]; String commandParameterQn = hasTwoParameters ? commandParts[SECOND_PARAMETER] : DUMMY_QUESTION_PARAMETER; - int topicNum = getTopicOrQuestionNum(commandParts, commandParameterTopic, topicList.getSize()); + int topicNum = getTopicOrQuestionNum(commandParameterTopic, topicList.getSize()); QuestionsList qnList = questionListByTopic.getQuestionSet(topicNum - 1); - int questionNum = getTopicOrQuestionNum(commandParts, commandParameterQn, qnList.getSize()); + int questionNum = getTopicOrQuestionNum(commandParameterQn, qnList.getSize()); // checks if attempted topic before if (!topicList.get(topicNum - 1).hasAttempted()) { @@ -248,17 +234,46 @@ private void processSolutionCommand( String allSolutions = qnList.getAllSolutions(); ui.printAllSolutions(allSolutions); } - } - // returns true if 2 parameters, else false (1 param only) - private static boolean checkIfTwoParameters(String[] commandParts) throws CustomException { + private void processExplainCommand(String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) + throws CustomException { + // process command + String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER); + boolean hasTwoParameters = checkIfTwoParameters(EXPLAIN_PARAMETER, commandParts); + + // process parameters + String commandParameterTopic = commandParts[FIRST_PARAMETER]; + String commandParameterQn = hasTwoParameters ? commandParts[SECOND_PARAMETER] : DUMMY_QUESTION_PARAMETER; + + int topicNum = getTopicOrQuestionNum(commandParameterTopic, topicList.getSize()); + QuestionsList qnList = questionListByTopic.getQuestionSet(topicNum - 1); + int questionNum = getTopicOrQuestionNum(commandParameterQn, qnList.getSize()); + + // checks if attempted topic before + if (!topicList.get(topicNum - 1).hasAttempted()) { + ui.printNoSolutionAccess(); // has not attempted + return; + } + + if (hasTwoParameters) { + // get specific explanation + String explanation = qnList.getOneExplanation(questionNum); + ui.printOneSolution(questionNum, explanation); + } else { + // get all explanations + String allExplanations = qnList.getAllExplanations(); + ui.printAllSolutions(allExplanations); + } + } + // checks valid command type and parameters: returns true if 2 parameters, else false (1 param only) + private static boolean checkIfTwoParameters(String expectedCommandType, String[] commandParts) throws CustomException { int commandPartsLength = commandParts.length; - String commandType = commandParts[0]; + String actualCommandType = commandParts[0]; // checks validity of command - if (!commandType.contentEquals("solution")) { - throw new CustomException("Do you mean \"solution\" instead?"); + if (!actualCommandType.contentEquals(expectedCommandType)) { + throw new CustomException("Do you mean " + expectedCommandType + " instead?"); } // checks correct number of parameters (1 or 2 only) @@ -268,13 +283,19 @@ private static boolean checkIfTwoParameters(String[] commandParts) throws Custom return (commandPartsLength == TWO_PARAMETER_LENGTH); } - - private void processExplainCommand(String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) - throws CustomException { - // process command - - // get 1 explanation - // or get all explanations (TODO) + // convert String commandParameter to int topicNum/ questionNum and check validity + private int getTopicOrQuestionNum(String commandParameter, int maxSize) throws CustomException { + int parameterNum; + try { + parameterNum = Integer.parseInt(commandParameter); + } catch (NumberFormatException e) { + throw new CustomException(MESSAGE_INVALID_PARAMETERS); + } + // checks validity + if (parameterNum < 1 || parameterNum > maxSize) { + throw new CustomException("No such topic or question"); + } + return parameterNum; } public void handleAnswerInputs(String[] inputAnswers, int index, String answer, Question questionUnit, From fc01a92456a774a377e3ee0ae905f43574cac9e4 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Sun, 31 Mar 2024 02:23:12 +0800 Subject: [PATCH 115/334] Fix checkstyleMain errors --- src/main/java/seedu/duke/CommandList.java | 20 +++++++------------- src/main/java/seedu/duke/Parser.java | 10 ++++++---- src/main/java/seedu/duke/Ui.java | 10 +++++++++- 3 files changed, 22 insertions(+), 18 deletions(-) diff --git a/src/main/java/seedu/duke/CommandList.java b/src/main/java/seedu/duke/CommandList.java index 3a992c39a9..2c5c6b9dbf 100644 --- a/src/main/java/seedu/duke/CommandList.java +++ b/src/main/java/seedu/duke/CommandList.java @@ -24,25 +24,19 @@ public static CommandList getCommandToken(String command) { String[] splitCommand = command.split(" "); String mainCommand = splitCommand[0].toLowerCase(); - if(mainCommand.contentEquals("topic")) { + if (mainCommand.contentEquals("topic")) { return TOPIC; - } - else if(mainCommand.contentEquals("help")) { + } else if (mainCommand.contentEquals("help")) { return HELP; - } - else if(mainCommand.contentEquals("solution")) { + } else if (mainCommand.contentEquals("solution")) { return SOLUTION; - } - else if(mainCommand.contentEquals("explanation")) { + } else if (mainCommand.contentEquals("explanation")) { return EXPLAIN; - } - else if(mainCommand.contentEquals("results")) { + } else if (mainCommand.contentEquals("results")) { return RESULTS; - } - else if(mainCommand.contentEquals("bye")) { + } else if (mainCommand.contentEquals("bye")) { return BYE; - } - else { + } else { return INVALID; } } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 6f16d0c590..beffd9dc12 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -236,7 +236,8 @@ private void processSolutionCommand( } } - private void processExplainCommand(String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) + private void processExplainCommand( + String lowerCaseCommand, Ui ui, TopicList topicList, QuestionListByTopic questionListByTopic) throws CustomException { // process command String[] commandParts = lowerCaseCommand.split(COMMAND_SPLITTER); @@ -259,15 +260,16 @@ private void processExplainCommand(String lowerCaseCommand, Ui ui, TopicList top if (hasTwoParameters) { // get specific explanation String explanation = qnList.getOneExplanation(questionNum); - ui.printOneSolution(questionNum, explanation); + ui.printOneExplanation(questionNum, explanation); } else { // get all explanations String allExplanations = qnList.getAllExplanations(); - ui.printAllSolutions(allExplanations); + ui.printAllExplanations(allExplanations); } } // checks valid command type and parameters: returns true if 2 parameters, else false (1 param only) - private static boolean checkIfTwoParameters(String expectedCommandType, String[] commandParts) throws CustomException { + private static boolean checkIfTwoParameters( + String expectedCommandType, String[] commandParts) throws CustomException { int commandPartsLength = commandParts.length; String actualCommandType = commandParts[0]; diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 40b20e6d24..d482340dca 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -152,11 +152,19 @@ public void printOneSolution(int questionNum, String solution) { + System.lineSeparator() + solution); } + public void printOneExplanation(int questionNum, String explanation) { + System.out.println("The explanation for question " + questionNum + ":" + + System.lineSeparator() + explanation); + } public void printAllSolutions(String allSolutions) { - System.out.println("The solutions are :" + System.out.print("The solutions are :" + System.lineSeparator() + allSolutions); } + public void printAllExplanations(String allExplanations) { + System.out.print("The explanations are :" + + System.lineSeparator() + allExplanations); + } public void printOneResult(boolean includesDetails, int topicNum, String score, QuestionListByTopic questionListByTopic, AnswerTracker userAnswers, int index) { System.out.println("Your results for Topic " + (topicNum + 1) + ":\n" + score + "\n"); From ac920410fa13c1f7cb3c57fa90fb46f18388465f Mon Sep 17 00:00:00 2001 From: ngxzs Date: Sun, 31 Mar 2024 12:34:29 +0800 Subject: [PATCH 116/334] Fix testGetTopic sametopicName and getTopic() zero-index bug --- src/main/java/seedu/duke/Parser.java | 6 +++--- src/test/java/seedu/duke/TopicListTest.java | 10 ++++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index beffd9dc12..33c6272c7b 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -53,9 +53,9 @@ public void parseCommand( } if (commandToken == CommandList.TOPIC) { // Still under testing. - beginStartCommand(command, ui, topicList, questionListByTopic, allResults, userAnswers); - /* processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, - allResults, userAnswers, isTimedMode); */ +// beginStartCommand(command, ui, topicList, questionListByTopic, allResults, userAnswers); + processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, + allResults, userAnswers, isTimedMode); isTimedMode = false; } else if (lowerCaseCommand.startsWith("solution")) { processSolutionCommand(lowerCaseCommand, ui, topicList, questionListByTopic); diff --git a/src/test/java/seedu/duke/TopicListTest.java b/src/test/java/seedu/duke/TopicListTest.java index 4a66c2051f..f31b6e39a1 100644 --- a/src/test/java/seedu/duke/TopicListTest.java +++ b/src/test/java/seedu/duke/TopicListTest.java @@ -13,7 +13,7 @@ class TopicListTest { void createTopicList(){ topicTest1 = new Topic(qnList, "topicTest1", false, "covers topic 1" ); - topicTest2 = new Topic(qnList2, "topicTest1", false, "covers topic 2" ); + topicTest2 = new Topic(qnList2, "topicTest2", false, "covers topic 2" ); topicListTest = new TopicList(); @@ -24,9 +24,15 @@ void createTopicList(){ @Test void testGetTopic(){ createTopicList(); - assertEquals("topicTest1",topicListTest.getTopic(1)); + assertEquals("topicTest1",topicListTest.getTopic(0)); + assertEquals("topicTest2",topicListTest.getTopic(1)); } +// @Test testGetRandomTopic() { +// createTopicList(); +// +// } + @Test void testGetSize(){ createTopicList(); From 4cba1b312fc8e2c88830b34c3bd338c0b5105caa Mon Sep 17 00:00:00 2001 From: ngxzs Date: Sun, 31 Mar 2024 13:09:55 +0800 Subject: [PATCH 117/334] Add choose randomTopic feature test in TopicListTest --- src/main/java/seedu/duke/Parser.java | 8 ++++---- .../java/seedu/duke/QuestionsListTest.java | 2 ++ src/test/java/seedu/duke/TopicListTest.java | 18 +++++++++++++----- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 33c6272c7b..a3cdf2b051 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -183,13 +183,13 @@ private void processStartCommand( throw new CustomException("No such topic"); } // checks if user wants a random topic num - final int randomTopicNum = topicList.getSize() + 1; - if (topicNum == randomTopicNum) { + final int upperLimit = topicList.getSize() + 1; + if (topicNum == upperLimit) { Helper helper = new Helper(); - topicNum = helper.generateRandomNumber(randomTopicNum); + topicNum = helper.generateRandomNumber(upperLimit); } assert (topicNum != 0) : "topicNum should not be 0"; - assert (topicNum != randomTopicNum) : "topicNum should not be randomTopicNum"; + assert (topicNum != upperLimit) : "topicNum should not be upperLimit"; // prints questions ui.printChosenTopic(topicNum, topicList, questionListByTopic, allResults, userAnswers, isTimedMode); diff --git a/src/test/java/seedu/duke/QuestionsListTest.java b/src/test/java/seedu/duke/QuestionsListTest.java index 96499f95e1..0431b72f3d 100644 --- a/src/test/java/seedu/duke/QuestionsListTest.java +++ b/src/test/java/seedu/duke/QuestionsListTest.java @@ -62,6 +62,7 @@ void getAllSolutions_twoQuestions_twoSolutions() throws CustomException { assertEquals(expectedOutput, questionsList.getAllSolutions()); } + @Test void getAllExplanations_twoQuestions_twoExplanations() throws CustomException { createQuestionList(); @@ -87,6 +88,7 @@ void getAllSolutions_noQuestions_customException() { assertThrows(CustomException.class, // expect Exception () -> questionsList.getAllSolutions()); } + @Test void getAllExplanations_noQuestions_customException() { createQuestionList(); // empty question List diff --git a/src/test/java/seedu/duke/TopicListTest.java b/src/test/java/seedu/duke/TopicListTest.java index f31b6e39a1..920cf72d04 100644 --- a/src/test/java/seedu/duke/TopicListTest.java +++ b/src/test/java/seedu/duke/TopicListTest.java @@ -28,14 +28,22 @@ void testGetTopic(){ assertEquals("topicTest2",topicListTest.getTopic(1)); } -// @Test testGetRandomTopic() { -// createTopicList(); -// -// } - @Test void testGetSize(){ createTopicList(); assertEquals(2, topicListTest.getSize()); } + // tests getRandomTopic/QuestionSet feature + @Test + void getTopic_randomTopicNum_validTopic() { + createTopicList(); + int upperLimit = topicListTest.getSize() + 1; + Helper helper = new Helper(); + // generate num btwn 1 to 2 (ie topicListTest.getSize()) inclusive + int topicNum = helper.generateRandomNumber(upperLimit); + String randomTopic = (topicNum == 1) ? "topicTest1" : "topicTest2"; + + assertEquals(randomTopic, topicListTest.getTopic(topicNum - 1)); + } } + From 2c101e0676d5bb3aa01b7c0a0e6d29009e5d1be1 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Sun, 31 Mar 2024 13:15:53 +0800 Subject: [PATCH 118/334] Fix format errors to pass github checks --- src/main/java/seedu/duke/Parser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index a3cdf2b051..eb19502cd8 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -53,9 +53,9 @@ public void parseCommand( } if (commandToken == CommandList.TOPIC) { // Still under testing. -// beginStartCommand(command, ui, topicList, questionListByTopic, allResults, userAnswers); + // beginStartCommand(command, ui, topicList, questionListByTopic, allResults, userAnswers); processStartCommand(lowerCaseCommand, ui, topicList, questionListByTopic, - allResults, userAnswers, isTimedMode); + allResults, userAnswers, isTimedMode); isTimedMode = false; } else if (lowerCaseCommand.startsWith("solution")) { processSolutionCommand(lowerCaseCommand, ui, topicList, questionListByTopic); From c24f3d0fe9c8b574c75ada9a9981f116b3327520 Mon Sep 17 00:00:00 2001 From: ngxzs Date: Sun, 31 Mar 2024 15:13:09 +0800 Subject: [PATCH 119/334] Update DG solution and explain features --- docs/DeveloperGuide.md | 57 +++++++++++++++++++++++------------- docs/team/img/Solution.png | Bin 10079 -> 66182 bytes docs/team/img/Solution.puml | 49 +++++++++++++++++++++++++++++-- 3 files changed, 83 insertions(+), 23 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index f6f0fdd8f8..b23c7a4b32 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -74,39 +74,56 @@ The solution feature either prints the solution to 1 question or all questions i The solution feature is facilitated by ```Parser#processSolutionCommand```, which is called by ```Parser#parseCommand``` -Step 1: After user runs the program and keys in the user commands, the commands will be passed to -```Parser#parseCommand```. +> **OVERVIEW:** +> +> ![Solution sequence diagram](./team/img/Solution.png) + +Step 1: After user runs the program and keys in the user command, the command will be passed to +```Parser#parseCommand```. -The command must contain the ```solution``` keyword before being passed into ```Parser#processSolutionCommand``` -![Solution sequence diagram](./team/img/Solution.png) +> **NOTE:** The command must contain the ```solution``` keyword. -Step 2: ```Parser#processSolutionCommand``` will first check number of parameters. -First, it will call ```QuestionsList``` class which contains all questions in a topic. -If there is 1 parameter, ```QuestionsList#getAllSolutions``` will be called to get all solutions in a topic. -If there are 2 parameters, ```QuestionsList#getOneSolution``` will be called to get one specific solution. +Step 2a: ```Parser#processSolutionCommand``` first checks the number of parameters in the user command +by calling ```Parser#checkIfTwoParameters```. +The, further processing of parameters is done by calling ```Parser#getTopicOrQuestionNum```. +This is facilitated by calling ```QuestionsListByTopic#getQuestionSet``` to get all questions in the specified topic. -Step 3: -To get all solutions, ```ui#printAllSolutions``` will be called to print all solutions -To get one specific solution, ```ui#printOneSolution``` will be called to print that one solution. +Step 2b: Before getting the solution(s), the program first verifies if the topic has been attempted before. +The program only prints them only if the topic is attempted before. +The topic is selected by calling ```TopicList#get``` and ```TopicList#hasAttempted``` returns the attempted status. -### [Intended] Explain feature +Step 3: +Depending on the number of parameters, +if there is 1 parameter (ie get all solutions): +```QuestionsList#getAllSolutions``` will get all solutions and ```ui#printAllSolutions``` will print them. +else if there are 2 parameters (ie get one solution): +```QuestionsList#getOneSolution``` will get the specified solution and ```ui#printOneSolution``` will print it. + +### Explain feature The explain feature either prints the explanation to 1 question or all questions in 1 topic. The explain feature is facilitated by ```Parser#processExplanationCommand```, which is called by ```Parser#parseCommand``` -Step 1: After user runs the program and keys in the user commands, the commands will be passed to +Step 1: After user runs the program and keys in the user command, the command will be passed to ```Parser#parseCommand```. -The command must contain the ```explain``` keyword before being passed into ```Parser#processExplainCommand``` +> **NOTE:** The command must contain the ```explain``` keyword. + +Step 2a: ```Parser#processExplainCommand``` first checks the number of parameters in the user command +by calling ```Parser#checkIfTwoParameters```. +The, further processing of parameters is done by calling ```Parser#getTopicOrQuestionNum```. +This is facilitated by calling ```QuestionsListByTopic#getQuestionSet``` to get all questions in the specified topic. -Step 2: ```Parser#processExplainCommand``` will first check number of parameters. -First, it will call ```QuestionsList``` class which contains all questions in a topic. -If there is 1 parameter, ```QuestionsList#getAllExplanations``` will be called to get all explanations in a topic. -If there are 2 parameters, ```QuestionsList#getOneExplanation``` will be called to get one specific explanation. +Step 2b: Before getting the explanation(s), the program first verifies if the topic has been attempted before. +The program only prints them only if the topic is attempted before. +The topic is selected by calling ```TopicList#get``` and ```TopicList#hasAttempted``` returns the attempted status. Step 3: -To get all explanations, ```ui#printAllExplanation``` will be called to print all explanations -To get one specific explanation, ```ui#printOneExplanation``` will be called to print that one explanation. +Depending on the number of parameters, +if there is 1 parameter (ie get all explanations): +```QuestionsList#getAllExplanations``` will get all explanations and ```ui#printAllExplanations``` will print them. +else if there are 2 parameters (ie get one explanation): +```QuestionsList#getOneExplanation``` will get the specified explanation and ```ui#printOneExplanation``` will print it. ## Product scope diff --git a/docs/team/img/Solution.png b/docs/team/img/Solution.png index 27491ec13a337628e798969cd8249dee06e474c1..33a9961fd9a0ba3fe51ac76b265cbd54911b5038 100644 GIT binary patch literal 66182 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