From 79d13c9f6690cbd34ff81e9f9a23322137775aef Mon Sep 17 00:00:00 2001 From: hozhenhong99 <69459292+hozhenhong99@users.noreply.github.com> Date: Fri, 1 Oct 2021 12:13:45 +0800 Subject: [PATCH 001/543] Set theme jekyll-theme-merlot --- docs/_config.yml | 1 + 1 file changed, 1 insertion(+) create mode 100644 docs/_config.yml diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000000..c50ff38dab --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-merlot \ No newline at end of file From 7939b7b2c56845e443772147fd9ee1969424cfe5 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Fri, 1 Oct 2021 12:45:49 +0800 Subject: [PATCH 002/543] add daknam.md --- docs/AboutUs.md | 2 +- docs/team/daknam.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 docs/team/daknam.md diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..3b87caf68b 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -3,7 +3,7 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Dak Nam | [Github](https://github.com/daknam2001) | [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/daknam.md b/docs/team/daknam.md new file mode 100644 index 0000000000..0688651ff8 --- /dev/null +++ b/docs/team/daknam.md @@ -0,0 +1 @@ +Hi, I'm Dak Nam. \ No newline at end of file From 3d604a8c667f4d84311a580eea8aca4804e87feb Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Fri, 1 Oct 2021 12:52:33 +0800 Subject: [PATCH 003/543] add zhenhong about us --- docs/AboutUs.md | 2 +- src/main/java/seedu/duke/Duke.java | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 3b87caf68b..3886a76954 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,7 +2,7 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | John Doe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Zhen Hong | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Dak Nam | [Github](https://github.com/daknam2001) | [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) diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 5c74e68d59..f99ebb805c 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -6,7 +6,8 @@ public class Duke { /** * Main entry-point for the java.duke.Duke application. */ - public static void main(String[] args) { + public static void main(String[] args) + { String logo = " ____ _ \n" + "| _ \\ _ _| | _____ \n" + "| | | | | | | |/ / _ \\\n" From af5039fea25c42fc2e3c86e5c4ccfb69340a6f05 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 1 Oct 2021 12:57:05 +0800 Subject: [PATCH 004/543] Add leyond aboutus --- docs/AboutUs.md | 2 +- docs/team/leyond.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 docs/team/leyond.md diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 3b87caf68b..6dc7960c9c 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -6,4 +6,4 @@ Display | Name | Github Profile | Portfolio ![](https://via.placeholder.com/100.png?text=Photo) | Dak Nam | [Github](https://github.com/daknam2001) | [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) | Leyond | [Github](https://github.com/leyondlee) | [Portfolio](docs/team/leyond.md) diff --git a/docs/team/leyond.md b/docs/team/leyond.md new file mode 100644 index 0000000000..6d57ed9f52 --- /dev/null +++ b/docs/team/leyond.md @@ -0,0 +1 @@ +Hi, I'm Leyond \ No newline at end of file From dce78bb666abafa216d1b151bcc8699592940cf4 Mon Sep 17 00:00:00 2001 From: rachel Date: Fri, 1 Oct 2021 12:57:49 +0800 Subject: [PATCH 005/543] add rachel aboutus. --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 3886a76954..410c6bf99f 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -5,5 +5,5 @@ Display | Name | Github Profile | Portfolio ![](https://via.placeholder.com/100.png?text=Photo) | Zhen Hong | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Dak Nam | [Github](https://github.com/daknam2001) | [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) | Rachel | [Github](https://github.com/rachelkeh) | [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 b79c5fdb67645fee6a8b37e458f0cd0172f0eee2 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Fri, 1 Oct 2021 13:02:07 +0800 Subject: [PATCH 006/543] edited about us --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 3886a76954..cf8c69fe91 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -4,6 +4,6 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | Zhen Hong | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Dak Nam | [Github](https://github.com/daknam2001) | [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) | Jon | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) From eb84f91ad12fa07dc21b7e96161fe25a2cac1fdd Mon Sep 17 00:00:00 2001 From: rachel Date: Fri, 1 Oct 2021 13:08:23 +0800 Subject: [PATCH 007/543] add rachel aboutus. --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index cf8c69fe91..3f910e1557 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -5,5 +5,5 @@ Display | Name | Github Profile | Portfolio ![](https://via.placeholder.com/100.png?text=Photo) | Zhen Hong | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Dak Nam | [Github](https://github.com/daknam2001) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Jon | [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) | Rachel | [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 ba6fefde5a949f70318a62dc451d0e1bf23602e8 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 6 Oct 2021 01:57:06 +0800 Subject: [PATCH 008/543] Add Ui class --- src/main/java/seedu/duke/Ui.java | 70 ++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 src/main/java/seedu/duke/Ui.java diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java new file mode 100644 index 0000000000..99385597ff --- /dev/null +++ b/src/main/java/seedu/duke/Ui.java @@ -0,0 +1,70 @@ +package seedu.duke; + +import java.util.Scanner; + +public class Ui { + private static final String INPUT_PROMPT = "$ "; + private static final String MESSAGE_BORDER = "------------------------------------------------------------"; + private static final String MESSAGE_WELCOME = "Welcome\nWhat can I do for you?"; + private static final String MESSAGE_EXIT = "Bye. Hope to see you again soon!"; + + private static final String MESSAGE_FORMAT_EXCEPTION = "An exception has occurred:\n%s"; + + private final Scanner scanner; + + /** + * Constructor for Ui class. + */ + public Ui() { + this.scanner = new Scanner(System.in); + } + + /** + * Gets a non-empty user input. + * + * @return Non-empty user input. + */ + public String getUserInput() { + String input; + do { + System.out.print(INPUT_PROMPT); + input = scanner.nextLine(); + } while (input.trim().isEmpty()); + + return input; + } + + /** + * Prints message within horizontal lines. + * + * @param message The message to print. + */ + public void printMessage(String message) { + System.out.println(MESSAGE_BORDER); + System.out.println(message); + System.out.println(MESSAGE_BORDER); + } + + /** + * Prints the welcome message. + */ + public void printWelcomeMessage() { + printMessage(MESSAGE_WELCOME); + } + + /** + * Prints the exit message. + */ + public void printExitMessage() { + printMessage(MESSAGE_EXIT); + } + + /** + * Prints an exception. + * + * @param message The message to print. + */ + public void printException(String message) { + printMessage(String.format(MESSAGE_FORMAT_EXCEPTION, message)); + } +} From 4f0a42d7124aed6ad67d86b9bf4bf7d78260b7ce Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 6 Oct 2021 01:58:14 +0800 Subject: [PATCH 009/543] Add base classes --- src/main/java/seedu/duke/command/Command.java | 48 +++++++++++++++++++ src/main/java/seedu/duke/module/Module.java | 29 +++++++++++ .../java/seedu/duke/student/Assessment.java | 5 ++ src/main/java/seedu/duke/student/Student.java | 10 ++++ 4 files changed, 92 insertions(+) create mode 100644 src/main/java/seedu/duke/command/Command.java create mode 100644 src/main/java/seedu/duke/module/Module.java create mode 100644 src/main/java/seedu/duke/student/Assessment.java create mode 100644 src/main/java/seedu/duke/student/Student.java diff --git a/src/main/java/seedu/duke/command/Command.java b/src/main/java/seedu/duke/command/Command.java new file mode 100644 index 0000000000..d110954a2e --- /dev/null +++ b/src/main/java/seedu/duke/command/Command.java @@ -0,0 +1,48 @@ +package seedu.duke.command; + +import seedu.duke.CustomException; +import seedu.duke.Ui; +import seedu.duke.module.ModuleList; + +import java.util.HashMap; + +public abstract class Command { + public static final String COMMAND_EXIT = "exit"; + public static final String COMMAND_LIST_MODULES = "list_modules"; + public static final String COMMAND_LIST_STUDENTS = "list_students"; + public static final String COMMAND_LIST_ASSESSMENTS = "list_assessments"; + public static final String COMMAND_LIST_ATTENDANCE = "list_attendance"; + public static final String COMMAND_LIST_MARKS = "list_marks"; + public static final String COMMAND_AVERAGE_MARKS = "average_marks"; + public static final String COMMAND_ADD_MODULE = "add_module"; + public static final String COMMAND_ADD_STUDENT = "add_student"; + public static final String COMMAND_EDIT_STUDENT = "edit_student"; + public static final String COMMAND_DELETE_STUDENT = "delete_student"; + public static final String COMMAND_SET_ATTENDANCE = "set_attendance"; + public static final String COMMAND_ADD_ASSESSMENT = "add_assessment"; + public static final String COMMAND_SET_MARKS = "set_marks"; + + protected String argument; + protected boolean isExit; + + public Command(String argument) { + this.argument = argument; + this.isExit = false; + } + + public boolean isExit() { + return isExit; + } + + public abstract void execute(ModuleList modules, Ui ui) throws CustomException; + + protected static boolean checkArgumentsMap(HashMap argumentsMap, String[] argumentKeys) { + for (String key : argumentKeys) { + if (!argumentsMap.containsKey(key)) { + return false; + } + } + + return true; + } +} diff --git a/src/main/java/seedu/duke/module/Module.java b/src/main/java/seedu/duke/module/Module.java new file mode 100644 index 0000000000..09f234fa0f --- /dev/null +++ b/src/main/java/seedu/duke/module/Module.java @@ -0,0 +1,29 @@ +package seedu.duke.module; + +import seedu.duke.student.Assessment; +import seedu.duke.student.Student; + +import java.util.ArrayList; + +public class Module { + private final String code; + private final String name; + private final ArrayList students; + private final ArrayList assessments; + + public Module(String code, String name) { + this.code = code; + this.name = name; + this.students = new ArrayList<>(); + this.assessments = new ArrayList<>(); + } + + @Override + public String toString() { + if (name.isEmpty()) { + return code; + } + + return String.format("%s - %s", code, name); + } +} diff --git a/src/main/java/seedu/duke/student/Assessment.java b/src/main/java/seedu/duke/student/Assessment.java new file mode 100644 index 0000000000..9680a797ef --- /dev/null +++ b/src/main/java/seedu/duke/student/Assessment.java @@ -0,0 +1,5 @@ +package seedu.duke.student; + +public class Assessment { + +} diff --git a/src/main/java/seedu/duke/student/Student.java b/src/main/java/seedu/duke/student/Student.java new file mode 100644 index 0000000000..c306396ac4 --- /dev/null +++ b/src/main/java/seedu/duke/student/Student.java @@ -0,0 +1,10 @@ +package seedu.duke.student; + +public class Student { + private static int TOTAL_WEEKS = 13; + private boolean[] attendance; + + public Student() { + this.attendance = new boolean[TOTAL_WEEKS]; + } +} From fa6fe34d9779a4676a639483596b668886581502 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 6 Oct 2021 01:58:43 +0800 Subject: [PATCH 010/543] Implement ModuleList --- .../java/seedu/duke/module/ModuleList.java | 46 +++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 src/main/java/seedu/duke/module/ModuleList.java diff --git a/src/main/java/seedu/duke/module/ModuleList.java b/src/main/java/seedu/duke/module/ModuleList.java new file mode 100644 index 0000000000..8290c2df9b --- /dev/null +++ b/src/main/java/seedu/duke/module/ModuleList.java @@ -0,0 +1,46 @@ +package seedu.duke.module; + +import java.util.ArrayList; + +public class ModuleList { + private static final String MESSAGE_MODULE_LIST_HEADER = "Module List:"; + + private final ArrayList modules; + + public ModuleList() { + this.modules = new ArrayList<>(); + } + + public void addModule(Module module) { + modules.add(module); + } + + public int getSize() { + return modules.size(); + } + + public boolean isValidIndex(int index) { + return (index >= 0 && index < getSize()); + } + + public Module getModuleAt(int index) { + if (isValidIndex(index)) { + return modules.get(index); + } + + return null; + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(MESSAGE_MODULE_LIST_HEADER); + for (int i = 0; i < getSize(); i += 1) { + stringBuilder.append("\n"); + stringBuilder.append(i + 1); + stringBuilder.append(": "); + stringBuilder.append(getModuleAt(i)); + } + + return stringBuilder.toString(); + } +} From 40189954c82d2ec71c56c7794ed3f59dc9ef94bf Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 6 Oct 2021 01:59:26 +0800 Subject: [PATCH 011/543] Add add_module, exit, list_modules commands --- .../seedu/duke/command/AddModuleCommand.java | 41 +++++++++++++++++++ .../java/seedu/duke/command/ExitCommand.java | 16 ++++++++ .../duke/command/ListModulesCommand.java | 22 ++++++++++ 3 files changed, 79 insertions(+) create mode 100644 src/main/java/seedu/duke/command/AddModuleCommand.java create mode 100644 src/main/java/seedu/duke/command/ExitCommand.java create mode 100644 src/main/java/seedu/duke/command/ListModulesCommand.java diff --git a/src/main/java/seedu/duke/command/AddModuleCommand.java b/src/main/java/seedu/duke/command/AddModuleCommand.java new file mode 100644 index 0000000000..28e0db2458 --- /dev/null +++ b/src/main/java/seedu/duke/command/AddModuleCommand.java @@ -0,0 +1,41 @@ +package seedu.duke.command; + +import seedu.duke.CustomException; +import seedu.duke.Parser; +import seedu.duke.Ui; +import seedu.duke.module.ModuleList; +import seedu.duke.module.Module; + +import java.util.HashMap; + +public class AddModuleCommand extends Command { + private static String MESSAGE_MODULE_ADDED_FORMAT = "Module added:\n %s\nThere are %d modules in the list."; + + private static String[] argumentKeys = new String[]{"n"}; + + public AddModuleCommand(String argument) { + super(argument); + } + + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + if (argument.isEmpty()) { + throw new CustomException(""); + } + + String[] argumentSplit = Parser.splitFirstSpace(argument); + String moduleCode = argumentSplit[0]; + String additionalArgument = argumentSplit[1]; + + HashMap argumentsMap = Parser.getArgumentsFromString(additionalArgument, argumentKeys); + if (!checkArgumentsMap(argumentsMap, argumentKeys)) { + throw new CustomException(""); + } + + String name = argumentsMap.get("n"); + Module module = new Module(moduleCode, name); + modules.addModule(module); + + ui.printMessage(String.format(MESSAGE_MODULE_ADDED_FORMAT, module, modules.getSize())); + } +} diff --git a/src/main/java/seedu/duke/command/ExitCommand.java b/src/main/java/seedu/duke/command/ExitCommand.java new file mode 100644 index 0000000000..b3a12eb8c4 --- /dev/null +++ b/src/main/java/seedu/duke/command/ExitCommand.java @@ -0,0 +1,16 @@ +package seedu.duke.command; + +import seedu.duke.CustomException; +import seedu.duke.Ui; +import seedu.duke.module.ModuleList; + +public class ExitCommand extends Command { + public ExitCommand(String argument) { + super(argument); + } + + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + this.isExit = true; + } +} diff --git a/src/main/java/seedu/duke/command/ListModulesCommand.java b/src/main/java/seedu/duke/command/ListModulesCommand.java new file mode 100644 index 0000000000..99a9bb7355 --- /dev/null +++ b/src/main/java/seedu/duke/command/ListModulesCommand.java @@ -0,0 +1,22 @@ +package seedu.duke.command; + +import seedu.duke.CustomException; +import seedu.duke.Ui; +import seedu.duke.module.ModuleList; + +public class ListModulesCommand extends Command { + private static final String MESSAGE_LIST_EMPTY = "There are no modules in the list."; + + public ListModulesCommand(String argument) { + super(argument); + } + + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + if (modules.getSize() == 0) { + ui.printMessage(MESSAGE_LIST_EMPTY); + } else { + ui.printMessage(modules.toString()); + } + } +} From 6b7ca8f83c8d3fbbe64b43744577a7a1e15a3c48 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 6 Oct 2021 02:00:23 +0800 Subject: [PATCH 012/543] Implement command parser and base app --- src/main/java/seedu/duke/CustomException.java | 8 ++ src/main/java/seedu/duke/Duke.java | 39 ++++++--- src/main/java/seedu/duke/Parser.java | 85 +++++++++++++++++++ 3 files changed, 121 insertions(+), 11 deletions(-) create mode 100644 src/main/java/seedu/duke/CustomException.java create mode 100644 src/main/java/seedu/duke/Parser.java diff --git a/src/main/java/seedu/duke/CustomException.java b/src/main/java/seedu/duke/CustomException.java new file mode 100644 index 0000000000..3d4a0e0aa9 --- /dev/null +++ b/src/main/java/seedu/duke/CustomException.java @@ -0,0 +1,8 @@ +package seedu.duke; + +// TODO: Rename classname +public class CustomException extends Exception { + public CustomException(String message) { + super(message); + } +} diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 5c74e68d59..81a66614ed 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -1,21 +1,38 @@ package seedu.duke; -import java.util.Scanner; +import seedu.duke.command.Command; +import seedu.duke.module.ModuleList; public class Duke { + private final ModuleList modules; + private final Ui ui; + + public Duke() { + this.modules = new ModuleList(); + this.ui = new Ui(); + } + + public void run() { + ui.printWelcomeMessage(); + + boolean isExit = false; + do { + String userInput = ui.getUserInput(); + + try { + Command command = Parser.parseUserInput(userInput); + command.execute(modules, ui); + isExit = command.isExit(); + } catch (CustomException e) { + ui.printException(e.getMessage()); + } + } while (!isExit); + } + /** * 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()); + new Duke().run(); } } diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java new file mode 100644 index 0000000000..6fa00dc95e --- /dev/null +++ b/src/main/java/seedu/duke/Parser.java @@ -0,0 +1,85 @@ +package seedu.duke; + +import seedu.duke.command.AddModuleCommand; +import seedu.duke.command.Command; +import seedu.duke.command.ExitCommand; +import seedu.duke.command.ListModulesCommand; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; + +public class Parser { + private static final int USERINPUT_SPLIT_COUNT = 2; + + public static Command parseUserInput(String userInput) throws CustomException { + String[] userInputSplit = splitFirstSpace(userInput); + String commandString = userInputSplit[0]; + String argument = userInputSplit[1]; + + Command command; + switch (commandString) { + case Command.COMMAND_EXIT: + command = new ExitCommand(argument); + break; + + case Command.COMMAND_LIST_MODULES: + command = new ListModulesCommand(argument); + break; + + case Command.COMMAND_ADD_MODULE: + command = new AddModuleCommand(argument); + break; + + default: + throw new CustomException("Unknown Command"); + } + + return command; + } + + public static String[] splitFirstSpace(String string) { + String[] result = string.trim().split("\\s+", USERINPUT_SPLIT_COUNT); + if (result.length != USERINPUT_SPLIT_COUNT) { + return new String[]{result[0], ""}; + } + + return result; + } + + public static HashMap getArgumentsFromString(String string, String[] argumentKeys) { + String argumentString = " " + string; + HashMap argumentIndexMap = new HashMap<>(); + ArrayList argumentIndexes = new ArrayList<>(); + for (String key : argumentKeys) { + String searchString = String.format(" %s/", key); + int index = argumentString.indexOf(searchString); + if (index != -1) { + argumentIndexMap.put(key, index); + argumentIndexes.add(index); + } + } + Collections.sort(argumentIndexes); + + HashMap result = new HashMap<>(); + for (String key : argumentIndexMap.keySet()) { + int argumentIndex = argumentIndexMap.get(key); + int startIndex = argumentIndex + key.length() + 1; + + String value; + int listIndex = argumentIndexes.indexOf(argumentIndex); + boolean isLastIndex = listIndex == (argumentIndexes.size() - 1); + if (isLastIndex) { + value = string.substring(startIndex); + } else { + int nextIndex = argumentIndexes.get(listIndex + 1); + value = string.substring(startIndex, nextIndex - 1); + } + value = value.trim(); + + result.put(key, value); + } + + return result; + } +} From 71e811cc9388c33efab8dd93614d2a659250e5e0 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 6 Oct 2021 02:31:37 +0800 Subject: [PATCH 013/543] Add message when exiting --- src/main/java/seedu/duke/command/ExitCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/seedu/duke/command/ExitCommand.java b/src/main/java/seedu/duke/command/ExitCommand.java index b3a12eb8c4..742d61cd57 100644 --- a/src/main/java/seedu/duke/command/ExitCommand.java +++ b/src/main/java/seedu/duke/command/ExitCommand.java @@ -11,6 +11,7 @@ public ExitCommand(String argument) { @Override public void execute(ModuleList modules, Ui ui) throws CustomException { + ui.printExitMessage(); this.isExit = true; } } From 0936f4fe34bd06c5915297f91791dbe8b16c8974 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 6 Oct 2021 02:32:20 +0800 Subject: [PATCH 014/543] Update automated testing files --- text-ui-test/EXPECTED.TXT | 32 +++++++++++++++++++++++--------- text-ui-test/input.txt | 6 +++++- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 892cb6cae7..4fa1459242 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,9 +1,23 @@ -Hello from - ____ _ -| _ \ _ _| | _____ -| | | | | | | |/ / _ \ -| |_| | |_| | < __/ -|____/ \__,_|_|\_\___| - -What is your name? -Hello James Gosling +------------------------------------------------------------ +Welcome +What can I do for you? +------------------------------------------------------------ +$ ------------------------------------------------------------ +There are no modules in the list. +------------------------------------------------------------ +$ ------------------------------------------------------------ +Module added: + CS2113T - Software Engineering and Object-oriented Programming +There are 1 modules in the list. +------------------------------------------------------------ +$ ------------------------------------------------------------ +Module List: +1: CS2113T - Software Engineering and Object-oriented Programming +------------------------------------------------------------ +$ ------------------------------------------------------------ +An exception has occurred: +Unknown Command +------------------------------------------------------------ +$ ------------------------------------------------------------ +Bye. Hope to see you again soon! +------------------------------------------------------------ diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index f6ec2e9f95..0b8204edd8 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1 +1,5 @@ -James Gosling \ No newline at end of file +list_modules +add_module CS2113T n/Software Engineering and Object-oriented Programming +list_modules +invalid_command +exit \ No newline at end of file From e906193611b4dbb10315d3a1691c592ef6563f72 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 6 Oct 2021 10:27:06 +0800 Subject: [PATCH 015/543] Add argument parsing within Command class --- .../seedu/duke/command/AddModuleCommand.java | 24 +++++++++---------- src/main/java/seedu/duke/command/Command.java | 18 ++++++++++++-- 2 files changed, 28 insertions(+), 14 deletions(-) diff --git a/src/main/java/seedu/duke/command/AddModuleCommand.java b/src/main/java/seedu/duke/command/AddModuleCommand.java index 28e0db2458..42cfb48724 100644 --- a/src/main/java/seedu/duke/command/AddModuleCommand.java +++ b/src/main/java/seedu/duke/command/AddModuleCommand.java @@ -1,38 +1,38 @@ package seedu.duke.command; import seedu.duke.CustomException; -import seedu.duke.Parser; import seedu.duke.Ui; import seedu.duke.module.ModuleList; import seedu.duke.module.Module; -import java.util.HashMap; - public class AddModuleCommand extends Command { - private static String MESSAGE_MODULE_ADDED_FORMAT = "Module added:\n %s\nThere are %d modules in the list."; + private static final String MESSAGE_MODULE_ADDED_FORMAT = "Module added:\n %s\nThere are %d modules in the list."; - private static String[] argumentKeys = new String[]{"n"}; + private static final String[] ADD_MODULE_ARGUMENT_KEYS = {"c","n"}; public AddModuleCommand(String argument) { - super(argument); + super(argument, ADD_MODULE_ARGUMENT_KEYS); } @Override public void execute(ModuleList modules, Ui ui) throws CustomException { if (argument.isEmpty()) { + // TODO Usage format message throw new CustomException(""); } - String[] argumentSplit = Parser.splitFirstSpace(argument); - String moduleCode = argumentSplit[0]; - String additionalArgument = argumentSplit[1]; + if (!checkArgumentMap()) { + // TODO Invalid/missing arguments message + throw new CustomException(""); + } - HashMap argumentsMap = Parser.getArgumentsFromString(additionalArgument, argumentKeys); - if (!checkArgumentsMap(argumentsMap, argumentKeys)) { + String moduleCode = argumentMap.get("c"); + if (moduleCode.contains(" ")) { + // TODO Invalid module code message throw new CustomException(""); } - String name = argumentsMap.get("n"); + String name = argumentMap.get("n"); Module module = new Module(moduleCode, name); modules.addModule(module); diff --git a/src/main/java/seedu/duke/command/Command.java b/src/main/java/seedu/duke/command/Command.java index d110954a2e..6a952657b5 100644 --- a/src/main/java/seedu/duke/command/Command.java +++ b/src/main/java/seedu/duke/command/Command.java @@ -1,6 +1,7 @@ package seedu.duke.command; import seedu.duke.CustomException; +import seedu.duke.Parser; import seedu.duke.Ui; import seedu.duke.module.ModuleList; @@ -24,10 +25,18 @@ public abstract class Command { protected String argument; protected boolean isExit; + protected String[] argumentKeys; + protected HashMap argumentMap; public Command(String argument) { + this(argument, null); + } + + public Command(String argument, String[] argumentKeys) { this.argument = argument; this.isExit = false; + this.argumentKeys = argumentKeys; + this.argumentMap = Parser.getArgumentsFromString(argument, argumentKeys); } public boolean isExit() { @@ -36,9 +45,14 @@ public boolean isExit() { public abstract void execute(ModuleList modules, Ui ui) throws CustomException; - protected static boolean checkArgumentsMap(HashMap argumentsMap, String[] argumentKeys) { + /** + * Checks if argumentMap contains all the argument keys. + * + * @return true if argumentMap contains all keys, else false. + */ + protected boolean checkArgumentMap() { for (String key : argumentKeys) { - if (!argumentsMap.containsKey(key)) { + if (!argumentMap.containsKey(key)) { return false; } } From b3bf61ba3103be852954578f555a1a93f6a06890 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 6 Oct 2021 10:28:59 +0800 Subject: [PATCH 016/543] Add comments and constants --- src/main/java/seedu/duke/Parser.java | 29 +++++++++++++++---- src/main/java/seedu/duke/Ui.java | 8 ++--- .../java/seedu/duke/command/ExitCommand.java | 5 ++++ .../duke/command/ListModulesCommand.java | 5 ++++ 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 6fa00dc95e..2e147270bb 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -10,7 +10,7 @@ import java.util.HashMap; public class Parser { - private static final int USERINPUT_SPLIT_COUNT = 2; + private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown Command"; public static Command parseUserInput(String userInput) throws CustomException { String[] userInputSplit = splitFirstSpace(userInput); @@ -32,22 +32,39 @@ public static Command parseUserInput(String userInput) throws CustomException { break; default: - throw new CustomException("Unknown Command"); + throw new CustomException(MESSAGE_UNKNOWN_COMMAND); } return command; } public static String[] splitFirstSpace(String string) { - String[] result = string.trim().split("\\s+", USERINPUT_SPLIT_COUNT); - if (result.length != USERINPUT_SPLIT_COUNT) { + String[] result = string.trim().split("\\s+", 2); + if (result.length != 2) { return new String[]{result[0], ""}; } return result; } + /** + * Gets argument values specified by argumentKeys. + * e.g. + * string: "add_module c/CS2113T n/Software Engineering and Object-oriented Programming", argumentKeys: {"c","n"} + * Result: HashMap( + * "c":"CS2113T", + * "n":"Software Engineering and Object-oriented Programming" + * ) + * + * @param string The string to parse. + * @param argumentKeys The argument keys to find. + * @return HashMap - argumentKey:argumentValue pair. + */ public static HashMap getArgumentsFromString(String string, String[] argumentKeys) { + if (argumentKeys == null) { + return new HashMap<>(); + } + String argumentString = " " + string; HashMap argumentIndexMap = new HashMap<>(); ArrayList argumentIndexes = new ArrayList<>(); @@ -72,8 +89,8 @@ public static HashMap getArgumentsFromString(String string, Strin if (isLastIndex) { value = string.substring(startIndex); } else { - int nextIndex = argumentIndexes.get(listIndex + 1); - value = string.substring(startIndex, nextIndex - 1); + int nextListIndex = argumentIndexes.get(listIndex + 1); + value = string.substring(startIndex, nextListIndex - 1); } value = value.trim(); diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java index 99385597ff..d04ed6c920 100644 --- a/src/main/java/seedu/duke/Ui.java +++ b/src/main/java/seedu/duke/Ui.java @@ -4,6 +4,7 @@ public class Ui { private static final String INPUT_PROMPT = "$ "; + private static final String MESSAGE_BORDER = "------------------------------------------------------------"; private static final String MESSAGE_WELCOME = "Welcome\nWhat can I do for you?"; private static final String MESSAGE_EXIT = "Bye. Hope to see you again soon!"; @@ -12,9 +13,6 @@ public class Ui { private final Scanner scanner; - /** - * Constructor for Ui class. - */ public Ui() { this.scanner = new Scanner(System.in); } @@ -35,7 +33,7 @@ public String getUserInput() { } /** - * Prints message within horizontal lines. + * Prints message within borders. * * @param message The message to print. */ @@ -60,7 +58,7 @@ public void printExitMessage() { } /** - * Prints an exception. + * Prints an exception message. * * @param message The message to print. */ diff --git a/src/main/java/seedu/duke/command/ExitCommand.java b/src/main/java/seedu/duke/command/ExitCommand.java index 742d61cd57..361f279002 100644 --- a/src/main/java/seedu/duke/command/ExitCommand.java +++ b/src/main/java/seedu/duke/command/ExitCommand.java @@ -11,6 +11,11 @@ public ExitCommand(String argument) { @Override public void execute(ModuleList modules, Ui ui) throws CustomException { + if (!argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + ui.printExitMessage(); this.isExit = true; } diff --git a/src/main/java/seedu/duke/command/ListModulesCommand.java b/src/main/java/seedu/duke/command/ListModulesCommand.java index 99a9bb7355..0b820cad58 100644 --- a/src/main/java/seedu/duke/command/ListModulesCommand.java +++ b/src/main/java/seedu/duke/command/ListModulesCommand.java @@ -13,6 +13,11 @@ public ListModulesCommand(String argument) { @Override public void execute(ModuleList modules, Ui ui) throws CustomException { + if (!argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + if (modules.getSize() == 0) { ui.printMessage(MESSAGE_LIST_EMPTY); } else { From 2e3fe416fabf8453bac2066cab78cd71382db5f9 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 6 Oct 2021 10:29:41 +0800 Subject: [PATCH 017/543] Update automatic testing files --- text-ui-test/input.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index 0b8204edd8..d54660ce29 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,5 +1,5 @@ list_modules -add_module CS2113T n/Software Engineering and Object-oriented Programming +add_module c/CS2113T n/Software Engineering and Object-oriented Programming list_modules invalid_command exit \ No newline at end of file From 7c7a5859ddca00856aedeab65e6950e837f9d112 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 6 Oct 2021 10:36:34 +0800 Subject: [PATCH 018/543] Refactor variable name to a more appropriate name --- 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 2e147270bb..756c642549 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -89,8 +89,8 @@ public static HashMap getArgumentsFromString(String string, Strin if (isLastIndex) { value = string.substring(startIndex); } else { - int nextListIndex = argumentIndexes.get(listIndex + 1); - value = string.substring(startIndex, nextListIndex - 1); + int nextArgumentIndex = argumentIndexes.get(listIndex + 1); + value = string.substring(startIndex, nextArgumentIndex - 1); } value = value.trim(); From e1f7ae4188c1957f65d77a6c8c5a2782c3210bcd Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 6 Oct 2021 13:41:34 +0800 Subject: [PATCH 019/543] Handle empty array for Parser.getArgumentsFromString --- src/main/java/seedu/duke/Parser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java index 756c642549..1992faa02b 100644 --- a/src/main/java/seedu/duke/Parser.java +++ b/src/main/java/seedu/duke/Parser.java @@ -61,7 +61,7 @@ public static String[] splitFirstSpace(String string) { * @return HashMap - argumentKey:argumentValue pair. */ public static HashMap getArgumentsFromString(String string, String[] argumentKeys) { - if (argumentKeys == null) { + if (argumentKeys == null || argumentKeys.length == 0) { return new HashMap<>(); } From 1cf88f17200b122114120459894cee1294823a56 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Thu, 7 Oct 2021 16:09:46 +0800 Subject: [PATCH 020/543] edited about us for me --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index c2c40dbff6..660733f9c1 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -4,6 +4,6 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: ![](https://via.placeholder.com/100.png?text=Photo) | Zhen Hong | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Dak Nam | [Github](https://github.com/daknam2001) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Jon | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) + | Jon Lim | [jon-the-melon](https://github.com/jon-the-melon) | [Jon's Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Rachel | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Leyond | [Github](https://github.com/leyondlee) | [Portfolio](docs/team/leyond.md) From e089e32a311ec8ff127d9e7efb86d53dd0aa0287 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Thu, 7 Oct 2021 16:36:22 +0800 Subject: [PATCH 021/543] add jon and zhenhong aboutus --- .classpath | 19 ++++++++++++ .project | 34 ++++++++++++++++++++++ .settings/org.eclipse.buildship.core.prefs | 13 +++++++++ docs/team/jon.md | 0 docs/team/zhenhong.md | 0 5 files changed, 66 insertions(+) create mode 100644 .classpath create mode 100644 .project create mode 100644 .settings/org.eclipse.buildship.core.prefs create mode 100644 docs/team/jon.md create mode 100644 docs/team/zhenhong.md diff --git a/.classpath b/.classpath new file mode 100644 index 0000000000..9f9cc9f128 --- /dev/null +++ b/.classpath @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000000..d918c22678 --- /dev/null +++ b/.project @@ -0,0 +1,34 @@ + + + tp + Project tp created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + + + 1633064733980 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs new file mode 100644 index 0000000000..4664863da7 --- /dev/null +++ b/.settings/org.eclipse.buildship.core.prefs @@ -0,0 +1,13 @@ +arguments= +auto.sync=false +build.scans.enabled=false +connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) +connection.project.dir= +eclipse.preferences.version=1 +gradle.user.home= +java.home=C\:/Program Files/Amazon Corretto/jdk11.0.12_7 +jvm.arguments= +offline.mode=false +override.workspace.settings=true +show.console.view=true +show.executions.view=true diff --git a/docs/team/jon.md b/docs/team/jon.md new file mode 100644 index 0000000000..e69de29bb2 diff --git a/docs/team/zhenhong.md b/docs/team/zhenhong.md new file mode 100644 index 0000000000..e69de29bb2 From a13db66c3abbc61ea8847fad6e8951d6d02bbfe7 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Thu, 7 Oct 2021 16:36:44 +0800 Subject: [PATCH 022/543] add jon and zhenhong about us --- docs/AboutUs.md | 4 ++-- docs/team/jon.md | 1 + docs/team/zhenhong.md | 1 + 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 660733f9c1..01eb6dfa04 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,8 +2,8 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Zhen Hong | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Zhen Hong | [hozhenhong99](https://github.com/hozhenhong99) | [Zhen Hong's Portfolio](docs/team/zhenhong.md) ![](https://via.placeholder.com/100.png?text=Photo) | Dak Nam | [Github](https://github.com/daknam2001) | [Portfolio](docs/team/johndoe.md) - | Jon Lim | [jon-the-melon](https://github.com/jon-the-melon) | [Jon's Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Jon Lim | [jon-the-melon](https://github.com/jon-the-melon) | [Jon's Portfolio](docs/team/jon.md) ![](https://via.placeholder.com/100.png?text=Photo) | Rachel | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Leyond | [Github](https://github.com/leyondlee) | [Portfolio](docs/team/leyond.md) diff --git a/docs/team/jon.md b/docs/team/jon.md index e69de29bb2..68a9f4605e 100644 --- a/docs/team/jon.md +++ b/docs/team/jon.md @@ -0,0 +1 @@ +hi im jon \ No newline at end of file diff --git a/docs/team/zhenhong.md b/docs/team/zhenhong.md index e69de29bb2..aeaed9d066 100644 --- a/docs/team/zhenhong.md +++ b/docs/team/zhenhong.md @@ -0,0 +1 @@ +Hi im zhen hong \ No newline at end of file From dd29199701107f1ef1f247105a7e07fef21cb121 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 7 Oct 2021 19:35:22 +0800 Subject: [PATCH 023/543] Refactor main class and package name --- .classpath | 19 ---- .gitignore | 1 + .project | 34 ------ build.gradle | 4 +- src/main/java/taa/CustomException.java | 8 ++ src/main/java/taa/Parser.java | 102 ++++++++++++++++++ src/main/java/taa/Taa.java | 38 +++++++ src/main/java/taa/Ui.java | 68 ++++++++++++ .../java/taa/command/AddModuleCommand.java | 41 +++++++ src/main/java/taa/command/Command.java | 62 +++++++++++ src/main/java/taa/command/ExitCommand.java | 22 ++++ .../java/taa/command/ListModulesCommand.java | 27 +++++ src/main/java/taa/module/Module.java | 29 +++++ src/main/java/taa/module/ModuleList.java | 46 ++++++++ src/main/java/taa/student/Assessment.java | 5 + src/main/java/taa/student/Student.java | 10 ++ src/test/java/taa/TaaTest.java | 12 +++ 17 files changed, 473 insertions(+), 55 deletions(-) delete mode 100644 .classpath delete mode 100644 .project create mode 100644 src/main/java/taa/CustomException.java create mode 100644 src/main/java/taa/Parser.java create mode 100644 src/main/java/taa/Taa.java create mode 100644 src/main/java/taa/Ui.java create mode 100644 src/main/java/taa/command/AddModuleCommand.java create mode 100644 src/main/java/taa/command/Command.java create mode 100644 src/main/java/taa/command/ExitCommand.java create mode 100644 src/main/java/taa/command/ListModulesCommand.java create mode 100644 src/main/java/taa/module/Module.java create mode 100644 src/main/java/taa/module/ModuleList.java create mode 100644 src/main/java/taa/student/Assessment.java create mode 100644 src/main/java/taa/student/Student.java create mode 100644 src/test/java/taa/TaaTest.java diff --git a/.classpath b/.classpath deleted file mode 100644 index 9f9cc9f128..0000000000 --- a/.classpath +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.gitignore b/.gitignore index f69985ef1f..12368a19b2 100644 --- a/.gitignore +++ b/.gitignore @@ -15,3 +15,4 @@ bin/ /text-ui-test/ACTUAL.txt text-ui-test/EXPECTED-UNIX.TXT +text-ui-test/ACTUAL.TXT diff --git a/.project b/.project deleted file mode 100644 index d918c22678..0000000000 --- a/.project +++ /dev/null @@ -1,34 +0,0 @@ - - - tp - Project tp created by Buildship. - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.buildship.core.gradleprojectnature - - - - 1633064733980 - - 30 - - org.eclipse.core.resources.regexFilterMatcher - node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ - - - - diff --git a/build.gradle b/build.gradle index b0c5528fb5..a15eb244c1 100644 --- a/build.gradle +++ b/build.gradle @@ -29,11 +29,11 @@ test { } application { - mainClassName = "seedu.duke.Duke" + mainClassName = "taa.Taa" } shadowJar { - archiveBaseName = "duke" + archiveBaseName = "taa" archiveClassifier = null } diff --git a/src/main/java/taa/CustomException.java b/src/main/java/taa/CustomException.java new file mode 100644 index 0000000000..f7a82c32a7 --- /dev/null +++ b/src/main/java/taa/CustomException.java @@ -0,0 +1,8 @@ +package taa; + +// TODO: Rename classname +public class CustomException extends Exception { + public CustomException(String message) { + super(message); + } +} diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java new file mode 100644 index 0000000000..49fd5369d1 --- /dev/null +++ b/src/main/java/taa/Parser.java @@ -0,0 +1,102 @@ +package taa; + +import taa.command.AddModuleCommand; +import taa.command.Command; +import taa.command.ExitCommand; +import taa.command.ListModulesCommand; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; + +public class Parser { + private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown Command"; + + public static Command parseUserInput(String userInput) throws CustomException { + String[] userInputSplit = splitFirstSpace(userInput); + String commandString = userInputSplit[0]; + String argument = userInputSplit[1]; + + Command command; + switch (commandString) { + case Command.COMMAND_EXIT: + command = new ExitCommand(argument); + break; + + case Command.COMMAND_LIST_MODULES: + command = new ListModulesCommand(argument); + break; + + case Command.COMMAND_ADD_MODULE: + command = new AddModuleCommand(argument); + break; + + default: + throw new CustomException(MESSAGE_UNKNOWN_COMMAND); + } + + return command; + } + + public static String[] splitFirstSpace(String string) { + String[] result = string.trim().split("\\s+", 2); + if (result.length != 2) { + return new String[]{result[0], ""}; + } + + return result; + } + + /** + * Gets argument values specified by argumentKeys. + * e.g. + * string: "add_module c/CS2113T n/Software Engineering and Object-oriented Programming", argumentKeys: {"c","n"} + * Result: HashMap( + * "c":"CS2113T", + * "n":"Software Engineering and Object-oriented Programming" + * ) + * + * @param string The string to parse. + * @param argumentKeys The argument keys to find. + * @return HashMap - argumentKey:argumentValue pair. + */ + public static HashMap getArgumentsFromString(String string, String[] argumentKeys) { + if (argumentKeys == null || argumentKeys.length == 0) { + return new HashMap<>(); + } + + String argumentString = " " + string; + HashMap argumentIndexMap = new HashMap<>(); + ArrayList argumentIndexes = new ArrayList<>(); + for (String key : argumentKeys) { + String searchString = String.format(" %s/", key); + int index = argumentString.indexOf(searchString); + if (index != -1) { + argumentIndexMap.put(key, index); + argumentIndexes.add(index); + } + } + Collections.sort(argumentIndexes); + + HashMap result = new HashMap<>(); + for (String key : argumentIndexMap.keySet()) { + int argumentIndex = argumentIndexMap.get(key); + int startIndex = argumentIndex + key.length() + 1; + + String value; + int listIndex = argumentIndexes.indexOf(argumentIndex); + boolean isLastIndex = listIndex == (argumentIndexes.size() - 1); + if (isLastIndex) { + value = string.substring(startIndex); + } else { + int nextArgumentIndex = argumentIndexes.get(listIndex + 1); + value = string.substring(startIndex, nextArgumentIndex - 1); + } + value = value.trim(); + + result.put(key, value); + } + + return result; + } +} diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java new file mode 100644 index 0000000000..2f0e512b6b --- /dev/null +++ b/src/main/java/taa/Taa.java @@ -0,0 +1,38 @@ +package taa; + +import taa.command.Command; +import taa.module.ModuleList; + +public class Taa { + private final ModuleList modules; + private final Ui ui; + + public Taa() { + this.modules = new ModuleList(); + this.ui = new Ui(); + } + + public void run() { + ui.printWelcomeMessage(); + + boolean isExit = false; + do { + String userInput = ui.getUserInput(); + + try { + Command command = Parser.parseUserInput(userInput); + command.execute(modules, ui); + isExit = command.isExit(); + } catch (CustomException e) { + ui.printException(e.getMessage()); + } + } while (!isExit); + } + + /** + * Main entry-point for the java.duke.Duke application. + */ + public static void main(String[] args) { + new Taa().run(); + } +} diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java new file mode 100644 index 0000000000..52c3313ff9 --- /dev/null +++ b/src/main/java/taa/Ui.java @@ -0,0 +1,68 @@ +package taa; + +import java.util.Scanner; + +public class Ui { + private static final String INPUT_PROMPT = "$ "; + + private static final String MESSAGE_BORDER = "------------------------------------------------------------"; + private static final String MESSAGE_WELCOME = "Welcome\nWhat can I do for you?"; + private static final String MESSAGE_EXIT = "Bye. Hope to see you again soon!"; + + private static final String MESSAGE_FORMAT_EXCEPTION = "An exception has occurred:\n%s"; + + private final Scanner scanner; + + public Ui() { + this.scanner = new Scanner(System.in); + } + + /** + * Gets a non-empty user input. + * + * @return Non-empty user input. + */ + public String getUserInput() { + String input; + do { + System.out.print(INPUT_PROMPT); + input = scanner.nextLine(); + } while (input.trim().isEmpty()); + + return input; + } + + /** + * Prints message within borders. + * + * @param message The message to print. + */ + public void printMessage(String message) { + System.out.println(MESSAGE_BORDER); + System.out.println(message); + System.out.println(MESSAGE_BORDER); + } + + /** + * Prints the welcome message. + */ + public void printWelcomeMessage() { + printMessage(MESSAGE_WELCOME); + } + + /** + * Prints the exit message. + */ + public void printExitMessage() { + printMessage(MESSAGE_EXIT); + } + + /** + * Prints an exception message. + * + * @param message The message to print. + */ + public void printException(String message) { + printMessage(String.format(MESSAGE_FORMAT_EXCEPTION, message)); + } +} diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java new file mode 100644 index 0000000000..d9f9e6074a --- /dev/null +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -0,0 +1,41 @@ +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.module.ModuleList; +import taa.module.Module; + +public class AddModuleCommand extends Command { + private static final String MESSAGE_MODULE_ADDED_FORMAT = "Module added:\n %s\nThere are %d modules in the list."; + + private static final String[] ADD_MODULE_ARGUMENT_KEYS = {"c","n"}; + + public AddModuleCommand(String argument) { + super(argument, ADD_MODULE_ARGUMENT_KEYS); + } + + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + if (argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + + if (!checkArgumentMap()) { + // TODO Invalid/missing arguments message + throw new CustomException(""); + } + + String moduleCode = argumentMap.get("c"); + if (moduleCode.contains(" ")) { + // TODO Invalid module code message + throw new CustomException(""); + } + + String name = argumentMap.get("n"); + Module module = new Module(moduleCode, name); + modules.addModule(module); + + ui.printMessage(String.format(MESSAGE_MODULE_ADDED_FORMAT, module, modules.getSize())); + } +} diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java new file mode 100644 index 0000000000..cee4b924b9 --- /dev/null +++ b/src/main/java/taa/command/Command.java @@ -0,0 +1,62 @@ +package taa.command; + +import taa.CustomException; +import taa.Parser; +import taa.Ui; +import taa.module.ModuleList; + +import java.util.HashMap; + +public abstract class Command { + public static final String COMMAND_EXIT = "exit"; + public static final String COMMAND_LIST_MODULES = "list_modules"; + public static final String COMMAND_LIST_STUDENTS = "list_students"; + public static final String COMMAND_LIST_ASSESSMENTS = "list_assessments"; + public static final String COMMAND_LIST_ATTENDANCE = "list_attendance"; + public static final String COMMAND_LIST_MARKS = "list_marks"; + public static final String COMMAND_AVERAGE_MARKS = "average_marks"; + public static final String COMMAND_ADD_MODULE = "add_module"; + public static final String COMMAND_ADD_STUDENT = "add_student"; + public static final String COMMAND_EDIT_STUDENT = "edit_student"; + public static final String COMMAND_DELETE_STUDENT = "delete_student"; + public static final String COMMAND_SET_ATTENDANCE = "set_attendance"; + public static final String COMMAND_ADD_ASSESSMENT = "add_assessment"; + public static final String COMMAND_SET_MARKS = "set_marks"; + + protected String argument; + protected boolean isExit; + protected String[] argumentKeys; + protected HashMap argumentMap; + + public Command(String argument) { + this(argument, null); + } + + public Command(String argument, String[] argumentKeys) { + this.argument = argument; + this.isExit = false; + this.argumentKeys = argumentKeys; + this.argumentMap = Parser.getArgumentsFromString(argument, argumentKeys); + } + + public boolean isExit() { + return isExit; + } + + public abstract void execute(ModuleList modules, Ui ui) throws CustomException; + + /** + * Checks if argumentMap contains all the argument keys. + * + * @return true if argumentMap contains all keys, else false. + */ + protected boolean checkArgumentMap() { + for (String key : argumentKeys) { + if (!argumentMap.containsKey(key)) { + return false; + } + } + + return true; + } +} diff --git a/src/main/java/taa/command/ExitCommand.java b/src/main/java/taa/command/ExitCommand.java new file mode 100644 index 0000000000..e992bb185d --- /dev/null +++ b/src/main/java/taa/command/ExitCommand.java @@ -0,0 +1,22 @@ +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.module.ModuleList; + +public class ExitCommand extends Command { + public ExitCommand(String argument) { + super(argument); + } + + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + if (!argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + + ui.printExitMessage(); + this.isExit = true; + } +} diff --git a/src/main/java/taa/command/ListModulesCommand.java b/src/main/java/taa/command/ListModulesCommand.java new file mode 100644 index 0000000000..4f07d0319f --- /dev/null +++ b/src/main/java/taa/command/ListModulesCommand.java @@ -0,0 +1,27 @@ +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.module.ModuleList; + +public class ListModulesCommand extends Command { + private static final String MESSAGE_LIST_EMPTY = "There are no modules in the list."; + + public ListModulesCommand(String argument) { + super(argument); + } + + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + if (!argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + + if (modules.getSize() == 0) { + ui.printMessage(MESSAGE_LIST_EMPTY); + } else { + ui.printMessage(modules.toString()); + } + } +} diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java new file mode 100644 index 0000000000..5747e21f6e --- /dev/null +++ b/src/main/java/taa/module/Module.java @@ -0,0 +1,29 @@ +package taa.module; + +import taa.student.Assessment; +import taa.student.Student; + +import java.util.ArrayList; + +public class Module { + private final String code; + private final String name; + private final ArrayList students; + private final ArrayList assessments; + + public Module(String code, String name) { + this.code = code; + this.name = name; + this.students = new ArrayList<>(); + this.assessments = new ArrayList<>(); + } + + @Override + public String toString() { + if (name.isEmpty()) { + return code; + } + + return String.format("%s - %s", code, name); + } +} diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java new file mode 100644 index 0000000000..24c0ba6313 --- /dev/null +++ b/src/main/java/taa/module/ModuleList.java @@ -0,0 +1,46 @@ +package taa.module; + +import java.util.ArrayList; + +public class ModuleList { + private static final String MESSAGE_MODULE_LIST_HEADER = "Module List:"; + + private final ArrayList modules; + + public ModuleList() { + this.modules = new ArrayList<>(); + } + + public void addModule(Module module) { + modules.add(module); + } + + public int getSize() { + return modules.size(); + } + + public boolean isValidIndex(int index) { + return (index >= 0 && index < getSize()); + } + + public Module getModuleAt(int index) { + if (isValidIndex(index)) { + return modules.get(index); + } + + return null; + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(MESSAGE_MODULE_LIST_HEADER); + for (int i = 0; i < getSize(); i += 1) { + stringBuilder.append("\n"); + stringBuilder.append(i + 1); + stringBuilder.append(": "); + stringBuilder.append(getModuleAt(i)); + } + + return stringBuilder.toString(); + } +} diff --git a/src/main/java/taa/student/Assessment.java b/src/main/java/taa/student/Assessment.java new file mode 100644 index 0000000000..7cccbeef46 --- /dev/null +++ b/src/main/java/taa/student/Assessment.java @@ -0,0 +1,5 @@ +package taa.student; + +public class Assessment { + +} diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java new file mode 100644 index 0000000000..3aeb7aa8d2 --- /dev/null +++ b/src/main/java/taa/student/Student.java @@ -0,0 +1,10 @@ +package taa.student; + +public class Student { + private static int TOTAL_WEEKS = 13; + private boolean[] attendance; + + public Student() { + this.attendance = new boolean[TOTAL_WEEKS]; + } +} diff --git a/src/test/java/taa/TaaTest.java b/src/test/java/taa/TaaTest.java new file mode 100644 index 0000000000..ee362ddbfa --- /dev/null +++ b/src/test/java/taa/TaaTest.java @@ -0,0 +1,12 @@ +package taa; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +class TaaTest { + @Test + public void sampleTest() { + assertTrue(true); + } +} From 024cc2548aa952ec5d441c4a1899e5b77761ed03 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 7 Oct 2021 19:40:36 +0800 Subject: [PATCH 024/543] Remove package with old name --- src/main/java/seedu/duke/CustomException.java | 8 -- src/main/java/seedu/duke/Duke.java | 38 ------- src/main/java/seedu/duke/Parser.java | 102 ------------------ src/main/java/seedu/duke/Ui.java | 68 ------------ .../seedu/duke/command/AddModuleCommand.java | 41 ------- src/main/java/seedu/duke/command/Command.java | 62 ----------- .../java/seedu/duke/command/ExitCommand.java | 22 ---- .../duke/command/ListModulesCommand.java | 27 ----- src/main/java/seedu/duke/module/Module.java | 29 ----- .../java/seedu/duke/module/ModuleList.java | 46 -------- .../java/seedu/duke/student/Assessment.java | 5 - src/main/java/seedu/duke/student/Student.java | 10 -- src/test/java/seedu/duke/DukeTest.java | 12 --- 13 files changed, 470 deletions(-) delete mode 100644 src/main/java/seedu/duke/CustomException.java delete mode 100644 src/main/java/seedu/duke/Duke.java delete mode 100644 src/main/java/seedu/duke/Parser.java delete mode 100644 src/main/java/seedu/duke/Ui.java delete mode 100644 src/main/java/seedu/duke/command/AddModuleCommand.java delete mode 100644 src/main/java/seedu/duke/command/Command.java delete mode 100644 src/main/java/seedu/duke/command/ExitCommand.java delete mode 100644 src/main/java/seedu/duke/command/ListModulesCommand.java delete mode 100644 src/main/java/seedu/duke/module/Module.java delete mode 100644 src/main/java/seedu/duke/module/ModuleList.java delete mode 100644 src/main/java/seedu/duke/student/Assessment.java delete mode 100644 src/main/java/seedu/duke/student/Student.java delete mode 100644 src/test/java/seedu/duke/DukeTest.java diff --git a/src/main/java/seedu/duke/CustomException.java b/src/main/java/seedu/duke/CustomException.java deleted file mode 100644 index 3d4a0e0aa9..0000000000 --- a/src/main/java/seedu/duke/CustomException.java +++ /dev/null @@ -1,8 +0,0 @@ -package seedu.duke; - -// TODO: Rename classname -public class CustomException extends Exception { - public CustomException(String message) { - super(message); - } -} diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java deleted file mode 100644 index 81a66614ed..0000000000 --- a/src/main/java/seedu/duke/Duke.java +++ /dev/null @@ -1,38 +0,0 @@ -package seedu.duke; - -import seedu.duke.command.Command; -import seedu.duke.module.ModuleList; - -public class Duke { - private final ModuleList modules; - private final Ui ui; - - public Duke() { - this.modules = new ModuleList(); - this.ui = new Ui(); - } - - public void run() { - ui.printWelcomeMessage(); - - boolean isExit = false; - do { - String userInput = ui.getUserInput(); - - try { - Command command = Parser.parseUserInput(userInput); - command.execute(modules, ui); - isExit = command.isExit(); - } catch (CustomException e) { - ui.printException(e.getMessage()); - } - } while (!isExit); - } - - /** - * Main entry-point for the java.duke.Duke application. - */ - public static void main(String[] args) { - new Duke().run(); - } -} diff --git a/src/main/java/seedu/duke/Parser.java b/src/main/java/seedu/duke/Parser.java deleted file mode 100644 index 1992faa02b..0000000000 --- a/src/main/java/seedu/duke/Parser.java +++ /dev/null @@ -1,102 +0,0 @@ -package seedu.duke; - -import seedu.duke.command.AddModuleCommand; -import seedu.duke.command.Command; -import seedu.duke.command.ExitCommand; -import seedu.duke.command.ListModulesCommand; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; - -public class Parser { - private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown Command"; - - public static Command parseUserInput(String userInput) throws CustomException { - String[] userInputSplit = splitFirstSpace(userInput); - String commandString = userInputSplit[0]; - String argument = userInputSplit[1]; - - Command command; - switch (commandString) { - case Command.COMMAND_EXIT: - command = new ExitCommand(argument); - break; - - case Command.COMMAND_LIST_MODULES: - command = new ListModulesCommand(argument); - break; - - case Command.COMMAND_ADD_MODULE: - command = new AddModuleCommand(argument); - break; - - default: - throw new CustomException(MESSAGE_UNKNOWN_COMMAND); - } - - return command; - } - - public static String[] splitFirstSpace(String string) { - String[] result = string.trim().split("\\s+", 2); - if (result.length != 2) { - return new String[]{result[0], ""}; - } - - return result; - } - - /** - * Gets argument values specified by argumentKeys. - * e.g. - * string: "add_module c/CS2113T n/Software Engineering and Object-oriented Programming", argumentKeys: {"c","n"} - * Result: HashMap( - * "c":"CS2113T", - * "n":"Software Engineering and Object-oriented Programming" - * ) - * - * @param string The string to parse. - * @param argumentKeys The argument keys to find. - * @return HashMap - argumentKey:argumentValue pair. - */ - public static HashMap getArgumentsFromString(String string, String[] argumentKeys) { - if (argumentKeys == null || argumentKeys.length == 0) { - return new HashMap<>(); - } - - String argumentString = " " + string; - HashMap argumentIndexMap = new HashMap<>(); - ArrayList argumentIndexes = new ArrayList<>(); - for (String key : argumentKeys) { - String searchString = String.format(" %s/", key); - int index = argumentString.indexOf(searchString); - if (index != -1) { - argumentIndexMap.put(key, index); - argumentIndexes.add(index); - } - } - Collections.sort(argumentIndexes); - - HashMap result = new HashMap<>(); - for (String key : argumentIndexMap.keySet()) { - int argumentIndex = argumentIndexMap.get(key); - int startIndex = argumentIndex + key.length() + 1; - - String value; - int listIndex = argumentIndexes.indexOf(argumentIndex); - boolean isLastIndex = listIndex == (argumentIndexes.size() - 1); - if (isLastIndex) { - value = string.substring(startIndex); - } else { - int nextArgumentIndex = argumentIndexes.get(listIndex + 1); - value = string.substring(startIndex, nextArgumentIndex - 1); - } - value = value.trim(); - - result.put(key, value); - } - - return result; - } -} diff --git a/src/main/java/seedu/duke/Ui.java b/src/main/java/seedu/duke/Ui.java deleted file mode 100644 index d04ed6c920..0000000000 --- a/src/main/java/seedu/duke/Ui.java +++ /dev/null @@ -1,68 +0,0 @@ -package seedu.duke; - -import java.util.Scanner; - -public class Ui { - private static final String INPUT_PROMPT = "$ "; - - private static final String MESSAGE_BORDER = "------------------------------------------------------------"; - private static final String MESSAGE_WELCOME = "Welcome\nWhat can I do for you?"; - private static final String MESSAGE_EXIT = "Bye. Hope to see you again soon!"; - - private static final String MESSAGE_FORMAT_EXCEPTION = "An exception has occurred:\n%s"; - - private final Scanner scanner; - - public Ui() { - this.scanner = new Scanner(System.in); - } - - /** - * Gets a non-empty user input. - * - * @return Non-empty user input. - */ - public String getUserInput() { - String input; - do { - System.out.print(INPUT_PROMPT); - input = scanner.nextLine(); - } while (input.trim().isEmpty()); - - return input; - } - - /** - * Prints message within borders. - * - * @param message The message to print. - */ - public void printMessage(String message) { - System.out.println(MESSAGE_BORDER); - System.out.println(message); - System.out.println(MESSAGE_BORDER); - } - - /** - * Prints the welcome message. - */ - public void printWelcomeMessage() { - printMessage(MESSAGE_WELCOME); - } - - /** - * Prints the exit message. - */ - public void printExitMessage() { - printMessage(MESSAGE_EXIT); - } - - /** - * Prints an exception message. - * - * @param message The message to print. - */ - public void printException(String message) { - printMessage(String.format(MESSAGE_FORMAT_EXCEPTION, message)); - } -} diff --git a/src/main/java/seedu/duke/command/AddModuleCommand.java b/src/main/java/seedu/duke/command/AddModuleCommand.java deleted file mode 100644 index 42cfb48724..0000000000 --- a/src/main/java/seedu/duke/command/AddModuleCommand.java +++ /dev/null @@ -1,41 +0,0 @@ -package seedu.duke.command; - -import seedu.duke.CustomException; -import seedu.duke.Ui; -import seedu.duke.module.ModuleList; -import seedu.duke.module.Module; - -public class AddModuleCommand extends Command { - private static final String MESSAGE_MODULE_ADDED_FORMAT = "Module added:\n %s\nThere are %d modules in the list."; - - private static final String[] ADD_MODULE_ARGUMENT_KEYS = {"c","n"}; - - public AddModuleCommand(String argument) { - super(argument, ADD_MODULE_ARGUMENT_KEYS); - } - - @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { - if (argument.isEmpty()) { - // TODO Usage format message - throw new CustomException(""); - } - - if (!checkArgumentMap()) { - // TODO Invalid/missing arguments message - throw new CustomException(""); - } - - String moduleCode = argumentMap.get("c"); - if (moduleCode.contains(" ")) { - // TODO Invalid module code message - throw new CustomException(""); - } - - String name = argumentMap.get("n"); - Module module = new Module(moduleCode, name); - modules.addModule(module); - - ui.printMessage(String.format(MESSAGE_MODULE_ADDED_FORMAT, module, modules.getSize())); - } -} diff --git a/src/main/java/seedu/duke/command/Command.java b/src/main/java/seedu/duke/command/Command.java deleted file mode 100644 index 6a952657b5..0000000000 --- a/src/main/java/seedu/duke/command/Command.java +++ /dev/null @@ -1,62 +0,0 @@ -package seedu.duke.command; - -import seedu.duke.CustomException; -import seedu.duke.Parser; -import seedu.duke.Ui; -import seedu.duke.module.ModuleList; - -import java.util.HashMap; - -public abstract class Command { - public static final String COMMAND_EXIT = "exit"; - public static final String COMMAND_LIST_MODULES = "list_modules"; - public static final String COMMAND_LIST_STUDENTS = "list_students"; - public static final String COMMAND_LIST_ASSESSMENTS = "list_assessments"; - public static final String COMMAND_LIST_ATTENDANCE = "list_attendance"; - public static final String COMMAND_LIST_MARKS = "list_marks"; - public static final String COMMAND_AVERAGE_MARKS = "average_marks"; - public static final String COMMAND_ADD_MODULE = "add_module"; - public static final String COMMAND_ADD_STUDENT = "add_student"; - public static final String COMMAND_EDIT_STUDENT = "edit_student"; - public static final String COMMAND_DELETE_STUDENT = "delete_student"; - public static final String COMMAND_SET_ATTENDANCE = "set_attendance"; - public static final String COMMAND_ADD_ASSESSMENT = "add_assessment"; - public static final String COMMAND_SET_MARKS = "set_marks"; - - protected String argument; - protected boolean isExit; - protected String[] argumentKeys; - protected HashMap argumentMap; - - public Command(String argument) { - this(argument, null); - } - - public Command(String argument, String[] argumentKeys) { - this.argument = argument; - this.isExit = false; - this.argumentKeys = argumentKeys; - this.argumentMap = Parser.getArgumentsFromString(argument, argumentKeys); - } - - public boolean isExit() { - return isExit; - } - - public abstract void execute(ModuleList modules, Ui ui) throws CustomException; - - /** - * Checks if argumentMap contains all the argument keys. - * - * @return true if argumentMap contains all keys, else false. - */ - protected boolean checkArgumentMap() { - for (String key : argumentKeys) { - if (!argumentMap.containsKey(key)) { - return false; - } - } - - return true; - } -} diff --git a/src/main/java/seedu/duke/command/ExitCommand.java b/src/main/java/seedu/duke/command/ExitCommand.java deleted file mode 100644 index 361f279002..0000000000 --- a/src/main/java/seedu/duke/command/ExitCommand.java +++ /dev/null @@ -1,22 +0,0 @@ -package seedu.duke.command; - -import seedu.duke.CustomException; -import seedu.duke.Ui; -import seedu.duke.module.ModuleList; - -public class ExitCommand extends Command { - public ExitCommand(String argument) { - super(argument); - } - - @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { - if (!argument.isEmpty()) { - // TODO Usage format message - throw new CustomException(""); - } - - ui.printExitMessage(); - this.isExit = true; - } -} diff --git a/src/main/java/seedu/duke/command/ListModulesCommand.java b/src/main/java/seedu/duke/command/ListModulesCommand.java deleted file mode 100644 index 0b820cad58..0000000000 --- a/src/main/java/seedu/duke/command/ListModulesCommand.java +++ /dev/null @@ -1,27 +0,0 @@ -package seedu.duke.command; - -import seedu.duke.CustomException; -import seedu.duke.Ui; -import seedu.duke.module.ModuleList; - -public class ListModulesCommand extends Command { - private static final String MESSAGE_LIST_EMPTY = "There are no modules in the list."; - - public ListModulesCommand(String argument) { - super(argument); - } - - @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { - if (!argument.isEmpty()) { - // TODO Usage format message - throw new CustomException(""); - } - - if (modules.getSize() == 0) { - ui.printMessage(MESSAGE_LIST_EMPTY); - } else { - ui.printMessage(modules.toString()); - } - } -} diff --git a/src/main/java/seedu/duke/module/Module.java b/src/main/java/seedu/duke/module/Module.java deleted file mode 100644 index 09f234fa0f..0000000000 --- a/src/main/java/seedu/duke/module/Module.java +++ /dev/null @@ -1,29 +0,0 @@ -package seedu.duke.module; - -import seedu.duke.student.Assessment; -import seedu.duke.student.Student; - -import java.util.ArrayList; - -public class Module { - private final String code; - private final String name; - private final ArrayList students; - private final ArrayList assessments; - - public Module(String code, String name) { - this.code = code; - this.name = name; - this.students = new ArrayList<>(); - this.assessments = new ArrayList<>(); - } - - @Override - public String toString() { - if (name.isEmpty()) { - return code; - } - - return String.format("%s - %s", code, name); - } -} diff --git a/src/main/java/seedu/duke/module/ModuleList.java b/src/main/java/seedu/duke/module/ModuleList.java deleted file mode 100644 index 8290c2df9b..0000000000 --- a/src/main/java/seedu/duke/module/ModuleList.java +++ /dev/null @@ -1,46 +0,0 @@ -package seedu.duke.module; - -import java.util.ArrayList; - -public class ModuleList { - private static final String MESSAGE_MODULE_LIST_HEADER = "Module List:"; - - private final ArrayList modules; - - public ModuleList() { - this.modules = new ArrayList<>(); - } - - public void addModule(Module module) { - modules.add(module); - } - - public int getSize() { - return modules.size(); - } - - public boolean isValidIndex(int index) { - return (index >= 0 && index < getSize()); - } - - public Module getModuleAt(int index) { - if (isValidIndex(index)) { - return modules.get(index); - } - - return null; - } - - @Override - public String toString() { - StringBuilder stringBuilder = new StringBuilder(MESSAGE_MODULE_LIST_HEADER); - for (int i = 0; i < getSize(); i += 1) { - stringBuilder.append("\n"); - stringBuilder.append(i + 1); - stringBuilder.append(": "); - stringBuilder.append(getModuleAt(i)); - } - - return stringBuilder.toString(); - } -} diff --git a/src/main/java/seedu/duke/student/Assessment.java b/src/main/java/seedu/duke/student/Assessment.java deleted file mode 100644 index 9680a797ef..0000000000 --- a/src/main/java/seedu/duke/student/Assessment.java +++ /dev/null @@ -1,5 +0,0 @@ -package seedu.duke.student; - -public class Assessment { - -} diff --git a/src/main/java/seedu/duke/student/Student.java b/src/main/java/seedu/duke/student/Student.java deleted file mode 100644 index c306396ac4..0000000000 --- a/src/main/java/seedu/duke/student/Student.java +++ /dev/null @@ -1,10 +0,0 @@ -package seedu.duke.student; - -public class Student { - private static int TOTAL_WEEKS = 13; - private boolean[] attendance; - - public Student() { - this.attendance = new boolean[TOTAL_WEEKS]; - } -} diff --git a/src/test/java/seedu/duke/DukeTest.java b/src/test/java/seedu/duke/DukeTest.java deleted file mode 100644 index 2dda5fd651..0000000000 --- a/src/test/java/seedu/duke/DukeTest.java +++ /dev/null @@ -1,12 +0,0 @@ -package seedu.duke; - -import static org.junit.jupiter.api.Assertions.assertTrue; - -import org.junit.jupiter.api.Test; - -class DukeTest { - @Test - public void sampleTest() { - assertTrue(true); - } -} From ee4f4de052f1d72364db872ea21c82ebc2624368 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 7 Oct 2021 19:55:55 +0800 Subject: [PATCH 025/543] Add test for Parser.getArgumentsFromString --- src/test/java/taa/ParserTest.java | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 src/test/java/taa/ParserTest.java diff --git a/src/test/java/taa/ParserTest.java b/src/test/java/taa/ParserTest.java new file mode 100644 index 0000000000..214902bfdf --- /dev/null +++ b/src/test/java/taa/ParserTest.java @@ -0,0 +1,29 @@ +package taa; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class ParserTest { + + @Test + void getArgumentsFromString_noKeys_expectEmpty() { + String inputString = "c/CS2113T n/Software Engineering and Object-oriented Programming"; + String[] keys = {}; + assertTrue(Parser.getArgumentsFromString(inputString, keys).isEmpty()); + } + + @Test + void getArgumentsFromString_oneKey_expectOneItem() { + String inputString = "c/CS2113T n/Software Engineering and Object-oriented Programming"; + String[] keys = {"n"}; + assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 1); + } + + @Test + void getArgumentsFromString_twoKeys_expectTwoItems() { + String inputString = "c/CS2113T n/Software Engineering and Object-oriented Programming"; + String[] keys = {"c","n"}; + assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 2); + } +} \ No newline at end of file From 4105e08130e0df520d4b3ec2d46e6e26aeaf06bb Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 7 Oct 2021 19:58:36 +0800 Subject: [PATCH 026/543] Add new line at end of file --- src/test/java/taa/ParserTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/taa/ParserTest.java b/src/test/java/taa/ParserTest.java index 214902bfdf..620983f4b8 100644 --- a/src/test/java/taa/ParserTest.java +++ b/src/test/java/taa/ParserTest.java @@ -26,4 +26,4 @@ void getArgumentsFromString_twoKeys_expectTwoItems() { String[] keys = {"c","n"}; assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 2); } -} \ No newline at end of file +} From b1eaea703cc9aaea6e41151976b20c8f993c0dfa Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 7 Oct 2021 20:00:59 +0800 Subject: [PATCH 027/543] Remove wildcard import --- src/test/java/taa/ParserTest.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/java/taa/ParserTest.java b/src/test/java/taa/ParserTest.java index 620983f4b8..d801589117 100644 --- a/src/test/java/taa/ParserTest.java +++ b/src/test/java/taa/ParserTest.java @@ -2,7 +2,8 @@ import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; class ParserTest { From af9a0d2c3d30af287f4d8b5e85b84c4d4f9ff403 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Thu, 7 Oct 2021 22:33:04 +0800 Subject: [PATCH 028/543] implement testing for toString method of student --- .classpath | 19 ++++++++++++ .project | 34 +++++++++++++++++++++ src/main/java/taa/student/Student.java | 41 +++++++++++++++++++++++--- src/test/java/taa/StudentTest.java | 14 +++++++++ 4 files changed, 104 insertions(+), 4 deletions(-) create mode 100644 .classpath create mode 100644 .project create mode 100644 src/test/java/taa/StudentTest.java diff --git a/.classpath b/.classpath new file mode 100644 index 0000000000..9f9cc9f128 --- /dev/null +++ b/.classpath @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000000..ab8bd61efe --- /dev/null +++ b/.project @@ -0,0 +1,34 @@ + + + tp + Project tp created by Buildship. + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.buildship.core.gradleprojectbuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.buildship.core.gradleprojectnature + + + + 1633614929414 + + 30 + + org.eclipse.core.resources.regexFilterMatcher + node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ + + + + diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index 3aeb7aa8d2..29054a1138 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -1,10 +1,43 @@ package taa.student; public class Student { - private static int TOTAL_WEEKS = 13; - private boolean[] attendance; + private static final int NUM_LESSONS = 13; - public Student() { - this.attendance = new boolean[TOTAL_WEEKS]; + private String name; + private String studentID; + private final boolean[] attendance = new boolean[NUM_LESSONS]; + + public Student(String name, String studentID) { + this.name = name; + this.studentID = studentID; + } + + public void markAttendance(int lesson_index) { + attendance[lesson_index] = true; + } + + public boolean getAttendance(int lesson_index) { + return attendance[lesson_index]; + } + + public void setName(String name) { + this.name = name; + } + + public String getName() { + return this.name; + } + + public void setStudentID(String studentID) { + this.studentID = studentID; + } + + public String getStudentID() { + return this.studentID; + } + + @Override + public String toString() { + return name + ", " + studentID; } } diff --git a/src/test/java/taa/StudentTest.java b/src/test/java/taa/StudentTest.java new file mode 100644 index 0000000000..2c6ae1d461 --- /dev/null +++ b/src/test/java/taa/StudentTest.java @@ -0,0 +1,14 @@ +package taa; + +import taa.student.Student; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class StudentTest { + @Test + public void testStringConversion() { + assertEquals("Jon Lim, A0217746X", new Student("Jon Lim", "A0217746X").toString()); + } + +} From 66914767571a84712a41c833f284c3e21ccb4196 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Thu, 7 Oct 2021 22:57:29 +0800 Subject: [PATCH 029/543] added junit test for marks --- src/main/java/taa/student/Mark.java | 42 +++++++++++++++++++++++++++++ src/test/java/taa/MarkTest.java | 14 ++++++++++ 2 files changed, 56 insertions(+) create mode 100644 src/main/java/taa/student/Mark.java create mode 100644 src/test/java/taa/MarkTest.java diff --git a/src/main/java/taa/student/Mark.java b/src/main/java/taa/student/Mark.java new file mode 100644 index 0000000000..bca403c96b --- /dev/null +++ b/src/main/java/taa/student/Mark.java @@ -0,0 +1,42 @@ +package taa.student; + +public class Mark { + private String assessment_name; + private int marks; + private double weightage; + + public Mark(String assessment_name, int marks, double weightage) { + this.assessment_name = assessment_name; + this.marks = marks; + this.weightage = weightage; + } + + public void setAssessmentName(String assessment_name) { + this.assessment_name = assessment_name; + } + + public void setMarks(int marks) { + this.marks = marks; + } + + public void setWeightage(double weightage) { + this.weightage = weightage; + } + + public String getAssessmentName() { + return assessment_name; + } + + public int getMarks() { + return marks; + } + + public double getWeightage() { + return weightage; + } + + @Override + public String toString() { + return assessment_name + ", " + marks + ", " + weightage; + } +} diff --git a/src/test/java/taa/MarkTest.java b/src/test/java/taa/MarkTest.java new file mode 100644 index 0000000000..d4e903f90c --- /dev/null +++ b/src/test/java/taa/MarkTest.java @@ -0,0 +1,14 @@ +package taa; + +import org.junit.jupiter.api.Test; +import taa.student.Mark; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class MarkTest { + @Test + public void testMarksStringConversion() { + assertEquals("Assignment 5, 56, 0.5", + new Mark("Assignment 5", 56, 0.5).toString()); + } +} From d36757386bcc3bd241622896d4aa5ebf6d47b989 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Thu, 7 Oct 2021 23:04:38 +0800 Subject: [PATCH 030/543] Edited to fit coding style --- src/main/java/taa/student/Mark.java | 14 +++++++------- src/main/java/taa/student/Student.java | 8 ++++---- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/taa/student/Mark.java b/src/main/java/taa/student/Mark.java index bca403c96b..6322eab4a2 100644 --- a/src/main/java/taa/student/Mark.java +++ b/src/main/java/taa/student/Mark.java @@ -1,18 +1,18 @@ package taa.student; public class Mark { - private String assessment_name; + private String assessmentName; private int marks; private double weightage; - public Mark(String assessment_name, int marks, double weightage) { - this.assessment_name = assessment_name; + public Mark(String assessmentName, int marks, double weightage) { + this.assessmentName = assessmentName; this.marks = marks; this.weightage = weightage; } - public void setAssessmentName(String assessment_name) { - this.assessment_name = assessment_name; + public void setAssessmentName(String assessmentName) { + this.assessmentName = assessmentName; } public void setMarks(int marks) { @@ -24,7 +24,7 @@ public void setWeightage(double weightage) { } public String getAssessmentName() { - return assessment_name; + return assessmentName; } public int getMarks() { @@ -37,6 +37,6 @@ public double getWeightage() { @Override public String toString() { - return assessment_name + ", " + marks + ", " + weightage; + return assessmentName + ", " + marks + ", " + weightage; } } diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index 29054a1138..53ff816722 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -12,12 +12,12 @@ public Student(String name, String studentID) { this.studentID = studentID; } - public void markAttendance(int lesson_index) { - attendance[lesson_index] = true; + public void markAttendance(int lessonIndex) { + attendance[lessonIndex] = true; } - public boolean getAttendance(int lesson_index) { - return attendance[lesson_index]; + public boolean getAttendance(int lessonIndex) { + return attendance[lessonIndex]; } public void setName(String name) { From d1858d15ae3b2a76d4a022dbd659e6a9b05e52a7 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 7 Oct 2021 23:10:57 +0800 Subject: [PATCH 031/543] Add local project files in .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 12368a19b2..789d235f52 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ src/main/resources/docs/ *.iml bin/ -/text-ui-test/ACTUAL.txt text-ui-test/EXPECTED-UNIX.TXT text-ui-test/ACTUAL.TXT +.classpath +.project From 0503d78ac634152a574ec0d3bf336e3de46a0302 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 7 Oct 2021 23:12:11 +0800 Subject: [PATCH 032/543] Remove local project files --- .classpath | 19 ------------------- .project | 34 ---------------------------------- 2 files changed, 53 deletions(-) delete mode 100644 .classpath delete mode 100644 .project diff --git a/.classpath b/.classpath deleted file mode 100644 index 9f9cc9f128..0000000000 --- a/.classpath +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/.project b/.project deleted file mode 100644 index ab8bd61efe..0000000000 --- a/.project +++ /dev/null @@ -1,34 +0,0 @@ - - - tp - Project tp created by Buildship. - - - - - org.eclipse.jdt.core.javabuilder - - - - - org.eclipse.buildship.core.gradleprojectbuilder - - - - - - org.eclipse.jdt.core.javanature - org.eclipse.buildship.core.gradleprojectnature - - - - 1633614929414 - - 30 - - org.eclipse.core.resources.regexFilterMatcher - node_modules|.git|__CREATED_BY_JAVA_LANGUAGE_SERVER__ - - - - From 0a1bd605bea5748d2e8e9904f1874251c054ab48 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Thu, 7 Oct 2021 23:41:18 +0800 Subject: [PATCH 033/543] add toString for attendance and test --- src/main/java/taa/student/Assessment.java | 1 - src/main/java/taa/student/Attendance.java | 20 +++++++++++++++++++ src/test/java/taa/student/AttendanceTest.java | 14 +++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/main/java/taa/student/Attendance.java create mode 100644 src/test/java/taa/student/AttendanceTest.java diff --git a/src/main/java/taa/student/Assessment.java b/src/main/java/taa/student/Assessment.java index 7cccbeef46..1d708b5bfe 100644 --- a/src/main/java/taa/student/Assessment.java +++ b/src/main/java/taa/student/Assessment.java @@ -1,5 +1,4 @@ package taa.student; public class Assessment { - } diff --git a/src/main/java/taa/student/Attendance.java b/src/main/java/taa/student/Attendance.java new file mode 100644 index 0000000000..b12c6338b3 --- /dev/null +++ b/src/main/java/taa/student/Attendance.java @@ -0,0 +1,20 @@ +package taa.student; + +public class Attendance { + private int lessonNum; + private boolean hadAttend; + + public Attendance(int lessonNum){ + this.lessonNum = lessonNum; + this.hadAttend = false; + } + + public int markAttendance() { + return (hadAttend? 1 : 0); + } + + @Override + public String toString(){ + return lessonNum + " - " + markAttendance(); + } +} diff --git a/src/test/java/taa/student/AttendanceTest.java b/src/test/java/taa/student/AttendanceTest.java new file mode 100644 index 0000000000..2837c83e90 --- /dev/null +++ b/src/test/java/taa/student/AttendanceTest.java @@ -0,0 +1,14 @@ +package taa.student; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class AttendanceTest { + + @Test + void testAttendanceStringConversion() { + assertEquals("1 - 0", + new Attendance(1).toString()); + } +} \ No newline at end of file From 7d301b975418a3f403c62295a3e02d1e47fa8626 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Thu, 7 Oct 2021 23:47:04 +0800 Subject: [PATCH 034/543] fix format issues --- src/main/java/taa/student/Attendance.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/taa/student/Attendance.java b/src/main/java/taa/student/Attendance.java index b12c6338b3..d85c34e4f5 100644 --- a/src/main/java/taa/student/Attendance.java +++ b/src/main/java/taa/student/Attendance.java @@ -4,17 +4,17 @@ public class Attendance { private int lessonNum; private boolean hadAttend; - public Attendance(int lessonNum){ + public Attendance(int lessonNum) { this.lessonNum = lessonNum; this.hadAttend = false; } public int markAttendance() { - return (hadAttend? 1 : 0); + return (hadAttend ? 1 : 0); } @Override - public String toString(){ - return lessonNum + " - " + markAttendance(); + public String toString() { + return lessonNum + " - " + markAttendance(); } } From 02bbbb947d49cd64a948fad1f84576c82dc140c2 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Thu, 7 Oct 2021 23:50:33 +0800 Subject: [PATCH 035/543] fix importing with * --- src/test/java/taa/student/AttendanceTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/taa/student/AttendanceTest.java b/src/test/java/taa/student/AttendanceTest.java index 2837c83e90..202f847c7e 100644 --- a/src/test/java/taa/student/AttendanceTest.java +++ b/src/test/java/taa/student/AttendanceTest.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 AttendanceTest { From ca3573fbd665f8eb5a9b4a1346dd122c14d1df14 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Fri, 8 Oct 2021 22:52:43 +0800 Subject: [PATCH 036/543] implement add student --- src/main/java/taa/Parser.java | 8 ++-- .../java/taa/command/AddStudentCommand.java | 45 +++++++++++++++++++ src/main/java/taa/student/Student.java | 41 ++++++++++++++++- 3 files changed, 89 insertions(+), 5 deletions(-) create mode 100644 src/main/java/taa/command/AddStudentCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 49fd5369d1..da53f063b2 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,9 +1,6 @@ package taa; -import taa.command.AddModuleCommand; -import taa.command.Command; -import taa.command.ExitCommand; -import taa.command.ListModulesCommand; +import taa.command.*; import java.util.ArrayList; import java.util.Collections; @@ -31,6 +28,9 @@ public static Command parseUserInput(String userInput) throws CustomException { command = new AddModuleCommand(argument); break; + case Command.COMMAND_ADD_STUDENT: + command = new AddStudentCommand(argument); + default: throw new CustomException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java new file mode 100644 index 0000000000..5663485f91 --- /dev/null +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -0,0 +1,45 @@ +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.module.Module; +import taa.module.ModuleList; +import taa.student.Student; + +public class AddStudentCommand extends Command{ + + private static final String MESSAGE_STUDENT_ADDED_FORMAT = "Student %s, %s has been added to %s"; + private static final String[] ADD_STUDENT_ARGUMENT_KEYS = {"c","s","i"}; + + public AddStudentCommand(String argument) { + super(argument, ADD_STUDENT_ARGUMENT_KEYS); + } + + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + if (argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + + if (!checkArgumentMap()) { + // TODO Invalid/missing arguments message + throw new CustomException(""); + } + + String moduleCode = argumentMap.get("c"); + if (moduleCode.contains(" ")) { + // TODO Invalid module code message + throw new CustomException(""); + } + + String studentName = argumentMap.get("s"); + String studentID = argumentMap.get("i"); + Student student = new Student(studentName, studentID); + for (int i = 0; i < modules.getSize(); i += 1) { + //TODO find module in modules and add student to module + } + + ui.printMessage(String.format(MESSAGE_STUDENT_ADDED_FORMAT, studentName, studentID, moduleCode)); + } +} diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index 53ff816722..fd69e9802d 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -1,5 +1,8 @@ package taa.student; +/** + * Represents students + */ public class Student { private static final int NUM_LESSONS = 13; @@ -12,30 +15,66 @@ public Student(String name, String studentID) { this.studentID = studentID; } + /** + * Marks the student as present for a particular lesson + * + * @param lessonIndex The lesson index the student is present for + */ public void markAttendance(int lessonIndex) { attendance[lessonIndex] = true; } - public boolean getAttendance(int lessonIndex) { + /** + * Returns the attendance status of the student for a particular lesson + * + * @param lessonIndex The lesson index + * @return The attendance status of the student for the lesson + */ + public boolean isPresent(int lessonIndex) { return attendance[lessonIndex]; } + /** + * Sets the name of the student + * + * @param name The name of the student + */ public void setName(String name) { this.name = name; } + /** + * Returns the name of the student + * + * @return The name of the student + */ public String getName() { return this.name; } + /** + * Sets the student ID of the student + * + * @param studentID the student ID of the student + */ public void setStudentID(String studentID) { this.studentID = studentID; } + /** + * returns the student ID of the student + * + * @return the student ID of the student + */ public String getStudentID() { return this.studentID; } + /** + * Overrides default toString method with the custom print message + * + * @return the custom print message + */ @Override public String toString() { return name + ", " + studentID; From 5dcf9fc88ae4f3922ea7fc64c228e46a9dfd9334 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 02:29:57 +0800 Subject: [PATCH 037/543] Modify variable name to a consistent format --- src/main/java/taa/Ui.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index 52c3313ff9..fdee857f33 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -9,7 +9,7 @@ public class Ui { private static final String MESSAGE_WELCOME = "Welcome\nWhat can I do for you?"; private static final String MESSAGE_EXIT = "Bye. Hope to see you again soon!"; - private static final String MESSAGE_FORMAT_EXCEPTION = "An exception has occurred:\n%s"; + private static final String MESSAGE_EXCEPTION_FORMAT = "An exception has occurred:\n%s"; private final Scanner scanner; @@ -63,6 +63,6 @@ public void printExitMessage() { * @param message The message to print. */ public void printException(String message) { - printMessage(String.format(MESSAGE_FORMAT_EXCEPTION, message)); + printMessage(String.format(MESSAGE_EXCEPTION_FORMAT, message)); } } From b3252f738d0b54d1888f4eb2f2ba8d6749d55593 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 02:32:38 +0800 Subject: [PATCH 038/543] Add getters/setters and add student/assessment functions --- src/main/java/taa/module/Module.java | 62 ++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index 5747e21f6e..669c8fbf22 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -1,21 +1,77 @@ package taa.module; -import taa.student.Assessment; import taa.student.Student; import java.util.ArrayList; +import java.util.HashMap; public class Module { + private static final double MAX_ASSESSMENT_WEIGHTAGE = 100; + private final String code; private final String name; private final ArrayList students; - private final ArrayList assessments; + private final HashMap assessments; + private int lessonCount; public Module(String code, String name) { this.code = code; this.name = name; this.students = new ArrayList<>(); - this.assessments = new ArrayList<>(); + this.assessments = new HashMap<>(); + } + + public String getCode() { + return code; + } + + public String getName() { + return name; + } + + public int getLessonCount() { + return lessonCount; + } + + public void setLessonCount(int lessonCount) { + this.lessonCount = lessonCount; + } + + public ArrayList getStudents() { + return new ArrayList<>(students); + } + + public HashMap getAssessments() { + return new HashMap<>(assessments); + } + + public void addStudent(Student student) { + students.add(student); + } + + /** + * Add an assessment to the module. Does not add if assessment name already exists + * or total weightage exceed MAX_ASSESSMENT_WEIGHTAGE after adding. + * + * @param name Name of assessment. + * @param weightage Assessment weightage. + * @return true if success, else false. + */ + public boolean addAssessment(String name, double weightage) { + if (assessments.containsKey(name)) { + return false; + } + + double totalWeightage = 0; + for (String key : assessments.keySet()) { + totalWeightage += assessments.get(key); + } + if ((totalWeightage + weightage) > MAX_ASSESSMENT_WEIGHTAGE) { + return false; + } + + assessments.put(name, weightage); + return true; } @Override From eba6d6c7eb4d9b25d4a025876f4b27bb7010f2e9 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Sat, 9 Oct 2021 03:38:45 +0800 Subject: [PATCH 039/543] make changes to javadoc --- src/main/java/taa/student/Student.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index fd69e9802d..b263498b97 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -16,7 +16,7 @@ public Student(String name, String studentID) { } /** - * Marks the student as present for a particular lesson + * Marks the student as present for a particular lesson. * * @param lessonIndex The lesson index the student is present for */ @@ -25,7 +25,7 @@ public void markAttendance(int lessonIndex) { } /** - * Returns the attendance status of the student for a particular lesson + * Returns the attendance status of the student for a particular lesson. * * @param lessonIndex The lesson index * @return The attendance status of the student for the lesson @@ -35,7 +35,7 @@ public boolean isPresent(int lessonIndex) { } /** - * Sets the name of the student + * Sets the name of the student. * * @param name The name of the student */ @@ -44,7 +44,7 @@ public void setName(String name) { } /** - * Returns the name of the student + * Returns the name of the student. * * @return The name of the student */ @@ -53,7 +53,7 @@ public String getName() { } /** - * Sets the student ID of the student + * Sets the student ID of the student. * * @param studentID the student ID of the student */ @@ -62,7 +62,7 @@ public void setStudentID(String studentID) { } /** - * returns the student ID of the student + * returns the student ID of the student. * * @return the student ID of the student */ @@ -71,7 +71,7 @@ public String getStudentID() { } /** - * Overrides default toString method with the custom print message + * Overrides default toString method with the custom print message. * * @return the custom print message */ From 3abb48768da822073032a26b61dee9ffa8ea653d Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Sat, 9 Oct 2021 03:45:06 +0800 Subject: [PATCH 040/543] make changes to code formatting --- src/main/java/taa/Parser.java | 1 + src/main/java/taa/command/AddStudentCommand.java | 2 +- src/main/java/taa/student/Student.java | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index da53f063b2..62a1e952fa 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -30,6 +30,7 @@ public static Command parseUserInput(String userInput) throws CustomException { case Command.COMMAND_ADD_STUDENT: command = new AddStudentCommand(argument); + break; default: throw new CustomException(MESSAGE_UNKNOWN_COMMAND); diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index 5663485f91..7bd38754e9 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -6,7 +6,7 @@ import taa.module.ModuleList; import taa.student.Student; -public class AddStudentCommand extends Command{ +public class AddStudentCommand extends Command { private static final String MESSAGE_STUDENT_ADDED_FORMAT = "Student %s, %s has been added to %s"; private static final String[] ADD_STUDENT_ARGUMENT_KEYS = {"c","s","i"}; diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index b263498b97..eb90f29284 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -1,7 +1,7 @@ package taa.student; /** - * Represents students + * Represents students. */ public class Student { private static final int NUM_LESSONS = 13; From b47e9819e4995e50a0ace2341958ae1b74044bb2 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Sat, 9 Oct 2021 03:49:20 +0800 Subject: [PATCH 041/543] change the importing of packages within parser --- src/main/java/taa/Parser.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 62a1e952fa..81f84bbb9f 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,6 +1,10 @@ package taa; -import taa.command.*; +import taa.command.AddStudentCommand; +import taa.command.Command; +import taa.command.AddModuleCommand; +import taa.command.ExitCommand; +import taa.command.ListModulesCommand; import java.util.ArrayList; import java.util.Collections; From b77d475e644f31802642494f73c937921d59816f Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 11:53:42 +0800 Subject: [PATCH 042/543] Add function to search for module and comments --- src/main/java/taa/module/ModuleList.java | 29 ++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index 24c0ba6313..3da7623b09 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -19,10 +19,22 @@ public int getSize() { return modules.size(); } + /** + * Checks if an index is valid with respect to the modules list. + * + * @param index The index to check. + * @return true if valid, else false. + */ public boolean isValidIndex(int index) { return (index >= 0 && index < getSize()); } + /** + * Gets a module at the specified index. + * + * @param index The index of the module. + * @return A module object if index is valid, else null. + */ public Module getModuleAt(int index) { if (isValidIndex(index)) { return modules.get(index); @@ -31,6 +43,23 @@ public Module getModuleAt(int index) { return null; } + /** + * Gets the module from the list with the specified code. + * + * @param code The module code to search for. + * @return A Module object if found, else null. + */ + public Module getModule(String code) { + for (int i = 0; i < getSize(); i += 1) { + Module module = getModuleAt(i); + if (module.getCode().equals(code)) { + return module; + } + } + + return null; + } + @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(MESSAGE_MODULE_LIST_HEADER); From d9745a088ef72db444d79d6318990ff8e9788fa2 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Sat, 9 Oct 2021 16:03:27 +0800 Subject: [PATCH 043/543] implement basic commands for students --- .../taa/command/DeleteStudentCommand.java | 2 + .../java/taa/command/EditStudentCommand.java | 2 + .../java/taa/command/FindStudentCommand.java | 2 + .../java/taa/command/ListStudentCommand.java | 2 + .../java/taa/command/ListStudentsCommand.java | 48 +++++++++++++++++++ 5 files changed, 56 insertions(+) create mode 100644 src/main/java/taa/command/DeleteStudentCommand.java create mode 100644 src/main/java/taa/command/EditStudentCommand.java create mode 100644 src/main/java/taa/command/FindStudentCommand.java create mode 100644 src/main/java/taa/command/ListStudentCommand.java create mode 100644 src/main/java/taa/command/ListStudentsCommand.java diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java new file mode 100644 index 0000000000..4c23dea8f6 --- /dev/null +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -0,0 +1,2 @@ +package taa.command;public class DeleteStudentCommand { +} diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java new file mode 100644 index 0000000000..6717d131e7 --- /dev/null +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -0,0 +1,2 @@ +package taa.command;public class EditStudentCommand { +} diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java new file mode 100644 index 0000000000..fee620a380 --- /dev/null +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -0,0 +1,2 @@ +package taa.command;public class FindStudentCommand { +} diff --git a/src/main/java/taa/command/ListStudentCommand.java b/src/main/java/taa/command/ListStudentCommand.java new file mode 100644 index 0000000000..c293075f12 --- /dev/null +++ b/src/main/java/taa/command/ListStudentCommand.java @@ -0,0 +1,2 @@ +package taa.command;public class ListStudentCommand { +} diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java new file mode 100644 index 0000000000..378ba3029e --- /dev/null +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -0,0 +1,48 @@ +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.module.Module; +import taa.module.ModuleList; +import taa.student.Student; + +public class ListStudentsCommand extends Command { + + private static final String MESSAGE_STUDENT_ADDED_FORMAT = "Student %s, %s has been added to %s"; + private static final String[] ADD_STUDENT_ARGUMENT_KEYS = {"c","s","i"}; + + public AddStudentCommand(String argument) { + super(argument, ADD_STUDENT_ARGUMENT_KEYS); + } + + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + if (argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + + if (!checkArgumentMap()) { + // TODO Invalid/missing arguments message + throw new CustomException(""); + } + + String moduleCode = argumentMap.get("c"); + if (moduleCode.contains(" ")) { + // TODO Invalid module code message + throw new CustomException(""); + } + + String studentName = argumentMap.get("s"); + String studentID = argumentMap.get("i"); + Student student = new Student(studentName, studentID); + Module module = modules.getModule(moduleCode); + if (module == null) { + // TODO module not found message + throw new CustomException("Module not found"); + } + module.addStudent(student); + + ui.printMessage(String.format(MESSAGE_STUDENT_ADDED_FORMAT, studentName, studentID, moduleCode)); + } +} \ No newline at end of file From 178ec5eef9c0783c6383c43f4406547e9909f98b Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Sat, 9 Oct 2021 16:10:09 +0800 Subject: [PATCH 044/543] update code formatting for student functions --- src/main/java/taa/Parser.java | 21 ++++++ .../java/taa/command/AddStudentCommand.java | 14 +++- src/main/java/taa/command/Command.java | 1 + .../taa/command/DeleteStudentCommand.java | 57 ++++++++++++++- .../java/taa/command/EditStudentCommand.java | 61 +++++++++++++++- .../java/taa/command/FindStudentCommand.java | 72 ++++++++++++++++++- .../java/taa/command/ListStudentCommand.java | 2 - .../java/taa/command/ListStudentsCommand.java | 29 +++++--- src/main/java/taa/module/Module.java | 2 +- 9 files changed, 240 insertions(+), 19 deletions(-) delete mode 100644 src/main/java/taa/command/ListStudentCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 81f84bbb9f..33d24a7456 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -5,6 +5,11 @@ import taa.command.AddModuleCommand; import taa.command.ExitCommand; import taa.command.ListModulesCommand; +import taa.command.FindStudentCommand; +import taa.command.ListStudentsCommand; +import taa.command.EditStudentCommand; +import taa.command.DeleteStudentCommand; + import java.util.ArrayList; import java.util.Collections; @@ -36,6 +41,22 @@ public static Command parseUserInput(String userInput) throws CustomException { command = new AddStudentCommand(argument); break; + case Command.COMMAND_EDIT_STUDENT: + command = new EditStudentCommand(argument); + break; + + case Command.COMMAND_DELETE_STUDENT: + command = new DeleteStudentCommand(argument); + break; + + case Command.COMMAND_LIST_STUDENTS: + command = new ListStudentsCommand(argument); + break; + + case Command.COMMAND_FIND_STUDENT: + command = new FindStudentCommand(argument); + break; + default: throw new CustomException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index 7bd38754e9..4da9346642 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -15,6 +15,13 @@ public AddStudentCommand(String argument) { super(argument, ADD_STUDENT_ARGUMENT_KEYS); } + /** + * Adds a students to a particular module. + * + * @param modules The list of modules + * @param ui The ui instance to handle interactions with the user + * @throws CustomException If the user inputs an invalid command + */ @Override public void execute(ModuleList modules, Ui ui) throws CustomException { if (argument.isEmpty()) { @@ -36,9 +43,12 @@ public void execute(ModuleList modules, Ui ui) throws CustomException { String studentName = argumentMap.get("s"); String studentID = argumentMap.get("i"); Student student = new Student(studentName, studentID); - for (int i = 0; i < modules.getSize(); i += 1) { - //TODO find module in modules and add student to module + Module module = modules.getModule(moduleCode); + if (module == null) { + // TODO module not found message + throw new CustomException("Module not found"); } + module.addStudent(student); ui.printMessage(String.format(MESSAGE_STUDENT_ADDED_FORMAT, studentName, studentID, moduleCode)); } diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index cee4b924b9..2cc9c2661b 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -16,6 +16,7 @@ public abstract class Command { public static final String COMMAND_LIST_MARKS = "list_marks"; public static final String COMMAND_AVERAGE_MARKS = "average_marks"; public static final String COMMAND_ADD_MODULE = "add_module"; + public static final String COMMAND_FIND_STUDENT = "find_student"; public static final String COMMAND_ADD_STUDENT = "add_student"; public static final String COMMAND_EDIT_STUDENT = "edit_student"; public static final String COMMAND_DELETE_STUDENT = "delete_student"; diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 4c23dea8f6..ebdecffe24 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -1,2 +1,57 @@ -package taa.command;public class DeleteStudentCommand { +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.module.Module; +import taa.module.ModuleList; +import taa.student.Student; + +public class DeleteStudentCommand extends Command{ + + private static final String[] DELETE_STUDENT_ARGUMENT_KEYS = {"c", "n"}; + private static final String MESSAGE_STUDENT_DELETED_FORMAT = "%s, %s has been removed from %s"; + + public DeleteStudentCommand(String argument) { + super(argument, DELETE_STUDENT_ARGUMENT_KEYS); + } + + /** + * Deletes a student from a module. + * + * @param modules The list of modules + * @param ui The ui instance to handle interactions with the user + * @throws CustomException If the user inputs an invalid command + */ + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + if (argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + + if (!checkArgumentMap()) { + // TODO Invalid/missing arguments message + throw new CustomException(""); + } + + String moduleCode = argumentMap.get("c"); + if (moduleCode.contains(" ")) { + // TODO Invalid module code message + throw new CustomException(""); + } + + Module module = modules.getModule(moduleCode); + if (module == null) { + // TODO module not found message + throw new CustomException("Module not found"); + } + + // TODO exceptions for number format and array out of bounds + int studentIndex = Integer.parseInt(argumentMap.get("n")) - 1; + Student student = modules.getModule(moduleCode).getStudents().get(studentIndex); + String studentName = student.getName(); + String studentID = student.getStudentID(); + modules.getModule(moduleCode).getStudents().remove(studentIndex); + ui.printMessage(String.format(MESSAGE_STUDENT_DELETED_FORMAT, studentName, studentID, moduleCode)); + } } diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 6717d131e7..b5a9a5d43d 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -1,2 +1,59 @@ -package taa.command;public class EditStudentCommand { -} +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.module.Module; +import taa.module.ModuleList; +import taa.student.Student; + +public class EditStudentCommand extends Command{ + + private static final String[] EDIT_STUDENT_ARGUMENT_KEYS = {"c", "n", "s", "i"}; + private static final String MESSAGE_STUDENT_EDITED_FORMAT = "Student details updated:\n %d. %s, %s"; + + public EditStudentCommand(String argument) { + super(argument, EDIT_STUDENT_ARGUMENT_KEYS); + } + + /** + * Edits the name and student ID of a given student. + * + * @param modules The list of modules + * @param ui The ui instance to handle interactions with the user + * @throws CustomException If the user inputs an invalid command + */ + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + if (argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + + if (!checkArgumentMap()) { + // TODO Invalid/missing arguments message + throw new CustomException(""); + } + + String moduleCode = argumentMap.get("c"); + if (moduleCode.contains(" ")) { + // TODO Invalid module code message + throw new CustomException(""); + } + + Module module = modules.getModule(moduleCode); + if (module == null) { + // TODO module not found message + throw new CustomException("Module not found"); + } + + // TODO exceptions for number format and array out of bounds + int studentIndex = Integer.parseInt(argumentMap.get("n")) - 1; + String studentName = argumentMap.get("s"); + String studentID = argumentMap.get("i"); + Student student = modules.getModule(moduleCode).getStudents().get(studentIndex); + student.setName(studentName); + student.setStudentID(studentID); + + ui.printMessage(String.format(MESSAGE_STUDENT_EDITED_FORMAT, (studentIndex + 1), studentName, studentID)); + } +} \ No newline at end of file diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index fee620a380..4c7913c7ac 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -1,2 +1,70 @@ -package taa.command;public class FindStudentCommand { -} +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.module.Module; +import taa.module.ModuleList; +import taa.student.Student; + +import java.util.Locale; + +public class FindStudentCommand extends Command { + + private static final String[] FIND_STUDENT_ARGUMENT_KEYS = {"c","k"}; + private static final String MESSAGE_FOUND_STUDENT_FORMAT = "Here are the students in %s with '%s'"; + public static final String MESSAGE_NO_STUDENTS_FOUND = "No Students matching your keyword found"; + + public FindStudentCommand(String argument) { + super(argument, FIND_STUDENT_ARGUMENT_KEYS); + } + + /** + * Finds the students taking a particular module containing a particular keyword. + * + * @param modules The list of modules + * @param ui The ui instance to handle interactions with the user + * @throws CustomException If the user inputs an invalid command + */ + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + if (argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + + if (!checkArgumentMap()) { + // TODO Invalid/missing arguments message + throw new CustomException(""); + } + + String moduleCode = argumentMap.get("c"); + if (moduleCode.contains(" ")) { + // TODO Invalid module code message + throw new CustomException(""); + } + + Module module = modules.getModule(moduleCode); + if (module == null) { + // TODO module not found message + throw new CustomException("Module not found"); + } + + boolean isFound = false; + Student student; + String keyword = argumentMap.get("k").toLowerCase(); + for (int i = 0; i < module.getStudents().size(); i += 1) { + student = module.getStudents().get(i); + if (student.getName().toLowerCase().contains(keyword) + || student.getStudentID().toLowerCase().contains(keyword)) { + if (!isFound) { + ui.printMessage(String.format(MESSAGE_FOUND_STUDENT_FORMAT, moduleCode, keyword)); + isFound = true; + } + System.out.println(i + 1 + ". " + student); + } + } + if (!isFound) { + ui.printMessage(MESSAGE_NO_STUDENTS_FOUND); + } + } +} \ No newline at end of file diff --git a/src/main/java/taa/command/ListStudentCommand.java b/src/main/java/taa/command/ListStudentCommand.java deleted file mode 100644 index c293075f12..0000000000 --- a/src/main/java/taa/command/ListStudentCommand.java +++ /dev/null @@ -1,2 +0,0 @@ -package taa.command;public class ListStudentCommand { -} diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index 378ba3029e..b45472b4ee 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -8,13 +8,21 @@ public class ListStudentsCommand extends Command { - private static final String MESSAGE_STUDENT_ADDED_FORMAT = "Student %s, %s has been added to %s"; - private static final String[] ADD_STUDENT_ARGUMENT_KEYS = {"c","s","i"}; + private static final String[] LIST_STUDENT_ARGUMENT_KEYS = {"c"}; + private static final String MESSAGE_NO_STUDENTS = "No students added yet!"; + private static final String MESSAGE_LIST_STUDENT_FORMAT = "Here are the students in %s"; - public AddStudentCommand(String argument) { - super(argument, ADD_STUDENT_ARGUMENT_KEYS); + public ListStudentsCommand(String argument) { + super(argument, LIST_STUDENT_ARGUMENT_KEYS); } + /** + * Lists the students taking a particular module. + * + * @param modules The list of modules + * @param ui The ui instance to handle interactions with the user + * @throws CustomException If the user inputs an invalid command + */ @Override public void execute(ModuleList modules, Ui ui) throws CustomException { if (argument.isEmpty()) { @@ -33,16 +41,19 @@ public void execute(ModuleList modules, Ui ui) throws CustomException { throw new CustomException(""); } - String studentName = argumentMap.get("s"); - String studentID = argumentMap.get("i"); - Student student = new Student(studentName, studentID); Module module = modules.getModule(moduleCode); if (module == null) { // TODO module not found message throw new CustomException("Module not found"); } - module.addStudent(student); - ui.printMessage(String.format(MESSAGE_STUDENT_ADDED_FORMAT, studentName, studentID, moduleCode)); + if (module.getStudents().size() == 0) { + ui.printMessage(MESSAGE_NO_STUDENTS); + } else { + ui.printMessage(String.format(MESSAGE_LIST_STUDENT_FORMAT, moduleCode)); + for (int i = 0; i < module.getStudents().size(); i += 1) { + System.out.println(i + 1 + ". " + module.getStudents().get(i)); + } + } } } \ No newline at end of file diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index 669c8fbf22..7a80387823 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -38,7 +38,7 @@ public void setLessonCount(int lessonCount) { } public ArrayList getStudents() { - return new ArrayList<>(students); + return students; } public HashMap getAssessments() { From 20aa00b86fcf7fe28301f2123b05667e3a105466 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Sat, 9 Oct 2021 16:11:44 +0800 Subject: [PATCH 045/543] update code formatting --- src/main/java/taa/command/DeleteStudentCommand.java | 2 +- src/main/java/taa/command/EditStudentCommand.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index ebdecffe24..b1bd4e40d9 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -6,7 +6,7 @@ import taa.module.ModuleList; import taa.student.Student; -public class DeleteStudentCommand extends Command{ +public class DeleteStudentCommand extends Command { private static final String[] DELETE_STUDENT_ARGUMENT_KEYS = {"c", "n"}; private static final String MESSAGE_STUDENT_DELETED_FORMAT = "%s, %s has been removed from %s"; diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index b5a9a5d43d..35fdd620eb 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -6,7 +6,7 @@ import taa.module.ModuleList; import taa.student.Student; -public class EditStudentCommand extends Command{ +public class EditStudentCommand extends Command { private static final String[] EDIT_STUDENT_ARGUMENT_KEYS = {"c", "n", "s", "i"}; private static final String MESSAGE_STUDENT_EDITED_FORMAT = "Student details updated:\n %d. %s, %s"; From 80b5400929e93b01e3148fadf5c4a12cf9f072d3 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Sat, 9 Oct 2021 16:17:23 +0800 Subject: [PATCH 046/543] delete mark class and mark tests --- src/main/java/taa/student/Mark.java | 42 ----------------------------- src/test/java/taa/MarkTest.java | 14 ---------- 2 files changed, 56 deletions(-) delete mode 100644 src/main/java/taa/student/Mark.java delete mode 100644 src/test/java/taa/MarkTest.java diff --git a/src/main/java/taa/student/Mark.java b/src/main/java/taa/student/Mark.java deleted file mode 100644 index 6322eab4a2..0000000000 --- a/src/main/java/taa/student/Mark.java +++ /dev/null @@ -1,42 +0,0 @@ -package taa.student; - -public class Mark { - private String assessmentName; - private int marks; - private double weightage; - - public Mark(String assessmentName, int marks, double weightage) { - this.assessmentName = assessmentName; - this.marks = marks; - this.weightage = weightage; - } - - public void setAssessmentName(String assessmentName) { - this.assessmentName = assessmentName; - } - - public void setMarks(int marks) { - this.marks = marks; - } - - public void setWeightage(double weightage) { - this.weightage = weightage; - } - - public String getAssessmentName() { - return assessmentName; - } - - public int getMarks() { - return marks; - } - - public double getWeightage() { - return weightage; - } - - @Override - public String toString() { - return assessmentName + ", " + marks + ", " + weightage; - } -} diff --git a/src/test/java/taa/MarkTest.java b/src/test/java/taa/MarkTest.java deleted file mode 100644 index d4e903f90c..0000000000 --- a/src/test/java/taa/MarkTest.java +++ /dev/null @@ -1,14 +0,0 @@ -package taa; - -import org.junit.jupiter.api.Test; -import taa.student.Mark; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -public class MarkTest { - @Test - public void testMarksStringConversion() { - assertEquals("Assignment 5, 56, 0.5", - new Mark("Assignment 5", 56, 0.5).toString()); - } -} From 05703571ed35df7d1da4e9f5b641b4ba0427a0e5 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 20:29:45 +0800 Subject: [PATCH 047/543] Refactor CustomException to TaaException --- src/main/java/taa/Parser.java | 5 +++-- src/main/java/taa/Taa.java | 3 ++- src/main/java/taa/Ui.java | 4 ++-- .../{CustomException.java => exception/TaaException.java} | 0 4 files changed, 7 insertions(+), 5 deletions(-) rename src/main/java/taa/{CustomException.java => exception/TaaException.java} (100%) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 33d24a7456..cbe23b73e1 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -9,6 +9,7 @@ import taa.command.ListStudentsCommand; import taa.command.EditStudentCommand; import taa.command.DeleteStudentCommand; +import taa.exception.TaaException; import java.util.ArrayList; @@ -18,7 +19,7 @@ public class Parser { private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown Command"; - public static Command parseUserInput(String userInput) throws CustomException { + public static Command parseUserInput(String userInput) throws TaaException { String[] userInputSplit = splitFirstSpace(userInput); String commandString = userInputSplit[0]; String argument = userInputSplit[1]; @@ -58,7 +59,7 @@ public static Command parseUserInput(String userInput) throws CustomException { break; default: - throw new CustomException(MESSAGE_UNKNOWN_COMMAND); + throw new TaaException(MESSAGE_UNKNOWN_COMMAND); } return command; diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index 2f0e512b6b..9cb9e50647 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -1,6 +1,7 @@ package taa; import taa.command.Command; +import taa.exception.TaaException; import taa.module.ModuleList; public class Taa { @@ -23,7 +24,7 @@ public void run() { Command command = Parser.parseUserInput(userInput); command.execute(modules, ui); isExit = command.isExit(); - } catch (CustomException e) { + } catch (TaaException e) { ui.printException(e.getMessage()); } } while (!isExit); diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index fdee857f33..52c3313ff9 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -9,7 +9,7 @@ public class Ui { private static final String MESSAGE_WELCOME = "Welcome\nWhat can I do for you?"; private static final String MESSAGE_EXIT = "Bye. Hope to see you again soon!"; - private static final String MESSAGE_EXCEPTION_FORMAT = "An exception has occurred:\n%s"; + private static final String MESSAGE_FORMAT_EXCEPTION = "An exception has occurred:\n%s"; private final Scanner scanner; @@ -63,6 +63,6 @@ public void printExitMessage() { * @param message The message to print. */ public void printException(String message) { - printMessage(String.format(MESSAGE_EXCEPTION_FORMAT, message)); + printMessage(String.format(MESSAGE_FORMAT_EXCEPTION, message)); } } diff --git a/src/main/java/taa/CustomException.java b/src/main/java/taa/exception/TaaException.java similarity index 100% rename from src/main/java/taa/CustomException.java rename to src/main/java/taa/exception/TaaException.java From 517556d9c0466df5d73bfc96a50e8b2dd3222628 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 20:30:34 +0800 Subject: [PATCH 048/543] Add exception messages to module related commands --- .../java/taa/command/AddModuleCommand.java | 40 +++++++++++++------ .../java/taa/command/ListModulesCommand.java | 15 +++++-- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index d9f9e6074a..f400dd6e31 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -1,41 +1,55 @@ package taa.command; -import taa.CustomException; +import taa.exception.TaaException; import taa.Ui; import taa.module.ModuleList; import taa.module.Module; public class AddModuleCommand extends Command { - private static final String MESSAGE_MODULE_ADDED_FORMAT = "Module added:\n %s\nThere are %d modules in the list."; + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_MODULE_NAME = "n"; + private static final String[] ADD_MODULE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_MODULE_NAME}; - private static final String[] ADD_MODULE_ARGUMENT_KEYS = {"c","n"}; + private static final String MESSAGE_INVALID_MODULE_CODE = "Invalid module code."; + + private static final String MESSAGE_FORMAT_ADD_MODULE_USAGE = "Usage: %s " + + "%s/ %s/"; + private static final String MESSAGE_FORMAT_MODULE_ADDED = "Module added:\n %s\nThere are %d modules in the list."; public AddModuleCommand(String argument) { super(argument, ADD_MODULE_ARGUMENT_KEYS); } @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { + public void execute(ModuleList modules, Ui ui) throws TaaException { if (argument.isEmpty()) { - // TODO Usage format message - throw new CustomException(""); + throw new TaaException(getUsageMessage()); } if (!checkArgumentMap()) { - // TODO Invalid/missing arguments message - throw new CustomException(""); + throw new TaaException(getMissingArgumentMessage()); } - String moduleCode = argumentMap.get("c"); + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + String name = argumentMap.get(KEY_MODULE_NAME); + if (moduleCode.contains(" ")) { - // TODO Invalid module code message - throw new CustomException(""); + throw new TaaException(MESSAGE_INVALID_MODULE_CODE); } - String name = argumentMap.get("n"); Module module = new Module(moduleCode, name); modules.addModule(module); - ui.printMessage(String.format(MESSAGE_MODULE_ADDED_FORMAT, module, modules.getSize())); + ui.printMessage(String.format(MESSAGE_FORMAT_MODULE_ADDED, module, modules.getSize())); + } + + @Override + protected String getUsageMessage() { + return String.format( + MESSAGE_FORMAT_ADD_MODULE_USAGE, + COMMAND_ADD_MODULE, + KEY_MODULE_CODE, + KEY_MODULE_NAME + ); } } diff --git a/src/main/java/taa/command/ListModulesCommand.java b/src/main/java/taa/command/ListModulesCommand.java index 4f07d0319f..05dd90323f 100644 --- a/src/main/java/taa/command/ListModulesCommand.java +++ b/src/main/java/taa/command/ListModulesCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.CustomException; +import taa.exception.TaaException; import taa.Ui; import taa.module.ModuleList; @@ -12,10 +12,9 @@ public ListModulesCommand(String argument) { } @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { + public void execute(ModuleList modules, Ui ui) throws TaaException { if (!argument.isEmpty()) { - // TODO Usage format message - throw new CustomException(""); + throw new TaaException(getUsageMessage()); } if (modules.getSize() == 0) { @@ -24,4 +23,12 @@ public void execute(ModuleList modules, Ui ui) throws CustomException { ui.printMessage(modules.toString()); } } + + @Override + protected String getUsageMessage() { + return String.format( + MESSAGE_FORMAT_GENERIC_USAGE, + COMMAND_LIST_MODULES + ); + } } From 205d23c59407fd2be3561d03af4f4b6daffccfa4 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 20:32:09 +0800 Subject: [PATCH 049/543] Add functions to access private variables in Module class --- src/main/java/taa/module/Module.java | 106 +++++++++++++++++++---- src/main/java/taa/module/ModuleList.java | 2 +- 2 files changed, 91 insertions(+), 17 deletions(-) diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index 7a80387823..1cac5404f1 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -1,18 +1,20 @@ package taa.module; +import taa.exception.TaaException; import taa.student.Student; import java.util.ArrayList; import java.util.HashMap; +import java.util.regex.Pattern; public class Module { - private static final double MAX_ASSESSMENT_WEIGHTAGE = 100; + private static final double MAX_ASSESSMENT_WEIGHTAGE = 1; - private final String code; - private final String name; + private String code; + private String name; + private int lessonCount; private final ArrayList students; private final HashMap assessments; - private int lessonCount; public Module(String code, String name) { this.code = code; @@ -38,28 +40,77 @@ public void setLessonCount(int lessonCount) { } public ArrayList getStudents() { - return students; - } - - public HashMap getAssessments() { - return new HashMap<>(assessments); + return new ArrayList<>(students); } public void addStudent(Student student) { students.add(student); } + public int getStudentCount() { + return students.size(); + } + + public Student getStudentAt(int index) { + if (isValidStudentIndex(index)) { + return students.get(index); + } + + return null; + } + + /** + * Deletes a student from the student list. + * + * @param index The index of the student. + * @return A Student object if successfully deleted, else null. + */ + public Student deleteStudent(int index) { + if (isValidStudentIndex(index)) { + return students.remove(index); + } + + return null; + } + + public ArrayList findStudents(String keyword) { + String keywordLower = keyword.toLowerCase(); + + ArrayList studentsFound = new ArrayList<>(); + for (int i = 0; i < getStudentCount(); i += 1) { + Student student = getStudentAt(i); + String id = student.getId(); + String name = student.getName(); + + if (id.toLowerCase().contains(keywordLower) || name.toLowerCase().contains(keywordLower)) { + studentsFound.add(student); + } + } + + return studentsFound; + } + + public HashMap getAssessments() { + return new HashMap<>(assessments); + } + /** * Add an assessment to the module. Does not add if assessment name already exists * or total weightage exceed MAX_ASSESSMENT_WEIGHTAGE after adding. * - * @param name Name of assessment. - * @param weightage Assessment weightage. - * @return true if success, else false. + * @param name The name of the assessment. + * @param weightage The assessment weightage. + * @throws TaaException if weightage is invalid or total weightage exceeds max. */ - public boolean addAssessment(String name, double weightage) { + public void addAssessment(String name, double weightage) throws TaaException { if (assessments.containsKey(name)) { - return false; + // TODO Assessment name already exist message + throw new TaaException(""); + } + + if (weightage < 0 || weightage > MAX_ASSESSMENT_WEIGHTAGE) { + // TODO Invalid weightage message + throw new TaaException(""); } double totalWeightage = 0; @@ -67,11 +118,30 @@ public boolean addAssessment(String name, double weightage) { totalWeightage += assessments.get(key); } if ((totalWeightage + weightage) > MAX_ASSESSMENT_WEIGHTAGE) { - return false; + // TODO Invalid weightage message + throw new TaaException(""); } assessments.put(name, weightage); - return true; + } + + /** + * Deletes an assessment from the module. + * + * @param name The name of the assessment. + * @throws TaaException if assessment does not exist. + */ + public void deleteAssessment(String name) throws TaaException { + if (!assessments.containsKey(name)) { + // TODO Invalid assessment name message + throw new TaaException(""); + } + + for (int i = 0; i < getStudentCount(); i += 1) { + // TODO Delete Assessment in Student. + } + + assessments.remove(name); } @Override @@ -82,4 +152,8 @@ public String toString() { return String.format("%s - %s", code, name); } + + private boolean isValidStudentIndex(int index) { + return (index >= 0 && index < getStudentCount()); + } } diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index 3da7623b09..48f187c714 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -66,7 +66,7 @@ public String toString() { for (int i = 0; i < getSize(); i += 1) { stringBuilder.append("\n"); stringBuilder.append(i + 1); - stringBuilder.append(": "); + stringBuilder.append(". "); stringBuilder.append(getModuleAt(i)); } From 92da3c29d81aa5723161f6a49234a542678ca145 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 20:33:40 +0800 Subject: [PATCH 050/543] Refactor and rearrange variables in Student class --- src/main/java/taa/student/Student.java | 18 +++++++++--------- src/test/java/taa/StudentTest.java | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index eb90f29284..e033693c2a 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -6,13 +6,13 @@ public class Student { private static final int NUM_LESSONS = 13; + private String id; private String name; - private String studentID; private final boolean[] attendance = new boolean[NUM_LESSONS]; - public Student(String name, String studentID) { + public Student(String id, String name) { + this.id = id; this.name = name; - this.studentID = studentID; } /** @@ -55,10 +55,10 @@ public String getName() { /** * Sets the student ID of the student. * - * @param studentID the student ID of the student + * @param id the student ID of the student */ - public void setStudentID(String studentID) { - this.studentID = studentID; + public void setId(String id) { + this.id = id; } /** @@ -66,8 +66,8 @@ public void setStudentID(String studentID) { * * @return the student ID of the student */ - public String getStudentID() { - return this.studentID; + public String getId() { + return this.id; } /** @@ -77,6 +77,6 @@ public String getStudentID() { */ @Override public String toString() { - return name + ", " + studentID; + return String.format("%s - %s", id, name); } } diff --git a/src/test/java/taa/StudentTest.java b/src/test/java/taa/StudentTest.java index 2c6ae1d461..60d0fbb8a4 100644 --- a/src/test/java/taa/StudentTest.java +++ b/src/test/java/taa/StudentTest.java @@ -8,7 +8,7 @@ public class StudentTest { @Test public void testStringConversion() { - assertEquals("Jon Lim, A0217746X", new Student("Jon Lim", "A0217746X").toString()); + assertEquals("A1234567B - Jon Lim", new Student("A1234567B", "Jon Lim").toString()); } } From 13baf34190470a4e6138240b63b149fb5b3b0695 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 20:34:47 +0800 Subject: [PATCH 051/543] Add getUsageMessage as an abstract function and getMissingArgumentMessage --- src/main/java/taa/command/Command.java | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 2cc9c2661b..7baac6b48e 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -1,6 +1,6 @@ package taa.command; -import taa.CustomException; +import taa.exception.TaaException; import taa.Parser; import taa.Ui; import taa.module.ModuleList; @@ -24,6 +24,13 @@ public abstract class Command { public static final String COMMAND_ADD_ASSESSMENT = "add_assessment"; public static final String COMMAND_SET_MARKS = "set_marks"; + protected static final String MESSAGE_UNKNOWN_USAGE = "Unknown usage."; + protected static final String MESSAGE_MODULE_NOT_FOUND = "Module not found."; + protected static final String MESSAGE_INVALID_STUDENT_INDEX = "Invalid student index."; + + protected static final String MESSAGE_FORMAT_GENERIC_USAGE = "Usage: %s"; + protected static final String MESSAGE_FORMAT_MISSING_ARGUMENT = "Missing Argument(s).\n%s"; + protected String argument; protected boolean isExit; protected String[] argumentKeys; @@ -44,7 +51,9 @@ public boolean isExit() { return isExit; } - public abstract void execute(ModuleList modules, Ui ui) throws CustomException; + public abstract void execute(ModuleList modules, Ui ui) throws TaaException; + + protected abstract String getUsageMessage(); /** * Checks if argumentMap contains all the argument keys. @@ -60,4 +69,13 @@ protected boolean checkArgumentMap() { return true; } + + protected String getMissingArgumentMessage() { + String usageMessage = getUsageMessage(); + if (usageMessage == null) { + usageMessage = MESSAGE_UNKNOWN_USAGE; + } + + return String.format(MESSAGE_FORMAT_MISSING_ARGUMENT, usageMessage); + } } From 0daa3c5229742ae29ed7e071eb6bc14baffef600 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 20:35:21 +0800 Subject: [PATCH 052/543] Add TaaException class --- src/main/java/taa/exception/TaaException.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/taa/exception/TaaException.java b/src/main/java/taa/exception/TaaException.java index f7a82c32a7..4d7f49de09 100644 --- a/src/main/java/taa/exception/TaaException.java +++ b/src/main/java/taa/exception/TaaException.java @@ -1,8 +1,7 @@ -package taa; +package taa.exception; -// TODO: Rename classname -public class CustomException extends Exception { - public CustomException(String message) { +public class TaaException extends Exception { + public TaaException(String message) { super(message); } } From 17848cf52f9762bcc7873512255d62b3d96664a6 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 20:36:25 +0800 Subject: [PATCH 053/543] Add exception messages and use Module functions in student related commands --- .../java/taa/command/AddStudentCommand.java | 49 +++++++----- .../taa/command/DeleteStudentCommand.java | 57 ++++++++------ .../java/taa/command/EditStudentCommand.java | 75 +++++++++++++------ .../java/taa/command/FindStudentCommand.java | 72 ++++++++++-------- .../java/taa/command/ListStudentsCommand.java | 57 ++++++++------ 5 files changed, 191 insertions(+), 119 deletions(-) diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index 4da9346642..2efbb48002 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -1,15 +1,20 @@ package taa.command; -import taa.CustomException; +import taa.exception.TaaException; import taa.Ui; import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; public class AddStudentCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_STUDENT_ID = "i"; + private static final String KEY_STUDENT_NAME = "n"; + private static final String[] ADD_STUDENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_ID, KEY_STUDENT_NAME}; - private static final String MESSAGE_STUDENT_ADDED_FORMAT = "Student %s, %s has been added to %s"; - private static final String[] ADD_STUDENT_ARGUMENT_KEYS = {"c","s","i"}; + private static final String MESSAGE_FORMAT_ADD_STUDENT_USAGE = "Usage: %s " + + "%s/ %s/ %s/"; + private static final String MESSAGE_STUDENT_ADDED_FORMAT = "Student has been added to %s:\n %s"; public AddStudentCommand(String argument) { super(argument, ADD_STUDENT_ARGUMENT_KEYS); @@ -20,36 +25,40 @@ public AddStudentCommand(String argument) { * * @param modules The list of modules * @param ui The ui instance to handle interactions with the user - * @throws CustomException If the user inputs an invalid command + * @throws TaaException If the user inputs an invalid command */ @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { + public void execute(ModuleList modules, Ui ui) throws TaaException { if (argument.isEmpty()) { - // TODO Usage format message - throw new CustomException(""); + throw new TaaException(getUsageMessage()); } if (!checkArgumentMap()) { - // TODO Invalid/missing arguments message - throw new CustomException(""); + throw new TaaException(getMissingArgumentMessage()); } - String moduleCode = argumentMap.get("c"); - if (moduleCode.contains(" ")) { - // TODO Invalid module code message - throw new CustomException(""); - } + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + String studentID = argumentMap.get(KEY_STUDENT_ID); + String studentName = argumentMap.get(KEY_STUDENT_NAME); - String studentName = argumentMap.get("s"); - String studentID = argumentMap.get("i"); - Student student = new Student(studentName, studentID); Module module = modules.getModule(moduleCode); if (module == null) { - // TODO module not found message - throw new CustomException("Module not found"); + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } + Student student = new Student(studentID, studentName); module.addStudent(student); - ui.printMessage(String.format(MESSAGE_STUDENT_ADDED_FORMAT, studentName, studentID, moduleCode)); + ui.printMessage(String.format(MESSAGE_STUDENT_ADDED_FORMAT, moduleCode, student)); + } + + @Override + protected String getUsageMessage() { + return String.format( + MESSAGE_FORMAT_ADD_STUDENT_USAGE, + COMMAND_ADD_STUDENT, + KEY_MODULE_CODE, + KEY_STUDENT_ID, + KEY_STUDENT_NAME + ); } } diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index b1bd4e40d9..8bd7884012 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -1,15 +1,20 @@ package taa.command; -import taa.CustomException; +import taa.exception.TaaException; import taa.Ui; import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; +import taa.util.Util; public class DeleteStudentCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_STUDENT_INDEX = "s"; + private static final String[] DELETE_STUDENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX}; - private static final String[] DELETE_STUDENT_ARGUMENT_KEYS = {"c", "n"}; - private static final String MESSAGE_STUDENT_DELETED_FORMAT = "%s, %s has been removed from %s"; + private static final String MESSAGE_FORMAT_DELETE_STUDENT_USAGE = "Usage: %s " + + "%s/ %s/"; + private static final String MESSAGE_FORMAT_STUDENT_DELETED = "Student removed from %s:\n %s"; public DeleteStudentCommand(String argument) { super(argument, DELETE_STUDENT_ARGUMENT_KEYS); @@ -20,38 +25,46 @@ public DeleteStudentCommand(String argument) { * * @param modules The list of modules * @param ui The ui instance to handle interactions with the user - * @throws CustomException If the user inputs an invalid command + * @throws TaaException If the user inputs an invalid command */ @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { + public void execute(ModuleList modules, Ui ui) throws TaaException { if (argument.isEmpty()) { - // TODO Usage format message - throw new CustomException(""); + throw new TaaException(getUsageMessage()); } if (!checkArgumentMap()) { - // TODO Invalid/missing arguments message - throw new CustomException(""); + throw new TaaException(getMissingArgumentMessage()); } String moduleCode = argumentMap.get("c"); - if (moduleCode.contains(" ")) { - // TODO Invalid module code message - throw new CustomException(""); - } + String studentIndexInput = argumentMap.get("s"); Module module = modules.getModule(moduleCode); if (module == null) { - // TODO module not found message - throw new CustomException("Module not found"); + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + + if (!Util.isInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + int studentIndex = Integer.parseInt(studentIndexInput) - 1; + + Student student = module.deleteStudent(studentIndex); + if (student == null) { + ui.printMessage(MESSAGE_INVALID_STUDENT_INDEX); } - // TODO exceptions for number format and array out of bounds - int studentIndex = Integer.parseInt(argumentMap.get("n")) - 1; - Student student = modules.getModule(moduleCode).getStudents().get(studentIndex); - String studentName = student.getName(); - String studentID = student.getStudentID(); - modules.getModule(moduleCode).getStudents().remove(studentIndex); - ui.printMessage(String.format(MESSAGE_STUDENT_DELETED_FORMAT, studentName, studentID, moduleCode)); + ui.printMessage(String.format(MESSAGE_FORMAT_STUDENT_DELETED, moduleCode, student)); + } + + @Override + protected String getUsageMessage() { + return String.format( + MESSAGE_FORMAT_DELETE_STUDENT_USAGE, + COMMAND_DELETE_STUDENT, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX + ); } } diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 35fdd620eb..804f469020 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -1,15 +1,28 @@ package taa.command; -import taa.CustomException; +import taa.exception.TaaException; import taa.Ui; import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; +import taa.util.Util; public class EditStudentCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_STUDENT_INDEX = "s"; + private static final String KEY_NEW_ID = "i"; + private static final String KEY_NEW_NAME = "n"; + private static final String[] EDIT_STUDENT_ARGUMENT_KEYS = { + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_NEW_ID, + KEY_NEW_NAME + }; - private static final String[] EDIT_STUDENT_ARGUMENT_KEYS = {"c", "n", "s", "i"}; - private static final String MESSAGE_STUDENT_EDITED_FORMAT = "Student details updated:\n %d. %s, %s"; + + private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "Usage: %s " + + "%s/ %s/ %s/ %s/"; + private static final String MESSAGE_FORMAT_STUDENT_EDITED = "Student updated:\n %s"; public EditStudentCommand(String argument) { super(argument, EDIT_STUDENT_ARGUMENT_KEYS); @@ -20,40 +33,54 @@ public EditStudentCommand(String argument) { * * @param modules The list of modules * @param ui The ui instance to handle interactions with the user - * @throws CustomException If the user inputs an invalid command + * @throws TaaException If the user inputs an invalid command */ @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { + public void execute(ModuleList modules, Ui ui) throws TaaException { if (argument.isEmpty()) { - // TODO Usage format message - throw new CustomException(""); + throw new TaaException(getUsageMessage()); } if (!checkArgumentMap()) { - // TODO Invalid/missing arguments message - throw new CustomException(""); + throw new TaaException(getMissingArgumentMessage()); } - String moduleCode = argumentMap.get("c"); - if (moduleCode.contains(" ")) { - // TODO Invalid module code message - throw new CustomException(""); - } + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + String newId = argumentMap.get(KEY_NEW_ID); + String newName = argumentMap.get(KEY_NEW_NAME); Module module = modules.getModule(moduleCode); if (module == null) { - // TODO module not found message - throw new CustomException("Module not found"); + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - // TODO exceptions for number format and array out of bounds - int studentIndex = Integer.parseInt(argumentMap.get("n")) - 1; - String studentName = argumentMap.get("s"); - String studentID = argumentMap.get("i"); - Student student = modules.getModule(moduleCode).getStudents().get(studentIndex); - student.setName(studentName); - student.setStudentID(studentID); + if (!Util.isInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + int studentIndex = Integer.parseInt(studentIndexInput) - 1; + + Student student = module.getStudentAt(studentIndex); + if (student == null) { + ui.printMessage(MESSAGE_INVALID_STUDENT_INDEX); + return; + } - ui.printMessage(String.format(MESSAGE_STUDENT_EDITED_FORMAT, (studentIndex + 1), studentName, studentID)); + student.setId(newId); + student.setName(newName); + + ui.printMessage(String.format(MESSAGE_FORMAT_STUDENT_EDITED, student)); + } + + @Override + protected String getUsageMessage() { + return String.format( + MESSAGE_FORMAT_FIND_STUDENT_USAGE, + COMMAND_EDIT_STUDENT, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_NEW_ID, + KEY_NEW_NAME + ); } } \ No newline at end of file diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 4c7913c7ac..1f34fdb912 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -1,18 +1,23 @@ package taa.command; -import taa.CustomException; +import taa.exception.TaaException; import taa.Ui; import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; -import java.util.Locale; +import java.util.ArrayList; public class FindStudentCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_KEYWORD = "k"; + private static final String[] FIND_STUDENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_KEYWORD}; - private static final String[] FIND_STUDENT_ARGUMENT_KEYS = {"c","k"}; - private static final String MESSAGE_FOUND_STUDENT_FORMAT = "Here are the students in %s with '%s'"; - public static final String MESSAGE_NO_STUDENTS_FOUND = "No Students matching your keyword found"; + private static final String MESSAGE_NO_STUDENTS_FOUND = "There are no students matching your keyword."; + + private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "Usage: %s " + + "%s/ %s/"; + private static final String MESSAGE_FORMAT_STUDENT_FOUND_HEADER = "Here are the students in %s with \"%s\":"; public FindStudentCommand(String argument) { super(argument, FIND_STUDENT_ARGUMENT_KEYS); @@ -23,48 +28,51 @@ public FindStudentCommand(String argument) { * * @param modules The list of modules * @param ui The ui instance to handle interactions with the user - * @throws CustomException If the user inputs an invalid command + * @throws TaaException If the user inputs an invalid command */ @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { + public void execute(ModuleList modules, Ui ui) throws TaaException { if (argument.isEmpty()) { - // TODO Usage format message - throw new CustomException(""); + throw new TaaException(getUsageMessage()); } if (!checkArgumentMap()) { - // TODO Invalid/missing arguments message - throw new CustomException(""); + throw new TaaException(getMissingArgumentMessage()); } String moduleCode = argumentMap.get("c"); - if (moduleCode.contains(" ")) { - // TODO Invalid module code message - throw new CustomException(""); - } + String keyword = argumentMap.get("k"); Module module = modules.getModule(moduleCode); if (module == null) { - // TODO module not found message - throw new CustomException("Module not found"); + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - boolean isFound = false; - Student student; - String keyword = argumentMap.get("k").toLowerCase(); - for (int i = 0; i < module.getStudents().size(); i += 1) { - student = module.getStudents().get(i); - if (student.getName().toLowerCase().contains(keyword) - || student.getStudentID().toLowerCase().contains(keyword)) { - if (!isFound) { - ui.printMessage(String.format(MESSAGE_FOUND_STUDENT_FORMAT, moduleCode, keyword)); - isFound = true; - } - System.out.println(i + 1 + ". " + student); - } - } - if (!isFound) { + ArrayList studentsFound = module.findStudents(keyword); + if (studentsFound.isEmpty()) { ui.printMessage(MESSAGE_NO_STUDENTS_FOUND); + return; + } + + String header = String.format(MESSAGE_FORMAT_STUDENT_FOUND_HEADER, moduleCode, keyword); + StringBuilder stringBuilder = new StringBuilder(header); + for (int i = 0; i < studentsFound.size(); i += 1) { + stringBuilder.append("\n"); + stringBuilder.append(i + 1); + stringBuilder.append(". "); + stringBuilder.append(studentsFound.get(i)); } + + ui.printMessage(stringBuilder.toString()); + } + + @Override + protected String getUsageMessage() { + return String.format( + MESSAGE_FORMAT_FIND_STUDENT_USAGE, + COMMAND_FIND_STUDENT, + KEY_MODULE_CODE, + KEY_KEYWORD + ); } } \ No newline at end of file diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index b45472b4ee..b2e710c0f0 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -1,16 +1,22 @@ package taa.command; -import taa.CustomException; +import taa.exception.TaaException; import taa.Ui; import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; +import java.util.ArrayList; + public class ListStudentsCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String[] LIST_STUDENT_ARGUMENT_KEYS = {KEY_MODULE_CODE}; - private static final String[] LIST_STUDENT_ARGUMENT_KEYS = {"c"}; private static final String MESSAGE_NO_STUDENTS = "No students added yet!"; - private static final String MESSAGE_LIST_STUDENT_FORMAT = "Here are the students in %s"; + + private static final String MESSAGE_FORMAT_LIST_STUDENT_USAGE = "Usage: %s " + + "%s/"; + private static final String MESSAGE_FORMAT_LIST_STUDENT_HEADER = "Here are the students in %s:"; public ListStudentsCommand(String argument) { super(argument, LIST_STUDENT_ARGUMENT_KEYS); @@ -21,39 +27,48 @@ public ListStudentsCommand(String argument) { * * @param modules The list of modules * @param ui The ui instance to handle interactions with the user - * @throws CustomException If the user inputs an invalid command + * @throws TaaException If the user inputs an invalid command */ @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { + public void execute(ModuleList modules, Ui ui) throws TaaException { if (argument.isEmpty()) { - // TODO Usage format message - throw new CustomException(""); + throw new TaaException(getUsageMessage()); } if (!checkArgumentMap()) { - // TODO Invalid/missing arguments message - throw new CustomException(""); + throw new TaaException(getMissingArgumentMessage()); } String moduleCode = argumentMap.get("c"); - if (moduleCode.contains(" ")) { - // TODO Invalid module code message - throw new CustomException(""); - } Module module = modules.getModule(moduleCode); if (module == null) { - // TODO module not found message - throw new CustomException("Module not found"); + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - if (module.getStudents().size() == 0) { + ArrayList students = module.getStudents(); + if (students.isEmpty()) { ui.printMessage(MESSAGE_NO_STUDENTS); - } else { - ui.printMessage(String.format(MESSAGE_LIST_STUDENT_FORMAT, moduleCode)); - for (int i = 0; i < module.getStudents().size(); i += 1) { - System.out.println(i + 1 + ". " + module.getStudents().get(i)); - } + return; + } + + String header = String.format(MESSAGE_FORMAT_LIST_STUDENT_HEADER, moduleCode); + StringBuilder stringBuilder = new StringBuilder(header); + for (int i = 0; i < students.size(); i += 1) { + stringBuilder.append("\n"); + stringBuilder.append(i + 1); + stringBuilder.append(". "); + stringBuilder.append(students.get(i)); } + + ui.printMessage(stringBuilder.toString()); + } + + @Override + protected String getUsageMessage() { + return String.format(MESSAGE_FORMAT_LIST_STUDENT_USAGE, + COMMAND_LIST_STUDENTS, + KEY_MODULE_CODE + ); } } \ No newline at end of file From df270fda3f50a8625bd6c7da96dcf4ee55f27b8f Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 20:36:54 +0800 Subject: [PATCH 054/543] Add usage message to Exit command --- src/main/java/taa/command/ExitCommand.java | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/main/java/taa/command/ExitCommand.java b/src/main/java/taa/command/ExitCommand.java index e992bb185d..ad943a18b2 100644 --- a/src/main/java/taa/command/ExitCommand.java +++ b/src/main/java/taa/command/ExitCommand.java @@ -1,22 +1,28 @@ package taa.command; -import taa.CustomException; +import taa.exception.TaaException; import taa.Ui; import taa.module.ModuleList; public class ExitCommand extends Command { + private static final String MESSAGE_FORMAT_EXIT_USAGE = "Usage: %s"; + public ExitCommand(String argument) { super(argument); } @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { + public void execute(ModuleList modules, Ui ui) throws TaaException { if (!argument.isEmpty()) { - // TODO Usage format message - throw new CustomException(""); + throw new TaaException(getUsageMessage()); } ui.printExitMessage(); this.isExit = true; } + + @Override + protected String getUsageMessage() { + return String.format(MESSAGE_FORMAT_EXIT_USAGE, COMMAND_EXIT); + } } From 6e383e22a4f095f2452b55da991228d4b35a60de Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 20:37:09 +0800 Subject: [PATCH 055/543] Add Util class for basic utility functions --- src/main/java/taa/util/Util.java | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 src/main/java/taa/util/Util.java diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java new file mode 100644 index 0000000000..c7eb8225cf --- /dev/null +++ b/src/main/java/taa/util/Util.java @@ -0,0 +1,15 @@ +package taa.util; + +public class Util { + public static boolean isInteger(String string) { + boolean isInt; + try { + int value = Integer.parseInt(string); + isInt = true; + } catch (NumberFormatException e) { + isInt = false; + } + + return isInt; + } +} From 364cf3bbf415cc6ace069a1fcc72e2bcd1257016 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 20:37:28 +0800 Subject: [PATCH 056/543] Update automatic testing files --- text-ui-test/EXPECTED.TXT | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 4fa1459242..c78214e0fc 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -12,7 +12,7 @@ There are 1 modules in the list. ------------------------------------------------------------ $ ------------------------------------------------------------ Module List: -1: CS2113T - Software Engineering and Object-oriented Programming +1. CS2113T - Software Engineering and Object-oriented Programming ------------------------------------------------------------ $ ------------------------------------------------------------ An exception has occurred: From 40960f3e102d516de1a7c79a01dd413cde9f6778 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 20:41:16 +0800 Subject: [PATCH 057/543] Add empty line at end of file --- src/main/java/taa/command/EditStudentCommand.java | 2 +- src/main/java/taa/command/FindStudentCommand.java | 2 +- src/main/java/taa/command/ListStudentsCommand.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 804f469020..3eda7aa891 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -83,4 +83,4 @@ protected String getUsageMessage() { KEY_NEW_NAME ); } -} \ No newline at end of file +} diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 1f34fdb912..122c26e954 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -75,4 +75,4 @@ protected String getUsageMessage() { KEY_KEYWORD ); } -} \ No newline at end of file +} diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index b2e710c0f0..e1e2c05f46 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -71,4 +71,4 @@ protected String getUsageMessage() { KEY_MODULE_CODE ); } -} \ No newline at end of file +} From 5e5e83525eba5efb315e58663301296e641c9e4c Mon Sep 17 00:00:00 2001 From: Leyond Date: Sat, 9 Oct 2021 20:45:54 +0800 Subject: [PATCH 058/543] Move variables closer to usage --- src/main/java/taa/command/AddModuleCommand.java | 3 +-- src/main/java/taa/command/AddStudentCommand.java | 6 +++--- src/main/java/taa/command/DeleteStudentCommand.java | 5 ++--- src/main/java/taa/command/EditStudentCommand.java | 7 +++---- src/main/java/taa/command/FindStudentCommand.java | 5 ++--- src/main/java/taa/command/ListStudentsCommand.java | 3 +-- 6 files changed, 12 insertions(+), 17 deletions(-) diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index f400dd6e31..dac294f779 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -31,12 +31,11 @@ public void execute(ModuleList modules, Ui ui) throws TaaException { } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - String name = argumentMap.get(KEY_MODULE_NAME); - if (moduleCode.contains(" ")) { throw new TaaException(MESSAGE_INVALID_MODULE_CODE); } + String name = argumentMap.get(KEY_MODULE_NAME); Module module = new Module(moduleCode, name); modules.addModule(module); diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index 2efbb48002..bee681c970 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -38,13 +38,13 @@ public void execute(ModuleList modules, Ui ui) throws TaaException { } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - String studentID = argumentMap.get(KEY_STUDENT_ID); - String studentName = argumentMap.get(KEY_STUDENT_NAME); - Module module = modules.getModule(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } + + String studentID = argumentMap.get(KEY_STUDENT_ID); + String studentName = argumentMap.get(KEY_STUDENT_NAME); Student student = new Student(studentID, studentName); module.addStudent(student); diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 8bd7884012..c4201cf54b 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -37,14 +37,13 @@ public void execute(ModuleList modules, Ui ui) throws TaaException { throw new TaaException(getMissingArgumentMessage()); } - String moduleCode = argumentMap.get("c"); - String studentIndexInput = argumentMap.get("s"); - + String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = modules.getModule(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); if (!Util.isInteger(studentIndexInput)) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 3eda7aa891..782c43cd20 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -46,15 +46,12 @@ public void execute(ModuleList modules, Ui ui) throws TaaException { } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); - String newId = argumentMap.get(KEY_NEW_ID); - String newName = argumentMap.get(KEY_NEW_NAME); - Module module = modules.getModule(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); if (!Util.isInteger(studentIndexInput)) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } @@ -66,6 +63,8 @@ public void execute(ModuleList modules, Ui ui) throws TaaException { return; } + String newId = argumentMap.get(KEY_NEW_ID); + String newName = argumentMap.get(KEY_NEW_NAME); student.setId(newId); student.setName(newName); diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 122c26e954..6f1ecc2505 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -40,14 +40,13 @@ public void execute(ModuleList modules, Ui ui) throws TaaException { throw new TaaException(getMissingArgumentMessage()); } - String moduleCode = argumentMap.get("c"); - String keyword = argumentMap.get("k"); - + String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = modules.getModule(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } + String keyword = argumentMap.get(KEY_KEYWORD); ArrayList studentsFound = module.findStudents(keyword); if (studentsFound.isEmpty()) { ui.printMessage(MESSAGE_NO_STUDENTS_FOUND); diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index e1e2c05f46..c0e036c507 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -39,8 +39,7 @@ public void execute(ModuleList modules, Ui ui) throws TaaException { throw new TaaException(getMissingArgumentMessage()); } - String moduleCode = argumentMap.get("c"); - + String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = modules.getModule(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); From 462d9741721b4f9454f55cd47b3666a52cbb0c5e Mon Sep 17 00:00:00 2001 From: rachel Date: Sun, 10 Oct 2021 01:12:44 +0800 Subject: [PATCH 059/543] Add add_assessment command and AssessmentList and Assessment classes. Add comments for them too. --- src/main/java/taa/Parser.java | 14 ++-- src/main/java/taa/assessment/Assessment.java | 32 +++++++++ .../java/taa/assessment/AssessmentList.java | 66 +++++++++++++++++++ .../taa/command/AddAssessmentCommand.java | 50 ++++++++++++++ .../java/taa/command/AddStudentCommand.java | 2 +- src/main/java/taa/module/Module.java | 38 ++++------- src/main/java/taa/student/Assessment.java | 4 -- src/test/java/taa/ParserTest.java | 7 ++ .../taa/assessment/AssessmentListTest.java | 17 +++++ 9 files changed, 191 insertions(+), 39 deletions(-) create mode 100644 src/main/java/taa/assessment/Assessment.java create mode 100644 src/main/java/taa/assessment/AssessmentList.java create mode 100644 src/main/java/taa/command/AddAssessmentCommand.java delete mode 100644 src/main/java/taa/student/Assessment.java create mode 100644 src/test/java/taa/assessment/AssessmentListTest.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 33d24a7456..942000bd80 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,14 +1,6 @@ package taa; -import taa.command.AddStudentCommand; -import taa.command.Command; -import taa.command.AddModuleCommand; -import taa.command.ExitCommand; -import taa.command.ListModulesCommand; -import taa.command.FindStudentCommand; -import taa.command.ListStudentsCommand; -import taa.command.EditStudentCommand; -import taa.command.DeleteStudentCommand; +import taa.command.*; import java.util.ArrayList; @@ -57,6 +49,10 @@ public static Command parseUserInput(String userInput) throws CustomException { command = new FindStudentCommand(argument); break; + case Command.COMMAND_ADD_ASSESSMENT: + command = new AddAssessmentCommand(argument); + break; + default: throw new CustomException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/taa/assessment/Assessment.java b/src/main/java/taa/assessment/Assessment.java new file mode 100644 index 0000000000..6cba734944 --- /dev/null +++ b/src/main/java/taa/assessment/Assessment.java @@ -0,0 +1,32 @@ +package taa.assessment; + +public class Assessment { + private String assessmentName; + private double weightage; + + public Assessment(String assessmentName, double weightage) { + this.assessmentName = assessmentName; + this.weightage = weightage; + } + + public String getAssessmentName() { + return assessmentName; + } + + public double getWeightage() { + return weightage; + } + + /** + * Format the string to print out the assessment. + * For Midterms with 20% weightage, + * this will be printed: Midterms + * Weightage: 20.0 + * + * @return Assessment string. + */ + @Override + public String toString() { + return String.format("%s\n Weightage: %s", assessmentName, weightage); + } +} diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java new file mode 100644 index 0000000000..215a95ef64 --- /dev/null +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -0,0 +1,66 @@ +package taa.assessment; + +import java.util.ArrayList; + +public class AssessmentList { + private static final double MAX_ASSESSMENT_WEIGHTAGE = 100; + private static final String MESSAGE_ASSESSMENT_LIST_HEADER = "Assessment List:"; + + private final ArrayList assessments; + + public AssessmentList() { + this.assessments = new ArrayList<>(); + } + + /** + * Adds an assessment to the list of assessments in a particular module. + * Does not add if assessment name already exists + * or total weightage exceed MAX_ASSESSMENT_WEIGHTAGE after adding. + * + * @param assessment The assessment object to be added. + */ + public void addAssessment(Assessment assessment) { + boolean isValidAssessment = true; + double totalWeightage = 0; + for (Assessment a : assessments) { + totalWeightage += a.getWeightage(); + if (a.getAssessmentName().equalsIgnoreCase(assessment.getAssessmentName())) { + isValidAssessment = false; + } + } + if ((totalWeightage + assessment.getWeightage()) > MAX_ASSESSMENT_WEIGHTAGE) { + isValidAssessment = false; + } + + if (isValidAssessment) { + assessments.add(assessment); + } + } + + public boolean isValidIndex(int index) { + return (index >= 0 && index < assessments.size()); + } + + private Assessment getAssessmentAt(int index) { + if (isValidIndex(index)) { + return assessments.get(index); + } + + return null; + } + + public Assessment getAssessment(String assessmentName) { + for (int i = 0; i < assessments.size(); i += 1) { + Assessment assessment = getAssessmentAt(i); + if (assessment.getAssessmentName().equalsIgnoreCase(assessmentName)) { + return assessment; + } + } + + return null; + } + + public int getSize() { + return assessments.size(); + } +} diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java new file mode 100644 index 0000000000..7d9a239b61 --- /dev/null +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -0,0 +1,50 @@ +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.assessment.Assessment; +import taa.module.Module; +import taa.module.ModuleList; + +public class AddAssessmentCommand extends Command { + private static final String MESSAGE_ASSESSMENT_ADDED_FORMAT = "Assessment added:\n %s\nThere are %d assessments in the %s module."; + + private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {"c", "a", "w"}; + + public AddAssessmentCommand(String argument) { + super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); + } + + /** + * Adds an assessment to a particular module. + * + * @param modules The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @throws CustomException If the user inputs an invalid command. + */ + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + if (argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + + if (!checkArgumentMap()) { + // TODO Invalid/missing arguments message + throw new CustomException(""); + } + + String moduleCode = argumentMap.get("c"); + if (moduleCode.contains(" ")) { + // TODO Invalid module code message + throw new CustomException(""); + } + String assessmentName = argumentMap.get("a"); + double assessmentWeightage = Double.parseDouble(argumentMap.get("w")); + Module module = modules.getModule(moduleCode); + Assessment assessment = new Assessment(assessmentName, assessmentWeightage); + module.addAssessment(assessment); + + ui.printMessage(String.format(MESSAGE_ASSESSMENT_ADDED_FORMAT, assessment, module.getAssessmentsSize(), module)); + } +} diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index 4da9346642..8ab5f9caf0 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -16,7 +16,7 @@ public AddStudentCommand(String argument) { } /** - * Adds a students to a particular module. + * Adds a student to a particular module. * * @param modules The list of modules * @param ui The ui instance to handle interactions with the user diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index 7a80387823..1ab0437736 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -1,24 +1,24 @@ package taa.module; +import taa.assessment.Assessment; +import taa.assessment.AssessmentList; import taa.student.Student; import java.util.ArrayList; -import java.util.HashMap; public class Module { - private static final double MAX_ASSESSMENT_WEIGHTAGE = 100; private final String code; private final String name; private final ArrayList students; - private final HashMap assessments; + private final AssessmentList assessments; private int lessonCount; public Module(String code, String name) { this.code = code; this.name = name; this.students = new ArrayList<>(); - this.assessments = new HashMap<>(); + this.assessments = new AssessmentList(); } public String getCode() { @@ -41,8 +41,8 @@ public ArrayList getStudents() { return students; } - public HashMap getAssessments() { - return new HashMap<>(assessments); + public AssessmentList getAssessments() { + return assessments; } public void addStudent(Student student) { @@ -50,28 +50,16 @@ public void addStudent(Student student) { } /** - * Add an assessment to the module. Does not add if assessment name already exists - * or total weightage exceed MAX_ASSESSMENT_WEIGHTAGE after adding. + * Add an assessment to the module. * - * @param name Name of assessment. - * @param weightage Assessment weightage. - * @return true if success, else false. + * @param assessment Assessment object to be added. */ - public boolean addAssessment(String name, double weightage) { - if (assessments.containsKey(name)) { - return false; - } - - double totalWeightage = 0; - for (String key : assessments.keySet()) { - totalWeightage += assessments.get(key); - } - if ((totalWeightage + weightage) > MAX_ASSESSMENT_WEIGHTAGE) { - return false; - } + public void addAssessment(Assessment assessment) { + assessments.addAssessment(assessment); + } - assessments.put(name, weightage); - return true; + public int getAssessmentsSize() { + return assessments.getSize(); } @Override diff --git a/src/main/java/taa/student/Assessment.java b/src/main/java/taa/student/Assessment.java deleted file mode 100644 index 1d708b5bfe..0000000000 --- a/src/main/java/taa/student/Assessment.java +++ /dev/null @@ -1,4 +0,0 @@ -package taa.student; - -public class Assessment { -} diff --git a/src/test/java/taa/ParserTest.java b/src/test/java/taa/ParserTest.java index d801589117..69743981e6 100644 --- a/src/test/java/taa/ParserTest.java +++ b/src/test/java/taa/ParserTest.java @@ -27,4 +27,11 @@ void getArgumentsFromString_twoKeys_expectTwoItems() { String[] keys = {"c","n"}; assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 2); } + + @Test + void getArgumentsFromString_threeKeys_expectThreeItems() { + String inputString = "c/CS2113T a/Midterms w/20"; + String[] keys = {"c", "a", "w"}; + assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 3); + } } diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java new file mode 100644 index 0000000000..dc12e2706e --- /dev/null +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -0,0 +1,17 @@ +package taa.assessment; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class AssessmentListTest { + + @Test + void addAssessment_newAssessmentArguments_assessmentAddedCorrectly() { + String inputString = "c/CS2113T a/Midterms w/20"; + AssessmentList assessments = new AssessmentList(); + assessments.addAssessment(new Assessment("Midterms", 20)); + assertEquals("Midterms", assessments.getAssessment("Midterms").getAssessmentName()); + assertEquals(20, assessments.getAssessment("Midterms").getWeightage()); + } +} \ No newline at end of file From d3cdb8acf42b0e912146f65723b06cdca58c47d1 Mon Sep 17 00:00:00 2001 From: rachel Date: Sun, 10 Oct 2021 01:25:54 +0800 Subject: [PATCH 060/543] Update code formatting to pass checkstyle test. --- src/main/java/taa/Parser.java | 13 +++++++++++-- src/main/java/taa/command/AddAssessmentCommand.java | 8 +++++--- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 942000bd80..28533b140e 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,7 +1,16 @@ package taa; -import taa.command.*; - +import taa.command.AddModuleCommand; +import taa.command.Command; +import taa.command.ExitCommand; +import taa.command.ListModulesCommand; +import taa.command.AddAssessmentCommand; +import taa.command.AddStudentCommand; +import taa.command.DeleteStudentCommand; +import taa.command.EditStudentCommand; +import taa.command.ExitCommand; +import taa.command.FindStudentCommand; +import taa.command.ListStudentsCommand; import java.util.ArrayList; import java.util.Collections; diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 7d9a239b61..093d8d8381 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -7,7 +7,8 @@ import taa.module.ModuleList; public class AddAssessmentCommand extends Command { - private static final String MESSAGE_ASSESSMENT_ADDED_FORMAT = "Assessment added:\n %s\nThere are %d assessments in the %s module."; + private static final String MESSAGE_ASSESSMENT_ADDED_FORMAT = + "Assessment added:\n %s\nThere are %d assessments in the %s module."; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {"c", "a", "w"}; @@ -19,7 +20,7 @@ public AddAssessmentCommand(String argument) { * Adds an assessment to a particular module. * * @param modules The list of modules. - * @param ui The ui instance to handle interactions with the user. + * @param ui The ui instance to handle interactions with the user. * @throws CustomException If the user inputs an invalid command. */ @Override @@ -45,6 +46,7 @@ public void execute(ModuleList modules, Ui ui) throws CustomException { Assessment assessment = new Assessment(assessmentName, assessmentWeightage); module.addAssessment(assessment); - ui.printMessage(String.format(MESSAGE_ASSESSMENT_ADDED_FORMAT, assessment, module.getAssessmentsSize(), module)); + ui.printMessage(String.format(MESSAGE_ASSESSMENT_ADDED_FORMAT, + assessment, module.getAssessmentsSize(), module)); } } From 5c635ed74b33571ea488889f80a85964d7f3ad03 Mon Sep 17 00:00:00 2001 From: rachel Date: Sun, 10 Oct 2021 01:33:10 +0800 Subject: [PATCH 061/543] update code to pass checkstyle test. --- src/test/java/taa/assessment/AssessmentListTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index dc12e2706e..4b16453f93 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.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 AssessmentListTest { From f5117da47d0ae871af25e259778646c79b0179f4 Mon Sep 17 00:00:00 2001 From: rachel Date: Sun, 10 Oct 2021 02:14:10 +0800 Subject: [PATCH 062/543] Add list_assessments command. --- src/main/java/taa/Parser.java | 15 +++------ .../java/taa/assessment/AssessmentList.java | 13 ++++++++ .../taa/command/ListAssessmentsCommand.java | 31 +++++++++++++++++++ 3 files changed, 49 insertions(+), 10 deletions(-) create mode 100644 src/main/java/taa/command/ListAssessmentsCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 28533b140e..21c4ad246a 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,16 +1,7 @@ package taa; -import taa.command.AddModuleCommand; -import taa.command.Command; +import taa.command.*; import taa.command.ExitCommand; -import taa.command.ListModulesCommand; -import taa.command.AddAssessmentCommand; -import taa.command.AddStudentCommand; -import taa.command.DeleteStudentCommand; -import taa.command.EditStudentCommand; -import taa.command.ExitCommand; -import taa.command.FindStudentCommand; -import taa.command.ListStudentsCommand; import java.util.ArrayList; import java.util.Collections; @@ -62,6 +53,10 @@ public static Command parseUserInput(String userInput) throws CustomException { command = new AddAssessmentCommand(argument); break; + case Command.COMMAND_LIST_ASSESSMENTS: + command = new ListAssessmentsCommand(argument); + break; + default: throw new CustomException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 215a95ef64..c201bd259b 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -63,4 +63,17 @@ public Assessment getAssessment(String assessmentName) { public int getSize() { return assessments.size(); } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(MESSAGE_ASSESSMENT_LIST_HEADER); + for (int i = 0; i < getSize(); i += 1) { + stringBuilder.append("\n"); + stringBuilder.append(i + 1); + stringBuilder.append(": "); + stringBuilder.append(getAssessmentAt(i)); + } + + return stringBuilder.toString(); + } } diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java new file mode 100644 index 0000000000..d19697f171 --- /dev/null +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -0,0 +1,31 @@ +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.module.Module; +import taa.module.ModuleList; + +public class ListAssessmentsCommand extends Command { + private static final String MESSAGE_LIST_EMPTY = "There are no assessments in the module."; + private static final String[] LIST_ASSESSMENTS_ARGUMENT_KEYS = {"c"}; + + public ListAssessmentsCommand(String argument) { + super(argument, LIST_ASSESSMENTS_ARGUMENT_KEYS); + } + + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + if (argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + + String moduleCode = argumentMap.get("c"); + Module module = modules.getModule(moduleCode); + if (module.getAssessmentsSize() == 0) { + ui.printMessage(MESSAGE_LIST_EMPTY); + } else { + ui.printMessage(module.getAssessments().toString()); + } + } +} From 427cdbf67708b3bd27cbd5c74e4b1a507d6fac50 Mon Sep 17 00:00:00 2001 From: rachel Date: Sun, 10 Oct 2021 02:17:47 +0800 Subject: [PATCH 063/543] Add comments for list_assessments. --- src/main/java/taa/assessment/AssessmentList.java | 5 +++++ src/main/java/taa/command/ListAssessmentsCommand.java | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index c201bd259b..33a3e475cc 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -64,6 +64,11 @@ public int getSize() { return assessments.size(); } + /** + * Format the string to print out all the assessments. + * + * @return Assessment list string. + */ @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(MESSAGE_ASSESSMENT_LIST_HEADER); diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index d19697f171..12cd5ba835 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -13,6 +13,13 @@ public ListAssessmentsCommand(String argument) { super(argument, LIST_ASSESSMENTS_ARGUMENT_KEYS); } + /** + * Lists all the assessments of a particular module. + * + * @param modules The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @throws CustomException If the user inputs an invalid command. + */ @Override public void execute(ModuleList modules, Ui ui) throws CustomException { if (argument.isEmpty()) { From e1e912b5a16a0cd8448854ac8760203637180265 Mon Sep 17 00:00:00 2001 From: rachel Date: Sun, 10 Oct 2021 02:20:04 +0800 Subject: [PATCH 064/543] update code to pass checkstyle test. --- src/main/java/taa/Parser.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 21c4ad246a..3d51274ea3 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,7 +1,17 @@ package taa; -import taa.command.*; +import taa.command.AddAssessmentCommand; +import taa.command.AddModuleCommand; +import taa.command.AddStudentCommand; +import taa.command.Command; +import taa.command.DeleteStudentCommand; +import taa.command.EditStudentCommand; import taa.command.ExitCommand; +import taa.command.ExitCommand; +import taa.command.FindStudentCommand; +import taa.command.ListAssessmentsCommand; +import taa.command.ListModulesCommand; +import taa.command.ListStudentsCommand; import java.util.ArrayList; import java.util.Collections; From c12e3a29c6477968c4019517071a70f9db61da2f Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 10 Oct 2021 02:28:13 +0800 Subject: [PATCH 065/543] Add empty line at end of file --- src/test/java/taa/assessment/AssessmentListTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index 0e62cca095..227df55614 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -14,4 +14,4 @@ void addAssessment_newAssessmentArguments_assessmentAddedCorrectly() { assertEquals("Midterms", assessments.getAssessment("Midterms").getName()); assertEquals(20, assessments.getAssessment("Midterms").getWeightage()); } -} \ No newline at end of file +} From 77307ddab733c2061989c5c3e2ff05e4ff9614f6 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 10 Oct 2021 02:46:36 +0800 Subject: [PATCH 066/543] Add formmatted list_assessments output --- .../java/taa/assessment/AssessmentList.java | 20 ---------- .../taa/command/AddAssessmentCommand.java | 2 +- .../taa/command/ListAssessmentsCommand.java | 38 +++++++++++++++---- src/main/java/taa/module/Module.java | 2 +- 4 files changed, 32 insertions(+), 30 deletions(-) diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 72318248c3..3f31b667a7 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -5,8 +5,6 @@ public class AssessmentList { private static final double MAX_ASSESSMENT_WEIGHTAGE = 100; - private static final String MESSAGE_ASSESSMENT_LIST_HEADER = "Assessment List:"; - private final ArrayList assessments; public AssessmentList() { @@ -71,22 +69,4 @@ public ArrayList getAssessments() { public int getSize() { return assessments.size(); } - - /** - * Format the string to print out all the assessments. - * - * @return Assessment list string. - */ - @Override - public String toString() { - StringBuilder stringBuilder = new StringBuilder(MESSAGE_ASSESSMENT_LIST_HEADER); - for (int i = 0; i < getSize(); i += 1) { - stringBuilder.append("\n"); - stringBuilder.append(i + 1); - stringBuilder.append(". "); - stringBuilder.append(assessments.get(i)); - } - - return stringBuilder.toString(); - } } diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 435c56d076..9a8f3c3a99 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -9,7 +9,7 @@ public class AddAssessmentCommand extends Command { private static final String KEY_MODULE_CODE = "c"; - private static final String KEY_ASSESSMENT_NAME = "a"; + private static final String KEY_ASSESSMENT_NAME = "n"; private static final String KEY_WEIGHTAGE = "w"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME, KEY_WEIGHTAGE}; diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index 350898a601..22d86e5cf5 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -1,14 +1,18 @@ package taa.command; import taa.Ui; +import taa.assessment.Assessment; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; +import java.util.ArrayList; + public class ListAssessmentsCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String[] LIST_ASSESSMENTS_ARGUMENT_KEYS = {KEY_MODULE_CODE}; + private static final String MESSAGE_ASSESSMENT_LIST_HEADER = "Assessment List:"; private static final String MESSAGE_LIST_EMPTY = "There are no assessments in the module."; private static final String MESSAGE_FORMAT_LIST_ASSESSMENTS_USAGE = "Usage: %s %s/"; @@ -20,23 +24,41 @@ public ListAssessmentsCommand(String argument) { /** * Lists all the assessments of a particular module. * - * @param modules The list of modules. + * @param moduleList The list of modules. * @param ui The ui instance to handle interactions with the user. * @throws TaaException If the user inputs an invalid command. */ @Override - public void execute(ModuleList modules, Ui ui) throws TaaException { - if (!argument.isEmpty()) { + public void execute(ModuleList moduleList, Ui ui) throws TaaException { + if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } - String moduleCode = argumentMap.get("c"); - Module module = modules.getModule(moduleCode); - if (module.getAssessmentsCount() == 0) { + if (!checkArgumentMap()) { + throw new TaaException(getMissingArgumentMessage()); + } + + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModule(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + + ArrayList assessments = module.getAssessments(); + if (assessments.isEmpty()) { ui.printMessage(MESSAGE_LIST_EMPTY); - } else { - ui.printMessage(module.getAssessmentList().toString()); + return; + } + + StringBuilder stringBuilder = new StringBuilder(MESSAGE_ASSESSMENT_LIST_HEADER); + for (int i = 0; i < assessments.size(); i += 1) { + stringBuilder.append("\n"); + stringBuilder.append(i + 1); + stringBuilder.append(". "); + stringBuilder.append(assessments.get(i)); } + + ui.printMessage(stringBuilder.toString()); } @Override diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index 44e1ef0cd7..b891398bde 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -88,7 +88,7 @@ public ArrayList findStudents(String keyword) { return studentsFound; } - public ArrayList getAssessmentList() { + public ArrayList getAssessments() { return assessmentList.getAssessments(); } From ff76f45005f69f9aa3202a31380959e745172a65 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 10 Oct 2021 02:49:55 +0800 Subject: [PATCH 067/543] Remove extra space --- src/main/java/taa/command/EditStudentCommand.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index e6a4b30603..1e14d47261 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -19,7 +19,6 @@ public class EditStudentCommand extends Command { KEY_NEW_NAME }; - private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "Usage: %s " + "%s/ %s/ %s/ %s/"; private static final String MESSAGE_FORMAT_STUDENT_EDITED = "Student updated:\n %s"; From d122a04b3c5e82908c51b4aa1b46709e1ce85a00 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 10 Oct 2021 03:20:33 +0800 Subject: [PATCH 068/543] Add back accidentally deleted Mark class --- src/main/java/taa/student/Mark.java | 42 +++++++++++++++++++++++++ src/test/java/taa/student/MarkTest.java | 13 ++++++++ 2 files changed, 55 insertions(+) create mode 100644 src/main/java/taa/student/Mark.java create mode 100644 src/test/java/taa/student/MarkTest.java diff --git a/src/main/java/taa/student/Mark.java b/src/main/java/taa/student/Mark.java new file mode 100644 index 0000000000..6322eab4a2 --- /dev/null +++ b/src/main/java/taa/student/Mark.java @@ -0,0 +1,42 @@ +package taa.student; + +public class Mark { + private String assessmentName; + private int marks; + private double weightage; + + public Mark(String assessmentName, int marks, double weightage) { + this.assessmentName = assessmentName; + this.marks = marks; + this.weightage = weightage; + } + + public void setAssessmentName(String assessmentName) { + this.assessmentName = assessmentName; + } + + public void setMarks(int marks) { + this.marks = marks; + } + + public void setWeightage(double weightage) { + this.weightage = weightage; + } + + public String getAssessmentName() { + return assessmentName; + } + + public int getMarks() { + return marks; + } + + public double getWeightage() { + return weightage; + } + + @Override + public String toString() { + return assessmentName + ", " + marks + ", " + weightage; + } +} diff --git a/src/test/java/taa/student/MarkTest.java b/src/test/java/taa/student/MarkTest.java new file mode 100644 index 0000000000..82ab90fa3a --- /dev/null +++ b/src/test/java/taa/student/MarkTest.java @@ -0,0 +1,13 @@ +package taa.student; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class MarkTest { + @Test + public void testMarksStringConversion() { + assertEquals("Assignment 5, 56, 0.5", + new Mark("Assignment 5", 56, 0.5).toString()); + } +} From 53373cd32937f9bc7e2239191e9c2e0e65832626 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Mon, 11 Oct 2021 03:13:53 +0800 Subject: [PATCH 069/543] added list, average and set for marks. added marks attribute as hashmap in student class with assessment name as key. --- src/main/java/taa/Parser.java | 24 +++--- .../java/taa/assessment/AssessmentList.java | 17 ++++ .../java/taa/command/AverageMarksCommand.java | 67 ++++++++++++++++ .../java/taa/command/ListMarksCommand.java | 78 +++++++++++++++++++ .../java/taa/command/SetMarksCommand.java | 76 ++++++++++++++++++ src/main/java/taa/module/Module.java | 10 +++ src/main/java/taa/student/Student.java | 21 +++++ 7 files changed, 282 insertions(+), 11 deletions(-) create mode 100644 src/main/java/taa/command/AverageMarksCommand.java create mode 100644 src/main/java/taa/command/ListMarksCommand.java create mode 100644 src/main/java/taa/command/SetMarksCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 3d51274ea3..bfad4ab2e6 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,17 +1,7 @@ package taa; -import taa.command.AddAssessmentCommand; -import taa.command.AddModuleCommand; -import taa.command.AddStudentCommand; -import taa.command.Command; -import taa.command.DeleteStudentCommand; -import taa.command.EditStudentCommand; +import taa.command.*; import taa.command.ExitCommand; -import taa.command.ExitCommand; -import taa.command.FindStudentCommand; -import taa.command.ListAssessmentsCommand; -import taa.command.ListModulesCommand; -import taa.command.ListStudentsCommand; import java.util.ArrayList; import java.util.Collections; @@ -67,6 +57,18 @@ public static Command parseUserInput(String userInput) throws CustomException { command = new ListAssessmentsCommand(argument); break; + case Command.COMMAND_SET_MARKS: + command = new SetMarksCommand(argument); + break; + + case Command.COMMAND_AVERAGE_MARKS: + command = new AverageMarksCommand(argument); + break; + + case Command.COMMAND_LIST_MARKS: + command = new ListMarksCommand(argument); + break; + default: throw new CustomException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 33a3e475cc..606a8701ca 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -41,6 +41,23 @@ public boolean isValidIndex(int index) { return (index >= 0 && index < assessments.size()); } + /** + * Returns true if there exists an assessment with the inputted name in the assessment list. + * Returns false otherwise. + * + * @param assessmentName name of assessment to be checked. + * @return true if assessment exists, false otherwise. + */ + public boolean isValidAssessment(String assessmentName) { + for (Assessment a : assessments) { + if (a.getAssessmentName().equalsIgnoreCase(assessmentName)) { + return true; + } + } + return false; + } + + private Assessment getAssessmentAt(int index) { if (isValidIndex(index)) { return assessments.get(index); diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java new file mode 100644 index 0000000000..17a620c93f --- /dev/null +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -0,0 +1,67 @@ +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.assessment.AssessmentList; +import taa.module.Module; +import taa.module.ModuleList; +import taa.student.Student; + +/** + * Class that deals with the outputting of the average marks. + */ +public class AverageMarksCommand extends Command{ + private static final String MESSAGE_AVERAGE_MARKS_FORMAT = "Average marks for %s is %,.4f"; + private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {"c", "a"}; + + public AverageMarksCommand(String argument) { + super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); + } + + /** + * Checks if the set marks command is valid. Throws an exception if not. + * @param modules List of modules. + * @throws CustomException When average marks command is invalid. + */ + public void commandValidation(ModuleList modules) throws CustomException { + Module module = modules.getModule(argumentMap.get("c")); + AssessmentList list = module.getAssessments(); + if (argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + if (!checkArgumentMap()) { + // TODO Invalid/missing arguments message + throw new CustomException(""); + } + if (argumentMap.get("c").contains(" ")) { + // TODO Invalid module code message + throw new CustomException(""); + } + if (!list.isValidAssessment(argumentMap.get("a"))) { + // TODO non-existent assessment error message + throw new CustomException("assessment does not exist!"); + } + } + + /** + * Outputs the average marks of an assessment in a module. + * + * @param modules List of modules. + * @param ui The ui instance to handle interactions with the user. + * @throws CustomException When average marks command is invalid. + */ + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + commandValidation(modules); + Module module = modules.getModule(argumentMap.get("c")); + String assessmentName = argumentMap.get("a"); + double classSize = module.getNumberOfStudents(); + double totalMarks = 0; + for (Student student : module.getStudents()) { + totalMarks += student.getMarks(assessmentName); + } + double averageMarks = totalMarks / classSize; + ui.printMessage(String.format(MESSAGE_AVERAGE_MARKS_FORMAT, assessmentName, averageMarks)); + } +} diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java new file mode 100644 index 0000000000..08348a5040 --- /dev/null +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -0,0 +1,78 @@ +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.assessment.AssessmentList; +import taa.module.Module; +import taa.module.ModuleList; +import taa.student.Student; + +/** + * Class that deals with the command for the listing of marks. + */ +public class ListMarksCommand extends Command{ + private static final String MESSAGE_LIST_MARKS_HEADER = "Here is the list of students and " + + "their marks for %s:"; + private static final String MARKS_LIST_EMPTY = "There are no marks inputted!"; + private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {"c", "a"}; + + public ListMarksCommand(String argument) { + super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); + } + + /** + * Checks if the set marks command is valid. Throws an exception if not. + * @param modules List of modules. + * @throws CustomException When list marks command is invalid. + */ + public void commandValidation(ModuleList modules) throws CustomException { + Module module = modules.getModule(argumentMap.get("c")); + AssessmentList list = module.getAssessments(); + if (argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + if (!checkArgumentMap()) { + // TODO Invalid/missing arguments message + throw new CustomException(""); + } + if (argumentMap.get("c").contains(" ")) { + // TODO Invalid module code message + throw new CustomException(""); + } + if (!list.isValidAssessment(argumentMap.get("a"))) { + // TODO non-existent assessment error message + throw new CustomException("assessment does not exist!"); + } + } + + /** + * Returns a string with the student name and the marks associated with the student. + * @param studentName Name of the student. + * @param marks Marks of the student. + * @return String with the name and marks of the student separated with a vertical line. + */ + public String marksToString(String studentName, double marks) { + return studentName + " | " + marks; + } + + /** + * Lists the student and the marks they attained for an assessment. + * + * @param modules List of modules. + * @param ui The ui instance to handle interactions with the user. + * @throws CustomException When list marks command is invalid. + */ + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + commandValidation(modules); + Module module = modules.getModule(argumentMap.get("c")); + String assessmentName = argumentMap.get("a"); + StringBuilder marksList = new StringBuilder(String.format(MESSAGE_LIST_MARKS_HEADER, assessmentName)); + for (Student student : module.getStudents()) { + marksList.append("\n"); + marksList.append(marksToString(student.getName(), student.getMarks(assessmentName))); + } + ui.printMessage(marksList.toString()); + } +} diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java new file mode 100644 index 0000000000..7530318a5e --- /dev/null +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -0,0 +1,76 @@ +package taa.command; + +import taa.CustomException; +import taa.Ui; +import taa.assessment.AssessmentList; +import taa.module.Module; +import taa.module.ModuleList; +import taa.student.Student; + +/** + * Class that deals with the command for the setting of marks. + */ +public class SetMarksCommand extends Command{ + private static final String MESSAGE_MARKS_ADDED_FORMAT = "Marks set for %s: %,.4f for %s"; + private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {"c", "s", "a", "m"}; + + public SetMarksCommand(String argument) { + super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); + } + + /** + * Checks if the set marks command is valid. Throws an exception if not. + * @param modules List of modules. + * @throws CustomException When set marks command is invalid. + */ + public void commandValidation(ModuleList modules) throws CustomException { + Module module = modules.getModule(argumentMap.get("c")); + AssessmentList list = module.getAssessments(); + int studentIndex = Integer.parseInt(argumentMap.get("s")); + if (argument.isEmpty()) { + // TODO Usage format message + throw new CustomException(""); + } + if (!checkArgumentMap()) { + // TODO Invalid/missing arguments message + throw new CustomException(""); + } + if (argumentMap.get("c").contains(" ")) { + // TODO Invalid module code message + throw new CustomException(""); + } + if ((studentIndex > module.getNumberOfStudents()) || (studentIndex < 0)) { + // TODO non-existent student error message + throw new CustomException("student does not exist!"); + } + if (!list.isValidAssessment(argumentMap.get("a"))) { + // TODO non-existent assessment error message + throw new CustomException("assessment does not exist!"); + } + if(Double.parseDouble(argumentMap.get("m")) < 0) { + // TODO marks are negative + throw new CustomException("Marks are negative!"); + } + } + + /** + * Sets marks for a student's assessment. + * + * @param modules Module list to access the module the student is enrolled in. + * @param ui The ui instance to handle interactions with the user. + * @throws CustomException when set marks command is invalid. + */ + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { + commandValidation(modules); + String moduleCode = argumentMap.get("c"); + int studentIndex = Integer.parseInt(argumentMap.get("s")); + String assessmentName = argumentMap.get("a"); + double marks = Double.parseDouble(argumentMap.get("m")); + Module module = modules.getModule(moduleCode); + Student student = module.getStudent(studentIndex); + student.setMarks(assessmentName, marks); + String studentName = student.getName(); + ui.printMessage(String.format(MESSAGE_MARKS_ADDED_FORMAT, studentName, marks, assessmentName)); + } +} diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index 1ab0437736..8e1e87d43e 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -37,10 +37,18 @@ public void setLessonCount(int lessonCount) { this.lessonCount = lessonCount; } + public int getNumberOfStudents() { + return students.size(); + } + public ArrayList getStudents() { return students; } + public Student getStudent(int studentIndex) { + return students.get(studentIndex); + } + public AssessmentList getAssessments() { return assessments; } @@ -70,4 +78,6 @@ public String toString() { return String.format("%s - %s", code, name); } + + } diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index eb90f29284..b143135b59 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -1,5 +1,7 @@ package taa.student; +import java.util.HashMap; + /** * Represents students. */ @@ -10,6 +12,8 @@ public class Student { private String studentID; private final boolean[] attendance = new boolean[NUM_LESSONS]; + private final HashMap results = new HashMap<>(); + public Student(String name, String studentID) { this.name = name; this.studentID = studentID; @@ -79,4 +83,21 @@ public String getStudentID() { public String toString() { return name + ", " + studentID; } + + /** + * Adds a key,value pair to the hashmap. + * @param assessmentName key of the hashmap + * @param marks value to be stored under the key given + */ + public void setMarks(String assessmentName, double marks) { + results.put(assessmentName, marks); + } + + public double getMarks(String assessmentName) { + return results.get(assessmentName); + } + + public HashMap getAllMarks() { + return results; + } } From 1ed23b67968bb7330794bf3298920c09cf3ff3ef Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Mon, 11 Oct 2021 03:37:52 +0800 Subject: [PATCH 070/543] current process of error-handling (incomplete) --- .../java/taa/command/AverageMarksCommand.java | 20 +++----- .../java/taa/command/ListMarksCommand.java | 48 +++++++++---------- .../java/taa/command/SetMarksCommand.java | 30 +++++------- 3 files changed, 42 insertions(+), 56 deletions(-) diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index 17a620c93f..9ad50dc0df 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -19,11 +19,14 @@ public AverageMarksCommand(String argument) { } /** - * Checks if the set marks command is valid. Throws an exception if not. + * Outputs the average marks of an assessment in a module. + * * @param modules List of modules. + * @param ui The ui instance to handle interactions with the user. * @throws CustomException When average marks command is invalid. */ - public void commandValidation(ModuleList modules) throws CustomException { + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { Module module = modules.getModule(argumentMap.get("c")); AssessmentList list = module.getAssessments(); if (argument.isEmpty()) { @@ -42,19 +45,10 @@ public void commandValidation(ModuleList modules) throws CustomException { // TODO non-existent assessment error message throw new CustomException("assessment does not exist!"); } + averageMarks(ui, module); } - /** - * Outputs the average marks of an assessment in a module. - * - * @param modules List of modules. - * @param ui The ui instance to handle interactions with the user. - * @throws CustomException When average marks command is invalid. - */ - @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { - commandValidation(modules); - Module module = modules.getModule(argumentMap.get("c")); + private void averageMarks(Ui ui, Module module) { String assessmentName = argumentMap.get("a"); double classSize = module.getNumberOfStudents(); double totalMarks = 0; diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index 08348a5040..d6deccc805 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -21,11 +21,24 @@ public ListMarksCommand(String argument) { } /** - * Checks if the set marks command is valid. Throws an exception if not. + * Returns a string with the student name and the marks associated with the student. + * @param studentName Name of the student. + * @param marks Marks of the student. + * @return String with the name and marks of the student separated with a vertical line. + */ + public String marksToString(String studentName, double marks) { + return studentName + " | " + marks; + } + + /** + * Lists the student and the marks they attained for an assessment. + * * @param modules List of modules. + * @param ui The ui instance to handle interactions with the user. * @throws CustomException When list marks command is invalid. */ - public void commandValidation(ModuleList modules) throws CustomException { + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { Module module = modules.getModule(argumentMap.get("c")); AssessmentList list = module.getAssessments(); if (argument.isEmpty()) { @@ -44,35 +57,22 @@ public void commandValidation(ModuleList modules) throws CustomException { // TODO non-existent assessment error message throw new CustomException("assessment does not exist!"); } + listMarks(ui, module); } - /** - * Returns a string with the student name and the marks associated with the student. - * @param studentName Name of the student. - * @param marks Marks of the student. - * @return String with the name and marks of the student separated with a vertical line. - */ - public String marksToString(String studentName, double marks) { - return studentName + " | " + marks; - } - - /** - * Lists the student and the marks they attained for an assessment. - * - * @param modules List of modules. - * @param ui The ui instance to handle interactions with the user. - * @throws CustomException When list marks command is invalid. - */ - @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { - commandValidation(modules); - Module module = modules.getModule(argumentMap.get("c")); + private void listMarks(Ui ui, Module module) { String assessmentName = argumentMap.get("a"); StringBuilder marksList = new StringBuilder(String.format(MESSAGE_LIST_MARKS_HEADER, assessmentName)); + int marksCount = 0; for (Student student : module.getStudents()) { + marksCount += 1; marksList.append("\n"); marksList.append(marksToString(student.getName(), student.getMarks(assessmentName))); } - ui.printMessage(marksList.toString()); + if (marksCount <= 0) { + ui.printMessage(MARKS_LIST_EMPTY); + } else { + ui.printMessage(marksList.toString()); + } } } diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 7530318a5e..95d42b7a97 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -19,11 +19,14 @@ public SetMarksCommand(String argument) { } /** - * Checks if the set marks command is valid. Throws an exception if not. - * @param modules List of modules. - * @throws CustomException When set marks command is invalid. + * Sets marks for a student's assessment. + * + * @param modules Module list to access the module the student is enrolled in. + * @param ui The ui instance to handle interactions with the user. + * @throws CustomException when set marks command is invalid. */ - public void commandValidation(ModuleList modules) throws CustomException { + @Override + public void execute(ModuleList modules, Ui ui) throws CustomException { Module module = modules.getModule(argumentMap.get("c")); AssessmentList list = module.getAssessments(); int studentIndex = Integer.parseInt(argumentMap.get("s")); @@ -39,7 +42,7 @@ public void commandValidation(ModuleList modules) throws CustomException { // TODO Invalid module code message throw new CustomException(""); } - if ((studentIndex > module.getNumberOfStudents()) || (studentIndex < 0)) { + if ((studentIndex > module.getNumberOfStudents()) || (studentIndex <= 0)) { // TODO non-existent student error message throw new CustomException("student does not exist!"); } @@ -51,24 +54,13 @@ public void commandValidation(ModuleList modules) throws CustomException { // TODO marks are negative throw new CustomException("Marks are negative!"); } + setMarks(ui, module, studentIndex); } - /** - * Sets marks for a student's assessment. - * - * @param modules Module list to access the module the student is enrolled in. - * @param ui The ui instance to handle interactions with the user. - * @throws CustomException when set marks command is invalid. - */ - @Override - public void execute(ModuleList modules, Ui ui) throws CustomException { - commandValidation(modules); - String moduleCode = argumentMap.get("c"); - int studentIndex = Integer.parseInt(argumentMap.get("s")); + private void setMarks(Ui ui, Module module, int studentIndex) { String assessmentName = argumentMap.get("a"); double marks = Double.parseDouble(argumentMap.get("m")); - Module module = modules.getModule(moduleCode); - Student student = module.getStudent(studentIndex); + Student student = module.getStudent(studentIndex - 1); student.setMarks(assessmentName, marks); String studentName = student.getName(); ui.printMessage(String.format(MESSAGE_MARKS_ADDED_FORMAT, studentName, marks, assessmentName)); From cee94c7083f129c145cf5cea6c9ddb91b22919ec Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Mon, 11 Oct 2021 15:03:09 +0800 Subject: [PATCH 071/543] current attempt at bug fixing --- src/main/java/taa/command/SetMarksCommand.java | 2 +- src/main/java/taa/module/ModuleList.java | 9 +++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 95d42b7a97..359ead86dd 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -38,7 +38,7 @@ public void execute(ModuleList modules, Ui ui) throws CustomException { // TODO Invalid/missing arguments message throw new CustomException(""); } - if (argumentMap.get("c").contains(" ")) { + if (argumentMap.get("c").contains(" ") || (modules.isModuleExist(argumentMap.get("c")))) { // TODO Invalid module code message throw new CustomException(""); } diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index 3da7623b09..8b82a6aaca 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -60,6 +60,15 @@ public Module getModule(String code) { return null; } + public boolean isModuleExist(String moduleName) { + for (Module module : modules) { + if (module.getName().toLowerCase().equalsIgnoreCase(moduleName)) { + return true; + } + } + return false; + } + @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(MESSAGE_MODULE_LIST_HEADER); From e8f32ae25b2a05e4e51d443b3fe34f78026b79ef Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Mon, 11 Oct 2021 16:26:49 +0800 Subject: [PATCH 072/543] finished error handling for now --- src/main/java/taa/Parser.java | 10 +++++++++- src/main/java/taa/command/AverageMarksCommand.java | 2 +- src/main/java/taa/command/ListAssessmentsCommand.java | 2 +- src/main/java/taa/command/ListMarksCommand.java | 2 +- src/main/java/taa/command/SetMarksCommand.java | 2 +- src/main/java/taa/module/Module.java | 5 ++++- 6 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 6aa87e0436..069fde5196 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,11 +1,19 @@ package taa; -import taa.command.*; +import taa.command.AddAssessmentCommand; +import taa.command.AddModuleCommand; +import taa.command.AddStudentCommand; +import taa.command.AverageMarksCommand; +import taa.command.Command; +import taa.command.DeleteStudentCommand; +import taa.command.EditStudentCommand; import taa.command.ExitCommand; import taa.command.FindStudentCommand; import taa.command.ListAssessmentsCommand; +import taa.command.ListMarksCommand; import taa.command.ListModulesCommand; import taa.command.ListStudentsCommand; +import taa.command.SetMarksCommand; import taa.exception.TaaException; import java.util.ArrayList; diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index e8d20b75ce..c9708c54f3 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -53,7 +53,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException("No students taking this assessment!"); } - AssessmentList list = module.getAssessments(); + AssessmentList list = module.getAssessmentList(); Assessment assessment = list.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { throw new TaaException("Assessment does not exist!"); diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index 2c22d585b9..22d86e5cf5 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -44,7 +44,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - ArrayList assessments = module.getAssessments().getAssessments(); + ArrayList assessments = module.getAssessments(); if (assessments.isEmpty()) { ui.printMessage(MESSAGE_LIST_EMPTY); return; diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index 6656c6b230..9484d58aef 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -63,7 +63,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException("No students to list!"); } - AssessmentList list = module.getAssessments(); + AssessmentList list = module.getAssessmentList(); Assessment assessment = list.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { // TODO non-existent assessment error message diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 206b668976..6dbdb56292 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -59,7 +59,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException("No such student!"); } - AssessmentList list = module.getAssessments(); + AssessmentList list = module.getAssessmentList(); Assessment assessment = list.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { // TODO non-existent assessment error message diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index 096ce7d61f..b4b73e3632 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -49,9 +49,12 @@ public Student getStudent(int studentIndex) { return students.get(studentIndex); } - public AssessmentList getAssessments() { + public AssessmentList getAssessmentList() { return assessmentList; } + public ArrayList getAssessments() { + return assessmentList.getAssessments(); + } public void addStudent(Student student) { students.add(student); From e467e6ce440aee6db8bc16ee68101e75a48483da Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Mon, 11 Oct 2021 16:28:36 +0800 Subject: [PATCH 073/543] added todos for messages --- src/main/java/taa/command/AverageMarksCommand.java | 2 ++ src/main/java/taa/command/ListMarksCommand.java | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index c9708c54f3..9d6dff6ce7 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -50,12 +50,14 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } if (module.getNumberOfStudents() <= 0) { + //TODO no students in assessment message throw new TaaException("No students taking this assessment!"); } AssessmentList list = module.getAssessmentList(); Assessment assessment = list.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { + //TODO no such assessment message throw new TaaException("Assessment does not exist!"); } diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index 9484d58aef..e9d305ef0e 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -60,13 +60,14 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } if (module.getNumberOfStudents() <= 0) { + //TODO no students in assessment message throw new TaaException("No students to list!"); } AssessmentList list = module.getAssessmentList(); Assessment assessment = list.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { - // TODO non-existent assessment error message + // TODO no such assessment message throw new TaaException("Assessment does not exist!"); } From afcac7942343cedea239ec266d3657bf0d17c445 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Mon, 11 Oct 2021 16:46:16 +0800 Subject: [PATCH 074/543] edited to pass Gradle checks and added documentation --- .../java/taa/command/AverageMarksCommand.java | 22 +++++++++++----- .../java/taa/command/ListMarksCommand.java | 23 ++++++++++++----- .../java/taa/command/SetMarksCommand.java | 25 +++++++++++++------ src/main/java/taa/module/Module.java | 1 + 4 files changed, 52 insertions(+), 19 deletions(-) diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index 9d6dff6ce7..420b82692c 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -11,25 +11,26 @@ /** * Class that deals with the outputting of the average marks. */ -public class AverageMarksCommand extends Command{ +public class AverageMarksCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_ASSESSMENT_NAME = "a"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME }; private static final String MESSAGE_FORMAT_AVERAGE_MARKS_USAGE = "Usage: %s " + "%s/ %s/"; private static final String MESSAGE_AVERAGE_MARKS_FORMAT = "Average marks for %s is %,.4f"; - private static final String MESSAGE_AVERAGE_MARKS_WITH_UNMARKED_FORMAT = "Average marks for %s is %,.4f\n" + - "Note that %d student(s) have yet to be marked!"; + private static final String MESSAGE_AVERAGE_MARKS_WITH_UNMARKED_FORMAT = "Average marks for %s is %,.4f\n" + + "Note that %d student(s) have yet to be marked!"; public AverageMarksCommand(String argument) { super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); } /** - * Outputs the average marks of an assessment in a module. + * Checks for errors before calling the function to output the average marks + * of an assessment in a module. * * @param moduleList List of modules. * @param ui The ui instance to handle interactions with the user. @@ -64,6 +65,10 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { averageMarks(ui, module); } + /** + * Returns the usage message of the average marks command. + * @return String which contains the usage message. + */ @Override protected String getUsageMessage() { return String.format( @@ -74,6 +79,11 @@ protected String getUsageMessage() { ); } + /** + * Outputs the average marks of an assessment in a module. + * @param ui The ui instance to handle interactions with the user. + * @param module The module the assessment belongs to. + */ private void averageMarks(Ui ui, Module module) { String assessmentName = argumentMap.get("a"); double classSize = module.getNumberOfStudents(); diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index e9d305ef0e..3c71a1a809 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -11,17 +11,17 @@ /** * Class that deals with the command for the listing of marks. */ -public class ListMarksCommand extends Command{ +public class ListMarksCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_ASSESSMENT_NAME = "a"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME }; private static final String MESSAGE_FORMAT_LIST_MARKS_USAGE = "Usage: %s " + "%s/ %s/"; - private static final String MESSAGE_LIST_MARKS_HEADER = "Here is the list of students and " + - "their marks for %s:"; + private static final String MESSAGE_LIST_MARKS_HEADER = "Here is the list of students and " + + "their marks for %s:"; private static final String MARKS_LIST_EMPTY = "There are no marks inputted!"; public ListMarksCommand(String argument) { @@ -39,7 +39,8 @@ public String marksToString(String studentName, double marks) { } /** - * Lists the student and the marks they attained for an assessment. + * Checks for errors before calling the function that + * lists the student and the marks they attained for an assessment. * * @param moduleList List of modules. * @param ui The ui instance to handle interactions with the user. @@ -74,6 +75,10 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { listMarks(ui, module); } + /** + * Returns the usage message of the list marks command. + * @return String which contains the usage message. + */ @Override protected String getUsageMessage() { return String.format( @@ -84,6 +89,12 @@ protected String getUsageMessage() { ); } + /** + * Lists the student and the marks they attained for an assessment. + * + * @param ui The ui instance to handle interactions with the user. + * @param module The module that the student and assessment belong to. + */ private void listMarks(Ui ui, Module module) { String assessmentName = argumentMap.get("a"); StringBuilder marksList = new StringBuilder(String.format(MESSAGE_LIST_MARKS_HEADER, assessmentName)); diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 6dbdb56292..f165c23c81 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -12,16 +12,16 @@ /** * Class that deals with the command for the setting of marks. */ -public class SetMarksCommand extends Command{ +public class SetMarksCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_ASSESSMENT_NAME = "a"; private static final String KEY_MARKS = "m"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_ASSESSMENT_NAME, - KEY_MARKS + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_ASSESSMENT_NAME, + KEY_MARKS }; private static final String MESSAGE_FORMAT_SET_MARKS_USAGE = "Usage: %s " + "%s/ %s/ %s/ %s/"; @@ -32,7 +32,7 @@ public SetMarksCommand(String argument) { } /** - * Sets marks for a student's assessment. + * Checks for errors before calling the function that sets marks for a student's assessment. * * @param moduleList Module list to access the module the student is enrolled in. * @param ui The ui instance to handle interactions with the user. @@ -65,13 +65,17 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { // TODO non-existent assessment error message throw new TaaException("Assessment does not exist!"); } - if(Double.parseDouble(argumentMap.get(KEY_MARKS)) < 0) { + if (Double.parseDouble(argumentMap.get(KEY_MARKS)) < 0) { // TODO marks are negative throw new TaaException("Marks cannot be negative!"); } setMarks(ui, module, studentIndex); } + /** + * Returns the usage message of the set marks command. + * @return String which contains the usage message. + */ @Override protected String getUsageMessage() { return String.format( @@ -84,6 +88,13 @@ protected String getUsageMessage() { ); } + /** + * Sets the marks for a student's assessment. + * + * @param ui The ui instance to handle interactions with the user. + * @param module The module the assessment and student belong to. + * @param studentIndex Index of the student. + */ private void setMarks(Ui ui, Module module, int studentIndex) { String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); double marks = Double.parseDouble(argumentMap.get(KEY_MARKS)); diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index b4b73e3632..b13b11705d 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -52,6 +52,7 @@ public Student getStudent(int studentIndex) { public AssessmentList getAssessmentList() { return assessmentList; } + public ArrayList getAssessments() { return assessmentList.getAssessments(); } From 923bdee7fbfa6035281b14168fb706bfe7ce2727 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 11 Oct 2021 18:46:12 +0800 Subject: [PATCH 075/543] Handle empty argument values for parser --- src/main/java/taa/Parser.java | 6 ++++-- src/test/java/taa/ParserTest.java | 14 ++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 7fce22f0ea..e6f397c9dc 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -84,7 +84,7 @@ public static String[] splitFirstSpace(String string) { } /** - * Gets argument values specified by argumentKeys. + * Gets argument values specified by argumentKeys. Keys with empty values are not included in the returned HashMap. * e.g. * string: "add_module c/CS2113T n/Software Engineering and Object-oriented Programming", argumentKeys: {"c","n"} * Result: HashMap( @@ -130,7 +130,9 @@ public static HashMap getArgumentsFromString(String string, Strin } value = value.trim(); - result.put(key, value); + if (!value.isEmpty()) { + result.put(key, value); + } } return result; diff --git a/src/test/java/taa/ParserTest.java b/src/test/java/taa/ParserTest.java index 69743981e6..84bf4a1bd0 100644 --- a/src/test/java/taa/ParserTest.java +++ b/src/test/java/taa/ParserTest.java @@ -34,4 +34,18 @@ void getArgumentsFromString_threeKeys_expectThreeItems() { String[] keys = {"c", "a", "w"}; assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 3); } + + @Test + void getArgumentsFromString_OneKeyAndEmptyValue_expectZeroItems() { + String inputString = "c/"; + String[] keys = {"c"}; + assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 0); + } + + @Test + void getArgumentsFromString_TwoKeyAndOneEmptyValue_expectOneItem() { + String inputString = "c/ n/Software Engineering and Object-oriented Programming"; + String[] keys = {"c","n"}; + assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 1); + } } From ce95f0b995ca6bfebc8404151721340d33d6d0f8 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 11 Oct 2021 19:39:34 +0800 Subject: [PATCH 076/543] Add StudentList class to handle students --- src/main/java/taa/module/Module.java | 86 ++-------------------- src/main/java/taa/module/ModuleList.java | 3 +- src/main/java/taa/student/Student.java | 15 ++-- src/main/java/taa/student/StudentList.java | 82 +++++++++++++++++++++ 4 files changed, 96 insertions(+), 90 deletions(-) create mode 100644 src/main/java/taa/student/StudentList.java diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index b13b11705d..990be89598 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -1,23 +1,19 @@ package taa.module; -import taa.assessment.Assessment; import taa.assessment.AssessmentList; -import taa.student.Student; - -import java.util.ArrayList; +import taa.student.StudentList; public class Module { - private static final double MAX_ASSESSMENT_WEIGHTAGE = 1; private String code; private String name; private int lessonCount; - private final ArrayList students; + private final StudentList studentList; private final AssessmentList assessmentList; public Module(String code, String name) { this.code = code; this.name = name; - this.students = new ArrayList<>(); + this.studentList = new StudentList(); this.assessmentList = new AssessmentList(); } @@ -37,81 +33,14 @@ public void setLessonCount(int lessonCount) { this.lessonCount = lessonCount; } - public int getNumberOfStudents() { - return students.size(); - } - - public ArrayList getStudents() { - return new ArrayList<>(students); - } - - public Student getStudent(int studentIndex) { - return students.get(studentIndex); + public StudentList getStudentList() { + return studentList; } public AssessmentList getAssessmentList() { return assessmentList; } - public ArrayList getAssessments() { - return assessmentList.getAssessments(); - } - - public void addStudent(Student student) { - students.add(student); - } - - public int getStudentCount() { - return students.size(); - } - - public Student getStudentAt(int index) { - if (isValidStudentIndex(index)) { - return students.get(index); - } - - return null; - } - - /** - * Deletes a student from the student list. - * - * @param index The index of the student. - * @return A Student object if successfully deleted, else null. - */ - public Student deleteStudent(int index) { - if (isValidStudentIndex(index)) { - return students.remove(index); - } - - return null; - } - - public ArrayList findStudents(String keyword) { - String keywordLower = keyword.toLowerCase(); - - ArrayList studentsFound = new ArrayList<>(); - for (int i = 0; i < getStudentCount(); i += 1) { - Student student = students.get(i); - String id = student.getId(); - String name = student.getName(); - - if (id.toLowerCase().contains(keywordLower) || name.toLowerCase().contains(keywordLower)) { - studentsFound.add(student); - } - } - - return studentsFound; - } - - public boolean addAssessment(Assessment assessment) { - return assessmentList.addAssessment(assessment); - } - - public int getAssessmentsCount() { - return assessmentList.getSize(); - } - @Override public String toString() { if (name.isEmpty()) { @@ -120,9 +49,4 @@ public String toString() { return String.format("%s - %s", code, name); } - - - private boolean isValidStudentIndex(int index) { - return (index >= 0 && index < getStudentCount()); - } } diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index 8b997b2f93..ed24d8b370 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -50,8 +50,7 @@ public Module getModuleAt(int index) { * @return A Module object if found, else null. */ public Module getModule(String code) { - for (int i = 0; i < getSize(); i += 1) { - Module module = modules.get(i); + for (Module module : modules) { if (module.getCode().equals(code)) { return module; } diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index b2b5385bbc..7b6a00c141 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -1,22 +1,22 @@ package taa.student; +import java.util.ArrayList; import java.util.HashMap; /** * Represents students. */ public class Student { - private static final int NUM_LESSONS = 13; - private String id; private String name; - private final boolean[] attendance = new boolean[NUM_LESSONS]; - - private final HashMap results = new HashMap<>(); + private final ArrayList attendance; + private final HashMap results; public Student(String id, String name) { this.id = id; this.name = name; + this.attendance = new ArrayList<>(); + this.results = new HashMap<>(); } /** @@ -25,7 +25,7 @@ public Student(String id, String name) { * @param lessonIndex The lesson index the student is present for */ public void markAttendance(int lessonIndex) { - attendance[lessonIndex] = true; + // TODO } /** @@ -35,7 +35,8 @@ public void markAttendance(int lessonIndex) { * @return The attendance status of the student for the lesson */ public boolean isPresent(int lessonIndex) { - return attendance[lessonIndex]; + // TODO + return false; } /** diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java new file mode 100644 index 0000000000..366d6e1c3f --- /dev/null +++ b/src/main/java/taa/student/StudentList.java @@ -0,0 +1,82 @@ +package taa.student; + +import java.util.ArrayList; + +public class StudentList { + private static String MESSAGE_LIST_STUDENT_HEADER = "Student List:"; + + private ArrayList students; + + /** + * Gets a list of students in the ArrayList. Note that this returns a new ArrayList instance. + * + * @return A new ArrayList containing all the students. + */ + public ArrayList getStudents() { + return new ArrayList<>(students); + } + + public int getSize() { + return students.size(); + } + + private boolean isValidStudentIndex(int index) { + return (index >= 0 && index < getSize()); + } + + public Student getStudentAt(int index) { + if (isValidStudentIndex(index)) { + return students.get(index); + } + + return null; + } + + public void addStudent(Student student) { + students.add(student); + } + + /** + * Deletes a student from the student list. + * + * @param index The index of the student. + * @return A Student object if successfully deleted, else null. + */ + public Student deleteStudent(int index) { + if (isValidStudentIndex(index)) { + return students.remove(index); + } + + return null; + } + + public ArrayList findStudents(String keyword) { + String keywordLower = keyword.toLowerCase(); + + ArrayList studentsFound = new ArrayList<>(); + for (Student student : students) { + String id = student.getId(); + String name = student.getName(); + + if (id.toLowerCase().contains(keywordLower) || name.toLowerCase().contains(keywordLower)) { + studentsFound.add(student); + } + } + + return studentsFound; + } + + @Override + public String toString() { + String header = String.format(MESSAGE_LIST_STUDENT_HEADER); + StringBuilder stringBuilder = new StringBuilder(header); + for (int i = 0; i < students.size(); i += 1) { + stringBuilder.append("\n"); + stringBuilder.append(i + 1); + stringBuilder.append(". "); + stringBuilder.append(students.get(i)); + } + + return stringBuilder.toString(); + } +} From abc0e6017dcde1bbb9873a6d4f2a16298884090d Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 11 Oct 2021 19:41:16 +0800 Subject: [PATCH 077/543] Refactor to use StudentList class --- .../java/taa/command/AddStudentCommand.java | 5 ++++- src/main/java/taa/command/Command.java | 2 ++ .../taa/command/DeleteStudentCommand.java | 4 +++- .../java/taa/command/EditStudentCommand.java | 4 +++- .../java/taa/command/FindStudentCommand.java | 4 +++- .../java/taa/command/ListStudentsCommand.java | 20 ++++--------------- 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index ebbb404931..afad77d797 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -5,6 +5,7 @@ import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; +import taa.student.StudentList; public class AddStudentCommand extends Command { private static final String KEY_MODULE_CODE = "c"; @@ -46,7 +47,9 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { String studentID = argumentMap.get(KEY_STUDENT_ID); String studentName = argumentMap.get(KEY_STUDENT_NAME); Student student = new Student(studentID, studentName); - module.addStudent(student); + + StudentList studentList = module.getStudentList(); + studentList.addStudent(student); ui.printMessage(String.format(MESSAGE_STUDENT_ADDED_FORMAT, moduleCode, student)); } diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 11149c0e3c..43d9affd16 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -27,6 +27,8 @@ public abstract class Command { protected static final String MESSAGE_UNKNOWN_USAGE = "Unknown usage."; protected static final String MESSAGE_MODULE_NOT_FOUND = "Module not found."; protected static final String MESSAGE_INVALID_STUDENT_INDEX = "Invalid student index."; + protected static final String MESSAGE_INVALID_ASSESSMENT_NAME = "Invalid assessment name."; + protected static final String MESSAGE_NO_STUDENTS = "There are no students in this module"; protected static final String MESSAGE_FORMAT_GENERIC_USAGE = "Usage: %s"; protected static final String MESSAGE_FORMAT_MISSING_ARGUMENT = "Missing Argument(s).\n%s"; diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 2d3a2d0d65..6aea535ace 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -5,6 +5,7 @@ import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; +import taa.student.StudentList; import taa.util.Util; public class DeleteStudentCommand extends Command { @@ -49,7 +50,8 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { } int studentIndex = Integer.parseInt(studentIndexInput) - 1; - Student student = module.deleteStudent(studentIndex); + StudentList studentList = module.getStudentList(); + Student student = studentList.deleteStudent(studentIndex); if (student == null) { ui.printMessage(MESSAGE_INVALID_STUDENT_INDEX); } diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 1e14d47261..c4ce97c060 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -5,6 +5,7 @@ import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; +import taa.student.StudentList; import taa.util.Util; public class EditStudentCommand extends Command { @@ -56,7 +57,8 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { } int studentIndex = Integer.parseInt(studentIndexInput) - 1; - Student student = module.getStudentAt(studentIndex); + StudentList studentList = module.getStudentList(); + Student student = studentList.getStudentAt(studentIndex); if (student == null) { ui.printMessage(MESSAGE_INVALID_STUDENT_INDEX); return; diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 06e558f8fc..3959c70d42 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -5,6 +5,7 @@ import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; +import taa.student.StudentList; import java.util.ArrayList; @@ -47,7 +48,8 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { } String keyword = argumentMap.get(KEY_KEYWORD); - ArrayList studentsFound = module.findStudents(keyword); + StudentList studentList = module.getStudentList(); + ArrayList studentsFound = studentList.findStudents(keyword); if (studentsFound.isEmpty()) { ui.printMessage(MESSAGE_NO_STUDENTS_FOUND); return; diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index 4824faed8e..b44aba896f 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -4,9 +4,7 @@ import taa.Ui; import taa.module.Module; import taa.module.ModuleList; -import taa.student.Student; - -import java.util.ArrayList; +import taa.student.StudentList; public class ListStudentsCommand extends Command { private static final String KEY_MODULE_CODE = "c"; @@ -16,7 +14,6 @@ public class ListStudentsCommand extends Command { private static final String MESSAGE_FORMAT_LIST_STUDENT_USAGE = "Usage: %s " + "%s/"; - private static final String MESSAGE_FORMAT_LIST_STUDENT_HEADER = "Here are the students in %s:"; public ListStudentsCommand(String argument) { super(argument, LIST_STUDENT_ARGUMENT_KEYS); @@ -45,22 +42,13 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - ArrayList students = module.getStudents(); - if (students.isEmpty()) { + StudentList studentList = module.getStudentList(); + if (studentList.getSize() == 0) { ui.printMessage(MESSAGE_NO_STUDENTS); return; } - String header = String.format(MESSAGE_FORMAT_LIST_STUDENT_HEADER, moduleCode); - StringBuilder stringBuilder = new StringBuilder(header); - for (int i = 0; i < students.size(); i += 1) { - stringBuilder.append("\n"); - stringBuilder.append(i + 1); - stringBuilder.append(". "); - stringBuilder.append(students.get(i)); - } - - ui.printMessage(stringBuilder.toString()); + ui.printMessage(studentList.toString()); } @Override From 1cbfafa4d1c9cf12be12568e4cdae4128c029bd1 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 11 Oct 2021 19:42:06 +0800 Subject: [PATCH 078/543] Add check for weightage value boundaries --- src/main/java/taa/assessment/Assessment.java | 4 ++- .../java/taa/assessment/AssessmentList.java | 21 +++++++++---- .../taa/command/AddAssessmentCommand.java | 30 ++++++++++++++----- .../taa/command/ListAssessmentsCommand.java | 19 +++--------- 4 files changed, 45 insertions(+), 29 deletions(-) diff --git a/src/main/java/taa/assessment/Assessment.java b/src/main/java/taa/assessment/Assessment.java index 7eb00fea4b..414d5ffded 100644 --- a/src/main/java/taa/assessment/Assessment.java +++ b/src/main/java/taa/assessment/Assessment.java @@ -1,6 +1,8 @@ package taa.assessment; public class Assessment { + public static final double[] WEIGHTAGE_RANGE = {0, 100}; + private String name; private double weightage; @@ -26,6 +28,6 @@ public double getWeightage() { */ @Override public String toString() { - return String.format("%s (%.1f%%)", name, weightage); + return String.format("%s (%,.2f%%)", name, weightage); } } diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 3f31b667a7..4aafc16251 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -3,7 +3,7 @@ import java.util.ArrayList; public class AssessmentList { - private static final double MAX_ASSESSMENT_WEIGHTAGE = 100; + private static final String MESSAGE_ASSESSMENT_LIST_HEADER = "Assessment List:"; private final ArrayList assessments; @@ -20,10 +20,6 @@ public AssessmentList() { * @return tue if success, else false. */ public boolean addAssessment(Assessment assessment) { - if (assessment.getWeightage() > MAX_ASSESSMENT_WEIGHTAGE) { - return false; - } - double totalWeightage = 0; for (Assessment a : assessments) { if (a.getName().equalsIgnoreCase(assessment.getName())) { @@ -31,7 +27,7 @@ public boolean addAssessment(Assessment assessment) { } } - if ((totalWeightage + assessment.getWeightage()) > MAX_ASSESSMENT_WEIGHTAGE) { + if ((totalWeightage + assessment.getWeightage()) > Assessment.WEIGHTAGE_RANGE[1]) { return false; } @@ -69,4 +65,17 @@ public ArrayList getAssessments() { public int getSize() { return assessments.size(); } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(MESSAGE_ASSESSMENT_LIST_HEADER); + for (int i = 0; i < assessments.size(); i += 1) { + stringBuilder.append("\n"); + stringBuilder.append(i + 1); + stringBuilder.append(". "); + stringBuilder.append(assessments.get(i)); + } + + return stringBuilder.toString(); + } } diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 9a8f3c3a99..046aa6c636 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -2,6 +2,7 @@ import taa.Ui; import taa.assessment.Assessment; +import taa.assessment.AssessmentList; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; @@ -14,10 +15,11 @@ public class AddAssessmentCommand extends Command { private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME, KEY_WEIGHTAGE}; private static final String MESSAGE_FAIL_TO_ADD = "Fail to add assessment."; - private static final String MESSAGE_INVALID_WEIGHTAGE = "Invalid weightage."; private static final String MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE = "Usage: %s " + "%s/ %s/ %s/"; + private static final String MESSAGE_FORMAT_INVALID_WEIGHTAGE = "Invalid weightage. " + + "Weightage must be between %,.2f and %,.2f (inclusive)"; private static final String MESSAGE_FORMAT_ASSESSMENT_ADDED = "Assessment added:\n %s\nThere are %d assessments in the %s."; @@ -50,19 +52,33 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { String weightageString = argumentMap.get(KEY_WEIGHTAGE); if (!Util.isStringDouble(weightageString)) { - throw new TaaException(MESSAGE_INVALID_WEIGHTAGE); + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) + ); } - double assessmentWeightage = Double.parseDouble(weightageString); - String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); - Assessment assessment = new Assessment(assessmentName, assessmentWeightage); - boolean isSuccessful = module.addAssessment(assessment); + double weightage = Double.parseDouble(weightageString); + if (weightage < Assessment.WEIGHTAGE_RANGE[0] || weightage > Assessment.WEIGHTAGE_RANGE[1]) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) + ); + } + + String name = argumentMap.get(KEY_ASSESSMENT_NAME); + Assessment assessment = new Assessment(name, weightage); + + AssessmentList assessmentList = module.getAssessmentList(); + boolean isSuccessful = assessmentList.addAssessment(assessment); if (!isSuccessful) { throw new TaaException(MESSAGE_FAIL_TO_ADD); } ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_ADDED, - assessment, module.getAssessmentsCount(), module)); + assessment, assessmentList.getSize(), module)); } @Override diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index 22d86e5cf5..9347512599 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -1,18 +1,15 @@ package taa.command; import taa.Ui; -import taa.assessment.Assessment; +import taa.assessment.AssessmentList; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; -import java.util.ArrayList; - public class ListAssessmentsCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String[] LIST_ASSESSMENTS_ARGUMENT_KEYS = {KEY_MODULE_CODE}; - private static final String MESSAGE_ASSESSMENT_LIST_HEADER = "Assessment List:"; private static final String MESSAGE_LIST_EMPTY = "There are no assessments in the module."; private static final String MESSAGE_FORMAT_LIST_ASSESSMENTS_USAGE = "Usage: %s %s/"; @@ -44,21 +41,13 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - ArrayList assessments = module.getAssessments(); - if (assessments.isEmpty()) { + AssessmentList assessmentList = module.getAssessmentList(); + if (assessmentList.getSize() == 0) { ui.printMessage(MESSAGE_LIST_EMPTY); return; } - StringBuilder stringBuilder = new StringBuilder(MESSAGE_ASSESSMENT_LIST_HEADER); - for (int i = 0; i < assessments.size(); i += 1) { - stringBuilder.append("\n"); - stringBuilder.append(i + 1); - stringBuilder.append(". "); - stringBuilder.append(assessments.get(i)); - } - - ui.printMessage(stringBuilder.toString()); + ui.printMessage(assessmentList.toString()); } @Override From 63cbca947f81d2f4d5b21c6ce72c38754cec60df Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 11 Oct 2021 19:42:26 +0800 Subject: [PATCH 079/543] Refactor to use StudentList class --- .../java/taa/command/AverageMarksCommand.java | 73 ++++++++-------- .../java/taa/command/ListMarksCommand.java | 85 ++++++++++--------- .../java/taa/command/SetMarksCommand.java | 79 ++++++++++------- 3 files changed, 135 insertions(+), 102 deletions(-) diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index 420b82692c..d01ff0b752 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -7,6 +7,7 @@ import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; +import taa.student.StudentList; /** * Class that deals with the outputting of the average marks. @@ -14,14 +15,12 @@ public class AverageMarksCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_ASSESSMENT_NAME = "a"; - private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME - }; + private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; + private static final String MESSAGE_FORMAT_AVERAGE_MARKS_USAGE = "Usage: %s " + "%s/ %s/"; - private static final String MESSAGE_AVERAGE_MARKS_FORMAT = "Average marks for %s is %,.4f"; - private static final String MESSAGE_AVERAGE_MARKS_WITH_UNMARKED_FORMAT = "Average marks for %s is %,.4f\n" + private static final String MESSAGE_FORMAT_AVERAGE_MARKS = "Average marks for %s is %,.2f"; + private static final String MESSAGE_FORMAT_AVERAGE_MARKS_WITH_UNMARKED = "Average marks for %s is %,.2f\n" + "Note that %d student(s) have yet to be marked!"; public AverageMarksCommand(String argument) { @@ -41,6 +40,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } + if (!checkArgumentMap()) { throw new TaaException(getMissingArgumentMessage()); } @@ -50,58 +50,63 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - if (module.getNumberOfStudents() <= 0) { - //TODO no students in assessment message - throw new TaaException("No students taking this assessment!"); + + StudentList studentList = module.getStudentList(); + if (studentList.getSize() <= 0) { + throw new TaaException(MESSAGE_NO_STUDENTS); } - AssessmentList list = module.getAssessmentList(); - Assessment assessment = list.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); + AssessmentList assessmentList = module.getAssessmentList(); + Assessment assessment = assessmentList.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { - //TODO no such assessment message - throw new TaaException("Assessment does not exist!"); + throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } - averageMarks(ui, module); - } - - /** - * Returns the usage message of the average marks command. - * @return String which contains the usage message. - */ - @Override - protected String getUsageMessage() { - return String.format( - MESSAGE_FORMAT_AVERAGE_MARKS_USAGE, - COMMAND_AVERAGE_MARKS, - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME - ); + printAverageMarks(ui, module, assessment); } /** * Outputs the average marks of an assessment in a module. + * * @param ui The ui instance to handle interactions with the user. * @param module The module the assessment belongs to. */ - private void averageMarks(Ui ui, Module module) { - String assessmentName = argumentMap.get("a"); - double classSize = module.getNumberOfStudents(); + private void printAverageMarks(Ui ui, Module module, Assessment assessment) { + StudentList studentList = module.getStudentList(); + String assessmentName = assessment.getName(); + + double classSize = studentList.getSize(); double totalMarks = 0; int unmarkedStudents = 0; - for (Student student : module.getStudents()) { + for (Student student : studentList.getStudents()) { if (student.marksExist(assessmentName)) { totalMarks += student.getMarks(assessmentName); } else { unmarkedStudents += 1; } } + double averageMarks = totalMarks / classSize; if (unmarkedStudents <= 0) { - ui.printMessage(String.format(MESSAGE_AVERAGE_MARKS_FORMAT, assessmentName, averageMarks)); + ui.printMessage(String.format(MESSAGE_FORMAT_AVERAGE_MARKS, assessmentName, averageMarks)); } else { - ui.printMessage(String.format(MESSAGE_AVERAGE_MARKS_WITH_UNMARKED_FORMAT, + ui.printMessage(String.format(MESSAGE_FORMAT_AVERAGE_MARKS_WITH_UNMARKED, assessmentName, averageMarks, unmarkedStudents)); } } + + /** + * Returns the usage message of the average marks command. + * + * @return String which contains the usage message. + */ + @Override + protected String getUsageMessage() { + return String.format( + MESSAGE_FORMAT_AVERAGE_MARKS_USAGE, + COMMAND_AVERAGE_MARKS, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME + ); + } } diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index 3c71a1a809..b15f1ef518 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -7,6 +7,7 @@ import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; +import taa.student.StudentList; /** * Class that deals with the command for the listing of marks. @@ -18,18 +19,21 @@ public class ListMarksCommand extends Command { KEY_MODULE_CODE, KEY_ASSESSMENT_NAME }; - private static final String MESSAGE_FORMAT_LIST_MARKS_USAGE = "Usage: %s " - + "%s/ %s/"; + private static final String MESSAGE_LIST_MARKS_HEADER = "Here is the list of students and " + "their marks for %s:"; private static final String MARKS_LIST_EMPTY = "There are no marks inputted!"; + private static final String MESSAGE_FORMAT_LIST_MARKS_USAGE = "Usage: %s " + + "%s/ %s/"; + public ListMarksCommand(String argument) { super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); } /** * Returns a string with the student name and the marks associated with the student. + * * @param studentName Name of the student. * @param marks Marks of the student. * @return String with the name and marks of the student separated with a vertical line. @@ -60,33 +64,19 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - if (module.getNumberOfStudents() <= 0) { - //TODO no students in assessment message - throw new TaaException("No students to list!"); + + StudentList studentList = module.getStudentList(); + if (studentList.getSize() <= 0) { + throw new TaaException(MESSAGE_NO_STUDENTS); } - AssessmentList list = module.getAssessmentList(); - Assessment assessment = list.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); + AssessmentList assessmentList = module.getAssessmentList(); + Assessment assessment = assessmentList.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { - // TODO no such assessment message - throw new TaaException("Assessment does not exist!"); + throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } - listMarks(ui, module); - } - - /** - * Returns the usage message of the list marks command. - * @return String which contains the usage message. - */ - @Override - protected String getUsageMessage() { - return String.format( - MESSAGE_FORMAT_LIST_MARKS_USAGE, - COMMAND_LIST_MARKS, - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME - ); + listMarks(ui, module, assessment); } /** @@ -95,30 +85,47 @@ protected String getUsageMessage() { * @param ui The ui instance to handle interactions with the user. * @param module The module that the student and assessment belong to. */ - private void listMarks(Ui ui, Module module) { - String assessmentName = argumentMap.get("a"); - StringBuilder marksList = new StringBuilder(String.format(MESSAGE_LIST_MARKS_HEADER, assessmentName)); + private void listMarks(Ui ui, Module module, Assessment assessment) { + StudentList studentList = module.getStudentList(); + String assessmentName = assessment.getName(); + + StringBuilder stringBuilder = new StringBuilder(String.format(MESSAGE_LIST_MARKS_HEADER, assessmentName)); int studentIndex = 0; - for (Student student : module.getStudents()) { + for (Student student : studentList.getStudents()) { studentIndex += 1; if (student.marksExist(assessmentName)) { - marksList.append("\n"); - marksList.append(studentIndex); - marksList.append(". "); - marksList.append(marksToString(student.getName(), student.getMarks(assessmentName))); + stringBuilder.append("\n"); + stringBuilder.append(studentIndex); + stringBuilder.append(". "); + stringBuilder.append(marksToString(student.getName(), student.getMarks(assessmentName))); } else { - marksList.append("\n"); - marksList.append(studentIndex); - marksList.append(". "); - marksList.append(student.getName()); - marksList.append(" | "); - marksList.append("Marks not added."); + stringBuilder.append("\n"); + stringBuilder.append(studentIndex); + stringBuilder.append(". "); + stringBuilder.append(student.getName()); + stringBuilder.append(" | "); + stringBuilder.append("NIL"); } } if (studentIndex <= 0) { ui.printMessage(MARKS_LIST_EMPTY); } else { - ui.printMessage(marksList.toString()); + ui.printMessage(stringBuilder.toString()); } } + + /** + * Returns the usage message of the list marks command. + * + * @return String which contains the usage message. + */ + @Override + protected String getUsageMessage() { + return String.format( + MESSAGE_FORMAT_LIST_MARKS_USAGE, + COMMAND_LIST_MARKS, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME + ); + } } diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index f165c23c81..23ab561d58 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -8,6 +8,8 @@ import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; +import taa.student.StudentList; +import taa.util.Util; /** * Class that deals with the command for the setting of marks. @@ -23,9 +25,14 @@ public class SetMarksCommand extends Command { KEY_ASSESSMENT_NAME, KEY_MARKS }; + + private static final double[] MARKS_RANGE = {0, 100}; + private static final String MESSAGE_FORMAT_SET_MARKS_USAGE = "Usage: %s " + "%s/ %s/ %s/ %s/"; - private static final String MESSAGE_MARKS_ADDED_FORMAT = "Marks set for %s: %,.4f for %s"; + private static final String MESSAGE_FORMAT_INVALID_MARKS = "Invalid Marks. " + + "Marks must be between %,.2f and %,.2f (inclusive)"; + private static final String MESSAGE_FORMAT_MARKS_ADDED = "Marks set for %s: %,.2f for %s"; public SetMarksCommand(String argument) { super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); @@ -53,23 +60,53 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - int studentIndex = Integer.parseInt(argumentMap.get(KEY_STUDENT_INDEX)); - if ((studentIndex > module.getNumberOfStudents()) || (studentIndex <= 0)) { - // TODO non-existent student error message - throw new TaaException("No such student!"); + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + int studentIndex = Integer.parseInt(studentIndexInput) - 1; + + StudentList studentList = module.getStudentList(); + Student student = studentList.getStudentAt(studentIndex); + if (student == null) { + ui.printMessage(MESSAGE_INVALID_STUDENT_INDEX); + return; } - AssessmentList list = module.getAssessmentList(); - Assessment assessment = list.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); + AssessmentList assessmentList = module.getAssessmentList(); + String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); + Assessment assessment = assessmentList.getAssessment(assessmentName); if (assessment == null) { - // TODO non-existent assessment error message - throw new TaaException("Assessment does not exist!"); + throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); + } + + String marksInput = argumentMap.get(KEY_MARKS); + if (!Util.isStringDouble(marksInput)) { + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, MARKS_RANGE[0], MARKS_RANGE[1])); } - if (Double.parseDouble(argumentMap.get(KEY_MARKS)) < 0) { - // TODO marks are negative - throw new TaaException("Marks cannot be negative!"); + + double marks = Double.parseDouble(marksInput); + if (marks < MARKS_RANGE[0] || marks > MARKS_RANGE[1]) { + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, MARKS_RANGE[0], MARKS_RANGE[1])); } - setMarks(ui, module, studentIndex); + + setMarks(ui, student, assessment, marks); + } + + /** + * Sets the marks for a student's assessment. + * + * @param ui The ui instance to handle interactions with the user. + * @param student The student instance to set the mark for. + * @param assessment The assessment instance. + * @param marks The marks to set for the assessment. + */ + private void setMarks(Ui ui, Student student, Assessment assessment, double marks) { + String assessmentName = assessment.getName(); + + student.setMarks(assessmentName, marks); + String studentName = student.getName(); + ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_ADDED, studentName, marks, assessmentName)); } /** @@ -87,20 +124,4 @@ protected String getUsageMessage() { KEY_MARKS ); } - - /** - * Sets the marks for a student's assessment. - * - * @param ui The ui instance to handle interactions with the user. - * @param module The module the assessment and student belong to. - * @param studentIndex Index of the student. - */ - private void setMarks(Ui ui, Module module, int studentIndex) { - String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); - double marks = Double.parseDouble(argumentMap.get(KEY_MARKS)); - Student student = module.getStudent(studentIndex - 1); - student.setMarks(assessmentName, marks); - String studentName = student.getName(); - ui.printMessage(String.format(MESSAGE_MARKS_ADDED_FORMAT, studentName, marks, assessmentName)); - } } From bbee07a81adcf92add35209149dcc83fcc1cd9e7 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 11 Oct 2021 22:50:38 +0800 Subject: [PATCH 080/543] Add constructor for StudentList class --- src/main/java/taa/student/StudentList.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index 366d6e1c3f..c0e61b1ad2 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -7,6 +7,10 @@ public class StudentList { private ArrayList students; + public StudentList() { + this.students = new ArrayList<>(); + } + /** * Gets a list of students in the ArrayList. Note that this returns a new ArrayList instance. * From 4c6281e54984e22050d0929c08dc38658e70fba8 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Mon, 11 Oct 2021 23:42:00 +0800 Subject: [PATCH 081/543] add assertion for edit and delete student command --- src/main/java/taa/command/DeleteStudentCommand.java | 4 ++++ src/main/java/taa/command/EditStudentCommand.java | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 6aea535ace..ccfe340c42 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -51,6 +51,10 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { int studentIndex = Integer.parseInt(studentIndexInput) - 1; StudentList studentList = module.getStudentList(); + if (studentIndex < 0 || studentIndex >= studentList.getSize()) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + assert studentIndex < module.getStudentList().getSize(); Student student = studentList.deleteStudent(studentIndex); if (student == null) { ui.printMessage(MESSAGE_INVALID_STUDENT_INDEX); diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index c4ce97c060..cfc6f84cf7 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -55,9 +55,14 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { if (!Util.isStringInteger(studentIndexInput)) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } + int studentIndex = Integer.parseInt(studentIndexInput) - 1; StudentList studentList = module.getStudentList(); + if (studentIndex < 0 || studentIndex >= studentList.getSize()) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + assert studentIndex < module.getStudentList().getSize(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { ui.printMessage(MESSAGE_INVALID_STUDENT_INDEX); From 89db41f4159da670d5d1937f17c83e4c92193d25 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 11 Oct 2021 23:55:26 +0800 Subject: [PATCH 082/543] Add Storage class to handle data saving and loading --- .gitignore | 1 + build.gradle | 2 + src/main/java/taa/Storage.java | 67 ++++++++++++++++++++++++++++++++ src/main/java/taa/Taa.java | 27 +++++++++++-- src/main/java/taa/util/Util.java | 65 +++++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 3 deletions(-) create mode 100644 src/main/java/taa/Storage.java diff --git a/.gitignore b/.gitignore index 789d235f52..ed6661e30c 100644 --- a/.gitignore +++ b/.gitignore @@ -17,3 +17,4 @@ text-ui-test/EXPECTED-UNIX.TXT text-ui-test/ACTUAL.TXT .classpath .project +data/taa_data.json diff --git a/build.gradle b/build.gradle index a15eb244c1..1e4ffc3e92 100644 --- a/build.gradle +++ b/build.gradle @@ -10,6 +10,7 @@ repositories { } dependencies { + implementation 'com.google.code.gson:gson:2.8.8' testImplementation group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.5.0' testRuntimeOnly group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.5.0' } @@ -43,4 +44,5 @@ checkstyle { run{ standardInput = System.in + enableAssertions = true } diff --git a/src/main/java/taa/Storage.java b/src/main/java/taa/Storage.java new file mode 100644 index 0000000000..21ce7294ab --- /dev/null +++ b/src/main/java/taa/Storage.java @@ -0,0 +1,67 @@ +package taa; + +import com.google.gson.Gson; +import com.google.gson.JsonIOException; +import com.google.gson.JsonSyntaxException; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; +import taa.exception.TaaException; +import taa.module.ModuleList; +import taa.util.Util; + +import java.io.FileNotFoundException; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; + +public class Storage { + private static final String MESSAGE_FORMAT_UNABLE_TO_OPEN_FILE = "Unable to open file - %s"; + private static final String MESSAGE_FORMAT_UNABLE_TO_READ_JSON = "Unable to read from JSON file - %s"; + private static final String MESSAGE_FORMAT_UNABLE_TO_WRITE_JSON = "Unable to write to JSON file - %s"; + private static final String MESSAGE_FORMAT_JSON_SYNTAX_ERROR = "JSON file syntax error - %s"; + + private final String filename; + + public Storage(String filename) { + this.filename = filename; + } + + public ModuleList load() throws TaaException { + if (!Util.fileExists(filename)) { + return null; + } + + ModuleList moduleList; + Gson gson = new Gson(); + try { + FileReader fileReader = new FileReader(filename); + JsonReader jsonReader = new JsonReader(fileReader); + moduleList = gson.fromJson(jsonReader, ModuleList.class); + jsonReader.close(); + } catch (FileNotFoundException e) { + throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_FILE, filename)); + } catch (JsonIOException | IOException e) { + throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_READ_JSON, filename)); + } catch (JsonSyntaxException e) { + throw new TaaException(String.format(MESSAGE_FORMAT_JSON_SYNTAX_ERROR, filename)); + } + + return moduleList; + } + + public void save(ModuleList moduleList) throws TaaException { + Util.createFile(filename); + + Gson gson = new Gson(); + try { + FileWriter fileWriter = new FileWriter(filename); + JsonWriter jsonWriter = new JsonWriter(fileWriter); + gson.toJson(moduleList, ModuleList.class, jsonWriter); + jsonWriter.close(); + } catch (IOException e) { + throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_FILE, filename)); + } catch (JsonIOException e) { + throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_WRITE_JSON, filename)); + } + } +} diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index c04341c8ad..d2088926e5 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -5,15 +5,21 @@ import taa.module.ModuleList; public class Taa { - private final ModuleList moduleList; + private static final String DATA_FILENAME = "./data/taa_data.json"; + + private ModuleList moduleList; private final Ui ui; + private final Storage storage; public Taa() { - this.moduleList = new ModuleList(); this.ui = new Ui(); + this.storage = new Storage(DATA_FILENAME); } public void run() { + loadModuleListFromStorage(); + assert moduleList != null; + ui.printWelcomeMessage(); boolean isExit = false; @@ -22,7 +28,7 @@ public void run() { try { Command command = Parser.parseUserInput(userInput); - command.execute(moduleList, ui); + command.execute(moduleList, ui, storage); isExit = command.isExit(); } catch (TaaException e) { ui.printException(e.getMessage()); @@ -30,6 +36,21 @@ public void run() { } while (!isExit); } + private void loadModuleListFromStorage() { + ModuleList savedModuleList = null; + try { + savedModuleList = storage.load(); + } catch (TaaException e) { + ui.printException(e.getMessage()); + } + + if (savedModuleList == null) { + moduleList = new ModuleList(); + } else { + moduleList = savedModuleList; + } + } + /** * Main entry-point for the java.duke.Duke application. */ diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java index 8fe79fb19e..a5d286f6c1 100644 --- a/src/main/java/taa/util/Util.java +++ b/src/main/java/taa/util/Util.java @@ -1,5 +1,12 @@ package taa.util; +import java.io.IOException; +import java.nio.file.FileSystems; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; + public class Util { public static boolean isStringInteger(String string) { boolean isInt; @@ -24,4 +31,62 @@ public static boolean isStringDouble(String string) { return isDouble; } + + /** + * Gets the Path object from filename. + * + * @param filename The filename. + * @return A Path object. + */ + public static Path getPathFromFilename(String filename) { + String separator = FileSystems.getDefault().getSeparator(); + String[] filenameSplit = filename.split(separator.replace("\\", "\\\\")); + + String firstPathString = filenameSplit[0]; + Path path; + if (filenameSplit.length > 1) { + String[] additionalPathStrings = Arrays.copyOfRange(filenameSplit, 1, filenameSplit.length - 1); + path = Paths.get(firstPathString, additionalPathStrings); + } else { + path = Paths.get(firstPathString); + } + + return path; + } + + /** + * Checks if file exists. + * + * @param filename The file to check. + * @return true if exists, else false. + */ + public static boolean fileExists(String filename) { + Path path = getPathFromFilename(filename); + + return Files.exists(path); + } + + /** + * Creates a file and parent directories (if necessary). + * + * @param filename The file to create. + * @return true if file already exists or successfully created, else false. + */ + public static boolean createFile(String filename) { + if (fileExists(filename)) { + return true; + } + + Path path = getPathFromFilename(filename); + Path parentPath = path.getParent(); + + try { + Files.createDirectories(parentPath); + Files.createFile(path); + } catch (IOException e) { + return false; + } + + return true; + } } From 67ea7a16905a69e6edb0de67eb6aa2238f7cbb51 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 11 Oct 2021 23:56:32 +0800 Subject: [PATCH 083/543] Add storage instance as parameter and save data for certain commands --- src/main/java/taa/command/AddAssessmentCommand.java | 6 +++++- src/main/java/taa/command/AddModuleCommand.java | 5 ++++- src/main/java/taa/command/AddStudentCommand.java | 6 +++++- src/main/java/taa/command/AverageMarksCommand.java | 4 +++- src/main/java/taa/command/Command.java | 3 ++- src/main/java/taa/command/DeleteStudentCommand.java | 6 +++++- src/main/java/taa/command/EditStudentCommand.java | 6 +++++- src/main/java/taa/command/ExitCommand.java | 3 ++- src/main/java/taa/command/FindStudentCommand.java | 4 +++- src/main/java/taa/command/ListAssessmentsCommand.java | 4 +++- src/main/java/taa/command/ListMarksCommand.java | 4 +++- src/main/java/taa/command/ListModulesCommand.java | 3 ++- src/main/java/taa/command/ListStudentsCommand.java | 4 +++- src/main/java/taa/command/SetMarksCommand.java | 6 +++++- 14 files changed, 50 insertions(+), 14 deletions(-) diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 046aa6c636..a9f7d0776e 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; @@ -32,10 +33,11 @@ public AddAssessmentCommand(String argument) { * * @param moduleList The list of modules. * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command. */ @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -77,6 +79,8 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(MESSAGE_FAIL_TO_ADD); } + storage.save(moduleList); + ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_ADDED, assessment, assessmentList.getSize(), module)); } diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index f8da9cb44d..26dec3e553 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.ModuleList; @@ -21,7 +22,7 @@ public AddModuleCommand(String argument) { } @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -39,6 +40,8 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { Module module = new Module(moduleCode, name); moduleList.addModule(module); + storage.save(moduleList); + ui.printMessage(String.format(MESSAGE_FORMAT_MODULE_ADDED, module, moduleList.getSize())); } diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index afad77d797..a104bbf6f4 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.Module; @@ -26,10 +27,11 @@ public AddStudentCommand(String argument) { * * @param moduleList The list of modules * @param ui The ui instance to handle interactions with the user + * @param storage * @throws TaaException If the user inputs an invalid command */ @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -51,6 +53,8 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { StudentList studentList = module.getStudentList(); studentList.addStudent(student); + storage.save(moduleList); + ui.printMessage(String.format(MESSAGE_STUDENT_ADDED_FORMAT, moduleCode, student)); } diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index d01ff0b752..577301d4ab 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.assessment.Assessment; import taa.exception.TaaException; import taa.Ui; @@ -33,10 +34,11 @@ public AverageMarksCommand(String argument) { * * @param moduleList List of modules. * @param ui The ui instance to handle interactions with the user. + * @param storage * @throws TaaException When average marks command is invalid. */ @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 43d9affd16..083efa7776 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.exception.TaaException; import taa.Parser; import taa.Ui; @@ -53,7 +54,7 @@ public boolean isExit() { return isExit; } - public abstract void execute(ModuleList moduleList, Ui ui) throws TaaException; + public abstract void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException; protected abstract String getUsageMessage(); diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 6aea535ace..61bdfd6942 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.Module; @@ -26,10 +27,11 @@ public DeleteStudentCommand(String argument) { * * @param moduleList The list of modules * @param ui The ui instance to handle interactions with the user + * @param storage * @throws TaaException If the user inputs an invalid command */ @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -56,6 +58,8 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { ui.printMessage(MESSAGE_INVALID_STUDENT_INDEX); } + storage.save(moduleList); + ui.printMessage(String.format(MESSAGE_FORMAT_STUDENT_DELETED, moduleCode, student)); } diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index c4ce97c060..4f7fe3a87a 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.Module; @@ -33,10 +34,11 @@ public EditStudentCommand(String argument) { * * @param moduleList The list of modules * @param ui The ui instance to handle interactions with the user + * @param storage * @throws TaaException If the user inputs an invalid command */ @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -69,6 +71,8 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { student.setId(newId); student.setName(newName); + storage.save(moduleList); + ui.printMessage(String.format(MESSAGE_FORMAT_STUDENT_EDITED, student)); } diff --git a/src/main/java/taa/command/ExitCommand.java b/src/main/java/taa/command/ExitCommand.java index 912c3b7085..d0b63e521d 100644 --- a/src/main/java/taa/command/ExitCommand.java +++ b/src/main/java/taa/command/ExitCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.ModuleList; @@ -12,7 +13,7 @@ public ExitCommand(String argument) { } @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (!argument.isEmpty()) { throw new TaaException(getUsageMessage()); } diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 3959c70d42..eadf1131cb 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.Module; @@ -29,10 +30,11 @@ public FindStudentCommand(String argument) { * * @param moduleList The list of modules * @param ui The ui instance to handle interactions with the user + * @param storage * @throws TaaException If the user inputs an invalid command */ @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index 9347512599..c4be1870cd 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.Ui; import taa.assessment.AssessmentList; import taa.exception.TaaException; @@ -23,10 +24,11 @@ public ListAssessmentsCommand(String argument) { * * @param moduleList The list of modules. * @param ui The ui instance to handle interactions with the user. + * @param storage * @throws TaaException If the user inputs an invalid command. */ @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index b15f1ef518..6c761a1590 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; @@ -48,10 +49,11 @@ public String marksToString(String studentName, double marks) { * * @param moduleList List of modules. * @param ui The ui instance to handle interactions with the user. + * @param storage * @throws TaaException When list marks command is invalid. */ @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } diff --git a/src/main/java/taa/command/ListModulesCommand.java b/src/main/java/taa/command/ListModulesCommand.java index 981b1f7626..9aa010217d 100644 --- a/src/main/java/taa/command/ListModulesCommand.java +++ b/src/main/java/taa/command/ListModulesCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.ModuleList; @@ -12,7 +13,7 @@ public ListModulesCommand(String argument) { } @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (!argument.isEmpty()) { throw new TaaException(getUsageMessage()); } diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index b44aba896f..7f3710af56 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.Module; @@ -24,10 +25,11 @@ public ListStudentsCommand(String argument) { * * @param moduleList The list of modules * @param ui The ui instance to handle interactions with the user + * @param storage * @throws TaaException If the user inputs an invalid command */ @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 23ab561d58..bd3a9bba2a 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -1,6 +1,7 @@ package taa.command; +import taa.Storage; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; @@ -43,10 +44,11 @@ public SetMarksCommand(String argument) { * * @param moduleList Module list to access the module the student is enrolled in. * @param ui The ui instance to handle interactions with the user. + * @param storage * @throws TaaException when set marks command is invalid. */ @Override - public void execute(ModuleList moduleList, Ui ui) throws TaaException { + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -91,6 +93,8 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { } setMarks(ui, student, assessment, marks); + + storage.save(moduleList); } /** From 121570fc364ee9a154d29b83a7f34a0138b16009 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 11 Oct 2021 23:57:28 +0800 Subject: [PATCH 084/543] Ignore data file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ed6661e30c..c7d178e0bc 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ text-ui-test/ACTUAL.TXT .classpath .project data/taa_data.json +text-ui-test/data/taa_data.json From 1abba1cf3207bc16f6439f8e377585a8f7c92e0b Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 00:47:37 +0800 Subject: [PATCH 085/543] Add checks for classes after reading from file --- src/main/java/taa/ClassChecker.java | 5 +++ src/main/java/taa/Storage.java | 6 +++ src/main/java/taa/assessment/Assessment.java | 23 ++++++++++- .../java/taa/assessment/AssessmentList.java | 31 ++++++++------ .../taa/command/AddAssessmentCommand.java | 12 +++--- .../java/taa/command/SetMarksCommand.java | 13 +++--- src/main/java/taa/module/Module.java | 26 +++++++++--- src/main/java/taa/module/ModuleList.java | 19 +++++++-- src/main/java/taa/student/Attendance.java | 13 +++++- src/main/java/taa/student/Student.java | 40 ++++++++++++++++--- src/main/java/taa/student/StudentList.java | 17 ++++++-- 11 files changed, 160 insertions(+), 45 deletions(-) create mode 100644 src/main/java/taa/ClassChecker.java diff --git a/src/main/java/taa/ClassChecker.java b/src/main/java/taa/ClassChecker.java new file mode 100644 index 0000000000..349afb163c --- /dev/null +++ b/src/main/java/taa/ClassChecker.java @@ -0,0 +1,5 @@ +package taa; + +public interface ClassChecker { + public abstract boolean verify(); +} diff --git a/src/main/java/taa/Storage.java b/src/main/java/taa/Storage.java index 21ce7294ab..344f1461b9 100644 --- a/src/main/java/taa/Storage.java +++ b/src/main/java/taa/Storage.java @@ -6,6 +6,7 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import taa.exception.TaaException; +import taa.module.Module; import taa.module.ModuleList; import taa.util.Util; @@ -13,6 +14,7 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.util.ArrayList; public class Storage { private static final String MESSAGE_FORMAT_UNABLE_TO_OPEN_FILE = "Unable to open file - %s"; @@ -46,6 +48,10 @@ public ModuleList load() throws TaaException { throw new TaaException(String.format(MESSAGE_FORMAT_JSON_SYNTAX_ERROR, filename)); } + if (!moduleList.verify()) { + moduleList = null; + } + return moduleList; } diff --git a/src/main/java/taa/assessment/Assessment.java b/src/main/java/taa/assessment/Assessment.java index 414d5ffded..342b8dac6a 100644 --- a/src/main/java/taa/assessment/Assessment.java +++ b/src/main/java/taa/assessment/Assessment.java @@ -1,7 +1,9 @@ package taa.assessment; -public class Assessment { - public static final double[] WEIGHTAGE_RANGE = {0, 100}; +import taa.ClassChecker; + +public class Assessment implements ClassChecker { + private static final double[] WEIGHTAGE_RANGE = {0, 100}; private String name; private double weightage; @@ -11,6 +13,14 @@ public Assessment(String name, double weightage) { this.weightage = weightage; } + public static boolean isWeightageWithinRange(double weightage) { + return (weightage >= WEIGHTAGE_RANGE[0] && weightage <= WEIGHTAGE_RANGE[1]); + } + + public static double[] getWeightageRange() { + return WEIGHTAGE_RANGE; + } + public String getName() { return name; } @@ -30,4 +40,13 @@ public double getWeightage() { public String toString() { return String.format("%s (%,.2f%%)", name, weightage); } + + @Override + public boolean verify() { + if (name.isEmpty() || !isWeightageWithinRange(weightage)) { + return false; + } + + return true; + } } diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 4aafc16251..254bf7d748 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -1,14 +1,20 @@ package taa.assessment; +import taa.ClassChecker; + import java.util.ArrayList; -public class AssessmentList { +public class AssessmentList implements ClassChecker { private static final String MESSAGE_ASSESSMENT_LIST_HEADER = "Assessment List:"; - private final ArrayList assessments; + private final ArrayList assessments = new ArrayList<>(); + + public int getSize() { + return assessments.size(); + } - public AssessmentList() { - this.assessments = new ArrayList<>(); + public ArrayList getAssessments() { + return new ArrayList<>(assessments); } /** @@ -27,7 +33,7 @@ public boolean addAssessment(Assessment assessment) { } } - if ((totalWeightage + assessment.getWeightage()) > Assessment.WEIGHTAGE_RANGE[1]) { + if ((totalWeightage + assessment.getWeightage()) > Assessment.getWeightageRange()[1]) { return false; } @@ -58,14 +64,6 @@ public Assessment getAssessment(String assessmentName) { return null; } - public ArrayList getAssessments() { - return new ArrayList<>(assessments); - } - - public int getSize() { - return assessments.size(); - } - @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(MESSAGE_ASSESSMENT_LIST_HEADER); @@ -78,4 +76,11 @@ public String toString() { return stringBuilder.toString(); } + + @Override + public boolean verify() { + assessments.removeIf(assessment -> !assessment.verify()); + + return true; + } } diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index a9f7d0776e..afca6e56f3 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -54,19 +54,21 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc String weightageString = argumentMap.get(KEY_WEIGHTAGE); if (!Util.isStringDouble(weightageString)) { + double[] weightageRange = Assessment.getWeightageRange(); throw new TaaException(String.format( MESSAGE_FORMAT_INVALID_WEIGHTAGE, - Assessment.WEIGHTAGE_RANGE[0], - Assessment.WEIGHTAGE_RANGE[1]) + weightageRange[0], + weightageRange[1]) ); } double weightage = Double.parseDouble(weightageString); - if (weightage < Assessment.WEIGHTAGE_RANGE[0] || weightage > Assessment.WEIGHTAGE_RANGE[1]) { + if (!Assessment.isWeightageWithinRange(weightage)) { + double[] weightageRange = Assessment.getWeightageRange(); throw new TaaException(String.format( MESSAGE_FORMAT_INVALID_WEIGHTAGE, - Assessment.WEIGHTAGE_RANGE[0], - Assessment.WEIGHTAGE_RANGE[1]) + weightageRange[0], + weightageRange[1]) ); } diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index bd3a9bba2a..58bc470b49 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -1,6 +1,5 @@ package taa.command; - import taa.Storage; import taa.Ui; import taa.assessment.Assessment; @@ -27,8 +26,6 @@ public class SetMarksCommand extends Command { KEY_MARKS }; - private static final double[] MARKS_RANGE = {0, 100}; - private static final String MESSAGE_FORMAT_SET_MARKS_USAGE = "Usage: %s " + "%s/ %s/ %s/ %s/"; private static final String MESSAGE_FORMAT_INVALID_MARKS = "Invalid Marks. " @@ -44,7 +41,7 @@ public SetMarksCommand(String argument) { * * @param moduleList Module list to access the module the student is enrolled in. * @param ui The ui instance to handle interactions with the user. - * @param storage + * @param storage The storage instance to handle saving. * @throws TaaException when set marks command is invalid. */ @Override @@ -84,12 +81,14 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc String marksInput = argumentMap.get(KEY_MARKS); if (!Util.isStringDouble(marksInput)) { - throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, MARKS_RANGE[0], MARKS_RANGE[1])); + double[] marksRange = Student.getMarksRange(); + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, marksRange[0], marksRange[1])); } double marks = Double.parseDouble(marksInput); - if (marks < MARKS_RANGE[0] || marks > MARKS_RANGE[1]) { - throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, MARKS_RANGE[0], MARKS_RANGE[1])); + if (!Student.isMarksWithinRange(marks)) { + double[] marksRange = Student.getMarksRange(); + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, marksRange[0], marksRange[1])); } setMarks(ui, student, assessment, marks); diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index 990be89598..02dad65368 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -1,20 +1,19 @@ package taa.module; +import taa.ClassChecker; import taa.assessment.AssessmentList; import taa.student.StudentList; -public class Module { +public class Module implements ClassChecker { private String code; private String name; private int lessonCount; - private final StudentList studentList; - private final AssessmentList assessmentList; + private final StudentList studentList = new StudentList(); + private final AssessmentList assessmentList = new AssessmentList(); public Module(String code, String name) { this.code = code; this.name = name; - this.studentList = new StudentList(); - this.assessmentList = new AssessmentList(); } public String getCode() { @@ -49,4 +48,21 @@ public String toString() { return String.format("%s - %s", code, name); } + + @Override + public boolean verify() { + if (code.isEmpty() || name.isEmpty() || lessonCount < 0) { + return false; + } + + if (!studentList.verify()) { + return false; + } + + if (!assessmentList.verify()) { + return false; + } + + return true; + } } diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index ed24d8b370..e2fc09bdeb 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -1,14 +1,16 @@ package taa.module; +import taa.ClassChecker; + import java.util.ArrayList; -public class ModuleList { +public class ModuleList implements ClassChecker { private static final String MESSAGE_MODULE_LIST_HEADER = "Module List:"; - private final ArrayList modules; + private final ArrayList modules = new ArrayList<>(); public ModuleList() { - this.modules = new ArrayList<>(); + } public void addModule(Module module) { @@ -19,6 +21,10 @@ public int getSize() { return modules.size(); } + public ArrayList getModules() { + return new ArrayList<>(modules); + } + /** * Checks if an index is valid with respect to the modules list. * @@ -71,4 +77,11 @@ public String toString() { return stringBuilder.toString(); } + + @Override + public boolean verify() { + modules.removeIf(module -> !module.verify()); + + return true; + } } diff --git a/src/main/java/taa/student/Attendance.java b/src/main/java/taa/student/Attendance.java index d85c34e4f5..38dd868310 100644 --- a/src/main/java/taa/student/Attendance.java +++ b/src/main/java/taa/student/Attendance.java @@ -1,6 +1,8 @@ package taa.student; -public class Attendance { +import taa.ClassChecker; + +public class Attendance implements ClassChecker { private int lessonNum; private boolean hadAttend; @@ -17,4 +19,13 @@ public int markAttendance() { public String toString() { return lessonNum + " - " + markAttendance(); } + + @Override + public boolean verify() { + if (lessonNum < 0) { + return false; + } + + return true; + } } diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index 7b6a00c141..27a9034eff 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -1,22 +1,32 @@ package taa.student; +import taa.ClassChecker; + import java.util.ArrayList; import java.util.HashMap; /** * Represents students. */ -public class Student { +public class Student implements ClassChecker { + private static final double[] MARKS_RANGE = {0, 100}; + private String id; private String name; - private final ArrayList attendance; - private final HashMap results; + private final ArrayList attendances = new ArrayList<>(); + private final HashMap results = new HashMap<>(); public Student(String id, String name) { this.id = id; this.name = name; - this.attendance = new ArrayList<>(); - this.results = new HashMap<>(); + } + + public static boolean isMarksWithinRange(double marks) { + return (marks >= MARKS_RANGE[0] && marks <= MARKS_RANGE[1]); + } + + public static double[] getMarksRange() { + return MARKS_RANGE; } /** @@ -124,4 +134,24 @@ public boolean marksExist(String assessmentName) { return results.containsKey(assessmentName); } + @Override + public boolean verify() { + if (id.isEmpty() || name.isEmpty()) { + return false; + } + + for (Attendance attendance : attendances) { + if (!attendance.verify()) { + return false; + } + } + + for (String assessmentName : results.keySet()) { + if (!isMarksWithinRange(results.get(assessmentName))) { + return false; + } + } + + return true; + } } diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index c0e61b1ad2..efd9fd7668 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -1,14 +1,16 @@ package taa.student; +import taa.ClassChecker; + import java.util.ArrayList; -public class StudentList { - private static String MESSAGE_LIST_STUDENT_HEADER = "Student List:"; +public class StudentList implements ClassChecker { + private static final String MESSAGE_LIST_STUDENT_HEADER = "Student List:"; - private ArrayList students; + private final ArrayList students = new ArrayList<>(); public StudentList() { - this.students = new ArrayList<>(); + } /** @@ -83,4 +85,11 @@ public String toString() { return stringBuilder.toString(); } + + @Override + public boolean verify() { + students.removeIf(student -> !student.verify()); + + return true; + } } From fecc21e5388031a30a32ddbe4cd07c2e0e77bd14 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 00:52:58 +0800 Subject: [PATCH 086/543] Add comment to fix gradle --- src/main/java/taa/command/AddStudentCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index a104bbf6f4..6aafebd0de 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -27,7 +27,7 @@ public AddStudentCommand(String argument) { * * @param moduleList The list of modules * @param ui The ui instance to handle interactions with the user - * @param storage + * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command */ @Override From 9c6baaae850852dc42ae6c3b9ff0f38d4b2f1b19 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 00:57:14 +0800 Subject: [PATCH 087/543] Add more comments to fix checkstyle --- src/main/java/taa/command/AverageMarksCommand.java | 2 +- src/main/java/taa/command/DeleteStudentCommand.java | 2 +- src/main/java/taa/command/EditStudentCommand.java | 2 +- src/main/java/taa/command/FindStudentCommand.java | 2 +- src/main/java/taa/command/ListAssessmentsCommand.java | 2 +- src/main/java/taa/command/ListMarksCommand.java | 2 +- src/main/java/taa/command/ListStudentsCommand.java | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index 577301d4ab..25354e69f1 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -34,7 +34,7 @@ public AverageMarksCommand(String argument) { * * @param moduleList List of modules. * @param ui The ui instance to handle interactions with the user. - * @param storage + * @param storage The storage instance to handle saving. * @throws TaaException When average marks command is invalid. */ @Override diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 61bdfd6942..e3ace4509f 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -27,7 +27,7 @@ public DeleteStudentCommand(String argument) { * * @param moduleList The list of modules * @param ui The ui instance to handle interactions with the user - * @param storage + * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command */ @Override diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 4f7fe3a87a..3856a8579f 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -34,7 +34,7 @@ public EditStudentCommand(String argument) { * * @param moduleList The list of modules * @param ui The ui instance to handle interactions with the user - * @param storage + * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command */ @Override diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index eadf1131cb..74d456b5b2 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -30,7 +30,7 @@ public FindStudentCommand(String argument) { * * @param moduleList The list of modules * @param ui The ui instance to handle interactions with the user - * @param storage + * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command */ @Override diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index c4be1870cd..c2c6ce7b8f 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -24,7 +24,7 @@ public ListAssessmentsCommand(String argument) { * * @param moduleList The list of modules. * @param ui The ui instance to handle interactions with the user. - * @param storage + * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command. */ @Override diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index 6c761a1590..b008a188f3 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -49,7 +49,7 @@ public String marksToString(String studentName, double marks) { * * @param moduleList List of modules. * @param ui The ui instance to handle interactions with the user. - * @param storage + * @param storage The storage instance to handle saving. * @throws TaaException When list marks command is invalid. */ @Override diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index 7f3710af56..cbdc4d1a5d 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -25,7 +25,7 @@ public ListStudentsCommand(String argument) { * * @param moduleList The list of modules * @param ui The ui instance to handle interactions with the user - * @param storage + * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command */ @Override From 67787e501579a0ef1608a690555ebd2b5d296bdc Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 01:17:07 +0800 Subject: [PATCH 088/543] Disable saving for automatic test scripts --- src/main/java/taa/Storage.java | 16 ++++++++++++++-- src/main/java/taa/Taa.java | 26 +++++++++++++++++++++----- text-ui-test/runtest.bat | 2 +- text-ui-test/runtest.sh | 2 +- 4 files changed, 37 insertions(+), 9 deletions(-) diff --git a/src/main/java/taa/Storage.java b/src/main/java/taa/Storage.java index 344f1461b9..9073a7597c 100644 --- a/src/main/java/taa/Storage.java +++ b/src/main/java/taa/Storage.java @@ -6,7 +6,6 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import taa.exception.TaaException; -import taa.module.Module; import taa.module.ModuleList; import taa.util.Util; @@ -14,7 +13,6 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; -import java.util.ArrayList; public class Storage { private static final String MESSAGE_FORMAT_UNABLE_TO_OPEN_FILE = "Unable to open file - %s"; @@ -23,12 +21,22 @@ public class Storage { private static final String MESSAGE_FORMAT_JSON_SYNTAX_ERROR = "JSON file syntax error - %s"; private final String filename; + private boolean isEnabled; public Storage(String filename) { this.filename = filename; + this.isEnabled = true; + } + + public void setEnabled(boolean enabled) { + isEnabled = enabled; } public ModuleList load() throws TaaException { + if (!isEnabled) { + return null; + } + if (!Util.fileExists(filename)) { return null; } @@ -56,6 +64,10 @@ public ModuleList load() throws TaaException { } public void save(ModuleList moduleList) throws TaaException { + if (!isEnabled) { + return; + } + Util.createFile(filename); Gson gson = new Gson(); diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index d2088926e5..6f654a1dc1 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -8,12 +8,16 @@ public class Taa { private static final String DATA_FILENAME = "./data/taa_data.json"; private ModuleList moduleList; - private final Ui ui; - private final Storage storage; + private final Ui ui = new Ui(); + private final Storage storage = new Storage(DATA_FILENAME); public Taa() { - this.ui = new Ui(); - this.storage = new Storage(DATA_FILENAME); + + } + + public Taa(boolean enableSaving) { + this(); + storage.setEnabled(enableSaving); } public void run() { @@ -55,6 +59,18 @@ private void loadModuleListFromStorage() { * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - new Taa().run(); + Taa taa = null; + for (int i = 0; i < args.length && taa == null; i += 1) { + String arg = args[i]; + if (arg.equals("nosave")) { + taa = new Taa(false); + } + } + + if (taa == null) { + taa = new Taa(); + } + + taa.run(); } } diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 25ac7a2989..8e31139797 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -12,7 +12,7 @@ for /f "tokens=*" %%a in ( set jarloc=%%a ) -java -jar %jarloc% < ..\..\text-ui-test\input.txt > ..\..\text-ui-test\ACTUAL.TXT +java -jar %jarloc% nosave < ..\..\text-ui-test\input.txt > ..\..\text-ui-test\ACTUAL.TXT cd ..\..\text-ui-test diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh index 1dcbd12021..693fc5433b 100755 --- a/text-ui-test/runtest.sh +++ b/text-ui-test/runtest.sh @@ -8,7 +8,7 @@ cd .. cd text-ui-test -java -jar $(find ../build/libs/ -mindepth 1 -print -quit) < input.txt > ACTUAL.TXT +java -jar $(find ../build/libs/ -mindepth 1 -print -quit) nosave < input.txt > ACTUAL.TXT cp EXPECTED.TXT EXPECTED-UNIX.TXT dos2unix EXPECTED-UNIX.TXT ACTUAL.TXT From 35593b30763df4e87c8673e887f37960846d0276 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 02:21:26 +0800 Subject: [PATCH 089/543] Refactor isValidStudentIndex to isValidIndex in StudentList class --- src/main/java/taa/student/StudentList.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index efd9fd7668..78ac83415c 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -26,12 +26,12 @@ public int getSize() { return students.size(); } - private boolean isValidStudentIndex(int index) { + private boolean isValidIndex(int index) { return (index >= 0 && index < getSize()); } public Student getStudentAt(int index) { - if (isValidStudentIndex(index)) { + if (isValidIndex(index)) { return students.get(index); } @@ -49,7 +49,7 @@ public void addStudent(Student student) { * @return A Student object if successfully deleted, else null. */ public Student deleteStudent(int index) { - if (isValidStudentIndex(index)) { + if (isValidIndex(index)) { return students.remove(index); } From 0c928f64388effd36c3cda7eeaf4f41d11b7de48 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 02:22:49 +0800 Subject: [PATCH 090/543] Make public isValidIndex function in StudentList --- src/main/java/taa/student/StudentList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index 78ac83415c..1630251bbd 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -26,7 +26,7 @@ public int getSize() { return students.size(); } - private boolean isValidIndex(int index) { + public boolean isValidIndex(int index) { return (index >= 0 && index < getSize()); } From 942426ca8a5a897d61e60b602fffd2f0b4f16a3e Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 11:22:58 +0800 Subject: [PATCH 091/543] Handle data file creation failure --- src/main/java/taa/Storage.java | 5 ++++- src/main/java/taa/Taa.java | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/Storage.java b/src/main/java/taa/Storage.java index 9073a7597c..e005ecfe57 100644 --- a/src/main/java/taa/Storage.java +++ b/src/main/java/taa/Storage.java @@ -15,6 +15,7 @@ import java.io.IOException; public class Storage { + private static final String MESSAGE_FORMAT_FAIL_CREATE_FILE = "Fail to create file - %s"; private static final String MESSAGE_FORMAT_UNABLE_TO_OPEN_FILE = "Unable to open file - %s"; private static final String MESSAGE_FORMAT_UNABLE_TO_READ_JSON = "Unable to read from JSON file - %s"; private static final String MESSAGE_FORMAT_UNABLE_TO_WRITE_JSON = "Unable to write to JSON file - %s"; @@ -68,7 +69,9 @@ public void save(ModuleList moduleList) throws TaaException { return; } - Util.createFile(filename); + if (!Util.createFile(filename)) { + throw new TaaException(String.format(MESSAGE_FORMAT_FAIL_CREATE_FILE, filename)); + } Gson gson = new Gson(); try { diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index 6f654a1dc1..68c1e4e036 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -59,7 +59,7 @@ private void loadModuleListFromStorage() { * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - Taa taa = null; + /*Taa taa = null; for (int i = 0; i < args.length && taa == null; i += 1) { String arg = args[i]; if (arg.equals("nosave")) { @@ -69,8 +69,9 @@ public static void main(String[] args) { if (taa == null) { taa = new Taa(); - } + }*/ + Taa taa = new Taa(); taa.run(); } } From 28d37bb18542e10be417ad2b7a927064078c99ab Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 11:27:24 +0800 Subject: [PATCH 092/543] Use seperate exception messages for read and write --- src/main/java/taa/Storage.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/Storage.java b/src/main/java/taa/Storage.java index e005ecfe57..ddbe7ca23a 100644 --- a/src/main/java/taa/Storage.java +++ b/src/main/java/taa/Storage.java @@ -16,7 +16,8 @@ public class Storage { private static final String MESSAGE_FORMAT_FAIL_CREATE_FILE = "Fail to create file - %s"; - private static final String MESSAGE_FORMAT_UNABLE_TO_OPEN_FILE = "Unable to open file - %s"; + private static final String MESSAGE_FORMAT_UNABLE_TO_OPEN_READ = "Unable to open file to read - %s"; + private static final String MESSAGE_FORMAT_UNABLE_TO_OPEN_WRITE = "Unable to open file to write - %s"; private static final String MESSAGE_FORMAT_UNABLE_TO_READ_JSON = "Unable to read from JSON file - %s"; private static final String MESSAGE_FORMAT_UNABLE_TO_WRITE_JSON = "Unable to write to JSON file - %s"; private static final String MESSAGE_FORMAT_JSON_SYNTAX_ERROR = "JSON file syntax error - %s"; @@ -50,7 +51,7 @@ public ModuleList load() throws TaaException { moduleList = gson.fromJson(jsonReader, ModuleList.class); jsonReader.close(); } catch (FileNotFoundException e) { - throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_FILE, filename)); + throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_READ, filename)); } catch (JsonIOException | IOException e) { throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_READ_JSON, filename)); } catch (JsonSyntaxException e) { @@ -80,7 +81,7 @@ public void save(ModuleList moduleList) throws TaaException { gson.toJson(moduleList, ModuleList.class, jsonWriter); jsonWriter.close(); } catch (IOException e) { - throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_FILE, filename)); + throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_WRITE, filename)); } catch (JsonIOException e) { throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_WRITE_JSON, filename)); } From 1dcde407624ad29509f61cf37b297df8e5777797 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 11:30:09 +0800 Subject: [PATCH 093/543] Add debug messages to debug GitHub jobs --- src/main/java/taa/Storage.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/taa/Storage.java b/src/main/java/taa/Storage.java index ddbe7ca23a..964b032376 100644 --- a/src/main/java/taa/Storage.java +++ b/src/main/java/taa/Storage.java @@ -77,9 +77,13 @@ public void save(ModuleList moduleList) throws TaaException { Gson gson = new Gson(); try { FileWriter fileWriter = new FileWriter(filename); + System.out.println("After FileWriter"); JsonWriter jsonWriter = new JsonWriter(fileWriter); + System.out.println("After JsonWriter"); gson.toJson(moduleList, ModuleList.class, jsonWriter); + System.out.println("After toJson"); jsonWriter.close(); + System.out.println("After JsonWriter close"); } catch (IOException e) { throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_WRITE, filename)); } catch (JsonIOException e) { From 46474a3720b5f4b846ee36504d532e9abd7c0b32 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 11:32:33 +0800 Subject: [PATCH 094/543] Print IOException message to debug in GitHub --- src/main/java/taa/Storage.java | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/main/java/taa/Storage.java b/src/main/java/taa/Storage.java index 964b032376..843ecff974 100644 --- a/src/main/java/taa/Storage.java +++ b/src/main/java/taa/Storage.java @@ -77,15 +77,12 @@ public void save(ModuleList moduleList) throws TaaException { Gson gson = new Gson(); try { FileWriter fileWriter = new FileWriter(filename); - System.out.println("After FileWriter"); JsonWriter jsonWriter = new JsonWriter(fileWriter); - System.out.println("After JsonWriter"); gson.toJson(moduleList, ModuleList.class, jsonWriter); - System.out.println("After toJson"); jsonWriter.close(); - System.out.println("After JsonWriter close"); } catch (IOException e) { - throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_WRITE, filename)); + //throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_WRITE, filename)); + throw new TaaException(e.getMessage()); } catch (JsonIOException e) { throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_WRITE_JSON, filename)); } From fa2207026bbfb305019159a08555376de09d69f7 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 11:42:24 +0800 Subject: [PATCH 095/543] Use File class to create directories and files --- src/main/java/taa/util/Util.java | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java index a5d286f6c1..49a22fbc1f 100644 --- a/src/main/java/taa/util/Util.java +++ b/src/main/java/taa/util/Util.java @@ -1,5 +1,6 @@ package taa.util; +import java.io.File; import java.io.IOException; import java.nio.file.FileSystems; import java.nio.file.Files; @@ -61,9 +62,9 @@ public static Path getPathFromFilename(String filename) { * @return true if exists, else false. */ public static boolean fileExists(String filename) { - Path path = getPathFromFilename(filename); + File file = new File(filename); - return Files.exists(path); + return file.exists(); } /** @@ -77,16 +78,25 @@ public static boolean createFile(String filename) { return true; } - Path path = getPathFromFilename(filename); - Path parentPath = path.getParent(); + File file = new File(filename); + File parentFile = file.getParentFile(); + boolean result; try { - Files.createDirectories(parentPath); - Files.createFile(path); + boolean hasCreatedDir = true; + if (parentFile != null) { + hasCreatedDir = parentFile.mkdirs(); + } + + if (hasCreatedDir) { + result = file.createNewFile(); + } else { + result = false; + } } catch (IOException e) { - return false; + result = false; } - return true; + return result; } } From bb87e410dc0005c0e97d6ca5fc0fbbb54a099ced Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 11:42:53 +0800 Subject: [PATCH 096/543] Remove unused import --- src/main/java/taa/util/Util.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java index 49a22fbc1f..6a3391a59b 100644 --- a/src/main/java/taa/util/Util.java +++ b/src/main/java/taa/util/Util.java @@ -3,7 +3,6 @@ import java.io.File; import java.io.IOException; import java.nio.file.FileSystems; -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; From 120a93b0efdcdb1eaec8c9c94b2b836a8d3bf68e Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 11:45:57 +0800 Subject: [PATCH 097/543] Remove unused functions in Util and Storage classes --- src/main/java/taa/Storage.java | 17 +---------------- src/main/java/taa/Taa.java | 17 ----------------- src/main/java/taa/util/Util.java | 26 -------------------------- 3 files changed, 1 insertion(+), 59 deletions(-) diff --git a/src/main/java/taa/Storage.java b/src/main/java/taa/Storage.java index 843ecff974..78c90e2050 100644 --- a/src/main/java/taa/Storage.java +++ b/src/main/java/taa/Storage.java @@ -23,22 +23,12 @@ public class Storage { private static final String MESSAGE_FORMAT_JSON_SYNTAX_ERROR = "JSON file syntax error - %s"; private final String filename; - private boolean isEnabled; public Storage(String filename) { this.filename = filename; - this.isEnabled = true; - } - - public void setEnabled(boolean enabled) { - isEnabled = enabled; } public ModuleList load() throws TaaException { - if (!isEnabled) { - return null; - } - if (!Util.fileExists(filename)) { return null; } @@ -66,10 +56,6 @@ public ModuleList load() throws TaaException { } public void save(ModuleList moduleList) throws TaaException { - if (!isEnabled) { - return; - } - if (!Util.createFile(filename)) { throw new TaaException(String.format(MESSAGE_FORMAT_FAIL_CREATE_FILE, filename)); } @@ -81,8 +67,7 @@ public void save(ModuleList moduleList) throws TaaException { gson.toJson(moduleList, ModuleList.class, jsonWriter); jsonWriter.close(); } catch (IOException e) { - //throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_WRITE, filename)); - throw new TaaException(e.getMessage()); + throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_WRITE, filename)); } catch (JsonIOException e) { throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_WRITE_JSON, filename)); } diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index 68c1e4e036..29cb28df30 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -15,11 +15,6 @@ public Taa() { } - public Taa(boolean enableSaving) { - this(); - storage.setEnabled(enableSaving); - } - public void run() { loadModuleListFromStorage(); assert moduleList != null; @@ -59,18 +54,6 @@ private void loadModuleListFromStorage() { * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - /*Taa taa = null; - for (int i = 0; i < args.length && taa == null; i += 1) { - String arg = args[i]; - if (arg.equals("nosave")) { - taa = new Taa(false); - } - } - - if (taa == null) { - taa = new Taa(); - }*/ - Taa taa = new Taa(); taa.run(); } diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java index 6a3391a59b..e0cf794af0 100644 --- a/src/main/java/taa/util/Util.java +++ b/src/main/java/taa/util/Util.java @@ -2,10 +2,6 @@ import java.io.File; import java.io.IOException; -import java.nio.file.FileSystems; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.Arrays; public class Util { public static boolean isStringInteger(String string) { @@ -32,28 +28,6 @@ public static boolean isStringDouble(String string) { return isDouble; } - /** - * Gets the Path object from filename. - * - * @param filename The filename. - * @return A Path object. - */ - public static Path getPathFromFilename(String filename) { - String separator = FileSystems.getDefault().getSeparator(); - String[] filenameSplit = filename.split(separator.replace("\\", "\\\\")); - - String firstPathString = filenameSplit[0]; - Path path; - if (filenameSplit.length > 1) { - String[] additionalPathStrings = Arrays.copyOfRange(filenameSplit, 1, filenameSplit.length - 1); - path = Paths.get(firstPathString, additionalPathStrings); - } else { - path = Paths.get(firstPathString); - } - - return path; - } - /** * Checks if file exists. * From f47bc42803261970e8cbad758d136db56a8fbebd Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 13:24:08 +0800 Subject: [PATCH 098/543] Add custom deserializers to parse data file --- src/main/java/taa/Taa.java | 8 +- .../java/taa/assessment/AssessmentList.java | 16 +++- .../taa/command/AddAssessmentCommand.java | 2 +- .../java/taa/command/AddModuleCommand.java | 2 +- .../java/taa/command/AddStudentCommand.java | 2 +- .../java/taa/command/AverageMarksCommand.java | 2 +- src/main/java/taa/command/Command.java | 2 +- .../taa/command/DeleteStudentCommand.java | 2 +- .../java/taa/command/EditStudentCommand.java | 2 +- src/main/java/taa/command/ExitCommand.java | 2 +- .../java/taa/command/FindStudentCommand.java | 2 +- .../taa/command/ListAssessmentsCommand.java | 2 +- .../java/taa/command/ListMarksCommand.java | 2 +- .../java/taa/command/ListModulesCommand.java | 2 +- .../java/taa/command/ListStudentsCommand.java | 2 +- .../java/taa/command/SetMarksCommand.java | 2 +- src/main/java/taa/module/Module.java | 7 +- src/main/java/taa/module/ModuleList.java | 6 +- src/main/java/taa/{ => storage}/Storage.java | 13 +-- .../deserializer/AssessmentDeserializer.java | 42 ++++++++++ .../AssessmentListDeserializer.java | 52 ++++++++++++ .../deserializer/ModuleDeserializer.java | 79 +++++++++++++++++++ .../deserializer/ModuleListDeserializer.java | 52 ++++++++++++ .../deserializer/StorageDeserializer.java | 15 ++++ .../deserializer/StudentDeserializer.java | 70 ++++++++++++++++ .../deserializer/StudentListDeserializer.java | 51 ++++++++++++ src/main/java/taa/student/Student.java | 6 +- src/main/java/taa/student/StudentList.java | 6 +- 28 files changed, 414 insertions(+), 37 deletions(-) rename src/main/java/taa/{ => storage}/Storage.java (90%) create mode 100644 src/main/java/taa/storage/deserializer/AssessmentDeserializer.java create mode 100644 src/main/java/taa/storage/deserializer/AssessmentListDeserializer.java create mode 100644 src/main/java/taa/storage/deserializer/ModuleDeserializer.java create mode 100644 src/main/java/taa/storage/deserializer/ModuleListDeserializer.java create mode 100644 src/main/java/taa/storage/deserializer/StorageDeserializer.java create mode 100644 src/main/java/taa/storage/deserializer/StudentDeserializer.java create mode 100644 src/main/java/taa/storage/deserializer/StudentListDeserializer.java diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index 29cb28df30..814ba61ec2 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -3,16 +3,18 @@ import taa.command.Command; import taa.exception.TaaException; import taa.module.ModuleList; +import taa.storage.Storage; public class Taa { private static final String DATA_FILENAME = "./data/taa_data.json"; private ModuleList moduleList; - private final Ui ui = new Ui(); - private final Storage storage = new Storage(DATA_FILENAME); + private final Ui ui; + private final Storage storage; public Taa() { - + this.ui = new Ui(); + this.storage = new Storage(DATA_FILENAME); } public void run() { diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 254bf7d748..6449250107 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -7,7 +7,11 @@ public class AssessmentList implements ClassChecker { private static final String MESSAGE_ASSESSMENT_LIST_HEADER = "Assessment List:"; - private final ArrayList assessments = new ArrayList<>(); + private final ArrayList assessments; + + public AssessmentList() { + this.assessments = new ArrayList<>(); + } public int getSize() { return assessments.size(); @@ -79,7 +83,15 @@ public String toString() { @Override public boolean verify() { - assessments.removeIf(assessment -> !assessment.verify()); + ArrayList assessmentNames = new ArrayList<>(); + for (Assessment assessment : assessments) { + String name = assessment.getName(); + if (assessmentNames.contains(name)) { + assessments.remove(assessment); + } else { + assessmentNames.add(name); + } + } return true; } diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index afca6e56f3..d3c95f7ca5 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index 26dec3e553..238f5ca6f5 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.ModuleList; diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index 6aafebd0de..134d24075b 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.Module; diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index 25354e69f1..278bb25364 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.assessment.Assessment; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 083efa7776..ff3bb5580e 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.exception.TaaException; import taa.Parser; import taa.Ui; diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index e3ace4509f..119fb8bfbd 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.Module; diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 3856a8579f..eac41f6b7e 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.Module; diff --git a/src/main/java/taa/command/ExitCommand.java b/src/main/java/taa/command/ExitCommand.java index d0b63e521d..3b0f9697ed 100644 --- a/src/main/java/taa/command/ExitCommand.java +++ b/src/main/java/taa/command/ExitCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.ModuleList; diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 74d456b5b2..3fc381a8c5 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.Module; diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index c2c6ce7b8f..c3d07e93a4 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.Ui; import taa.assessment.AssessmentList; import taa.exception.TaaException; diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index b008a188f3..71d58fafdb 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; diff --git a/src/main/java/taa/command/ListModulesCommand.java b/src/main/java/taa/command/ListModulesCommand.java index 9aa010217d..449de59a41 100644 --- a/src/main/java/taa/command/ListModulesCommand.java +++ b/src/main/java/taa/command/ListModulesCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.ModuleList; diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index cbdc4d1a5d..79a0a3b330 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; import taa.module.Module; diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 58bc470b49..bee26710ba 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -1,6 +1,6 @@ package taa.command; -import taa.Storage; +import taa.storage.Storage; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index 02dad65368..d75dbb541e 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -8,12 +8,15 @@ public class Module implements ClassChecker { private String code; private String name; private int lessonCount; - private final StudentList studentList = new StudentList(); - private final AssessmentList assessmentList = new AssessmentList(); + private final StudentList studentList; + private final AssessmentList assessmentList; public Module(String code, String name) { this.code = code; this.name = name; + this.lessonCount = 0; + this.studentList = new StudentList(); + this.assessmentList = new AssessmentList(); } public String getCode() { diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index e2fc09bdeb..ab2c0be0d2 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -7,10 +7,10 @@ public class ModuleList implements ClassChecker { private static final String MESSAGE_MODULE_LIST_HEADER = "Module List:"; - private final ArrayList modules = new ArrayList<>(); + private final ArrayList modules; public ModuleList() { - + this.modules = new ArrayList<>(); } public void addModule(Module module) { @@ -80,8 +80,6 @@ public String toString() { @Override public boolean verify() { - modules.removeIf(module -> !module.verify()); - return true; } } diff --git a/src/main/java/taa/Storage.java b/src/main/java/taa/storage/Storage.java similarity index 90% rename from src/main/java/taa/Storage.java rename to src/main/java/taa/storage/Storage.java index 78c90e2050..ed6bb0c175 100644 --- a/src/main/java/taa/Storage.java +++ b/src/main/java/taa/storage/Storage.java @@ -1,12 +1,14 @@ -package taa; +package taa.storage; import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.JsonIOException; import com.google.gson.JsonSyntaxException; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import taa.exception.TaaException; import taa.module.ModuleList; +import taa.storage.deserializer.ModuleListDeserializer; import taa.util.Util; import java.io.FileNotFoundException; @@ -33,8 +35,11 @@ public ModuleList load() throws TaaException { return null; } + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.registerTypeAdapter(ModuleList.class, new ModuleListDeserializer()); + Gson gson = gsonBuilder.create(); + ModuleList moduleList; - Gson gson = new Gson(); try { FileReader fileReader = new FileReader(filename); JsonReader jsonReader = new JsonReader(fileReader); @@ -48,10 +53,6 @@ public ModuleList load() throws TaaException { throw new TaaException(String.format(MESSAGE_FORMAT_JSON_SYNTAX_ERROR, filename)); } - if (!moduleList.verify()) { - moduleList = null; - } - return moduleList; } diff --git a/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java b/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java new file mode 100644 index 0000000000..7c16b248ad --- /dev/null +++ b/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java @@ -0,0 +1,42 @@ +package taa.storage.deserializer; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import taa.assessment.Assessment; +import taa.util.Util; + +import java.lang.reflect.Type; + +public class AssessmentDeserializer extends StorageDeserializer implements JsonDeserializer { + private static final String MEMBER_NAME = "name"; + private static final String MEMBER_WEIGHTAGE = "weightage"; + private static final String[] MEMBERS = {MEMBER_NAME, MEMBER_WEIGHTAGE}; + + @Override + public Assessment deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + if (!hasMembers(jsonObject, MEMBERS)) { + return null; + } + + JsonElement nameJson = jsonObject.get(MEMBER_NAME); + String name = nameJson.getAsString(); + + JsonElement weightageJson = jsonObject.get(MEMBER_WEIGHTAGE); + if (!Util.isStringDouble(weightageJson.getAsString())) { + return null; + } + double weightage = weightageJson.getAsDouble(); + + Assessment assessment = new Assessment(name, weightage); + if (!assessment.verify()) { + return null; + } + + return assessment; + } +} diff --git a/src/main/java/taa/storage/deserializer/AssessmentListDeserializer.java b/src/main/java/taa/storage/deserializer/AssessmentListDeserializer.java new file mode 100644 index 0000000000..17dc6c2dfc --- /dev/null +++ b/src/main/java/taa/storage/deserializer/AssessmentListDeserializer.java @@ -0,0 +1,52 @@ +package taa.storage.deserializer; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import taa.assessment.Assessment; +import taa.assessment.AssessmentList; + +import java.lang.reflect.Type; + +public class AssessmentListDeserializer extends StorageDeserializer implements JsonDeserializer { + private static final String MEMBER_ASSESSMENTS = "assessments"; + private static final String[] MEMBERS = {MEMBER_ASSESSMENTS}; + + @Override + public AssessmentList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + if (!hasMembers(jsonObject, MEMBERS)) { + return null; + } + + JsonElement assessmentsJson = jsonObject.get(MEMBER_ASSESSMENTS); + if (!assessmentsJson.isJsonArray()) { + return null; + } + + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.registerTypeAdapter(Assessment.class, new AssessmentDeserializer()); + Gson gson = gsonBuilder.create(); + + AssessmentList assessmentList = new AssessmentList(); + JsonArray assessmentsJsonArray = assessmentsJson.getAsJsonArray(); + for (JsonElement assessmentJson : assessmentsJsonArray) { + Assessment assessment = gson.fromJson(assessmentJson, Assessment.class); + if (assessment != null) { + assessmentList.addAssessment(assessment); + } + } + + if (!assessmentList.verify()) { + return null; + } + + return assessmentList; + } +} diff --git a/src/main/java/taa/storage/deserializer/ModuleDeserializer.java b/src/main/java/taa/storage/deserializer/ModuleDeserializer.java new file mode 100644 index 0000000000..99609d6c3a --- /dev/null +++ b/src/main/java/taa/storage/deserializer/ModuleDeserializer.java @@ -0,0 +1,79 @@ +package taa.storage.deserializer; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import taa.assessment.Assessment; +import taa.assessment.AssessmentList; +import taa.module.Module; +import taa.student.Student; +import taa.student.StudentList; +import taa.util.Util; + +import java.lang.reflect.Type; + +public class ModuleDeserializer extends StorageDeserializer implements JsonDeserializer { + private static final String MEMBER_CODE = "code"; + private static final String MEMBER_NAME = "name"; + private static final String MEMBER_LESSONCOUNT = "lessonCount"; + private static final String MEMBER_STUDENTLIST = "studentList"; + private static final String MEMBER_ASSESSMENTLIST = "assessmentList"; + private static final String[] MEMBERS = { + MEMBER_CODE, + MEMBER_NAME, + MEMBER_LESSONCOUNT, + MEMBER_STUDENTLIST, + MEMBER_ASSESSMENTLIST + }; + + @Override + public Module deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + if (!hasMembers(jsonObject, MEMBERS)) { + return null; + } + + JsonElement codeJson = jsonObject.get(MEMBER_CODE); + String code = codeJson.getAsString(); + + JsonElement nameJson = jsonObject.get(MEMBER_NAME); + String name = nameJson.getAsString(); + + JsonElement lessonCountJson = jsonObject.get(MEMBER_LESSONCOUNT); + if (!Util.isStringInteger(lessonCountJson.getAsString())) { + return null; + } + int lessonCount = lessonCountJson.getAsInt(); + + Module module = new Module(code, name); + module.setLessonCount(lessonCount); + + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.registerTypeAdapter(StudentList.class, new StudentListDeserializer()); + gsonBuilder.registerTypeAdapter(AssessmentList.class, new AssessmentListDeserializer()); + Gson gson = gsonBuilder.create(); + + JsonElement studentListJson = jsonObject.get(MEMBER_STUDENTLIST); + StudentList studentList = gson.fromJson(studentListJson, StudentList.class); + for (Student student : studentList.getStudents()) { + module.getStudentList().addStudent(student); + } + + JsonElement assessmentListJson = jsonObject.get(MEMBER_ASSESSMENTLIST); + AssessmentList assessmentList = gson.fromJson(assessmentListJson, AssessmentList.class); + for (Assessment assessment : assessmentList.getAssessments()) { + module.getAssessmentList().addAssessment(assessment); + } + + if (!module.verify()) { + return null; + } + + return module; + } +} diff --git a/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java b/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java new file mode 100644 index 0000000000..a63a0d149b --- /dev/null +++ b/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java @@ -0,0 +1,52 @@ +package taa.storage.deserializer; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import taa.module.ModuleList; +import taa.module.Module; + +import java.lang.reflect.Type; + +public class ModuleListDeserializer extends StorageDeserializer implements JsonDeserializer { + private static final String MEMBER_MODULES = "modules"; + private static final String[] MEMBERS = {MEMBER_MODULES}; + + @Override + public ModuleList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + if (!hasMembers(jsonObject, MEMBERS)) { + return null; + } + + JsonElement modulesJson = jsonObject.get(MEMBER_MODULES); + if (modulesJson == null || !modulesJson.isJsonArray()) { + return null; + } + + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.registerTypeAdapter(Module.class, new ModuleDeserializer()); + Gson gson = gsonBuilder.create(); + + ModuleList moduleList = new ModuleList(); + JsonArray modulesJsonArray = modulesJson.getAsJsonArray(); + for (JsonElement moduleJson : modulesJsonArray) { + Module module = gson.fromJson(moduleJson, Module.class); + if (module != null) { + moduleList.addModule(module); + } + } + + if (!moduleList.verify()) { + return null; + } + + return moduleList; + } +} diff --git a/src/main/java/taa/storage/deserializer/StorageDeserializer.java b/src/main/java/taa/storage/deserializer/StorageDeserializer.java new file mode 100644 index 0000000000..e891dd1ca5 --- /dev/null +++ b/src/main/java/taa/storage/deserializer/StorageDeserializer.java @@ -0,0 +1,15 @@ +package taa.storage.deserializer; + +import com.google.gson.JsonObject; + +public abstract class StorageDeserializer { + protected boolean hasMembers(JsonObject jsonObject, String[] members) { + for (String member : members) { + if (!jsonObject.has(member)) { + return false; + } + } + + return true; + } +} diff --git a/src/main/java/taa/storage/deserializer/StudentDeserializer.java b/src/main/java/taa/storage/deserializer/StudentDeserializer.java new file mode 100644 index 0000000000..20555cce58 --- /dev/null +++ b/src/main/java/taa/storage/deserializer/StudentDeserializer.java @@ -0,0 +1,70 @@ +package taa.storage.deserializer; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import com.google.gson.reflect.TypeToken; +import taa.student.Attendance; +import taa.student.Student; + +import java.lang.reflect.Type; +import java.util.HashMap; + +public class StudentDeserializer extends StorageDeserializer implements JsonDeserializer { + private static final String MEMBER_ID = "id"; + private static final String MEMBER_NAME = "name"; + private static final String MEMBER_ATTENDANCES = "attendances"; + private static final String MEMBER_RESULTS = "results"; + private static final String[] MEMBERS = { + MEMBER_ID, + MEMBER_NAME, + MEMBER_ATTENDANCES, + MEMBER_RESULTS + }; + + @Override + public Student deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + if (!hasMembers(jsonObject, MEMBERS)) { + return null; + } + + JsonElement idJson = jsonObject.get(MEMBER_ID); + String id = idJson.getAsString(); + + JsonElement nameJson = jsonObject.get(MEMBER_NAME); + String name = nameJson.getAsString(); + + Student student = new Student(id, name); + + GsonBuilder gsonBuilder = new GsonBuilder(); + Gson gson = gsonBuilder.create(); + + JsonElement attendancesJson = jsonObject.get(MEMBER_ATTENDANCES); + JsonArray attendancesJsonArray = attendancesJson.getAsJsonArray(); + for (JsonElement attendanceJson : attendancesJsonArray) { + Attendance attendance = gson.fromJson(attendanceJson, Attendance.class); + // TODO Add attendance to student after parsing + } + + JsonElement resultsJson = jsonObject.get(MEMBER_RESULTS); + Type resultsType = new TypeToken>(){}.getType(); + HashMap results = gson.fromJson(resultsJson, resultsType); + for (String key : results.keySet()) { + double value = results.get(key); + student.setMarks(key, value); + } + + if (!student.verify()) { + return null; + } + + return student; + } +} diff --git a/src/main/java/taa/storage/deserializer/StudentListDeserializer.java b/src/main/java/taa/storage/deserializer/StudentListDeserializer.java new file mode 100644 index 0000000000..5b2313a26f --- /dev/null +++ b/src/main/java/taa/storage/deserializer/StudentListDeserializer.java @@ -0,0 +1,51 @@ +package taa.storage.deserializer; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import taa.student.Student; +import taa.student.StudentList; + +import java.lang.reflect.Type; + +public class StudentListDeserializer extends StorageDeserializer implements JsonDeserializer { + private static final String MEMBER_STUDENTS = "students"; + private static final String[] MEMBERS = {MEMBER_STUDENTS}; + + @Override + public StudentList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + if (!hasMembers(jsonObject, MEMBERS)) { + return null; + } + + JsonElement studentsJson = jsonObject.get(MEMBER_STUDENTS); + if (!studentsJson.isJsonArray()) { + return null; + } + + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.registerTypeAdapter(Student.class, new StudentDeserializer()); + Gson gson = gsonBuilder.create(); + + StudentList studentList = new StudentList(); + JsonArray studentsJsonArray = studentsJson.getAsJsonArray(); + for (JsonElement studentJson : studentsJsonArray) { + Student student = gson.fromJson(studentJson, Student.class); + if (student != null) { + studentList.addStudent(student); + } + } + + if (!studentList.verify()) { + return null; + } + + return studentList; + } +} diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index 27a9034eff..10b362b874 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -13,12 +13,14 @@ public class Student implements ClassChecker { private String id; private String name; - private final ArrayList attendances = new ArrayList<>(); - private final HashMap results = new HashMap<>(); + private final ArrayList attendances; + private final HashMap results; public Student(String id, String name) { this.id = id; this.name = name; + this.attendances = new ArrayList<>(); + this.results = new HashMap<>(); } public static boolean isMarksWithinRange(double marks) { diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index 1630251bbd..dde1d698f3 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -7,10 +7,10 @@ public class StudentList implements ClassChecker { private static final String MESSAGE_LIST_STUDENT_HEADER = "Student List:"; - private final ArrayList students = new ArrayList<>(); + private final ArrayList students; public StudentList() { - + this.students = new ArrayList<>(); } /** @@ -88,8 +88,6 @@ public String toString() { @Override public boolean verify() { - students.removeIf(student -> !student.verify()); - return true; } } From d7cfbdc941ab0b16bc8234be87979a23f7436772 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 13:26:15 +0800 Subject: [PATCH 099/543] Fix checkstyle error --- .../java/taa/storage/deserializer/StudentListDeserializer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/storage/deserializer/StudentListDeserializer.java b/src/main/java/taa/storage/deserializer/StudentListDeserializer.java index 5b2313a26f..a8890dcd71 100644 --- a/src/main/java/taa/storage/deserializer/StudentListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/StudentListDeserializer.java @@ -18,7 +18,8 @@ public class StudentListDeserializer extends StorageDeserializer implements Json private static final String[] MEMBERS = {MEMBER_STUDENTS}; @Override - public StudentList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + public StudentList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); if (!hasMembers(jsonObject, MEMBERS)) { return null; From 51d5b8c7b6971b81082670adb260ea9a2a040090 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 13:36:40 +0800 Subject: [PATCH 100/543] Update runtest scripts --- text-ui-test/runtest.bat | 2 +- text-ui-test/runtest.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/text-ui-test/runtest.bat b/text-ui-test/runtest.bat index 8e31139797..25ac7a2989 100644 --- a/text-ui-test/runtest.bat +++ b/text-ui-test/runtest.bat @@ -12,7 +12,7 @@ for /f "tokens=*" %%a in ( set jarloc=%%a ) -java -jar %jarloc% nosave < ..\..\text-ui-test\input.txt > ..\..\text-ui-test\ACTUAL.TXT +java -jar %jarloc% < ..\..\text-ui-test\input.txt > ..\..\text-ui-test\ACTUAL.TXT cd ..\..\text-ui-test diff --git a/text-ui-test/runtest.sh b/text-ui-test/runtest.sh index 693fc5433b..1dcbd12021 100755 --- a/text-ui-test/runtest.sh +++ b/text-ui-test/runtest.sh @@ -8,7 +8,7 @@ cd .. cd text-ui-test -java -jar $(find ../build/libs/ -mindepth 1 -print -quit) nosave < input.txt > ACTUAL.TXT +java -jar $(find ../build/libs/ -mindepth 1 -print -quit) < input.txt > ACTUAL.TXT cp EXPECTED.TXT EXPECTED-UNIX.TXT dos2unix EXPECTED-UNIX.TXT ACTUAL.TXT From 81a1be0c2bc82fe14676bd7cceebfee755d0518c Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Tue, 12 Oct 2021 15:42:00 +0800 Subject: [PATCH 101/543] Add Attendance and AttendanceList --- src/main/java/taa/Parser.java | 20 +-- src/main/java/taa/attendance/Attendance.java | 34 ++++ .../java/taa/attendance/AttendanceList.java | 66 ++++++++ src/main/java/taa/command/Command.java | 6 + .../taa/command/ListAttendanceCommand.java | 141 ++++++++++++++++ .../taa/command/SetAttendanceCommand.java | 159 ++++++++++++++++++ src/main/java/taa/module/Module.java | 48 ++++++ src/main/java/taa/student/Attendance.java | 20 --- src/main/java/taa/student/Student.java | 32 +++- .../java/taa/attendance/AttendanceTest.java | 19 +++ src/test/java/taa/student/AttendanceTest.java | 14 -- 11 files changed, 507 insertions(+), 52 deletions(-) create mode 100644 src/main/java/taa/attendance/Attendance.java create mode 100644 src/main/java/taa/attendance/AttendanceList.java create mode 100644 src/main/java/taa/command/ListAttendanceCommand.java create mode 100644 src/main/java/taa/command/SetAttendanceCommand.java delete mode 100644 src/main/java/taa/student/Attendance.java create mode 100644 src/test/java/taa/attendance/AttendanceTest.java delete mode 100644 src/test/java/taa/student/AttendanceTest.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 7fce22f0ea..dfc09796a3 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,16 +1,6 @@ package taa; -import taa.command.AddAssessmentCommand; -import taa.command.AddModuleCommand; -import taa.command.AddStudentCommand; -import taa.command.Command; -import taa.command.DeleteStudentCommand; -import taa.command.EditStudentCommand; -import taa.command.ExitCommand; -import taa.command.FindStudentCommand; -import taa.command.ListAssessmentsCommand; -import taa.command.ListModulesCommand; -import taa.command.ListStudentsCommand; +import taa.command.*; import taa.exception.TaaException; import java.util.ArrayList; @@ -67,6 +57,14 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new ListAssessmentsCommand(argument); break; + case Command.COMMAND_SET_ATTENDANCE: + command = new SetAttendanceCommand(argument); + break; + + case Command.COMMAND_LIST_ATTENDANCE: + command = new ListAttendanceCommand(argument); + break; + default: throw new TaaException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/taa/attendance/Attendance.java b/src/main/java/taa/attendance/Attendance.java new file mode 100644 index 0000000000..ac9bb6a040 --- /dev/null +++ b/src/main/java/taa/attendance/Attendance.java @@ -0,0 +1,34 @@ +package taa.attendance; + +public class Attendance { + private final String code; + private final String studentIndex; + private final String lessonIndex; + private boolean hasAttend; + + public Attendance(String code, String studentIndex, String lessonIndex, boolean hasAttend) { + this.code = code; + this.studentIndex = studentIndex; + this.lessonIndex = lessonIndex; + this.hasAttend = hasAttend; + } + + public String markAttendance() { + return (hasAttend ? "1" : "0"); + } + + public String getLessonIndex() { + return lessonIndex; + } + + public String getLessonNum() { + return Integer.toString(Integer.parseInt(lessonIndex) + 1); + } + + + @Override + public String toString() { + return String.format("%s %s %s %s", code, studentIndex, lessonIndex, hasAttend); + } +} + diff --git a/src/main/java/taa/attendance/AttendanceList.java b/src/main/java/taa/attendance/AttendanceList.java new file mode 100644 index 0000000000..ee537f8876 --- /dev/null +++ b/src/main/java/taa/attendance/AttendanceList.java @@ -0,0 +1,66 @@ +package taa.attendance; + + +import java.util.ArrayList; +import java.util.Arrays; + +public class AttendanceList { + private static final String MESSAGE_ATTENDANCE_LIST_HEADER = "Attendance List:"; + + private final ArrayList attendances; + + public AttendanceList() { + this.attendances = new ArrayList<>(); + } + + public int getSize() { + return attendances.size(); + } + + public ArrayList getAttendances() { + return attendances; + } + + /** + * Converts the array of attendances from all lessons for a student to a string + * + * @param individualAttendances the array of attendances from all lessons for a student + * @return String representation of the array of attendances from all lessons for a student + */ + public String individualAttendancesToString(String[] individualAttendances) { + return Arrays.toString(individualAttendances); + } + + /** + * Adds the array of attendances from all lessons for a student to the AttendanceList + * + * @param individualAttendances the array of attendances from all lessons for a student + */ + public void addIndividualAttendances(String[] individualAttendances) { + String studentAttendances = individualAttendancesToString(individualAttendances); + String formattedStudentAttendances = formatStudentAttendances(studentAttendances); + attendances.add(formattedStudentAttendances); + } + + private String formatStudentAttendances(String studentAttendances) { + studentAttendances = studentAttendances.replace("[", " | "); + studentAttendances = studentAttendances.replace("]", " |"); + studentAttendances = studentAttendances.replace(",", " |"); + return studentAttendances; + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(MESSAGE_ATTENDANCE_LIST_HEADER); + for (int i = 0; i < getSize(); i += 1) { + stringBuilder.append("\n"); + stringBuilder.append(i + 1); + stringBuilder.append(". "); + stringBuilder.append(attendances.get(i)); + } + + return stringBuilder.toString(); + } + +} + diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 11149c0e3c..b7b2920b8a 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -26,7 +26,13 @@ public abstract class Command { protected static final String MESSAGE_UNKNOWN_USAGE = "Unknown usage."; protected static final String MESSAGE_MODULE_NOT_FOUND = "Module not found."; + protected static final String MESSAGE_NO_STUDENTS = "No students added yet!"; protected static final String MESSAGE_INVALID_STUDENT_INDEX = "Invalid student index."; + protected static final String MESSAGE_STUDENT_INDEX_OUT_OF_BOUNDS = "Student index is out of bounds."; + protected static final String MESSAGE_INVALID_LESSON_INDEX = "Invalid lesson index."; + protected static final String MESSAGE_LESSON_INDEX_OUT_OF_BOUNDS = "Lesson index is out of bounds."; + protected static final String MESSAGE_INVALID_ATTENDANCE = "Invalid attendance."; + protected static final String MESSAGE_ATTENDANCE_LIST_EMPTY = "There is no recorded attendance in the module."; protected static final String MESSAGE_FORMAT_GENERIC_USAGE = "Usage: %s"; protected static final String MESSAGE_FORMAT_MISSING_ARGUMENT = "Missing Argument(s).\n%s"; diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/ListAttendanceCommand.java new file mode 100644 index 0000000000..4fbfabb338 --- /dev/null +++ b/src/main/java/taa/command/ListAttendanceCommand.java @@ -0,0 +1,141 @@ +package taa.command; + +import taa.Ui; +import taa.attendance.AttendanceList; +import taa.exception.TaaException; +import taa.module.Module; +import taa.module.ModuleList; +import taa.student.Student; + +import java.util.ArrayList; + +public class ListAttendanceCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String[] LIST_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE}; + + private static final String MESSAGE_ATTENDANCE_LIST_HEADER = "Attendance List:"; + + private static final String MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE = "Usage: %s %s/"; + private static final int SPACE_FOR_NAME = 25; + private static final int BEGIN_INDEX = 0; + private static final int SPACE_FOR_TRIMMED_NAME = 22; + private static final String LESSONS_TITLE = "LESSON NUMBER"; + + public ListAttendanceCommand(String argument) { + super(argument, LIST_ATTENDANCE_ARGUMENT_KEYS); + } + + /** + * @param moduleList The list of modules + * @param ui The ui instance to handle interactions with the user + * @throws TaaException If the user inputs an invalid command + */ + @Override + public void execute(ModuleList moduleList, Ui ui) throws TaaException { + checkIfArgumentIsEmpty(); + checkIfArgumentIsMissing(); + + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModule(moduleCode); + checkIfModuleListIsEmpty(module); + + ArrayList students = module.getStudents(); + checkIfStudentsIsEmpty(students); + + ArrayList attendances = module.getAttendances(); + checkIfAttendancesIsEmpty(attendances); + + StringBuilder stringBuilder = new StringBuilder(MESSAGE_ATTENDANCE_LIST_HEADER); + buildString(stringBuilder, module, students, attendances); + + ui.printMessage(stringBuilder.toString()); + } + + private void checkIfArgumentIsEmpty() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + } + + private void checkIfArgumentIsMissing() throws TaaException { + if (!checkArgumentMap()) { + throw new TaaException(getMissingArgumentMessage()); + } + } + + private void checkIfModuleListIsEmpty(Module module) throws TaaException { + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + } + + private void checkIfStudentsIsEmpty(ArrayList students) throws TaaException { + if (students.isEmpty()) { + throw new TaaException(MESSAGE_NO_STUDENTS); + } + } + + private void checkIfAttendancesIsEmpty(ArrayList attendances) throws TaaException { + if (attendances.isEmpty()) { + throw new TaaException(MESSAGE_ATTENDANCE_LIST_EMPTY); + } + } + + private void buildString(StringBuilder stringBuilder, Module module, ArrayList students, + ArrayList attendances) { + stringBuilder.append("\n"); + stringBuilder.append(padWithWhiteSpace(LESSONS_TITLE, LESSONS_TITLE.length())); + stringBuilder.append(module.getFormattedLessons()); + for (int i = 0; i < attendances.size(); i += 1) { + stringBuilder.append("\n"); + stringBuilder.append(i + 1); + stringBuilder.append(". "); + String trimmedStudentName = trimName(students.get(i).getName(), i + 1); + stringBuilder.append(trimmedStudentName); + stringBuilder.append(attendances.get(i)); + } + } + + /** + * Trims the student's name if it is too long + * + * @param studentName name of the student + * @param number the length of the list number + * @return truncated student name or student name with whitespace + */ + private String trimName(String studentName, int number) { + int lengthOfDot = 2; + int lengthOfNumber = ((number / 10) + 1) + lengthOfDot; + int lengthOfNumberAndName = lengthOfNumber + studentName.length(); + if (lengthOfNumberAndName > SPACE_FOR_NAME) { + return studentName.substring(BEGIN_INDEX, SPACE_FOR_TRIMMED_NAME - lengthOfNumber) + "..."; + } + return padWithWhiteSpace(studentName, lengthOfNumberAndName); + } + + /** + * Pads a string with whitespace + * + * @param stringToPad string to pad with whitespace + * @param lengthOfString length of the string to pad with whitespace + * @return string with whitespace + */ + private String padWithWhiteSpace(String stringToPad, int lengthOfString) { + int amountToPad = SPACE_FOR_NAME - lengthOfString; + for (int i = 0; i < amountToPad; i++) { + stringToPad = stringToPad + " "; + } + return stringToPad; + } + + + @Override + protected String getUsageMessage() { + return String.format( + MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE, + COMMAND_LIST_ATTENDANCE, + KEY_MODULE_CODE + ); + } + +} diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java new file mode 100644 index 0000000000..467291ec4a --- /dev/null +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -0,0 +1,159 @@ +package taa.command; + +import taa.attendance.AttendanceList; +import taa.exception.TaaException; +import taa.Ui; +import taa.attendance.Attendance; +import taa.module.Module; +import taa.module.ModuleList; +import taa.student.Student; +import taa.util.Util; + +import java.util.ArrayList; + +public class SetAttendanceCommand extends Command { + private static final String MESSAGE_FORMAT_SET_ATTENDANCE = + "Attendance set:\n %s - %s\nfor Lesson %s"; + + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_STUDENT_NUM = "s"; + private static final String KEY_LESSON_NUM = "l"; + private static final String KEY_ATTENDANCE_MARK = "attend"; + private static final String ATTENDANCE_MARK_PRESENT = "1"; + private static final String ATTENDANCE_MARK_ABSENT = "0"; + private static final String[] SET_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_NUM, KEY_LESSON_NUM + , KEY_ATTENDANCE_MARK}; + + private static final int MIN_STUDENT_NUM = 1; + private static final int MAX_LESSON_INDEX = 12; + private static final int MIN_LESSON_INDEX = 0; + + private static final String MESSAGE_FORMAT_SET_ATTENDANCE_USAGE = "Usage: %s " + + "%s/ %s/ %s/ %s/"; + + + public SetAttendanceCommand(String argument) { + super(argument, SET_ATTENDANCE_ARGUMENT_KEYS); + } + + /** + * Sets the attendance of a student to 1 or 0 + * + * @param moduleList The list of modules + * @param ui The ui instance to handle interactions with the user + * @throws TaaException If the user inputs an invalid command + */ + public void execute(ModuleList moduleList, Ui ui) throws TaaException { + checkIfArgumentIsEmpty(); + checkIfArgumentIsMissing(); + + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModule(moduleCode); + checkIfModuleListIsEmpty(module); + + ArrayList students = module.getStudents(); + checkIfStudentsIsEmpty(students); + + String studentNum = argumentMap.get(KEY_STUDENT_NUM); + checkIfStudentNumIsInteger(studentNum); + checkIfStudentNumOutOfBounds(module, studentNum); + + int studentIndex = Integer.parseInt(studentNum) - 1; + Student student = module.getStudentAt(studentIndex); + + String lessonNum = argumentMap.get(KEY_LESSON_NUM); + checkIfLessonNumIsInteger(lessonNum); + + int lessonIndex = Integer.parseInt(lessonNum) - 1; + checkIfLessonIndexOutOfBounds(lessonIndex); + + boolean hasAttend = hasAttend(); + Attendance attendance = new Attendance(moduleCode, Integer.toString(studentIndex), + Integer.toString(lessonIndex), hasAttend); + student.setAttendance(attendance); + + AttendanceList attendances = module.getAttendanceList(); + module.addAttendances(attendances, student); + + ui.printMessage(String.format(MESSAGE_FORMAT_SET_ATTENDANCE, + student.getName(), attendance.markAttendance(), attendance.getLessonNum())); + } + + private void checkIfArgumentIsEmpty() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + } + + private void checkIfArgumentIsMissing() throws TaaException { + if (!checkArgumentMap()) { + throw new TaaException(getMissingArgumentMessage()); + } + } + + private void checkIfModuleListIsEmpty(Module module) throws TaaException { + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + } + + private void checkIfStudentsIsEmpty(ArrayList students) throws TaaException { + if (students.isEmpty()) { + throw new TaaException(MESSAGE_NO_STUDENTS); + } + } + + private void checkIfStudentNumIsInteger(String studentNum) throws TaaException { + boolean isStudentNumAnInteger = Util.isStringInteger(studentNum); + if (!isStudentNumAnInteger) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + } + + private void checkIfStudentNumOutOfBounds(Module module, String studentNum) throws TaaException { + if (Integer.parseInt(studentNum) > module.getStudentCount() || Integer.parseInt(studentNum) < MIN_STUDENT_NUM) { + throw new TaaException(MESSAGE_STUDENT_INDEX_OUT_OF_BOUNDS); + } + } + + private void checkIfLessonNumIsInteger(String lessonNum) throws TaaException { + boolean isLessonNumAnInteger = Util.isStringInteger(lessonNum); + if (!isLessonNumAnInteger) { + throw new TaaException(MESSAGE_INVALID_LESSON_INDEX); + } + } + + private void checkIfLessonIndexOutOfBounds(int lessonIndex) throws TaaException { + if (lessonIndex > MAX_LESSON_INDEX || lessonIndex < MIN_LESSON_INDEX) { + throw new TaaException(MESSAGE_LESSON_INDEX_OUT_OF_BOUNDS); + } + } + + /** + * Returns whether a student has attended a lesson, based on the attendance mark the user inputs + * + * @return whether a student has attended a lesson + * @throws TaaException If the user enters an invalid attendance mark + */ + private boolean hasAttend() throws TaaException { + if (argumentMap.get(KEY_ATTENDANCE_MARK).equals(ATTENDANCE_MARK_PRESENT)) { + return true; + } else if (argumentMap.get(KEY_ATTENDANCE_MARK).equals(ATTENDANCE_MARK_ABSENT)) { + return false; + } else { + throw new TaaException(MESSAGE_INVALID_ATTENDANCE); + } + } + + @Override + protected String getUsageMessage() { + return String.format( + MESSAGE_FORMAT_SET_ATTENDANCE_USAGE, + COMMAND_SET_ATTENDANCE, + KEY_MODULE_CODE, + KEY_STUDENT_NUM, + KEY_LESSON_NUM, + KEY_ATTENDANCE_MARK + ); + } +} diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index b891398bde..587e757ceb 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -2,9 +2,12 @@ import taa.assessment.Assessment; import taa.assessment.AssessmentList; +import taa.attendance.Attendance; +import taa.attendance.AttendanceList; import taa.student.Student; import java.util.ArrayList; +import java.util.Arrays; public class Module { private static final double MAX_ASSESSMENT_WEIGHTAGE = 1; @@ -13,12 +16,16 @@ public class Module { private int lessonCount; private final ArrayList students; private final AssessmentList assessmentList; + private final AttendanceList attendanceList; + private static final int NUM_LESSONS = 13; + private final int[] lessonArray = new int[NUM_LESSONS]; public Module(String code, String name) { this.code = code; this.name = name; this.students = new ArrayList<>(); this.assessmentList = new AssessmentList(); + this.attendanceList = new AttendanceList(); } public String getCode() { @@ -100,6 +107,47 @@ public int getAssessmentsCount() { return assessmentList.getSize(); } + public int getAttendanceCount() { + return attendanceList.getSize(); + } + + + public ArrayList getAttendances() { + return attendanceList.getAttendances(); + } + + public AttendanceList getAttendanceList() { + return attendanceList; + } + + public void addAttendances(AttendanceList attendances, Student student){ + attendances.addIndividualAttendances(student.getIndividualAttendances()); + } + + private String getLessonArrayAsString(){ + buildLessonArray(); + return Arrays.toString(lessonArray); + } + + private int[] buildLessonArray(){ + for (int i = 0; i < NUM_LESSONS; i++){ + lessonArray[i] = i + 1; + } + return lessonArray; + } + + public String getFormattedLessons(){ + String lessons = getLessonArrayAsString(); + String singleDigitLessons = lessons.substring(0, 27); + String doubleDigitLessons = lessons.substring(28); + singleDigitLessons = singleDigitLessons.replace(",", " |"); + doubleDigitLessons = doubleDigitLessons.replace(", ", " |"); + lessons = singleDigitLessons + doubleDigitLessons; + lessons = lessons.replace("[", " | "); + lessons = lessons.replace("]", " |"); + return lessons; + } + @Override public String toString() { if (name.isEmpty()) { diff --git a/src/main/java/taa/student/Attendance.java b/src/main/java/taa/student/Attendance.java deleted file mode 100644 index d85c34e4f5..0000000000 --- a/src/main/java/taa/student/Attendance.java +++ /dev/null @@ -1,20 +0,0 @@ -package taa.student; - -public class Attendance { - private int lessonNum; - private boolean hadAttend; - - public Attendance(int lessonNum) { - this.lessonNum = lessonNum; - this.hadAttend = false; - } - - public int markAttendance() { - return (hadAttend ? 1 : 0); - } - - @Override - public String toString() { - return lessonNum + " - " + markAttendance(); - } -} diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index e033693c2a..bb7cc87b10 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -1,5 +1,7 @@ package taa.student; +import taa.attendance.Attendance; + /** * Represents students. */ @@ -8,30 +10,40 @@ public class Student { private String id; private String name; - private final boolean[] attendance = new boolean[NUM_LESSONS]; + private final String[] individualAttendances = new String[NUM_LESSONS]; + private static final String ABSENT_MARK = "0"; public Student(String id, String name) { this.id = id; this.name = name; } + private void initIndividualAttendances(){ + for (int i = 0; i < NUM_LESSONS; i++){ + individualAttendances[i] = ABSENT_MARK; + } + } + /** - * Marks the student as present for a particular lesson. + * Marks the student as present or absent for a particular lesson. * - * @param lessonIndex The lesson index the student is present for + * @param attendance */ - public void markAttendance(int lessonIndex) { - attendance[lessonIndex] = true; + public void setAttendance(Attendance attendance) { + int lessonIndex = Integer.parseInt(attendance.getLessonIndex()); + initIndividualAttendances(); + individualAttendances[lessonIndex] = attendance.markAttendance(); } + /** * Returns the attendance status of the student for a particular lesson. * * @param lessonIndex The lesson index * @return The attendance status of the student for the lesson */ - public boolean isPresent(int lessonIndex) { - return attendance[lessonIndex]; + public String isPresent(int lessonIndex) { + return individualAttendances[lessonIndex]; } /** @@ -70,6 +82,12 @@ public String getId() { return this.id; } + public String[] getIndividualAttendances() { + return individualAttendances; + } + + + /** * Overrides default toString method with the custom print message. * diff --git a/src/test/java/taa/attendance/AttendanceTest.java b/src/test/java/taa/attendance/AttendanceTest.java new file mode 100644 index 0000000000..119b6306b0 --- /dev/null +++ b/src/test/java/taa/attendance/AttendanceTest.java @@ -0,0 +1,19 @@ +package taa.attendance; + +import org.junit.jupiter.api.Test; +import taa.attendance.Attendance; +import taa.command.SetAttendanceCommand; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +class AttendanceTest { + + + @Test + void testAttendance() { + assertEquals("CS2113T 2 3 true", + new Attendance("CS2113T", "2", "3", true).toString()); + } + + +} \ No newline at end of file diff --git a/src/test/java/taa/student/AttendanceTest.java b/src/test/java/taa/student/AttendanceTest.java deleted file mode 100644 index 202f847c7e..0000000000 --- a/src/test/java/taa/student/AttendanceTest.java +++ /dev/null @@ -1,14 +0,0 @@ -package taa.student; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.assertEquals; - -class AttendanceTest { - - @Test - void testAttendanceStringConversion() { - assertEquals("1 - 0", - new Attendance(1).toString()); - } -} \ No newline at end of file From dbe37c852414c6218c0432dd14c53b46c8917a92 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Tue, 12 Oct 2021 16:12:28 +0800 Subject: [PATCH 102/543] fix merging errors --- src/main/java/taa/Parser.java | 2 ++ src/main/java/taa/command/ListAttendanceCommand.java | 2 +- src/main/java/taa/command/SetAttendanceCommand.java | 6 +++--- src/main/java/taa/student/Student.java | 2 ++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index f5d797b642..843d7b6067 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -3,6 +3,7 @@ import taa.command.AddAssessmentCommand; import taa.command.AddModuleCommand; import taa.command.AddStudentCommand; +import taa.command.SetAttendanceCommand; import taa.command.AverageMarksCommand; import taa.command.Command; import taa.command.DeleteStudentCommand; @@ -13,6 +14,7 @@ import taa.command.ListMarksCommand; import taa.command.ListModulesCommand; import taa.command.ListStudentsCommand; +import taa.command.ListAttendanceCommand; import taa.command.SetMarksCommand; import taa.exception.TaaException; diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/ListAttendanceCommand.java index 4fbfabb338..12d898cda5 100644 --- a/src/main/java/taa/command/ListAttendanceCommand.java +++ b/src/main/java/taa/command/ListAttendanceCommand.java @@ -39,7 +39,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { Module module = moduleList.getModule(moduleCode); checkIfModuleListIsEmpty(module); - ArrayList students = module.getStudents(); + ArrayList students = module.getStudentList().getStudents(); checkIfStudentsIsEmpty(students); ArrayList attendances = module.getAttendances(); diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index 467291ec4a..202323c4bd 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -51,7 +51,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { Module module = moduleList.getModule(moduleCode); checkIfModuleListIsEmpty(module); - ArrayList students = module.getStudents(); + ArrayList students = module.getStudentList().getStudents(); checkIfStudentsIsEmpty(students); String studentNum = argumentMap.get(KEY_STUDENT_NUM); @@ -59,7 +59,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { checkIfStudentNumOutOfBounds(module, studentNum); int studentIndex = Integer.parseInt(studentNum) - 1; - Student student = module.getStudentAt(studentIndex); + Student student = module.getStudentList().getStudentAt(studentIndex); String lessonNum = argumentMap.get(KEY_LESSON_NUM); checkIfLessonNumIsInteger(lessonNum); @@ -111,7 +111,7 @@ private void checkIfStudentNumIsInteger(String studentNum) throws TaaException { } private void checkIfStudentNumOutOfBounds(Module module, String studentNum) throws TaaException { - if (Integer.parseInt(studentNum) > module.getStudentCount() || Integer.parseInt(studentNum) < MIN_STUDENT_NUM) { + if (Integer.parseInt(studentNum) > module.getStudentList().getSize() || Integer.parseInt(studentNum) < MIN_STUDENT_NUM) { throw new TaaException(MESSAGE_STUDENT_INDEX_OUT_OF_BOUNDS); } } diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index 5fe5ca07f2..2565314cd3 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -9,6 +9,8 @@ * Represents students. */ public class Student { + private static final int NUM_LESSONS = 13; + private String id; private String name; private final String[] individualAttendances = new String[NUM_LESSONS]; From 8d775bcc3b515df9e8c7f89a86b5fbd10ad1aeab Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Tue, 12 Oct 2021 16:19:45 +0800 Subject: [PATCH 103/543] fix checkstyle issues --- src/main/java/taa/attendance/AttendanceList.java | 4 ++-- src/main/java/taa/command/ListAttendanceCommand.java | 6 +++--- src/main/java/taa/command/SetAttendanceCommand.java | 11 ++++++----- src/main/java/taa/module/Module.java | 10 +++++----- src/main/java/taa/student/Student.java | 7 +++---- 5 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/java/taa/attendance/AttendanceList.java b/src/main/java/taa/attendance/AttendanceList.java index ee537f8876..c398c949b7 100644 --- a/src/main/java/taa/attendance/AttendanceList.java +++ b/src/main/java/taa/attendance/AttendanceList.java @@ -22,7 +22,7 @@ public ArrayList getAttendances() { } /** - * Converts the array of attendances from all lessons for a student to a string + * Converts the array of attendances from all lessons for a student to a string. * * @param individualAttendances the array of attendances from all lessons for a student * @return String representation of the array of attendances from all lessons for a student @@ -32,7 +32,7 @@ public String individualAttendancesToString(String[] individualAttendances) { } /** - * Adds the array of attendances from all lessons for a student to the AttendanceList + * Adds the array of attendances from all lessons for a student to the AttendanceList. * * @param individualAttendances the array of attendances from all lessons for a student */ diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/ListAttendanceCommand.java index 12d898cda5..0b66717380 100644 --- a/src/main/java/taa/command/ListAttendanceCommand.java +++ b/src/main/java/taa/command/ListAttendanceCommand.java @@ -25,7 +25,7 @@ public ListAttendanceCommand(String argument) { super(argument, LIST_ATTENDANCE_ARGUMENT_KEYS); } - /** + /** Lists out the attendance for all students in a module. * @param moduleList The list of modules * @param ui The ui instance to handle interactions with the user * @throws TaaException If the user inputs an invalid command @@ -97,7 +97,7 @@ private void buildString(StringBuilder stringBuilder, Module module, ArrayList module.getStudentList().getSize() || Integer.parseInt(studentNum) < MIN_STUDENT_NUM) { + if (Integer.parseInt(studentNum) > module.getStudentList().getSize() + || Integer.parseInt(studentNum) < MIN_STUDENT_NUM) { throw new TaaException(MESSAGE_STUDENT_INDEX_OUT_OF_BOUNDS); } } @@ -130,7 +131,7 @@ private void checkIfLessonIndexOutOfBounds(int lessonIndex) throws TaaException } /** - * Returns whether a student has attended a lesson, based on the attendance mark the user inputs + * Returns whether a student has attended a lesson, based on the attendance mark the user inputs. * * @return whether a student has attended a lesson * @throws TaaException If the user enters an invalid attendance mark diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index 8dec92a365..e1f0083261 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -65,23 +65,23 @@ public AttendanceList getAttendanceList() { return attendanceList; } - public void addAttendances(AttendanceList attendances, Student student){ + public void addAttendances(AttendanceList attendances, Student student) { attendances.addIndividualAttendances(student.getIndividualAttendances()); } - private String getLessonArrayAsString(){ + private String getLessonArrayAsString() { buildLessonArray(); return Arrays.toString(lessonArray); } - private int[] buildLessonArray(){ - for (int i = 0; i < NUM_LESSONS; i++){ + private int[] buildLessonArray() { + for (int i = 0; i < NUM_LESSONS; i++) { lessonArray[i] = i + 1; } return lessonArray; } - public String getFormattedLessons(){ + public String getFormattedLessons() { String lessons = getLessonArrayAsString(); String singleDigitLessons = lessons.substring(0, 27); String doubleDigitLessons = lessons.substring(28); diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index 2565314cd3..6c9571b47d 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -27,8 +27,8 @@ public Student(String id, String name) { this.results = new HashMap<>(); } - private void initIndividualAttendances(){ - for (int i = 0; i < NUM_LESSONS; i++){ + private void initIndividualAttendances() { + for (int i = 0; i < NUM_LESSONS; i++) { individualAttendances[i] = ABSENT_MARK; } } @@ -96,7 +96,6 @@ public String[] getIndividualAttendances() { } - /** * Overrides default toString method with the custom print message. * @@ -111,7 +110,7 @@ public String toString() { * Adds a key,value pair to the hashmap. * * @param assessmentName key of the hashmap - * @param marks value to be stored under the key given + * @param marks value to be stored under the key given */ public void setMarks(String assessmentName, double marks) { results.put(assessmentName, marks); From 21971459f03adeff4a962cb9cdad93d6304dc27d Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Tue, 12 Oct 2021 16:21:56 +0800 Subject: [PATCH 104/543] fix checkstyle issues --- src/main/java/taa/command/SetAttendanceCommand.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index 5e677324ab..0197ed7d5f 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -21,8 +21,7 @@ public class SetAttendanceCommand extends Command { private static final String KEY_ATTENDANCE_MARK = "attend"; private static final String ATTENDANCE_MARK_PRESENT = "1"; private static final String ATTENDANCE_MARK_ABSENT = "0"; - private static final String[] SET_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_NUM, KEY_LESSON_NUM, - KEY_ATTENDANCE_MARK}; + private static final String[] SET_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_NUM, KEY_LESSON_NUM, KEY_ATTENDANCE_MARK}; private static final int MIN_STUDENT_NUM = 1; private static final int MAX_LESSON_INDEX = 12; From 8c6c4998038e611f8e1715e5a88c6dcfb5b1b885 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Tue, 12 Oct 2021 16:25:14 +0800 Subject: [PATCH 105/543] fix checkstyle issues --- src/main/java/taa/command/SetAttendanceCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index 0197ed7d5f..5e677324ab 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -21,7 +21,8 @@ public class SetAttendanceCommand extends Command { private static final String KEY_ATTENDANCE_MARK = "attend"; private static final String ATTENDANCE_MARK_PRESENT = "1"; private static final String ATTENDANCE_MARK_ABSENT = "0"; - private static final String[] SET_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_NUM, KEY_LESSON_NUM, KEY_ATTENDANCE_MARK}; + private static final String[] SET_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_NUM, KEY_LESSON_NUM, + KEY_ATTENDANCE_MARK}; private static final int MIN_STUDENT_NUM = 1; private static final int MAX_LESSON_INDEX = 12; From bba35cb204d6fc73e26655ee38b62c6694acacb5 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Tue, 12 Oct 2021 16:30:36 +0800 Subject: [PATCH 106/543] fix checkstyle issues --- src/main/java/taa/command/SetAttendanceCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index 5e677324ab..848d3fd843 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -22,7 +22,7 @@ public class SetAttendanceCommand extends Command { private static final String ATTENDANCE_MARK_PRESENT = "1"; private static final String ATTENDANCE_MARK_ABSENT = "0"; private static final String[] SET_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_NUM, KEY_LESSON_NUM, - KEY_ATTENDANCE_MARK}; + KEY_ATTENDANCE_MARK}; private static final int MIN_STUDENT_NUM = 1; private static final int MAX_LESSON_INDEX = 12; From b05e78fdff4bf965c7090258b2fc98b8155ab04b Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 19:40:36 +0800 Subject: [PATCH 107/543] Store attendance in Student class, change list_attendance to print for 1 student, change some message formats --- .../java/taa/assessment/AssessmentList.java | 11 +- src/main/java/taa/attendance/Attendance.java | 31 ++-- .../java/taa/attendance/AttendanceList.java | 58 +++---- .../taa/command/AddAssessmentCommand.java | 6 +- .../java/taa/command/AddModuleCommand.java | 2 +- .../java/taa/command/AddStudentCommand.java | 2 +- .../java/taa/command/AverageMarksCommand.java | 2 +- src/main/java/taa/command/Command.java | 15 +- .../taa/command/DeleteStudentCommand.java | 4 +- .../java/taa/command/EditStudentCommand.java | 5 +- .../java/taa/command/FindStudentCommand.java | 11 +- .../taa/command/ListAssessmentsCommand.java | 11 +- .../taa/command/ListAttendanceCommand.java | 117 +++---------- .../java/taa/command/ListMarksCommand.java | 3 +- .../java/taa/command/ListModulesCommand.java | 9 +- .../java/taa/command/ListStudentsCommand.java | 11 +- .../taa/command/SetAttendanceCommand.java | 158 +++++++----------- .../java/taa/command/SetMarksCommand.java | 9 +- src/main/java/taa/module/Module.java | 63 +------ src/main/java/taa/module/ModuleList.java | 9 +- src/main/java/taa/student/Student.java | 84 +++------- src/main/java/taa/student/StudentList.java | 14 +- .../java/taa/attendance/AttendanceTest.java | 8 +- 23 files changed, 221 insertions(+), 422 deletions(-) diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 4aafc16251..75c987c500 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -3,8 +3,6 @@ import java.util.ArrayList; public class AssessmentList { - private static final String MESSAGE_ASSESSMENT_LIST_HEADER = "Assessment List:"; - private final ArrayList assessments; public AssessmentList() { @@ -25,6 +23,8 @@ public boolean addAssessment(Assessment assessment) { if (a.getName().equalsIgnoreCase(assessment.getName())) { return false; } + + totalWeightage += a.getWeightage(); } if ((totalWeightage + assessment.getWeightage()) > Assessment.WEIGHTAGE_RANGE[1]) { @@ -68,9 +68,12 @@ public int getSize() { @Override public String toString() { - StringBuilder stringBuilder = new StringBuilder(MESSAGE_ASSESSMENT_LIST_HEADER); + StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < assessments.size(); i += 1) { - stringBuilder.append("\n"); + if (i > 0) { + stringBuilder.append("\n"); + } + stringBuilder.append(i + 1); stringBuilder.append(". "); stringBuilder.append(assessments.get(i)); diff --git a/src/main/java/taa/attendance/Attendance.java b/src/main/java/taa/attendance/Attendance.java index ac9bb6a040..2c3888c0df 100644 --- a/src/main/java/taa/attendance/Attendance.java +++ b/src/main/java/taa/attendance/Attendance.java @@ -1,34 +1,27 @@ package taa.attendance; public class Attendance { - private final String code; - private final String studentIndex; - private final String lessonIndex; - private boolean hasAttend; + private static final String MESSAGE_FORMAT_ATTENDANCE = "Lesson %d (%s)"; - public Attendance(String code, String studentIndex, String lessonIndex, boolean hasAttend) { - this.code = code; - this.studentIndex = studentIndex; - this.lessonIndex = lessonIndex; - this.hasAttend = hasAttend; - } + private final int lessonNumber; + private boolean isPresent; - public String markAttendance() { - return (hasAttend ? "1" : "0"); + public Attendance(int lessonNumber, boolean isPresent) { + this.lessonNumber = lessonNumber; + this.isPresent = isPresent; } - public String getLessonIndex() { - return lessonIndex; + public void setPresent(boolean present) { + isPresent = present; } - public String getLessonNum() { - return Integer.toString(Integer.parseInt(lessonIndex) + 1); + public int getLessonNumber() { + return lessonNumber; } - @Override public String toString() { - return String.format("%s %s %s %s", code, studentIndex, lessonIndex, hasAttend); + String presentString = (isPresent) ? "Present" : "Absent"; + return String.format(MESSAGE_FORMAT_ATTENDANCE, lessonNumber, presentString); } } - diff --git a/src/main/java/taa/attendance/AttendanceList.java b/src/main/java/taa/attendance/AttendanceList.java index c398c949b7..9041695952 100644 --- a/src/main/java/taa/attendance/AttendanceList.java +++ b/src/main/java/taa/attendance/AttendanceList.java @@ -2,12 +2,10 @@ import java.util.ArrayList; -import java.util.Arrays; +import java.util.Comparator; public class AttendanceList { - private static final String MESSAGE_ATTENDANCE_LIST_HEADER = "Attendance List:"; - - private final ArrayList attendances; + private final ArrayList attendances; public AttendanceList() { this.attendances = new ArrayList<>(); @@ -17,43 +15,42 @@ public int getSize() { return attendances.size(); } - public ArrayList getAttendances() { - return attendances; + public ArrayList getAttendances() { + return new ArrayList<>(attendances); } - /** - * Converts the array of attendances from all lessons for a student to a string. - * - * @param individualAttendances the array of attendances from all lessons for a student - * @return String representation of the array of attendances from all lessons for a student - */ - public String individualAttendancesToString(String[] individualAttendances) { - return Arrays.toString(individualAttendances); + public Attendance getAttendance(int lessonNumber) { + for (Attendance attendance : attendances) { + if (attendance.getLessonNumber() == lessonNumber) { + return attendance; + } + } + + return null; } - /** - * Adds the array of attendances from all lessons for a student to the AttendanceList. - * - * @param individualAttendances the array of attendances from all lessons for a student - */ - public void addIndividualAttendances(String[] individualAttendances) { - String studentAttendances = individualAttendancesToString(individualAttendances); - String formattedStudentAttendances = formatStudentAttendances(studentAttendances); - attendances.add(formattedStudentAttendances); + public void addAttendance(Attendance attendance) { + attendances.add(attendance); + sortAttendances(); } - private String formatStudentAttendances(String studentAttendances) { - studentAttendances = studentAttendances.replace("[", " | "); - studentAttendances = studentAttendances.replace("]", " |"); - studentAttendances = studentAttendances.replace(",", " |"); - return studentAttendances; + private void sortAttendances() { + attendances.sort(new Comparator() { + @Override + public int compare(Attendance attendance1, Attendance attendance2) { + return attendance1.getLessonNumber() - attendance2.getLessonNumber(); + } + }); } @Override public String toString() { - StringBuilder stringBuilder = new StringBuilder(MESSAGE_ATTENDANCE_LIST_HEADER); + StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < getSize(); i += 1) { - stringBuilder.append("\n"); + if (i > 0) { + stringBuilder.append("\n"); + } + stringBuilder.append(i + 1); stringBuilder.append(". "); stringBuilder.append(attendances.get(i)); @@ -63,4 +60,3 @@ public String toString() { } } - diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 046aa6c636..14d2520954 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -20,8 +20,8 @@ public class AddAssessmentCommand extends Command { + "%s/ %s/ %s/"; private static final String MESSAGE_FORMAT_INVALID_WEIGHTAGE = "Invalid weightage. " + "Weightage must be between %,.2f and %,.2f (inclusive)"; - private static final String MESSAGE_FORMAT_ASSESSMENT_ADDED = - "Assessment added:\n %s\nThere are %d assessments in the %s."; + private static final String MESSAGE_FORMAT_ASSESSMENT_ADDED = "Assessment added:\n" + + " %s\nThere are %d assessments in the %s."; public AddAssessmentCommand(String argument) { super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); @@ -40,7 +40,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(getUsageMessage()); } - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index f8da9cb44d..b286a3bf1d 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -26,7 +26,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(getUsageMessage()); } - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index afad77d797..0df56616a3 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -34,7 +34,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(getUsageMessage()); } - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index d01ff0b752..0f3194afc7 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -41,7 +41,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(getUsageMessage()); } - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 14fc7c14c5..5878761dd9 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -24,20 +24,15 @@ public abstract class Command { public static final String COMMAND_ADD_ASSESSMENT = "add_assessment"; public static final String COMMAND_SET_MARKS = "set_marks"; + // Common messages protected static final String MESSAGE_UNKNOWN_USAGE = "Unknown usage."; protected static final String MESSAGE_MODULE_NOT_FOUND = "Module not found."; protected static final String MESSAGE_INVALID_STUDENT_INDEX = "Invalid student index."; - - protected static final String MESSAGE_STUDENT_INDEX_OUT_OF_BOUNDS = "Student index is out of bounds."; protected static final String MESSAGE_INVALID_LESSON_INDEX = "Invalid lesson index."; - protected static final String MESSAGE_LESSON_INDEX_OUT_OF_BOUNDS = "Lesson index is out of bounds."; - protected static final String MESSAGE_INVALID_ATTENDANCE = "Invalid attendance."; - protected static final String MESSAGE_ATTENDANCE_LIST_EMPTY = "There is no recorded attendance in the module."; - protected static final String MESSAGE_INVALID_ASSESSMENT_NAME = "Invalid assessment name."; protected static final String MESSAGE_NO_STUDENTS = "There are no students in this module"; - + // Common message formats protected static final String MESSAGE_FORMAT_GENERIC_USAGE = "Usage: %s"; protected static final String MESSAGE_FORMAT_MISSING_ARGUMENT = "Missing Argument(s).\n%s"; @@ -66,11 +61,11 @@ public boolean isExit() { protected abstract String getUsageMessage(); /** - * Checks if argumentMap contains all the argument keys. + * Checks if there are any missing arguments. * - * @return true if argumentMap contains all keys, else false. + * @return true if there no missing arguments, else false. */ - protected boolean checkArgumentMap() { + protected boolean checkArguments() { for (String key : argumentKeys) { if (!argumentMap.containsKey(key)) { return false; diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 6aea535ace..84d3cdbad8 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -34,7 +34,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(getUsageMessage()); } - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } @@ -53,7 +53,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { StudentList studentList = module.getStudentList(); Student student = studentList.deleteStudent(studentIndex); if (student == null) { - ui.printMessage(MESSAGE_INVALID_STUDENT_INDEX); + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } ui.printMessage(String.format(MESSAGE_FORMAT_STUDENT_DELETED, moduleCode, student)); diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index c4ce97c060..e1928aec38 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -41,7 +41,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(getUsageMessage()); } - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } @@ -60,8 +60,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { StudentList studentList = module.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { - ui.printMessage(MESSAGE_INVALID_STUDENT_INDEX); - return; + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } String newId = argumentMap.get(KEY_NEW_ID); diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 3959c70d42..03ed8ec70c 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -27,9 +27,9 @@ public FindStudentCommand(String argument) { /** * Finds the students taking a particular module containing a particular keyword. * - * @param moduleList The list of modules - * @param ui The ui instance to handle interactions with the user - * @throws TaaException If the user inputs an invalid command + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @throws TaaException If the user inputs an invalid command. */ @Override public void execute(ModuleList moduleList, Ui ui) throws TaaException { @@ -37,7 +37,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(getUsageMessage()); } - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } @@ -51,8 +51,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { StudentList studentList = module.getStudentList(); ArrayList studentsFound = studentList.findStudents(keyword); if (studentsFound.isEmpty()) { - ui.printMessage(MESSAGE_NO_STUDENTS_FOUND); - return; + throw new TaaException(MESSAGE_NO_STUDENTS_FOUND); } String header = String.format(MESSAGE_FORMAT_STUDENT_FOUND_HEADER, moduleCode, keyword); diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index 9347512599..3dde4d67df 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -13,6 +13,7 @@ public class ListAssessmentsCommand extends Command { private static final String MESSAGE_LIST_EMPTY = "There are no assessments in the module."; private static final String MESSAGE_FORMAT_LIST_ASSESSMENTS_USAGE = "Usage: %s %s/"; + private static final String MESSAGE_FORMAT_OUTPUT = "Assessments for %s:\n%s"; public ListAssessmentsCommand(String argument) { super(argument, LIST_ASSESSMENTS_ARGUMENT_KEYS); @@ -31,7 +32,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(getUsageMessage()); } - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } @@ -41,13 +42,15 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } + String message; AssessmentList assessmentList = module.getAssessmentList(); if (assessmentList.getSize() == 0) { - ui.printMessage(MESSAGE_LIST_EMPTY); - return; + message = MESSAGE_LIST_EMPTY; + } else { + message = String.format(MESSAGE_FORMAT_OUTPUT, module, assessmentList); } - ui.printMessage(assessmentList.toString()); + ui.printMessage(message); } @Override diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/ListAttendanceCommand.java index 0b66717380..3b294a95b8 100644 --- a/src/main/java/taa/command/ListAttendanceCommand.java +++ b/src/main/java/taa/command/ListAttendanceCommand.java @@ -6,20 +6,17 @@ import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; - -import java.util.ArrayList; +import taa.student.StudentList; +import taa.util.Util; public class ListAttendanceCommand extends Command { private static final String KEY_MODULE_CODE = "c"; - private static final String[] LIST_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE}; - - private static final String MESSAGE_ATTENDANCE_LIST_HEADER = "Attendance List:"; + private static final String KEY_STUDENT_INDEX = "s"; + private static final String[] LIST_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX}; - private static final String MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE = "Usage: %s %s/"; - private static final int SPACE_FOR_NAME = 25; - private static final int BEGIN_INDEX = 0; - private static final int SPACE_FOR_TRIMMED_NAME = 22; - private static final String LESSONS_TITLE = "LESSON NUMBER"; + private static final String MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE = "Usage: %s %s/ %s/"; + protected static final String MESSAGE_FORMAT_NO_ATTENDANCE = "There is no recorded attendance for %s."; + private static final String MESSAGE_FORMAT_OUTPUT = "Attendance for %s:\n%s"; public ListAttendanceCommand(String argument) { super(argument, LIST_ATTENDANCE_ARGUMENT_KEYS); @@ -32,110 +29,50 @@ public ListAttendanceCommand(String argument) { */ @Override public void execute(ModuleList moduleList, Ui ui) throws TaaException { - checkIfArgumentIsEmpty(); - checkIfArgumentIsMissing(); - - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); - checkIfModuleListIsEmpty(module); - - ArrayList students = module.getStudentList().getStudents(); - checkIfStudentsIsEmpty(students); - - ArrayList attendances = module.getAttendances(); - checkIfAttendancesIsEmpty(attendances); - - StringBuilder stringBuilder = new StringBuilder(MESSAGE_ATTENDANCE_LIST_HEADER); - buildString(stringBuilder, module, students, attendances); - - ui.printMessage(stringBuilder.toString()); - } - - private void checkIfArgumentIsEmpty() throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } - } - private void checkIfArgumentIsMissing() throws TaaException { - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } - } - private void checkIfModuleListIsEmpty(Module module) throws TaaException { + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModule(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - } - private void checkIfStudentsIsEmpty(ArrayList students) throws TaaException { - if (students.isEmpty()) { - throw new TaaException(MESSAGE_NO_STUDENTS); + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - } + int studentIndex = Integer.parseInt(studentIndexInput) - 1; - private void checkIfAttendancesIsEmpty(ArrayList attendances) throws TaaException { - if (attendances.isEmpty()) { - throw new TaaException(MESSAGE_ATTENDANCE_LIST_EMPTY); + StudentList studentList = module.getStudentList(); + Student student = studentList.getStudentAt(studentIndex); + if (student == null) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - } - private void buildString(StringBuilder stringBuilder, Module module, ArrayList students, - ArrayList attendances) { - stringBuilder.append("\n"); - stringBuilder.append(padWithWhiteSpace(LESSONS_TITLE, LESSONS_TITLE.length())); - stringBuilder.append(module.getFormattedLessons()); - for (int i = 0; i < attendances.size(); i += 1) { - stringBuilder.append("\n"); - stringBuilder.append(i + 1); - stringBuilder.append(". "); - String trimmedStudentName = trimName(students.get(i).getName(), i + 1); - stringBuilder.append(trimmedStudentName); - stringBuilder.append(attendances.get(i)); + String message; + AttendanceList attendanceList = student.getAttendanceList(); + if (attendanceList.getSize() == 0) { + message = String.format(MESSAGE_FORMAT_NO_ATTENDANCE, student); + } else { + message = String.format(MESSAGE_FORMAT_OUTPUT, student, attendanceList); } - } - /** - * Trims the student's name if it is too long. - * - * @param studentName name of the student - * @param number the length of the list number - * @return truncated student name or student name with whitespace - */ - private String trimName(String studentName, int number) { - int lengthOfDot = 2; - int lengthOfNumber = ((number / 10) + 1) + lengthOfDot; - int lengthOfNumberAndName = lengthOfNumber + studentName.length(); - if (lengthOfNumberAndName > SPACE_FOR_NAME) { - return studentName.substring(BEGIN_INDEX, SPACE_FOR_TRIMMED_NAME - lengthOfNumber) + "..."; - } - return padWithWhiteSpace(studentName, lengthOfNumberAndName); + ui.printMessage(message); } - /** - * Pads a string with whitespace. - * - * @param stringToPad string to pad with whitespace - * @param lengthOfString length of the string to pad with whitespace - * @return string with whitespace - */ - private String padWithWhiteSpace(String stringToPad, int lengthOfString) { - int amountToPad = SPACE_FOR_NAME - lengthOfString; - for (int i = 0; i < amountToPad; i++) { - stringToPad = stringToPad + " "; - } - return stringToPad; - } - - @Override protected String getUsageMessage() { return String.format( MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE, COMMAND_LIST_ATTENDANCE, - KEY_MODULE_CODE + KEY_MODULE_CODE, + KEY_STUDENT_INDEX ); } - } diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index b15f1ef518..69a8f8bb22 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -55,7 +55,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } @@ -107,6 +107,7 @@ private void listMarks(Ui ui, Module module, Assessment assessment) { stringBuilder.append("NIL"); } } + if (studentIndex <= 0) { ui.printMessage(MARKS_LIST_EMPTY); } else { diff --git a/src/main/java/taa/command/ListModulesCommand.java b/src/main/java/taa/command/ListModulesCommand.java index 981b1f7626..78d1f21242 100644 --- a/src/main/java/taa/command/ListModulesCommand.java +++ b/src/main/java/taa/command/ListModulesCommand.java @@ -7,6 +7,8 @@ public class ListModulesCommand extends Command { private static final String MESSAGE_LIST_EMPTY = "There are no modules in the list."; + private static final String MESSAGE_FORMAT_OUTPUT = "Module list:\n%s"; + public ListModulesCommand(String argument) { super(argument); } @@ -17,11 +19,14 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(getUsageMessage()); } + String message; if (moduleList.getSize() == 0) { - ui.printMessage(MESSAGE_LIST_EMPTY); + message = MESSAGE_LIST_EMPTY; } else { - ui.printMessage(moduleList.toString()); + message = String.format(MESSAGE_FORMAT_OUTPUT, moduleList); } + + ui.printMessage(message); } @Override diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index b44aba896f..f3c3af917b 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -14,6 +14,7 @@ public class ListStudentsCommand extends Command { private static final String MESSAGE_FORMAT_LIST_STUDENT_USAGE = "Usage: %s " + "%s/"; + private static final String MESSAGE_FORMAT_OUTPUT = "Students for %s:\n%s"; public ListStudentsCommand(String argument) { super(argument, LIST_STUDENT_ARGUMENT_KEYS); @@ -32,7 +33,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(getUsageMessage()); } - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } @@ -42,13 +43,15 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } + String message; StudentList studentList = module.getStudentList(); if (studentList.getSize() == 0) { - ui.printMessage(MESSAGE_NO_STUDENTS); - return; + message = MESSAGE_NO_STUDENTS; + } else { + message = String.format(MESSAGE_FORMAT_OUTPUT, module, studentList); } - ui.printMessage(studentList.toString()); + ui.printMessage(message); } @Override diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index 848d3fd843..8087bf5d0b 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -7,30 +7,33 @@ import taa.module.Module; import taa.module.ModuleList; import taa.student.Student; +import taa.student.StudentList; import taa.util.Util; -import java.util.ArrayList; - public class SetAttendanceCommand extends Command { - private static final String MESSAGE_FORMAT_SET_ATTENDANCE = - "Attendance set:\n %s - %s\nfor Lesson %s"; - private static final String KEY_MODULE_CODE = "c"; - private static final String KEY_STUDENT_NUM = "s"; - private static final String KEY_LESSON_NUM = "l"; - private static final String KEY_ATTENDANCE_MARK = "attend"; - private static final String ATTENDANCE_MARK_PRESENT = "1"; - private static final String ATTENDANCE_MARK_ABSENT = "0"; - private static final String[] SET_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_NUM, KEY_LESSON_NUM, - KEY_ATTENDANCE_MARK}; - - private static final int MIN_STUDENT_NUM = 1; - private static final int MAX_LESSON_INDEX = 12; - private static final int MIN_LESSON_INDEX = 0; + private static final String KEY_STUDENT_INDEX = "s"; + private static final String KEY_LESSON_NUMBER = "l"; + private static final String KEY_PRESENT = "p"; + private static final String[] SET_ATTENDANCE_ARGUMENT_KEYS = { + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_LESSON_NUMBER, + KEY_PRESENT + }; + + private static final String MESSAGE_INVALID_LESSON_NUMBER = "Invalid lesson number."; + + private static final String MESSAGE_FORMAT_INVALID_PRESENT = "Invalid present value.\n" + + "Possible values: %s (Present), %s (Absent)"; + private static final String MESSAGE_FORMAT_SET_ATTENDANCE = "Attendance set for %s:\n %s"; + + private static final int MIN_LESSON_NUMBER = 1; + private static final String PRESENT_VALUE = "1"; + private static final String ABSENT_VALUE = "0"; private static final String MESSAGE_FORMAT_SET_ATTENDANCE_USAGE = "Usage: %s " - + "%s/ %s/ %s/ %s/"; - + + "%s/ %s/ %s/ %s/"; public SetAttendanceCommand(String argument) { super(argument, SET_ATTENDANCE_ARGUMENT_KEYS); @@ -44,106 +47,67 @@ public SetAttendanceCommand(String argument) { * @throws TaaException If the user inputs an invalid command */ public void execute(ModuleList moduleList, Ui ui) throws TaaException { - checkIfArgumentIsEmpty(); - checkIfArgumentIsMissing(); - - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); - checkIfModuleListIsEmpty(module); - - ArrayList students = module.getStudentList().getStudents(); - checkIfStudentsIsEmpty(students); - - String studentNum = argumentMap.get(KEY_STUDENT_NUM); - checkIfStudentNumIsInteger(studentNum); - checkIfStudentNumOutOfBounds(module, studentNum); - - int studentIndex = Integer.parseInt(studentNum) - 1; - Student student = module.getStudentList().getStudentAt(studentIndex); - - String lessonNum = argumentMap.get(KEY_LESSON_NUM); - checkIfLessonNumIsInteger(lessonNum); - - int lessonIndex = Integer.parseInt(lessonNum) - 1; - checkIfLessonIndexOutOfBounds(lessonIndex); - - boolean hasAttend = hasAttend(); - Attendance attendance = new Attendance(moduleCode, Integer.toString(studentIndex), - Integer.toString(lessonIndex), hasAttend); - student.setAttendance(attendance); - - AttendanceList attendances = module.getAttendanceList(); - module.addAttendances(attendances, student); - - ui.printMessage(String.format(MESSAGE_FORMAT_SET_ATTENDANCE, - student.getName(), attendance.markAttendance(), attendance.getLessonNum())); - } - - private void checkIfArgumentIsEmpty() throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } - } - private void checkIfArgumentIsMissing() throws TaaException { - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } - } - private void checkIfModuleListIsEmpty(Module module) throws TaaException { + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModule(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - } - private void checkIfStudentsIsEmpty(ArrayList students) throws TaaException { - if (students.isEmpty()) { - throw new TaaException(MESSAGE_NO_STUDENTS); + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_LESSON_INDEX); } - } + int studentIndex = Integer.parseInt(studentIndexInput) - 1; - private void checkIfStudentNumIsInteger(String studentNum) throws TaaException { - boolean isStudentNumAnInteger = Util.isStringInteger(studentNum); - if (!isStudentNumAnInteger) { + StudentList studentList = module.getStudentList(); + Student student = studentList.getStudentAt(studentIndex); + if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - } - private void checkIfStudentNumOutOfBounds(Module module, String studentNum) throws TaaException { - if (Integer.parseInt(studentNum) > module.getStudentList().getSize() - || Integer.parseInt(studentNum) < MIN_STUDENT_NUM) { - throw new TaaException(MESSAGE_STUDENT_INDEX_OUT_OF_BOUNDS); + String lessonNumberInput = argumentMap.get(KEY_LESSON_NUMBER); + if (!Util.isStringInteger(lessonNumberInput)) { + throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); } - } - private void checkIfLessonNumIsInteger(String lessonNum) throws TaaException { - boolean isLessonNumAnInteger = Util.isStringInteger(lessonNum); - if (!isLessonNumAnInteger) { - throw new TaaException(MESSAGE_INVALID_LESSON_INDEX); + int lessonNumber = Integer.parseInt(lessonNumberInput); + if (lessonNumber < MIN_LESSON_NUMBER) { + throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); } - } - private void checkIfLessonIndexOutOfBounds(int lessonIndex) throws TaaException { - if (lessonIndex > MAX_LESSON_INDEX || lessonIndex < MIN_LESSON_INDEX) { - throw new TaaException(MESSAGE_LESSON_INDEX_OUT_OF_BOUNDS); + String present = argumentMap.get(KEY_PRESENT); + boolean isPresent; + switch (present) { + case PRESENT_VALUE: + isPresent = true; + break; + + case ABSENT_VALUE: + isPresent = false; + break; + + default: + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_PRESENT, PRESENT_VALUE, ABSENT_VALUE)); } - } - /** - * Returns whether a student has attended a lesson, based on the attendance mark the user inputs. - * - * @return whether a student has attended a lesson - * @throws TaaException If the user enters an invalid attendance mark - */ - private boolean hasAttend() throws TaaException { - if (argumentMap.get(KEY_ATTENDANCE_MARK).equals(ATTENDANCE_MARK_PRESENT)) { - return true; - } else if (argumentMap.get(KEY_ATTENDANCE_MARK).equals(ATTENDANCE_MARK_ABSENT)) { - return false; + AttendanceList attendanceList = student.getAttendanceList(); + Attendance attendance = attendanceList.getAttendance(lessonNumber); + if (attendance == null) { + attendance = new Attendance(lessonNumber, isPresent); + attendanceList.addAttendance(attendance); } else { - throw new TaaException(MESSAGE_INVALID_ATTENDANCE); + attendance.setPresent(isPresent); } + + ui.printMessage(String.format(MESSAGE_FORMAT_SET_ATTENDANCE, student.getName(), attendance)); } @Override @@ -152,9 +116,9 @@ protected String getUsageMessage() { MESSAGE_FORMAT_SET_ATTENDANCE_USAGE, COMMAND_SET_ATTENDANCE, KEY_MODULE_CODE, - KEY_STUDENT_NUM, - KEY_LESSON_NUM, - KEY_ATTENDANCE_MARK + KEY_STUDENT_INDEX, + KEY_LESSON_NUMBER, + KEY_PRESENT ); } } diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 23ab561d58..e3d660d3a5 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -50,7 +50,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } - if (!checkArgumentMap()) { + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } @@ -69,8 +69,7 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { StudentList studentList = module.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { - ui.printMessage(MESSAGE_INVALID_STUDENT_INDEX); - return; + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } AssessmentList assessmentList = module.getAssessmentList(); @@ -103,10 +102,8 @@ public void execute(ModuleList moduleList, Ui ui) throws TaaException { */ private void setMarks(Ui ui, Student student, Assessment assessment, double marks) { String assessmentName = assessment.getName(); - student.setMarks(assessmentName, marks); - String studentName = student.getName(); - ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_ADDED, studentName, marks, assessmentName)); + ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_ADDED, student, marks, assessmentName)); } /** diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index e1f0083261..a3d0b7f39d 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -1,31 +1,19 @@ package taa.module; import taa.assessment.AssessmentList; -import taa.attendance.Attendance; -import taa.attendance.AttendanceList; -import taa.student.Student; - -import java.util.ArrayList; -import java.util.Arrays; - import taa.student.StudentList; public class Module { private String code; private String name; - private int lessonCount; private final StudentList studentList; private final AssessmentList assessmentList; - private final AttendanceList attendanceList; - private static final int NUM_LESSONS = 13; - private final int[] lessonArray = new int[NUM_LESSONS]; public Module(String code, String name) { this.code = code; this.name = name; this.studentList = new StudentList(); this.assessmentList = new AssessmentList(); - this.attendanceList = new AttendanceList(); } public String getCode() { @@ -36,14 +24,6 @@ public String getName() { return name; } - public int getLessonCount() { - return lessonCount; - } - - public void setLessonCount(int lessonCount) { - this.lessonCount = lessonCount; - } - public StudentList getStudentList() { return studentList; } @@ -52,53 +32,12 @@ public AssessmentList getAssessmentList() { return assessmentList; } - public int getAttendanceCount() { - return attendanceList.getSize(); - } - - - public ArrayList getAttendances() { - return attendanceList.getAttendances(); - } - - public AttendanceList getAttendanceList() { - return attendanceList; - } - - public void addAttendances(AttendanceList attendances, Student student) { - attendances.addIndividualAttendances(student.getIndividualAttendances()); - } - - private String getLessonArrayAsString() { - buildLessonArray(); - return Arrays.toString(lessonArray); - } - - private int[] buildLessonArray() { - for (int i = 0; i < NUM_LESSONS; i++) { - lessonArray[i] = i + 1; - } - return lessonArray; - } - - public String getFormattedLessons() { - String lessons = getLessonArrayAsString(); - String singleDigitLessons = lessons.substring(0, 27); - String doubleDigitLessons = lessons.substring(28); - singleDigitLessons = singleDigitLessons.replace(",", " |"); - doubleDigitLessons = doubleDigitLessons.replace(", ", " |"); - lessons = singleDigitLessons + doubleDigitLessons; - lessons = lessons.replace("[", " | "); - lessons = lessons.replace("]", " |"); - return lessons; - } - @Override public String toString() { if (name.isEmpty()) { return code; } - return String.format("%s - %s", code, name); + return String.format("%s (%s)", code, name); } } diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index ed24d8b370..504611ab02 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -3,8 +3,6 @@ import java.util.ArrayList; public class ModuleList { - private static final String MESSAGE_MODULE_LIST_HEADER = "Module List:"; - private final ArrayList modules; public ModuleList() { @@ -61,9 +59,12 @@ public Module getModule(String code) { @Override public String toString() { - StringBuilder stringBuilder = new StringBuilder(MESSAGE_MODULE_LIST_HEADER); + StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < getSize(); i += 1) { - stringBuilder.append("\n"); + if (i > 0) { + stringBuilder.append("\n"); + } + stringBuilder.append(i + 1); stringBuilder.append(". "); stringBuilder.append(modules.get(i)); diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index 6c9571b47d..2828e0ba71 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -1,58 +1,28 @@ package taa.student; -import taa.attendance.Attendance; +import taa.attendance.AttendanceList; -import java.util.ArrayList; import java.util.HashMap; /** * Represents students. */ public class Student { - private static final int NUM_LESSONS = 13; - private String id; private String name; - private final String[] individualAttendances = new String[NUM_LESSONS]; - private static final String ABSENT_MARK = "0"; - - private final ArrayList attendance; - private final HashMap results; + private final AttendanceList attendanceList; + private final HashMap marksMap; public Student(String id, String name) { this.id = id; this.name = name; - this.attendance = new ArrayList<>(); - this.results = new HashMap<>(); - } - - private void initIndividualAttendances() { - for (int i = 0; i < NUM_LESSONS; i++) { - individualAttendances[i] = ABSENT_MARK; - } - } - - /** - * Marks the student as present or absent for a particular lesson. - * - * @param attendance the attendance object - */ - public void setAttendance(Attendance attendance) { - int lessonIndex = Integer.parseInt(attendance.getLessonIndex()); - initIndividualAttendances(); - individualAttendances[lessonIndex] = attendance.markAttendance(); + this.attendanceList = new AttendanceList(); + this.marksMap = new HashMap<>(); } - - /** - * Returns the attendance status of the student for a particular lesson. - * - * @param lessonIndex The lesson index - * @return The attendance status of the student for the lesson - */ - public String isPresent(int lessonIndex) { - return individualAttendances[lessonIndex]; + public AttendanceList getAttendanceList() { + return attendanceList; } /** @@ -91,21 +61,6 @@ public String getId() { return this.id; } - public String[] getIndividualAttendances() { - return individualAttendances; - } - - - /** - * Overrides default toString method with the custom print message. - * - * @return the custom print message - */ - @Override - public String toString() { - return String.format("%s - %s", id, name); - } - /** * Adds a key,value pair to the hashmap. * @@ -113,17 +68,21 @@ public String toString() { * @param marks value to be stored under the key given */ public void setMarks(String assessmentName, double marks) { - results.put(assessmentName, marks); + marksMap.put(assessmentName, marks); } /** * Gets the marks for the given assessment. * * @param assessmentName Assessment to get marks for. - * @return Marks for the inputted assessment. + * @return The marks for the inputted assessment if it exists, else -1. */ public double getMarks(String assessmentName) { - return results.get(assessmentName); + if (!marksMap.containsKey(assessmentName)) { + return -1; + } + + return marksMap.get(assessmentName); } /** @@ -131,8 +90,8 @@ public double getMarks(String assessmentName) { * * @return Hashmap containing assessment names as keys and the marks as values. */ - public HashMap getAllMarks() { - return results; + public HashMap getMarksMap() { + return new HashMap<>(marksMap); } /** @@ -142,7 +101,16 @@ public HashMap getAllMarks() { * @return True if marks have been inputted. Returns false otherwise. */ public boolean marksExist(String assessmentName) { - return results.containsKey(assessmentName); + return marksMap.containsKey(assessmentName); } + /** + * Overrides default toString method with the custom print message. + * + * @return the custom print message + */ + @Override + public String toString() { + return String.format("%s (%s)", id, name); + } } diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index c0e61b1ad2..48a0865aae 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -3,9 +3,7 @@ import java.util.ArrayList; public class StudentList { - private static String MESSAGE_LIST_STUDENT_HEADER = "Student List:"; - - private ArrayList students; + private final ArrayList students; public StudentList() { this.students = new ArrayList<>(); @@ -72,10 +70,12 @@ public ArrayList findStudents(String keyword) { @Override public String toString() { - String header = String.format(MESSAGE_LIST_STUDENT_HEADER); - StringBuilder stringBuilder = new StringBuilder(header); - for (int i = 0; i < students.size(); i += 1) { - stringBuilder.append("\n"); + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < getSize(); i += 1) { + if (i > 0) { + stringBuilder.append("\n"); + } + stringBuilder.append(i + 1); stringBuilder.append(". "); stringBuilder.append(students.get(i)); diff --git a/src/test/java/taa/attendance/AttendanceTest.java b/src/test/java/taa/attendance/AttendanceTest.java index 119b6306b0..69a35b1d3f 100644 --- a/src/test/java/taa/attendance/AttendanceTest.java +++ b/src/test/java/taa/attendance/AttendanceTest.java @@ -7,13 +7,9 @@ import static org.junit.jupiter.api.Assertions.assertEquals; class AttendanceTest { - - @Test void testAttendance() { - assertEquals("CS2113T 2 3 true", - new Attendance("CS2113T", "2", "3", true).toString()); + assertEquals("Lesson: 2 (Present:true)", + new Attendance(2, true).toString()); } - - } \ No newline at end of file From 7519c53221e031a905636a6ecd86e43466625dd6 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 19:42:05 +0800 Subject: [PATCH 108/543] Move getMissingArgumentMessage function position in Command class --- src/main/java/taa/command/Command.java | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 5878761dd9..f2984a43c6 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -60,6 +60,15 @@ public boolean isExit() { protected abstract String getUsageMessage(); + protected String getMissingArgumentMessage() { + String usageMessage = getUsageMessage(); + if (usageMessage == null) { + usageMessage = MESSAGE_UNKNOWN_USAGE; + } + + return String.format(MESSAGE_FORMAT_MISSING_ARGUMENT, usageMessage); + } + /** * Checks if there are any missing arguments. * @@ -74,13 +83,4 @@ protected boolean checkArguments() { return true; } - - protected String getMissingArgumentMessage() { - String usageMessage = getUsageMessage(); - if (usageMessage == null) { - usageMessage = MESSAGE_UNKNOWN_USAGE; - } - - return String.format(MESSAGE_FORMAT_MISSING_ARGUMENT, usageMessage); - } } From 8a61084638ae67f88edea5786e6faf2d6ebea391 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 19:44:27 +0800 Subject: [PATCH 109/543] Update Comparator for sorting attendance --- src/main/java/taa/attendance/AttendanceList.java | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/main/java/taa/attendance/AttendanceList.java b/src/main/java/taa/attendance/AttendanceList.java index 9041695952..ac1a09e3f8 100644 --- a/src/main/java/taa/attendance/AttendanceList.java +++ b/src/main/java/taa/attendance/AttendanceList.java @@ -35,12 +35,7 @@ public void addAttendance(Attendance attendance) { } private void sortAttendances() { - attendances.sort(new Comparator() { - @Override - public int compare(Attendance attendance1, Attendance attendance2) { - return attendance1.getLessonNumber() - attendance2.getLessonNumber(); - } - }); + attendances.sort(Comparator.comparingInt(Attendance::getLessonNumber)); } @Override From f0199d19ceb5de79a998462daf9ce73b632c2071 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 20:25:34 +0800 Subject: [PATCH 110/543] Add data persistence for attendance --- .../deserializer/AttendanceDeserializer.java | 45 ++++++++++++++++ .../AttendanceListDeserializer.java | 51 +++++++++++++++++++ .../deserializer/ModuleDeserializer.java | 21 +++----- .../deserializer/StudentDeserializer.java | 27 +++++----- 4 files changed, 119 insertions(+), 25 deletions(-) create mode 100644 src/main/java/taa/storage/deserializer/AttendanceDeserializer.java create mode 100644 src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java diff --git a/src/main/java/taa/storage/deserializer/AttendanceDeserializer.java b/src/main/java/taa/storage/deserializer/AttendanceDeserializer.java new file mode 100644 index 0000000000..012b20bfaf --- /dev/null +++ b/src/main/java/taa/storage/deserializer/AttendanceDeserializer.java @@ -0,0 +1,45 @@ +package taa.storage.deserializer; + +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import taa.attendance.Attendance; +import taa.util.Util; + +import java.lang.reflect.Type; + +public class AttendanceDeserializer extends StorageDeserializer implements JsonDeserializer { + private static final String MEMBER_LESSONNUMBER = "lessonNumber"; + private static final String MEMBER_ISPRESENT = "isPresent"; + private static final String[] MEMBERS = {MEMBER_LESSONNUMBER, MEMBER_ISPRESENT}; + + @Override + public Attendance deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + if (!hasMembers(jsonObject, MEMBERS)) { + return null; + } + + JsonElement lessonNumberJson = jsonObject.get(MEMBER_LESSONNUMBER); + if (!Util.isStringInteger(lessonNumberJson.getAsString())) { + return null; + } + int lessonNumber = lessonNumberJson.getAsInt(); + + JsonElement isPresentJson = jsonObject.get(MEMBER_ISPRESENT); + if (!Util.isStringBoolean(isPresentJson.getAsString())) { + return null; + } + boolean isPresent = isPresentJson.getAsBoolean(); + + Attendance attendance = new Attendance(lessonNumber, isPresent); + if (!attendance.verify()) { + return null; + } + + return attendance; + } +} diff --git a/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java b/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java new file mode 100644 index 0000000000..0f457a42db --- /dev/null +++ b/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java @@ -0,0 +1,51 @@ +package taa.storage.deserializer; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; +import taa.attendance.Attendance; +import taa.attendance.AttendanceList; + +import java.lang.reflect.Type; + +public class AttendanceListDeserializer extends StorageDeserializer implements JsonDeserializer { + private static final String MEMBER_ATTENDANCES = "attendances"; + private static final String[] MEMBERS = {MEMBER_ATTENDANCES}; + + @Override + public AttendanceList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + JsonObject jsonObject = json.getAsJsonObject(); + if (!hasMembers(jsonObject, MEMBERS)) { + return null; + } + + JsonElement attendancesJson = jsonObject.get(MEMBER_ATTENDANCES); + if (!attendancesJson.isJsonArray()) { + return null; + } + + GsonBuilder gsonBuilder = new GsonBuilder(); + gsonBuilder.registerTypeAdapter(Attendance.class, new AttendanceDeserializer()); + Gson gson = gsonBuilder.create(); + + AttendanceList attendanceList = new AttendanceList(); + JsonArray attendancesJsonArray = attendancesJson.getAsJsonArray(); + for (JsonElement attendanceJson : attendancesJsonArray) { + Attendance attendance = gson.fromJson(attendanceJson, Attendance.class); + if (attendance != null) { + attendanceList.addAttendance(attendance); + } + } + + if (!attendanceList.verify()) { + return null; + } + + return attendanceList; + } +} diff --git a/src/main/java/taa/storage/deserializer/ModuleDeserializer.java b/src/main/java/taa/storage/deserializer/ModuleDeserializer.java index 99609d6c3a..edf09c8c3e 100644 --- a/src/main/java/taa/storage/deserializer/ModuleDeserializer.java +++ b/src/main/java/taa/storage/deserializer/ModuleDeserializer.java @@ -19,13 +19,11 @@ public class ModuleDeserializer extends StorageDeserializer implements JsonDeserializer { private static final String MEMBER_CODE = "code"; private static final String MEMBER_NAME = "name"; - private static final String MEMBER_LESSONCOUNT = "lessonCount"; private static final String MEMBER_STUDENTLIST = "studentList"; private static final String MEMBER_ASSESSMENTLIST = "assessmentList"; private static final String[] MEMBERS = { MEMBER_CODE, MEMBER_NAME, - MEMBER_LESSONCOUNT, MEMBER_STUDENTLIST, MEMBER_ASSESSMENTLIST }; @@ -44,14 +42,7 @@ public Module deserialize(JsonElement json, Type typeOfT, JsonDeserializationCon JsonElement nameJson = jsonObject.get(MEMBER_NAME); String name = nameJson.getAsString(); - JsonElement lessonCountJson = jsonObject.get(MEMBER_LESSONCOUNT); - if (!Util.isStringInteger(lessonCountJson.getAsString())) { - return null; - } - int lessonCount = lessonCountJson.getAsInt(); - Module module = new Module(code, name); - module.setLessonCount(lessonCount); GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(StudentList.class, new StudentListDeserializer()); @@ -60,14 +51,18 @@ public Module deserialize(JsonElement json, Type typeOfT, JsonDeserializationCon JsonElement studentListJson = jsonObject.get(MEMBER_STUDENTLIST); StudentList studentList = gson.fromJson(studentListJson, StudentList.class); - for (Student student : studentList.getStudents()) { - module.getStudentList().addStudent(student); + if (studentList != null) { + for (Student student : studentList.getStudents()) { + module.getStudentList().addStudent(student); + } } JsonElement assessmentListJson = jsonObject.get(MEMBER_ASSESSMENTLIST); AssessmentList assessmentList = gson.fromJson(assessmentListJson, AssessmentList.class); - for (Assessment assessment : assessmentList.getAssessments()) { - module.getAssessmentList().addAssessment(assessment); + if (assessmentList != null) { + for (Assessment assessment : assessmentList.getAssessments()) { + module.getAssessmentList().addAssessment(assessment); + } } if (!module.verify()) { diff --git a/src/main/java/taa/storage/deserializer/StudentDeserializer.java b/src/main/java/taa/storage/deserializer/StudentDeserializer.java index 20555cce58..10a52cffda 100644 --- a/src/main/java/taa/storage/deserializer/StudentDeserializer.java +++ b/src/main/java/taa/storage/deserializer/StudentDeserializer.java @@ -2,14 +2,14 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.google.gson.JsonArray; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; -import taa.student.Attendance; +import taa.attendance.Attendance; +import taa.attendance.AttendanceList; import taa.student.Student; import java.lang.reflect.Type; @@ -18,12 +18,12 @@ public class StudentDeserializer extends StorageDeserializer implements JsonDeserializer { private static final String MEMBER_ID = "id"; private static final String MEMBER_NAME = "name"; - private static final String MEMBER_ATTENDANCES = "attendances"; + private static final String MEMBER_ATTENDANCELIST = "attendanceList"; private static final String MEMBER_RESULTS = "results"; private static final String[] MEMBERS = { MEMBER_ID, MEMBER_NAME, - MEMBER_ATTENDANCES, + MEMBER_ATTENDANCELIST, MEMBER_RESULTS }; @@ -46,19 +46,22 @@ public Student deserialize(JsonElement json, Type typeOfT, JsonDeserializationCo GsonBuilder gsonBuilder = new GsonBuilder(); Gson gson = gsonBuilder.create(); - JsonElement attendancesJson = jsonObject.get(MEMBER_ATTENDANCES); - JsonArray attendancesJsonArray = attendancesJson.getAsJsonArray(); - for (JsonElement attendanceJson : attendancesJsonArray) { - Attendance attendance = gson.fromJson(attendanceJson, Attendance.class); - // TODO Add attendance to student after parsing + JsonElement attendanceListJson = jsonObject.get(MEMBER_ATTENDANCELIST); + AttendanceList attendanceList = gson.fromJson(attendanceListJson, AttendanceList.class); + if (attendanceList != null) { + for (Attendance attendance : attendanceList.getAttendances()) { + student.getAttendanceList().addAttendance(attendance); + } } JsonElement resultsJson = jsonObject.get(MEMBER_RESULTS); Type resultsType = new TypeToken>(){}.getType(); HashMap results = gson.fromJson(resultsJson, resultsType); - for (String key : results.keySet()) { - double value = results.get(key); - student.setMarks(key, value); + if (results != null) { + for (String key : results.keySet()) { + double value = results.get(key); + student.setMarks(key, value); + } } if (!student.verify()) { From 9ea70f42978071a8cc006028ca1c90de387164d1 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 20:27:50 +0800 Subject: [PATCH 111/543] Fix checkstyle --- .../taa/storage/deserializer/AttendanceListDeserializer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java b/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java index 0f457a42db..272048fd82 100644 --- a/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java @@ -18,7 +18,8 @@ public class AttendanceListDeserializer extends StorageDeserializer implements J private static final String[] MEMBERS = {MEMBER_ATTENDANCES}; @Override - public AttendanceList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + public AttendanceList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); if (!hasMembers(jsonObject, MEMBERS)) { return null; From fc25e61979906f103a26ce4247333d2799aca5d0 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 20:30:59 +0800 Subject: [PATCH 112/543] Add new line to end of file and fix test --- src/test/java/taa/StudentTest.java | 2 +- src/test/java/taa/attendance/AttendanceTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/java/taa/StudentTest.java b/src/test/java/taa/StudentTest.java index 60d0fbb8a4..24355fd620 100644 --- a/src/test/java/taa/StudentTest.java +++ b/src/test/java/taa/StudentTest.java @@ -8,7 +8,7 @@ public class StudentTest { @Test public void testStringConversion() { - assertEquals("A1234567B - Jon Lim", new Student("A1234567B", "Jon Lim").toString()); + assertEquals("A1234567B (Jon Lim)", new Student("A1234567B", "Jon Lim").toString()); } } diff --git a/src/test/java/taa/attendance/AttendanceTest.java b/src/test/java/taa/attendance/AttendanceTest.java index 2b4bb62c4e..af67cec567 100644 --- a/src/test/java/taa/attendance/AttendanceTest.java +++ b/src/test/java/taa/attendance/AttendanceTest.java @@ -12,4 +12,4 @@ void testAttendance() { assertEquals("Lesson 2 (Present)", new Attendance(2, true).toString()); } -} \ No newline at end of file +} From 0df58cbdf40113e892637fcea87ce297acb13af4 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 20:33:36 +0800 Subject: [PATCH 113/543] Update automatic testing files --- text-ui-test/EXPECTED.TXT | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index c78214e0fc..897b7bc692 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -7,12 +7,12 @@ There are no modules in the list. ------------------------------------------------------------ $ ------------------------------------------------------------ Module added: - CS2113T - Software Engineering and Object-oriented Programming + CS2113T (Software Engineering and Object-oriented Programming) There are 1 modules in the list. ------------------------------------------------------------ $ ------------------------------------------------------------ -Module List: -1. CS2113T - Software Engineering and Object-oriented Programming +Module list: +1. CS2113T (Software Engineering and Object-oriented Programming) ------------------------------------------------------------ $ ------------------------------------------------------------ An exception has occurred: From fb1911afd2884d840541a0c6528313ee39c87176 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 22:31:40 +0800 Subject: [PATCH 114/543] Add documentation to most functions --- src/main/java/taa/Parser.java | 14 +++---- src/main/java/taa/assessment/Assessment.java | 16 ++++++++ .../java/taa/assessment/AssessmentList.java | 41 ++++++++++++++++--- src/main/java/taa/attendance/Attendance.java | 10 +++++ .../java/taa/attendance/AttendanceList.java | 24 +++++++++++ .../taa/command/AddAssessmentCommand.java | 8 ++-- .../java/taa/command/AddModuleCommand.java | 8 ++++ .../java/taa/command/AddStudentCommand.java | 10 ++--- .../java/taa/command/AverageMarksCommand.java | 15 ++++--- src/main/java/taa/command/Command.java | 2 +- .../taa/command/DeleteStudentCommand.java | 10 ++--- .../java/taa/command/EditStudentCommand.java | 18 ++++---- src/main/java/taa/command/ExitCommand.java | 8 ++++ .../java/taa/command/FindStudentCommand.java | 10 ++--- .../taa/command/ListAssessmentsCommand.java | 8 ++-- .../taa/command/ListAttendanceCommand.java | 11 +++-- .../java/taa/command/ListMarksCommand.java | 41 +++++++++---------- .../java/taa/command/ListModulesCommand.java | 8 ++++ .../java/taa/command/ListStudentsCommand.java | 10 ++--- .../taa/command/SetAttendanceCommand.java | 17 ++++---- .../java/taa/command/SetMarksCommand.java | 25 +++++------ src/main/java/taa/module/Module.java | 15 +++++++ src/main/java/taa/module/ModuleList.java | 23 +++++++++-- src/main/java/taa/storage/Storage.java | 12 ++++++ src/main/java/taa/student/Student.java | 16 ++++++++ src/main/java/taa/student/StudentList.java | 35 ++++++++++++---- src/main/java/taa/util/Util.java | 19 ++++++++- 27 files changed, 316 insertions(+), 118 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 843d7b6067..ade95dc9da 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -72,7 +72,7 @@ public static Command parseUserInput(String userInput) throws TaaException { case Command.COMMAND_LIST_ASSESSMENTS: command = new ListAssessmentsCommand(argument); break; - + case Command.COMMAND_SET_ATTENDANCE: command = new SetAttendanceCommand(argument); break; @@ -114,15 +114,15 @@ public static String[] splitFirstSpace(String string) { * e.g. * string: "add_module c/CS2113T n/Software Engineering and Object-oriented Programming", argumentKeys: {"c","n"} * Result: HashMap( - * "c":"CS2113T", - * "n":"Software Engineering and Object-oriented Programming" - * ) + * "c":"CS2113T", + * "n":"Software Engineering and Object-oriented Programming" + * ) * - * @param string The string to parse. + * @param string The string to parse. * @param argumentKeys The argument keys to find. * @return HashMap - argumentKey:argumentValue pair. */ - public static HashMap getArgumentsFromString(String string, String[] argumentKeys) { + public static HashMap getArgumentsFromString(String string, String[] argumentKeys) { if (argumentKeys == null || argumentKeys.length == 0) { return new HashMap<>(); } @@ -140,7 +140,7 @@ public static HashMap getArgumentsFromString(String string, Strin } Collections.sort(argumentIndexes); - HashMap result = new HashMap<>(); + HashMap result = new HashMap<>(); for (String key : argumentIndexMap.keySet()) { int argumentIndex = argumentIndexMap.get(key); int startIndex = argumentIndex + key.length() + 1; diff --git a/src/main/java/taa/assessment/Assessment.java b/src/main/java/taa/assessment/Assessment.java index 342b8dac6a..466676c670 100644 --- a/src/main/java/taa/assessment/Assessment.java +++ b/src/main/java/taa/assessment/Assessment.java @@ -13,10 +13,21 @@ public Assessment(String name, double weightage) { this.weightage = weightage; } + /** + * Checks if a weightage is valid. + * + * @param weightage The weightage to check. + * @return true if valid, else false. + */ public static boolean isWeightageWithinRange(double weightage) { return (weightage >= WEIGHTAGE_RANGE[0] && weightage <= WEIGHTAGE_RANGE[1]); } + /** + * Gets the weightage range. + * + * @return A double array of size 2: [0] - Min weightage, [1] Max weightage. + */ public static double[] getWeightageRange() { return WEIGHTAGE_RANGE; } @@ -41,6 +52,11 @@ public String toString() { return String.format("%s (%,.2f%%)", name, weightage); } + /** + * Checks if the variables within the class are valid. + * + * @return true if valid, else false. + */ @Override public boolean verify() { if (name.isEmpty() || !isWeightageWithinRange(weightage)) { diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 3de41e1032..a961feaf19 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -15,10 +15,25 @@ public int getSize() { return assessments.size(); } + /** + * Gets the list of assessments. Note: This returns a new ArrayList instance. + * + * @return A new ArrayList containing all the assessments. + */ public ArrayList getAssessments() { return new ArrayList<>(assessments); } + /** + * Checks if an index is valid with respect to the assessments ArrayList. + * + * @param index The index to check. + * @return true if valid, else false. + */ + public boolean isValidIndex(int index) { + return (index >= 0 && index < assessments.size()); + } + /** * Adds an assessment to the list of assessments in a particular module. * Does not add if assessment name already exists @@ -46,10 +61,12 @@ public boolean addAssessment(Assessment assessment) { return true; } - public boolean isValidIndex(int index) { - return (index >= 0 && index < assessments.size()); - } - + /** + * Gets an Assessment object at the index from the assessment ArrayList. + * + * @param index The index of the object. + * @return An Assessment object if the index is valid, else null. + */ private Assessment getAssessmentAt(int index) { if (isValidIndex(index)) { return assessments.get(index); @@ -58,6 +75,12 @@ private Assessment getAssessmentAt(int index) { return null; } + /** + * Gets an Assessment object with a particular name. Note: name is case-insensitive. + * + * @param assessmentName The name of the assessment. + * @return An Assessment object if found, else null. + */ public Assessment getAssessment(String assessmentName) { for (Assessment assessment : assessments) { String name = assessment.getName(); @@ -85,16 +108,22 @@ public String toString() { return stringBuilder.toString(); } + /** + * Checks if the variables within the class are valid. Filters out duplicate assessments with the same name. + * Also, checks if the total weightage is valid. + * + * @return true if valid, else false. + */ @Override public boolean verify() { ArrayList assessmentNames = new ArrayList<>(); double totalWeightage = 0; for (Assessment assessment : assessments) { String name = assessment.getName(); - if (assessmentNames.contains(name)) { + if (assessmentNames.contains(name.toLowerCase())) { assessments.remove(assessment); } else { - assessmentNames.add(name); + assessmentNames.add(name.toLowerCase()); totalWeightage += assessment.getWeightage(); } } diff --git a/src/main/java/taa/attendance/Attendance.java b/src/main/java/taa/attendance/Attendance.java index 3c77838e21..fcaee3b69a 100644 --- a/src/main/java/taa/attendance/Attendance.java +++ b/src/main/java/taa/attendance/Attendance.java @@ -15,6 +15,11 @@ public Attendance(int lessonNumber, boolean isPresent) { this.isPresent = isPresent; } + /** + * Gets the minimum lesson number. + * + * @return The minimum lesson number. + */ public static int getMinLessonNumber() { return MIN_LESSON_NUMBER; } @@ -33,6 +38,11 @@ public String toString() { return String.format(MESSAGE_FORMAT_ATTENDANCE, lessonNumber, presentString); } + /** + * Checks if the variables in the class are valid. + * + * @return true if valid, else false. + */ @Override public boolean verify() { if (lessonNumber < MIN_LESSON_NUMBER) { diff --git a/src/main/java/taa/attendance/AttendanceList.java b/src/main/java/taa/attendance/AttendanceList.java index f7eb222400..07ecede7ac 100644 --- a/src/main/java/taa/attendance/AttendanceList.java +++ b/src/main/java/taa/attendance/AttendanceList.java @@ -17,10 +17,21 @@ public int getSize() { return attendances.size(); } + /** + * Gets the list of attendances. Note: This returns a new ArrayList instance. + * + * @return A new ArrayList containing all the attendances. + */ public ArrayList getAttendances() { return new ArrayList<>(attendances); } + /** + * Gets an Attendance object with a particular lesson number from the attendances ArrayList. + * + * @param lessonNumber The lesson number of the attendance. + * @return An Attendance object if found, else null. + */ public Attendance getAttendance(int lessonNumber) { for (Attendance attendance : attendances) { if (attendance.getLessonNumber() == lessonNumber) { @@ -31,11 +42,19 @@ public Attendance getAttendance(int lessonNumber) { return null; } + /** + * Adds an Attendance object to the list of attendances. The attendances ArrayList is sorted after adding. + * + * @param attendance The attendance object to add. + */ public void addAttendance(Attendance attendance) { attendances.add(attendance); sortAttendances(); } + /** + * Sorts the Attendance objects in the attendances ArrayList in ascending order based on lesson number. + */ private void sortAttendances() { attendances.sort(Comparator.comparingInt(Attendance::getLessonNumber)); } @@ -56,6 +75,11 @@ public String toString() { return stringBuilder.toString(); } + /** + * Checks if the variables in the class are valid. Filters out duplicate attendance with the same lesson number. + * + * @return Always returns true. + */ @Override public boolean verify() { ArrayList lessonNumbers = new ArrayList<>(); diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 7e6b81bc8a..7b72a60246 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -29,12 +29,12 @@ public AddAssessmentCommand(String argument) { } /** - * Adds an assessment to a particular module. + * Executes the add_assessment command and adds an assessment to a particular module. * * @param moduleList The list of modules. - * @param ui The ui instance to handle interactions with the user. - * @param storage The storage instance to handle saving. - * @throws TaaException If the user inputs an invalid command. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index e363bc2ffc..0b71505e75 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -21,6 +21,14 @@ public AddModuleCommand(String argument) { super(argument, ADD_MODULE_ARGUMENT_KEYS); } + /** + * Executes the add_module command and adds a module. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index d4ffe84c35..b95952a6ee 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -23,12 +23,12 @@ public AddStudentCommand(String argument) { } /** - * Adds a student to a particular module. + * Executes the add_student command and adds a student to a particular module. * - * @param moduleList The list of modules - * @param ui The ui instance to handle interactions with the user - * @param storage The storage instance to handle saving. - * @throws TaaException If the user inputs an invalid command + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index 6cfc848edf..f5024514a0 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -29,13 +29,12 @@ public AverageMarksCommand(String argument) { } /** - * Checks for errors before calling the function to output the average marks - * of an assessment in a module. + * Executes the average_marks command and displays the average mark of an assessment to the user. * - * @param moduleList List of modules. - * @param ui The ui instance to handle interactions with the user. - * @param storage The storage instance to handle saving. - * @throws TaaException When average marks command is invalid. + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { @@ -70,7 +69,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc /** * Outputs the average marks of an assessment in a module. * - * @param ui The ui instance to handle interactions with the user. + * @param ui The ui instance to handle interactions with the user. * @param module The module the assessment belongs to. */ private void printAverageMarks(Ui ui, Module module, Assessment assessment) { @@ -98,7 +97,7 @@ private void printAverageMarks(Ui ui, Module module, Assessment assessment) { } /** - * Returns the usage message of the average marks command. + * Returns the usage message of the command. * * @return String which contains the usage message. */ diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 9e90327fcb..20d29c3731 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -40,7 +40,7 @@ public abstract class Command { protected String argument; protected boolean isExit; protected String[] argumentKeys; - protected HashMap argumentMap; + protected HashMap argumentMap; public Command(String argument) { this(argument, null); diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index d5f4b65266..5298220471 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -23,12 +23,12 @@ public DeleteStudentCommand(String argument) { } /** - * Deletes a student from a module. + * Executes the delete_student command and deletes a student from the module. * - * @param moduleList The list of modules - * @param ui The ui instance to handle interactions with the user - * @param storage The storage instance to handle saving. - * @throws TaaException If the user inputs an invalid command + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 6fff2ff137..2b835ab63b 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -15,10 +15,10 @@ public class EditStudentCommand extends Command { private static final String KEY_NEW_ID = "i"; private static final String KEY_NEW_NAME = "n"; private static final String[] EDIT_STUDENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_NEW_ID, - KEY_NEW_NAME + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_NEW_ID, + KEY_NEW_NAME }; private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "Usage: %s " @@ -30,12 +30,12 @@ public EditStudentCommand(String argument) { } /** - * Edits the name and student ID of a given student. + * Executes the edit_student command and edits the particulars of a student. * - * @param moduleList The list of modules - * @param ui The ui instance to handle interactions with the user - * @param storage The storage instance to handle saving. - * @throws TaaException If the user inputs an invalid command + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { diff --git a/src/main/java/taa/command/ExitCommand.java b/src/main/java/taa/command/ExitCommand.java index 3b0f9697ed..666a25678c 100644 --- a/src/main/java/taa/command/ExitCommand.java +++ b/src/main/java/taa/command/ExitCommand.java @@ -12,6 +12,14 @@ public ExitCommand(String argument) { super(argument); } + /** + * Executes the exit command and exits the program. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command. + */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (!argument.isEmpty()) { diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index b1a8829eb3..4052fa8669 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -26,12 +26,12 @@ public FindStudentCommand(String argument) { } /** - * Finds the students taking a particular module containing a particular keyword. + * Executes the find_student command and finds students in the module based on a keyword. * - * @param moduleList The list of modules - * @param ui The ui instance to handle interactions with the user - * @param storage The storage instance to handle saving. - * @throws TaaException If the user inputs an invalid command + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index a6ccec80db..3ea354128b 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -21,12 +21,12 @@ public ListAssessmentsCommand(String argument) { } /** - * Lists all the assessments of a particular module. + * Executes the list_assessment command and list all the assessments of a particular module. * * @param moduleList The list of modules. - * @param ui The ui instance to handle interactions with the user. - * @param storage The storage instance to handle saving. - * @throws TaaException If the user inputs an invalid command. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/ListAttendanceCommand.java index 8d0e4709b9..e9fc5d0582 100644 --- a/src/main/java/taa/command/ListAttendanceCommand.java +++ b/src/main/java/taa/command/ListAttendanceCommand.java @@ -23,10 +23,13 @@ public ListAttendanceCommand(String argument) { super(argument, LIST_ATTENDANCE_ARGUMENT_KEYS); } - /** Lists out the attendance for all students in a module. - * @param moduleList The list of modules - * @param ui The ui instance to handle interactions with the user - * @throws TaaException If the user inputs an invalid command + /** + * Executes the list_attendance command and list all the attendance record of a student. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index b95415c062..2c4a28f3ac 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -17,8 +17,8 @@ public class ListMarksCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_ASSESSMENT_NAME = "a"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME }; private static final String MESSAGE_LIST_MARKS_HEADER = "Here is the list of students and " @@ -33,24 +33,12 @@ public ListMarksCommand(String argument) { } /** - * Returns a string with the student name and the marks associated with the student. - * - * @param studentName Name of the student. - * @param marks Marks of the student. - * @return String with the name and marks of the student separated with a vertical line. - */ - public String marksToString(String studentName, double marks) { - return studentName + " | " + marks; - } - - /** - * Checks for errors before calling the function that - * lists the student and the marks they attained for an assessment. + * Executes the list_marks command and list marks of students for an assessment. * - * @param moduleList List of modules. - * @param ui The ui instance to handle interactions with the user. - * @param storage The storage instance to handle saving. - * @throws TaaException When list marks command is invalid. + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { @@ -81,10 +69,21 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc listMarks(ui, module, assessment); } + /** + * Returns a string with the student name and the marks associated with the student. + * + * @param studentName Name of the student. + * @param marks Marks of the student. + * @return String with the name and marks of the student separated with a vertical line. + */ + public String marksToString(String studentName, double marks) { + return studentName + " | " + marks; + } + /** * Lists the student and the marks they attained for an assessment. * - * @param ui The ui instance to handle interactions with the user. + * @param ui The ui instance to handle interactions with the user. * @param module The module that the student and assessment belong to. */ private void listMarks(Ui ui, Module module, Assessment assessment) { @@ -118,7 +117,7 @@ private void listMarks(Ui ui, Module module, Assessment assessment) { } /** - * Returns the usage message of the list marks command. + * Returns the usage message of the command. * * @return String which contains the usage message. */ diff --git a/src/main/java/taa/command/ListModulesCommand.java b/src/main/java/taa/command/ListModulesCommand.java index 9f2af9bdb4..80adea6241 100644 --- a/src/main/java/taa/command/ListModulesCommand.java +++ b/src/main/java/taa/command/ListModulesCommand.java @@ -14,6 +14,14 @@ public ListModulesCommand(String argument) { super(argument); } + /** + * Executes the list_modules command and lists all the modules. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (!argument.isEmpty()) { diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index f2e11e3573..bb39e1ce0e 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -22,12 +22,12 @@ public ListStudentsCommand(String argument) { } /** - * Lists the students taking a particular module. + * Executes the list_student command and lists the students of a particular module. * - * @param moduleList The list of modules - * @param ui The ui instance to handle interactions with the user - * @param storage The storage instance to handle saving. - * @throws TaaException If the user inputs an invalid command + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index 8143933fba..1615878f42 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -17,10 +17,10 @@ public class SetAttendanceCommand extends Command { private static final String KEY_LESSON_NUMBER = "l"; private static final String KEY_PRESENT = "p"; private static final String[] SET_ATTENDANCE_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_LESSON_NUMBER, - KEY_PRESENT + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_LESSON_NUMBER, + KEY_PRESENT }; private static final String MESSAGE_INVALID_LESSON_NUMBER = "Invalid lesson number."; @@ -40,11 +40,12 @@ public SetAttendanceCommand(String argument) { } /** - * Sets the attendance of a student to 1 or 0. + * Executes the set_attendance command and sets the attendance of a student. * - * @param moduleList The list of modules - * @param ui The ui instance to handle interactions with the user - * @throws TaaException If the user inputs an invalid command + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 388cb05339..3b84aac82c 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -20,10 +20,10 @@ public class SetMarksCommand extends Command { private static final String KEY_ASSESSMENT_NAME = "a"; private static final String KEY_MARKS = "m"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_ASSESSMENT_NAME, - KEY_MARKS + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_ASSESSMENT_NAME, + KEY_MARKS }; private static final String MESSAGE_FORMAT_SET_MARKS_USAGE = "Usage: %s " @@ -37,12 +37,12 @@ public SetMarksCommand(String argument) { } /** - * Checks for errors before calling the function that sets marks for a student's assessment. + * Executes the set_marks command and sets the marks of a student's assessment. * - * @param moduleList Module list to access the module the student is enrolled in. - * @param ui The ui instance to handle interactions with the user. - * @param storage The storage instance to handle saving. - * @throws TaaException when set marks command is invalid. + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { @@ -98,10 +98,10 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc /** * Sets the marks for a student's assessment. * - * @param ui The ui instance to handle interactions with the user. - * @param student The student instance to set the mark for. + * @param ui The ui instance to handle interactions with the user. + * @param student The student instance to set the mark for. * @param assessment The assessment instance. - * @param marks The marks to set for the assessment. + * @param marks The marks to set for the assessment. */ private void setMarks(Ui ui, Student student, Assessment assessment, double marks) { String assessmentName = assessment.getName(); @@ -111,6 +111,7 @@ private void setMarks(Ui ui, Student student, Assessment assessment, double mark /** * Returns the usage message of the set marks command. + * * @return String which contains the usage message. */ @Override diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index ec050159db..f8fc9924cb 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -25,10 +25,20 @@ public String getName() { return name; } + /** + * Gets the StudentList object associated to the module. + * + * @return A StudentList object. + */ public StudentList getStudentList() { return studentList; } + /** + * Gets the AssessmentList object associated to the module. + * + * @return A AssessmentList object. + */ public AssessmentList getAssessmentList() { return assessmentList; } @@ -42,6 +52,11 @@ public String toString() { return String.format("%s (%s)", code, name); } + /** + * Checks if the variables in the class are valid. + * + * @return true if valid, else false. + */ @Override public boolean verify() { if (code.isEmpty() || name.isEmpty()) { diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index 89424959e1..622c1f6c01 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -11,14 +11,15 @@ public ModuleList() { this.modules = new ArrayList<>(); } - public void addModule(Module module) { - modules.add(module); - } - public int getSize() { return modules.size(); } + /** + * Gets the list of modules. Note: This returns a new ArrayList instance. + * + * @return A new ArrayList containing all the modules. + */ public ArrayList getModules() { return new ArrayList<>(modules); } @@ -33,6 +34,15 @@ public boolean isValidIndex(int index) { return (index >= 0 && index < getSize()); } + /** + * Adds a Module object to the list of modules. + * + * @param module The Module object to add. + */ + public void addModule(Module module) { + modules.add(module); + } + /** * Gets a module at the specified index. * @@ -79,6 +89,11 @@ public String toString() { return stringBuilder.toString(); } + /** + * Checks if the variables in the class are valid. Filters out duplicate modules with the same module code. + * + * @return Always returns true. + */ @Override public boolean verify() { ArrayList moduleCodes = new ArrayList<>(); diff --git a/src/main/java/taa/storage/Storage.java b/src/main/java/taa/storage/Storage.java index ed6bb0c175..824c0c3bbd 100644 --- a/src/main/java/taa/storage/Storage.java +++ b/src/main/java/taa/storage/Storage.java @@ -30,6 +30,12 @@ public Storage(String filename) { this.filename = filename; } + /** + * Load the module list from the file. + * + * @return A ModuleList object after parsing from the file. + * @throws TaaException if fail to open, read, or parse the file. + */ public ModuleList load() throws TaaException { if (!Util.fileExists(filename)) { return null; @@ -56,6 +62,12 @@ public ModuleList load() throws TaaException { return moduleList; } + /** + * Saves a ModuleList object to the file. + * + * @param moduleList The ModuleList object to save. + * @throws TaaException if fail to create, open, or write to the file. + */ public void save(ModuleList moduleList) throws TaaException { if (!Util.createFile(filename)) { throw new TaaException(String.format(MESSAGE_FORMAT_FAIL_CREATE_FILE, filename)); diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index 9280d6d15a..d30980a982 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -23,14 +23,30 @@ public Student(String id, String name) { this.results = new HashMap<>(); } + /** + * Checks if the marks are valid. + * + * @param marks The marks to check. + * @return true if valid, else false. + */ public static boolean isMarksWithinRange(double marks) { return (marks >= MARKS_RANGE[0] && marks <= MARKS_RANGE[1]); } + /** + * Gets the marks range. + * + * @return A double array of size 2: [0] - Min marks, [1] - Max marks. + */ public static double[] getMarksRange() { return MARKS_RANGE; } + /** + * Gets the AttendanceList object associated to the student. + * + * @return An AttendanceList object. + */ public AttendanceList getAttendanceList() { return attendanceList; } diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index 6e4fa843f6..ae7c75ae2a 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -13,23 +13,29 @@ public StudentList() { this.students = new ArrayList<>(); } - /** - * Gets a list of students in the ArrayList. Note that this returns a new ArrayList instance. - * - * @return A new ArrayList containing all the students. - */ - public ArrayList getStudents() { - return new ArrayList<>(students); - } - public int getSize() { return students.size(); } + /** + * Checks if an index is valid with respect to the students ArrayList. + * + * @param index The index to check. + * @return true if valid, else false. + */ public boolean isValidIndex(int index) { return (index >= 0 && index < getSize()); } + /** + * Gets a list of students in the ArrayList. Note: This returns a new ArrayList instance. + * + * @return A new ArrayList containing all the students. + */ + public ArrayList getStudents() { + return new ArrayList<>(students); + } + public Student getStudentAt(int index) { if (isValidIndex(index)) { return students.get(index); @@ -38,6 +44,11 @@ public Student getStudentAt(int index) { return null; } + /** + * Adds a Student object to the list of students. + * + * @param student The Student object to add. + */ public void addStudent(Student student) { students.add(student); } @@ -56,6 +67,12 @@ public Student deleteStudent(int index) { return null; } + /** + * Gets a list of students based on a particular keyword. + * + * @param keyword The keyword to search for. + * @return A list of students with the keyword. + */ public ArrayList findStudents(String keyword) { String keywordLower = keyword.toLowerCase(); diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java index a886b5a80a..72b7b95072 100644 --- a/src/main/java/taa/util/Util.java +++ b/src/main/java/taa/util/Util.java @@ -2,9 +2,14 @@ import java.io.File; import java.io.IOException; -import java.util.regex.Pattern; public class Util { + /** + * Checks if a string can be converted to an integer. + * + * @param string The string to check. + * @return true if string can convert to integer, else false. + */ public static boolean isStringInteger(String string) { boolean isInt; try { @@ -17,6 +22,12 @@ public static boolean isStringInteger(String string) { return isInt; } + /** + * Checks if a string can be converted to a double. + * + * @param string The string to check. + * @return true if string can convert to double, else false. + */ public static boolean isStringDouble(String string) { boolean isDouble; try { @@ -29,6 +40,12 @@ public static boolean isStringDouble(String string) { return isDouble; } + /** + * Checks if a string can be converted to a boolean. + * + * @param string The string to check. + * @return true if string can convert to boolean, else false. + */ public static boolean isStringBoolean(String string) { return string.equals("true") || string.equals("false"); } From c0a65404fb61376ab27b14f060df8d3caae4ecb9 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 22:36:35 +0800 Subject: [PATCH 115/543] Fix indentation --- .../java/taa/command/EditStudentCommand.java | 22 ++++++++--------- .../java/taa/command/ListMarksCommand.java | 17 ++++++------- .../taa/command/SetAttendanceCommand.java | 24 +++++++++---------- .../java/taa/command/SetMarksCommand.java | 24 +++++++++---------- 4 files changed, 42 insertions(+), 45 deletions(-) diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 2b835ab63b..24c80178b4 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -15,14 +15,14 @@ public class EditStudentCommand extends Command { private static final String KEY_NEW_ID = "i"; private static final String KEY_NEW_NAME = "n"; private static final String[] EDIT_STUDENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_NEW_ID, - KEY_NEW_NAME + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_NEW_ID, + KEY_NEW_NAME }; private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "Usage: %s " - + "%s/ %s/ %s/ %s/"; + + "%s/ %s/ %s/ %s/"; private static final String MESSAGE_FORMAT_STUDENT_EDITED = "Student updated:\n %s"; public EditStudentCommand(String argument) { @@ -78,12 +78,12 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsageMessage() { return String.format( - MESSAGE_FORMAT_FIND_STUDENT_USAGE, - COMMAND_EDIT_STUDENT, - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_NEW_ID, - KEY_NEW_NAME + MESSAGE_FORMAT_FIND_STUDENT_USAGE, + COMMAND_EDIT_STUDENT, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_NEW_ID, + KEY_NEW_NAME ); } } diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index 2c4a28f3ac..3ab8e52086 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -16,17 +16,14 @@ public class ListMarksCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_ASSESSMENT_NAME = "a"; - private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME - }; + private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; private static final String MESSAGE_LIST_MARKS_HEADER = "Here is the list of students and " - + "their marks for %s:"; + + "their marks for %s:"; private static final String MARKS_LIST_EMPTY = "There are no marks inputted!"; private static final String MESSAGE_FORMAT_LIST_MARKS_USAGE = "Usage: %s " - + "%s/ %s/"; + + "%s/ %s/"; public ListMarksCommand(String argument) { super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); @@ -124,10 +121,10 @@ private void listMarks(Ui ui, Module module, Assessment assessment) { @Override protected String getUsageMessage() { return String.format( - MESSAGE_FORMAT_LIST_MARKS_USAGE, - COMMAND_LIST_MARKS, - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME + MESSAGE_FORMAT_LIST_MARKS_USAGE, + COMMAND_LIST_MARKS, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME ); } } diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index 1615878f42..c505445729 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -17,23 +17,23 @@ public class SetAttendanceCommand extends Command { private static final String KEY_LESSON_NUMBER = "l"; private static final String KEY_PRESENT = "p"; private static final String[] SET_ATTENDANCE_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_LESSON_NUMBER, - KEY_PRESENT + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_LESSON_NUMBER, + KEY_PRESENT }; private static final String MESSAGE_INVALID_LESSON_NUMBER = "Invalid lesson number."; private static final String MESSAGE_FORMAT_INVALID_PRESENT = "Invalid present value.\n" - + "Possible values: %s (Present), %s (Absent)"; + + "Possible values: %s (Present), %s (Absent)"; private static final String MESSAGE_FORMAT_SET_ATTENDANCE = "Attendance set for %s:\n %s"; private static final String PRESENT_VALUE = "1"; private static final String ABSENT_VALUE = "0"; private static final String MESSAGE_FORMAT_SET_ATTENDANCE_USAGE = "Usage: %s " - + "%s/ %s/ %s/ %s/"; + + "%s/ %s/ %s/ %s/"; public SetAttendanceCommand(String argument) { super(argument, SET_ATTENDANCE_ARGUMENT_KEYS); @@ -116,12 +116,12 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsageMessage() { return String.format( - MESSAGE_FORMAT_SET_ATTENDANCE_USAGE, - COMMAND_SET_ATTENDANCE, - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_LESSON_NUMBER, - KEY_PRESENT + MESSAGE_FORMAT_SET_ATTENDANCE_USAGE, + COMMAND_SET_ATTENDANCE, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_LESSON_NUMBER, + KEY_PRESENT ); } } diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 3b84aac82c..e0fe05f944 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -20,16 +20,16 @@ public class SetMarksCommand extends Command { private static final String KEY_ASSESSMENT_NAME = "a"; private static final String KEY_MARKS = "m"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_ASSESSMENT_NAME, - KEY_MARKS + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_ASSESSMENT_NAME, + KEY_MARKS }; private static final String MESSAGE_FORMAT_SET_MARKS_USAGE = "Usage: %s " - + "%s/ %s/ %s/ %s/"; + + "%s/ %s/ %s/ %s/"; private static final String MESSAGE_FORMAT_INVALID_MARKS = "Invalid Marks. " - + "Marks must be between %,.2f and %,.2f (inclusive)"; + + "Marks must be between %,.2f and %,.2f (inclusive)"; private static final String MESSAGE_FORMAT_MARKS_ADDED = "Marks set for %s: %,.2f for %s"; public SetMarksCommand(String argument) { @@ -117,12 +117,12 @@ private void setMarks(Ui ui, Student student, Assessment assessment, double mark @Override protected String getUsageMessage() { return String.format( - MESSAGE_FORMAT_SET_MARKS_USAGE, - COMMAND_SET_MARKS, - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_ASSESSMENT_NAME, - KEY_MARKS + MESSAGE_FORMAT_SET_MARKS_USAGE, + COMMAND_SET_MARKS, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_ASSESSMENT_NAME, + KEY_MARKS ); } } From 8e0a7d68213ba5ad8127aa28824408f6d6a9d0b6 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 12 Oct 2021 22:50:07 +0800 Subject: [PATCH 116/543] Add documentation to getStudentAt function in StudentList class --- src/main/java/taa/student/StudentList.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index ae7c75ae2a..54d5297b5b 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -36,6 +36,12 @@ public ArrayList getStudents() { return new ArrayList<>(students); } + /** + * Gets the Student object at a particular index. + * + * @param index The index of the Student object. + * @return A Student object if the index is valid, else null. + */ public Student getStudentAt(int index) { if (isValidIndex(index)) { return students.get(index); From 50ec6482878bb13c21a9fdc72c946f4b71c76d92 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Wed, 13 Oct 2021 00:09:23 +0800 Subject: [PATCH 117/543] remove repeated checks for studentIndex --- src/main/java/taa/command/DeleteStudentCommand.java | 5 +---- src/main/java/taa/command/EditStudentCommand.java | 5 +---- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 6d5ea6afe7..fbf11f1af1 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -53,10 +53,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc int studentIndex = Integer.parseInt(studentIndexInput) - 1; StudentList studentList = module.getStudentList(); - if (studentIndex < 0 || studentIndex >= studentList.getSize()) { - throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); - } - assert studentIndex < module.getStudentList().getSize(); + assert studentIndex >= 0 && studentIndex < module.getStudentList().getSize(); Student student = studentList.deleteStudent(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index a6b09dace1..59ba0d1a74 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -61,10 +61,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc int studentIndex = Integer.parseInt(studentIndexInput) - 1; StudentList studentList = module.getStudentList(); - if (studentIndex < 0 || studentIndex >= studentList.getSize()) { - throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); - } - assert studentIndex < module.getStudentList().getSize(); + assert studentIndex >= 0 && studentIndex < module.getStudentList().getSize(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); From 789e97e74c83fd5a69cc3aecee6c1d59a3969013 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 13 Oct 2021 13:55:48 +0800 Subject: [PATCH 118/543] Add assertions and remove unused variable in StudentList --- src/main/java/taa/Ui.java | 2 ++ src/main/java/taa/command/AddModuleCommand.java | 2 ++ src/main/java/taa/storage/Storage.java | 2 ++ src/main/java/taa/student/StudentList.java | 2 -- 4 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index 52c3313ff9..e34e7cbc77 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -29,6 +29,8 @@ public String getUserInput() { input = scanner.nextLine(); } while (input.trim().isEmpty()); + assert !input.isEmpty(); + return input; } diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index 0b71505e75..509fb3885e 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -39,11 +39,13 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getMissingArgumentMessage()); } + assert argumentMap.containsKey(KEY_MODULE_CODE); String moduleCode = argumentMap.get(KEY_MODULE_CODE); if (moduleCode.contains(" ")) { throw new TaaException(MESSAGE_INVALID_MODULE_CODE); } + assert argumentMap.containsKey(KEY_MODULE_NAME); String name = argumentMap.get(KEY_MODULE_NAME); Module module = new Module(moduleCode, name); moduleList.addModule(module); diff --git a/src/main/java/taa/storage/Storage.java b/src/main/java/taa/storage/Storage.java index 824c0c3bbd..d4942782ec 100644 --- a/src/main/java/taa/storage/Storage.java +++ b/src/main/java/taa/storage/Storage.java @@ -73,6 +73,8 @@ public void save(ModuleList moduleList) throws TaaException { throw new TaaException(String.format(MESSAGE_FORMAT_FAIL_CREATE_FILE, filename)); } + assert Util.fileExists(filename); + Gson gson = new Gson(); try { FileWriter fileWriter = new FileWriter(filename); diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index 54d5297b5b..b60dc5d683 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -5,8 +5,6 @@ import java.util.ArrayList; public class StudentList implements ClassChecker { - private static final String MESSAGE_LIST_STUDENT_HEADER = "Student List:"; - private final ArrayList students; public StudentList() { From c7b7fc8563fcbf0b89cb474c9aa3fc69ead88243 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 13 Oct 2021 19:34:06 +0800 Subject: [PATCH 119/543] Add help command --- src/main/java/taa/Parser.java | 5 ++ .../java/taa/assessment/AssessmentList.java | 7 ++- .../java/taa/attendance/AttendanceList.java | 7 ++- .../taa/command/AddAssessmentCommand.java | 6 +- .../java/taa/command/AddModuleCommand.java | 5 +- .../java/taa/command/AddStudentCommand.java | 5 +- .../java/taa/command/AverageMarksCommand.java | 5 +- src/main/java/taa/command/Command.java | 12 +++- .../taa/command/DeleteStudentCommand.java | 5 +- .../java/taa/command/EditStudentCommand.java | 6 +- src/main/java/taa/command/ExitCommand.java | 4 +- .../java/taa/command/FindStudentCommand.java | 5 +- src/main/java/taa/command/HelpCommand.java | 63 +++++++++++++++++++ .../taa/command/ListAssessmentsCommand.java | 4 +- .../taa/command/ListAttendanceCommand.java | 4 +- .../java/taa/command/ListMarksCommand.java | 5 +- .../java/taa/command/ListModulesCommand.java | 2 +- .../java/taa/command/ListStudentsCommand.java | 5 +- .../taa/command/SetAttendanceCommand.java | 6 +- .../java/taa/command/SetMarksCommand.java | 6 +- src/main/java/taa/module/ModuleList.java | 9 ++- src/main/java/taa/student/Student.java | 20 +++--- 22 files changed, 139 insertions(+), 57 deletions(-) create mode 100644 src/main/java/taa/command/HelpCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index ade95dc9da..74c766717c 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -3,6 +3,7 @@ import taa.command.AddAssessmentCommand; import taa.command.AddModuleCommand; import taa.command.AddStudentCommand; +import taa.command.HelpCommand; import taa.command.SetAttendanceCommand; import taa.command.AverageMarksCommand; import taa.command.Command; @@ -33,6 +34,10 @@ public static Command parseUserInput(String userInput) throws TaaException { Command command; switch (commandString) { + case Command.COMMAND_HELP: + command = new HelpCommand(argument); + break; + case Command.COMMAND_EXIT: command = new ExitCommand(argument); break; diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index a961feaf19..b81a00589d 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -117,17 +117,22 @@ public String toString() { @Override public boolean verify() { ArrayList assessmentNames = new ArrayList<>(); + ArrayList duplicatedAssessments = new ArrayList<>(); double totalWeightage = 0; for (Assessment assessment : assessments) { String name = assessment.getName(); if (assessmentNames.contains(name.toLowerCase())) { - assessments.remove(assessment); + duplicatedAssessments.add(assessment); } else { assessmentNames.add(name.toLowerCase()); totalWeightage += assessment.getWeightage(); } } + for (Assessment assessment : duplicatedAssessments) { + assessments.remove(assessment); + } + if (!Assessment.isWeightageWithinRange(totalWeightage)) { return false; } diff --git a/src/main/java/taa/attendance/AttendanceList.java b/src/main/java/taa/attendance/AttendanceList.java index 07ecede7ac..ca3da2661d 100644 --- a/src/main/java/taa/attendance/AttendanceList.java +++ b/src/main/java/taa/attendance/AttendanceList.java @@ -83,14 +83,19 @@ public String toString() { @Override public boolean verify() { ArrayList lessonNumbers = new ArrayList<>(); + ArrayList duplicatedAttendances = new ArrayList<>(); for (Attendance attendance : attendances) { if (lessonNumbers.contains(attendance.getLessonNumber())) { - attendances.remove(attendance); + duplicatedAttendances.add(attendance); } else { lessonNumbers.add(attendance.getLessonNumber()); } } + for (Attendance attendance : duplicatedAttendances) { + attendances.remove(attendance); + } + return true; } } diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 7b72a60246..86075a2ce2 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -17,8 +17,8 @@ public class AddAssessmentCommand extends Command { private static final String MESSAGE_FAIL_TO_ADD = "Fail to add assessment."; - private static final String MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE = "Usage: %s " - + "%s/ %s/ %s/"; + private static final String MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE = "%s %s/ %s/ " + + "%s/"; private static final String MESSAGE_FORMAT_INVALID_WEIGHTAGE = "Invalid weightage. " + "Weightage must be between %,.2f and %,.2f (inclusive)"; private static final String MESSAGE_FORMAT_ASSESSMENT_ADDED = "Assessment added:\n" @@ -88,7 +88,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE, COMMAND_ADD_ASSESSMENT, diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index 509fb3885e..e8d8dde3a0 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -13,8 +13,7 @@ public class AddModuleCommand extends Command { private static final String MESSAGE_INVALID_MODULE_CODE = "Invalid module code."; - private static final String MESSAGE_FORMAT_ADD_MODULE_USAGE = "Usage: %s " - + "%s/ %s/"; + private static final String MESSAGE_FORMAT_ADD_MODULE_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_MODULE_ADDED = "Module added:\n %s\nThere are %d modules in the list."; public AddModuleCommand(String argument) { @@ -56,7 +55,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_ADD_MODULE_USAGE, COMMAND_ADD_MODULE, diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index b95952a6ee..a24b24fd66 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -14,8 +14,7 @@ public class AddStudentCommand extends Command { private static final String KEY_STUDENT_NAME = "n"; private static final String[] ADD_STUDENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_ID, KEY_STUDENT_NAME}; - private static final String MESSAGE_FORMAT_ADD_STUDENT_USAGE = "Usage: %s " - + "%s/ %s/ %s/"; + private static final String MESSAGE_FORMAT_ADD_STUDENT_USAGE = "%s %s/ %s/ %s/"; private static final String MESSAGE_STUDENT_ADDED_FORMAT = "Student has been added to %s:\n %s"; public AddStudentCommand(String argument) { @@ -59,7 +58,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_ADD_STUDENT_USAGE, COMMAND_ADD_STUDENT, diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index f5024514a0..445d6aec6f 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -18,8 +18,7 @@ public class AverageMarksCommand extends Command { private static final String KEY_ASSESSMENT_NAME = "a"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; - private static final String MESSAGE_FORMAT_AVERAGE_MARKS_USAGE = "Usage: %s " - + "%s/ %s/"; + private static final String MESSAGE_FORMAT_AVERAGE_MARKS_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_AVERAGE_MARKS = "Average marks for %s is %,.2f"; private static final String MESSAGE_FORMAT_AVERAGE_MARKS_WITH_UNMARKED = "Average marks for %s is %,.2f\n" + "Note that %d student(s) have yet to be marked!"; @@ -102,7 +101,7 @@ private void printAverageMarks(Ui ui, Module module, Assessment assessment) { * @return String which contains the usage message. */ @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_AVERAGE_MARKS_USAGE, COMMAND_AVERAGE_MARKS, diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 20d29c3731..dfbf79e067 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -24,6 +24,7 @@ public abstract class Command { public static final String COMMAND_SET_ATTENDANCE = "set_attendance"; public static final String COMMAND_ADD_ASSESSMENT = "add_assessment"; public static final String COMMAND_SET_MARKS = "set_marks"; + public static final String COMMAND_HELP = "help"; // Common messages protected static final String MESSAGE_UNKNOWN_USAGE = "Unknown usage."; @@ -34,8 +35,9 @@ public abstract class Command { protected static final String MESSAGE_NO_STUDENTS = "There are no students in this module"; // Common message formats - protected static final String MESSAGE_FORMAT_GENERIC_USAGE = "Usage: %s"; + protected static final String MESSAGE_FORMAT_GENERIC_USAGE = "%s"; protected static final String MESSAGE_FORMAT_MISSING_ARGUMENT = "Missing Argument(s).\n%s"; + protected static final String MESSAGE_FORMAT_USAGE_MESSAGE = "Usage: %s"; protected String argument; protected boolean isExit; @@ -57,9 +59,13 @@ public boolean isExit() { return isExit; } - public abstract void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException; + protected abstract String getUsage(); + + protected String getUsageMessage() { + return String.format(MESSAGE_FORMAT_USAGE_MESSAGE, getUsage()); + } - protected abstract String getUsageMessage(); + public abstract void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException; protected String getMissingArgumentMessage() { String usageMessage = getUsageMessage(); diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index fbf11f1af1..7777003bcf 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -14,8 +14,7 @@ public class DeleteStudentCommand extends Command { private static final String KEY_STUDENT_INDEX = "s"; private static final String[] DELETE_STUDENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX}; - private static final String MESSAGE_FORMAT_DELETE_STUDENT_USAGE = "Usage: %s " - + "%s/ %s/"; + private static final String MESSAGE_FORMAT_DELETE_STUDENT_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_STUDENT_DELETED = "Student removed from %s:\n %s"; public DeleteStudentCommand(String argument) { @@ -65,7 +64,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_DELETE_STUDENT_USAGE, COMMAND_DELETE_STUDENT, diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 59ba0d1a74..2681a114c7 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -21,8 +21,8 @@ public class EditStudentCommand extends Command { KEY_NEW_NAME }; - private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "Usage: %s " - + "%s/ %s/ %s/ %s/"; + private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "%s %s/ %s/ %s/ " + + "%s/"; private static final String MESSAGE_FORMAT_STUDENT_EDITED = "Student updated:\n %s"; public EditStudentCommand(String argument) { @@ -78,7 +78,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_FIND_STUDENT_USAGE, COMMAND_EDIT_STUDENT, diff --git a/src/main/java/taa/command/ExitCommand.java b/src/main/java/taa/command/ExitCommand.java index 666a25678c..5031bb4c8d 100644 --- a/src/main/java/taa/command/ExitCommand.java +++ b/src/main/java/taa/command/ExitCommand.java @@ -6,7 +6,7 @@ import taa.module.ModuleList; public class ExitCommand extends Command { - private static final String MESSAGE_FORMAT_EXIT_USAGE = "Usage: %s"; + private static final String MESSAGE_FORMAT_EXIT_USAGE = "%s"; public ExitCommand(String argument) { super(argument); @@ -31,7 +31,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format(MESSAGE_FORMAT_EXIT_USAGE, COMMAND_EXIT); } } diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 4052fa8669..1b5f34f386 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -17,8 +17,7 @@ public class FindStudentCommand extends Command { private static final String MESSAGE_NO_STUDENTS_FOUND = "There are no students matching your keyword."; - private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "Usage: %s " - + "%s/ %s/"; + private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_STUDENT_FOUND_HEADER = "Here are the students in %s with \"%s\":"; public FindStudentCommand(String argument) { @@ -69,7 +68,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_FIND_STUDENT_USAGE, COMMAND_FIND_STUDENT, diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java new file mode 100644 index 0000000000..d611582959 --- /dev/null +++ b/src/main/java/taa/command/HelpCommand.java @@ -0,0 +1,63 @@ +package taa.command; + +import taa.Ui; +import taa.exception.TaaException; +import taa.module.ModuleList; +import taa.storage.Storage; + +public class HelpCommand extends Command { + private static final String MESSAGE_FORMAT_OUTPUT = "Available commands:\n%s"; + + private static final Command[] commands = { + new AddAssessmentCommand(""), + new AddModuleCommand(""), + new AddStudentCommand(""), + new AverageMarksCommand(""), + new DeleteStudentCommand(""), + new EditStudentCommand(""), + new ExitCommand(""), + new FindStudentCommand(""), + new HelpCommand(""), + new ListAssessmentsCommand(""), + new ListAttendanceCommand(""), + new ListMarksCommand(""), + new ListModulesCommand(""), + new ListStudentsCommand(""), + new SetAttendanceCommand(""), + new SetMarksCommand("") + }; + + public HelpCommand(String argument) { + super(argument); + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + if (!argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < commands.length; i += 1) { + Command command = commands[i]; + + if (i > 0) { + stringBuilder.append("\n"); + } + + stringBuilder.append("- "); + stringBuilder.append(command.getUsage()); + } + + String message = String.format(MESSAGE_FORMAT_OUTPUT, stringBuilder.toString()); + ui.printMessage(message); + } + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_GENERIC_USAGE, + COMMAND_HELP + ); + } +} diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index 3ea354128b..995699a272 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -13,7 +13,7 @@ public class ListAssessmentsCommand extends Command { private static final String MESSAGE_LIST_EMPTY = "There are no assessments in the module."; - private static final String MESSAGE_FORMAT_LIST_ASSESSMENTS_USAGE = "Usage: %s %s/"; + private static final String MESSAGE_FORMAT_LIST_ASSESSMENTS_USAGE = "%s %s/"; private static final String MESSAGE_FORMAT_OUTPUT = "Assessments for %s:\n%s"; public ListAssessmentsCommand(String argument) { @@ -56,7 +56,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_LIST_ASSESSMENTS_USAGE, COMMAND_LIST_ASSESSMENTS, diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/ListAttendanceCommand.java index e9fc5d0582..b175d5e803 100644 --- a/src/main/java/taa/command/ListAttendanceCommand.java +++ b/src/main/java/taa/command/ListAttendanceCommand.java @@ -15,7 +15,7 @@ public class ListAttendanceCommand extends Command { private static final String KEY_STUDENT_INDEX = "s"; private static final String[] LIST_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX}; - private static final String MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE = "Usage: %s %s/ %s/"; + private static final String MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE = "%s %s/ %s/"; protected static final String MESSAGE_FORMAT_NO_ATTENDANCE = "There is no recorded attendance for %s."; private static final String MESSAGE_FORMAT_OUTPUT = "Attendance for %s:\n%s"; @@ -71,7 +71,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE, COMMAND_LIST_ATTENDANCE, diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index 3ab8e52086..3454e69abe 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -22,8 +22,7 @@ public class ListMarksCommand extends Command { + "their marks for %s:"; private static final String MARKS_LIST_EMPTY = "There are no marks inputted!"; - private static final String MESSAGE_FORMAT_LIST_MARKS_USAGE = "Usage: %s " - + "%s/ %s/"; + private static final String MESSAGE_FORMAT_LIST_MARKS_USAGE = "%s %s/ %s/"; public ListMarksCommand(String argument) { super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); @@ -119,7 +118,7 @@ private void listMarks(Ui ui, Module module, Assessment assessment) { * @return String which contains the usage message. */ @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_LIST_MARKS_USAGE, COMMAND_LIST_MARKS, diff --git a/src/main/java/taa/command/ListModulesCommand.java b/src/main/java/taa/command/ListModulesCommand.java index 80adea6241..70801ae69d 100644 --- a/src/main/java/taa/command/ListModulesCommand.java +++ b/src/main/java/taa/command/ListModulesCommand.java @@ -39,7 +39,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_GENERIC_USAGE, COMMAND_LIST_MODULES diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index bb39e1ce0e..dc7b2e8ba0 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -13,8 +13,7 @@ public class ListStudentsCommand extends Command { private static final String MESSAGE_NO_STUDENTS = "No students added yet!"; - private static final String MESSAGE_FORMAT_LIST_STUDENT_USAGE = "Usage: %s " - + "%s/"; + private static final String MESSAGE_FORMAT_LIST_STUDENT_USAGE = "%s %s/"; private static final String MESSAGE_FORMAT_OUTPUT = "Students for %s:\n%s"; public ListStudentsCommand(String argument) { @@ -57,7 +56,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format(MESSAGE_FORMAT_LIST_STUDENT_USAGE, COMMAND_LIST_STUDENTS, KEY_MODULE_CODE diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index c505445729..6a8fbf07d0 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -32,8 +32,8 @@ public class SetAttendanceCommand extends Command { private static final String PRESENT_VALUE = "1"; private static final String ABSENT_VALUE = "0"; - private static final String MESSAGE_FORMAT_SET_ATTENDANCE_USAGE = "Usage: %s " - + "%s/ %s/ %s/ %s/"; + private static final String MESSAGE_FORMAT_SET_ATTENDANCE_USAGE = "%s %s/ %s/ " + + "%s/ %s/"; public SetAttendanceCommand(String argument) { super(argument, SET_ATTENDANCE_ARGUMENT_KEYS); @@ -114,7 +114,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_SET_ATTENDANCE_USAGE, COMMAND_SET_ATTENDANCE, diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index e0fe05f944..9dd24b9e2d 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -26,8 +26,8 @@ public class SetMarksCommand extends Command { KEY_MARKS }; - private static final String MESSAGE_FORMAT_SET_MARKS_USAGE = "Usage: %s " - + "%s/ %s/ %s/ %s/"; + private static final String MESSAGE_FORMAT_SET_MARKS_USAGE = "%s %s/ %s/ " + + "%s/ %s/"; private static final String MESSAGE_FORMAT_INVALID_MARKS = "Invalid Marks. " + "Marks must be between %,.2f and %,.2f (inclusive)"; private static final String MESSAGE_FORMAT_MARKS_ADDED = "Marks set for %s: %,.2f for %s"; @@ -115,7 +115,7 @@ private void setMarks(Ui ui, Student student, Assessment assessment, double mark * @return String which contains the usage message. */ @Override - protected String getUsageMessage() { + protected String getUsage() { return String.format( MESSAGE_FORMAT_SET_MARKS_USAGE, COMMAND_SET_MARKS, diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index 622c1f6c01..c7031c43bf 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -96,15 +96,20 @@ public String toString() { */ @Override public boolean verify() { - ArrayList moduleCodes = new ArrayList<>(); + /*ArrayList moduleCodes = new ArrayList<>(); + ArrayList duplicatedModules = new ArrayList<>(); for (Module module : modules) { if (moduleCodes.contains(module.getCode())) { - modules.remove(module); + duplicatedModules.add(module); } else { moduleCodes.add(module.getCode()); } } + for (Module module : duplicatedModules) { + modules.remove(module); + }*/ + return true; } } diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index d30980a982..5e55475888 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -120,6 +120,16 @@ public HashMap getResults() { return new HashMap<>(results); } + /** + * Overrides default toString method with the custom print message. + * + * @return the custom print message + */ + @Override + public String toString() { + return String.format("%s (%s)", id, name); + } + /** * Returns true if marks have been inputted for a given assessment. * @@ -144,14 +154,4 @@ public boolean verify() { return true; } - - /** - * Overrides default toString method with the custom print message. - * - * @return the custom print message - */ - @Override - public String toString() { - return String.format("%s (%s)", id, name); - } } From 1b9121c6528aa3dc55acf38ce6664cca87e4e336 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 13 Oct 2021 19:34:24 +0800 Subject: [PATCH 120/543] Add TaaLogger for logging --- .gitignore | 1 + .../java/taa/command/AddModuleCommand.java | 2 + src/main/java/taa/logger/TaaLogger.java | 51 +++++++++++++++++++ .../java/taa/logger/TaaLoggerFormatter.java | 31 +++++++++++ 4 files changed, 85 insertions(+) create mode 100644 src/main/java/taa/logger/TaaLogger.java create mode 100644 src/main/java/taa/logger/TaaLoggerFormatter.java diff --git a/.gitignore b/.gitignore index c7d178e0bc..d5709d3332 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,4 @@ text-ui-test/ACTUAL.TXT .project data/taa_data.json text-ui-test/data/taa_data.json +taa.log* diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index e8d8dde3a0..d03050c6a6 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -1,5 +1,6 @@ package taa.command; +import taa.logger.TaaLogger; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; @@ -48,6 +49,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc String name = argumentMap.get(KEY_MODULE_NAME); Module module = new Module(moduleCode, name); moduleList.addModule(module); + TaaLogger.LOGGER.logInfo(String.format("Added module: %s", module)); storage.save(moduleList); diff --git a/src/main/java/taa/logger/TaaLogger.java b/src/main/java/taa/logger/TaaLogger.java new file mode 100644 index 0000000000..8fb8cda59f --- /dev/null +++ b/src/main/java/taa/logger/TaaLogger.java @@ -0,0 +1,51 @@ +package taa.logger; + +import java.io.IOException; +import java.util.logging.FileHandler; +import java.util.logging.Level; +import java.util.logging.Logger; + +public class TaaLogger { + private static final String LOG_FILENAME = "taa.log"; + + private static final String MESSAGE_UNABLE_TO_OPEN = "Unable to open log file - %s"; + + public static final TaaLogger LOGGER = new TaaLogger(); + + private final Logger logger; + + public TaaLogger() { + this.logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); + init(); + } + + private void init() { + FileHandler fileHandler; + try { + fileHandler = new FileHandler(LOG_FILENAME); + } catch (IOException e) { + fileHandler = null; + } + + if (fileHandler == null) { + logger.warning(String.format(MESSAGE_UNABLE_TO_OPEN, LOG_FILENAME)); + } else { + logger.setUseParentHandlers(false); + + fileHandler.setFormatter(new TaaLoggerFormatter()); + logger.addHandler(fileHandler); + } + } + + public void logInfo(String message) { + logger.log(Level.INFO, message); + } + + public void logWarning(String message) { + logger.log(Level.WARNING, message); + } + + public void logSevere(String message) { + logger.log(Level.SEVERE, message); + } +} diff --git a/src/main/java/taa/logger/TaaLoggerFormatter.java b/src/main/java/taa/logger/TaaLoggerFormatter.java new file mode 100644 index 0000000000..a0fa4e64d9 --- /dev/null +++ b/src/main/java/taa/logger/TaaLoggerFormatter.java @@ -0,0 +1,31 @@ +package taa.logger; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.logging.Formatter; +import java.util.logging.LogRecord; + +public class TaaLoggerFormatter extends Formatter { + private static final String MESSAGE_FORMAT_LOG_OUTPUT = "%d %s %s %s"; + + private static final String DATE_FORMAT = "dd/MM/yyyy HHmm"; + + @Override + public String format(LogRecord record) { + String dateTimeString = msToDateTimeString(record.getMillis()); + + return String.format( + MESSAGE_FORMAT_LOG_OUTPUT, + record.getSequenceNumber(), + dateTimeString, + record.getLevel().getName(), + record.getMessage() + ); + } + + private String msToDateTimeString(long ms) { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_FORMAT); + Date date = new Date(ms); + return simpleDateFormat.format(date); + } +} From 056bc6cf26d911aaacf9201fcf0ab3cfdbab008a Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 13 Oct 2021 19:41:37 +0800 Subject: [PATCH 121/543] Fix checkstyle --- src/main/java/taa/command/AddAssessmentCommand.java | 10 +++++----- src/main/java/taa/command/AddModuleCommand.java | 8 ++++---- src/main/java/taa/command/AddStudentCommand.java | 13 +++++++------ src/main/java/taa/command/AverageMarksCommand.java | 8 ++++---- src/main/java/taa/command/DeleteStudentCommand.java | 8 ++++---- src/main/java/taa/command/EditStudentCommand.java | 4 ++-- src/main/java/taa/command/FindStudentCommand.java | 8 ++++---- .../java/taa/command/ListAssessmentsCommand.java | 6 +++--- .../java/taa/command/ListAttendanceCommand.java | 8 ++++---- src/main/java/taa/command/ListModulesCommand.java | 4 ++-- src/main/java/taa/command/ListStudentsCommand.java | 7 ++++--- 11 files changed, 43 insertions(+), 41 deletions(-) diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 86075a2ce2..fe448c36b8 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -90,11 +90,11 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE, - COMMAND_ADD_ASSESSMENT, - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME, - KEY_WEIGHTAGE + MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE, + COMMAND_ADD_ASSESSMENT, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME, + KEY_WEIGHTAGE ); } } diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index d03050c6a6..bf9b1e59ab 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -59,10 +59,10 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_ADD_MODULE_USAGE, - COMMAND_ADD_MODULE, - KEY_MODULE_CODE, - KEY_MODULE_NAME + MESSAGE_FORMAT_ADD_MODULE_USAGE, + COMMAND_ADD_MODULE, + KEY_MODULE_CODE, + KEY_MODULE_NAME ); } } diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index a24b24fd66..2c8f7c3dec 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -14,7 +14,8 @@ public class AddStudentCommand extends Command { private static final String KEY_STUDENT_NAME = "n"; private static final String[] ADD_STUDENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_ID, KEY_STUDENT_NAME}; - private static final String MESSAGE_FORMAT_ADD_STUDENT_USAGE = "%s %s/ %s/ %s/"; + private static final String MESSAGE_FORMAT_ADD_STUDENT_USAGE = "%s %s/ %s/ " + + "%s/"; private static final String MESSAGE_STUDENT_ADDED_FORMAT = "Student has been added to %s:\n %s"; public AddStudentCommand(String argument) { @@ -60,11 +61,11 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_ADD_STUDENT_USAGE, - COMMAND_ADD_STUDENT, - KEY_MODULE_CODE, - KEY_STUDENT_ID, - KEY_STUDENT_NAME + MESSAGE_FORMAT_ADD_STUDENT_USAGE, + COMMAND_ADD_STUDENT, + KEY_MODULE_CODE, + KEY_STUDENT_ID, + KEY_STUDENT_NAME ); } } diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index 445d6aec6f..9784e15379 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -103,10 +103,10 @@ private void printAverageMarks(Ui ui, Module module, Assessment assessment) { @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_AVERAGE_MARKS_USAGE, - COMMAND_AVERAGE_MARKS, - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME + MESSAGE_FORMAT_AVERAGE_MARKS_USAGE, + COMMAND_AVERAGE_MARKS, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME ); } } diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 7777003bcf..73e9cbc833 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -66,10 +66,10 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_DELETE_STUDENT_USAGE, - COMMAND_DELETE_STUDENT, - KEY_MODULE_CODE, - KEY_STUDENT_INDEX + MESSAGE_FORMAT_DELETE_STUDENT_USAGE, + COMMAND_DELETE_STUDENT, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX ); } } diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 2681a114c7..7aee7fc72d 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -21,8 +21,8 @@ public class EditStudentCommand extends Command { KEY_NEW_NAME }; - private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "%s %s/ %s/ %s/ " - + "%s/"; + private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "%s %s/ %s/ " + + "%s/ %s/"; private static final String MESSAGE_FORMAT_STUDENT_EDITED = "Student updated:\n %s"; public EditStudentCommand(String argument) { diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 1b5f34f386..057312c9df 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -70,10 +70,10 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_FIND_STUDENT_USAGE, - COMMAND_FIND_STUDENT, - KEY_MODULE_CODE, - KEY_KEYWORD + MESSAGE_FORMAT_FIND_STUDENT_USAGE, + COMMAND_FIND_STUDENT, + KEY_MODULE_CODE, + KEY_KEYWORD ); } } diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index 995699a272..313d05ec43 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -58,9 +58,9 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_LIST_ASSESSMENTS_USAGE, - COMMAND_LIST_ASSESSMENTS, - KEY_MODULE_CODE + MESSAGE_FORMAT_LIST_ASSESSMENTS_USAGE, + COMMAND_LIST_ASSESSMENTS, + KEY_MODULE_CODE ); } } diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/ListAttendanceCommand.java index b175d5e803..7bb114993b 100644 --- a/src/main/java/taa/command/ListAttendanceCommand.java +++ b/src/main/java/taa/command/ListAttendanceCommand.java @@ -73,10 +73,10 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE, - COMMAND_LIST_ATTENDANCE, - KEY_MODULE_CODE, - KEY_STUDENT_INDEX + MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE, + COMMAND_LIST_ATTENDANCE, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX ); } } diff --git a/src/main/java/taa/command/ListModulesCommand.java b/src/main/java/taa/command/ListModulesCommand.java index 70801ae69d..e2fa241799 100644 --- a/src/main/java/taa/command/ListModulesCommand.java +++ b/src/main/java/taa/command/ListModulesCommand.java @@ -41,8 +41,8 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_GENERIC_USAGE, - COMMAND_LIST_MODULES + MESSAGE_FORMAT_GENERIC_USAGE, + COMMAND_LIST_MODULES ); } } diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index dc7b2e8ba0..bbbd43c272 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -57,9 +57,10 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsage() { - return String.format(MESSAGE_FORMAT_LIST_STUDENT_USAGE, - COMMAND_LIST_STUDENTS, - KEY_MODULE_CODE + return String.format( + MESSAGE_FORMAT_LIST_STUDENT_USAGE, + COMMAND_LIST_STUDENTS, + KEY_MODULE_CODE ); } } From dd74903d7750d072a196be65dbfdf5d86c377c9a Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 13 Oct 2021 19:41:57 +0800 Subject: [PATCH 122/543] Make TaaLogger constructor as private --- src/main/java/taa/logger/TaaLogger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/logger/TaaLogger.java b/src/main/java/taa/logger/TaaLogger.java index 8fb8cda59f..8b7bbf6771 100644 --- a/src/main/java/taa/logger/TaaLogger.java +++ b/src/main/java/taa/logger/TaaLogger.java @@ -14,7 +14,7 @@ public class TaaLogger { private final Logger logger; - public TaaLogger() { + private TaaLogger() { this.logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); init(); } From e8fd5daa21ab18cf263b5fa56ee118d5e07b883f Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Wed, 13 Oct 2021 19:58:08 +0800 Subject: [PATCH 123/543] added assert and junit testing for student marks --- src/test/java/taa/StudentTest.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/test/java/taa/StudentTest.java b/src/test/java/taa/StudentTest.java index 24355fd620..e57d94f05f 100644 --- a/src/test/java/taa/StudentTest.java +++ b/src/test/java/taa/StudentTest.java @@ -1,5 +1,7 @@ package taa; +import taa.assessment.Assessment; +import taa.assessment.AssessmentList; import taa.student.Student; import org.junit.jupiter.api.Test; @@ -10,5 +12,13 @@ public class StudentTest { public void testStringConversion() { assertEquals("A1234567B (Jon Lim)", new Student("A1234567B", "Jon Lim").toString()); } - + + @Test + void setMarks_newMarksArguments_marksAddedCorrectly() { + Student student = new Student("A0123456X", "Jim"); + AssessmentList assessments = new AssessmentList(); + assessments.addAssessment(new Assessment("Midterms", 20)); + student.setMarks("Midterms", 99.9); + assertEquals(99.9, student.getMarks("Midterms")); + } } From 95e4592f330393d7f758370ca2c2472652aa44fb Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Wed, 13 Oct 2021 20:11:05 +0800 Subject: [PATCH 124/543] added assertions for marks commands. --- src/main/java/taa/command/SetMarksCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 9dd24b9e2d..b7caf55a4a 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -104,6 +104,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc * @param marks The marks to set for the assessment. */ private void setMarks(Ui ui, Student student, Assessment assessment, double marks) { + assert marks > 0; String assessmentName = assessment.getName(); student.setMarks(assessmentName, marks); ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_ADDED, student, marks, assessmentName)); From 99f9e463accaa33775e91851da0ce66a143e5733 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Wed, 13 Oct 2021 20:15:11 +0800 Subject: [PATCH 125/543] asserted >= 0 instead of > 0 for marks setting --- src/main/java/taa/command/SetMarksCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index b7caf55a4a..c28865c973 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -104,7 +104,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc * @param marks The marks to set for the assessment. */ private void setMarks(Ui ui, Student student, Assessment assessment, double marks) { - assert marks > 0; + assert marks >= 0; String assessmentName = assessment.getName(); student.setMarks(assessmentName, marks); ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_ADDED, student, marks, assessmentName)); From a06022663e640a94cd257373fe9479dbef4b9675 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 13 Oct 2021 20:26:32 +0800 Subject: [PATCH 126/543] Check if module exists before adding --- src/main/java/taa/command/AddModuleCommand.java | 9 ++++++++- src/main/java/taa/module/ModuleList.java | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index bf9b1e59ab..82f3373674 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -13,6 +13,7 @@ public class AddModuleCommand extends Command { private static final String[] ADD_MODULE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_MODULE_NAME}; private static final String MESSAGE_INVALID_MODULE_CODE = "Invalid module code."; + private static final String MESSAGE_MODULE_EXISTS = "Module already exists."; private static final String MESSAGE_FORMAT_ADD_MODULE_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_MODULE_ADDED = "Module added:\n %s\nThere are %d modules in the list."; @@ -45,9 +46,15 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(MESSAGE_INVALID_MODULE_CODE); } + Module module = moduleList.getModule(moduleCode); + if (module != null) { + throw new TaaException(MESSAGE_MODULE_EXISTS); + } + assert argumentMap.containsKey(KEY_MODULE_NAME); String name = argumentMap.get(KEY_MODULE_NAME); - Module module = new Module(moduleCode, name); + + module = new Module(moduleCode, name); moduleList.addModule(module); TaaLogger.LOGGER.logInfo(String.format("Added module: %s", module)); diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index c7031c43bf..214926b2a9 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -96,7 +96,7 @@ public String toString() { */ @Override public boolean verify() { - /*ArrayList moduleCodes = new ArrayList<>(); + ArrayList moduleCodes = new ArrayList<>(); ArrayList duplicatedModules = new ArrayList<>(); for (Module module : modules) { if (moduleCodes.contains(module.getCode())) { @@ -108,7 +108,7 @@ public boolean verify() { for (Module module : duplicatedModules) { modules.remove(module); - }*/ + } return true; } From 2846e7842d3e1b96449ba24b4d5e7ccf88fa101a Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 13 Oct 2021 20:32:44 +0800 Subject: [PATCH 127/543] Add timezone to log output --- src/main/java/taa/logger/TaaLoggerFormatter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/logger/TaaLoggerFormatter.java b/src/main/java/taa/logger/TaaLoggerFormatter.java index a0fa4e64d9..ddf39178b2 100644 --- a/src/main/java/taa/logger/TaaLoggerFormatter.java +++ b/src/main/java/taa/logger/TaaLoggerFormatter.java @@ -8,7 +8,7 @@ public class TaaLoggerFormatter extends Formatter { private static final String MESSAGE_FORMAT_LOG_OUTPUT = "%d %s %s %s"; - private static final String DATE_FORMAT = "dd/MM/yyyy HHmm"; + private static final String DATE_FORMAT = "dd/MM/yyyy HHmm z"; @Override public String format(LogRecord record) { From ab33ef7b7350f850d712e7d685442a3740faceb0 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Wed, 13 Oct 2021 21:29:35 +0800 Subject: [PATCH 128/543] edit help command --- src/main/java/taa/command/HelpCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index d611582959..9dca3de10f 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -15,8 +15,8 @@ public class HelpCommand extends Command { new AverageMarksCommand(""), new DeleteStudentCommand(""), new EditStudentCommand(""), - new ExitCommand(""), new FindStudentCommand(""), + new ExitCommand(""), new HelpCommand(""), new ListAssessmentsCommand(""), new ListAttendanceCommand(""), From e10f17edfdf1790c8be5dcadca8a0a97057dc0bb Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Wed, 13 Oct 2021 21:59:21 +0800 Subject: [PATCH 129/543] update about us document --- docs/AboutUs.md | 10 +++++----- docs/team/{johndoe.md => rachel.md} | 2 +- src/main/java/META-INF/MANIFEST.MF | 3 +++ 3 files changed, 9 insertions(+), 6 deletions(-) rename docs/team/{johndoe.md => rachel.md} (55%) create mode 100644 src/main/java/META-INF/MANIFEST.MF diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 01eb6dfa04..602ed6fdaa 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,8 +2,8 @@ Display | Name | Github Profile | Portfolio --------|:----:|:--------------:|:---------: -![](https://via.placeholder.com/100.png?text=Photo) | Zhen Hong | [hozhenhong99](https://github.com/hozhenhong99) | [Zhen Hong's Portfolio](docs/team/zhenhong.md) -![](https://via.placeholder.com/100.png?text=Photo) | Dak Nam | [Github](https://github.com/daknam2001) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Jon Lim | [jon-the-melon](https://github.com/jon-the-melon) | [Jon's Portfolio](docs/team/jon.md) -![](https://via.placeholder.com/100.png?text=Photo) | Rachel | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Leyond | [Github](https://github.com/leyondlee) | [Portfolio](docs/team/leyond.md) +![](https://via.placeholder.com/100.png?text=Photo) | Zhen Hong | [hozhenhong99](https://github.com/hozhenhong99) | [Zhen Hong's Portfolio](team/zhenhong.md) +![](https://via.placeholder.com/100.png?text=Photo) | Dak Nam | [daknam2001](https://github.com/daknam2001) | [Portfolio](team/daknam.md) +![](https://via.placeholder.com/100.png?text=Photo) | Jon Lim | [jon-the-melon](https://github.com/jon-the-melon) | [Jon's Portfolio](team/jon.md) +![](https://via.placeholder.com/100.png?text=Photo) | Rachel | [rachelkeh](https://github.com/rachelkeh) | [Portfolio](team/rachel.md) +![](https://via.placeholder.com/100.png?text=Photo) | Leyond | [leyondlee](https://github.com/leyondlee) | [Portfolio](team/leyond.md) diff --git a/docs/team/johndoe.md b/docs/team/rachel.md similarity index 55% rename from docs/team/johndoe.md rename to docs/team/rachel.md index ab75b391b8..e4f157818a 100644 --- a/docs/team/johndoe.md +++ b/docs/team/rachel.md @@ -1,4 +1,4 @@ -# John Doe - Project Portfolio Page +# Rachel - Project Portfolio Page ## Overview diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF new file mode 100644 index 0000000000..0797128cc7 --- /dev/null +++ b/src/main/java/META-INF/MANIFEST.MF @@ -0,0 +1,3 @@ +Manifest-Version: 1.0 +Main-Class: taa.Taa + From e84cbb670fafc3936da521105ded0f1c09c3c7dd Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Thu, 14 Oct 2021 22:50:08 +0800 Subject: [PATCH 130/543] add assert --- src/main/java/taa/attendance/Attendance.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/taa/attendance/Attendance.java b/src/main/java/taa/attendance/Attendance.java index fcaee3b69a..8971c935a2 100644 --- a/src/main/java/taa/attendance/Attendance.java +++ b/src/main/java/taa/attendance/Attendance.java @@ -29,6 +29,7 @@ public void setPresent(boolean present) { } public int getLessonNumber() { + assert lessonNumber >= MIN_LESSON_NUMBER; return lessonNumber; } From d0d5e9fe77fe001b4cf28505aafe7d8556598f31 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 19 Oct 2021 22:51:45 +0800 Subject: [PATCH 131/543] Add Architecture diagram and explaination of add module feature into DG --- docs/DeveloperGuide.md | 52 +++++++++++++++++++++++-- docs/diagrams/ArchitectureDiagram.png | Bin 0 -> 16073 bytes docs/diagrams/ArchitectureDiagram.puml | 51 ++++++++++++++++++++++++ src/main/java/taa/Parser.java | 6 +-- 4 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 docs/diagrams/ArchitectureDiagram.png create mode 100644 docs/diagrams/ArchitectureDiagram.puml diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 64e1f0ed2b..7a9fcee42d 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -5,9 +5,55 @@ {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.} - +### Architecture +![ArchitectureDiagram](diagrams/ArchitectureDiagram.png) +
+_Figure 1. Architecture Diagram_
+
+The _Architecture Diagram_ shown above explains the high-level design of the Application.
+
+Overview of components: +* `Main` + * On app launch: Creates and runs an instance of `Duke`. +* `UI` + * Handles UI operations. +* `Taa` + * On creation: Initializes the `UI` and `Storage` components. + * On run: Loads data saved in `Storage`, receives and processes user input from `UI`. +* `Command` + * Defines how a command is to be executed. +* `Models` + * Represents a collection of classes that holds the data of the application in-memory. + * Includes: `ModuleList`, `Modules`, `StudentList` , `Student`, `AssessmentList` , `Assessment`, `AttendanceList` , `Attendance` +* `Storage` + * Handles data storage operations (e.g. Reading from and writing to data file). +* `Commons` + * Represents a collection of classes used by other components. + * `Parser`: Used to translate user input into a `Command` and to parse an argument string into its various values. + * `Util`: Contains utility functions used by other classes. + +### Add module feature +The add module mechanism is facilitated by `AddModuleCommand`. It extends `Command` and uses `ModuleList` which stores +module internally as an ArrayList `modules`.
+ +`AddModuleCommand` implements the following methods: +* `AddModuleCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Performs operations for the command. + +`ModuleList` implements the following methods: +* `ModuleList#getSize()` - Returns the no. of modules currently in the list. +* `ModuleList#getModules()` - Returns an ArrayList containing all the modules. +* `ModuleList#getModule(code:String)` - Returns a module with a particular code. +* `ModuleList#isValidIndex()` - Checks if an index is valid w.r.t the `modules` ArrayList. +* `ModuleList#addModule(module:Module)` - Adds a module to the `modules` ArrayList. +* `ModuleList#getModuleAt(index:int)` - Returns a `Module` object at the specified `index` within the `modules` ArrayList. + +Below is an example scenario of how the add module feature behaves at each step:
+* Step 1 - The user executes `add_module c/CS2113T n/Software Engineering` to add a module. The `add_module` command calls +the `AddModuleCommand#execute` method. Within `AddModuleCommand#execute`, `ModuleList#getModule("CS2113T")` is called to +ensure that there is no existing module with code `CS2113T`. +* Step 2 - If no existing module with code `CS2113T` is found, a new `Module` object with code and name set to `CS2113T` +and `Software Engineering` set as its code and name respectively. Then, `ModuleList#addModule` is called to add the newly +created `Module` object into the `modules` ArrayList within `ModuleList`. ## Product scope ### Target user profile diff --git a/docs/diagrams/ArchitectureDiagram.png b/docs/diagrams/ArchitectureDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..ae34c14281428260ba422cb80a193806a42fb260 GIT binary patch literal 16073 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 literal 0 HcmV?d00001 diff --git a/docs/diagrams/ArchitectureDiagram.puml b/docs/diagrams/ArchitectureDiagram.puml new file mode 100644 index 0000000000..57d24fbb2b --- /dev/null +++ b/docs/diagrams/ArchitectureDiagram.puml @@ -0,0 +1,51 @@ +@startuml +!include +!include +!include + +skinparam Shadowing false +skinparam MinClassWidth 50 + +skinparam Class { + FontColor #FFFFFF + BorderThickness 1 + BorderColor #FFFFFF + StereotypeFontColor #FFFFFF + FontName Arial +} + +hide footbox +hide members +hide circle + +Package " "<>{ + Class UI #ForestGreen + Class Taa #Blue + Class Storage #DarkGoldenRod + Class Main #IndianRed + Class Command #DarkSlateBlue + Class Models #DarkRed + Class Commons #Purple + Class Dummy #White + Class Parser #Navy + Class Util #LightSeaGreen +} +Class "<$user>" as User #Red +Class "<$documents>" as File #Gray + +Main -down-> Taa +UI -> Taa +Taa -> Command +UI -down-> Command +Command -right-> Storage +Command -down-> Models +Models -right[hidden]- Dummy +Dummy .down.> Commons +Dummy .down.> Commons +Dummy .down.> Commons +Commons -left- Parser +Commons -down- Util + +UI <-up- User +Storage -right-> File +@enduml \ No newline at end of file diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 74c766717c..0b3307f752 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -119,9 +119,9 @@ public static String[] splitFirstSpace(String string) { * e.g. * string: "add_module c/CS2113T n/Software Engineering and Object-oriented Programming", argumentKeys: {"c","n"} * Result: HashMap( - * "c":"CS2113T", - * "n":"Software Engineering and Object-oriented Programming" - * ) + * "c":"CS2113T", + * "n":"Software Engineering and Object-oriented Programming" + * ) * * @param string The string to parse. * @param argumentKeys The argument keys to find. From d1c9563b36fc0e52f28140442c4060eff9d64c67 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 19 Oct 2021 22:51:45 +0800 Subject: [PATCH 132/543] Add Architecture diagram and explanation of add module feature into DG --- docs/DeveloperGuide.md | 52 +++++++++++++++++++++++-- docs/diagrams/ArchitectureDiagram.png | Bin 0 -> 16073 bytes docs/diagrams/ArchitectureDiagram.puml | 51 ++++++++++++++++++++++++ src/main/java/taa/Parser.java | 6 +-- 4 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 docs/diagrams/ArchitectureDiagram.png create mode 100644 docs/diagrams/ArchitectureDiagram.puml diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 64e1f0ed2b..7a9fcee42d 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -5,9 +5,55 @@ {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.} - +### Architecture +![ArchitectureDiagram](diagrams/ArchitectureDiagram.png) +
+_Figure 1. Architecture Diagram_
+
+The _Architecture Diagram_ shown above explains the high-level design of the Application.
+
+Overview of components: +* `Main` + * On app launch: Creates and runs an instance of `Duke`. +* `UI` + * Handles UI operations. +* `Taa` + * On creation: Initializes the `UI` and `Storage` components. + * On run: Loads data saved in `Storage`, receives and processes user input from `UI`. +* `Command` + * Defines how a command is to be executed. +* `Models` + * Represents a collection of classes that holds the data of the application in-memory. + * Includes: `ModuleList`, `Modules`, `StudentList` , `Student`, `AssessmentList` , `Assessment`, `AttendanceList` , `Attendance` +* `Storage` + * Handles data storage operations (e.g. Reading from and writing to data file). +* `Commons` + * Represents a collection of classes used by other components. + * `Parser`: Used to translate user input into a `Command` and to parse an argument string into its various values. + * `Util`: Contains utility functions used by other classes. + +### Add module feature +The add module mechanism is facilitated by `AddModuleCommand`. It extends `Command` and uses `ModuleList` which stores +module internally as an ArrayList `modules`.
+ +`AddModuleCommand` implements the following methods: +* `AddModuleCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Performs operations for the command. + +`ModuleList` implements the following methods: +* `ModuleList#getSize()` - Returns the no. of modules currently in the list. +* `ModuleList#getModules()` - Returns an ArrayList containing all the modules. +* `ModuleList#getModule(code:String)` - Returns a module with a particular code. +* `ModuleList#isValidIndex()` - Checks if an index is valid w.r.t the `modules` ArrayList. +* `ModuleList#addModule(module:Module)` - Adds a module to the `modules` ArrayList. +* `ModuleList#getModuleAt(index:int)` - Returns a `Module` object at the specified `index` within the `modules` ArrayList. + +Below is an example scenario of how the add module feature behaves at each step:
+* Step 1 - The user executes `add_module c/CS2113T n/Software Engineering` to add a module. The `add_module` command calls +the `AddModuleCommand#execute` method. Within `AddModuleCommand#execute`, `ModuleList#getModule("CS2113T")` is called to +ensure that there is no existing module with code `CS2113T`. +* Step 2 - If no existing module with code `CS2113T` is found, a new `Module` object with code and name set to `CS2113T` +and `Software Engineering` set as its code and name respectively. Then, `ModuleList#addModule` is called to add the newly +created `Module` object into the `modules` ArrayList within `ModuleList`. ## Product scope ### Target user profile diff --git a/docs/diagrams/ArchitectureDiagram.png b/docs/diagrams/ArchitectureDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..ae34c14281428260ba422cb80a193806a42fb260 GIT binary patch literal 16073 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 literal 0 HcmV?d00001 diff --git a/docs/diagrams/ArchitectureDiagram.puml b/docs/diagrams/ArchitectureDiagram.puml new file mode 100644 index 0000000000..57d24fbb2b --- /dev/null +++ b/docs/diagrams/ArchitectureDiagram.puml @@ -0,0 +1,51 @@ +@startuml +!include +!include +!include + +skinparam Shadowing false +skinparam MinClassWidth 50 + +skinparam Class { + FontColor #FFFFFF + BorderThickness 1 + BorderColor #FFFFFF + StereotypeFontColor #FFFFFF + FontName Arial +} + +hide footbox +hide members +hide circle + +Package " "<>{ + Class UI #ForestGreen + Class Taa #Blue + Class Storage #DarkGoldenRod + Class Main #IndianRed + Class Command #DarkSlateBlue + Class Models #DarkRed + Class Commons #Purple + Class Dummy #White + Class Parser #Navy + Class Util #LightSeaGreen +} +Class "<$user>" as User #Red +Class "<$documents>" as File #Gray + +Main -down-> Taa +UI -> Taa +Taa -> Command +UI -down-> Command +Command -right-> Storage +Command -down-> Models +Models -right[hidden]- Dummy +Dummy .down.> Commons +Dummy .down.> Commons +Dummy .down.> Commons +Commons -left- Parser +Commons -down- Util + +UI <-up- User +Storage -right-> File +@enduml \ No newline at end of file diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 74c766717c..0b3307f752 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -119,9 +119,9 @@ public static String[] splitFirstSpace(String string) { * e.g. * string: "add_module c/CS2113T n/Software Engineering and Object-oriented Programming", argumentKeys: {"c","n"} * Result: HashMap( - * "c":"CS2113T", - * "n":"Software Engineering and Object-oriented Programming" - * ) + * "c":"CS2113T", + * "n":"Software Engineering and Object-oriented Programming" + * ) * * @param string The string to parse. * @param argumentKeys The argument keys to find. From 6f1a075a4b2af3e2541baf1f4cfbdd6087e45143 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 19 Oct 2021 22:55:00 +0800 Subject: [PATCH 133/543] Add newline to end of file --- docs/diagrams/ArchitectureDiagram.puml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/diagrams/ArchitectureDiagram.puml b/docs/diagrams/ArchitectureDiagram.puml index 57d24fbb2b..5165424b8f 100644 --- a/docs/diagrams/ArchitectureDiagram.puml +++ b/docs/diagrams/ArchitectureDiagram.puml @@ -48,4 +48,4 @@ Commons -down- Util UI <-up- User Storage -right-> File -@enduml \ No newline at end of file +@enduml From 6eea39aa4c6e1a8db25a65e036549338eb39846c Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 20 Oct 2021 13:43:01 +0800 Subject: [PATCH 134/543] Add description, Quick Start, list/add module and list students into UG --- docs/UserGuide.md | 54 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index abd9fbe891..141965b54d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,33 +1,57 @@ # User Guide +Teaching Assistant's Assistant (TAA) is a Command Line Interface (CLI) application for keeping track of modules and students. +If you can type fast, TAA can help keep track of your modules and students faster than traditional Graphical User Interface (GUI) apps. -## Introduction - -{Give a product intro} +* [Quick Start](#quick-start) +* [Features](#features) + * [Listing all modules: `list_modules`](#listing-all-modules-list_modules) + * [Adding a module: `add_module`](#adding-a-module-add_module) + * [Listing all students in a module: `list_students`](#listing-all-students-in-a-module-list_students) +* [FAQ](#faq) +* [Command Summary](#command-summary) ## Quick Start -{Give steps to get started quickly} - 1. Ensure that you have Java 11 or above installed. -1. Down the latest version of `Duke` from [here](http://link.to/duke). +2. Down the latest version of `Taa.jar` from [here](https://github.com/AY2122S1-CS2113T-F12-3/tp/releases). +3. Create a new folder and place `Taa.jar` inside. +4. Open Command Prompt/Terminal and navigate to the folder containing `Taa.jar`. +5. Run `java -jar Taa.jar` to start the app. +6. Enter `help` to view a list of available commands. See [Features](#features) for more information. ## Features -{Give detailed description of each feature} +### Listing all modules: `list_modules` +Shows a list of all modules in the module list. + +Format: `list_modules` + +
+ +### Adding a module: `add_module` +Adds a module to the module list. + +Format: `add_module c/ n/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `MODULE_NAME` refers to the name of the module. -### Adding a todo: `todo` -Adds a new item to the list of todo items. +Examples: +* `add_module c/CS2113T n/Software Engineering and Object-oriented Programming` +* `add_module n/Effective Communication for Computing Professionals c/CS2101` -Format: `todo n/TODO_NAME d/DEADLINE` +
-* The `DEADLINE` can be in a natural language format. -* The `TODO_NAME` cannot contain punctuation. +### Listing all students in a module: `list_students` +Shows a list of all students in a particular module. -Example of usage: +Format: `list_students c/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -`todo n/Write the rest of the User Guide d/next week` +Examples: +* `list_students c/CS2113T` +* `list_students c/CS2101` -`todo n/Refactor the User Guide to remove passive voice d/13/04/2020` +
## FAQ From 165f5baf07fea1cfa291cf76432c057e391dd5b8 Mon Sep 17 00:00:00 2001 From: rachel Date: Wed, 20 Oct 2021 20:40:49 +0800 Subject: [PATCH 135/543] add maximum marks to the assessment-related classes. test as well --- src/main/java/taa/assessment/Assessment.java | 25 ++++++++++- .../java/taa/assessment/AssessmentList.java | 7 ++- .../taa/command/AddAssessmentCommand.java | 43 +++++++++++++++---- .../deserializer/AssessmentDeserializer.java | 11 ++++- src/test/java/taa/StudentTest.java | 2 +- .../taa/assessment/AssessmentListTest.java | 26 ++++++++++- 6 files changed, 98 insertions(+), 16 deletions(-) diff --git a/src/main/java/taa/assessment/Assessment.java b/src/main/java/taa/assessment/Assessment.java index 466676c670..de3290970a 100644 --- a/src/main/java/taa/assessment/Assessment.java +++ b/src/main/java/taa/assessment/Assessment.java @@ -4,12 +4,15 @@ public class Assessment implements ClassChecker { private static final double[] WEIGHTAGE_RANGE = {0, 100}; + private static final int MAXIMUM_MARKS_RANGE = 0; private String name; + private int maximumMarks; private double weightage; - public Assessment(String name, double weightage) { + public Assessment(String name, int maximumMarks, double weightage) { this.name = name; + this.maximumMarks = maximumMarks; this.weightage = weightage; } @@ -23,6 +26,16 @@ public static boolean isWeightageWithinRange(double weightage) { return (weightage >= WEIGHTAGE_RANGE[0] && weightage <= WEIGHTAGE_RANGE[1]); } + /** + * Checks if a maximum marks is valid. + * + * @param maximumMarks The maximum marks to check. + * @return true if valid, else false. + */ + public static boolean isMaximumMarksWithinRange(int maximumMarks) { + return (maximumMarks >= MAXIMUM_MARKS_RANGE); + } + /** * Gets the weightage range. * @@ -32,6 +45,10 @@ public static double[] getWeightageRange() { return WEIGHTAGE_RANGE; } + public static int getMaximumMarksRange() { + return MAXIMUM_MARKS_RANGE; + } + public String getName() { return name; } @@ -40,6 +57,10 @@ public double getWeightage() { return weightage; } + public int getMaximumMarks() { + return maximumMarks; + } + /** * Format the string to print out the assessment. * For Midterms with 20% weightage, @@ -49,7 +70,7 @@ public double getWeightage() { */ @Override public String toString() { - return String.format("%s (%,.2f%%)", name, weightage); + return String.format("%s (%d, %,.2f%%)", name, maximumMarks, weightage); } /** diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index b81a00589d..d9a6353de5 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -53,7 +53,8 @@ public boolean addAssessment(Assessment assessment) { } double newTotalWeightage = totalWeightage + assessment.getWeightage(); - if (!Assessment.isWeightageWithinRange(newTotalWeightage)) { + if (!Assessment.isWeightageWithinRange(newTotalWeightage) + || !Assessment.isMaximumMarksWithinRange(assessment.getMaximumMarks())) { return false; } @@ -127,6 +128,10 @@ public boolean verify() { assessmentNames.add(name.toLowerCase()); totalWeightage += assessment.getWeightage(); } + + if (!Assessment.isMaximumMarksWithinRange(assessment.getMaximumMarks())) { + return false; + } } for (Assessment assessment : duplicatedAssessments) { diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index fe448c36b8..1c07158020 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -13,14 +13,22 @@ public class AddAssessmentCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_ASSESSMENT_NAME = "n"; private static final String KEY_WEIGHTAGE = "w"; - private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME, KEY_WEIGHTAGE}; + private static final String KEY_MAXIMUM_MARKS = "m"; + private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME, + KEY_MAXIMUM_MARKS, + KEY_WEIGHTAGE + }; private static final String MESSAGE_FAIL_TO_ADD = "Fail to add assessment."; private static final String MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE = "%s %s/ %s/ " - + "%s/"; + + "%s/ %s/"; private static final String MESSAGE_FORMAT_INVALID_WEIGHTAGE = "Invalid weightage. " + "Weightage must be between %,.2f and %,.2f (inclusive)"; + private static final String MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS = "Invalid maximum marks. " + + "Maximum marks must be larger than %d (inclusive)"; private static final String MESSAGE_FORMAT_ASSESSMENT_ADDED = "Assessment added:\n" + " %s\nThere are %d assessments in the %s."; @@ -52,6 +60,24 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } + String maximumMarksString = argumentMap.get(KEY_MAXIMUM_MARKS); + if (!Util.isStringInteger(maximumMarksString)) { + int maximumMarksRange = Assessment.getMaximumMarksRange(); + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS, + maximumMarksRange) + ); + } + + int maximumMarks = Integer.parseInt(maximumMarksString); + if (!Assessment.isMaximumMarksWithinRange(maximumMarks)) { + int maximumMarksRange = Assessment.getMaximumMarksRange(); + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS, + maximumMarksRange) + ); + } + String weightageString = argumentMap.get(KEY_WEIGHTAGE); if (!Util.isStringDouble(weightageString)) { double[] weightageRange = Assessment.getWeightageRange(); @@ -73,7 +99,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String name = argumentMap.get(KEY_ASSESSMENT_NAME); - Assessment assessment = new Assessment(name, weightage); + Assessment assessment = new Assessment(name, maximumMarks, weightage); AssessmentList assessmentList = module.getAssessmentList(); boolean isSuccessful = assessmentList.addAssessment(assessment); @@ -90,11 +116,12 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE, - COMMAND_ADD_ASSESSMENT, - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME, - KEY_WEIGHTAGE + MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE, + COMMAND_ADD_ASSESSMENT, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME, + KEY_MAXIMUM_MARKS, + KEY_WEIGHTAGE ); } } diff --git a/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java b/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java index 7c16b248ad..068be58ab4 100644 --- a/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java +++ b/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java @@ -13,7 +13,8 @@ public class AssessmentDeserializer extends StorageDeserializer implements JsonDeserializer { private static final String MEMBER_NAME = "name"; private static final String MEMBER_WEIGHTAGE = "weightage"; - private static final String[] MEMBERS = {MEMBER_NAME, MEMBER_WEIGHTAGE}; + private static final String MEMBER_MAXIMUM_MARKS = "maximumMarks"; + private static final String[] MEMBERS = {MEMBER_NAME, MEMBER_MAXIMUM_MARKS, MEMBER_WEIGHTAGE}; @Override public Assessment deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) @@ -32,7 +33,13 @@ public Assessment deserialize(JsonElement json, Type typeOfT, JsonDeserializatio } double weightage = weightageJson.getAsDouble(); - Assessment assessment = new Assessment(name, weightage); + JsonElement maximumMarksJson = jsonObject.get(MEMBER_MAXIMUM_MARKS); + if (!Util.isStringInteger(maximumMarksJson.getAsString())) { + return null; + } + int maximumMarks = maximumMarksJson.getAsInt(); + + Assessment assessment = new Assessment(name, maximumMarks, weightage); if (!assessment.verify()) { return null; } diff --git a/src/test/java/taa/StudentTest.java b/src/test/java/taa/StudentTest.java index e57d94f05f..a48e2b4d6b 100644 --- a/src/test/java/taa/StudentTest.java +++ b/src/test/java/taa/StudentTest.java @@ -17,7 +17,7 @@ public void testStringConversion() { void setMarks_newMarksArguments_marksAddedCorrectly() { Student student = new Student("A0123456X", "Jim"); AssessmentList assessments = new AssessmentList(); - assessments.addAssessment(new Assessment("Midterms", 20)); + assessments.addAssessment(new Assessment("Midterms", 100, 20)); student.setMarks("Midterms", 99.9); assertEquals(99.9, student.getMarks("Midterms")); } diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index 227df55614..e9baa690c9 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -1,6 +1,12 @@ package taa.assessment; import org.junit.jupiter.api.Test; +import taa.Parser; +import taa.Ui; +import taa.command.Command; +import taa.exception.TaaException; +import taa.module.ModuleList; +import taa.storage.Storage; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -8,10 +14,26 @@ class AssessmentListTest { @Test void addAssessment_newAssessmentArguments_assessmentAddedCorrectly() { - String inputString = "c/CS2113T a/Midterms w/20"; AssessmentList assessments = new AssessmentList(); - assessments.addAssessment(new Assessment("Midterms", 20)); + assessments.addAssessment(new Assessment("Midterms", 50, 20)); assertEquals("Midterms", assessments.getAssessment("Midterms").getName()); + assertEquals(50, assessments.getAssessment("Midterms").getMaximumMarks()); assertEquals(20, assessments.getAssessment("Midterms").getWeightage()); } + + @Test + void addAssessment_userInput_assessmentAddedCorrectly() throws TaaException { + Ui ui = new Ui(); + Storage storage = new Storage("./data/taa_data.json"); + ModuleList moduleList = new ModuleList(); + String moduleInput = "add_module c/cs2113t n/software engineering"; + String assessmentInput = "add_assessment c/cs2113t n/Midterms m/50 w/20"; + Command command1 = Parser.parseUserInput(moduleInput); + command1.execute(moduleList, ui, storage); + Command command2 = Parser.parseUserInput(assessmentInput); + command2.execute(moduleList, ui, storage); + assertEquals("Midterms", moduleList.getModule("cs2113t").getAssessmentList().getAssessment("Midterms").getName()); + assertEquals(50, moduleList.getModule("cs2113t").getAssessmentList().getAssessment("Midterms").getMaximumMarks()); + assertEquals(20, moduleList.getModule("cs2113t").getAssessmentList().getAssessment("Midterms").getWeightage()); + } } From 9967739d518472434705ed7f18c8a2f0b8815d3a Mon Sep 17 00:00:00 2001 From: rachel Date: Wed, 20 Oct 2021 20:48:45 +0800 Subject: [PATCH 136/543] Fix checkstyle. --- src/main/java/taa/command/AddAssessmentCommand.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 1c07158020..b403912f86 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -15,10 +15,10 @@ public class AddAssessmentCommand extends Command { private static final String KEY_WEIGHTAGE = "w"; private static final String KEY_MAXIMUM_MARKS = "m"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME, - KEY_MAXIMUM_MARKS, - KEY_WEIGHTAGE + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME, + KEY_MAXIMUM_MARKS, + KEY_WEIGHTAGE }; private static final String MESSAGE_FAIL_TO_ADD = "Fail to add assessment."; From c428fe8f75e5ba6d5be48d24ea1c5d0f6bed78e6 Mon Sep 17 00:00:00 2001 From: rachel Date: Wed, 20 Oct 2021 20:53:02 +0800 Subject: [PATCH 137/543] Fix checkstyle. --- src/test/java/taa/assessment/AssessmentListTest.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index e9baa690c9..5f72f96afa 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -32,8 +32,11 @@ void addAssessment_userInput_assessmentAddedCorrectly() throws TaaException { command1.execute(moduleList, ui, storage); Command command2 = Parser.parseUserInput(assessmentInput); command2.execute(moduleList, ui, storage); - assertEquals("Midterms", moduleList.getModule("cs2113t").getAssessmentList().getAssessment("Midterms").getName()); - assertEquals(50, moduleList.getModule("cs2113t").getAssessmentList().getAssessment("Midterms").getMaximumMarks()); - assertEquals(20, moduleList.getModule("cs2113t").getAssessmentList().getAssessment("Midterms").getWeightage()); + assertEquals("Midterms", moduleList.getModule("cs2113t"). + getAssessmentList().getAssessment("Midterms").getName()); + assertEquals(50, moduleList.getModule("cs2113t"). + getAssessmentList().getAssessment("Midterms").getMaximumMarks()); + assertEquals(20, moduleList.getModule("cs2113t"). + getAssessmentList().getAssessment("Midterms").getWeightage()); } } From 297612b76fa18421613a3f95ff75bd5b2fcdbb21 Mon Sep 17 00:00:00 2001 From: rachel Date: Wed, 20 Oct 2021 20:56:46 +0800 Subject: [PATCH 138/543] Fix checkstyle. --- src/test/java/taa/assessment/AssessmentListTest.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index 5f72f96afa..cd8a499e4b 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -32,11 +32,11 @@ void addAssessment_userInput_assessmentAddedCorrectly() throws TaaException { command1.execute(moduleList, ui, storage); Command command2 = Parser.parseUserInput(assessmentInput); command2.execute(moduleList, ui, storage); - assertEquals("Midterms", moduleList.getModule("cs2113t"). - getAssessmentList().getAssessment("Midterms").getName()); - assertEquals(50, moduleList.getModule("cs2113t"). - getAssessmentList().getAssessment("Midterms").getMaximumMarks()); - assertEquals(20, moduleList.getModule("cs2113t"). - getAssessmentList().getAssessment("Midterms").getWeightage()); + assertEquals("Midterms", moduleList.getModule("cs2113t") + .getAssessmentList().getAssessment("Midterms").getName()); + assertEquals(50, moduleList.getModule("cs2113t") + .getAssessmentList().getAssessment("Midterms").getMaximumMarks()); + assertEquals(20, moduleList.getModule("cs2113t") + .getAssessmentList().getAssessment("Midterms").getWeightage()); } } From 3daf89d6e8cfd6c0f23fdf2cff7f9d9f90d943f7 Mon Sep 17 00:00:00 2001 From: rachel Date: Wed, 20 Oct 2021 21:06:52 +0800 Subject: [PATCH 139/543] Update about us --- docs/AboutUs.md | 2 +- docs/team/rachel.md | 7 +------ 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 602ed6fdaa..bb8932de5a 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -5,5 +5,5 @@ Display | Name | Github Profile | Portfolio ![](https://via.placeholder.com/100.png?text=Photo) | Zhen Hong | [hozhenhong99](https://github.com/hozhenhong99) | [Zhen Hong's Portfolio](team/zhenhong.md) ![](https://via.placeholder.com/100.png?text=Photo) | Dak Nam | [daknam2001](https://github.com/daknam2001) | [Portfolio](team/daknam.md) ![](https://via.placeholder.com/100.png?text=Photo) | Jon Lim | [jon-the-melon](https://github.com/jon-the-melon) | [Jon's Portfolio](team/jon.md) -![](https://via.placeholder.com/100.png?text=Photo) | Rachel | [rachelkeh](https://github.com/rachelkeh) | [Portfolio](team/rachel.md) +![](https://via.placeholder.com/100.png?text=Photo) | Rachel | [rachelkeh](https://github.com/rachelkeh) | [Rachel's Portfolio](team/rachel.md) ![](https://via.placeholder.com/100.png?text=Photo) | Leyond | [leyondlee](https://github.com/leyondlee) | [Portfolio](team/leyond.md) diff --git a/docs/team/rachel.md b/docs/team/rachel.md index e4f157818a..c76478e2f7 100644 --- a/docs/team/rachel.md +++ b/docs/team/rachel.md @@ -1,6 +1 @@ -# Rachel - Project Portfolio Page - -## Overview - - -### Summary of Contributions +Hi, I'm Rachel. From 5476d49efa7d9146bb7f47a532871d8db9a9c9ce Mon Sep 17 00:00:00 2001 From: rachel Date: Wed, 20 Oct 2021 21:46:02 +0800 Subject: [PATCH 140/543] Add assertions for the assessment-related classes --- src/main/java/taa/assessment/AssessmentList.java | 1 + src/main/java/taa/command/AddAssessmentCommand.java | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index d9a6353de5..bcefb01008 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -121,6 +121,7 @@ public boolean verify() { ArrayList duplicatedAssessments = new ArrayList<>(); double totalWeightage = 0; for (Assessment assessment : assessments) { + assert assessment != null : "assessment should exist."; String name = assessment.getName(); if (assessmentNames.contains(name.toLowerCase())) { duplicatedAssessments.add(assessment); diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index b403912f86..be3499a9c5 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -107,8 +107,10 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(MESSAGE_FAIL_TO_ADD); } + assert storage != null : "storage should exist."; storage.save(moduleList); + assert ui != null : "ui should exist."; ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_ADDED, assessment, assessmentList.getSize(), module)); } From 736982448175431922e6b3045b5fb2cdf77575ba Mon Sep 17 00:00:00 2001 From: rachel Date: Thu, 21 Oct 2021 00:16:06 +0800 Subject: [PATCH 141/543] Add and tested delete_assessment command with assertions and exceptions. --- src/main/java/taa/Parser.java | 22 ++---- .../java/taa/assessment/AssessmentList.java | 21 +++++- .../taa/command/AddAssessmentCommand.java | 13 ++-- src/main/java/taa/command/Command.java | 1 + .../taa/command/DeleteAssessmentCommand.java | 71 +++++++++++++++++++ src/main/java/taa/command/HelpCommand.java | 1 + .../taa/assessment/AssessmentListTest.java | 29 ++++++++ 7 files changed, 134 insertions(+), 24 deletions(-) create mode 100644 src/main/java/taa/command/DeleteAssessmentCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 0b3307f752..6fd735435f 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,22 +1,6 @@ package taa; -import taa.command.AddAssessmentCommand; -import taa.command.AddModuleCommand; -import taa.command.AddStudentCommand; -import taa.command.HelpCommand; -import taa.command.SetAttendanceCommand; -import taa.command.AverageMarksCommand; -import taa.command.Command; -import taa.command.DeleteStudentCommand; -import taa.command.EditStudentCommand; -import taa.command.ExitCommand; -import taa.command.FindStudentCommand; -import taa.command.ListAssessmentsCommand; -import taa.command.ListMarksCommand; -import taa.command.ListModulesCommand; -import taa.command.ListStudentsCommand; -import taa.command.ListAttendanceCommand; -import taa.command.SetMarksCommand; +import taa.command.*; import taa.exception.TaaException; @@ -78,6 +62,10 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new ListAssessmentsCommand(argument); break; + case Command.COMMAND_DELETE_ASSESSMENT: + command = new DeleteAssessmentCommand(argument); + break; + case Command.COMMAND_SET_ATTENDANCE: command = new SetAttendanceCommand(argument); break; diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index bcefb01008..0e4efaaad7 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -40,7 +40,7 @@ public boolean isValidIndex(int index) { * or total weightage exceed the maximum weightage after adding. * * @param assessment The assessment object to be added. - * @return tue if success, else false. + * @return True if success, else false. */ public boolean addAssessment(Assessment assessment) { double totalWeightage = 0; @@ -62,6 +62,25 @@ public boolean addAssessment(Assessment assessment) { return true; } + /** + * Deletes an assessment from the list of assessments in a particular module. + * + * @param assessmentName The name of the assessment object to be removed. + * @return The removed assessment object. + */ + public Assessment deleteAssessment(String assessmentName) { + int indexOfAssessmentToRemove = 0; + for (Assessment assessment : assessments) { + String name = assessment.getName(); + if (name.equalsIgnoreCase(assessmentName)) { + return assessments.remove(indexOfAssessmentToRemove); + } + indexOfAssessmentToRemove += 1; + } + + return null; + } + /** * Gets an Assessment object at the index from the assessment ArrayList. * diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index be3499a9c5..09fa786b71 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -15,10 +15,10 @@ public class AddAssessmentCommand extends Command { private static final String KEY_WEIGHTAGE = "w"; private static final String KEY_MAXIMUM_MARKS = "m"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME, - KEY_MAXIMUM_MARKS, - KEY_WEIGHTAGE + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME, + KEY_MAXIMUM_MARKS, + KEY_WEIGHTAGE }; private static final String MESSAGE_FAIL_TO_ADD = "Fail to add assessment."; @@ -29,7 +29,7 @@ public class AddAssessmentCommand extends Command { + "Weightage must be between %,.2f and %,.2f (inclusive)"; private static final String MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS = "Invalid maximum marks. " + "Maximum marks must be larger than %d (inclusive)"; - private static final String MESSAGE_FORMAT_ASSESSMENT_ADDED = "Assessment added:\n" + private static final String MESSAGE_FORMAT_ASSESSMENT_ADDED = "Assessment added to %s:\n" + " %s\nThere are %d assessments in the %s."; public AddAssessmentCommand(String argument) { @@ -102,6 +102,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc Assessment assessment = new Assessment(name, maximumMarks, weightage); AssessmentList assessmentList = module.getAssessmentList(); + assert assessmentList != null : "assessment list should exist."; boolean isSuccessful = assessmentList.addAssessment(assessment); if (!isSuccessful) { throw new TaaException(MESSAGE_FAIL_TO_ADD); @@ -111,7 +112,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc storage.save(moduleList); assert ui != null : "ui should exist."; - ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_ADDED, + ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_ADDED, moduleCode, assessment, assessmentList.getSize(), module)); } diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index dfbf79e067..b4437d91c5 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -23,6 +23,7 @@ public abstract class Command { public static final String COMMAND_DELETE_STUDENT = "delete_student"; public static final String COMMAND_SET_ATTENDANCE = "set_attendance"; public static final String COMMAND_ADD_ASSESSMENT = "add_assessment"; + public static final String COMMAND_DELETE_ASSESSMENT = "delete_assessment"; public static final String COMMAND_SET_MARKS = "set_marks"; public static final String COMMAND_HELP = "help"; diff --git a/src/main/java/taa/command/DeleteAssessmentCommand.java b/src/main/java/taa/command/DeleteAssessmentCommand.java new file mode 100644 index 0000000000..be7e7d20e0 --- /dev/null +++ b/src/main/java/taa/command/DeleteAssessmentCommand.java @@ -0,0 +1,71 @@ +package taa.command; + +import taa.Ui; +import taa.assessment.Assessment; +import taa.assessment.AssessmentList; +import taa.exception.TaaException; +import taa.module.Module; +import taa.module.ModuleList; +import taa.storage.Storage; + +public class DeleteAssessmentCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_ASSESSMENT_NAME = "n"; + private static final String[] DELETE_ASSESSMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; + + private static final String MESSAGE_FORMAT_DELETE_ASSESSMENT_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_ASSESSMENT_DELETED = "Assessment removed from %s:\n %s"; + + public DeleteAssessmentCommand(String argument) { + super(argument, DELETE_ASSESSMENT_ARGUMENT_KEYS); + } + + /** + * Executes the delete_assessment command and deletes an assessment with the specified assessment name. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!checkArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModule(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + + String name = argumentMap.get(KEY_ASSESSMENT_NAME); + AssessmentList assessmentList = module.getAssessmentList(); + assert assessmentList != null : "assessment list should exist."; + Assessment assessment = assessmentList.deleteAssessment(name); + if (assessment == null) { + throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); + } + + assert storage != null : "storage should exist."; + storage.save(moduleList); + + assert ui != null : "ui should exist."; + ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_DELETED, moduleCode, assessment)); + } + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_DELETE_ASSESSMENT_USAGE, + COMMAND_DELETE_ASSESSMENT, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME + ); + } +} diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index 9dca3de10f..476e9eed37 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -14,6 +14,7 @@ public class HelpCommand extends Command { new AddStudentCommand(""), new AverageMarksCommand(""), new DeleteStudentCommand(""), + new DeleteAssessmentCommand(""), new EditStudentCommand(""), new FindStudentCommand(""), new ExitCommand(""), diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index cd8a499e4b..8522afdcc0 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -8,6 +8,8 @@ import taa.module.ModuleList; import taa.storage.Storage; +import java.util.ArrayList; + import static org.junit.jupiter.api.Assertions.assertEquals; class AssessmentListTest { @@ -39,4 +41,31 @@ void addAssessment_userInput_assessmentAddedCorrectly() throws TaaException { assertEquals(20, moduleList.getModule("cs2113t") .getAssessmentList().getAssessment("Midterms").getWeightage()); } + + @Test + void deleteAssessment_deleteAssessmentArguments_assessmentDeletedCorrectly() throws TaaException { + AssessmentList assessments = new AssessmentList(); + assessments.addAssessment(new Assessment("Midterms", 50, 20)); + Assessment assessment = assessments.deleteAssessment("Midterms"); + assertEquals("Midterms", assessment.getName()); + assertEquals(50, assessment.getMaximumMarks()); + assertEquals(20, assessment.getWeightage()); + } + + @Test + void deleteAssessment_userInput_emptyAssessmentList() throws TaaException { + Ui ui = new Ui(); + Storage storage = new Storage("./data/taa_data.json"); + ModuleList moduleList = new ModuleList(); + String moduleInput = "add_module c/cs2113t n/software engineering"; + String assessmentInput = "add_assessment c/cs2113t n/Midterms m/50 w/20"; + String deleteAssessmentInput = "delete_assessment c/cs2113t n/Midterms"; + Command command1 = Parser.parseUserInput(moduleInput); + command1.execute(moduleList, ui, storage); + Command command2 = Parser.parseUserInput(assessmentInput); + command2.execute(moduleList, ui, storage); + Command command3 = Parser.parseUserInput(deleteAssessmentInput); + command3.execute(moduleList, ui, storage); + assertEquals(new AssessmentList().getSize(), moduleList.getModule("cs2113t").getAssessmentList().getSize()); + } } From 925fa4b7e8140eaada71543c202cbf11882eb7af Mon Sep 17 00:00:00 2001 From: rachel Date: Thu, 21 Oct 2021 00:19:01 +0800 Subject: [PATCH 142/543] Update checkstyle --- src/main/java/taa/Parser.java | 20 +++++++++++++++++-- .../taa/command/AddAssessmentCommand.java | 8 ++++---- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 6fd735435f..ed7525c6cf 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,7 +1,23 @@ package taa; -import taa.command.*; - +import taa.command.AddAssessmentCommand; +import taa.command.AddModuleCommand; +import taa.command.AddStudentCommand; +import taa.command.AverageMarksCommand; +import taa.command.Command; +import taa.command.DeleteAssessmentCommand; +import taa.command.DeleteStudentCommand; +import taa.command.EditStudentCommand; +import taa.command.ExitCommand; +import taa.command.FindStudentCommand; +import taa.command.HelpCommand; +import taa.command.ListAssessmentsCommand; +import taa.command.ListAttendanceCommand; +import taa.command.ListMarksCommand; +import taa.command.ListModulesCommand; +import taa.command.ListStudentsCommand; +import taa.command.SetAttendanceCommand; +import taa.command.SetMarksCommand; import taa.exception.TaaException; import java.util.ArrayList; diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 09fa786b71..b138909474 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -15,10 +15,10 @@ public class AddAssessmentCommand extends Command { private static final String KEY_WEIGHTAGE = "w"; private static final String KEY_MAXIMUM_MARKS = "m"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME, - KEY_MAXIMUM_MARKS, - KEY_WEIGHTAGE + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME, + KEY_MAXIMUM_MARKS, + KEY_WEIGHTAGE }; private static final String MESSAGE_FAIL_TO_ADD = "Fail to add assessment."; From 08a382cf21ee4bea279b0c9df92acb82205ef2b3 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 21 Oct 2021 01:18:26 +0800 Subject: [PATCH 143/543] Add sequence diagram for architecture and change arrow direction for architecture diagram --- docs/DeveloperGuide.md | 28 +++++++---- docs/diagrams/ArchitectureDiagram.png | Bin 16073 -> 16039 bytes docs/diagrams/ArchitectureDiagram.puml | 8 ++-- docs/diagrams/ArchitectureSequenceDiagram.png | Bin 0 -> 28022 bytes .../diagrams/ArchitectureSequenceDiagram.puml | 45 ++++++++++++++++++ 5 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 docs/diagrams/ArchitectureSequenceDiagram.png create mode 100644 docs/diagrams/ArchitectureSequenceDiagram.puml diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 7a9fcee42d..8c8d2e913e 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,10 +1,17 @@ # Developer Guide +* [Acknowledgements](#acknowledgements) +* [Design](#design) +* [Implementation](#implementation) +* [Project scope](#product-scope) +* [User Stories](#user-stories) +* [Non-Functional Requirements](#non-functional-requirements) +* [Glossary](#glossary) ## 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 +## Design ### Architecture ![ArchitectureDiagram](diagrams/ArchitectureDiagram.png)
@@ -12,7 +19,7 @@ _Figure 1. Architecture Diagram_

The _Architecture Diagram_ shown above explains the high-level design of the Application.

-Overview of components: +**Overview of components** * `Main` * On app launch: Creates and runs an instance of `Duke`. * `UI` @@ -22,7 +29,7 @@ Overview of components: * On run: Loads data saved in `Storage`, receives and processes user input from `UI`. * `Command` * Defines how a command is to be executed. -* `Models` +* `Model` * Represents a collection of classes that holds the data of the application in-memory. * Includes: `ModuleList`, `Modules`, `StudentList` , `Student`, `AssessmentList` , `Assessment`, `AttendanceList` , `Attendance` * `Storage` @@ -32,7 +39,16 @@ Overview of components: * `Parser`: Used to translate user input into a `Command` and to parse an argument string into its various values. * `Util`: Contains utility functions used by other classes. -### Add module feature +
+ +**Interactions between components** +
+ +![ArchitectureSequenceDiagram](diagrams/ArchitectureSequenceDiagram.png) +_Figure 2. An example of interactions between components for `add_module c/CS2113T n/Software Engineering`._ + +## Implementation +### Add module The add module mechanism is facilitated by `AddModuleCommand`. It extends `Command` and uses `ModuleList` which stores module internally as an ArrayList `modules`.
@@ -78,7 +94,3 @@ created `Module` object into the `modules` ArrayList within `ModuleList`. ## Glossary * *glossary item* - Definition - -## Instructions for manual testing - -{Give instructions on how to do a manual product testing e.g., how to load sample data to be used for testing} diff --git a/docs/diagrams/ArchitectureDiagram.png b/docs/diagrams/ArchitectureDiagram.png index ae34c14281428260ba422cb80a193806a42fb260..1a4942b2dd8660cb73c7795c85ab2b2b187edfe3 100644 GIT binary patch literal 16039 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 diff --git a/docs/diagrams/ArchitectureDiagram.puml b/docs/diagrams/ArchitectureDiagram.puml index 5165424b8f..b400a5389a 100644 --- a/docs/diagrams/ArchitectureDiagram.puml +++ b/docs/diagrams/ArchitectureDiagram.puml @@ -24,7 +24,7 @@ Package " "<>{ Class Storage #DarkGoldenRod Class Main #IndianRed Class Command #DarkSlateBlue - Class Models #DarkRed + Class Model #DarkRed Class Commons #Purple Class Dummy #White Class Parser #Navy @@ -36,10 +36,10 @@ Class "<$documents>" as File #Gray Main -down-> Taa UI -> Taa Taa -> Command -UI -down-> Command +Command -up-> UI Command -right-> Storage -Command -down-> Models -Models -right[hidden]- Dummy +Command -down-> Model +Model -right[hidden]- Dummy Dummy .down.> Commons Dummy .down.> Commons Dummy .down.> Commons diff --git a/docs/diagrams/ArchitectureSequenceDiagram.png b/docs/diagrams/ArchitectureSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..3f7bcf89e5b436579bdcebec96a4f376b4efed82 GIT binary patch literal 28022 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 literal 0 HcmV?d00001 diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml new file mode 100644 index 0000000000..26b22e026c --- /dev/null +++ b/docs/diagrams/ArchitectureSequenceDiagram.puml @@ -0,0 +1,45 @@ +@startuml + +Actor User as user +Participant ":UI" as ui +Participant ":Taa" as taa +Participant ":Command" as command +Participant ":ModuleList" as modulelist +Participant ":Storage" as storage + +note left of modulelist: Model + +user -> ui : "add_module c/CS2113T\nn/Software Engineering" +activate ui + +ui -> taa +activate taa + +taa -> command : execute() +activate command + +command -> modulelist : addModule(module) +activate modulelist + +modulelist --> command +deactivate modulelist + +command -> storage : save(moduleList) +activate storage + +storage --> command +deactivate storage + +command -> ui : printMessage(...) +ui --> command + +command --> taa +deactivate command + +taa --> ui +deactivate taa + +ui --> user +deactivate ui + +@enduml \ No newline at end of file From 7126f79ce9caed0694790998fd0a2574e2d3698b Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 21 Oct 2021 01:18:26 +0800 Subject: [PATCH 144/543] Add sequence diagram for architecture and change arrow direction --- docs/DeveloperGuide.md | 28 +++++++---- docs/diagrams/ArchitectureDiagram.png | Bin 16073 -> 16039 bytes docs/diagrams/ArchitectureDiagram.puml | 8 ++-- docs/diagrams/ArchitectureSequenceDiagram.png | Bin 0 -> 28022 bytes .../diagrams/ArchitectureSequenceDiagram.puml | 45 ++++++++++++++++++ 5 files changed, 69 insertions(+), 12 deletions(-) create mode 100644 docs/diagrams/ArchitectureSequenceDiagram.png create mode 100644 docs/diagrams/ArchitectureSequenceDiagram.puml diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 7a9fcee42d..8c8d2e913e 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -1,10 +1,17 @@ # Developer Guide +* [Acknowledgements](#acknowledgements) +* [Design](#design) +* [Implementation](#implementation) +* [Project scope](#product-scope) +* [User Stories](#user-stories) +* [Non-Functional Requirements](#non-functional-requirements) +* [Glossary](#glossary) ## 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 +## Design ### Architecture ![ArchitectureDiagram](diagrams/ArchitectureDiagram.png)
@@ -12,7 +19,7 @@ _Figure 1. Architecture Diagram_

The _Architecture Diagram_ shown above explains the high-level design of the Application.

-Overview of components: +**Overview of components** * `Main` * On app launch: Creates and runs an instance of `Duke`. * `UI` @@ -22,7 +29,7 @@ Overview of components: * On run: Loads data saved in `Storage`, receives and processes user input from `UI`. * `Command` * Defines how a command is to be executed. -* `Models` +* `Model` * Represents a collection of classes that holds the data of the application in-memory. * Includes: `ModuleList`, `Modules`, `StudentList` , `Student`, `AssessmentList` , `Assessment`, `AttendanceList` , `Attendance` * `Storage` @@ -32,7 +39,16 @@ Overview of components: * `Parser`: Used to translate user input into a `Command` and to parse an argument string into its various values. * `Util`: Contains utility functions used by other classes. -### Add module feature +
+ +**Interactions between components** +
+ +![ArchitectureSequenceDiagram](diagrams/ArchitectureSequenceDiagram.png) +_Figure 2. An example of interactions between components for `add_module c/CS2113T n/Software Engineering`._ + +## Implementation +### Add module The add module mechanism is facilitated by `AddModuleCommand`. It extends `Command` and uses `ModuleList` which stores module internally as an ArrayList `modules`.
@@ -78,7 +94,3 @@ created `Module` object into the `modules` ArrayList within `ModuleList`. ## Glossary * *glossary item* - Definition - -## Instructions for manual testing - -{Give instructions on how to do a manual product testing e.g., how to load sample data to be used for testing} diff --git a/docs/diagrams/ArchitectureDiagram.png b/docs/diagrams/ArchitectureDiagram.png index ae34c14281428260ba422cb80a193806a42fb260..1a4942b2dd8660cb73c7795c85ab2b2b187edfe3 100644 GIT binary patch literal 16039 zcmeHuWn9$XyWju<$_R*vLnERR0wdDhAR-}%lnf$L(gG4gD2OzOAl=<9C^0lhcS}px z07KV)XAu9tyLb2AH+S#ui+#n1?>Xl=PoJm8M_Eypkbsf^1OgGtJ(5xZfv|KyAZ+T( z*ua-jyyX($53{YbhONG(m7|$~p)E+(z{23Io~^;_Tdy2%8Qa=g2|%G%W_lL3cIIa6 z`j+M-5BRA;AiQIfXBxH_-$7Ua7>AfO&2gn)eAnD`ea>p}_qs(ug`|u`5*f@dp2E9t zGp$Lg#n$D0@HQ)IHT;p(ce25I`e=r4WW0u6Csm*JdByGqZyZHXGu@FPtV#MuL>g7H z?iaHd_IuQ83qwOK5gWAgBN1J#2kQz^x|^b3a(+uUwRxy@%Zb3AI6m(@QVzF)wcA6G zSE{Iz4|KkC%-oJk@*8vbau)fTcTqrb;n%8wLQy?eTvzqIkgc0f(-lH>7V`s0upPsV z=Jev`aYvmPrMas+{H{PnChyHw_~TGUcL?u;twI*&>iwZlnW99SR0ET4`_Nmtfuk)* ztxy78ZP~|Or`&UW_pLO}C>b01=CGY^25rnx1@iRFpPus5g|(q(!=?DJWJe_Wj`h1vZ5^)z zTS_BRX~d)1FJsF}+gFs-+=zL*=8ad(p0@YiTr%c}6-mg=FOwU2BkBkKiB+=0fp9ZE zcyaGRliXVyZ5UGHh_FYkD*C9pwSPp4Lo5~B;VufP#07nz@w)o@8u4d#KWat-=63}~q~*^$ZJFmMAXI*z+Z4r5*ZFIp;bIu6wRI_?mjRrXZ z4ZS|Xi~&*9^)h2$s-ZR@fIOQHNzn>3d|1~Cx`|7hSs3v>RN9WK^3$}e)|J8jYp5$@ zT-|?6DTk>??UOhlzWl=>phx*>?nvuiHG7VVZ%6*xH+X@*ZSvNfd@(S?rpJtHP-M;sX zF9J``tJXR4V;;=dJrRx_OaJkZHFPBgw|^i2rosG>{1rC6B(=8p!XW2O?&mGy)ap`n zH{@yWHK;y6}}~R~g#zk`WmHM%U{qlT9EYl~?|8F=|FR?U;kyiC*=Cslm;DI+av+)4}`WOe~27 zA8}t+&}AH|e!ah3LM}jDxo(Cx3YyorDs4ib&|zgqy#C;sY}E}GnFIt^bmEU}$2Y4r zuNT>VS}Nzps;;UaV9=;(--w8@get*`SNbGUjUXl>gK^E)Yt*cSr2f}-NoCl?x|k)6 z@61q7y(_i z#<1)hKWxI7c&asd)i|iPrrix^R6our@9R!Cr65R4&r6K^-L;a;$d$zFg4eXxv?LP> zL|(tlYVYT1o~XnNdNW%rnRM5ViVl8s3x|Dd>w!Vmpt7Ru?rW?|8`*=d9fO|Vr(`KT*s z>%BxMQX20F4ZEt?X^!1n@nuaJlwOV`WVJPY9zlFPBJrw^4@|w^4zbuw3g27v-JI$U z87k%K`aCYRM)D#V|9v!mo8t35AKgU!i1F=`A6hK7>Cbl`?_3tRbEj9q2PVoZQ7N0a zQ@@a4)h2agF^*t>ajuBK5Ibn z))wm0xFi9i<0mB1hYmOVS#^lDk4S+0?`u*>+ReQOGLYu@;6*oKCp+hN?(+vpmj$h8ZHHjIP;r>5M?Jk%ssf! znj5G&Tib^GS!pe7{TQVL#eYx3r~l$slgc5e0LRE5+@SH84)kuy-}(c&{1Q$LQ49zB zHGO6m(C`P&Cfrx7<^k*DRCvS|j~*FQmsocR6E4Je1r-WjfFmKwde5OB$c;^vUv*Pe z@ZuB$#k|eO2gxpQ*WAk&7Z#0>$T4>(7?Jh}n_gV~iB3tRWt+}WncKUpd-d;E3e;IO z`6+TX4!$42_4h8lCe!@QVP3&SX)g!C=?kzA`@Lsc+&NZVv9A9?p5o057j9zbkM-;F zS3rVRP2a`*4Klbr?1!%Jk+^9U%kM(n4#{CcixSEz`Ns-Mc)qg zt@TKTdV)^B*3x3cMR9O#jJ`?c0p1_kKI}K16!{GyF%ju!*U#spFuagUqjKRxs@jJ;O-i0MZZ!T>%ryAe;k`C&>wd$fwf@r;vM-;;`@ng?}v-r_F z?Sc$T6dxVPRxZ{k8QROJay+(_l<3;UhkSo)N7z1zpo_X##(Q;?;dxm$B0l=!i_Cs$ z>ac7^m&>I;>L+u;4}SO051$UcB+fD{?r~oz*(;}UD)DObD;QJ@p2%!o0T=ow#CL-J zd~n)r#MQraavcXle$B(BT6?AuF{qdsAcOY?59`V}`S}{4!q^yTf^{y<`$A6%n9b-0W9_a))${_3YJVf3!q=c-nK*E`G0 zO#x_4AzH4cw}f3)LpU1fzT;s?%lUBi3`>EX5QW`<2N;^hJvH+Gz|c~O|42O*bs>{b zkqZu-TWvo#vlUxBHu92_xXvQ(XWXg;b`hT)RYw*iDpsc{lhL`2X}Vai_$L3}bet_f8*_K0NmI^K*2tB}suSV&RKn^@E)W zo;|dj5Td2k`MByC%plu|lbHe8zmcKW;7!740yRF4IKkG{RSw&wz>t!_y2gniOJyY5mL z>_02iS2IVH^;R0M;YOub%}amA;CVwu)5`eG7_A|9M3opPml9lwnm`3ZoYwq~v)iF_!1vF!yaa9k=%Rt+WCyko-Zy=~%_n|K% z`)V;sO1JpAd#n8SyRt#G=bPiVqS10>V%aGp?#}kH+wh+i6vM)>BBK&@S8id#fA3+Y z97a}lFQ?y#;J)b=VF=u*Ypp(({#F~l_;t5_G@EDtIz3O1L4#~JxRVrkl#q8N%#zx? zgAyPyjKBjnCI4|)Dx8E)9LlHUpNgstzg+0U&LH9rvx)=WG7l)pD^eX9=Sx*nLg;r- z_jbd*a{qnr^eU@6yu9{xm$q-4_xU?S@ZYW+QTBlL+<(Q&Ks{sEL17)9Tl@Snhc5tX z#su1}_w{JcNc5D?yf0qO(~|_oQ4XL-#t}wBv{^py|GjPS<^7N3(f}Hpqn!e<(?+}#gHN7oo+yvwLXV|qpa<9F*0ifNm0vqObbv|v6EKzWqcis8w*yvjYFAJjldQw)sMlD!6kJQ_C zut~lpEPPbhTpC0zH*jm>ZFi6DhY1pWis@_lrk&muW`v~@-cM~QHc9f~dMBp&G$TJk zO55z$e<7QwX2{fqj|=!s#x=IvIn9bj^fY7B|JQhE91KG&iMfd;XdAZQ zrt7Po#~LGA{kntF=9A3Qe8^Pwl zTa9e;_E7Fp{U0N{i@51%P6u~`;fRw`M4F+cggd`va%rXWtmxT~!xlzx&_w=@!^%G} zYWCP9?(B-3w0kk6>xNvRorS-)=&IbSfCuOl{xXB3-22cP^=Q#k!Lmx4DtgjoC?>Jc zr9Z>hnZZiJ#e`U=2CjFjINA>EYI9uYdSkKbvgR?4_=SG*P3@W`|;DpKH;J z4`&$ScHNuLH7S)CA?2-rW<1J$8y#X@Y+1xz@F@%x`L9syhC&#q;!WHA{b#ECF%D>- zIOn9NGNmPwn(QGzl={NSNMVEoG5fvMT~f{*2{*WLmzRN74Eo5*LEd6Z$!RS*ve8~6 z$7Q>3|K?DhqYKw07QyFe65<3%;UbsM>ApMUu~ zfU2f4qw41-&!+QNCZlWYxxVQ;KURshK&b~?E$?WHJpNrF&hvv}6XaAYXs0${Qz2S5 z6Pf7j^|C2{J*gUB|B3lf$OhiXZ^H(hMcn-Up)=%^8?=1o+hMr?B0KYVL_Yn+@Hmra zOKwF&+3I&j&CY7vkGC>s#>=1#oLgc#8PV^ zg6Rmhes*}{cZ2iV0^)^Fz6iG3Y##)^3=`&HN*o|WskoP_vR4(G8Nq5RzlL;`TU!J{ z_7iUfo%18_#76y|uCwXpsJXN3gRi(=X{Bqy;pM~MA1QG>9^6PE%)*OmhR5{NW61dK zz5M?1hpZ19m-YIPmKoUXeoI3_&Q=F_`qA?y`9HwFzhLC>O9D!rc2>EUC%5D*YkZf= zCI`YSyFiRnqf4~Ne%MBV{;4^1Et+h-s`r-PIa-zFty%t5@vW!% z!OmU^n)YW5yc`}~?%3zt@fsK!Fc{xHoH?2>&d6UlGSk{Zj`8buP8BDB&c&yf4Wo{8 z-0lOU=$GopIoqADes;nj0{)|d)XF7> z_rFTi9;-Ranw2`oeBT>n-OD z7E0nt77;hX&1CzhoU<2chH25dW9$XZo{Kc_v)=p3`$S%=(UIS#l%U(1%I`7Ex^@?T zvie5r>5u!Imdjm#frU~#pQ$k6hvzDt%`*HYT}r?2h*UMdd@^$n>ZwxX+6*Y!++Vhp z>P)7lA1B!#te-f0^|ij6@1fbexaMWoX**fKhVCIpQkSmp)42~xndWfh-&K#z1Np(O z$JT0V!L1FPg8#xUlS#yl`Q0X)AkWd!y&CvArBallZcD94`p3tqOix4>(xQ3+6kms6 zv?oekUGuA>>e*_zERtqDIh>8`0RMpX=RFJuxzZ7?n^l&tcc_@=4vzhIT^^ThOc&pZ z#&DwBfAx$qvM04VN0%qwY2bw9bo~nQ%Q=%e(})oYRWpd?qUQe}T-Urxa8=5pdDDj{gc4#$~Qv%zZ=|E_^z%TL|di1%(;x>778UH7aW=d8W_h)!h!kouv0 zbH2;0>fcM7b6j`o{X3NgpZ|0O#2+o|T(+D_{1;=cq#g+SJ5T)!01KEq!B-n6l|Nd!eQ7j9>joH6}Q{Z53q@zU=jdKyIu5b@(U^y=s z$~#x5okiex!1@UNO7Sr}C2pR`i!OZ?g)>i1;|IiZWd4SiC>f#^=>$GKd=!p|YqZ~Q z0B%i&%@*JK3TUU;HtfMfb&2)Qvn`s_VAqa%{BX;uKT8WRzTMN*g~^Pr>PI-CwF@hnwrixQ_v3BcnqA4@2`T~4o~`QwhGJb|pE(A8~X6bz&m9e&Tj@ak7p8g`3T%Vc}zw41SZD#Y5djCl@*O!2sxui7sY zr(zEi%DPrK|Zry47940MsdSPd6GD8vD?)QyM4S0cH2)_)SyXNxSnP0!9 z-f~;>GfR_y!IM0{k=2pn5%bZ;=SbV_f0hJ!r}!i}hVk3d;{h?MX9SzMdGWv# zo)Hg;I*7NAtP<-g1WY6^FROfs{&1L=(-e3D0gJ#OLs@GW5^R$~IZW_%5%)`f+8FR+ zJVInJ;)-mdsM1Q-II7i=51xgGHpch%EPC#2DD0mSyXEq~=p^pFYhJ zq<(RX9zq)6l+J%ev?sd z+YN9xnwHJoYiB;5Za$0}O;g`0^k^GQKiecZ7f@IWIlPv{%rgsxefP)axB8wM#9`GhDfV3i5^Wz*LukRJ>i{2Om(wJLCUJ=uyqJa%GcWwpZ|&4Jy13xy7Zb4HJh31J(uDiN-yTU3Y_O;b(+Rgriw_ zr4rwqrl+=cjTlYiCT}iNx@1nJ{d=$KLI~xGm>_mS}*}`FIu(RG-cz@Pfb2MQvixAOJ z0Hgvw2EC8+9eXxm8W3^r0x~=~CEFlPAiJEt%VBa#dA#}k2`1Gfe{M^`QTT+ihZ|bn z1HMB~|AFpJ?Q`-w!ac%-jH%&ifo>Jh)F$PX#iPl!$XtbgO!Ua&>XNfp_!+6 zFX_1cO(3gvkb4qUjpruBexBlfBGZw1!WtrD+~K#rQ&-+SQ1hRHy#s)K1N{sr!PZIw z`ST2asePp8y@2mg5dBr$hkTckAKqBQwUM&V z{psaFFrWKGpn5E3g-*1kWGVP%v z?;F(ZebgMv3zHMl(0Hz@y0=@CNkWU9Q6=Tg8Pk6HRAIY*BH93E+AbUEc;uTayIXNG zJ8<8=2RkDxr_JKf_?5JqI*?HmZp!LI5q5n?;v$KClt0U(2)6kp4nKnzH9fdfOJX@@ zjBvG$2AE|Wue3WAynB#sa^wZIWEm|^DJ{<_;<7YvC2hi@U|{F}ZYr)e za!P0tK=)hkNhif=$gx7-8y5Lp%Q%sR6TjTH2OAvMr#XA~k=pi=wy5M!gIABA9cQ|Q z$)O}dYV*G7NlH#42#sQTkc-KL_(UJ0{jK=&HYbl(qpvGgByM`~b^TyI`bykEH}Vii zX0|(Vt9qPwP(VL$N%gsl086q`P;lsQDD#Nny*{Ip;q-+J`!jy?v9J@}pspmG#U;Es z{yLnu_BRnn^Cc7GGR_b90?O+v2TM}aP%({8cewi(iRXXWtuT!iupc#e*gl%&%(1ad zd)YmyHWL{eCd!|YhH7YD(7=%+>CoZdZKgPZ1Re;3vkD7M8zTaia54mWIvoSzlq29n z=~a9S9`R{3E{(ylD6zwCuv^T5?Le@^?ECQ%U1jTbic?GYAlKpQw};GRDCu0I^ZKAaJZN2=vsa1^33J*-cg5)m7d?>-{ok~{5ft5De7!&Y zDOu@D#ogGx{c7=9(Syt(w$<(B;HsmJ_dN;MCMI@pR{Z(5wtWNAub>*H#cK69L-uxP z6{y_GO@P7@yNyU4PP_F{M*x0-sb)|L;|&+M%Ok2F)X^`eo!Ou+Ig~y3w>36q(G8c? zjpfil8%xJ^QJd=e z5ca5QPZ+mG{#{y4ZEgFp9$aM`P2y{GQM3Ahv6CuR1)f5L3og(DELnNK@%ERAMzdD&2fx1K)>+ihN2U8#(R@sQK7T{b!an-|@WDM`1-y#q*4Fg{ z>bx=buzHAY%rKel!@6lc7F;JDzU`t4BiJDCPS%mVztWY%9Zw^=6W@ntgQluZ_H>)a zq`Dguc1VviIqr8IQKg3a3D2B5MCX&+M>1D5j3v$SV@oW;zp9Cx?Vt66KW?z;a$k0O z-5R=T9p7HDGWe7;&9E3JMmkjtO1+5t?(vamF`CvYG3f15Bf?10!?#X|0+-DKoG~M+ zZ4{mBe8$-WqJ8To)nYGhR~NmFQ6EG94(*IgR!t#9UktHpxzUdL{Bh@8yjdhfR$5Zs z(l~?no{f4y8|4s(%TL@DRb8gh;)e38Hs-;`JPhXn&k_)KSmg58Sqd%N;)==X}}ZU{mv(EqW`P z#dOi^@7DI%`Lw`OQ(~F>%J+u?+-&z^GRoSb6+o_47$>(HDr< z&50fc&y-d{_&~jlYGGWd`8FrOxq^qWn23Xy3^i>uCWI{O3Pz-9?Bk9 zzSPz-x1&(QGmqxrv7{GV`cPEIhI;Ydw?0Pn@Wk6wO_qSS^AxTyH$597I#zu*wKOZ| z4iw(ApspQ`etGx(SG!)sIXI<1AdWZa^)7VWe7%8N=H=mU`Pl2=g(l}q5t`%8hJ+D} zAf}cR)CsA2b(z~+ZrB&1k4N}RZJ{4-@@RKv=IG~<6xY9@AJWA>D{k@S@8v;uh zx-mc|ZTC&h>m3w^TvD6CGDF_|M8?8EBH|1@A@1q*@~?W2xq;{^5>t%l$XR^&>J?yg z4g!^T{st)MN@zV$X}=fNav6@Lt7~QWzlnzYJNy=L?f*AnRl{&4c^2fA7tEL%c0FW1 zzm_hj?Y!vvC+g{}0$FW&qr==qT<_i#u~|W9aS|Z&0-A#`>rF9qGlIlml}LoVXFT^wS0pL?xpiulhx z=yWg%a*S1#5K7KjCz%NlYL&??dMUD+$yo{lA+4W6PQMwwAxMTsL@g{ zO+rH`;3E{bOZFNPr}#0QR&|;1(-3WYj;z{6PoVNdsLY%vj6Cninl3bOWqF`G zj+Dk8kLeKuJ3x5AH1fHg7}pZhvF!aaY8&m^Lem1-Nr62QI{CzG4sYMsxh{HHC>`Cj ze5@^qBz^PoB5zJGB0Ro@jKOpXa}jB!=pk;M?_PV3P=$t@2|8<;(NQY;x_cv3zY zxXJ9y`!fLzC@Z@i>TlUY4}|M|?CWaknvM1zSJAD-DV%>Mnzww=Aogo&=T<^GSA2nX zqa;R`r)%m4oC(gmr1pg1OV5Dh=w#cQB2`OGhPLk3JVm9W}4sJ#QWk z14OvT+#MA)gq}BWYDLyKum5K4Ipu)Mop&F1P2z)Z8Tsr6jmW=ZMR$M-l#cu_@ynOE zwZpFKn*_RZn;MFqlsE>Ln#c&TE?#zP>sa?B|L39H1J((I%kL4RKAscJB2)GK*%7tK00O0BH8@VM%B5}@mLn}qJZsgYF5hYG1L-WtQ&&kzSGzjX)=sjYyX+iIMmIwiev>PaF8b6@k5>e=6uBIU2yFHYglx6Lajiwtz^zHw-(t4cylW6vzYg5Cy&cffD-2(}ZSMT8c%wM$16^12j@ly! z3=H^9OiIk3xDKZg3g3O zrmf7&-Qzv6Tbhi-k8HD zG~vG+l-x$I>p;;*dv&&HI56G~DRIb6yl~GDIpQrn1pc@lx*pZlgz<+pc8*K(s`-`G ziHNujZ;k#cG5g2%3gD^jLd-*Fr8D25v=I~0YP9B!fKXB{=9yqQ^YCEMUC&}?*6v@} z*x~->>_tldmmP7-ynweCN=m;M2SV&!F93jP;xc|D5PPYlo)^yd&Tr0GHg6jcdg4{rjuKyY``L!)->%bN|zR>WME@ zZTRdD6nC)MGOhLguo?@$`q}j5|BT>sUeq{>3hhtg-^`saev{zYv$db2fMIQC^w>`1 zvHzSi4<3Q9dLMEQ5x(x|26lhAY%on!PO7^u6Zj=kFkgtp`ISnE2Qf7dAHjhynuwXaNC-1z!q zmQ2JHc$CDU@9!hwi_U~qpuAy0{hmtgxY^>Kw^FAh&huSE4<`J|TP#ez z#4wq`^pqn?$+Hv)BLf_9$)Q%QD#$8Ch?-EMl}SDEm^u(CD~Q71jEGow}==HpvC06-=>X!llEwF z$Q^e?b!;c5H_g=Icr~q=hhZru+UU4Q3FypGeR7R;kV$7=u#cZyx$CNIj3&o+Xx>Y; z4=|(>A+6Va`fKNo1NL-x{e*WQS<>DpujtX~nP}+SrFh2p@w;335X$G(0=^cn zVL=O-H;na1yDYlmt3v5+P>$1#Gh-ZyxL+bwB3d^R&o%$Mdt8!{t<#scCt@Q@fp7(rPlrettBLTkrb#IfQE~z3pI~trom3UYBWVH4%Msm_CXFJl) zZThuog~(2JpF^-XskU#z2O8RQFJ#A`%BrEPz1{znZ-v zp&J+F{f=`XzWe>n<12>qvOw$A7H9$mSAT1@Abg-&Bo0S@993s{UWTouVMdd|<#%Q}c)V3l1%zrYc}?YGo#>X?5FF zWRk;3c3?W|YkWTSrXPt}zPpEL+&tRBx^rS<(YDp}6n6|84=l%?o*1!eh2E!~otToh zRgJl;pPWyw6Qxe+rhW|1ojgLS)6KVcMD7lAtzZ!lojOEerv5rFUvgl@34hJ3tbyt4Zc3o(KZ|axL z86&faq_y>2eZi}yl!oS_=qg8p-!=72h zAsmqh9szRYPFoBubNH<$&O=8P`EXaA^8Av#a*N)0MrjAJjA#Wof3C4?@Xk*;;M&G0 z-zZ`EUH=WCi5GX^d>xn>O`}V!AGo~uC(C!>ICv>gje@rC-}UN0AY5j<_-4mt>0;ka ziT!Xy_9=DoZB*8lD5Q#wv1ub*_QtPhm(g+&k@LT8QB!x37%D$IZISdc^ci~Pk=w0i z9R_1+gHr9ZJsqU5VLfutTn1-)bka)s=%K7#eEiDj1j+L&-gpHHTr1qg~0nb z3+49=Lbv)m*iVd^g^dbn<)}F0;x^y4l`W+aSqK}m`wPbyViFpR$llMHW#{CiGG3k; zf-LTMI_iuX4_QPM#>OFH<0x%ccFBa>9uQCbDBkZ^olFc+Rdj?O?Mlvk8-B1cj$<8$ zRNXzb8?DaaoM&ofet0UHel{)tE}T5Xc1LgRQ%{p%I?t(jH>UbqH<`2Zb8Tsi_m25~ z)|mQ6>`okqKJ80Cv~}U3=LvHTX1kKv@{KiiQJvg-feDY018^S`z>GewOCC2{Qg*w`rN4w0H zeRwB9<}Lza%`wBJues}RBqnmKes}wQT92tNF3kek2~O<;`Z@T+m{{ao{Sx7N({(zQ zRorFj`97%f8X*~>2-riR(|uHBrONC~oUqr@0j{7-Wtd&K(M%w|e^b!psqx8S-A8s( zfTjd0D)zqU+qnPzlm z=CRXFs|iPs>it(=9sPHvc2>ZLJMt;&giVlJ0WDo3+M5-VE>4F_XHLtRH=NXN!~6o$ zz_#i!ckSX&ra1`~%F5i1)+0AuT{{*$qX|OJ!pv5+I1Hr$l}1I0uFaJU=;ra<%T*^X zr?KrVr#a|Qk-WPrpEAS%fY1H6)Ju+)Sste;c%shE+Mwx?%^Jk(!`8o+2M)No?Vb?; zJLbA zIYu=8&;~5*H5pbKP#Pe>>o>E~(187S9R66P7bDLCAr^-UkK*^?|S+3+3Jn#Ja#RU{E3uQFnuBC86(uIYgmP zFc6&>)ZuCs=>H%5Z)47%l;wr(66(?bp6;t>m?+`Jd0oWc7xP^Eoo9$o&x4@g^8)XA zP|1EB^Zv?U3Wqh)uUM05&-nF=_$V5u9$!VHHf? zhLo)I6=BD-Ln{`H1q7aAfpYbe^86VYm^cNsW3=mXJdU( z+M!L#3rtbhEuN=IXvmv2GmhKfEsNF&yAl7Ean8PnTYKZhOnt*@s_OO~dwo!8r~`Ht z2w=p>s)P01mtR{&%jM-da|T^G8fKm8s~y5B+Hhv4T2df3|BqP*)Q}o7E-pqJF!_1H z2sy7n{mBt;pN|;)FXRLoPDAHLpi&H5-kW1=@Fiw4|G#+Y$_SW2#ydyC^zE(##LP(3#LC*( zh(X)b_zoi{832HDY9Oa*_2)SN0|~}1eqBl2bd2M6E$MgH>8FnR1d^{_M`Tjo$j%r` znn=S7gW?MnNgF-A^GMw1xgP2BgSySFhyE$=RoZceG2=Li*^Zr?VrI;awsM3>K=T%n zCc!RZ-^8loEv!DOt5Ffw+D7ORLLnf>Ap@88OVMv(AQA|{(95sK?>Xm`DwhPEVOv^7 z#@Sz{vE{kV)%)&yLQgKvKy z(F^R-ws0wuZg2-(G$iGp15~$%~KjsPqCc^sk&uJa2Wx9_i162!^a|7u7vH*s|cY7RXy$-E}GDXwK;t}4_V~6mFyo2Hjwm5V`f?c>sJht55!1-*^h2z}V~ zZ9DnK%-{_HRcE4y-kV(b+2Vq$WwfGm0>jsNxqb#4?L=h?Ha$6W08wx_(DAJy{gcy`aI8V3uxreu?O;;vW`z4m9aXs6ldk$ zNL7%qR_p{uzuGgbzMo`DaXM4PyXFeY>9J4ZA;;pzC;3iEL8*41Q}Uk7ng-(OXb@#e z$ehS0jaPTD@a{Aj63cm9d&!h?JCF@rpfP=$adNFzkq?6bnz3uPkNlMD}j&GVJqNek`*Jq69H+f{VnapVdSM=@hnnFwN=4L%yA}ljV z0A5C&c#TW&#=g?CAx>as4rxuH%zMV>YXUwTWw#M|de1-PhIw-2`$3;Y z^1Si;n!9I=W60#dTTU$hp-{eP=a%1lxeBuZrwVI|w{(OGU7SoHzaMwkRueAZy)neM zEx*hqu~vPqel$kHM2mIs%6ePyalqh-hC3Z|N>PBf+-J{8)}@Y>Y3a8bv^W4kT9JLH znkwt`{8fTrt13gjwDX{ML|%TX*0?`eTaw=#YcuW%WMB^cc%I3Z_8NOASE1^yoPZ`S zu-=AGdjBh}Lcal%6@}fz$gL8L&LZM~-g~jJGb zn>p*(t@1RCKDIIbl1Sz9ANZ=q;Wg7n)<|(9*nx@|e_ey9M6ZIuhU#ATtz^DiRX^xO z`j4SSeUbv_!L=kk6zT3UmpCPDJP1{~xMWrvKuIIM`-e43eOVTEK`I-{lF?Eheofa0 zx2)OuTX1Cq%1K5uFE9DyJl$ewFYlkM4Z3dJ2aXAVO#%I_)V{Beag(fquNf~nFeRB) zsnQXQSE~5pY`ftsVsCy5Ws`FA5l^ihFc$7R`8LpC`?J$;A%ptMeMRt?LTX+ma45z6 zJ+7KBzR?R6&yCD7GUL<Pl6H*N0jQyU#OBiRhd_hN-K8ko+1Idsf1N*s{iY zr!OyhR_qJU(^kHfNemJxiRK0Nvydt-4dya}pD+rN+$F5Z%3O8&8A^SyF-A1kkW5`* zY>@D<+JE$Mg)jktognf{?gn9<00Cq5qJd?N+>&J8+UJ!!R-&S5ad&I%O}y*~1Xg_! zFJ~hCpY`w(WlQDi)oCuh3@4OF6!2Qx;W+IXOt%r|rrSyn^yU}) z2(7N$$NwT}tiC1*s3xwf@DtxNmwDt%>2c^^7s^z{apCpqvg2pqTrpwE_ox=HRD*BN z0)JU3d3Z#n9&W1zbw?@1bRI!ZI2K1v+3OVWmde){Xm;MbnO!=M>cg3KoEsAJXRyP_ zNP>J#Wj~{ZWl%9bJ-$cV2IY#?7HD6(_O9ZP0=Z2b$alia|_<@KLh6QJf==T(`}6H_(VSY540z@tFScLsM_@~qW+KI9ZA ztCX@T&+FX5rKJr>BKmwA^C8AvEL`qy*FQP~z39F8?}mNkwNEsgvDl4|X&$~Yyjz$6H!KJM!0~UscwF}q_(24)sVAAk z(0ZN@`oH_lSpIM$80$J)2zW}a#C%9CSTC__ahM*k=El;B)vVa6nCABBaVW9-KnH~T z8`dA_+BCZl9=Gpz-)9-l*-hd)Rs!r@ql;`DxCf|cJPVa*?~Bw4c+ zii|%tfFA+F70yWX03K^#2unS+xJ<(;{WnUXO;R+ZnI;c z%s(5qFs1LtGf_~sGRw4_^E7T$6aRyz%68E`v}j2{5MKTa`!8JYL|II#2DETf<$~%+ zH0i6Q9tj+&;~ZQ`JoTRQA}AbOvj+9QG2==yjCDmK%x3B)d0T-TrpEOvd=78BA3Ku; zDk4d@4Nd=p6)Ce!pQE(fjhD=Y*U?fW5&!fcg(sPqgVBY?Ypd?on){U=U@7Ee4;r5R z(Ti~Q!TRG`Khbkh!Pd;-pua5M3k=ezP0~2DsD~#lO@1K|qW!Z&IWUOwqUxTtR^>HH z&%(o(El1C>{wPFO=u#-_+00QKB9N>={gG^N{V4t9ecm6;(ckT9=2-vF({i}zau;f*ugT)7b z9^C6&Rr5YCqPjA#=i%l~jUM4QPnU09Ehv0*axm-hR#RQ;3W=LeuWzFCHxG~-3sU=l zj`u;PdKN{^Q4|<{6+l72n&GJ-ocm+B$``wBsC4dsO><`sF7Voc?* zsH4@-SEv-RNDkE_EM#UwX|I44;`A=Evyxy#0D35sHl%cRkqv)43sJ>FYgPmA{T_k- zPUbZB^ev>K>zT6zFn+6C#^HbS+X^#-6`m=^G;qtKsvgLH|G(jfCR|!om51;dz}~&w z?R7*%#Mai505PNo!`BV-BghVz*_^9XY-eZnFa>m%kWddJ3;nR6P_rpS7NYOe`4Xc5 z@+|Ox#2wU+4U@jV&VmWa1j3V^kLq26NrUWODwQB^z>^rZJih5C-m!bBHjSV3e3mQ|8TxDKMiXK^PIa@;;VTcS44i-+}|a5`}>5FmFA=KhZ$w7FJVdRxL<8! zCUzlC6jvA`v_}$g!tdN4-+gc{{`q811(*Su4R@16BOoi)@eNb9eUbLjLV3|3YNAUI zFoKr3knW*F_f})Xfpb}if!ee`;)^FbiaknZs`MW%9Wp2HD$jUwYF;9!`8ooc0s76!B zS|Xq8?#G8E5|Q$6I5-F_BP)Xs*v?%Ts5NT1MO4@lwN%t(i&!KKOc{ zlpz7di^VunZzZM5P-qnu)2DvQNz366wfvX=j*W8AApC46*?3I9T5GJVw4j!DqvEXL zdRKP#~8CRknIBgxr0nTm&@uDN!z{wYnNhF?r4G{$~*RPpfLL27d%(du#y zKB6XKeLi1Z2iMu7=Tx!SxL7dJ{{A0m!-Xkco~)J>&E%DL;txd5G||~^=5v~9AT^~c zJB|dmIy`$O6r{7ZKOV8TBfev}@?mL8uQ!3|6n``Fj|r;ROj~YKop=+AFSkV9h`*yQ zjCl<{4MhcC>W|EXok(zRZ+V>h6-B_D{Od_jjMM`+9=FOkY*S(Cp-c?}QW5%J-(0bP ztr1lf@OlyxXX-RQnEjW0wAK( z)2(Oy;QdivYbaR1+e?;vE>=L|mu~a*Y3#bJaoPSoh3vMHGlgvGFGEjHGl=46y`oAglLi`XKEk^?bskGF zJaan4r}SluW)lU@{^b&!fh z`Ng`Ml?JaY)=WdLxjaHEsiJeI?pD|Gj-0bK9=K3ya#8j^^a$r4(C;Tc7R6jzt4oNH zfc*l`ei>EmP5&j^(CG4HY%kCOJUX&xYpbStSaMu!>KyVH^@jAvnzZF}@tpE4jO+Kh zl_MuA`Tl}dO|qMR8YVEaHt$qVavGJ}Rdw?6ubMg1wN4XCfF=kqpC2b> zSv2&EYLujCPz`Kjb?vX~GHqKzYMkn^o?f=)`PyvG{e4a0Xc@^?v&p0~^ z`PRj42l_6Iwv$5l?PGBl7h%hV&xfFbaU>~hXfqJV<+wac=ZH3+&=vx|+h+I}d_@VN zL}H!QaSc8n5|*xwYlgn}v{7cZVy zoDLkH!~D-T+bX}?9-eEDDa62m?;oSpU&6m}`9#-tLn`W)Q$6TDA5^1*I{Yu8eyu0A zb=?(f39(v^u6*4>k$i_6KAKZoe<}NvQ3tlw+~l}$i4V+m*iU6O4PN*ogoixd#j}^E z<_zC#>KExQp&qvGMrd>PW{k+4?A<$@vxwZmm>OYp8sFg~nE$iQ-BMpq^F*ko-1VFu z{IMbOZ8(VUhRYi=N6^s|RWZ zmJ8z-n16SP80a5u)Vg-o?V8F=*4^{>Sffg#{VT(e!rAo0Z>DxB`7+(7QIFp4O&s=d zLmU4Jk&x6UG|pyuV&Hlj(iZMg<*@0gnnV5q59WUQEA9MOS-`sEksD@&@d#(SGx#@f zj>(!r(~W?B8{Pl~qhDAbq?HQ!_RkW2%im1ZG1U&t%A)*~ zFk5#yl$b+AAjl(QmVbLbzEfhdxfMQSilt}8DbI#Riw-TIBQX9_4XS+_U;0($%Qecru= zL8fImFb(Cxk}5$#hmbtdJyYmyvdD9TtyY3CdyuFQ5*5E5gv|c3w|H~QoxfKg$!9PDRX3q_iy6%_8NU& z389W4n=^;zvaF{aNVG*$_-?;vp0pt3#rb&!&_rQ(H)@u0GcXGXp1w5ZXTWD^6wCq` zc~{xL{8R^Ce1yC#b~n#Rk%Hpryg`tTSxAI4fYKp+U|4bId;xiwz7AFU*h-QQbZ_+VYa*>nwJW zcs*qF1$j7x`F;#tJMwP|Dtwb~)48|YH{v|%ohMxjx=|&WVD>@pF^&)DW(MT7NuR;? z9M(~PQ?BGuf4_*J^EsRwc7Z&c`Uf+a#SXmeGZ7gDV#j5?%b8o~6uc$a{V$?)Q2WSaJu=Ebo$%7f>=%BkycG%>g>FOuwG$A@RAmP>A22Ij-U4 zNoRDi^_vr9frZnq8b>}2EAXS8a88~ZL-q&c-!bbr2H-*(x`M~inu zqDVcnAoa|=+yl(7f0r2mde$z1AjiKBEmaE*>e!rN31Qw3t8Fb2Gd5M?TZ@}V;C~rd zg~+}5qh`pAZZqx|j*rXBJb9sl;sa;J6;+8*}(|fUIpz9DEcxFT#u_U%=}NFtmJvG{%$jh8_&xB-+7bs+oH%mdBm%VtEhD z@uTF@Rw4Y(sMU{^t*wOIx!HD`jlibmj|%WJC>XGVwC2e6LRewYm}fr{1U)N~r+M#l z@xiqC0oLAAnciIL|;zml7LAz+N}7D91fdnjZ3k;)36H zlIy09UFlD;uF}`t_<<>AoM@&qgHnAXfUjKj_EXP9JjhiG=*OHs<@Wbs$yQ8q1F$BAD%3x5| z$hhpk8Qr2NoL%VG7ayg9EJ>*F?d2@-J zjSy1gl=mRcQL|elYIBUaCO;!(p~s!PGWBa+U-wcJC=Y}z%Ao`)Bdo>a6e;#Ne?h_* zMu{U_FYS{8W2CFC(Sm?z;!B^;ubHsqI~q;FKRc~4B9G{CeKgi-$L0Qql}%Ggr@hIy zbWw{0q|r1;`6xwog|=brmB!jh9+C|4m2uB;Lv8LEQi|Kq!xGPLE>lu(&#res+tn|! zNaUDm(A=iHPg~wX)NmprEqis{t)kSzH%N_&Uh4&tbG=|t>`{bGRyf+uVG+DCY*pM4 zxSVR|gKMfT#g+g~r*@X#vwi3qTZ`ZK_YCoO>;K59^SQ`*$aG4b!_`vAe!tN^ZWF%m z%n~km{e46vS<369v1SEz(MfeVn2O3}D_yu&{8kioTfSON&bMzqCxVj+x*M!J=kdJN z;<+rR69)|eI%5VHX|$`~;=sYOONOj75v0q8pB-Ef`-=rQNqeb$x+8m9m))Y%Ds!hukoOXa0hiNUxpMbf)z0V8 z=BX3C7%xyP(U{@-Xlt!AsT8zw`;*9n!}Y+ypd!_;%a^AmajlorCmHHyJm(qXph*_j zsPl^u5Tvc=9^Kei+$Is z#*=v3I3BvH{8TBB*qAULuEt_%CtrYt%SQIG23kKQ`OsX=va!S&&z9Q(wfV^K)5_ag z7<3cIIWNq0*r1&d>qAF~vr`D`$9q4|bP`?o(l5t9)#<)uWh;Y_S2C;$S+rG=K>Dz~ zIjf%TLRcox%@=0$$SP?Lb?~5vr&&_+U|QyN8*p}Gz=( zuMiefmxbvJ^5Cu-{;6S_roAt9$;kJCh!e`o1nBiNdv-k+wJc%J~|>oqHH= zf0X{(vfzhjwZ&aXO7I96rdye_K84RyY_M>d;F4*VV?CuSZtAbdEa00snlEy&F9Q9b zubP98jHJK0w#N$FJ#;9l>E;eBTXD}_P8&dp-Cx)p zAM+X(ZcugS=H%4vZ()8{9mJhYu7nXHmZ2BThRfAUwe}LAORcv@?A=c18Z#eQGFye6 z)reY-%%TzcnFU2b2{!NBG(kP-7`!hz zHX{0~=Db*{dS;5>Gy=N<)>&;$=2i>X4^{^3T8P?^D%5@s8RoIjlF7l}n~JyYYEl~F zi8x7xz3df{zi&DNLRZ8pibiEy6gSPqP2Ej4RkbXrlW_(&T`1UOuX`8VRRH=x z8`w1jS~_-hHcl@xmP|Fgrj0pYSLFmDP3J1qZph#?g-EOjBJPB&%g4I@a?orpcy3!t z*Bi=iyrd#afP^BVNF)<>!?2SX~ZA zijoVvh&!xBZ(6Z(?1yoGh4r$}1vr+6ND`c$G$v9UdoW*~bPzh)f)Cc_)HjA}FDEX$ z7=1D%V4PO`IJ}GCW0&r|pn>NlpUP0I&dyuMN~ z5gkt}fMV_m96f|N%|ouq5g`DhmX$yt6V@u;FhS-)rgnf}ze$2$Bm~?Z!jd zgm`G$^1ioPPHQX^+h%fEwpGKDB=X>HcN3{cpBsxq$2sWSUkO&Tv#}9(oz15%gsw!h zF2%EwxH3#u_Eg=nG%o7V5*EEFMymR@no2{3c(tLnzsm-;hW>i*|RIg4c*D< zTKmbkq!k=9&F1=JHqSekHkG)O^D{iyEPT`yD>#euGvXs&j_C$o-)!BhTG{F4t=xrH{;0ZD+no6d@f{iFw;OW_aiZ?o z)`hOQ2_P&gkeDwbWT*0*Zat>*nH^cr>`-=5C5VUKVX%;G)jI`FX6}cI22$QXiEPq~ zd7))A8T1Q#u^uQff4>OsFM$qPq~Ogvr62ZMfP3*N8Q&^u^H1tSuq~lg0`c_$5GLAB z%y;L|2dXwQ(N7Fn_?X)!MpxUJXt#Bmy>#xvwo3nf_`~FY?BG<$x;%PHuZRk}&_(&? z%;u;&glHBd>>9@Y7a%vW5)^0h8&X&;!hw8T$9|)st?Z;#-nb z5a#g-=GHyCmo%vNy?#aZEMcI9?l0B-__HGLMqm{N~vIcDrSe#j0;b?hf3N;$dEs7{uh2U0q1x%PWG0!Jl@p= z|5^0kQUuRlFIVxbN-SWr-Eth?%$mIZe`AxCD@pZobqpLin^ zWYVE*!R1jNDA5tR>l*QNzSG12G@jr9BiIqJh+CyDtI@G3SUh?%&5dr|#mW~ri3+3Y zp?eS_PLKQt|GYuw#u!C{fpATLhw5K! zrNxP?R1CX89G8|=Q>2|~QRugr`iG->Pdb%S&Y4dAquayiRqjf02P4~dz3XEwoS$e< zI+s$7o|^d`klbrKjJkqsTS5QwMcc3%wt6L2Z>*U-_wCrBk+gs`F?J_XfOmr^$ zd6r~6wmve_-|4jX)^cHsrF%F!Oh#Vjn?Y~d%-2Md$>O3<~O{7b(J$X zWdQAe#loE9dP%hj7aZH$4AM(rT6}&v?YYKx8N=|%BEc1E+k7Ln@bZX9-V1+qbpm!-O5(#Oj1c(-4T+AVq!E-Crj zBU)R_a-UblimnXOZ%4=m;pZ#>uWcte3pd77je?64{bI;^v*m>}XEN2#Qg-SwZkBO= z&Cd=n>BVu*`MP;5TwGfgY0}$T&3EK(one1zJuuL=alF;)x7$6&}c|d+p zgk2BQS3mI+qn`gk+Zwgj)8(nIaB5dRhrPj|TZReC4;t)vcRVc-dC#6P#_Dj}_DYN% z9eDsdWBSP)kg34t$a9CtPshXB^Nt6F2CZ+VZ?Ci5U3mWUBKrJQ=aX~p)fUjQ<3+pz zjEP&0P9&t$ZYjB0R;tVX;&>p@)#QbxNKo{CuXq!J9U@%u~btp7JpBTcg44#O`B|{Df{FOqQYn#myKk3xCT`DUATw+|Uvm#e@ zgy`r@Gfq98jM3}W!FC>_)`@1B;#-WD$jV~X(ZTMB46faiS>VsIi4Rm@<4uPa0$}Vv{is0L9$s2b!HM8GI33P|m#G8QCzZ zqIAUF`XCImz>K_&bT3#$ZK~pqNU2W-Vdr6xX z2ut$*xnno<6fOUaaOb&jZ%YgNAq*1-O-Tm&P+Md4)Xg-Mg^PD%V>N`q!Tr8)$DCRm zn%)XT&?)YeOm1lO{yK{ z1-@Dm(vGRuVv*(lF2t4z{D0Q!z;*nL_@C*?Wg!I3-gGdOed%jD)kD#;fqmMaBKVA) z7n-OrYXO!JE8pF0^+ulzDY;F^eBSrJ159rV_mhgQ426*HlFg(1Q86+w8I{Ez8E+;i>J}P*KB`(> z9`fy>ITr?yk$sV#Ct};-_t|w*@Cm9F^Ys3)Yp}c{EKGZDY88GAuiy=~q z`J{WBculo;>V&?QZ-!gVmLeOpMK1TsTq1?DBsq(7l5xTskFElowE~^qrk|d@g2hn! z(EDQI!KZjX(KIlGA09{eFHW9KfMHYYhu=l&?svC;>CbO#W~pAFmN12uW6MZxGSBNd z%Z%+Savyd4LKet*s!!Koh;6Y?$w)_(?#sp(AB)!G&qr~HQeU(bPVX(6i1OA^JC{pU zXC7t`K`#z2`931YGN|JRIS+<_c<1*#unb1Yo`bh=cLdpm2gd$%C zCUYkv4f#m!w{2jmrRdo@cvwVR3ACB#6{Nc^hd~dIHJxB`D>>N)kSfA#|3xcA#Tf~`^Py&oBiS&<6K-{2t>Ro zx}Efuap-*zexNHSH&UlB@qYE~ z_axv(&TSzNuH{lM?`j=5#R)lW*3hOkJ(dF&{T;^fi}#@AU%fNlfF5phlgf3NPsROe z6LOv>@$_^d?+s_MVbG=ybMo~RlzYcAK}G;bFAPpMEE|j@pPe9Pbp1uby~n?224B64 z(w&*F^s|?xv*LSUUeW?dfnX_d6r&B~0uL!r^EXRWxB|T%@@IC+=-g-H_RVedco;XTJ12_(19v@K^`h-Z-wc^3;CBTCkF8e8d*9+YeC_#sz;}7r6qQ`e& zVU$l$`R!LKl=qp&PreHCqwK%b(w*#AOq2eNk6HO#S`#(sL3$ZQI$f-ssJ3TA^9OG!w*f!A_-PEG9OPCblZc=j>JiqAL@S5-WUfWZk<` z($?Dw=%;9SjhFOiT*S|7}ts@Uz`j$>PAfBNJp z1AI1sz@Wf!^9!ThmXkT;osoA!n8vn%{mbL6M7(mFPUW+P*&sf>TO7s!Dw}P;7U6Ik z1bI03^d83CCRv@{aY9T1A`RE7@+C%yxj9akE0Vz-a5v^^kAEHAL213C6%S#B$aZ=5^YmF+*qaEpSo6zlsbN^ zHIn{%bB$t5=mr*UIF0LY{H4{lRQps_>9VCrS9_i^ zd5qbly{8^x@|~KR2!b`g>OnAUNw_Okr+dHzyn_Y<_Y}0N z^RqXC2`7{APC|@p$dWkQ%IKAX%>|mPiFEOyrdwqrV=LLKAAT4L!&rN{8t(r-fPQVv z_eOx0izcq;`!O{R!Rd?G3uNZZygGJkMJ2qBKZ4@8Z7I@Lfovk<9bCUiaYe9%_s@r> zRMgdp`|RJ$#0qG~)yDJ1 z2vJlWwUN&&rvfjv8)fP1yqGTYWS5)}9omXxVec#ZS+YT4!)?@8MSeOFvci$AA@tJO z*tw5@=7j9{p*Pci(884mYy9bkU2?SjpSvp56fM%dJVf^y>HpyfIj5Ks_2dS+-e-V| zx&_cON9D~mPhN_mnw|e!UiMG?i=m;q^k6a!eF5+T+(1q^Fyy~SVOu127}o%H4SLhq zw*k}GiSD5P^YXuy5CBG3!QVsB*I?8@_8j_3trxti?N(eRVz;mA!&li0&ntAo7<84e z5M0$>{@K>5#+S(a(x~;VlfU^@w)If!d1_Qe;K+#FyB}P$zZA2NG3Tz*0VEb-h&ia3 zQ0MzQR&|Z|t8m7TxMPWGL(3}HR=@iWb(_qB8YglH78!*6v%KjYtBN}OUzXdX7!7CZ zt_EI3I7qTcYG_wJZ5lSJ7v_ltOZWE`T;ptz zm0%z;EkjC(eo#Gc0Z0aOGi`Ap|5OeT6Ow$DFQDP^KLAFTwP64N diff --git a/docs/diagrams/ArchitectureDiagram.puml b/docs/diagrams/ArchitectureDiagram.puml index 5165424b8f..b400a5389a 100644 --- a/docs/diagrams/ArchitectureDiagram.puml +++ b/docs/diagrams/ArchitectureDiagram.puml @@ -24,7 +24,7 @@ Package " "<>{ Class Storage #DarkGoldenRod Class Main #IndianRed Class Command #DarkSlateBlue - Class Models #DarkRed + Class Model #DarkRed Class Commons #Purple Class Dummy #White Class Parser #Navy @@ -36,10 +36,10 @@ Class "<$documents>" as File #Gray Main -down-> Taa UI -> Taa Taa -> Command -UI -down-> Command +Command -up-> UI Command -right-> Storage -Command -down-> Models -Models -right[hidden]- Dummy +Command -down-> Model +Model -right[hidden]- Dummy Dummy .down.> Commons Dummy .down.> Commons Dummy .down.> Commons diff --git a/docs/diagrams/ArchitectureSequenceDiagram.png b/docs/diagrams/ArchitectureSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..3f7bcf89e5b436579bdcebec96a4f376b4efed82 GIT binary patch literal 28022 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
Cs+NupGFd)MqU?ahWX(QsZ__?_ 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 literal 0 HcmV?d00001 diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml new file mode 100644 index 0000000000..26b22e026c --- /dev/null +++ b/docs/diagrams/ArchitectureSequenceDiagram.puml @@ -0,0 +1,45 @@ +@startuml + +Actor User as user +Participant ":UI" as ui +Participant ":Taa" as taa +Participant ":Command" as command +Participant ":ModuleList" as modulelist +Participant ":Storage" as storage + +note left of modulelist: Model + +user -> ui : "add_module c/CS2113T\nn/Software Engineering" +activate ui + +ui -> taa +activate taa + +taa -> command : execute() +activate command + +command -> modulelist : addModule(module) +activate modulelist + +modulelist --> command +deactivate modulelist + +command -> storage : save(moduleList) +activate storage + +storage --> command +deactivate storage + +command -> ui : printMessage(...) +ui --> command + +command --> taa +deactivate command + +taa --> ui +deactivate taa + +ui --> user +deactivate ui + +@enduml \ No newline at end of file From f806a43958d2f62bf785d264a98dcfead877561d Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Thu, 21 Oct 2021 05:24:25 +0800 Subject: [PATCH 145/543] update UGDG --- docs/DeveloperGuide.md | 8 +++-- docs/UserGuide.md | 66 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 8c8d2e913e..f480db4e4c 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -74,11 +74,15 @@ created `Module` object into the `modules` ArrayList within `ModuleList`. ## Product scope ### Target user profile -{Describe the target user profile} +* Teaching assistant who has a need to manage a significant number of students and their information +* prefers desktop app over other types +* can type fast +* prefers typing to mouse interactions +* is reasonably comfortable using CLI apps ### Value proposition -{Describe the value proposition: what problem does it solve?} +* Manage student information faster than a typical mouse/GUI driven app ## User Stories diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 141965b54d..0090a7f505 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -21,6 +21,13 @@ If you can type fast, TAA can help keep track of your modules and students faste ## Features +### Viewing help: `help` +Displays the available commands and how to use them + +Format: `help` + +
+ ### Listing all modules: `list_modules` Shows a list of all modules in the module list. @@ -41,6 +48,47 @@ Examples:
+### Adding a student to a specified module: `add_student` +Adds a student to a particular module + +Format: `add_student c/ i/ n/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `STUDENT_ID` refers to the ID of the student (e.g. A0217978J) +* `STUDENT_NAME` refers to the name of the student (e.g. Jon Lim) + +Examples: +* `add_student c/cs2113t i/a0212345x n/Jon Lim` +* `add_student c/cs2113t n/Jonny Lims i/a1234567i` + +
+ +### Edits a student information: `edit_student` +Edits student information from a particular module + +Format: `edit_student c/ s/ i/ n/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `STUDENT_INDEX` refers to the index of the student in the module list +* `STUDENT_ID` refers to the updated ID of the student (e.g. A0217978J) +* `STUDENT_NAME` refers to the updated name of the student (e.g. Jon Limbs) + +Examples: +* `edit_student c/cs2113t s/1 i/a03452345x n/Jon Lim` +* `edit_student c/cs2113t s/5 n/Jonny Lims i/a120067i` + +
+ +### Deletes a student information: `delete_student` +Deletes student information from a particular module + +Format: `delete_student c/ s/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `STUDENT_INDEX` refers to the index of the student in the module list + +Examples: +* `delete_student c/cs2113t s/1` + +
+ ### Listing all students in a module: `list_students` Shows a list of all students in a particular module. @@ -53,6 +101,24 @@ Examples:
+### Find students in a module given a keyword: `find_student` +Displays all students in the module matching the keyword along with their index + +Format: `find_student c/ k/ + +### Exit the program: `exit` +Exits the program + +Format: `exit` + ## FAQ **Q**: How do I transfer my data to another computer? From d7dc30367b23113715634f7c10275cc5b1b2e1e9 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 21 Oct 2021 12:07:32 +0800 Subject: [PATCH 146/543] Fix spacing --- docs/DeveloperGuide.md | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 8c8d2e913e..ff8b373f2a 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -45,6 +45,7 @@ The _Architecture Diagram_ shown above explains the high-level design of the App
![ArchitectureSequenceDiagram](diagrams/ArchitectureSequenceDiagram.png) +
_Figure 2. An example of interactions between components for `add_module c/CS2113T n/Software Engineering`._ ## Implementation From 0760f1d506ec80491a95a78304e116f00fc9f967 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Thu, 21 Oct 2021 21:08:28 +0800 Subject: [PATCH 147/543] Added edit and delete for marks. Edited set marks to not work if the marks have already been set, and to implement a maximum mark from assessments class. Added commands to the user guide and edited command summary to become a table. --- docs/UserGuide.md | 109 +++++++++++++++++- src/main/java/taa/Parser.java | 27 ++--- src/main/java/taa/assessment/Assessment.java | 4 + .../java/taa/command/AverageMarksCommand.java | 4 +- src/main/java/taa/command/Command.java | 4 + .../java/taa/command/DeleteMarkCommand.java | 80 +++++++++++++ .../java/taa/command/EditMarkCommand.java | 93 +++++++++++++++ src/main/java/taa/command/HelpCommand.java | 8 +- .../java/taa/command/ListMarksCommand.java | 5 +- .../java/taa/command/SetMarksCommand.java | 39 +++---- src/main/java/taa/student/Student.java | 13 ++- 11 files changed, 329 insertions(+), 57 deletions(-) create mode 100644 src/main/java/taa/command/DeleteMarkCommand.java create mode 100644 src/main/java/taa/command/EditMarkCommand.java diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 0090a7f505..b15b8bf1e3 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -6,7 +6,16 @@ If you can type fast, TAA can help keep track of your modules and students faste * [Features](#features) * [Listing all modules: `list_modules`](#listing-all-modules-list_modules) * [Adding a module: `add_module`](#adding-a-module-add_module) + * [Adding a student to a specified module: `add_student`](#adding-a-student-to-a-specified-module-add_student) + * [Editing student information: `edit_student`](#editing-student-information-edit_student) + * [Deleting student information: `delete_student`](#deleting-student-information-delete_student) * [Listing all students in a module: `list_students`](#listing-all-students-in-a-module-list_students) + * [Find students in a module given a keyword: `find_student`](#find-students-in-a-module-given-a-keyword-find_student) + * [Listing marks for an assessment: `list_marks`](#listing-marks-for-an-assessment-list_marks) + * [Setting marks for a student's assessment: `set_marks`](#setting-marks-for-a-students-assessment-set_marks) + * [Editing marks for a student's assessment: `edit_mark`](#editing-marks-for-a-students-assessment-edit_mark) + * [Deleting marks for a student's assessment: `delete_mark`](#deleting-marks-for-a-students-assessment-delete_mark) + * [Finding average marks for an assessment: `average_marks`](#finding-average-marks-for-an-assessment-average_marks) * [FAQ](#faq) * [Command Summary](#command-summary) @@ -62,7 +71,7 @@ Examples:
-### Edits a student information: `edit_student` +### Editing student information: `edit_student` Edits student information from a particular module Format: `edit_student c/ s/ i/ n/` @@ -77,7 +86,7 @@ Examples:
-### Deletes a student information: `delete_student` +### Deleting student information: `delete_student` Deletes student information from a particular module Format: `delete_student c/ s/` @@ -104,7 +113,7 @@ Examples: ### Find students in a module given a keyword: `find_student` Displays all students in the module matching the keyword along with their index -Format: `find_student c/ k/ k/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). * `KEYWORD` refers to the keyword used to search the student list @@ -114,6 +123,76 @@ Examples:
+### Listing marks for an assessment: `list_marks` +Lists all students and their marks for an assessment. + +Format: `list_marks c/ a/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `ASSESSMENT_NAME` refers to the name of the assessment whose marks are to be listed. + +Examples: +* `list_marks c/CS2113T a/Midterms` +* `list_marks c/CS2101 a/Oral Presentation` + +
+ +### Setting marks for a student's assessment: `set_marks` +Add a student's marks for an assessment. + +Format: `set_marks c/ s/ a/ m/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `STUDENT_INDEX` refers to the index of the student in the module list. +* `ASSESSMENT_NAME` refers to the name of the assessment that is to be marked. +* `MARKS` refers to the marks given for the assessment. + +Examples: +* `set_marks c/CS2113T s/1 a/Midterms m/70.6` +* `set_marks c/CS2101 s/3 a/Oral Presentation m/80` + +
+ +### Editing marks for a student's assessment: `edit_mark` +Edits a student's mark for an assessment. + +Format: `edit_mark c/ s/ a/ m/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `STUDENT_INDEX` refers to the index of the student in the module list. +* `ASSESSMENT_NAME` refers to the name of the assessment that is to be remarked. +* `NEW_MARKS` refers to the new marks to be given for the assessment. + +Examples: +* `edit_mark c/CS2113T s/1 a/Midterms m/80.6` +* `edit_mark c/CS2101 s/3 a/Oral Presentation m/90` + +
+ +### Deleting marks for a student's assessment: `delete_mark` +Deletes a student's marks for an assessment. + +Format: `set_marks c/ s/ a/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `STUDENT_INDEX` refers to the index of the student in the module list. +* `ASSESSMENT_NAME` refers to the name of the assessment that is to be marked. + +Examples: +* `delete_mark c/CS2113T s/1 a/Midterms` +* `delete_mark c/CS2101 s/3 a/Oral Presentation` + +
+ +### Finding average marks for an assessment: `average_marks` +Finds the average marks for an assessment. + +Format: `set_marks c/ a/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `ASSESSMENT_NAME` refers to the name of the assessment that is to be marked. + +Examples: +* `average_marks c/CS2113T a/Midterms` +* `average_marks c/CS2101 a/Oral Presentation` + +
+ ### Exit the program: `exit` Exits the program @@ -129,4 +208,26 @@ Format: `exit` {Give a 'cheat sheet' of commands here} -* Add todo `todo n/TODO_NAME d/DEADLINE` +Command | Format and Examples | + ------ | --------------- | +add_assessment | `add_assessment c/ n/ m/ w/`
e.g. `hi` +add_module | `add_module c/ n/`
e.g. `add_module c/CS2113T n/Software Engineering and Object-oriented Programming` +add_student | `add_student c/ i/ n/`
e.g. `add_student c/cs2113t i/a0212345x n/Jon Lim` +set_attendance | `set_attendance c/ s/ l/ p/`
e.g. `hi` +set_marks | `set_marks c/ s/ a/ m/`
e.g. `set_marks c/CS2113T s/1 a/Midterms m/70.6` +average_marks | `average_marks c/ a/`
e.g. `average_marks c/CS2113T a/Midterms` +delete_student | `delete_student c/ s/`
e.g. `delete_student c/cs2113t s/1` +delete_assessment | `delete_assessment c/ n/`
e.g. `hi` +delete_mark | `delete_mark c/ s/ a/`
e.g. `delete_mark c/CS2113T s/1 a/Midterms` +edit_mark | `edit_mark c/ s/ a/ m/`
e.g. `edit_mark c/CS2113T s/1 a/Midterms m/80.6` +edit_student | `edit_student c/ s/ i/ n/`
e.g. `hi` +find_student | `find_student c/ k/`
e.g. `find_student c/CS2113T k/123` +exit | `exit` +help | `help` +list_assessments | `list_assessments c/`
e.g. `hi` +list_attendance | `list_attendance c/ s/`
e.g. `hi` +list_marks | `list_marks c/ a/`
e.g. `list_marks c/CS2113T a/Midterms` +list_modules | `list_modules` +list_students | `list_students c/`
e.g. `list_students c/CS2113T` + + diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index ed7525c6cf..4780103e1d 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,23 +1,6 @@ package taa; -import taa.command.AddAssessmentCommand; -import taa.command.AddModuleCommand; -import taa.command.AddStudentCommand; -import taa.command.AverageMarksCommand; -import taa.command.Command; -import taa.command.DeleteAssessmentCommand; -import taa.command.DeleteStudentCommand; -import taa.command.EditStudentCommand; -import taa.command.ExitCommand; -import taa.command.FindStudentCommand; -import taa.command.HelpCommand; -import taa.command.ListAssessmentsCommand; -import taa.command.ListAttendanceCommand; -import taa.command.ListMarksCommand; -import taa.command.ListModulesCommand; -import taa.command.ListStudentsCommand; -import taa.command.SetAttendanceCommand; -import taa.command.SetMarksCommand; +import taa.command.*; import taa.exception.TaaException; import java.util.ArrayList; @@ -94,6 +77,14 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new SetMarksCommand(argument); break; + case Command.COMMAND_EDIT_MARK: + command = new EditMarkCommand(argument); + break; + + case Command.COMMAND_DELETE_MARK: + command = new DeleteMarkCommand(argument); + break; + case Command.COMMAND_AVERAGE_MARKS: command = new AverageMarksCommand(argument); break; diff --git a/src/main/java/taa/assessment/Assessment.java b/src/main/java/taa/assessment/Assessment.java index de3290970a..1e91f7874a 100644 --- a/src/main/java/taa/assessment/Assessment.java +++ b/src/main/java/taa/assessment/Assessment.java @@ -57,6 +57,10 @@ public double getWeightage() { return weightage; } + public boolean isMarksValid(double marks) { + return ((marks >= 0) && (marks <= maximumMarks)); + } + public int getMaximumMarks() { return maximumMarks; } diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index 9784e15379..48eb4ed146 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -16,7 +16,7 @@ public class AverageMarksCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_ASSESSMENT_NAME = "a"; - private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; + private static final String[] AVERAGE_MARKS_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; private static final String MESSAGE_FORMAT_AVERAGE_MARKS_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_AVERAGE_MARKS = "Average marks for %s is %,.2f"; @@ -24,7 +24,7 @@ public class AverageMarksCommand extends Command { + "Note that %d student(s) have yet to be marked!"; public AverageMarksCommand(String argument) { - super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); + super(argument, AVERAGE_MARKS_ARGUMENT_KEYS); } /** diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index b4437d91c5..fedb10b944 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -25,6 +25,8 @@ public abstract class Command { public static final String COMMAND_ADD_ASSESSMENT = "add_assessment"; public static final String COMMAND_DELETE_ASSESSMENT = "delete_assessment"; public static final String COMMAND_SET_MARKS = "set_marks"; + public static final String COMMAND_EDIT_MARK = "edit_mark"; + public static final String COMMAND_DELETE_MARK = "delete_mark"; public static final String COMMAND_HELP = "help"; // Common messages @@ -34,6 +36,8 @@ public abstract class Command { protected static final String MESSAGE_INVALID_LESSON_INDEX = "Invalid lesson index."; protected static final String MESSAGE_INVALID_ASSESSMENT_NAME = "Invalid assessment name."; protected static final String MESSAGE_NO_STUDENTS = "There are no students in this module"; + protected static final String MESSAGE_NO_MARKS = "This student has not been marked yet."; + protected static final String MESSAGE_ALREADY_MARKED = "This student has already been marked."; // Common message formats protected static final String MESSAGE_FORMAT_GENERIC_USAGE = "%s"; diff --git a/src/main/java/taa/command/DeleteMarkCommand.java b/src/main/java/taa/command/DeleteMarkCommand.java new file mode 100644 index 0000000000..01427b1462 --- /dev/null +++ b/src/main/java/taa/command/DeleteMarkCommand.java @@ -0,0 +1,80 @@ +package taa.command; + +import taa.Ui; +import taa.assessment.Assessment; +import taa.assessment.AssessmentList; +import taa.exception.TaaException; +import taa.module.Module; +import taa.module.ModuleList; +import taa.storage.Storage; +import taa.student.Student; +import taa.student.StudentList; +import taa.util.Util; + +public class DeleteMarkCommand extends Command{ + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_STUDENT_INDEX = "s"; + private static final String KEY_ASSESSMENT_NAME = "a"; + private static final String[] DELETE_MARK_ARGUMENT_KEYS = { + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_ASSESSMENT_NAME + }; + private static final String MESSAGE_FORMAT_DELETE_MARKS_USAGE = "%s %s/ %s/ " + + "%s/"; + private static final String MESSAGE_FORMAT_MARKS_DELETED = "Marks for student '%s' have been deleted for" + + " assessment '%s'"; + public DeleteMarkCommand(String argument) { + super(argument, DELETE_MARK_ARGUMENT_KEYS); + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + if (!checkArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModule(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + int studentIndex = Integer.parseInt(studentIndexInput) - 1; + StudentList studentList = module.getStudentList(); + Student student = studentList.getStudentAt(studentIndex); + if (student == null || !Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + AssessmentList assessmentList = module.getAssessmentList(); + String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); + Assessment assessment = assessmentList.getAssessment(assessmentName); + if (assessment == null) { + throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); + } + if (student.getResults().get(assessmentName) == null) { + throw new TaaException(MESSAGE_NO_MARKS); + } + deleteMark(ui, student, assessmentName); + storage.save(moduleList); + } + + private void deleteMark(Ui ui, Student student, String assessmentName) { + student.deleteMark(assessmentName); + ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_DELETED, student, assessmentName)); + } + + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_DELETE_MARKS_USAGE, + COMMAND_DELETE_MARK, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_ASSESSMENT_NAME + ); + } +} diff --git a/src/main/java/taa/command/EditMarkCommand.java b/src/main/java/taa/command/EditMarkCommand.java new file mode 100644 index 0000000000..4315aac151 --- /dev/null +++ b/src/main/java/taa/command/EditMarkCommand.java @@ -0,0 +1,93 @@ +package taa.command; + +import taa.Ui; +import taa.assessment.Assessment; +import taa.assessment.AssessmentList; +import taa.exception.TaaException; +import taa.module.Module; +import taa.module.ModuleList; +import taa.storage.Storage; +import taa.student.Student; +import taa.student.StudentList; +import taa.util.Util; + +public class EditMarkCommand extends Command{ + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_STUDENT_INDEX = "s"; + private static final String KEY_ASSESSMENT_NAME = "a"; + private static final String KEY_NEW_MARKS = "m"; + private static final String[] EDIT_MARKS_ARGUMENT_KEYS = { + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_ASSESSMENT_NAME, + KEY_NEW_MARKS + }; + + private static final String MESSAGE_FORMAT_EDIT_MARKS_USAGE = "%s %s/ %s/ " + + "%s/ %s/"; + private static final String MESSAGE_FORMAT_INVALID_MARKS = "Invalid Marks. " + + "Marks must be between %d and %,.2f (inclusive)"; + private static final String MESSAGE_FORMAT_MARKS_EDITED = "Marks edited for %s: from %,.2f to %,.2f for %s"; + + public EditMarkCommand(String argument) { + super(argument, EDIT_MARKS_ARGUMENT_KEYS); + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + if (!checkArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModule(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + int studentIndex = Integer.parseInt(studentIndexInput) - 1; + StudentList studentList = module.getStudentList(); + Student student = studentList.getStudentAt(studentIndex); + if (student == null || !Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + AssessmentList assessmentList = module.getAssessmentList(); + String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); + Assessment assessment = assessmentList.getAssessment(assessmentName); + if (assessment == null) { + throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); + } + String marksInput = argumentMap.get(KEY_NEW_MARKS); + double marks = Double.parseDouble(marksInput); + double maximumMarks = assessment.getMaximumMarks(); + if ((!Util.isStringDouble(marksInput)) || !(assessment.isMarksValid(marks))) { + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, 0, maximumMarks)); + } + if (student.getResults().get(assessmentName) == null) { + throw new TaaException(MESSAGE_NO_MARKS); + } + editMark(ui, student, assessmentName, marks); + storage.save(moduleList); + } + + private void editMark(Ui ui, Student student, String assessmentName, double newMarks) { + double previousMark = student.getMarks(assessmentName); + student.deleteMark(assessmentName); + student.setMarks(assessmentName, newMarks); + ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_EDITED, student, previousMark, newMarks, assessmentName)); + } + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_EDIT_MARKS_USAGE, + COMMAND_EDIT_MARK, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_ASSESSMENT_NAME, + KEY_NEW_MARKS + ); + } +} diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index 476e9eed37..372a4c6045 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -12,9 +12,13 @@ public class HelpCommand extends Command { new AddAssessmentCommand(""), new AddModuleCommand(""), new AddStudentCommand(""), + new SetAttendanceCommand(""), + new SetMarksCommand(""), new AverageMarksCommand(""), new DeleteStudentCommand(""), new DeleteAssessmentCommand(""), + new DeleteMarkCommand(""), + new EditMarkCommand(""), new EditStudentCommand(""), new FindStudentCommand(""), new ExitCommand(""), @@ -23,9 +27,7 @@ public class HelpCommand extends Command { new ListAttendanceCommand(""), new ListMarksCommand(""), new ListModulesCommand(""), - new ListStudentsCommand(""), - new SetAttendanceCommand(""), - new SetMarksCommand("") + new ListStudentsCommand("") }; public HelpCommand(String argument) { diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index 3454e69abe..c2accf77f2 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -16,16 +16,15 @@ public class ListMarksCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_ASSESSMENT_NAME = "a"; - private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; + private static final String[] LIST_MARKS_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; private static final String MESSAGE_LIST_MARKS_HEADER = "Here is the list of students and " + "their marks for %s:"; private static final String MARKS_LIST_EMPTY = "There are no marks inputted!"; - private static final String MESSAGE_FORMAT_LIST_MARKS_USAGE = "%s %s/ %s/"; public ListMarksCommand(String argument) { - super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); + super(argument, LIST_MARKS_ARGUMENT_KEYS); } /** diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index c28865c973..01b1c6c434 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -19,7 +19,7 @@ public class SetMarksCommand extends Command { private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_ASSESSMENT_NAME = "a"; private static final String KEY_MARKS = "m"; - private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { + private static final String[] SET_MARKS_ARGUMENT_KEYS = { KEY_MODULE_CODE, KEY_STUDENT_INDEX, KEY_ASSESSMENT_NAME, @@ -29,11 +29,11 @@ public class SetMarksCommand extends Command { private static final String MESSAGE_FORMAT_SET_MARKS_USAGE = "%s %s/ %s/ " + "%s/ %s/"; private static final String MESSAGE_FORMAT_INVALID_MARKS = "Invalid Marks. " - + "Marks must be between %,.2f and %,.2f (inclusive)"; + + "Marks must be between %d and %,.2f (inclusive)"; private static final String MESSAGE_FORMAT_MARKS_ADDED = "Marks set for %s: %,.2f for %s"; public SetMarksCommand(String argument) { - super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); + super(argument, SET_MARKS_ARGUMENT_KEYS); } /** @@ -52,46 +52,34 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModule(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); - if (!Util.isStringInteger(studentIndexInput)) { - throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); - } int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = module.getStudentList(); Student student = studentList.getStudentAt(studentIndex); - if (student == null) { + if (student == null || !Util.isStringInteger(studentIndexInput)) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - AssessmentList assessmentList = module.getAssessmentList(); String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = assessmentList.getAssessment(assessmentName); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } - - String marksInput = argumentMap.get(KEY_MARKS); - if (!Util.isStringDouble(marksInput)) { - double[] marksRange = Student.getMarksRange(); - throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, marksRange[0], marksRange[1])); + if (student.marksExist(assessmentName)) { + throw new TaaException(MESSAGE_ALREADY_MARKED); } - + String marksInput = argumentMap.get(KEY_MARKS); double marks = Double.parseDouble(marksInput); - if (!Student.isMarksWithinRange(marks)) { - double[] marksRange = Student.getMarksRange(); - throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, marksRange[0], marksRange[1])); + double maximumMarks = assessment.getMaximumMarks(); + if ((!Util.isStringDouble(marksInput)) || !(assessment.isMarksValid(marks))) { + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, 0, maximumMarks)); } - - setMarks(ui, student, assessment, marks); - + setMarks(ui, student, assessmentName, marks); storage.save(moduleList); } @@ -100,12 +88,11 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc * * @param ui The ui instance to handle interactions with the user. * @param student The student instance to set the mark for. - * @param assessment The assessment instance. + * @param assessmentName The name of the assessment to be marked. * @param marks The marks to set for the assessment. */ - private void setMarks(Ui ui, Student student, Assessment assessment, double marks) { + private void setMarks(Ui ui, Student student, String assessmentName, double marks) { assert marks >= 0; - String assessmentName = assessment.getName(); student.setMarks(assessmentName, marks); ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_ADDED, student, marks, assessmentName)); } diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index 5e55475888..bdede9eca8 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -1,6 +1,8 @@ package taa.student; import taa.ClassChecker; +import taa.assessment.Assessment; +import taa.assessment.AssessmentList; import taa.attendance.AttendanceList; import java.util.HashMap; @@ -97,6 +99,15 @@ public void setMarks(String assessmentName, double marks) { results.put(assessmentName, marks); } + /** + * Deletes the marks for the given assessment. + * + * @param assessmentName Assessment whose marks are to be deleted. + */ + public void deleteMark(String assessmentName) { + results.remove(assessmentName); + } + /** * Gets the marks for the given assessment. * @@ -145,7 +156,7 @@ public boolean verify() { if (id.isEmpty() || name.isEmpty()) { return false; } - + //do this in module instead for (String assessmentName : results.keySet()) { if (!isMarksWithinRange(results.get(assessmentName))) { return false; From b876e3be1f06f50e12e4afd90922a34ac753b71f Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Thu, 21 Oct 2021 21:14:02 +0800 Subject: [PATCH 148/543] fixed wording for STUDENT_INDEX --- docs/UserGuide.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index b15b8bf1e3..6b7799ece0 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -76,7 +76,7 @@ Edits student information from a particular module Format: `edit_student c/ s/ i/ n/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the module list +* `STUDENT_INDEX` refers to the index of the student in the module * `STUDENT_ID` refers to the updated ID of the student (e.g. A0217978J) * `STUDENT_NAME` refers to the updated name of the student (e.g. Jon Limbs) @@ -91,7 +91,7 @@ Deletes student information from a particular module Format: `delete_student c/ s/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the module list +* `STUDENT_INDEX` refers to the index of the student in the module Examples: * `delete_student c/cs2113t s/1` @@ -141,7 +141,7 @@ Add a student's marks for an assessment. Format: `set_marks c/ s/ a/ m/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the module list. +* `STUDENT_INDEX` refers to the index of the student in the module. * `ASSESSMENT_NAME` refers to the name of the assessment that is to be marked. * `MARKS` refers to the marks given for the assessment. @@ -156,7 +156,7 @@ Edits a student's mark for an assessment. Format: `edit_mark c/ s/ a/ m/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the module list. +* `STUDENT_INDEX` refers to the index of the student in the module. * `ASSESSMENT_NAME` refers to the name of the assessment that is to be remarked. * `NEW_MARKS` refers to the new marks to be given for the assessment. @@ -171,7 +171,7 @@ Deletes a student's marks for an assessment. Format: `set_marks c/ s/ a/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the module list. +* `STUDENT_INDEX` refers to the index of the student in the module. * `ASSESSMENT_NAME` refers to the name of the assessment that is to be marked. Examples: From 788b317b5de035f22f5952fb1384677f8d6ad828 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Thu, 21 Oct 2021 21:31:41 +0800 Subject: [PATCH 149/543] edited for gradle --- src/main/java/taa/Parser.java | 21 ++++++++++++++++++- .../java/taa/command/DeleteMarkCommand.java | 17 ++++++++------- .../java/taa/command/EditMarkCommand.java | 10 ++++----- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 4780103e1d..fbd40dc078 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,6 +1,25 @@ package taa; -import taa.command.*; +import taa.command.AddAssessmentCommand; +import taa.command.AddModuleCommand; +import taa.command.AddStudentCommand; +import taa.command.AverageMarksCommand; +import taa.command.Command; +import taa.command.DeleteAssessmentCommand; +import taa.command.DeleteMarkCommand; +import taa.command.DeleteStudentCommand; +import taa.command.EditMarkCommand; +import taa.command.EditStudentCommand; +import taa.command.ExitCommand; +import taa.command.FindStudentCommand; +import taa.command.HelpCommand; +import taa.command.ListAssessmentsCommand; +import taa.command.ListAttendanceCommand; +import taa.command.ListMarksCommand; +import taa.command.ListModulesCommand; +import taa.command.ListStudentsCommand; +import taa.command.SetAttendanceCommand; +import taa.command.SetMarksCommand; import taa.exception.TaaException; import java.util.ArrayList; diff --git a/src/main/java/taa/command/DeleteMarkCommand.java b/src/main/java/taa/command/DeleteMarkCommand.java index 01427b1462..9d343de112 100644 --- a/src/main/java/taa/command/DeleteMarkCommand.java +++ b/src/main/java/taa/command/DeleteMarkCommand.java @@ -11,19 +11,20 @@ import taa.student.StudentList; import taa.util.Util; -public class DeleteMarkCommand extends Command{ +public class DeleteMarkCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_ASSESSMENT_NAME = "a"; private static final String[] DELETE_MARK_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_ASSESSMENT_NAME + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_ASSESSMENT_NAME }; - private static final String MESSAGE_FORMAT_DELETE_MARKS_USAGE = "%s %s/ %s/ " + - "%s/"; - private static final String MESSAGE_FORMAT_MARKS_DELETED = "Marks for student '%s' have been deleted for" + - " assessment '%s'"; + private static final String MESSAGE_FORMAT_DELETE_MARKS_USAGE = "%s %s/ %s/ " + + "%s/"; + private static final String MESSAGE_FORMAT_MARKS_DELETED = "Marks for student '%s' have been deleted for" + + " assessment '%s'"; + public DeleteMarkCommand(String argument) { super(argument, DELETE_MARK_ARGUMENT_KEYS); } diff --git a/src/main/java/taa/command/EditMarkCommand.java b/src/main/java/taa/command/EditMarkCommand.java index 4315aac151..85e70356d2 100644 --- a/src/main/java/taa/command/EditMarkCommand.java +++ b/src/main/java/taa/command/EditMarkCommand.java @@ -11,16 +11,16 @@ import taa.student.StudentList; import taa.util.Util; -public class EditMarkCommand extends Command{ +public class EditMarkCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_ASSESSMENT_NAME = "a"; private static final String KEY_NEW_MARKS = "m"; private static final String[] EDIT_MARKS_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_ASSESSMENT_NAME, - KEY_NEW_MARKS + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_ASSESSMENT_NAME, + KEY_NEW_MARKS }; private static final String MESSAGE_FORMAT_EDIT_MARKS_USAGE = "%s %s/ %s/ " From cb93a286fc00bae270e4cf86e5847518aa2246ca Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Thu, 21 Oct 2021 22:19:32 +0800 Subject: [PATCH 150/543] add delete function for attendance --- src/main/java/taa/Parser.java | 5 ++ .../java/taa/attendance/AttendanceList.java | 42 +++++++++ src/main/java/taa/command/Command.java | 3 +- .../taa/command/DeleteAttendanceCommand.java | 90 +++++++++++++++++++ .../taa/command/SetAttendanceCommand.java | 2 +- 5 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 src/main/java/taa/command/DeleteAttendanceCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 74c766717c..b615eda278 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -17,6 +17,7 @@ import taa.command.ListStudentsCommand; import taa.command.ListAttendanceCommand; import taa.command.SetMarksCommand; +import taa.command.DeleteAttendanceCommand; import taa.exception.TaaException; @@ -86,6 +87,10 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new ListAttendanceCommand(argument); break; + case Command.COMMAND_DELETE_ATTENDANCE: + command = new DeleteAttendanceCommand(argument); + break; + case Command.COMMAND_SET_MARKS: command = new SetMarksCommand(argument); break; diff --git a/src/main/java/taa/attendance/AttendanceList.java b/src/main/java/taa/attendance/AttendanceList.java index ca3da2661d..792e1ca606 100644 --- a/src/main/java/taa/attendance/AttendanceList.java +++ b/src/main/java/taa/attendance/AttendanceList.java @@ -17,6 +17,8 @@ public int getSize() { return attendances.size(); } + public static int ATTENDANCE_NOT_FOUND = -1; + /** * Gets the list of attendances. Note: This returns a new ArrayList instance. * @@ -52,6 +54,46 @@ public void addAttendance(Attendance attendance) { sortAttendances(); } + /** + * Checks if an index is valid with respect to the attendance ArrayList. + * + * @param index The index to check. + * @return true if valid, else false. + */ + public boolean isValidIndex(int index) { + return (index >= 0 && index < getSize()); + } + + /** + * Deletes a record of attendance from the attendance list. + * + * @param lessonNumInput The inputted lesson Num to delete. + * @return An Attendance object if successfully deleted, else null. + */ + public Attendance deleteAttendance(String lessonNumInput) { + int attendanceIndex = findAttendanceIndex(lessonNumInput); + if (isValidIndex(attendanceIndex)) { + return attendances.remove(attendanceIndex); + } + return null; + } + + /** + * Gets the index of a particular student's lesson attendance in attendance list. + * + * @param lessonNumInput The inputted lesson Num to search for. + * @return A index of student's lesson attendance in attendance list. + */ + public int findAttendanceIndex(String lessonNumInput) { + for (Attendance attendance : attendances) { + int lessonNumber = attendance.getLessonNumber(); + if (lessonNumber == Integer.parseInt(lessonNumInput)) { + return attendances.indexOf(attendance); + } + } + return ATTENDANCE_NOT_FOUND; + } + /** * Sorts the Attendance objects in the attendances ArrayList in ascending order based on lesson number. */ diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index dfbf79e067..67e3ed2d73 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -23,6 +23,7 @@ public abstract class Command { public static final String COMMAND_DELETE_STUDENT = "delete_student"; public static final String COMMAND_SET_ATTENDANCE = "set_attendance"; public static final String COMMAND_ADD_ASSESSMENT = "add_assessment"; + public static final String COMMAND_DELETE_ATTENDANCE = "delete_attendance"; public static final String COMMAND_SET_MARKS = "set_marks"; public static final String COMMAND_HELP = "help"; @@ -30,7 +31,7 @@ public abstract class Command { protected static final String MESSAGE_UNKNOWN_USAGE = "Unknown usage."; protected static final String MESSAGE_MODULE_NOT_FOUND = "Module not found."; protected static final String MESSAGE_INVALID_STUDENT_INDEX = "Invalid student index."; - protected static final String MESSAGE_INVALID_LESSON_INDEX = "Invalid lesson index."; + protected static final String MESSAGE_INVALID_LESSON_NUMBER = "Invalid lesson number."; protected static final String MESSAGE_INVALID_ASSESSMENT_NAME = "Invalid assessment name."; protected static final String MESSAGE_NO_STUDENTS = "There are no students in this module"; diff --git a/src/main/java/taa/command/DeleteAttendanceCommand.java b/src/main/java/taa/command/DeleteAttendanceCommand.java new file mode 100644 index 0000000000..db2b3467b9 --- /dev/null +++ b/src/main/java/taa/command/DeleteAttendanceCommand.java @@ -0,0 +1,90 @@ +package taa.command; + +import taa.Ui; +import taa.attendance.Attendance; +import taa.attendance.AttendanceList; +import taa.exception.TaaException; +import taa.module.Module; +import taa.module.ModuleList; +import taa.storage.Storage; +import taa.student.Student; +import taa.util.Util; + +public class DeleteAttendanceCommand extends Command{ + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_STUDENT_INDEX = "s"; + private static final String KEY_LESSON_NUMBER = "l"; + private static final String[] DELETE_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX, KEY_LESSON_NUMBER}; + + private static final String MESSAGE_FORMAT_DELETE_ATTENDANCE_USAGE = + "%s %s/ %s/ %s/"; + + private static final String MESSAGE_FORMAT_ATTENDANCE_DELETED = "Attendance removed for %s:\n Lesson %s"; + + public DeleteAttendanceCommand(String argument) { + super(argument, DELETE_ATTENDANCE_ARGUMENT_KEYS); + } + + /** + * Executes the delete_attendance command and deletes a student's attendance from the attendanceList. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!checkArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModule(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + int studentIndex = Integer.parseInt(studentIndexInput) - 1; + + Student student = module.getStudentList().getStudentAt(studentIndex); + assert studentIndex >= 0 && studentIndex < module.getStudentList().getSize(); + if (student == null) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + + String lessonNumInput = argumentMap.get(KEY_LESSON_NUMBER); + if (!Util.isStringInteger(lessonNumInput)) { + throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); + } + + AttendanceList attendanceList = student.getAttendanceList(); + Attendance attendance = attendanceList.deleteAttendance(lessonNumInput); + if (attendance == null) { + throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); + } + + storage.save(moduleList); + + ui.printMessage(String.format(MESSAGE_FORMAT_ATTENDANCE_DELETED, student, lessonNumInput)); + } + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_DELETE_ATTENDANCE_USAGE, + COMMAND_DELETE_ATTENDANCE, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_LESSON_NUMBER + ); + } +} diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index 6a8fbf07d0..dcc2a5de35 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -64,7 +64,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); if (!Util.isStringInteger(studentIndexInput)) { - throw new TaaException(MESSAGE_INVALID_LESSON_INDEX); + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } int studentIndex = Integer.parseInt(studentIndexInput) - 1; From 853dd6b0a72bb77e3eb278bdeeabb0a7a629076d Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Thu, 21 Oct 2021 22:36:07 +0800 Subject: [PATCH 151/543] fix checkstyle issues --- src/main/java/taa/command/DeleteAttendanceCommand.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/command/DeleteAttendanceCommand.java b/src/main/java/taa/command/DeleteAttendanceCommand.java index db2b3467b9..fc4b98adc4 100644 --- a/src/main/java/taa/command/DeleteAttendanceCommand.java +++ b/src/main/java/taa/command/DeleteAttendanceCommand.java @@ -10,14 +10,18 @@ import taa.student.Student; import taa.util.Util; -public class DeleteAttendanceCommand extends Command{ +public class DeleteAttendanceCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_LESSON_NUMBER = "l"; - private static final String[] DELETE_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX, KEY_LESSON_NUMBER}; + private static final String[] DELETE_ATTENDANCE_ARGUMENT_KEYS = { + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_LESSON_NUMBER + }; private static final String MESSAGE_FORMAT_DELETE_ATTENDANCE_USAGE = - "%s %s/ %s/ %s/"; + "%s %s/ %s/ %s/"; private static final String MESSAGE_FORMAT_ATTENDANCE_DELETED = "Attendance removed for %s:\n Lesson %s"; From 581c587b1d04a93233c7a629e2c3af41fb78d303 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Thu, 21 Oct 2021 23:27:25 +0800 Subject: [PATCH 152/543] added minimal stuff for dg --- docs/DeveloperGuide.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index f480db4e4c..79c3339c3c 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -71,14 +71,17 @@ ensure that there is no existing module with code `CS2113T`. and `Software Engineering` set as its code and name respectively. Then, `ModuleList#addModule` is called to add the newly created `Module` object into the `modules` ArrayList within `ModuleList`. +### Set marks +he set marks mechanism is facilitated by `SetMarksCommand`. It extends `Command`.
+ ## Product scope ### Target user profile * Teaching assistant who has a need to manage a significant number of students and their information -* prefers desktop app over other types -* can type fast -* prefers typing to mouse interactions -* is reasonably comfortable using CLI apps +* Prefers desktop app over other types +* Can type fast +* Prefers typing to mouse interactions +* Reasonably comfortable using CLI apps ### Value proposition From 05f8b813a5da11e7de5e80d75a93caf8b312d9a2 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Thu, 21 Oct 2021 23:33:55 +0800 Subject: [PATCH 153/543] edit developer guide to add set attendance impementation --- docs/DeveloperGuide.md | 32 ++++++++++++++- .../java/taa/attendance/AttendanceList.java | 40 +++++++++---------- 2 files changed, 51 insertions(+), 21 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 5c33ad55fe..d660acb769 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -60,7 +60,7 @@ module internally as an ArrayList `modules`.
* `ModuleList#getSize()` - Returns the no. of modules currently in the list. * `ModuleList#getModules()` - Returns an ArrayList containing all the modules. * `ModuleList#getModule(code:String)` - Returns a module with a particular code. -* `ModuleList#isValidIndex()` - Checks if an index is valid w.r.t the `modules` ArrayList. +* `ModuleList#isValidIndex(index:int)` - Checks if an index is valid w.r.t the `modules` ArrayList. * `ModuleList#addModule(module:Module)` - Adds a module to the `modules` ArrayList. * `ModuleList#getModuleAt(index:int)` - Returns a `Module` object at the specified `index` within the `modules` ArrayList. @@ -72,6 +72,36 @@ ensure that there is no existing module with code `CS2113T`. and `Software Engineering` set as its code and name respectively. Then, `ModuleList#addModule` is called to add the newly created `Module` object into the `modules` ArrayList within `ModuleList`. +### Set attendance +The set attendance mechanism is facilitated by SetAttendanceCommand. It extends `Command` and +uses `AttendanceList` which stores a student's lessons attendance as an +ArrayList `attendances`.
+ +`SetAttendanceCommand` implements the following methods: +* `SetAttendanceCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Performs operations for the command. + +`AttendanceList` implements the following methods: +* `AttendanceList#getSize()` - Returns the no. of attendance currently in the list. +* `AttendanceList#getAttendances()` - Returns an ArrayList containing all the attendances. +* `AttendanceList#getAttendance(lessonNumber:String)` - Returns an attendance with a particular lesson number. +* `AttendanceList#isValidIndex(index:int)` - Checks if an index is valid w.r.t the `attendances` ArrayList. +* `AttendanceList#addAttendance(attendance:Attendance)` - Adds an attendance to the `attendances` ArrayList. +* `AttendnaceList#getAttendnaceIndex(lessonNumInput:String)` - Returns the attendance index in the `attendances` ArrayList. +* `AttendanceList#deleteAttendance(lessonNumInput:String)` - Deletes an attendance with a particular lesson number. +* `AttendanceList#sortAttendances` - Sorts the attendance in the `attendances` ArrayList in ascending order based on lesson number. + +Below is an example scenario of how the set attendance feature behaves at each step: +* Step 1 - The user executes `set_attendance c/CS2113T s/1 l/1 p/1` to set an attendance to `Present` for student at +index `1`, lesson number `1` to set a student's attendance for a lesson. The `set_attendance` command calls the `SetAttendanceCommand#execute` method. Within +`SetAttendanceCommand#execute`, `AttendanceList#getAttendance("1")` is called to ensure that there is no existing attendance with the +lesson number `1`for student at index `1`. +* Step 2 - If no existing attendance object with lesson number `1` for student at index `1` is found, a new `Attendance` object +with lesson number `1` and attendance record `Present` is set as its lesson number and attendance record respectively. +Then, `AttendanceList#addAttendance` is called to add the newly created `Attendance` object into the `attendances` +ArrayList within `AttendanceList`. + + + ## Product scope ### Target user profile diff --git a/src/main/java/taa/attendance/AttendanceList.java b/src/main/java/taa/attendance/AttendanceList.java index 792e1ca606..869ead6b9e 100644 --- a/src/main/java/taa/attendance/AttendanceList.java +++ b/src/main/java/taa/attendance/AttendanceList.java @@ -44,16 +44,6 @@ public Attendance getAttendance(int lessonNumber) { return null; } - /** - * Adds an Attendance object to the list of attendances. The attendances ArrayList is sorted after adding. - * - * @param attendance The attendance object to add. - */ - public void addAttendance(Attendance attendance) { - attendances.add(attendance); - sortAttendances(); - } - /** * Checks if an index is valid with respect to the attendance ArrayList. * @@ -65,17 +55,13 @@ public boolean isValidIndex(int index) { } /** - * Deletes a record of attendance from the attendance list. + * Adds an Attendance object to the list of attendances. The attendances ArrayList is sorted after adding. * - * @param lessonNumInput The inputted lesson Num to delete. - * @return An Attendance object if successfully deleted, else null. + * @param attendance The attendance object to add. */ - public Attendance deleteAttendance(String lessonNumInput) { - int attendanceIndex = findAttendanceIndex(lessonNumInput); - if (isValidIndex(attendanceIndex)) { - return attendances.remove(attendanceIndex); - } - return null; + public void addAttendance(Attendance attendance) { + attendances.add(attendance); + sortAttendances(); } /** @@ -84,7 +70,7 @@ public Attendance deleteAttendance(String lessonNumInput) { * @param lessonNumInput The inputted lesson Num to search for. * @return A index of student's lesson attendance in attendance list. */ - public int findAttendanceIndex(String lessonNumInput) { + public int getAttendanceIndex(String lessonNumInput) { for (Attendance attendance : attendances) { int lessonNumber = attendance.getLessonNumber(); if (lessonNumber == Integer.parseInt(lessonNumInput)) { @@ -94,6 +80,20 @@ public int findAttendanceIndex(String lessonNumInput) { return ATTENDANCE_NOT_FOUND; } + /** + * Deletes a record of attendance from the attendance list. + * + * @param lessonNumInput The inputted lesson Num to delete. + * @return An Attendance object if successfully deleted, else null. + */ + public Attendance deleteAttendance(String lessonNumInput) { + int attendanceIndex = getAttendanceIndex(lessonNumInput); + if (isValidIndex(attendanceIndex)) { + return attendances.remove(attendanceIndex); + } + return null; + } + /** * Sorts the Attendance objects in the attendances ArrayList in ascending order based on lesson number. */ From 6833a14604a228adc301964405c9f7624b72dc70 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:06:35 +0800 Subject: [PATCH 154/543] Add ability to enable/disable logger and set default to disabled --- src/main/java/META-INF/MANIFEST.MF | 3 --- src/main/java/taa/Taa.java | 15 ++++++++++- src/main/java/taa/logger/TaaLogger.java | 34 ++++++++++++++++++++++++- 3 files changed, 47 insertions(+), 5 deletions(-) delete mode 100644 src/main/java/META-INF/MANIFEST.MF diff --git a/src/main/java/META-INF/MANIFEST.MF b/src/main/java/META-INF/MANIFEST.MF deleted file mode 100644 index 0797128cc7..0000000000 --- a/src/main/java/META-INF/MANIFEST.MF +++ /dev/null @@ -1,3 +0,0 @@ -Manifest-Version: 1.0 -Main-Class: taa.Taa - diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index 814ba61ec2..b32c9e29c5 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -2,6 +2,7 @@ import taa.command.Command; import taa.exception.TaaException; +import taa.logger.TaaLogger; import taa.module.ModuleList; import taa.storage.Storage; @@ -17,6 +18,11 @@ public Taa() { this.storage = new Storage(DATA_FILENAME); } + public Taa(boolean isLoggingEnabled) { + this(); + TaaLogger.setEnabled(isLoggingEnabled); + } + public void run() { loadModuleListFromStorage(); assert moduleList != null; @@ -56,7 +62,14 @@ private void loadModuleListFromStorage() { * Main entry-point for the java.duke.Duke application. */ public static void main(String[] args) { - Taa taa = new Taa(); + boolean isLoggingEnabled = false; + for (String arg : args) { + if (arg.equals("-log")) { + isLoggingEnabled = true; + } + } + + Taa taa = new Taa(isLoggingEnabled); taa.run(); } } diff --git a/src/main/java/taa/logger/TaaLogger.java b/src/main/java/taa/logger/TaaLogger.java index 8b7bbf6771..8d4d0d1b76 100644 --- a/src/main/java/taa/logger/TaaLogger.java +++ b/src/main/java/taa/logger/TaaLogger.java @@ -13,13 +13,20 @@ public class TaaLogger { public static final TaaLogger LOGGER = new TaaLogger(); private final Logger logger; + private boolean isInit; private TaaLogger() { this.logger = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); - init(); + this.isInit = false; } private void init() { + if (isInit) { + return; + } + + isInit = true; + FileHandler fileHandler; try { fileHandler = new FileHandler(LOG_FILENAME); @@ -37,15 +44,40 @@ private void init() { } } + public static void setEnabled(boolean isEnabled) { + Logger logger = LOGGER.logger; + + if (isEnabled) { + logger.setLevel(Level.INFO); + } else { + logger.setLevel(Level.OFF); + } + } + public void logInfo(String message) { + if (logger.getLevel() == Level.OFF) { + return; + } + + init(); logger.log(Level.INFO, message); } public void logWarning(String message) { + if (logger.getLevel() == Level.OFF) { + return; + } + + init(); logger.log(Level.WARNING, message); } public void logSevere(String message) { + if (logger.getLevel() == Level.OFF) { + return; + } + + init(); logger.log(Level.SEVERE, message); } } From 02bbdf8e153f2f5a254e0e3411898a221a4ff865 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:09:26 +0800 Subject: [PATCH 155/543] Change maximum marks check to Assessment class --- src/main/java/taa/assessment/Assessment.java | 31 +++---------------- .../java/taa/assessment/AssessmentList.java | 8 ++--- 2 files changed, 6 insertions(+), 33 deletions(-) diff --git a/src/main/java/taa/assessment/Assessment.java b/src/main/java/taa/assessment/Assessment.java index 1e91f7874a..1de3c69bc3 100644 --- a/src/main/java/taa/assessment/Assessment.java +++ b/src/main/java/taa/assessment/Assessment.java @@ -3,8 +3,8 @@ import taa.ClassChecker; public class Assessment implements ClassChecker { - private static final double[] WEIGHTAGE_RANGE = {0, 100}; - private static final int MAXIMUM_MARKS_RANGE = 0; + public static final double[] WEIGHTAGE_RANGE = {0, 100}; + public static final int MINIMUM_MARKS = 0; private String name; private int maximumMarks; @@ -26,29 +26,6 @@ public static boolean isWeightageWithinRange(double weightage) { return (weightage >= WEIGHTAGE_RANGE[0] && weightage <= WEIGHTAGE_RANGE[1]); } - /** - * Checks if a maximum marks is valid. - * - * @param maximumMarks The maximum marks to check. - * @return true if valid, else false. - */ - public static boolean isMaximumMarksWithinRange(int maximumMarks) { - return (maximumMarks >= MAXIMUM_MARKS_RANGE); - } - - /** - * Gets the weightage range. - * - * @return A double array of size 2: [0] - Min weightage, [1] Max weightage. - */ - public static double[] getWeightageRange() { - return WEIGHTAGE_RANGE; - } - - public static int getMaximumMarksRange() { - return MAXIMUM_MARKS_RANGE; - } - public String getName() { return name; } @@ -58,7 +35,7 @@ public double getWeightage() { } public boolean isMarksValid(double marks) { - return ((marks >= 0) && (marks <= maximumMarks)); + return ((marks >= MINIMUM_MARKS) && (marks <= maximumMarks)); } public int getMaximumMarks() { @@ -84,7 +61,7 @@ public String toString() { */ @Override public boolean verify() { - if (name.isEmpty() || !isWeightageWithinRange(weightage)) { + if (name.isEmpty() || !isWeightageWithinRange(weightage) || maximumMarks < MINIMUM_MARKS) { return false; } diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 0e4efaaad7..541feb38f7 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -40,7 +40,7 @@ public boolean isValidIndex(int index) { * or total weightage exceed the maximum weightage after adding. * * @param assessment The assessment object to be added. - * @return True if success, else false. + * @return true if success, else false. */ public boolean addAssessment(Assessment assessment) { double totalWeightage = 0; @@ -54,7 +54,7 @@ public boolean addAssessment(Assessment assessment) { double newTotalWeightage = totalWeightage + assessment.getWeightage(); if (!Assessment.isWeightageWithinRange(newTotalWeightage) - || !Assessment.isMaximumMarksWithinRange(assessment.getMaximumMarks())) { + || assessment.getMaximumMarks() < Assessment.MINIMUM_MARKS) { return false; } @@ -148,10 +148,6 @@ public boolean verify() { assessmentNames.add(name.toLowerCase()); totalWeightage += assessment.getWeightage(); } - - if (!Assessment.isMaximumMarksWithinRange(assessment.getMaximumMarks())) { - return false; - } } for (Assessment assessment : duplicatedAssessments) { From 3f128bffe45478774f259a18d62e95cb6a8770d5 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:11:35 +0800 Subject: [PATCH 156/543] Refactor checkArguments to hasAllArguments --- src/main/java/taa/command/AddAssessmentCommand.java | 1 + src/main/java/taa/command/AddStudentCommand.java | 1 + src/main/java/taa/command/AverageMarksCommand.java | 1 + src/main/java/taa/command/Command.java | 4 +++- src/main/java/taa/command/DeleteAssessmentCommand.java | 1 + src/main/java/taa/command/DeleteAttendanceCommand.java | 1 + src/main/java/taa/command/DeleteMarkCommand.java | 1 + src/main/java/taa/command/DeleteStudentCommand.java | 1 + src/main/java/taa/command/EditMarkCommand.java | 1 + src/main/java/taa/command/EditStudentCommand.java | 1 + src/main/java/taa/command/FindStudentCommand.java | 1 + src/main/java/taa/command/ListAssessmentsCommand.java | 1 + src/main/java/taa/command/ListAttendanceCommand.java | 1 + src/main/java/taa/command/ListMarksCommand.java | 1 + src/main/java/taa/command/ListStudentsCommand.java | 1 + src/main/java/taa/command/SetAttendanceCommand.java | 1 + src/main/java/taa/command/SetMarksCommand.java | 1 + 17 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index b138909474..17630a0469 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -51,6 +51,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index 2c8f7c3dec..f582d5e8e9 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -37,6 +37,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index 48eb4ed146..c9c66914aa 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -42,6 +42,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 2580b53cf0..46acf768cc 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -17,6 +17,8 @@ public abstract class Command { public static final String COMMAND_LIST_MARKS = "list_marks"; public static final String COMMAND_AVERAGE_MARKS = "average_marks"; public static final String COMMAND_ADD_MODULE = "add_module"; + public static final String COMMAND_EDIT_MODULE = "edit_module"; + public static final String COMMAND_DELETE_MODULE = "delete_module"; public static final String COMMAND_FIND_STUDENT = "find_student"; public static final String COMMAND_ADD_STUDENT = "add_student"; public static final String COMMAND_EDIT_STUDENT = "edit_student"; @@ -87,7 +89,7 @@ protected String getMissingArgumentMessage() { * * @return true if there no missing arguments, else false. */ - protected boolean checkArguments() { + protected boolean hasAllArguments() { for (String key : argumentKeys) { if (!argumentMap.containsKey(key)) { return false; diff --git a/src/main/java/taa/command/DeleteAssessmentCommand.java b/src/main/java/taa/command/DeleteAssessmentCommand.java index be7e7d20e0..69287ea0a0 100644 --- a/src/main/java/taa/command/DeleteAssessmentCommand.java +++ b/src/main/java/taa/command/DeleteAssessmentCommand.java @@ -35,6 +35,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/DeleteAttendanceCommand.java b/src/main/java/taa/command/DeleteAttendanceCommand.java index fc4b98adc4..c41e2a4b23 100644 --- a/src/main/java/taa/command/DeleteAttendanceCommand.java +++ b/src/main/java/taa/command/DeleteAttendanceCommand.java @@ -44,6 +44,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/DeleteMarkCommand.java b/src/main/java/taa/command/DeleteMarkCommand.java index 9d343de112..15fc6996e7 100644 --- a/src/main/java/taa/command/DeleteMarkCommand.java +++ b/src/main/java/taa/command/DeleteMarkCommand.java @@ -35,6 +35,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } String moduleCode = argumentMap.get(KEY_MODULE_CODE); diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 73e9cbc833..f244046cb9 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -36,6 +36,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/EditMarkCommand.java b/src/main/java/taa/command/EditMarkCommand.java index 85e70356d2..5e49117239 100644 --- a/src/main/java/taa/command/EditMarkCommand.java +++ b/src/main/java/taa/command/EditMarkCommand.java @@ -39,6 +39,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } String moduleCode = argumentMap.get(KEY_MODULE_CODE); diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 7aee7fc72d..b8ff64c384 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -44,6 +44,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 057312c9df..b0ad0903ad 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -39,6 +39,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index 313d05ec43..c0a1433381 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -35,6 +35,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/ListAttendanceCommand.java index 7bb114993b..88da778777 100644 --- a/src/main/java/taa/command/ListAttendanceCommand.java +++ b/src/main/java/taa/command/ListAttendanceCommand.java @@ -38,6 +38,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index c2accf77f2..3290cbd618 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -41,6 +41,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index bbbd43c272..f1b9e62b57 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -35,6 +35,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index dcc2a5de35..e1ff896b67 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -53,6 +53,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 01b1c6c434..bdeb6391e3 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -50,6 +50,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } if (!checkArguments()) { + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } String moduleCode = argumentMap.get(KEY_MODULE_CODE); From d7508b34c488f9b624a4c298fe9a8995f0a54829 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:13:43 +0800 Subject: [PATCH 157/543] Refactor checkArguments to hasAllArguments --- src/main/java/taa/command/AddAssessmentCommand.java | 1 - src/main/java/taa/command/AddStudentCommand.java | 1 - src/main/java/taa/command/AverageMarksCommand.java | 1 - src/main/java/taa/command/DeleteAssessmentCommand.java | 1 - src/main/java/taa/command/DeleteAttendanceCommand.java | 1 - src/main/java/taa/command/DeleteMarkCommand.java | 1 - src/main/java/taa/command/DeleteStudentCommand.java | 1 - src/main/java/taa/command/EditMarkCommand.java | 1 - src/main/java/taa/command/EditStudentCommand.java | 1 - src/main/java/taa/command/FindStudentCommand.java | 1 - src/main/java/taa/command/ListAssessmentsCommand.java | 1 - src/main/java/taa/command/ListAttendanceCommand.java | 1 - src/main/java/taa/command/ListMarksCommand.java | 1 - src/main/java/taa/command/ListStudentsCommand.java | 1 - src/main/java/taa/command/SetAttendanceCommand.java | 1 - src/main/java/taa/command/SetMarksCommand.java | 1 - 16 files changed, 16 deletions(-) diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 17630a0469..00de7ffbca 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -50,7 +50,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index f582d5e8e9..2235903412 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -36,7 +36,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index c9c66914aa..ac52a7e1e5 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -41,7 +41,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/DeleteAssessmentCommand.java b/src/main/java/taa/command/DeleteAssessmentCommand.java index 69287ea0a0..902f1cc639 100644 --- a/src/main/java/taa/command/DeleteAssessmentCommand.java +++ b/src/main/java/taa/command/DeleteAssessmentCommand.java @@ -34,7 +34,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/DeleteAttendanceCommand.java b/src/main/java/taa/command/DeleteAttendanceCommand.java index c41e2a4b23..46e2088e35 100644 --- a/src/main/java/taa/command/DeleteAttendanceCommand.java +++ b/src/main/java/taa/command/DeleteAttendanceCommand.java @@ -43,7 +43,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/DeleteMarkCommand.java b/src/main/java/taa/command/DeleteMarkCommand.java index 15fc6996e7..75d45b55d9 100644 --- a/src/main/java/taa/command/DeleteMarkCommand.java +++ b/src/main/java/taa/command/DeleteMarkCommand.java @@ -34,7 +34,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index f244046cb9..b304f8afd0 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -35,7 +35,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/EditMarkCommand.java b/src/main/java/taa/command/EditMarkCommand.java index 5e49117239..d6b29e3138 100644 --- a/src/main/java/taa/command/EditMarkCommand.java +++ b/src/main/java/taa/command/EditMarkCommand.java @@ -38,7 +38,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index b8ff64c384..b26bb1e01a 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -43,7 +43,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index b0ad0903ad..7dcfa1771e 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -38,7 +38,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index c0a1433381..bb686cb68a 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -34,7 +34,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/ListAttendanceCommand.java index 88da778777..d93d6ba968 100644 --- a/src/main/java/taa/command/ListAttendanceCommand.java +++ b/src/main/java/taa/command/ListAttendanceCommand.java @@ -37,7 +37,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index 3290cbd618..4979935069 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -40,7 +40,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index f1b9e62b57..5bf2468b62 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -34,7 +34,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index e1ff896b67..94f9ac47c0 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -52,7 +52,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index bdeb6391e3..4ccdbabf1f 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -49,7 +49,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } From 075595a879a48d8221914dc252d4bba53d3df3d0 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:14:44 +0800 Subject: [PATCH 158/543] Refactor getModule to getModuleWithCode --- .../taa/command/AddAssessmentCommand.java | 20 ++++++++----------- .../java/taa/command/AddModuleCommand.java | 10 +++++----- .../java/taa/command/AddStudentCommand.java | 2 +- .../java/taa/command/AverageMarksCommand.java | 2 +- .../taa/command/DeleteAssessmentCommand.java | 2 +- .../taa/command/DeleteAttendanceCommand.java | 2 +- .../java/taa/command/DeleteMarkCommand.java | 2 +- .../taa/command/DeleteStudentCommand.java | 4 ++-- .../java/taa/command/EditMarkCommand.java | 2 +- .../java/taa/command/EditStudentCommand.java | 2 +- .../java/taa/command/FindStudentCommand.java | 2 +- .../taa/command/ListAssessmentsCommand.java | 2 +- .../taa/command/ListAttendanceCommand.java | 2 +- .../java/taa/command/ListMarksCommand.java | 2 +- .../java/taa/command/ListStudentsCommand.java | 2 +- .../taa/command/SetAttendanceCommand.java | 2 +- .../java/taa/command/SetMarksCommand.java | 2 +- 17 files changed, 29 insertions(+), 33 deletions(-) diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 00de7ffbca..c36d594bf7 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -55,46 +55,42 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } String maximumMarksString = argumentMap.get(KEY_MAXIMUM_MARKS); if (!Util.isStringInteger(maximumMarksString)) { - int maximumMarksRange = Assessment.getMaximumMarksRange(); throw new TaaException(String.format( MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS, - maximumMarksRange) + Assessment.MINIMUM_MARKS) ); } int maximumMarks = Integer.parseInt(maximumMarksString); - if (!Assessment.isMaximumMarksWithinRange(maximumMarks)) { - int maximumMarksRange = Assessment.getMaximumMarksRange(); + if (maximumMarks < Assessment.MINIMUM_MARKS) { throw new TaaException(String.format( MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS, - maximumMarksRange) + Assessment.MINIMUM_MARKS) ); } String weightageString = argumentMap.get(KEY_WEIGHTAGE); if (!Util.isStringDouble(weightageString)) { - double[] weightageRange = Assessment.getWeightageRange(); throw new TaaException(String.format( MESSAGE_FORMAT_INVALID_WEIGHTAGE, - weightageRange[0], - weightageRange[1]) + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) ); } double weightage = Double.parseDouble(weightageString); if (!Assessment.isWeightageWithinRange(weightage)) { - double[] weightageRange = Assessment.getWeightageRange(); throw new TaaException(String.format( MESSAGE_FORMAT_INVALID_WEIGHTAGE, - weightageRange[0], - weightageRange[1]) + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) ); } diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index 82f3373674..53752a396b 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -15,7 +15,7 @@ public class AddModuleCommand extends Command { private static final String MESSAGE_INVALID_MODULE_CODE = "Invalid module code."; private static final String MESSAGE_MODULE_EXISTS = "Module already exists."; - private static final String MESSAGE_FORMAT_ADD_MODULE_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_ADD_MODULE_USAGE = "%s %s/ [%s/]"; private static final String MESSAGE_FORMAT_MODULE_ADDED = "Module added:\n %s\nThere are %d modules in the list."; public AddModuleCommand(String argument) { @@ -36,7 +36,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getUsageMessage()); } - if (!checkArguments()) { + if (!argumentMap.containsKey(KEY_MODULE_CODE)) { throw new TaaException(getMissingArgumentMessage()); } @@ -46,16 +46,16 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(MESSAGE_INVALID_MODULE_CODE); } - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module != null) { throw new TaaException(MESSAGE_MODULE_EXISTS); } - assert argumentMap.containsKey(KEY_MODULE_NAME); - String name = argumentMap.get(KEY_MODULE_NAME); + String name = argumentMap.getOrDefault(KEY_MODULE_NAME, ""); module = new Module(moduleCode, name); moduleList.addModule(module); + TaaLogger.LOGGER.logInfo(String.format("Added module: %s", module)); storage.save(moduleList); diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index 2235903412..7241fc5d94 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -41,7 +41,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index ac52a7e1e5..d87a150587 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -46,7 +46,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/DeleteAssessmentCommand.java b/src/main/java/taa/command/DeleteAssessmentCommand.java index 902f1cc639..e340d2e71f 100644 --- a/src/main/java/taa/command/DeleteAssessmentCommand.java +++ b/src/main/java/taa/command/DeleteAssessmentCommand.java @@ -39,7 +39,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/DeleteAttendanceCommand.java b/src/main/java/taa/command/DeleteAttendanceCommand.java index 46e2088e35..7d4da7e37b 100644 --- a/src/main/java/taa/command/DeleteAttendanceCommand.java +++ b/src/main/java/taa/command/DeleteAttendanceCommand.java @@ -48,7 +48,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/DeleteMarkCommand.java b/src/main/java/taa/command/DeleteMarkCommand.java index 75d45b55d9..df1ec2318a 100644 --- a/src/main/java/taa/command/DeleteMarkCommand.java +++ b/src/main/java/taa/command/DeleteMarkCommand.java @@ -38,7 +38,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getMissingArgumentMessage()); } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index b304f8afd0..8a1587abce 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -40,7 +40,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } @@ -53,7 +53,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc StudentList studentList = module.getStudentList(); assert studentIndex >= 0 && studentIndex < module.getStudentList().getSize(); - Student student = studentList.deleteStudent(studentIndex); + Student student = studentList.deleteStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } diff --git a/src/main/java/taa/command/EditMarkCommand.java b/src/main/java/taa/command/EditMarkCommand.java index d6b29e3138..5485f22bfa 100644 --- a/src/main/java/taa/command/EditMarkCommand.java +++ b/src/main/java/taa/command/EditMarkCommand.java @@ -42,7 +42,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getMissingArgumentMessage()); } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index b26bb1e01a..6662013b88 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -48,7 +48,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 7dcfa1771e..11af1a8c81 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -43,7 +43,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index bb686cb68a..ba5043678b 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -39,7 +39,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/ListAttendanceCommand.java index d93d6ba968..1b38ceff0f 100644 --- a/src/main/java/taa/command/ListAttendanceCommand.java +++ b/src/main/java/taa/command/ListAttendanceCommand.java @@ -42,7 +42,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index 4979935069..2d850a7cb4 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -45,7 +45,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index 5bf2468b62..c6a86044c8 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -39,7 +39,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index 94f9ac47c0..cbed90f9cd 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -57,7 +57,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 4ccdbabf1f..5365cdc331 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -53,7 +53,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getMissingArgumentMessage()); } String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModule(moduleCode); + Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } From f429ae30ad25c0735e0a26e359ca91565ef58edb Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:15:11 +0800 Subject: [PATCH 159/543] Refactor getModule to getModuleWithCode --- src/main/java/taa/module/ModuleList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index 214926b2a9..725c66b744 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -63,7 +63,7 @@ public Module getModuleAt(int index) { * @param code The module code to search for. * @return A Module object if found, else null. */ - public Module getModule(String code) { + public Module getModuleWithCode(String code) { for (Module module : modules) { if (module.getCode().equals(code)) { return module; From 418cb75349e106b6c3899b64fecc206a35777e64 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:16:10 +0800 Subject: [PATCH 160/543] Remove unnecassary variable --- src/main/java/taa/student/Student.java | 26 +++----------------------- 1 file changed, 3 insertions(+), 23 deletions(-) diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index bdede9eca8..ce64431110 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -11,8 +11,6 @@ * Represents students. */ public class Student implements ClassChecker { - private static final double[] MARKS_RANGE = {0, 100}; - private String id; private String name; private final AttendanceList attendanceList; @@ -25,25 +23,6 @@ public Student(String id, String name) { this.results = new HashMap<>(); } - /** - * Checks if the marks are valid. - * - * @param marks The marks to check. - * @return true if valid, else false. - */ - public static boolean isMarksWithinRange(double marks) { - return (marks >= MARKS_RANGE[0] && marks <= MARKS_RANGE[1]); - } - - /** - * Gets the marks range. - * - * @return A double array of size 2: [0] - Min marks, [1] - Max marks. - */ - public static double[] getMarksRange() { - return MARKS_RANGE; - } - /** * Gets the AttendanceList object associated to the student. * @@ -156,12 +135,13 @@ public boolean verify() { if (id.isEmpty() || name.isEmpty()) { return false; } - //do this in module instead + + /*//do this in module instead for (String assessmentName : results.keySet()) { if (!isMarksWithinRange(results.get(assessmentName))) { return false; } - } + }*/ return true; } From 10f94cea8f37f82a96c55e158170a441487c66b6 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:18:44 +0800 Subject: [PATCH 161/543] Refactor deleteStudent to deleteStudentAt --- src/main/java/taa/student/StudentList.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index b60dc5d683..14d4ad4dad 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -58,12 +58,12 @@ public void addStudent(Student student) { } /** - * Deletes a student from the student list. + * Deletes a student with a particular index from the student list. * * @param index The index of the student. * @return A Student object if successfully deleted, else null. */ - public Student deleteStudent(int index) { + public Student deleteStudentAt(int index) { if (isValidIndex(index)) { return students.remove(index); } From 93ba814090d8b5f6f534efcdb61ef16467a9f97b Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:19:46 +0800 Subject: [PATCH 162/543] Allow module without name and check for invalid marks for students --- src/main/java/taa/module/Module.java | 43 ++++++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index f8fc9924cb..2850e2967a 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -1,9 +1,14 @@ package taa.module; import taa.ClassChecker; +import taa.assessment.Assessment; import taa.assessment.AssessmentList; +import taa.student.Student; import taa.student.StudentList; +import java.util.ArrayList; +import java.util.HashMap; + public class Module implements ClassChecker { private String code; private String name; @@ -25,6 +30,14 @@ public String getName() { return name; } + public void setCode(String code) { + this.code = code; + } + + public void setName(String name) { + this.name = name; + } + /** * Gets the StudentList object associated to the module. * @@ -49,7 +62,7 @@ public String toString() { return code; } - return String.format("%s (%s)", code, name); + return String.format("%s - %s", code, name); } /** @@ -59,7 +72,7 @@ public String toString() { */ @Override public boolean verify() { - if (code.isEmpty() || name.isEmpty()) { + if (code.isEmpty()) { return false; } @@ -71,6 +84,32 @@ public boolean verify() { return false; } + HashMap assessmentMap = new HashMap<>(); + for (Assessment assessment : assessmentList.getAssessments()) { + assessmentMap.put(assessment.getName(), assessment); + } + + for (Student student : studentList.getStudents()) { + ArrayList invalidMarks = new ArrayList<>(); + HashMap results = student.getResults(); + for (String assessmentName : results.keySet()) { + if (!assessmentMap.containsKey(assessmentName)) { + invalidMarks.add(assessmentName); + continue; + } + + Assessment assessment = assessmentMap.get(assessmentName); + double marks = results.get(assessmentName); + if (!assessment.isMarksValid(marks)) { + invalidMarks.add(assessmentName); + } + } + + for (String assessmentName : invalidMarks) { + student.deleteMark(assessmentName); + } + } + return true; } } From ef45feedfba1133f4dd852e8f1d0e9855c7fc705 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:20:42 +0800 Subject: [PATCH 163/543] Add delete and edit module features --- src/main/java/taa/Parser.java | 10 +++ .../java/taa/command/DeleteModuleCommand.java | 54 ++++++++++++++ .../java/taa/command/EditModuleCommand.java | 73 +++++++++++++++++++ src/main/java/taa/command/HelpCommand.java | 28 +++---- src/main/java/taa/module/ModuleList.java | 12 +++ .../taa/assessment/AssessmentListTest.java | 10 +-- 6 files changed, 168 insertions(+), 19 deletions(-) create mode 100644 src/main/java/taa/command/DeleteModuleCommand.java create mode 100644 src/main/java/taa/command/EditModuleCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 4e1788c366..2089ca7921 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -7,8 +7,10 @@ import taa.command.Command; import taa.command.DeleteAssessmentCommand; import taa.command.DeleteMarkCommand; +import taa.command.DeleteModuleCommand; import taa.command.DeleteStudentCommand; import taa.command.EditMarkCommand; +import taa.command.EditModuleCommand; import taa.command.EditStudentCommand; import taa.command.ExitCommand; import taa.command.FindStudentCommand; @@ -56,6 +58,14 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new AddModuleCommand(argument); break; + case Command.COMMAND_EDIT_MODULE: + command = new EditModuleCommand(argument); + break; + + case Command.COMMAND_DELETE_MODULE: + command = new DeleteModuleCommand(argument); + break; + case Command.COMMAND_ADD_STUDENT: command = new AddStudentCommand(argument); break; diff --git a/src/main/java/taa/command/DeleteModuleCommand.java b/src/main/java/taa/command/DeleteModuleCommand.java new file mode 100644 index 0000000000..527e9b0c65 --- /dev/null +++ b/src/main/java/taa/command/DeleteModuleCommand.java @@ -0,0 +1,54 @@ +package taa.command; + +import taa.Ui; +import taa.exception.TaaException; +import taa.module.Module; +import taa.module.ModuleList; +import taa.storage.Storage; + +public class DeleteModuleCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String[] DELETE_MODULE_ARGUMENT_KEYS = {KEY_MODULE_CODE}; + + private static final String MESSAGE_FORMAT_DELETE_MODULE_USAGE = "%s %s/"; + private static final String MESSAGE_FORMAT_DELETE_FAILED = "Fail to delete module:\n %s"; + private static final String MESSAGE_FORMAT_MODULE_DELETED = "Module deleted:\n %s"; + + public DeleteModuleCommand(String argument) { + super(argument, DELETE_MODULE_ARGUMENT_KEYS); + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModuleWithCode(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + + String message; + boolean isSuccessful = moduleList.deleteModule(module); + if (isSuccessful) { + message = String.format(MESSAGE_FORMAT_MODULE_DELETED, module); + } else { + message = String.format(MESSAGE_FORMAT_DELETE_FAILED, module); + } + + storage.save(moduleList); + + ui.printMessage(message); + } + + @Override + protected String getUsage() { + return String.format(MESSAGE_FORMAT_DELETE_MODULE_USAGE, COMMAND_DELETE_MODULE, KEY_MODULE_CODE); + } +} diff --git a/src/main/java/taa/command/EditModuleCommand.java b/src/main/java/taa/command/EditModuleCommand.java new file mode 100644 index 0000000000..d04a0fd38e --- /dev/null +++ b/src/main/java/taa/command/EditModuleCommand.java @@ -0,0 +1,73 @@ +package taa.command; + +import taa.Ui; +import taa.exception.TaaException; +import taa.module.Module; +import taa.module.ModuleList; +import taa.storage.Storage; + +public class EditModuleCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_NEW_MODULE_CODE = "nc"; + private static final String KEY_NEW_MODULE_NAME = "n"; + private static final String[] EDIT_MODULE_ARGUMENT_KEYS = { + KEY_MODULE_CODE, + KEY_NEW_MODULE_CODE, + KEY_NEW_MODULE_NAME + }; + + private static final String MESSAGE_FORMAT_EDIT_MODULE_USAGE = "%s %s/ " + + "[%s/ | %s/]"; + private static final String MESSAGE_FORMAT_MODULE_EDITED = "Module edited:\n %s"; + + public EditModuleCommand(String argument) { + super(argument, EDIT_MODULE_ARGUMENT_KEYS); + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + boolean hasModuleCode = argumentMap.containsKey(KEY_MODULE_CODE); + boolean hasNewModuleCode = argumentMap.containsKey(KEY_NEW_MODULE_CODE); + boolean hasNewModuleName = argumentMap.containsKey(KEY_NEW_MODULE_NAME); + boolean hasNecessaryArguments = hasModuleCode && (hasNewModuleCode || hasNewModuleName); + if (!hasNecessaryArguments) { + throw new TaaException(getMissingArgumentMessage()); + } + + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModuleWithCode(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + + assert (argumentMap.containsKey(KEY_NEW_MODULE_CODE) || argumentMap.containsKey(KEY_NEW_MODULE_NAME)); + String newModuleCode = argumentMap.getOrDefault(KEY_NEW_MODULE_CODE, null); + if (newModuleCode != null) { + module.setCode(newModuleCode); + } + + String newModuleName = argumentMap.getOrDefault(KEY_NEW_MODULE_NAME, null); + if (newModuleName != null) { + module.setName(newModuleName); + } + + storage.save(moduleList); + + ui.printMessage(String.format(MESSAGE_FORMAT_MODULE_EDITED, module)); + } + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_EDIT_MODULE_USAGE, + COMMAND_EDIT_MODULE, + KEY_MODULE_CODE, + KEY_NEW_MODULE_CODE, + KEY_NEW_MODULE_NAME + ); + } +} diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index 372a4c6045..6c284a7f96 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -9,25 +9,27 @@ public class HelpCommand extends Command { private static final String MESSAGE_FORMAT_OUTPUT = "Available commands:\n%s"; private static final Command[] commands = { - new AddAssessmentCommand(""), + new ListModulesCommand(""), new AddModuleCommand(""), + new EditModuleCommand(""), + new DeleteModuleCommand(""), + new ListStudentsCommand(""), new AddStudentCommand(""), - new SetAttendanceCommand(""), - new SetMarksCommand(""), - new AverageMarksCommand(""), - new DeleteStudentCommand(""), - new DeleteAssessmentCommand(""), - new DeleteMarkCommand(""), - new EditMarkCommand(""), new EditStudentCommand(""), + new DeleteStudentCommand(""), new FindStudentCommand(""), - new ExitCommand(""), - new HelpCommand(""), new ListAssessmentsCommand(""), - new ListAttendanceCommand(""), + new AddAssessmentCommand(""), + new DeleteAssessmentCommand(""), new ListMarksCommand(""), - new ListModulesCommand(""), - new ListStudentsCommand("") + new SetMarksCommand(""), + new EditMarkCommand(""), + new DeleteMarkCommand(""), + new AverageMarksCommand(""), + new ListAttendanceCommand(""), + new SetAttendanceCommand(""), + new ExitCommand(""), + new HelpCommand("") }; public HelpCommand(String argument) { diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index 725c66b744..7083c923ea 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -73,6 +73,18 @@ public Module getModuleWithCode(String code) { return null; } + /** + * Deletes a particular module from the list. + * + * @param module The module object to delete. + * @return true if successfully removed, else false. + */ + public boolean deleteModule(Module module) { + assert module != null; + + return modules.remove(module); + } + @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(); diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index 8522afdcc0..5d7aec6adb 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -8,8 +8,6 @@ import taa.module.ModuleList; import taa.storage.Storage; -import java.util.ArrayList; - import static org.junit.jupiter.api.Assertions.assertEquals; class AssessmentListTest { @@ -34,11 +32,11 @@ void addAssessment_userInput_assessmentAddedCorrectly() throws TaaException { command1.execute(moduleList, ui, storage); Command command2 = Parser.parseUserInput(assessmentInput); command2.execute(moduleList, ui, storage); - assertEquals("Midterms", moduleList.getModule("cs2113t") + assertEquals("Midterms", moduleList.getModuleWithCode("cs2113t") .getAssessmentList().getAssessment("Midterms").getName()); - assertEquals(50, moduleList.getModule("cs2113t") + assertEquals(50, moduleList.getModuleWithCode("cs2113t") .getAssessmentList().getAssessment("Midterms").getMaximumMarks()); - assertEquals(20, moduleList.getModule("cs2113t") + assertEquals(20, moduleList.getModuleWithCode("cs2113t") .getAssessmentList().getAssessment("Midterms").getWeightage()); } @@ -66,6 +64,6 @@ void deleteAssessment_userInput_emptyAssessmentList() throws TaaException { command2.execute(moduleList, ui, storage); Command command3 = Parser.parseUserInput(deleteAssessmentInput); command3.execute(moduleList, ui, storage); - assertEquals(new AssessmentList().getSize(), moduleList.getModule("cs2113t").getAssessmentList().getSize()); + assertEquals(new AssessmentList().getSize(), moduleList.getModuleWithCode("cs2113t").getAssessmentList().getSize()); } } From 7bf7df39aeb8b5acacba8400ac5bf4f6e2602db9 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:29:20 +0800 Subject: [PATCH 164/543] Add assertion within Module.verify() --- src/main/java/taa/module/Module.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index 2850e2967a..f985156cf8 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -76,13 +76,7 @@ public boolean verify() { return false; } - if (!studentList.verify()) { - return false; - } - - if (!assessmentList.verify()) { - return false; - } + assert (assessmentList != null && studentList != null); HashMap assessmentMap = new HashMap<>(); for (Assessment assessment : assessmentList.getAssessments()) { From bff7320c5605ff35301c427f70d300d096b0771f Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:29:26 +0800 Subject: [PATCH 165/543] Fix checkstyle --- src/test/java/taa/assessment/AssessmentListTest.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index 5d7aec6adb..fc1d269630 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -64,6 +64,9 @@ void deleteAssessment_userInput_emptyAssessmentList() throws TaaException { command2.execute(moduleList, ui, storage); Command command3 = Parser.parseUserInput(deleteAssessmentInput); command3.execute(moduleList, ui, storage); - assertEquals(new AssessmentList().getSize(), moduleList.getModuleWithCode("cs2113t").getAssessmentList().getSize()); + assertEquals( + new AssessmentList().getSize(), + moduleList.getModuleWithCode("cs2113t").getAssessmentList().getSize() + ); } } From a425690ab110ef76a62b0d31707ed3d698210b31 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:31:46 +0800 Subject: [PATCH 166/543] Ignore client side file --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index d5709d3332..e18ae7a9a2 100644 --- a/.gitignore +++ b/.gitignore @@ -20,3 +20,4 @@ text-ui-test/ACTUAL.TXT data/taa_data.json text-ui-test/data/taa_data.json taa.log* +src/main/java/META-INF/MANIFEST.MF From b1035963cf693378f1c349b3c715a5f7b577a73f Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 22 Oct 2021 15:32:59 +0800 Subject: [PATCH 167/543] Update automatic testing files --- text-ui-test/EXPECTED.TXT | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 897b7bc692..9fabcd7265 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -7,12 +7,12 @@ There are no modules in the list. ------------------------------------------------------------ $ ------------------------------------------------------------ Module added: - CS2113T (Software Engineering and Object-oriented Programming) + CS2113T - Software Engineering and Object-oriented Programming There are 1 modules in the list. ------------------------------------------------------------ $ ------------------------------------------------------------ Module list: -1. CS2113T (Software Engineering and Object-oriented Programming) +1. CS2113T - Software Engineering and Object-oriented Programming ------------------------------------------------------------ $ ------------------------------------------------------------ An exception has occurred: From e623b90c4dd31652bb8a96cf889dd0bdb9b20e2b Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Fri, 22 Oct 2021 20:09:46 +0800 Subject: [PATCH 168/543] update developers guide --- docs/DeveloperGuide.md | 61 ++++++++++++++++++++++++++++++++---------- 1 file changed, 47 insertions(+), 14 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 8fc5334f55..67083be36f 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -31,7 +31,8 @@ The _Architecture Diagram_ shown above explains the high-level design of the App * Defines how a command is to be executed. * `Model` * Represents a collection of classes that holds the data of the application in-memory. - * Includes: `ModuleList`, `Modules`, `StudentList` , `Student`, `AssessmentList` , `Assessment`, `AttendanceList` , `Attendance` + * Includes: `ModuleList`, `Modules`, `StudentList` , `Student`, `AssessmentList` , `Assessment`, `AttendanceList` +, `Attendance` * `Storage` * Handles data storage operations (e.g. Reading from and writing to data file). * `Commons` @@ -62,20 +63,48 @@ module internally as an ArrayList `modules`.
* `ModuleList#getModule(code:String)` - Returns a module with a particular code. * `ModuleList#isValidIndex(index:int)` - Checks if an index is valid w.r.t the `modules` ArrayList. * `ModuleList#addModule(module:Module)` - Adds a module to the `modules` ArrayList. -* `ModuleList#getModuleAt(index:int)` - Returns a `Module` object at the specified `index` within the `modules` ArrayList. +* `ModuleList#getModuleAt(index:int)` - Returns a `Module` object at the specified `index` within the `modules` +ArrayList. Below is an example scenario of how the add module feature behaves at each step:
-* Step 1 - The user executes `add_module c/CS2113T n/Software Engineering` to add a module. The `add_module` command calls -the `AddModuleCommand#execute` method. Within `AddModuleCommand#execute`, `ModuleList#getModule("CS2113T")` is called to -ensure that there is no existing module with code `CS2113T`. +* Step 1 - The user executes `add_module c/CS2113T n/Software Engineering` to add a module. The `add_module` command +calls the `AddModuleCommand#execute` method. Within `AddModuleCommand#execute`, `ModuleList#getModule("CS2113T")` is +called to ensure that there is no existing module with code `CS2113T`. * Step 2 - If no existing module with code `CS2113T` is found, a new `Module` object with code and name set to `CS2113T` -and `Software Engineering` set as its code and name respectively. Then, `ModuleList#addModule` is called to add the newly -created `Module` object into the `modules` ArrayList within `ModuleList`. +and `Software Engineering` respectively. Then, `ModuleList#addModule` is called to add the newly created `Module` +object into the `modules` ArrayList within `ModuleList`. + +### Add student +The add student mechanism is facilitated by `AddStudentCommand`. It extends `Command` and uses `StudentList` which +stores student internally as an ArrayList `students`. +
+ +`AddStudentCommand` implements the following methods: +* `AddStudentCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Performs operations for the command. + +`StudentList` implements the following methods: +* `StudentList#getSize()` - Returns the no. of students currently in the list. +* `StudentList#getStudents()` - Returns an ArrayList containing all the students. +* `StudentList#getStudentAt(index:int)` - Returns a student with the particular index. +* `StudentList#isValidIndex(index:int)` - Checks if an index is valid w.r.t the `students` ArrayList. +* `StudentList#addStudent(student:Student)` - Adds a student to the `students` ArrayList. +* `StudentList#deleteStudent(index:int)` - Deletes the `student` object at the specified `index` within the `students` +ArrayList. +* `StudentList#findStudent(keyword:String)` - Returns an ArrayList of students containing the keyword + +Below is an example scenario of how the add student feature behaves at each step:
+* Step 1 - The user executes `add_student c/CS2113T i/a0217978j n/jonny` to add a module. The `add_student` command +calls the `AddStudentCommand#execute` method. Within `AddStudentCommand#execute`, `ModuleList#getModule("CS2113T")` is +called to ensure that there is an existing module with code `CS2113T`. +* Step 2 - If an existing module with code `CS2113T` is found, a new `Student` object with id and name set to +`a0217978j` and `jonny` respectively. Then, `StudentList#addModule` is called to add the newly created `Student` +object into the `students` ArrayList within `StudentList`. ### Set attendance The set attendance mechanism is facilitated by SetAttendanceCommand. It extends `Command` and uses `AttendanceList` which stores a student's lessons attendance as an -ArrayList `attendances`.
+ArrayList `attendances`. +
`SetAttendanceCommand` implements the following methods: * `SetAttendanceCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Performs operations for the command. @@ -86,16 +115,20 @@ ArrayList `attendances`.
* `AttendanceList#getAttendance(lessonNumber:String)` - Returns an attendance with a particular lesson number. * `AttendanceList#isValidIndex(index:int)` - Checks if an index is valid w.r.t the `attendances` ArrayList. * `AttendanceList#addAttendance(attendance:Attendance)` - Adds an attendance to the `attendances` ArrayList. -* `AttendnaceList#getAttendnaceIndex(lessonNumInput:String)` - Returns the attendance index in the `attendances` ArrayList. +* `AttendnaceList#getAttendnaceIndex(lessonNumInput:String)` - Returns the attendance index in the `attendances` +ArrayList. * `AttendanceList#deleteAttendance(lessonNumInput:String)` - Deletes an attendance with a particular lesson number. -* `AttendanceList#sortAttendances` - Sorts the attendance in the `attendances` ArrayList in ascending order based on lesson number. +* `AttendanceList#sortAttendances` - Sorts the attendance in the `attendances` ArrayList in ascending order based on +lesson number. Below is an example scenario of how the set attendance feature behaves at each step: * Step 1 - The user executes `set_attendance c/CS2113T s/1 l/1 p/1` to set an attendance to `Present` for student at -index `1`, lesson number `1` to set a student's attendance for a lesson. The `set_attendance` command calls the `SetAttendanceCommand#execute` method. Within -`SetAttendanceCommand#execute`, `AttendanceList#getAttendance("1")` is called to ensure that there is no existing attendance with the +index `1`, lesson number `1` to set a student's attendance for a lesson. The `set_attendance` command calls the +`SetAttendanceCommand#execute` method. Within `SetAttendanceCommand#execute`, `AttendanceList#getAttendance("1")` is +called to ensure that there is no existing attendance with the lesson number `1`for student at index `1`. -* Step 2 - If no existing attendance object with lesson number `1` for student at index `1` is found, a new `Attendance` object +* Step 2 - If no existing attendance object with lesson number `1` for student at index `1` is found, a new +`Attendance` object with lesson number `1` and attendance record `Present` is set as its lesson number and attendance record respectively. Then, `AttendanceList#addAttendance` is called to add the newly created `Attendance` object into the `attendances` ArrayList within `AttendanceList`. @@ -103,7 +136,7 @@ ArrayList within `AttendanceList`. ### Set marks -he set marks mechanism is facilitated by `SetMarksCommand`. It extends `Command`.
+The set marks mechanism is facilitated by `SetMarksCommand`. It extends `Command`.
## Product scope ### Target user profile From 9f32cf5207a632e03cb6e9599f0177a7fada883b Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Sat, 23 Oct 2021 00:29:28 +0800 Subject: [PATCH 169/543] update UGDG --- docs/DeveloperGuide.md | 12 +-- docs/UserGuide.md | 101 ++++++++++-------- .../java/taa/command/SetMarksCommand.java | 11 +- 3 files changed, 70 insertions(+), 54 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 67083be36f..55eeb6100d 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -141,15 +141,15 @@ The set marks mechanism is facilitated by `SetMarksCommand`. It extends `Command ## Product scope ### Target user profile -* Teaching assistant who has a need to manage a significant number of students and their information -* Prefers desktop app over other types -* Can type fast -* Prefers typing to mouse interactions -* Reasonably comfortable using CLI apps +* Teaching assistant who has a need to manage a significant number of students and their information. +* Prefers desktop app over other types of apps. +* Can type fast. +* Prefers typing to mouse interactions. +* Reasonably comfortable using CLI apps. ### Value proposition -* Manage student information faster than a typical mouse/GUI driven app +* Manage student information faster than a typical mouse/GUI driven app. ## User Stories diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 6b7799ece0..5abdb64d8b 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -22,23 +22,23 @@ If you can type fast, TAA can help keep track of your modules and students faste ## Quick Start 1. Ensure that you have Java 11 or above installed. -2. Down the latest version of `Taa.jar` from [here](https://github.com/AY2122S1-CS2113T-F12-3/tp/releases). +2. Download the latest version of `Taa.jar` from [here](https://github.com/AY2122S1-CS2113T-F12-3/tp/releases). 3. Create a new folder and place `Taa.jar` inside. 4. Open Command Prompt/Terminal and navigate to the folder containing `Taa.jar`. -5. Run `java -jar Taa.jar` to start the app. -6. Enter `help` to view a list of available commands. See [Features](#features) for more information. +5. Run `java -jar Taa.jar` in Command Prompt/Terminal to start the app. +6. Enter `help` to display the list of available commands. See [Features](#features) for more information. ## Features ### Viewing help: `help` -Displays the available commands and how to use them +Displays the list of available commands and how to use them. Format: `help`
### Listing all modules: `list_modules` -Shows a list of all modules in the module list. +Displays the list of all modules in the module list. Format: `list_modules` @@ -49,7 +49,7 @@ Adds a module to the module list. Format: `add_module c/ n/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `MODULE_NAME` refers to the name of the module. +* `MODULE_NAME` refers to the name of the module to be added. Examples: * `add_module c/CS2113T n/Software Engineering and Object-oriented Programming` @@ -62,8 +62,8 @@ Adds a student to a particular module Format: `add_student c/ i/ n/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_ID` refers to the ID of the student (e.g. A0217978J) -* `STUDENT_NAME` refers to the name of the student (e.g. Jon Lim) +* `STUDENT_ID` refers to the ID of the student (e.g. A0217978J). +* `STUDENT_NAME` refers to the name of the student (e.g. Jon Lim). Examples: * `add_student c/cs2113t i/a0212345x n/Jon Lim` @@ -76,9 +76,9 @@ Edits student information from a particular module Format: `edit_student c/ s/ i/ n/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the module -* `STUDENT_ID` refers to the updated ID of the student (e.g. A0217978J) -* `STUDENT_NAME` refers to the updated name of the student (e.g. Jon Limbs) +* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +* `STUDENT_ID` refers to the updated ID of the student (e.g. A0217978J). +* `STUDENT_NAME` refers to the updated name of the student (e.g. Jon Limbs). Examples: * `edit_student c/cs2113t s/1 i/a03452345x n/Jon Lim` @@ -87,11 +87,11 @@ Examples:
### Deleting student information: `delete_student` -Deletes student information from a particular module +Deletes student information from a particular module. Format: `delete_student c/ s/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the module +* `STUDENT_INDEX` refers to the index of the student in the student list of the module. Examples: * `delete_student c/cs2113t s/1` @@ -111,11 +111,11 @@ Examples:
### Find students in a module given a keyword: `find_student` -Displays all students in the module matching the keyword along with their index +Displays all students in the module matching the keyword along with their index. Format: `find_student c/ k/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `KEYWORD` refers to the keyword used to search the student list +* `KEYWORD` refers to the keyword used to search the student list of the module. Examples: * `find_student c/CS2113T k/123` @@ -123,26 +123,22 @@ Examples:
-### Listing marks for an assessment: `list_marks` -Lists all students and their marks for an assessment. +### Set attendance for a particular lesson for a student: `set_attendance` +Sets a student's attendance for a lesson -Format: `list_marks c/ a/` +Format: `set_attendance c/ l/ p/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `ASSESSMENT_NAME` refers to the name of the assessment whose marks are to be listed. - -Examples: -* `list_marks c/CS2113T a/Midterms` -* `list_marks c/CS2101 a/Oral Presentation` - -
+* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +* `LESSON_NUMBER` refers to the lesson number +* `PRESENT` refers to the whether a student is present. (1 for present, 0 for not present) ### Setting marks for a student's assessment: `set_marks` Add a student's marks for an assessment. Format: `set_marks c/ s/ a/ m/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the module. -* `ASSESSMENT_NAME` refers to the name of the assessment that is to be marked. +* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +* `ASSESSMENT_NAME` refers to the name of the particular assessment. * `MARKS` refers to the marks given for the assessment. Examples: @@ -156,8 +152,8 @@ Edits a student's mark for an assessment. Format: `edit_mark c/ s/ a/ m/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the module. -* `ASSESSMENT_NAME` refers to the name of the assessment that is to be remarked. +* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +* `ASSESSMENT_NAME` refers to the name of the particular assessment. * `NEW_MARKS` refers to the new marks to be given for the assessment. Examples: @@ -171,8 +167,8 @@ Deletes a student's marks for an assessment. Format: `set_marks c/ s/ a/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the module. -* `ASSESSMENT_NAME` refers to the name of the assessment that is to be marked. +* `STUDENT_INDEX` refers to the index of the student in student list of the module. +* `ASSESSMENT_NAME` refers to the name of the particular assessment. Examples: * `delete_mark c/CS2113T s/1 a/Midterms` @@ -181,11 +177,11 @@ Examples:
### Finding average marks for an assessment: `average_marks` -Finds the average marks for an assessment. +Computes and prints the average marks for an assessment. Format: `set_marks c/ a/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `ASSESSMENT_NAME` refers to the name of the assessment that is to be marked. +* `ASSESSMENT_NAME` refers to the name of the particular assessment. Examples: * `average_marks c/CS2113T a/Midterms` @@ -193,6 +189,19 @@ Examples:
+### Listing marks for an assessment: `list_marks` +Lists all students and their marks for an assessment. + +Format: `list_marks c/ a/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `ASSESSMENT_NAME` refers to the name of the assessment whose marks are to be listed. + +Examples: +* `list_marks c/CS2113T a/Midterms` +* `list_marks c/CS2101 a/Oral Presentation` + +
+ ### Exit the program: `exit` Exits the program @@ -210,24 +219,24 @@ Format: `exit` Command | Format and Examples | ------ | --------------- | -add_assessment | `add_assessment c/ n/ m/ w/`
e.g. `hi` -add_module | `add_module c/ n/`
e.g. `add_module c/CS2113T n/Software Engineering and Object-oriented Programming` -add_student | `add_student c/ i/ n/`
e.g. `add_student c/cs2113t i/a0212345x n/Jon Lim` -set_attendance | `set_attendance c/ s/ l/ p/`
e.g. `hi` +add_module | `add_module c/ n/`
e.g.`add_module c/CS2113T n/Software Engineeringand Object-oriented Programming` +add_student | `add_student c/ i/ n/`
e.g. `add_student c/CS2113T i/a0212345x n/Jon Lim` +add_assessment | `add_assessment c/ n/ m/ w/`
e.g. `add_assessment c/CS2113T n/test m/100 w/20 ` +set_attendance | `set_attendance c/ s/ l/ p/`
e.g. `set_attendance c/CS2113T s/1 l/1 p/1` set_marks | `set_marks c/ s/ a/ m/`
e.g. `set_marks c/CS2113T s/1 a/Midterms m/70.6` -average_marks | `average_marks c/ a/`
e.g. `average_marks c/CS2113T a/Midterms` delete_student | `delete_student c/ s/`
e.g. `delete_student c/cs2113t s/1` -delete_assessment | `delete_assessment c/ n/`
e.g. `hi` +delete_assessment | `delete_assessment c/ n/`
e.g. `delete_assessment c/CS2113T n/finals` delete_mark | `delete_mark c/ s/ a/`
e.g. `delete_mark c/CS2113T s/1 a/Midterms` edit_mark | `edit_mark c/ s/ a/ m/`
e.g. `edit_mark c/CS2113T s/1 a/Midterms m/80.6` -edit_student | `edit_student c/ s/ i/ n/`
e.g. `hi` -find_student | `find_student c/ k/`
e.g. `find_student c/CS2113T k/123` -exit | `exit` -help | `help` -list_assessments | `list_assessments c/`
e.g. `hi` -list_attendance | `list_attendance c/ s/`
e.g. `hi` -list_marks | `list_marks c/ a/`
e.g. `list_marks c/CS2113T a/Midterms` +edit_student | `edit_student c/ s/ i/ n/`
e.g. `edit_student c/CS2113T s/1 i/12345 n/jon geh` list_modules | `list_modules` list_students | `list_students c/`
e.g. `list_students c/CS2113T` +list_attendance | `list_attendance c/ s/`
e.g. `list_attendance c/CS2113T s/1` +list_assessments | `list_assessments c/`
e.g. `list_assessments c/CS2113T` +list_marks | `list_marks c/ a/`
e.g. `list_marks c/CS2113T a/Midterms` +find_student | `find_student c/ k/`
e.g. `find_student c/CS2113T k/123` +average_marks | `average_marks c/ a/`
e.g. `average_marks c/CS2113T a/Midterms` +help | `help` +exit | `exit` diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 01b1c6c434..7ac108736d 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -46,24 +46,30 @@ public SetMarksCommand(String argument) { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } + if (!checkArguments()) { throw new TaaException(getMissingArgumentMessage()); } + String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModule(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); int studentIndex = Integer.parseInt(studentIndexInput) - 1; + StudentList studentList = module.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null || !Util.isStringInteger(studentIndexInput)) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } + AssessmentList assessmentList = module.getAssessmentList(); String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = assessmentList.getAssessment(assessmentName); @@ -73,11 +79,12 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc if (student.marksExist(assessmentName)) { throw new TaaException(MESSAGE_ALREADY_MARKED); } + String marksInput = argumentMap.get(KEY_MARKS); double marks = Double.parseDouble(marksInput); - double maximumMarks = assessment.getMaximumMarks(); + double maxMarks = assessment.getMaximumMarks(); if ((!Util.isStringDouble(marksInput)) || !(assessment.isMarksValid(marks))) { - throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, 0, maximumMarks)); + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, 0, maxMarks)); } setMarks(ui, student, assessmentName, marks); storage.save(moduleList); From 99c0e722327e95de0029ec55a88cff4805961108 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Sat, 23 Oct 2021 00:33:10 +0800 Subject: [PATCH 170/543] update UG --- docs/UserGuide.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 5abdb64d8b..0acda30c78 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -110,7 +110,7 @@ Examples:
-### Find students in a module given a keyword: `find_student` +### Finding students in a module given a keyword: `find_student` Displays all students in the module matching the keyword along with their index. Format: `find_student c/ k/` @@ -123,7 +123,7 @@ Examples:
-### Set attendance for a particular lesson for a student: `set_attendance` +### Setting attendance for a particular lesson for a student: `set_attendance` Sets a student's attendance for a lesson Format: `set_attendance c/ l/ p/` @@ -133,7 +133,7 @@ Format: `set_attendance c/ l/ p/ s/ a/ m/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). @@ -202,7 +202,7 @@ Examples:
-### Exit the program: `exit` +### Exiting the program: `exit` Exits the program Format: `exit` From 194fbe588eb5356fcf1798114b75cbc1ac050bef Mon Sep 17 00:00:00 2001 From: rachel Date: Sat, 23 Oct 2021 02:05:02 +0800 Subject: [PATCH 171/543] Add and document edit_assessment command. Test the command with assertions and exceptions too. --- src/main/java/taa/Parser.java | 29 +--- src/main/java/taa/assessment/Assessment.java | 12 ++ .../taa/command/AddAssessmentCommand.java | 2 +- src/main/java/taa/command/Command.java | 1 + .../taa/command/EditAssessmentCommand.java | 142 ++++++++++++++++++ src/main/java/taa/command/HelpCommand.java | 1 + .../taa/assessment/AssessmentListTest.java | 37 ++++- 7 files changed, 197 insertions(+), 27 deletions(-) create mode 100644 src/main/java/taa/command/EditAssessmentCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 2089ca7921..87152d731b 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,29 +1,6 @@ package taa; -import taa.command.AddAssessmentCommand; -import taa.command.AddModuleCommand; -import taa.command.AddStudentCommand; -import taa.command.AverageMarksCommand; -import taa.command.Command; -import taa.command.DeleteAssessmentCommand; -import taa.command.DeleteMarkCommand; -import taa.command.DeleteModuleCommand; -import taa.command.DeleteStudentCommand; -import taa.command.EditMarkCommand; -import taa.command.EditModuleCommand; -import taa.command.EditStudentCommand; -import taa.command.ExitCommand; -import taa.command.FindStudentCommand; -import taa.command.HelpCommand; -import taa.command.ListAssessmentsCommand; -import taa.command.ListAttendanceCommand; -import taa.command.ListMarksCommand; -import taa.command.ListModulesCommand; -import taa.command.ListStudentsCommand; -import taa.command.SetAttendanceCommand; -import taa.command.SetMarksCommand; - -import taa.command.DeleteAttendanceCommand; +import taa.command.*; import taa.exception.TaaException; @@ -94,6 +71,10 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new ListAssessmentsCommand(argument); break; + case Command.COMMAND_EDIT_ASSESSMENT: + command = new EditAssessmentCommand(argument); + break; + case Command.COMMAND_DELETE_ASSESSMENT: command = new DeleteAssessmentCommand(argument); break; diff --git a/src/main/java/taa/assessment/Assessment.java b/src/main/java/taa/assessment/Assessment.java index 1de3c69bc3..ff244df86a 100644 --- a/src/main/java/taa/assessment/Assessment.java +++ b/src/main/java/taa/assessment/Assessment.java @@ -42,6 +42,18 @@ public int getMaximumMarks() { return maximumMarks; } + public void setName(String name) { + this.name = name; + } + + public void setMaximumMarks(int maximumMarks) { + this.maximumMarks = maximumMarks; + } + + public void setWeightage(double weightage) { + this.weightage = weightage; + } + /** * Format the string to print out the assessment. * For Midterms with 20% weightage, diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index c36d594bf7..164ea282b8 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -12,8 +12,8 @@ public class AddAssessmentCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_ASSESSMENT_NAME = "n"; - private static final String KEY_WEIGHTAGE = "w"; private static final String KEY_MAXIMUM_MARKS = "m"; + private static final String KEY_WEIGHTAGE = "w"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { KEY_MODULE_CODE, KEY_ASSESSMENT_NAME, diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 46acf768cc..95e5a3ed67 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -29,6 +29,7 @@ public abstract class Command { public static final String COMMAND_DELETE_ASSESSMENT = "delete_assessment"; public static final String COMMAND_SET_MARKS = "set_marks"; public static final String COMMAND_EDIT_MARK = "edit_mark"; + public static final String COMMAND_EDIT_ASSESSMENT = "edit_assessment"; public static final String COMMAND_DELETE_MARK = "delete_mark"; public static final String COMMAND_HELP = "help"; diff --git a/src/main/java/taa/command/EditAssessmentCommand.java b/src/main/java/taa/command/EditAssessmentCommand.java new file mode 100644 index 0000000000..9903466e8b --- /dev/null +++ b/src/main/java/taa/command/EditAssessmentCommand.java @@ -0,0 +1,142 @@ +package taa.command; + +import taa.Ui; +import taa.assessment.Assessment; +import taa.exception.TaaException; +import taa.module.Module; +import taa.module.ModuleList; +import taa.storage.Storage; +import taa.util.Util; + +public class EditAssessmentCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_ASSESSMENT_NAME = "n"; + private static final String KEY_NEW_ASSESSMENT_NAME = "nn"; + private static final String KEY_NEW_MAXIMUM_MARKS = "m"; + private static final String KEY_NEW_WEIGHTAGE = "w"; + private static final String[] EDIT_ASSESSMENT_ARGUMENT_KEYS = { + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME, + KEY_NEW_ASSESSMENT_NAME, + KEY_NEW_MAXIMUM_MARKS, + KEY_NEW_WEIGHTAGE + }; + + private static final String MESSAGE_FORMAT_EDIT_ASSESSMENT_USAGE = "%s %s/ " + + "%s/ %s/ %s/ %s/"; + private static final String MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE = "Invalid new weightage. " + + "Weightage must be between %,.2f and %,.2f (inclusive)"; + private static final String MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS = "Invalid new maximum marks. " + + "Maximum marks must be larger than %d (inclusive)"; + private static final String MESSAGE_FORMAT_ASSESSMENT_EDITED = "Assessment in %s updated:\n %s"; + + public EditAssessmentCommand(String argument) { + super(argument, EDIT_ASSESSMENT_ARGUMENT_KEYS); + } + + /** + * Executes the edit_assessment command and edits an assessment a particular module. + * The name, maximum marks and weightage of the assessment can be changed. + * Some new values can be missing and the old values of them will not change. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + boolean hasModuleCode = argumentMap.containsKey(KEY_MODULE_CODE); + boolean hasAssessmentName = argumentMap.containsKey(KEY_ASSESSMENT_NAME); + boolean hasNewAssessmentName = argumentMap.containsKey(KEY_NEW_ASSESSMENT_NAME); + boolean hasNewMaximumMarks = argumentMap.containsKey(KEY_NEW_MAXIMUM_MARKS); + boolean hasNewWeightage = argumentMap.containsKey(KEY_NEW_WEIGHTAGE); + boolean hasNecessaryArguments = hasModuleCode && hasAssessmentName && + (hasNewAssessmentName || hasNewMaximumMarks || hasNewWeightage); + if (!hasNecessaryArguments) { + throw new TaaException(getMissingArgumentMessage()); + } + + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModuleWithCode(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + + String name = argumentMap.get(KEY_ASSESSMENT_NAME); + Assessment assessment = module.getAssessmentList().getAssessment(name); + if (assessment == null) { + throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); + } + + assert (argumentMap.containsKey(KEY_NEW_ASSESSMENT_NAME) || argumentMap.containsKey(KEY_NEW_MAXIMUM_MARKS) + || argumentMap.containsKey(KEY_NEW_WEIGHTAGE)) : "a new value to edit should at least exist."; + String newName = argumentMap.getOrDefault(KEY_NEW_ASSESSMENT_NAME, null); + if (newName != null) { + assessment.setName(newName); + } + + String newMaximumMarksString = argumentMap.getOrDefault(KEY_NEW_MAXIMUM_MARKS, null); + if (newMaximumMarksString != null) { + if (!Util.isStringInteger(newMaximumMarksString)) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS, + Assessment.MINIMUM_MARKS) + ); + } + + int newMaximumMarks = Integer.parseInt(newMaximumMarksString); + if (newMaximumMarks < Assessment.MINIMUM_MARKS) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS, + Assessment.MINIMUM_MARKS) + ); + } + assessment.setMaximumMarks(newMaximumMarks); + } + + String newWeightageString = argumentMap.getOrDefault(KEY_NEW_WEIGHTAGE, null); + if (newWeightageString != null) { + if (!Util.isStringDouble(newWeightageString)) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) + ); + } + + double newWeightage = Double.parseDouble(newWeightageString); + if (!Assessment.isWeightageWithinRange(newWeightage)) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) + ); + } + assessment.setWeightage(newWeightage); + } + assert storage != null : "storage should exist."; + storage.save(moduleList); + + assert ui != null : "ui should exist."; + ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_EDITED, moduleCode, + assessment)); + } + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_EDIT_ASSESSMENT_USAGE, + COMMAND_EDIT_ASSESSMENT, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME, + KEY_NEW_ASSESSMENT_NAME, + KEY_NEW_MAXIMUM_MARKS, + KEY_NEW_WEIGHTAGE + ); + } +} diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index 6c284a7f96..c1f967329c 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -20,6 +20,7 @@ public class HelpCommand extends Command { new FindStudentCommand(""), new ListAssessmentsCommand(""), new AddAssessmentCommand(""), + new EditAssessmentCommand(""), new DeleteAssessmentCommand(""), new ListMarksCommand(""), new SetMarksCommand(""), diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index fc1d269630..acea90d726 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -65,8 +65,41 @@ void deleteAssessment_userInput_emptyAssessmentList() throws TaaException { Command command3 = Parser.parseUserInput(deleteAssessmentInput); command3.execute(moduleList, ui, storage); assertEquals( - new AssessmentList().getSize(), - moduleList.getModuleWithCode("cs2113t").getAssessmentList().getSize() + new AssessmentList().getSize(), + moduleList.getModuleWithCode("cs2113t").getAssessmentList().getSize() ); } + + @Test + void editAssessment_userInputFourEdits_assessmentEditedCorrectly() throws TaaException { + Ui ui = new Ui(); + Storage storage = new Storage("./data/taa_data.json"); + ModuleList moduleList = new ModuleList(); + String moduleInput = "add_module c/cs2113t n/software engineering"; + String assessmentInput = "add_assessment c/cs2113t n/Midterms m/50 w/20"; + String editAssessment1 = "edit_assessment c/cs2113t n/midterms nn/finals"; + String editAssessment2 = "edit_assessment c/cs2113t n/finals m/100"; + String editAssessment3 = "edit_assessment c/cs2113t n/finals w/50"; + String editAssessment4 = "edit_assessment c/cs2113t n/finals nn/midterms m/50 w/20"; + Command command1 = Parser.parseUserInput(moduleInput); + command1.execute(moduleList, ui, storage); + Command command2 = Parser.parseUserInput(assessmentInput); + command2.execute(moduleList, ui, storage); + Assessment assessment = moduleList.getModuleWithCode("cs2113t").getAssessmentList(). + getAssessment("midterms"); + Command command3 = Parser.parseUserInput(editAssessment1); + command3.execute(moduleList, ui, storage); + assertEquals("finals", assessment.getName()); + Command command4 = Parser.parseUserInput(editAssessment2); + command4.execute(moduleList, ui, storage); + assertEquals(100, assessment.getMaximumMarks()); + Command command5 = Parser.parseUserInput(editAssessment3); + command5.execute(moduleList, ui, storage); + assertEquals(50, assessment.getWeightage()); + Command command6 = Parser.parseUserInput(editAssessment4); + command6.execute(moduleList, ui, storage); + assertEquals("midterms", assessment.getName()); + assertEquals(50, assessment.getMaximumMarks()); + assertEquals(20, assessment.getWeightage()); + } } From 73504344871bb5342edf0c5c091d337b92b5cf99 Mon Sep 17 00:00:00 2001 From: rachel Date: Sat, 23 Oct 2021 02:08:34 +0800 Subject: [PATCH 172/543] Update checkstyle --- src/main/java/taa/Parser.java | 26 +++++++++++++++++-- .../taa/command/EditAssessmentCommand.java | 4 +-- 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 87152d731b..9b04b596e8 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,8 +1,30 @@ package taa; -import taa.command.*; - +import taa.command.AddAssessmentCommand; +import taa.command.AddModuleCommand; +import taa.command.AddStudentCommand; +import taa.command.AverageMarksCommand; +import taa.command.Command; +import taa.command.DeleteAssessmentCommand; +import taa.command.DeleteAttendanceCommand; +import taa.command.DeleteMarkCommand; +import taa.command.DeleteModuleCommand; +import taa.command.DeleteStudentCommand; +import taa.command.EditAssessmentCommand; +import taa.command.EditMarkCommand; +import taa.command.EditModuleCommand; +import taa.command.EditStudentCommand; +import taa.command.ExitCommand; +import taa.command.FindStudentCommand; +import taa.command.HelpCommand; +import taa.command.ListAssessmentsCommand; +import taa.command.ListAttendanceCommand; +import taa.command.ListMarksCommand; +import taa.command.ListModulesCommand; +import taa.command.ListStudentsCommand; +import taa.command.SetAttendanceCommand; +import taa.command.SetMarksCommand; import taa.exception.TaaException; import java.util.ArrayList; diff --git a/src/main/java/taa/command/EditAssessmentCommand.java b/src/main/java/taa/command/EditAssessmentCommand.java index 9903466e8b..533e7c75f5 100644 --- a/src/main/java/taa/command/EditAssessmentCommand.java +++ b/src/main/java/taa/command/EditAssessmentCommand.java @@ -55,8 +55,8 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc boolean hasNewAssessmentName = argumentMap.containsKey(KEY_NEW_ASSESSMENT_NAME); boolean hasNewMaximumMarks = argumentMap.containsKey(KEY_NEW_MAXIMUM_MARKS); boolean hasNewWeightage = argumentMap.containsKey(KEY_NEW_WEIGHTAGE); - boolean hasNecessaryArguments = hasModuleCode && hasAssessmentName && - (hasNewAssessmentName || hasNewMaximumMarks || hasNewWeightage); + boolean hasNecessaryArguments = hasModuleCode && hasAssessmentName + && (hasNewAssessmentName || hasNewMaximumMarks || hasNewWeightage); if (!hasNecessaryArguments) { throw new TaaException(getMissingArgumentMessage()); } From 806feabc9e5bdda31c0ce9b01d87538b3729de69 Mon Sep 17 00:00:00 2001 From: rachel Date: Sat, 23 Oct 2021 02:11:41 +0800 Subject: [PATCH 173/543] Update checkstyle --- src/test/java/taa/assessment/AssessmentListTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index acea90d726..c24b06ad1a 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -78,24 +78,24 @@ void editAssessment_userInputFourEdits_assessmentEditedCorrectly() throws TaaExc String moduleInput = "add_module c/cs2113t n/software engineering"; String assessmentInput = "add_assessment c/cs2113t n/Midterms m/50 w/20"; String editAssessment1 = "edit_assessment c/cs2113t n/midterms nn/finals"; - String editAssessment2 = "edit_assessment c/cs2113t n/finals m/100"; - String editAssessment3 = "edit_assessment c/cs2113t n/finals w/50"; - String editAssessment4 = "edit_assessment c/cs2113t n/finals nn/midterms m/50 w/20"; Command command1 = Parser.parseUserInput(moduleInput); command1.execute(moduleList, ui, storage); Command command2 = Parser.parseUserInput(assessmentInput); command2.execute(moduleList, ui, storage); - Assessment assessment = moduleList.getModuleWithCode("cs2113t").getAssessmentList(). - getAssessment("midterms"); + Assessment assessment = moduleList.getModuleWithCode("cs2113t").getAssessmentList() + .getAssessment("midterms"); Command command3 = Parser.parseUserInput(editAssessment1); command3.execute(moduleList, ui, storage); assertEquals("finals", assessment.getName()); + String editAssessment2 = "edit_assessment c/cs2113t n/finals m/100"; Command command4 = Parser.parseUserInput(editAssessment2); command4.execute(moduleList, ui, storage); assertEquals(100, assessment.getMaximumMarks()); + String editAssessment3 = "edit_assessment c/cs2113t n/finals w/50"; Command command5 = Parser.parseUserInput(editAssessment3); command5.execute(moduleList, ui, storage); assertEquals(50, assessment.getWeightage()); + String editAssessment4 = "edit_assessment c/cs2113t n/finals nn/midterms m/50 w/20"; Command command6 = Parser.parseUserInput(editAssessment4); command6.execute(moduleList, ui, storage); assertEquals("midterms", assessment.getName()); From d3f0513cd8c942471bf4fa2dca18761b8b57fd2a Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Sat, 23 Oct 2021 14:25:59 +0800 Subject: [PATCH 174/543] edited DG --- docs/DeveloperGuide.md | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 55eeb6100d..f793b53898 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -136,7 +136,32 @@ ArrayList within `AttendanceList`. ### Set marks -The set marks mechanism is facilitated by `SetMarksCommand`. It extends `Command`.
+The set marks mechanism is facilitated by `SetMarksCommand`. It extends `Command` and uses a `results` HashMap to store +`assessmentName` and the `marks` for it as a key-value pair.
+ +`SetMarksCommand` implements the following methods: +* `SetMarksCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Checks input for errors before calling the +`setMarks` command and saving the data. +* `SetMarksCommand#setMarks(ui:Ui, student:Student, assessmentName:String, marks:double)` - Puts a key-value pair with +`assessmentName` as key and `marks` as the value into the `results` HashMap of `student`. + +Below is an example scenario of how the set marks mechanism behaves at each step: +* Precursor Step - The user must have executed the commands to create `module`, `assessment`, and `student` entities. +For purpose of this example, the user will have created `CS2113T` as the `module`, `Midterms` as the `assessment` with +a maximum mark of `100`, and `Jim Ho` as the `student`. +* Step 1 - The user executes the `set_marks c/CS2113T s/1 a/Midterms m/50` command to set marks for student at index `1` +for the `Midterms` assessment under the `CS2113T` module. The `set_marks` command calls the `SetMarksCommand#execute` +method. Within `SetMarksCommand#execute`, `StudentList#getStudentAt("1")` is called to ensure that the student to be +marked (in this case student at index `1`) exists. +* Step 2 - `AssessmentList#getAssessment(Midterms)` is then called to ensure that the `Midterms` assessment exists and +that the student has yet to be marked for it. +* Step 3 - `Assessment#getMaximumMarks();` is then called to ensure that the marks to be given for the `Midterms` +assessment do not exceed the maximum marks attributed to it. +* Step 4 - If the above steps do not output an error, the `SetMarksCommand#setMarks` command is then called, which in +turn calls the `Student#setMarks` command to put the key-value pair into the `results` HashMap of the student at index +`1`. + + ## Product scope ### Target user profile From ab323b8bb0ccee5a965a11ef7359b205511cc736 Mon Sep 17 00:00:00 2001 From: rachel Date: Sat, 23 Oct 2021 17:27:05 +0800 Subject: [PATCH 175/543] Update UG --- docs/UserGuide.md | 62 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 0acda30c78..7589b18dda 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -10,7 +10,11 @@ If you can type fast, TAA can help keep track of your modules and students faste * [Editing student information: `edit_student`](#editing-student-information-edit_student) * [Deleting student information: `delete_student`](#deleting-student-information-delete_student) * [Listing all students in a module: `list_students`](#listing-all-students-in-a-module-list_students) - * [Find students in a module given a keyword: `find_student`](#find-students-in-a-module-given-a-keyword-find_student) + * [Finding students in a module given a keyword: `find_student`](#finding-students-in-a-module-given-a-keyword-find_student) + * [Listing all assessments in a module: `list_assessments`](#listing-all-assessments-in-a-module-list_assessments) + * [Adding an assessment to a module: `add_assessment`](#adding-an-assessment-to-a-module-add_assessment) + * [Editing an assessment in a module: `edit_assessment`](#editing-an-assessment-in-a-module-edit_assessment) + * [Deleting an assessment from a module: `delete_assessment`](#deleting-an-assessment-from-a-module-delete_assessment) * [Listing marks for an assessment: `list_marks`](#listing-marks-for-an-assessment-list_marks) * [Setting marks for a student's assessment: `set_marks`](#setting-marks-for-a-students-assessment-set_marks) * [Editing marks for a student's assessment: `edit_mark`](#editing-marks-for-a-students-assessment-edit_mark) @@ -98,6 +102,61 @@ Examples:
+### Listing all assessments in a module: `list_assessments` +List all assessments in a module. + +Format: `list_assessments c/` +* MODULE_CODE refers to the code of the module (e.g. CS2113T). + +Examples: +* `list_assessments c/CS2113T` +* `list_assessments c/CS2101` + +### Adding an assessment to a module: `add_assessment` +Adds an assessment to a module. + +Format: `add_assessment c/ n/ m/ w/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). +* `MAXIMUM_MARKS` refers to the maximum marks of the assessment (e.g. 100). +* `WEIGHTAGE` refers to the weightage of the assessment (e.g. 10%). + +Examples: +* `add_assessment c/CS2101 n/OP1 m/20 w/10` +* `add_assessment c/CS2101 n/OP2 m/25 w/15` + +
+ +### Editing an assessment in a module: `edit_assessment` +Edits an assessment of a module. + +Format: `add_assessment c/ n/ [nn/] [m/]` +* At least one of the optional fields must be provided. +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). +* `NEW_ASSESSMENT_NAME` refers to the new name of the assessment (e.g. Finals, Assignment 2, etc.). +* `NEW_MAXIMUM_MARKS` refers to the new maximum marks of the assessment (e.g. 50). +* `NEW_WEIGHTAGE` refers to the new weightage of the assessment (e.g. 20%). + +Examples: +* `edit_assessment c/CS2101 n/OP1 m/20 w/10` +* `edit_assessment c/CS2101 n/OP2 nn/UGDG` + +
+ +### Deleting an assessment from a module: `delete_assessment` +Deletes an assessment of a module. + +Format: `delete_assessment c/ n/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). + +Examples: +* `delete_assessment c/CS2101 n/OP1` +* `delete_assessment c/CS2101 n/OP2` + +
+ ### Listing all students in a module: `list_students` Shows a list of all students in a particular module. @@ -229,6 +288,7 @@ delete_assessment | `delete_assessment c/ n/`
s/ a/`
e.g. `delete_mark c/CS2113T s/1 a/Midterms` edit_mark | `edit_mark c/ s/ a/ m/`
e.g. `edit_mark c/CS2113T s/1 a/Midterms m/80.6` edit_student | `edit_student c/ s/ i/ n/`
e.g. `edit_student c/CS2113T s/1 i/12345 n/jon geh` +edit_assessment | `add_assessment c/ n/ [nn/] [m/]`
e.g. `edit_assessment c/CS2101 n/OP1 m/20 w/10` list_modules | `list_modules` list_students | `list_students c/`
e.g. `list_students c/CS2113T` list_attendance | `list_attendance c/ s/`
e.g. `list_attendance c/CS2113T s/1` From d83923ab7c19c6a632dab3751a954c0084d8ca4e Mon Sep 17 00:00:00 2001 From: rachel Date: Sat, 23 Oct 2021 17:33:54 +0800 Subject: [PATCH 176/543] Update formatting error and typos in UG --- docs/UserGuide.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7589b18dda..0894080b91 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -112,6 +112,8 @@ Examples: * `list_assessments c/CS2113T` * `list_assessments c/CS2101` +
+ ### Adding an assessment to a module: `add_assessment` Adds an assessment to a module. @@ -130,7 +132,7 @@ Examples: ### Editing an assessment in a module: `edit_assessment` Edits an assessment of a module. -Format: `add_assessment c/ n/ [nn/] [m/]` +Format: `edit_assessment c/ n/ [nn/] [m/]` * At least one of the optional fields must be provided. * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). * `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). @@ -288,7 +290,7 @@ delete_assessment | `delete_assessment c/ n/`
s/ a/`
e.g. `delete_mark c/CS2113T s/1 a/Midterms` edit_mark | `edit_mark c/ s/ a/ m/`
e.g. `edit_mark c/CS2113T s/1 a/Midterms m/80.6` edit_student | `edit_student c/ s/ i/ n/`
e.g. `edit_student c/CS2113T s/1 i/12345 n/jon geh` -edit_assessment | `add_assessment c/ n/ [nn/] [m/]`
e.g. `edit_assessment c/CS2101 n/OP1 m/20 w/10` +edit_assessment | `edit_assessment c/ n/ [nn/] [m/]`
e.g. `edit_assessment c/CS2101 n/OP1 m/20 w/10` list_modules | `list_modules` list_students | `list_students c/`
e.g. `list_students c/CS2113T` list_attendance | `list_attendance c/ s/`
e.g. `list_attendance c/CS2113T s/1` From 81193b1da7f021fd8e8dd6fbd0a4998ad1c53396 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Sat, 23 Oct 2021 23:14:53 +0800 Subject: [PATCH 177/543] updated user and developer guide --- docs/DeveloperGuide.md | 27 ++++++++++++++++++--------- docs/UserGuide.md | 3 ++- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index f793b53898..aac6724aab 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -50,7 +50,7 @@ The _Architecture Diagram_ shown above explains the high-level design of the App _Figure 2. An example of interactions between components for `add_module c/CS2113T n/Software Engineering`._ ## Implementation -### Add module +### Add Module The add module mechanism is facilitated by `AddModuleCommand`. It extends `Command` and uses `ModuleList` which stores module internally as an ArrayList `modules`.
@@ -74,7 +74,7 @@ called to ensure that there is no existing module with code `CS2113T`. and `Software Engineering` respectively. Then, `ModuleList#addModule` is called to add the newly created `Module` object into the `modules` ArrayList within `ModuleList`. -### Add student +### Add Student The add student mechanism is facilitated by `AddStudentCommand`. It extends `Command` and uses `StudentList` which stores student internally as an ArrayList `students`.
@@ -100,7 +100,9 @@ called to ensure that there is an existing module with code `CS2113T`. `a0217978j` and `jonny` respectively. Then, `StudentList#addModule` is called to add the newly created `Student` object into the `students` ArrayList within `StudentList`. -### Set attendance + + +### Set Attendance The set attendance mechanism is facilitated by SetAttendanceCommand. It extends `Command` and uses `AttendanceList` which stores a student's lessons attendance as an ArrayList `attendances`. @@ -133,9 +135,10 @@ with lesson number `1` and attendance record `Present` is set as its lesson numb Then, `AttendanceList#addAttendance` is called to add the newly created `Attendance` object into the `attendances` ArrayList within `AttendanceList`. +### Add Assessment +HI - -### Set marks +### Set Marks The set marks mechanism is facilitated by `SetMarksCommand`. It extends `Command` and uses a `results` HashMap to store `assessmentName` and the `marks` for it as a key-value pair.
@@ -162,7 +165,6 @@ turn calls the `Student#setMarks` command to put the key-value pair into the `re `1`. - ## Product scope ### Target user profile @@ -184,9 +186,16 @@ turn calls the `Student#setMarks` command to put the key-value pair into the `re |v2.0|user|find a to-do item by name|locate a to-do without having to go through the entire list| ## Non-Functional Requirements - -{Give non-functional requirements} +1. Should work on any mainstream OS as long as it has Java 11 or above installed. +2. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should +be able to accomplish most of the tasks faster using commands than using the mouse. ## Glossary +* Mainstream OS: Windows, Linux, Unix, OS-X + + +## Method Summary -* *glossary item* - Definition +Method | Description | + ------ | --------------- | +add_module | adds a module lol diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 0894080b91..25b2dc00cd 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -11,6 +11,7 @@ If you can type fast, TAA can help keep track of your modules and students faste * [Deleting student information: `delete_student`](#deleting-student-information-delete_student) * [Listing all students in a module: `list_students`](#listing-all-students-in-a-module-list_students) * [Finding students in a module given a keyword: `find_student`](#finding-students-in-a-module-given-a-keyword-find_student) + * [Setting attendance for a particular lesson for a student: `set_attendance`](#setting-attendance-for-a-particular-lesson-for-a-student-set_attendance) * [Listing all assessments in a module: `list_assessments`](#listing-all-assessments-in-a-module-list_assessments) * [Adding an assessment to a module: `add_assessment`](#adding-an-assessment-to-a-module-add_assessment) * [Editing an assessment in a module: `edit_assessment`](#editing-an-assessment-in-a-module-edit_assessment) @@ -272,7 +273,7 @@ Format: `exit` **Q**: How do I transfer my data to another computer? -**A**: {your answer here} +**A**: Simply transfer the `data` folder to your new computer and ensure that it is in the same folder as the jar file. ## Command Summary From fc4da9642ff33830dd94fb61aa978fa09c0ede5a Mon Sep 17 00:00:00 2001 From: rachel Date: Mon, 25 Oct 2021 00:06:34 +0800 Subject: [PATCH 178/543] Remove the unused methods in the class. --- .../java/taa/assessment/AssessmentList.java | 24 ------------------- 1 file changed, 24 deletions(-) diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 541feb38f7..425de73aca 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -24,16 +24,6 @@ public ArrayList getAssessments() { return new ArrayList<>(assessments); } - /** - * Checks if an index is valid with respect to the assessments ArrayList. - * - * @param index The index to check. - * @return true if valid, else false. - */ - public boolean isValidIndex(int index) { - return (index >= 0 && index < assessments.size()); - } - /** * Adds an assessment to the list of assessments in a particular module. * Does not add if assessment name already exists @@ -81,20 +71,6 @@ public Assessment deleteAssessment(String assessmentName) { return null; } - /** - * Gets an Assessment object at the index from the assessment ArrayList. - * - * @param index The index of the object. - * @return An Assessment object if the index is valid, else null. - */ - private Assessment getAssessmentAt(int index) { - if (isValidIndex(index)) { - return assessments.get(index); - } - - return null; - } - /** * Gets an Assessment object with a particular name. Note: name is case-insensitive. * From 4e249725fe1b7952bd05de0a8bd49c3682388e34 Mon Sep 17 00:00:00 2001 From: rachel Date: Mon, 25 Oct 2021 00:13:31 +0800 Subject: [PATCH 179/543] Update DG --- docs/DeveloperGuide.md | 36 ++++++++++++++++++++++++++++++++---- 1 file changed, 32 insertions(+), 4 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index aac6724aab..f182bc8e92 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -93,15 +93,13 @@ ArrayList. * `StudentList#findStudent(keyword:String)` - Returns an ArrayList of students containing the keyword Below is an example scenario of how the add student feature behaves at each step:
-* Step 1 - The user executes `add_student c/CS2113T i/a0217978j n/jonny` to add a module. The `add_student` command +* Step 1 - The user executes `add_student c/CS2113T i/a0217978j n/jonny` to add a student. The `add_student` command calls the `AddStudentCommand#execute` method. Within `AddStudentCommand#execute`, `ModuleList#getModule("CS2113T")` is called to ensure that there is an existing module with code `CS2113T`. * Step 2 - If an existing module with code `CS2113T` is found, a new `Student` object with id and name set to `a0217978j` and `jonny` respectively. Then, `StudentList#addModule` is called to add the newly created `Student` object into the `students` ArrayList within `StudentList`. - - ### Set Attendance The set attendance mechanism is facilitated by SetAttendanceCommand. It extends `Command` and uses `AttendanceList` which stores a student's lessons attendance as an @@ -136,7 +134,37 @@ Then, `AttendanceList#addAttendance` is called to add the newly created `Attenda ArrayList within `AttendanceList`. ### Add Assessment -HI +The add assessment mechanism is facilitated by `AddAssessmentCommand`. It extends `Command` and uses `AssessmentList` +which stores assessment internally as an ArrayList `assessments`.
+ +`AddAssessmentCommand` implements the following methods: +* `AddAssessmentCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Performs operations for the command. + +`AssessmentList` implements the following methods: +* `AssessmentList#getSize()` - Returns the no. of assessments currently in the list. +* `AssessmentList#getAssessments()` - Returns an ArrayList containing all the assessments. +* `AssessmentList#getAssessment(assessmentName:String)` - Returns an assessment with a particular name specified by the + user. +* `AssessmentList#addAssessment(assessment:Assessment)` - Adds an assessment to the `assessments` ArrayList. +* `AssessmentList#deleteAssessment(assessmentName:String)` - Deletes an assessment with the name specified by the user + from the `assessments` ArrayList. + +Below is an example scenario of how the add assessment feature behaves at each step: +* Step 1 - The user executes `add_assessment c/cs2113t n/midterms m/20 w/10` to add an assessment. The `add_assessment` + command calls the `AddAssessmentCommand#execute` method. Within `AddAssessmentCommand#execute`, + `ModuleList#getModuleWithCode("cs2113t")` is called to ensure that there is an existing module with code `cs2113t`. +* Step 2 - If an existing module with code `cs2113t` is found, the `MAXIMUM_MARKS` and `WEIGHTAGE` arguments are checked + to ensure that they are valid. +* Step 3 - If the `MAXIMUM_MARKS` and `WEIGHTAGE` arguments are valid, a new `Assessment` object with name, + maximum marks and weightage set to `midterms`, `20` and `10` respectively is created under the existing `Module` with + code `cs2113t`. Then, `AssessmentList#addAssessment` is called to add the newly created `Assessment` object into the + `assessments` ArrayList within `AssessmentList`. +* Step 4 - Within `AssessmentList#addAssessment`, the name of the newly created `Assessment` object is checked to ensure + there is no existing assessment with name `midterms`. At the same time, the weightage of the newly created + `Assessment` object is also checked to ensure that the total weightage of the assessments in the `cs2113t` module + will not exceed 100 with the addition of the weightage of the newly created `Assessment` object. +* Step 5 - If the name and weightage of the newly created `Assessment` object are valid, the newly created `Assessment` + object is added into the `assessments` ArrayList within `AssessmentList`. ### Set Marks The set marks mechanism is facilitated by `SetMarksCommand`. It extends `Command` and uses a `results` HashMap to store From c517e522d4863536014629a7e617898f40009b39 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Mon, 25 Oct 2021 00:32:21 +0800 Subject: [PATCH 180/543] edit user guide and add delete_attendance to help --- docs/UserGuide.md | 30 +++++++++++++++++++--- src/main/java/taa/command/HelpCommand.java | 1 + 2 files changed, 28 insertions(+), 3 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 25b2dc00cd..87cb399d5f 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -12,6 +12,8 @@ If you can type fast, TAA can help keep track of your modules and students faste * [Listing all students in a module: `list_students`](#listing-all-students-in-a-module-list_students) * [Finding students in a module given a keyword: `find_student`](#finding-students-in-a-module-given-a-keyword-find_student) * [Setting attendance for a particular lesson for a student: `set_attendance`](#setting-attendance-for-a-particular-lesson-for-a-student-set_attendance) + * [Deleting attendance for a particular lesson for a student: `delete_attendance`](#deleting-attendance-for-a-particular-lesson-for-a-student-delete_attendance) + * [Listing attendance for a particular student: `list_attendance`](#listing-attendance-for-a-particular-student-list_attendance) * [Listing all assessments in a module: `list_assessments`](#listing-all-assessments-in-a-module-list_assessments) * [Adding an assessment to a module: `add_assessment`](#adding-an-assessment-to-a-module-add_assessment) * [Editing an assessment in a module: `edit_assessment`](#editing-an-assessment-in-a-module-edit_assessment) @@ -186,14 +188,35 @@ Examples:
### Setting attendance for a particular lesson for a student: `set_attendance` -Sets a student's attendance for a lesson +Sets a student's attendance for a lesson. -Format: `set_attendance c/ l/ p/` +Format: `set_attendance c/ s/ l/ p/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). * `STUDENT_INDEX` refers to the index of the student in the student list of the module. -* `LESSON_NUMBER` refers to the lesson number +* `LESSON_NUMBER` refers to the lesson number. * `PRESENT` refers to the whether a student is present. (1 for present, 0 for not present) +
+ +### Deleting attendance for a particular lesson for a student: `delete_attendance` +Deletes a student's attendance for a lesson. + +Format: `delete_attendance c/ s/ l/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +* `LESSON_NUMBER` refers to the lesson number. + +
+ +### Listing attendance for a particular student: `list_attendance` +Lists a student's attendance. + +Format: `list_attendance c/ s/ + ### Setting marks for a student's assessment: `set_marks` Adds a student's marks for an assessment. @@ -288,6 +311,7 @@ set_attendance | `set_attendance c/ s/ l/ s/ a/ m/`
e.g. `set_marks c/CS2113T s/1 a/Midterms m/70.6` delete_student | `delete_student c/ s/`
e.g. `delete_student c/cs2113t s/1` delete_assessment | `delete_assessment c/ n/`
e.g. `delete_assessment c/CS2113T n/finals` +delete_attendance | `delete_attendance c/ s/ l/`
e.g. `delete_attendance c/CS2113T s/1 l/1` delete_mark | `delete_mark c/ s/ a/`
e.g. `delete_mark c/CS2113T s/1 a/Midterms` edit_mark | `edit_mark c/ s/ a/ m/`
e.g. `edit_mark c/CS2113T s/1 a/Midterms m/80.6` edit_student | `edit_student c/ s/ i/ n/`
e.g. `edit_student c/CS2113T s/1 i/12345 n/jon geh` diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index c1f967329c..2e4c19d0bf 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -29,6 +29,7 @@ public class HelpCommand extends Command { new AverageMarksCommand(""), new ListAttendanceCommand(""), new SetAttendanceCommand(""), + new DeleteAttendanceCommand(""), new ExitCommand(""), new HelpCommand("") }; From b5c08bdd88fa18fcab4c42ecb8fec020e8db4592 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 01:31:31 +0800 Subject: [PATCH 181/543] Add an abstract method "checkArgument" --- src/main/java/taa/command/Command.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 95e5a3ed67..273c5af595 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -64,18 +64,20 @@ public Command(String argument, String[] argumentKeys) { this.argumentMap = Parser.getArgumentsFromString(argument, argumentKeys); } + protected abstract String getUsage(); + + protected abstract void checkArgument() throws TaaException; + + public abstract void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException; + public boolean isExit() { return isExit; } - protected abstract String getUsage(); - protected String getUsageMessage() { return String.format(MESSAGE_FORMAT_USAGE_MESSAGE, getUsage()); } - public abstract void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException; - protected String getMissingArgumentMessage() { String usageMessage = getUsageMessage(); if (usageMessage == null) { From b607e3d8f960efd96f42de4f01432ebab4b05da0 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 01:32:18 +0800 Subject: [PATCH 182/543] Move argument checks to checkArgument method --- .../taa/command/AddAssessmentCommand.java | 65 ++++++++++++------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 164ea282b8..364eb18046 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -36,16 +36,8 @@ public AddAssessmentCommand(String argument) { super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); } - /** - * Executes the add_assessment command and adds an assessment to a particular module. - * - * @param moduleList The list of modules. - * @param ui The ui instance to handle interactions with the user. - * @param storage The storage instance to handle saving. - * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). - */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + protected void checkArgument() throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -54,45 +46,68 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getMissingArgumentMessage()); } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); - } - String maximumMarksString = argumentMap.get(KEY_MAXIMUM_MARKS); if (!Util.isStringInteger(maximumMarksString)) { throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS, - Assessment.MINIMUM_MARKS) + MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS, + Assessment.MINIMUM_MARKS) ); } int maximumMarks = Integer.parseInt(maximumMarksString); if (maximumMarks < Assessment.MINIMUM_MARKS) { throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS, - Assessment.MINIMUM_MARKS) + MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS, + Assessment.MINIMUM_MARKS) ); } String weightageString = argumentMap.get(KEY_WEIGHTAGE); if (!Util.isStringDouble(weightageString)) { throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_WEIGHTAGE, - Assessment.WEIGHTAGE_RANGE[0], - Assessment.WEIGHTAGE_RANGE[1]) + MESSAGE_FORMAT_INVALID_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) ); } double weightage = Double.parseDouble(weightageString); if (!Assessment.isWeightageWithinRange(weightage)) { throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_WEIGHTAGE, - Assessment.WEIGHTAGE_RANGE[0], - Assessment.WEIGHTAGE_RANGE[1]) + MESSAGE_FORMAT_INVALID_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) ); } + } + + /** + * Executes the add_assessment command and adds an assessment to a particular module. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + checkArgument(); + + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModuleWithCode(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + + String maximumMarksString = argumentMap.get(KEY_MAXIMUM_MARKS); + assert Util.isStringInteger(maximumMarksString); + int maximumMarks = Integer.parseInt(maximumMarksString); + assert maximumMarks >= Assessment.MINIMUM_MARKS; + + String weightageString = argumentMap.get(KEY_WEIGHTAGE); + assert Util.isStringDouble(weightageString); + double weightage = Double.parseDouble(weightageString); + assert Assessment.isWeightageWithinRange(weightage); String name = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = new Assessment(name, maximumMarks, weightage); From 3d39953e8add7a0b41a11889df5e084c13c45011 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 01:33:14 +0800 Subject: [PATCH 183/543] Move module commands argument checks to checkArgument method --- .../java/taa/command/AddModuleCommand.java | 28 +++++++++++-------- .../java/taa/command/DeleteModuleCommand.java | 8 +++++- .../java/taa/command/EditModuleCommand.java | 17 ++++++++--- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index 53752a396b..96e9d5a3f3 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -22,16 +22,8 @@ public AddModuleCommand(String argument) { super(argument, ADD_MODULE_ARGUMENT_KEYS); } - /** - * Executes the add_module command and adds a module. - * - * @param moduleList The list of modules. - * @param ui The ui instance to handle interactions with the user. - * @param storage The storage instance to handle saving. - * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). - */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + protected void checkArgument() throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -40,11 +32,26 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(getMissingArgumentMessage()); } - assert argumentMap.containsKey(KEY_MODULE_CODE); String moduleCode = argumentMap.get(KEY_MODULE_CODE); if (moduleCode.contains(" ")) { throw new TaaException(MESSAGE_INVALID_MODULE_CODE); } + } + + /** + * Executes the add_module command and adds a module. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + checkArgument(); + + assert argumentMap.containsKey(KEY_MODULE_CODE); + String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module != null) { @@ -52,7 +59,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String name = argumentMap.getOrDefault(KEY_MODULE_NAME, ""); - module = new Module(moduleCode, name); moduleList.addModule(module); diff --git a/src/main/java/taa/command/DeleteModuleCommand.java b/src/main/java/taa/command/DeleteModuleCommand.java index 527e9b0c65..964111c4ed 100644 --- a/src/main/java/taa/command/DeleteModuleCommand.java +++ b/src/main/java/taa/command/DeleteModuleCommand.java @@ -19,7 +19,7 @@ public DeleteModuleCommand(String argument) { } @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + protected void checkArgument() throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -27,7 +27,13 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + checkArgument(); + assert argumentMap.containsKey(KEY_MODULE_CODE); String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { diff --git a/src/main/java/taa/command/EditModuleCommand.java b/src/main/java/taa/command/EditModuleCommand.java index d04a0fd38e..f25b82c8d6 100644 --- a/src/main/java/taa/command/EditModuleCommand.java +++ b/src/main/java/taa/command/EditModuleCommand.java @@ -17,7 +17,7 @@ public class EditModuleCommand extends Command { }; private static final String MESSAGE_FORMAT_EDIT_MODULE_USAGE = "%s %s/ " - + "[%s/ | %s/]"; + + "[%s/] [%s/]"; private static final String MESSAGE_FORMAT_MODULE_EDITED = "Module edited:\n %s"; public EditModuleCommand(String argument) { @@ -25,19 +25,28 @@ public EditModuleCommand(String argument) { } @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + protected void checkArgument() throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } - boolean hasModuleCode = argumentMap.containsKey(KEY_MODULE_CODE); + if (!argumentMap.containsKey(KEY_MODULE_CODE)) { + throw new TaaException(getMissingArgumentMessage()); + } + boolean hasNewModuleCode = argumentMap.containsKey(KEY_NEW_MODULE_CODE); boolean hasNewModuleName = argumentMap.containsKey(KEY_NEW_MODULE_NAME); - boolean hasNecessaryArguments = hasModuleCode && (hasNewModuleCode || hasNewModuleName); + boolean hasNecessaryArguments = (hasNewModuleCode || hasNewModuleName); if (!hasNecessaryArguments) { throw new TaaException(getMissingArgumentMessage()); } + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + checkArgument(); + assert argumentMap.containsKey(KEY_MODULE_CODE); String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { From 072116ac69fabaea825f48fd1b62ffc05bc83278 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 01:34:00 +0800 Subject: [PATCH 184/543] Change EditAssessment usage string --- src/main/java/taa/command/EditAssessmentCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/command/EditAssessmentCommand.java b/src/main/java/taa/command/EditAssessmentCommand.java index 533e7c75f5..00ebb39f70 100644 --- a/src/main/java/taa/command/EditAssessmentCommand.java +++ b/src/main/java/taa/command/EditAssessmentCommand.java @@ -23,7 +23,7 @@ public class EditAssessmentCommand extends Command { }; private static final String MESSAGE_FORMAT_EDIT_ASSESSMENT_USAGE = "%s %s/ " - + "%s/ %s/ %s/ %s/"; + + "%s/ [%s/] [%s/] [%s/]"; private static final String MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE = "Invalid new weightage. " + "Weightage must be between %,.2f and %,.2f (inclusive)"; private static final String MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS = "Invalid new maximum marks. " From eeba6a10de8af536b8cec4b6d97079583a8d134f Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 01:34:51 +0800 Subject: [PATCH 185/543] Move argument checks to checkArgument() method --- src/main/java/taa/command/ExitCommand.java | 11 ++++++++--- src/main/java/taa/command/HelpCommand.java | 7 ++++++- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/src/main/java/taa/command/ExitCommand.java b/src/main/java/taa/command/ExitCommand.java index 5031bb4c8d..bacac2cc78 100644 --- a/src/main/java/taa/command/ExitCommand.java +++ b/src/main/java/taa/command/ExitCommand.java @@ -12,6 +12,13 @@ public ExitCommand(String argument) { super(argument); } + @Override + protected void checkArgument() throws TaaException { + if (!argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + } + /** * Executes the exit command and exits the program. * @@ -22,9 +29,7 @@ public ExitCommand(String argument) { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (!argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } + checkArgument(); ui.printExitMessage(); this.isExit = true; diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index c1f967329c..fa5517572b 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -38,10 +38,15 @@ public HelpCommand(String argument) { } @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + protected void checkArgument() throws TaaException { if (!argument.isEmpty()) { throw new TaaException(getUsageMessage()); } + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + checkArgument(); StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < commands.length; i += 1) { From 3df3606e336e5622a517754f18466cbc7b0f14b2 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 01:35:38 +0800 Subject: [PATCH 186/543] Move ListModulesCommand argument check to checkArgument() method --- src/main/java/taa/command/ListModulesCommand.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/command/ListModulesCommand.java b/src/main/java/taa/command/ListModulesCommand.java index e2fa241799..de64c079d6 100644 --- a/src/main/java/taa/command/ListModulesCommand.java +++ b/src/main/java/taa/command/ListModulesCommand.java @@ -14,6 +14,13 @@ public ListModulesCommand(String argument) { super(argument); } + @Override + protected void checkArgument() throws TaaException { + if (!argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + } + /** * Executes the list_modules command and lists all the modules. * @@ -24,9 +31,7 @@ public ListModulesCommand(String argument) { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (!argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } + checkArgument(); String message; if (moduleList.getSize() == 0) { From 3f0217325f558ad53a6d476d1da0454e6d609435 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 01:36:10 +0800 Subject: [PATCH 187/543] Create empty checkArgument() methods --- src/main/java/taa/command/AddStudentCommand.java | 5 +++++ src/main/java/taa/command/AverageMarksCommand.java | 5 +++++ src/main/java/taa/command/DeleteAssessmentCommand.java | 5 +++++ src/main/java/taa/command/DeleteAttendanceCommand.java | 5 +++++ src/main/java/taa/command/DeleteMarkCommand.java | 5 +++++ src/main/java/taa/command/DeleteStudentCommand.java | 5 +++++ src/main/java/taa/command/EditAssessmentCommand.java | 5 +++++ src/main/java/taa/command/EditMarkCommand.java | 5 +++++ src/main/java/taa/command/EditStudentCommand.java | 5 +++++ src/main/java/taa/command/FindStudentCommand.java | 5 +++++ src/main/java/taa/command/ListAssessmentsCommand.java | 5 +++++ src/main/java/taa/command/ListAttendanceCommand.java | 5 +++++ src/main/java/taa/command/ListMarksCommand.java | 5 +++++ src/main/java/taa/command/ListStudentsCommand.java | 5 +++++ src/main/java/taa/command/SetAttendanceCommand.java | 5 +++++ src/main/java/taa/command/SetMarksCommand.java | 5 +++++ 16 files changed, 80 insertions(+) diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index 7241fc5d94..77d44eeb10 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -22,6 +22,11 @@ public AddStudentCommand(String argument) { super(argument, ADD_STUDENT_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the add_student command and adds a student to a particular module. * diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index d87a150587..2b972096ed 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -27,6 +27,11 @@ public AverageMarksCommand(String argument) { super(argument, AVERAGE_MARKS_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the average_marks command and displays the average mark of an assessment to the user. * diff --git a/src/main/java/taa/command/DeleteAssessmentCommand.java b/src/main/java/taa/command/DeleteAssessmentCommand.java index e340d2e71f..51cbb1a9da 100644 --- a/src/main/java/taa/command/DeleteAssessmentCommand.java +++ b/src/main/java/taa/command/DeleteAssessmentCommand.java @@ -20,6 +20,11 @@ public DeleteAssessmentCommand(String argument) { super(argument, DELETE_ASSESSMENT_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the delete_assessment command and deletes an assessment with the specified assessment name. * diff --git a/src/main/java/taa/command/DeleteAttendanceCommand.java b/src/main/java/taa/command/DeleteAttendanceCommand.java index 7d4da7e37b..c88e4684c8 100644 --- a/src/main/java/taa/command/DeleteAttendanceCommand.java +++ b/src/main/java/taa/command/DeleteAttendanceCommand.java @@ -29,6 +29,11 @@ public DeleteAttendanceCommand(String argument) { super(argument, DELETE_ATTENDANCE_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the delete_attendance command and deletes a student's attendance from the attendanceList. * diff --git a/src/main/java/taa/command/DeleteMarkCommand.java b/src/main/java/taa/command/DeleteMarkCommand.java index df1ec2318a..733da06867 100644 --- a/src/main/java/taa/command/DeleteMarkCommand.java +++ b/src/main/java/taa/command/DeleteMarkCommand.java @@ -29,6 +29,11 @@ public DeleteMarkCommand(String argument) { super(argument, DELETE_MARK_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 8a1587abce..233c6efddc 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -21,6 +21,11 @@ public DeleteStudentCommand(String argument) { super(argument, DELETE_STUDENT_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the delete_student command and deletes a student from the module. * diff --git a/src/main/java/taa/command/EditAssessmentCommand.java b/src/main/java/taa/command/EditAssessmentCommand.java index 00ebb39f70..502fc0f4b9 100644 --- a/src/main/java/taa/command/EditAssessmentCommand.java +++ b/src/main/java/taa/command/EditAssessmentCommand.java @@ -34,6 +34,11 @@ public EditAssessmentCommand(String argument) { super(argument, EDIT_ASSESSMENT_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the edit_assessment command and edits an assessment a particular module. * The name, maximum marks and weightage of the assessment can be changed. diff --git a/src/main/java/taa/command/EditMarkCommand.java b/src/main/java/taa/command/EditMarkCommand.java index 5485f22bfa..582f4a65e2 100644 --- a/src/main/java/taa/command/EditMarkCommand.java +++ b/src/main/java/taa/command/EditMarkCommand.java @@ -33,6 +33,11 @@ public EditMarkCommand(String argument) { super(argument, EDIT_MARKS_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { if (argument.isEmpty()) { diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 6662013b88..5edaf1fbe0 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -29,6 +29,11 @@ public EditStudentCommand(String argument) { super(argument, EDIT_STUDENT_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the edit_student command and edits the particulars of a student. * diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 11af1a8c81..8d5d8f9b98 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -24,6 +24,11 @@ public FindStudentCommand(String argument) { super(argument, FIND_STUDENT_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the find_student command and finds students in the module based on a keyword. * diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index ba5043678b..fb87da0dd5 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -20,6 +20,11 @@ public ListAssessmentsCommand(String argument) { super(argument, LIST_ASSESSMENTS_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the list_assessment command and list all the assessments of a particular module. * diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/ListAttendanceCommand.java index 1b38ceff0f..a86ee1594d 100644 --- a/src/main/java/taa/command/ListAttendanceCommand.java +++ b/src/main/java/taa/command/ListAttendanceCommand.java @@ -23,6 +23,11 @@ public ListAttendanceCommand(String argument) { super(argument, LIST_ATTENDANCE_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the list_attendance command and list all the attendance record of a student. * diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index 2d850a7cb4..f70476401e 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -27,6 +27,11 @@ public ListMarksCommand(String argument) { super(argument, LIST_MARKS_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the list_marks command and list marks of students for an assessment. * diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index c6a86044c8..15fef3c307 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -20,6 +20,11 @@ public ListStudentsCommand(String argument) { super(argument, LIST_STUDENT_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the list_student command and lists the students of a particular module. * diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index cbed90f9cd..e7d3bc7945 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -39,6 +39,11 @@ public SetAttendanceCommand(String argument) { super(argument, SET_ATTENDANCE_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the set_attendance command and sets the attendance of a student. * diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 8dfe134487..ea66547133 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -36,6 +36,11 @@ public SetMarksCommand(String argument) { super(argument, SET_MARKS_ARGUMENT_KEYS); } + @Override + protected void checkArgument() throws TaaException { + + } + /** * Executes the set_marks command and sets the marks of a student's assessment. * From a9fb9c5467ce6c84cce0866a60de9aacd9a2dcca Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 01:37:59 +0800 Subject: [PATCH 188/543] Add edit and delete module to UG --- docs/UserGuide.md | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 25b2dc00cd..97011bf942 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -4,8 +4,11 @@ If you can type fast, TAA can help keep track of your modules and students faste * [Quick Start](#quick-start) * [Features](#features) + * [Viewing help: `help`](#viewing-help-help) * [Listing all modules: `list_modules`](#listing-all-modules-list_modules) * [Adding a module: `add_module`](#adding-a-module-add_module) + * [Editing a module: `edit_module`](#editing-a-module-edit_module) + * [Deleting a module: `delete_module`](#deleting-a-module-delete_module) * [Adding a student to a specified module: `add_student`](#adding-a-student-to-a-specified-module-add_student) * [Editing student information: `edit_student`](#editing-student-information-edit_student) * [Deleting student information: `delete_student`](#deleting-student-information-delete_student) @@ -52,13 +55,39 @@ Format: `list_modules` ### Adding a module: `add_module` Adds a module to the module list. -Format: `add_module c/ n/` +Format: `add_module c/ [n/]` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `MODULE_NAME` refers to the name of the module to be added. +* `MODULE_NAME` [Optional] refers to the name of the module to be added. Examples: * `add_module c/CS2113T n/Software Engineering and Object-oriented Programming` * `add_module n/Effective Communication for Computing Professionals c/CS2101` +* `add_module c/CS2102` + +### Editing a module: `edit_module` +Edits the code or name of an existing module. + +Format: `edit_module c/ [nc/] [n/]` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `NEW_MODULE_CODE` [Optional] refers to the updated code of the module. +* `NEW_MODULE_NAME` [Optional] refers to the updated name of the module. +> 💡 **Note:**
+> Either `NEW_MODULE_CODE`, `NEW_MODULE_NAME`, or both must be provided. + +Examples: +* `edit_module c/CS2113T nc/cs2113t` +* `edit_module c/CS2113T n/software engineering` +* `edit_module c/CS2113T nc/cs2113t n/software engineering` + +### Deleting a module: `delete_module` +Deletes an existing module from the module list. + +Format: `delete_module c/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). + +Examples: +* `delete_module c/CS2113T` +* `delete_module c/CS2101`
@@ -140,6 +169,8 @@ Format: `edit_assessment c/ n/ [nn/ 💡 **Note:**
+> TODO Examples: * `edit_assessment c/CS2101 n/OP1 m/20 w/10` From 382ca09cb5939d9a533a46b293194446a24fd327 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 02:04:58 +0800 Subject: [PATCH 189/543] Reorder table of contents and command summary --- docs/UserGuide.md | 207 ++++++++++++++++++++++++---------------------- 1 file changed, 106 insertions(+), 101 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 5c68a828a7..8d40c02ca1 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -4,28 +4,29 @@ If you can type fast, TAA can help keep track of your modules and students faste * [Quick Start](#quick-start) * [Features](#features) - * [Viewing help: `help`](#viewing-help-help) * [Listing all modules: `list_modules`](#listing-all-modules-list_modules) * [Adding a module: `add_module`](#adding-a-module-add_module) * [Editing a module: `edit_module`](#editing-a-module-edit_module) * [Deleting a module: `delete_module`](#deleting-a-module-delete_module) - * [Adding a student to a specified module: `add_student`](#adding-a-student-to-a-specified-module-add_student) - * [Editing student information: `edit_student`](#editing-student-information-edit_student) - * [Deleting student information: `delete_student`](#deleting-student-information-delete_student) * [Listing all students in a module: `list_students`](#listing-all-students-in-a-module-list_students) + * [Adding a student to a module: `add_student`](#adding-a-student-to-a-module-add_student) + * [Editing a student's information in a module: `edit_student`](#editing-a-students-information-in-a-module-edit_student) + * [Deleting a student from a module: `delete_student`](#deleting-a-student-from-a-module-delete_student) * [Finding students in a module given a keyword: `find_student`](#finding-students-in-a-module-given-a-keyword-find_student) - * [Setting attendance for a particular lesson for a student: `set_attendance`](#setting-attendance-for-a-particular-lesson-for-a-student-set_attendance) - * [Deleting attendance for a particular lesson for a student: `delete_attendance`](#deleting-attendance-for-a-particular-lesson-for-a-student-delete_attendance) - * [Listing attendance for a particular student: `list_attendance`](#listing-attendance-for-a-particular-student-list_attendance) * [Listing all assessments in a module: `list_assessments`](#listing-all-assessments-in-a-module-list_assessments) * [Adding an assessment to a module: `add_assessment`](#adding-an-assessment-to-a-module-add_assessment) * [Editing an assessment in a module: `edit_assessment`](#editing-an-assessment-in-a-module-edit_assessment) * [Deleting an assessment from a module: `delete_assessment`](#deleting-an-assessment-from-a-module-delete_assessment) * [Listing marks for an assessment: `list_marks`](#listing-marks-for-an-assessment-list_marks) - * [Setting marks for a student's assessment: `set_marks`](#setting-marks-for-a-students-assessment-set_marks) + * [Setting marks for a student's assessment: `set_marks`](#setting-marks-for-a-students-assessment-set_marks) * [Editing marks for a student's assessment: `edit_mark`](#editing-marks-for-a-students-assessment-edit_mark) * [Deleting marks for a student's assessment: `delete_mark`](#deleting-marks-for-a-students-assessment-delete_mark) - * [Finding average marks for an assessment: `average_marks`](#finding-average-marks-for-an-assessment-average_marks) + * [Viewing average marks for an assessment: `average_marks`](#viewing-average-marks-for-an-assessment-average_marks) + * [Listing attendance for a particular student: `list_attendance`](#listing-attendance-for-a-particular-student-list_attendance) + * [Setting attendance for a particular lesson for a student: `set_attendance`](#setting-attendance-for-a-particular-lesson-for-a-student-set_attendance) + * [Deleting attendance for a particular lesson for a student: `delete_attendance`](#deleting-attendance-for-a-particular-lesson-for-a-student-delete_attendance) + * [Viewing help: `help`](#viewing-help-help) + * [Exiting the program: `exit`](#exiting-the-program-exit) * [FAQ](#faq) * [Command Summary](#command-summary) @@ -38,14 +39,7 @@ If you can type fast, TAA can help keep track of your modules and students faste 5. Run `java -jar Taa.jar` in Command Prompt/Terminal to start the app. 6. Enter `help` to display the list of available commands. See [Features](#features) for more information. -## Features - -### Viewing help: `help` -Displays the list of available commands and how to use them. - -Format: `help` - -
+## Features ### Listing all modules: `list_modules` Displays the list of all modules in the module list. @@ -66,10 +60,12 @@ Examples: * `add_module n/Effective Communication for Computing Professionals c/CS2101` * `add_module c/CS2102` +
+ ### Editing a module: `edit_module` Edits the code or name of an existing module. -Format: `edit_module c/ [nc/] [n/]` +Format: `edit_module c/ [nc/] [n/]` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). * `NEW_MODULE_CODE` [Optional] refers to the updated code of the module. * `NEW_MODULE_NAME` [Optional] refers to the updated name of the module. @@ -81,6 +77,8 @@ Examples: * `edit_module c/CS2113T n/software engineering` * `edit_module c/CS2113T nc/cs2113t n/software engineering` +
+ ### Deleting a module: `delete_module` Deletes an existing module from the module list. @@ -93,7 +91,19 @@ Examples:
-### Adding a student to a specified module: `add_student` +### Listing all students in a module: `list_students` +Shows a list of all students in a particular module. + +Format: `list_students c/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). + +Examples: +* `list_students c/CS2113T` +* `list_students c/CS2101` + +
+ +### Adding a student to a module: `add_student` Adds a student to a particular module Format: `add_student c/ i/ n/` @@ -107,7 +117,7 @@ Examples:
-### Editing student information: `edit_student` +### Editing a student's information in a module: `edit_student` Edits student information from a particular module Format: `edit_student c/ s/ i/ n/` @@ -122,7 +132,7 @@ Examples:
-### Deleting student information: `delete_student` +### Deleting a student from a module: `delete_student` Deletes student information from a particular module. Format: `delete_student c/ s/` @@ -134,6 +144,19 @@ Examples:
+### Finding students in a module given a keyword: `find_student` +Displays all students in the module matching the keyword along with their index. + +Format: `find_student c/ k/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `KEYWORD` refers to the keyword used to search the student list of the module. + +Examples: +* `find_student c/CS2113T k/123` +* `find_students c/CS2101 k/Jon` + +
+ ### Listing all assessments in a module: `list_assessments` List all assessments in a module. @@ -193,58 +216,16 @@ Examples:
-### Listing all students in a module: `list_students` -Shows a list of all students in a particular module. - -Format: `list_students c/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). - -Examples: -* `list_students c/CS2113T` -* `list_students c/CS2101` - -
- -### Finding students in a module given a keyword: `find_student` -Displays all students in the module matching the keyword along with their index. +### Listing marks for an assessment: `list_marks` +Lists all students and their marks for an assessment. -Format: `find_student c/ k/` +Format: `list_marks c/ a/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `KEYWORD` refers to the keyword used to search the student list of the module. +* `ASSESSMENT_NAME` refers to the name of the assessment whose marks are to be listed. Examples: -* `find_student c/CS2113T k/123` -* `find_students c/CS2101 k/Jon` - -
- -### Setting attendance for a particular lesson for a student: `set_attendance` -Sets a student's attendance for a lesson. - -Format: `set_attendance c/ s/ l/ p/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the student list of the module. -* `LESSON_NUMBER` refers to the lesson number. -* `PRESENT` refers to the whether a student is present. (1 for present, 0 for not present) - -
- -### Deleting attendance for a particular lesson for a student: `delete_attendance` -Deletes a student's attendance for a lesson. - -Format: `delete_attendance c/ s/ l/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the student list of the module. -* `LESSON_NUMBER` refers to the lesson number. - -
- -### Listing attendance for a particular student: `list_attendance` -Lists a student's attendance. - -Format: `list_attendance c/ s/ @@ -292,7 +273,7 @@ Examples:
-### Finding average marks for an assessment: `average_marks` +### Viewing average marks for an assessment: `average_marks` Computes and prints the average marks for an assessment. Format: `set_marks c/ a/` @@ -305,16 +286,40 @@ Examples:
-### Listing marks for an assessment: `list_marks` -Lists all students and their marks for an assessment. +### Listing attendance for a particular student: `list_attendance` +Lists a student's attendance. -Format: `list_marks c/ a/` +Format: `list_attendance c/ s/ + +### Setting attendance for a particular lesson for a student: `set_attendance` +Sets a student's attendance for a lesson. + +Format: `set_attendance c/ s/ l/ p/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +* `LESSON_NUMBER` refers to the lesson number. +* `PRESENT` refers to the whether a student is present. (`1` for present, `0` for not present) + +
+ +### Deleting attendance for a particular lesson for a student: `delete_attendance` +Deletes a student's attendance for a lesson. + +Format: `delete_attendance c/ s/ l/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +* `LESSON_NUMBER` refers to the lesson number. + +
+ +### Viewing help: `help` +Displays the list of available commands and how to use them. + +Format: `help`
@@ -333,28 +338,28 @@ Format: `exit` {Give a 'cheat sheet' of commands here} -Command | Format and Examples | +Action | Format | ------ | --------------- | -add_module | `add_module c/ n/`
e.g.`add_module c/CS2113T n/Software Engineeringand Object-oriented Programming` -add_student | `add_student c/ i/ n/`
e.g. `add_student c/CS2113T i/a0212345x n/Jon Lim` -add_assessment | `add_assessment c/ n/ m/ w/`
e.g. `add_assessment c/CS2113T n/test m/100 w/20 ` -set_attendance | `set_attendance c/ s/ l/ p/`
e.g. `set_attendance c/CS2113T s/1 l/1 p/1` -set_marks | `set_marks c/ s/ a/ m/`
e.g. `set_marks c/CS2113T s/1 a/Midterms m/70.6` -delete_student | `delete_student c/ s/`
e.g. `delete_student c/cs2113t s/1` -delete_assessment | `delete_assessment c/ n/`
e.g. `delete_assessment c/CS2113T n/finals` -delete_attendance | `delete_attendance c/ s/ l/`
e.g. `delete_attendance c/CS2113T s/1 l/1` -delete_mark | `delete_mark c/ s/ a/`
e.g. `delete_mark c/CS2113T s/1 a/Midterms` -edit_mark | `edit_mark c/ s/ a/ m/`
e.g. `edit_mark c/CS2113T s/1 a/Midterms m/80.6` -edit_student | `edit_student c/ s/ i/ n/`
e.g. `edit_student c/CS2113T s/1 i/12345 n/jon geh` -edit_assessment | `edit_assessment c/ n/ [nn/] [m/]`
e.g. `edit_assessment c/CS2101 n/OP1 m/20 w/10` -list_modules | `list_modules` -list_students | `list_students c/`
e.g. `list_students c/CS2113T` -list_attendance | `list_attendance c/ s/`
e.g. `list_attendance c/CS2113T s/1` -list_assessments | `list_assessments c/`
e.g. `list_assessments c/CS2113T` -list_marks | `list_marks c/ a/`
e.g. `list_marks c/CS2113T a/Midterms` -find_student | `find_student c/ k/`
e.g. `find_student c/CS2113T k/123` -average_marks | `average_marks c/ a/`
e.g. `average_marks c/CS2113T a/Midterms` -help | `help` -exit | `exit` - - +Listing all modules | `list_modules` +Adding a module | `add_module c/ [n/]` +Editing a module | `edit_module c/ [nc/] [n/]` +Deleting a module | `delete_module c/` +Listing all students in a module | `list_students c/` +Adding a student to a module | `add_student c/ i/ n/` +Editing a student's information in a module | `edit_student c/ s/ i/ n/` +Deleting a student from a module | `delete_student c/ s/` +Finding students in a module given a keyword | `find_student c/ k/` +Listing all assessments in a module | `list_assessments c/` +Adding an assessment to a module | `add_assessment c/ n/ m/ w/` +Editing an assessment in a module | `edit_assessment c/ n/ [nn/] [m/]` +Deleting an assessment from a module | `delete_assessment c/ n/` +Listing marks for an assessment: | `list_marks c/ a/` +Setting marks for a student's assessment | `set_marks c/ s/ a/ m/` +Editing marks for a student's assessment | `edit_mark c/ s/ a/ m/` +Deleting marks for a student's assessment | `delete_mark c/ s/ a/` +Viewing average marks for an assessment | `average_marks c/ a/` +Listing attendance for a particular student | `list_attendance c/ s/` +Setting attendance for a particular lesson for a student | `set_attendance c/ s/ l/ p/` +Deleting attendance for a particular lesson for a student | `delete_attendance c/ s/ l/` +Viewing help | `help` +Exiting the program | `exit` From a7db00dcdcc4e905190d3d15c948846a0a187e3d Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 03:30:08 +0800 Subject: [PATCH 190/543] Move checkArgument() call to run() in Taa --- src/main/java/taa/Taa.java | 1 + src/main/java/taa/command/Command.java | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index b32c9e29c5..982db9ad08 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -35,6 +35,7 @@ public void run() { try { Command command = Parser.parseUserInput(userInput); + command.checkArgument(); command.execute(moduleList, ui, storage); isExit = command.isExit(); } catch (TaaException e) { diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 273c5af595..6475cbf54a 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -39,6 +39,7 @@ public abstract class Command { protected static final String MESSAGE_INVALID_STUDENT_INDEX = "Invalid student index."; protected static final String MESSAGE_INVALID_LESSON_NUMBER = "Invalid lesson number."; protected static final String MESSAGE_INVALID_ASSESSMENT_NAME = "Invalid assessment name."; + protected static final String MESSAGE_INVALID_MARKS = "Invalid marks."; protected static final String MESSAGE_NO_STUDENTS = "There are no students in this module"; protected static final String MESSAGE_NO_MARKS = "This student has not been marked yet."; protected static final String MESSAGE_ALREADY_MARKED = "This student has already been marked."; @@ -66,7 +67,7 @@ public Command(String argument, String[] argumentKeys) { protected abstract String getUsage(); - protected abstract void checkArgument() throws TaaException; + public abstract void checkArgument() throws TaaException; public abstract void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException; From 7436a8f0c689c0a03f30cba3623f5ef857afe74c Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 03:37:56 +0800 Subject: [PATCH 191/543] Move argument checking into checkArgument() method --- .../taa/command/AddAssessmentCommand.java | 26 ++--- .../java/taa/command/AddModuleCommand.java | 5 +- .../java/taa/command/AddStudentCommand.java | 17 ++- .../java/taa/command/AverageMarksCommand.java | 20 ++-- .../taa/command/DeleteAssessmentCommand.java | 24 ++-- .../taa/command/DeleteAttendanceCommand.java | 50 +++++---- .../java/taa/command/DeleteMarkCommand.java | 39 ++++--- .../java/taa/command/DeleteModuleCommand.java | 5 +- .../taa/command/DeleteStudentCommand.java | 26 ++--- .../taa/command/EditAssessmentCommand.java | 103 ++++++++++-------- .../java/taa/command/EditMarkCommand.java | 49 ++++++--- .../java/taa/command/EditModuleCommand.java | 4 +- .../java/taa/command/EditStudentCommand.java | 27 +++-- src/main/java/taa/command/ExitCommand.java | 4 +- .../java/taa/command/FindStudentCommand.java | 16 ++- src/main/java/taa/command/HelpCommand.java | 4 +- .../taa/command/ListAssessmentsCommand.java | 16 ++- .../taa/command/ListAttendanceCommand.java | 25 +++-- .../java/taa/command/ListMarksCommand.java | 15 ++- .../java/taa/command/ListModulesCommand.java | 4 +- .../java/taa/command/ListStudentsCommand.java | 16 ++- .../taa/command/SetAttendanceCommand.java | 35 +++--- .../java/taa/command/SetMarksCommand.java | 43 +++++--- 23 files changed, 296 insertions(+), 277 deletions(-) diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/AddAssessmentCommand.java index 364eb18046..c0d7731249 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/AddAssessmentCommand.java @@ -24,20 +24,20 @@ public class AddAssessmentCommand extends Command { private static final String MESSAGE_FAIL_TO_ADD = "Fail to add assessment."; private static final String MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE = "%s %s/ %s/ " - + "%s/ %s/"; + + "%s/ %s/"; private static final String MESSAGE_FORMAT_INVALID_WEIGHTAGE = "Invalid weightage. " - + "Weightage must be between %,.2f and %,.2f (inclusive)"; + + "Weightage must be between %,.2f and %,.2f (inclusive)"; private static final String MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS = "Invalid maximum marks. " - + "Maximum marks must be larger than %d (inclusive)"; + + "Maximum marks must be larger than %d (inclusive)"; private static final String MESSAGE_FORMAT_ASSESSMENT_ADDED = "Assessment added to %s:\n" - + " %s\nThere are %d assessments in the %s."; + + " %s\nThere are %d assessments in the %s."; public AddAssessmentCommand(String argument) { super(argument, ADD_ASSESSMENT_ARGUMENT_KEYS); } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -91,8 +91,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - checkArgument(); - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { @@ -124,18 +122,18 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc assert ui != null : "ui should exist."; ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_ADDED, moduleCode, - assessment, assessmentList.getSize(), module)); + assessment, assessmentList.getSize(), module)); } @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE, - COMMAND_ADD_ASSESSMENT, - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME, - KEY_MAXIMUM_MARKS, - KEY_WEIGHTAGE + MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE, + COMMAND_ADD_ASSESSMENT, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME, + KEY_MAXIMUM_MARKS, + KEY_WEIGHTAGE ); } } diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/AddModuleCommand.java index 96e9d5a3f3..03f5a58e23 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/AddModuleCommand.java @@ -23,7 +23,7 @@ public AddModuleCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -48,8 +48,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - checkArgument(); - assert argumentMap.containsKey(KEY_MODULE_CODE); String moduleCode = argumentMap.get(KEY_MODULE_CODE); @@ -65,7 +63,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc TaaLogger.LOGGER.logInfo(String.format("Added module: %s", module)); storage.save(moduleList); - ui.printMessage(String.format(MESSAGE_FORMAT_MODULE_ADDED, module, moduleList.getSize())); } diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index 77d44eeb10..f52bea6e9d 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -23,8 +23,14 @@ public AddStudentCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } } /** @@ -37,14 +43,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { @@ -59,7 +57,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc studentList.addStudent(student); storage.save(moduleList); - ui.printMessage(String.format(MESSAGE_STUDENT_ADDED_FORMAT, moduleCode, student)); } diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index 2b972096ed..eb48f80904 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -21,15 +21,21 @@ public class AverageMarksCommand extends Command { private static final String MESSAGE_FORMAT_AVERAGE_MARKS_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_AVERAGE_MARKS = "Average marks for %s is %,.2f"; private static final String MESSAGE_FORMAT_AVERAGE_MARKS_WITH_UNMARKED = "Average marks for %s is %,.2f\n" - + "Note that %d student(s) have yet to be marked!"; + + "Note that %d student(s) have yet to be marked!"; public AverageMarksCommand(String argument) { super(argument, AVERAGE_MARKS_ARGUMENT_KEYS); } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } } /** @@ -42,14 +48,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { @@ -96,7 +94,7 @@ private void printAverageMarks(Ui ui, Module module, Assessment assessment) { ui.printMessage(String.format(MESSAGE_FORMAT_AVERAGE_MARKS, assessmentName, averageMarks)); } else { ui.printMessage(String.format(MESSAGE_FORMAT_AVERAGE_MARKS_WITH_UNMARKED, - assessmentName, averageMarks, unmarkedStudents)); + assessmentName, averageMarks, unmarkedStudents)); } } diff --git a/src/main/java/taa/command/DeleteAssessmentCommand.java b/src/main/java/taa/command/DeleteAssessmentCommand.java index 51cbb1a9da..4101373704 100644 --- a/src/main/java/taa/command/DeleteAssessmentCommand.java +++ b/src/main/java/taa/command/DeleteAssessmentCommand.java @@ -21,8 +21,14 @@ public DeleteAssessmentCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } } /** @@ -35,14 +41,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { @@ -67,10 +65,10 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_DELETE_ASSESSMENT_USAGE, - COMMAND_DELETE_ASSESSMENT, - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME + MESSAGE_FORMAT_DELETE_ASSESSMENT_USAGE, + COMMAND_DELETE_ASSESSMENT, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME ); } } diff --git a/src/main/java/taa/command/DeleteAttendanceCommand.java b/src/main/java/taa/command/DeleteAttendanceCommand.java index c88e4684c8..6ec9335fa1 100644 --- a/src/main/java/taa/command/DeleteAttendanceCommand.java +++ b/src/main/java/taa/command/DeleteAttendanceCommand.java @@ -15,13 +15,13 @@ public class DeleteAttendanceCommand extends Command { private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_LESSON_NUMBER = "l"; private static final String[] DELETE_ATTENDANCE_ARGUMENT_KEYS = { - KEY_MODULE_CODE, + KEY_MODULE_CODE, KEY_STUDENT_INDEX, KEY_LESSON_NUMBER }; private static final String MESSAGE_FORMAT_DELETE_ATTENDANCE_USAGE = - "%s %s/ %s/ %s/"; + "%s %s/ %s/ %s/"; private static final String MESSAGE_FORMAT_ATTENDANCE_DELETED = "Attendance removed for %s:\n Lesson %s"; @@ -30,8 +30,24 @@ public DeleteAttendanceCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + String lessonNumInput = argumentMap.get(KEY_LESSON_NUMBER); + if (!Util.isStringInteger(lessonNumInput)) { + throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); + } } /** @@ -44,14 +60,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { @@ -59,9 +67,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); - if (!Util.isStringInteger(studentIndexInput)) { - throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); - } + assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; Student student = module.getStudentList().getStudentAt(studentIndex); @@ -71,10 +77,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String lessonNumInput = argumentMap.get(KEY_LESSON_NUMBER); - if (!Util.isStringInteger(lessonNumInput)) { - throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); - } - + assert Util.isStringInteger(lessonNumInput); AttendanceList attendanceList = student.getAttendanceList(); Attendance attendance = attendanceList.deleteAttendance(lessonNumInput); if (attendance == null) { @@ -82,18 +85,17 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } storage.save(moduleList); - ui.printMessage(String.format(MESSAGE_FORMAT_ATTENDANCE_DELETED, student, lessonNumInput)); } @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_DELETE_ATTENDANCE_USAGE, - COMMAND_DELETE_ATTENDANCE, - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_LESSON_NUMBER + MESSAGE_FORMAT_DELETE_ATTENDANCE_USAGE, + COMMAND_DELETE_ATTENDANCE, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_LESSON_NUMBER ); } } diff --git a/src/main/java/taa/command/DeleteMarkCommand.java b/src/main/java/taa/command/DeleteMarkCommand.java index 733da06867..ca3976495b 100644 --- a/src/main/java/taa/command/DeleteMarkCommand.java +++ b/src/main/java/taa/command/DeleteMarkCommand.java @@ -21,48 +21,59 @@ public class DeleteMarkCommand extends Command { KEY_ASSESSMENT_NAME }; private static final String MESSAGE_FORMAT_DELETE_MARKS_USAGE = "%s %s/ %s/ " - + "%s/"; + + "%s/"; private static final String MESSAGE_FORMAT_MARKS_DELETED = "Marks for student '%s' have been deleted for" - + " assessment '%s'"; + + " assessment '%s'"; public DeleteMarkCommand(String argument) { super(argument, DELETE_MARK_ARGUMENT_KEYS); } @Override - protected void checkArgument() throws TaaException { - - } - - @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + public void checkArgument() throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } + + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; + StudentList studentList = module.getStudentList(); Student student = studentList.getStudentAt(studentIndex); - if (student == null || !Util.isStringInteger(studentIndexInput)) { + if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } + AssessmentList assessmentList = module.getAssessmentList(); String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = assessmentList.getAssessment(assessmentName); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } + if (student.getResults().get(assessmentName) == null) { throw new TaaException(MESSAGE_NO_MARKS); } + deleteMark(ui, student, assessmentName); storage.save(moduleList); } @@ -76,11 +87,11 @@ private void deleteMark(Ui ui, Student student, String assessmentName) { @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_DELETE_MARKS_USAGE, - COMMAND_DELETE_MARK, - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_ASSESSMENT_NAME + MESSAGE_FORMAT_DELETE_MARKS_USAGE, + COMMAND_DELETE_MARK, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_ASSESSMENT_NAME ); } } diff --git a/src/main/java/taa/command/DeleteModuleCommand.java b/src/main/java/taa/command/DeleteModuleCommand.java index 964111c4ed..8a3e2d099c 100644 --- a/src/main/java/taa/command/DeleteModuleCommand.java +++ b/src/main/java/taa/command/DeleteModuleCommand.java @@ -19,7 +19,7 @@ public DeleteModuleCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -31,8 +31,6 @@ protected void checkArgument() throws TaaException { @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - checkArgument(); - assert argumentMap.containsKey(KEY_MODULE_CODE); String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); @@ -49,7 +47,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } storage.save(moduleList); - ui.printMessage(message); } diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 233c6efddc..6f0a293151 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -22,8 +22,19 @@ public DeleteStudentCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } } /** @@ -36,14 +47,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { @@ -51,9 +54,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); - if (!Util.isStringInteger(studentIndexInput)) { - throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); - } + assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; StudentList studentList = module.getStudentList(); @@ -64,7 +65,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } storage.save(moduleList); - ui.printMessage(String.format(MESSAGE_FORMAT_STUDENT_DELETED, moduleCode, student)); } diff --git a/src/main/java/taa/command/EditAssessmentCommand.java b/src/main/java/taa/command/EditAssessmentCommand.java index 502fc0f4b9..b6d8323acf 100644 --- a/src/main/java/taa/command/EditAssessmentCommand.java +++ b/src/main/java/taa/command/EditAssessmentCommand.java @@ -23,11 +23,11 @@ public class EditAssessmentCommand extends Command { }; private static final String MESSAGE_FORMAT_EDIT_ASSESSMENT_USAGE = "%s %s/ " - + "%s/ [%s/] [%s/] [%s/]"; + + "%s/ [%s/] [%s/] [%s/]"; private static final String MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE = "Invalid new weightage. " - + "Weightage must be between %,.2f and %,.2f (inclusive)"; + + "Weightage must be between %,.2f and %,.2f (inclusive)"; private static final String MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS = "Invalid new maximum marks. " - + "Maximum marks must be larger than %d (inclusive)"; + + "Maximum marks must be larger than %d (inclusive)"; private static final String MESSAGE_FORMAT_ASSESSMENT_EDITED = "Assessment in %s updated:\n %s"; public EditAssessmentCommand(String argument) { @@ -35,8 +35,42 @@ public EditAssessmentCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + boolean hasModuleCode = argumentMap.containsKey(KEY_MODULE_CODE); + boolean hasAssessmentName = argumentMap.containsKey(KEY_ASSESSMENT_NAME); + boolean hasNewAssessmentName = argumentMap.containsKey(KEY_NEW_ASSESSMENT_NAME); + boolean hasNewMaximumMarks = argumentMap.containsKey(KEY_NEW_MAXIMUM_MARKS); + boolean hasNewWeightage = argumentMap.containsKey(KEY_NEW_WEIGHTAGE); + boolean hasNecessaryArguments = hasModuleCode && hasAssessmentName + && (hasNewAssessmentName || hasNewMaximumMarks || hasNewWeightage); + if (!hasNecessaryArguments) { + throw new TaaException(getMissingArgumentMessage()); + } + String newMaximumMarksString = argumentMap.getOrDefault(KEY_NEW_MAXIMUM_MARKS, null); + if (newMaximumMarksString != null) { + if (!Util.isStringInteger(newMaximumMarksString)) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS, + Assessment.MINIMUM_MARKS) + ); + } + } + + String newWeightageString = argumentMap.getOrDefault(KEY_NEW_WEIGHTAGE, null); + if (newWeightageString != null) { + if (!Util.isStringDouble(newWeightageString)) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) + ); + } + } } /** @@ -51,21 +85,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - boolean hasModuleCode = argumentMap.containsKey(KEY_MODULE_CODE); - boolean hasAssessmentName = argumentMap.containsKey(KEY_ASSESSMENT_NAME); - boolean hasNewAssessmentName = argumentMap.containsKey(KEY_NEW_ASSESSMENT_NAME); - boolean hasNewMaximumMarks = argumentMap.containsKey(KEY_NEW_MAXIMUM_MARKS); - boolean hasNewWeightage = argumentMap.containsKey(KEY_NEW_WEIGHTAGE); - boolean hasNecessaryArguments = hasModuleCode && hasAssessmentName - && (hasNewAssessmentName || hasNewMaximumMarks || hasNewWeightage); - if (!hasNecessaryArguments) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { @@ -79,7 +98,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } assert (argumentMap.containsKey(KEY_NEW_ASSESSMENT_NAME) || argumentMap.containsKey(KEY_NEW_MAXIMUM_MARKS) - || argumentMap.containsKey(KEY_NEW_WEIGHTAGE)) : "a new value to edit should at least exist."; + || argumentMap.containsKey(KEY_NEW_WEIGHTAGE)) : "a new value to edit should at least exist."; String newName = argumentMap.getOrDefault(KEY_NEW_ASSESSMENT_NAME, null); if (newName != null) { assessment.setName(newName); @@ -87,18 +106,12 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc String newMaximumMarksString = argumentMap.getOrDefault(KEY_NEW_MAXIMUM_MARKS, null); if (newMaximumMarksString != null) { - if (!Util.isStringInteger(newMaximumMarksString)) { - throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS, - Assessment.MINIMUM_MARKS) - ); - } - + assert Util.isStringInteger(newMaximumMarksString); int newMaximumMarks = Integer.parseInt(newMaximumMarksString); if (newMaximumMarks < Assessment.MINIMUM_MARKS) { throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS, - Assessment.MINIMUM_MARKS) + MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS, + Assessment.MINIMUM_MARKS) ); } assessment.setMaximumMarks(newMaximumMarks); @@ -106,42 +119,36 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc String newWeightageString = argumentMap.getOrDefault(KEY_NEW_WEIGHTAGE, null); if (newWeightageString != null) { - if (!Util.isStringDouble(newWeightageString)) { - throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, - Assessment.WEIGHTAGE_RANGE[0], - Assessment.WEIGHTAGE_RANGE[1]) - ); - } - + assert Util.isStringDouble(newWeightageString); double newWeightage = Double.parseDouble(newWeightageString); if (!Assessment.isWeightageWithinRange(newWeightage)) { throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, - Assessment.WEIGHTAGE_RANGE[0], - Assessment.WEIGHTAGE_RANGE[1]) + MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) ); } assessment.setWeightage(newWeightage); } + assert storage != null : "storage should exist."; storage.save(moduleList); assert ui != null : "ui should exist."; ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_EDITED, moduleCode, - assessment)); + assessment)); } @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_EDIT_ASSESSMENT_USAGE, - COMMAND_EDIT_ASSESSMENT, - KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME, - KEY_NEW_ASSESSMENT_NAME, - KEY_NEW_MAXIMUM_MARKS, - KEY_NEW_WEIGHTAGE + MESSAGE_FORMAT_EDIT_ASSESSMENT_USAGE, + COMMAND_EDIT_ASSESSMENT, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME, + KEY_NEW_ASSESSMENT_NAME, + KEY_NEW_MAXIMUM_MARKS, + KEY_NEW_WEIGHTAGE ); } } diff --git a/src/main/java/taa/command/EditMarkCommand.java b/src/main/java/taa/command/EditMarkCommand.java index 582f4a65e2..6900b668c9 100644 --- a/src/main/java/taa/command/EditMarkCommand.java +++ b/src/main/java/taa/command/EditMarkCommand.java @@ -24,9 +24,9 @@ public class EditMarkCommand extends Command { }; private static final String MESSAGE_FORMAT_EDIT_MARKS_USAGE = "%s %s/ %s/ " - + "%s/ %s/"; + + "%s/ %s/"; private static final String MESSAGE_FORMAT_INVALID_MARKS = "Invalid Marks. " - + "Marks must be between %d and %,.2f (inclusive)"; + + "Marks must be between %d and %,.2f (inclusive)"; private static final String MESSAGE_FORMAT_MARKS_EDITED = "Marks edited for %s: from %,.2f to %,.2f for %s"; public EditMarkCommand(String argument) { @@ -34,45 +34,62 @@ public EditMarkCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { - - } - - @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + public void checkArgument() throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } + if (!hasAllArguments()) { throw new TaaException(getMissingArgumentMessage()); } + + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + + String marksInput = argumentMap.get(KEY_NEW_MARKS); + if (!Util.isStringDouble(marksInput)) { + throw new TaaException(MESSAGE_INVALID_MARKS); + } + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; StudentList studentList = module.getStudentList(); Student student = studentList.getStudentAt(studentIndex); - if (student == null || !Util.isStringInteger(studentIndexInput)) { + if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } + AssessmentList assessmentList = module.getAssessmentList(); String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = assessmentList.getAssessment(assessmentName); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } + String marksInput = argumentMap.get(KEY_NEW_MARKS); + assert Util.isStringDouble(marksInput); double marks = Double.parseDouble(marksInput); double maximumMarks = assessment.getMaximumMarks(); - if ((!Util.isStringDouble(marksInput)) || !(assessment.isMarksValid(marks))) { + if (!(assessment.isMarksValid(marks))) { throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, 0, maximumMarks)); } + if (student.getResults().get(assessmentName) == null) { throw new TaaException(MESSAGE_NO_MARKS); } + editMark(ui, student, assessmentName, marks); storage.save(moduleList); } @@ -87,12 +104,12 @@ private void editMark(Ui ui, Student student, String assessmentName, double newM @Override protected String getUsage() { return String.format( - MESSAGE_FORMAT_EDIT_MARKS_USAGE, - COMMAND_EDIT_MARK, - KEY_MODULE_CODE, - KEY_STUDENT_INDEX, - KEY_ASSESSMENT_NAME, - KEY_NEW_MARKS + MESSAGE_FORMAT_EDIT_MARKS_USAGE, + COMMAND_EDIT_MARK, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX, + KEY_ASSESSMENT_NAME, + KEY_NEW_MARKS ); } } diff --git a/src/main/java/taa/command/EditModuleCommand.java b/src/main/java/taa/command/EditModuleCommand.java index f25b82c8d6..0c33b33314 100644 --- a/src/main/java/taa/command/EditModuleCommand.java +++ b/src/main/java/taa/command/EditModuleCommand.java @@ -25,7 +25,7 @@ public EditModuleCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { if (argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -44,8 +44,6 @@ protected void checkArgument() throws TaaException { @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - checkArgument(); - assert argumentMap.containsKey(KEY_MODULE_CODE); String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 5edaf1fbe0..300d6c451e 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -30,8 +30,19 @@ public EditStudentCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } } /** @@ -44,14 +55,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { @@ -59,10 +62,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); - if (!Util.isStringInteger(studentIndexInput)) { - throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); - } - + assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; StudentList studentList = module.getStudentList(); @@ -78,7 +78,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc student.setName(newName); storage.save(moduleList); - ui.printMessage(String.format(MESSAGE_FORMAT_STUDENT_EDITED, student)); } diff --git a/src/main/java/taa/command/ExitCommand.java b/src/main/java/taa/command/ExitCommand.java index bacac2cc78..36d6778932 100644 --- a/src/main/java/taa/command/ExitCommand.java +++ b/src/main/java/taa/command/ExitCommand.java @@ -13,7 +13,7 @@ public ExitCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { if (!argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -29,8 +29,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - checkArgument(); - ui.printExitMessage(); this.isExit = true; } diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 8d5d8f9b98..7e0015527f 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -25,8 +25,14 @@ public FindStudentCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } } /** @@ -39,14 +45,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index fa5517572b..2a063995b3 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -38,7 +38,7 @@ public HelpCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { if (!argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -46,8 +46,6 @@ protected void checkArgument() throws TaaException { @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - checkArgument(); - StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < commands.length; i += 1) { Command command = commands[i]; diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/ListAssessmentsCommand.java index fb87da0dd5..9cc0976705 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/ListAssessmentsCommand.java @@ -21,8 +21,14 @@ public ListAssessmentsCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } } /** @@ -35,14 +41,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/ListAttendanceCommand.java index a86ee1594d..f6e68f80d1 100644 --- a/src/main/java/taa/command/ListAttendanceCommand.java +++ b/src/main/java/taa/command/ListAttendanceCommand.java @@ -24,8 +24,19 @@ public ListAttendanceCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } } /** @@ -38,14 +49,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { @@ -53,9 +56,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); - if (!Util.isStringInteger(studentIndexInput)) { - throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); - } + assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; StudentList studentList = module.getStudentList(); diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/ListMarksCommand.java index f70476401e..d22ddc579a 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/ListMarksCommand.java @@ -28,8 +28,14 @@ public ListMarksCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } } /** @@ -42,13 +48,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { diff --git a/src/main/java/taa/command/ListModulesCommand.java b/src/main/java/taa/command/ListModulesCommand.java index de64c079d6..16d7304be7 100644 --- a/src/main/java/taa/command/ListModulesCommand.java +++ b/src/main/java/taa/command/ListModulesCommand.java @@ -15,7 +15,7 @@ public ListModulesCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { if (!argument.isEmpty()) { throw new TaaException(getUsageMessage()); } @@ -31,8 +31,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - checkArgument(); - String message; if (moduleList.getSize() == 0) { message = MESSAGE_LIST_EMPTY; diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index 15fef3c307..eacb9c033c 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -21,8 +21,14 @@ public ListStudentsCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } } /** @@ -35,14 +41,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/SetAttendanceCommand.java index e7d3bc7945..40461867b3 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/SetAttendanceCommand.java @@ -40,8 +40,24 @@ public SetAttendanceCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + String lessonNumberInput = argumentMap.get(KEY_LESSON_NUMBER); + if (!Util.isStringInteger(lessonNumberInput)) { + throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); + } } /** @@ -53,14 +69,6 @@ protected void checkArgument() throws TaaException { * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { @@ -68,9 +76,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); - if (!Util.isStringInteger(studentIndexInput)) { - throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); - } + assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; StudentList studentList = module.getStudentList(); @@ -80,10 +86,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String lessonNumberInput = argumentMap.get(KEY_LESSON_NUMBER); - if (!Util.isStringInteger(lessonNumberInput)) { - throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); - } - + assert Util.isStringInteger(lessonNumberInput); int lessonNumber = Integer.parseInt(lessonNumberInput); if (lessonNumber < Attendance.getMinLessonNumber()) { throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index ea66547133..29a37e1407 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -37,8 +37,24 @@ public SetMarksCommand(String argument) { } @Override - protected void checkArgument() throws TaaException { + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + String marksInput = argumentMap.get(KEY_MARKS); + if (!Util.isStringDouble(marksInput)) { + throw new TaaException(MESSAGE_INVALID_MARKS); + } } /** @@ -51,15 +67,6 @@ protected void checkArgument() throws TaaException { */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - String moduleCode = argumentMap.get(KEY_MODULE_CODE); Module module = moduleList.getModuleWithCode(moduleCode); if (module == null) { @@ -67,11 +74,11 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = module.getStudentList(); Student student = studentList.getStudentAt(studentIndex); - if (student == null || !Util.isStringInteger(studentIndexInput)) { + if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } @@ -86,11 +93,13 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } String marksInput = argumentMap.get(KEY_MARKS); + assert Util.isStringDouble(marksInput); double marks = Double.parseDouble(marksInput); - double maxMarks = assessment.getMaximumMarks(); - if ((!Util.isStringDouble(marksInput)) || !(assessment.isMarksValid(marks))) { + if (!(assessment.isMarksValid(marks))) { + double maxMarks = assessment.getMaximumMarks(); throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, 0, maxMarks)); } + setMarks(ui, student, assessmentName, marks); storage.save(moduleList); } @@ -98,10 +107,10 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc /** * Sets the marks for a student's assessment. * - * @param ui The ui instance to handle interactions with the user. - * @param student The student instance to set the mark for. + * @param ui The ui instance to handle interactions with the user. + * @param student The student instance to set the mark for. * @param assessmentName The name of the assessment to be marked. - * @param marks The marks to set for the assessment. + * @param marks The marks to set for the assessment. */ private void setMarks(Ui ui, Student student, String assessmentName, double marks) { assert marks >= 0; From aa3c5ef2fece528a1de507326d2bf075c2cbf068 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Mon, 25 Oct 2021 13:31:26 +0800 Subject: [PATCH 192/543] add author for student class and commands --- src/main/java/taa/command/AddStudentCommand.java | 2 ++ src/main/java/taa/command/DeleteStudentCommand.java | 1 + src/main/java/taa/command/EditStudentCommand.java | 1 + src/main/java/taa/command/FindStudentCommand.java | 1 + src/main/java/taa/command/ListStudentsCommand.java | 1 + src/main/java/taa/student/Student.java | 1 + src/main/java/taa/student/StudentList.java | 1 + 7 files changed, 8 insertions(+) diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index 7241fc5d94..c3da6756a9 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -1,3 +1,4 @@ +//@@author hozhenhong99 package taa.command; import taa.storage.Storage; @@ -22,6 +23,7 @@ public AddStudentCommand(String argument) { super(argument, ADD_STUDENT_ARGUMENT_KEYS); } + /** * Executes the add_student command and adds a student to a particular module. * diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 8a1587abce..96a10c965c 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -1,3 +1,4 @@ +//@@author hozhenhong99 package taa.command; import taa.storage.Storage; diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 6662013b88..4dfe5052a8 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -1,3 +1,4 @@ +//@@author hozhenhong99 package taa.command; import taa.storage.Storage; diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index 11af1a8c81..b06cba3e41 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -1,3 +1,4 @@ +//@@author hozhenhong99 package taa.command; import taa.storage.Storage; diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index c6a86044c8..320a5559bc 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -1,3 +1,4 @@ +//@@author hozhenhong99 package taa.command; import taa.storage.Storage; diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index ce64431110..de08adac9f 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -1,3 +1,4 @@ +//@@author hozhenhong99 package taa.student; import taa.ClassChecker; diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index 14d4ad4dad..be03650ecd 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -1,3 +1,4 @@ +//@@author hozhenhong99 package taa.student; import taa.ClassChecker; From 843bfd89c545c6fa532782eebc296b313282364a Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Mon, 25 Oct 2021 21:41:54 +0800 Subject: [PATCH 193/543] fix formatting errors --- src/main/java/taa/command/AddStudentCommand.java | 2 +- src/main/java/taa/command/DeleteStudentCommand.java | 2 +- src/main/java/taa/command/EditStudentCommand.java | 2 +- src/main/java/taa/command/FindStudentCommand.java | 2 +- src/main/java/taa/command/ListStudentsCommand.java | 2 +- src/main/java/taa/student/Student.java | 2 +- src/main/java/taa/student/StudentList.java | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/AddStudentCommand.java index c3da6756a9..fdb5123267 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/AddStudentCommand.java @@ -1,6 +1,6 @@ -//@@author hozhenhong99 package taa.command; +//@@author hozhenhong99 import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/DeleteStudentCommand.java index 96a10c965c..ad0462c1fd 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/DeleteStudentCommand.java @@ -1,6 +1,6 @@ -//@@author hozhenhong99 package taa.command; +//@@author hozhenhong99 import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/EditStudentCommand.java index 4dfe5052a8..9c5093f836 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/EditStudentCommand.java @@ -1,6 +1,6 @@ -//@@author hozhenhong99 package taa.command; +//@@author hozhenhong99 import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/FindStudentCommand.java index b06cba3e41..9552986254 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/FindStudentCommand.java @@ -1,6 +1,6 @@ -//@@author hozhenhong99 package taa.command; +//@@author hozhenhong99 import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/ListStudentsCommand.java index 320a5559bc..1c57986fc8 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/ListStudentsCommand.java @@ -1,6 +1,6 @@ -//@@author hozhenhong99 package taa.command; +//@@author hozhenhong99 import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index de08adac9f..f6f35a91c3 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -1,6 +1,6 @@ -//@@author hozhenhong99 package taa.student; +//@@author hozhenhong99 import taa.ClassChecker; import taa.assessment.Assessment; import taa.assessment.AssessmentList; diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index be03650ecd..6bcb70f630 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -1,6 +1,6 @@ -//@@author hozhenhong99 package taa.student; +//@@author hozhenhong99 import taa.ClassChecker; import java.util.ArrayList; From 94c62e7aef3c1a62ab0b126a2334052c0af3c2a1 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 22:00:01 +0800 Subject: [PATCH 194/543] Update Architecture Diagram --- docs/diagrams/ArchitectureDiagram.png | Bin 16039 -> 16400 bytes docs/diagrams/ArchitectureDiagram.puml | 38 +++++++++---------------- 2 files changed, 14 insertions(+), 24 deletions(-) diff --git a/docs/diagrams/ArchitectureDiagram.png b/docs/diagrams/ArchitectureDiagram.png index 1a4942b2dd8660cb73c7795c85ab2b2b187edfe3..9c9aa0fbbdd17b39d0298fe24ab59d8b08bb89a1 100644 GIT binary patch literal 16400 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 Cv=lf1 literal 16039 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 !include !include - -skinparam Shadowing false -skinparam MinClassWidth 50 +!include style.puml skinparam Class { FontColor #FFFFFF @@ -14,9 +12,8 @@ skinparam Class { FontName Arial } -hide footbox -hide members -hide circle +Class "<$user>" as User #Red +Class "<$documents>" as File #Gray Package " "<>{ Class UI #ForestGreen @@ -24,28 +21,21 @@ Package " "<>{ Class Storage #DarkGoldenRod Class Main #IndianRed Class Command #DarkSlateBlue - Class Model #DarkRed - Class Commons #Purple - Class Dummy #White + Class ModuleList #DarkRed Class Parser #Navy Class Util #LightSeaGreen } -Class "<$user>" as User #Red -Class "<$documents>" as File #Gray -Main -down-> Taa -UI -> Taa -Taa -> Command +User <-down-> UI +UI -down-> Taa +Main -right-> Taa +Taa <-down-> Parser +Taa -right-> Command +Command <-down-> Util Command -up-> UI -Command -right-> Storage -Command -down-> Model -Model -right[hidden]- Dummy -Dummy .down.> Commons -Dummy .down.> Commons -Dummy .down.> Commons -Commons -left- Parser -Commons -down- Util +Command -down-> Storage +Storage -up-> Taa +Storage <-down-> File +Command <-right-> ModuleList -UI <-up- User -Storage -right-> File @enduml From 06f617f293a136de1efdd0fe8b664cefe62070a0 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 22:00:16 +0800 Subject: [PATCH 195/543] Update Architecture Sequence Diagram --- docs/diagrams/ArchitectureSequenceDiagram.png | Bin 28022 -> 75382 bytes .../diagrams/ArchitectureSequenceDiagram.puml | 112 +++++++++++++++--- 2 files changed, 94 insertions(+), 18 deletions(-) diff --git a/docs/diagrams/ArchitectureSequenceDiagram.png b/docs/diagrams/ArchitectureSequenceDiagram.png index 3f7bcf89e5b436579bdcebec96a4f376b4efed82..895f6b8bce3423a1ee6d0fffb6a9167183a1bb9c 100644 GIT binary patch literal 75382 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 diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml index 0c4dcde1df..44abb5fcd7 100644 --- a/docs/diagrams/ArchitectureSequenceDiagram.puml +++ b/docs/diagrams/ArchitectureSequenceDiagram.puml @@ -58,15 +58,6 @@ activate util util --> command deactivate util -alt Exception -command --> taa : throw :TaaException -taa -> ui : printException(message:String) -activate ui -ui -> user : Display Exception message -ui --> taa -deactivate ui - -else else command --> taa deactivate command @@ -83,15 +74,6 @@ activate moduleList moduleList --> command deactivate moduleList -alt Exception -command --> taa : throw :TaaException -taa -> ui : printException(message:String) -activate ui -ui -> user : Display Exception message -ui --> taa -deactivate ui - -else else command -> storage : save(moduleList:ModuleList) activate storage storage --> command @@ -115,7 +97,6 @@ taa -[hidden]-> command destroy command taa -[hidden]-> command -end end @enduml \ No newline at end of file From d1a114a4b556bc9226e64170e77677ee3caff3a5 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 26 Oct 2021 14:02:58 +0800 Subject: [PATCH 203/543] Remove less important details in AddModuleSequenceDiagram --- docs/diagrams/AddModuleSequenceDiagram.png | Bin 48032 -> 42870 bytes docs/diagrams/AddModuleSequenceDiagram.puml | 6 ------ 2 files changed, 6 deletions(-) diff --git a/docs/diagrams/AddModuleSequenceDiagram.png b/docs/diagrams/AddModuleSequenceDiagram.png index ad20b28b9fdbc9575c1e1368960a2841367ae7e2..d2deebb3f480f1ce2a1f1f05c552c4cee067494a 100644 GIT binary patch literal 42870 zcmcG$bwE_x_dbjuAxNkoN+T+W0#ed7BA`ghfV7H8Ni%eZA}OdK-7*ZRbc+E<*U+Vd z#L(Tty9Y4uy`S&zpZA~370#S<_TFo)=ULBMYn~}9%90Y(5aZzBklvJ&R>i?NdKU)= z*N+Gn{Knx#gAn*}$?nEoI|EBAr^kkm>~LfaEevh$+ZjG&df>!lY-eXB%*AE(_`Zc5 z%=|H@fu;G0t3q@*IC!ciYIp5^{2u2BxQ%1%th$2IfFwnwc7w<3H<8lb6y<(Ce&--; zaK1|?2%M!55vwQFd(C>v$&#RZE=D~G)=hPlUp}w3#1vaTa(HBOp6aF=4FUZ$9yOnw z8-c1A;bV%J&msJ8*l&$$y*ujfOPN4#79t+I^qL4?cRku6_?ZByhVPlcbE)@*MN^N2 z+3=N7m4w6+P{;IKZ0ub(3QHh(eA18kM3q-~?Ssxsyo#l21Pl=gv+rr(#}=--zN@F; zap^H(R$IKFa)l(v;47ZJ?CYae_iJ9Z^k|$&NA%?0hXn{nwA_C-`{2Apew^2wf@ocl zgzgaW+ld?N=x67TSNY>p2VKy)Qa0IipW1EJK1YZ&p9Imh7V84oJa(cPR2Wbx;_dljv>186rRT6Sgvw1*{<7pJ+VkqA zpPpbJi7K{ubh*Aw_?tUg|T^~~|IX7wa9w}%0AaY`jYcuU9ckIxSW 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

n1HfvE@q5XLM5(|tJ<~U<)ug+n`dZH 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 diff --git a/docs/diagrams/AddModuleSequenceDiagram.puml b/docs/diagrams/AddModuleSequenceDiagram.puml index 7c5ff0ce84..38d64c70c8 100644 --- a/docs/diagrams/AddModuleSequenceDiagram.puml +++ b/docs/diagrams/AddModuleSequenceDiagram.puml @@ -40,12 +40,6 @@ deactivate addModuleCommand taa -> addModuleCommand : execute(moduleList:ModuleList, ui:Ui, storage:Storage) activate addModuleCommand -addModuleCommand -> moduleList : getModuleWithCode(moduleCode:String) -activate moduleList - -moduleList --> addModuleCommand : module:Module -deactivate moduleList - create module addModuleCommand -> module activate module From 5542d72c8d9e2e072fbd4b4a005c7f7757b8aedf Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 26 Oct 2021 15:31:05 +0800 Subject: [PATCH 204/543] Update Add Module sequence explanation --- docs/DeveloperGuide.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index d80aa0240e..998d140c17 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -52,15 +52,11 @@ Steps: 1. The `Taa` instance reads in a user input through the `Ui.getUserInput()` method. 2. The user input is then parsed using the `Parser.parseUserInput(userInput:String)` static method and a `Command` object is returned. -3. `AddModuleCommand.checkArguments()` is then called to check if the arguments are valid. **If an exception occurs, the exception -message will be printed out and the command execution ends here.** -4. After checking the arguments, `Command.execute(moduleList:ModuleList, ui:Ui, storage:Storage)` will be called. -5. Within `AddModuleCommand.checkArguments()`, `ModuleList.getModuleWithCode(moduleCode:String)` is called and will return a -`Module` object if a module with the `moduleCode` is found. **If `ModuleList.getModuleWithCode(moduleCode:String)` returns -an object, an exception will occur (the exception message will be printed out) and the command execution ends here.** -6. A new `Module` object is created and the `ModuleList.addModule(module:Module)` method be invoked to add the `Module` +3. `AddModuleCommand.checkArguments()` is then called to check if the arguments are valid. +4. After checking the arguments, `Command.execute(moduleList:ModuleList, ui:Ui, storage:Storage)` will be called. A new +`Module` object is created and the `ModuleList.addModule(module:Module)` method is invoked to add the `Module` object into the list of modules. -7. Lastly, a message indicating that the module has been added will be printed out. +5. Lastly, a message indicating that the module has been added will be printed out. ### Add Student The add student mechanism is facilitated by `AddStudentCommand`. It extends `Command` and uses `StudentList` which From 837475f1b8ccc5aa08487b3076e8573207abcaa6 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Tue, 26 Oct 2021 23:14:03 +0800 Subject: [PATCH 205/543] implement sort by scores command --- .../java/taa/command/DeleteMarkCommand.java | 10 +- .../java/taa/command/EditMarkCommand.java | 15 ++- .../java/taa/command/SetMarksCommand.java | 10 +- .../java/taa/command/SortByScoresCommand.java | 123 ++++++------------ src/main/java/taa/student/Student.java | 13 +- 5 files changed, 61 insertions(+), 110 deletions(-) diff --git a/src/main/java/taa/command/DeleteMarkCommand.java b/src/main/java/taa/command/DeleteMarkCommand.java index b760a92982..fa06ac7373 100644 --- a/src/main/java/taa/command/DeleteMarkCommand.java +++ b/src/main/java/taa/command/DeleteMarkCommand.java @@ -82,7 +82,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(MESSAGE_NO_MARKS); } - deleteMark(ui, student, assessmentName); + deleteMark(ui, student, assessment); storage.save(moduleList); } @@ -91,11 +91,11 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc * * @param ui The ui instance to handle interactions with the user. * @param student The student whose marks are to be deleted. - * @param assessmentName The name of the assessment to delete marks for. + * @param assessment The assessment to delete marks for. */ - private void deleteMark(Ui ui, Student student, String assessmentName) { - student.deleteMark(assessmentName); - ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_DELETED, student, assessmentName)); + private void deleteMark(Ui ui, Student student, Assessment assessment) { + student.deleteMark(assessment.getName()); + ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_DELETED, student, assessment.getName())); } /** diff --git a/src/main/java/taa/command/EditMarkCommand.java b/src/main/java/taa/command/EditMarkCommand.java index 1f4d852cda..96f8bca059 100644 --- a/src/main/java/taa/command/EditMarkCommand.java +++ b/src/main/java/taa/command/EditMarkCommand.java @@ -98,7 +98,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(MESSAGE_NO_MARKS); } - editMark(ui, student, assessmentName, marks); + editMark(ui, student, assessment, marks); storage.save(moduleList); } @@ -107,13 +107,14 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc * * @param ui The ui instance to handle interactions with the user. * @param student The student whose marks are to be edited. - * @param assessmentName The name of the assessment to edit marks for. + * @param assessment The assessment to edit marks for. */ - private void editMark(Ui ui, Student student, String assessmentName, double newMarks) { - double previousMark = student.getMarks(assessmentName); - student.deleteMark(assessmentName); - student.setMarks(assessmentName, newMarks); - ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_EDITED, student, previousMark, newMarks, assessmentName)); + private void editMark(Ui ui, Student student, Assessment assessment, double newMarks) { + double previousMark = student.getMarks(assessment.getName()); + student.deleteMark(assessment.getName()); + student.setMarks(assessment.getName(), newMarks); + ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_EDITED, student, previousMark, newMarks, + assessment.getName())); } /** diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarksCommand.java index 29a37e1407..992a21a203 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarksCommand.java @@ -100,7 +100,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_MARKS, 0, maxMarks)); } - setMarks(ui, student, assessmentName, marks); + setMarks(ui, student, assessment, marks); storage.save(moduleList); } @@ -109,13 +109,13 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc * * @param ui The ui instance to handle interactions with the user. * @param student The student instance to set the mark for. - * @param assessmentName The name of the assessment to be marked. + * @param assessment The assessment to be marked. * @param marks The marks to set for the assessment. */ - private void setMarks(Ui ui, Student student, String assessmentName, double marks) { + private void setMarks(Ui ui, Student student, Assessment assessment, double marks) { assert marks >= 0; - student.setMarks(assessmentName, marks); - ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_ADDED, student, marks, assessmentName)); + student.setMarks(assessment.getName(), marks); + ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_ADDED, student, marks, assessment.getName())); } /** diff --git a/src/main/java/taa/command/SortByScoresCommand.java b/src/main/java/taa/command/SortByScoresCommand.java index 592b46da83..38787c82ac 100644 --- a/src/main/java/taa/command/SortByScoresCommand.java +++ b/src/main/java/taa/command/SortByScoresCommand.java @@ -1,5 +1,6 @@ package taa.command; +//@@author hozhenhong99 import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; @@ -11,23 +12,19 @@ import taa.student.StudentList; import taa.util.Util; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; +import java.util.*; public class SortByScoresCommand extends Command { private static final String KEY_MODULE_CODE = "c"; - private static final String KEY_ASSESSMENT_NAME = "a"; private static final String KEY_SORT_ORDER = "o"; private static final String[] SORT_SCORES_ARGUMENT_KEYS = { KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME, KEY_SORT_ORDER }; - private static final String MESSAGE_FORMAT_SORT_SCORES_USAGE = "%s %s/ %s/ " + private static final String MESSAGE_FORMAT_SORT_SCORES_USAGE = "%s %s/ " + "%s/"; - private static final String MESSAGE_LIST_MARKS_HEADER = "Here is the sorted list of students and " - + "their marks for %s:"; + private static final String MESSAGE_LIST_MARKS_HEADER = "Here is the sorted list of students and their scores"; + public static final String MESSAGE_INVALID_SORT_ORDER = "Please input a valid sort order."; public SortByScoresCommand(String argument) { super(argument, SORT_SCORES_ARGUMENT_KEYS); @@ -51,27 +48,36 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc if (module == null) { throw new TaaException(MESSAGE_MODULE_NOT_FOUND); } - AssessmentList assessmentList = module.getAssessmentList(); - String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); - Assessment assessment = assessmentList.getAssessment(assessmentName); - if (assessment == null) { - throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); - } + String order = argumentMap.get(KEY_SORT_ORDER); if (!order.equalsIgnoreCase("asc") && !order.equalsIgnoreCase("desc")) { - throw new TaaException("Please input a valid sort order."); + throw new TaaException(MESSAGE_INVALID_SORT_ORDER); } - ArrayList studentList = module.getStudentList().getStudents(); - ArrayList studentListClone = new ArrayList<>(); - for (Student student : studentList) { - Student clonedStudent = new Student(student.getId(), student.getName()); - studentListClone.add(clonedStudent); + ArrayList students = module.getStudentList().getStudents(); + AssessmentList assessmentList = module.getAssessmentList(); + HashMap unsortedScores = new HashMap<>(); + ArrayList sortedStudents = new ArrayList<>(); + for (Student student : students) { + double score = 0.0; + for (Assessment assessment : assessmentList.getAssessments()) { + if (!student.marksExist(assessment.getName())) { + continue; + } + score += student.getMarks(assessment.getName()) / assessment.getMaximumMarks() + * assessment.getWeightage(); + } + unsortedScores.put(student, score); + int i = 0; + while (i < sortedStudents.size() && score >= unsortedScores.get(sortedStudents.get(i))) { + i += 1; + } + sortedStudents.add(i, student); } if (order.equalsIgnoreCase("asc")) { - sortAscending(ui, module, assessmentName, studentListClone); + printAscending(ui, sortedStudents, unsortedScores); } else if (order.equalsIgnoreCase("desc")) { - sortDescending(ui, module, assessmentName, studentListClone); + printDescending(ui, sortedStudents, unsortedScores); } } @@ -79,74 +85,30 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc * Returns a string with the student name and the marks associated with the student. * * @param studentName Name of the student. - * @param marks Marks of the student. - * @return String with the name and marks of the student separated with a vertical line. + * @param score Score of the student. + * @return String with the name and score of the student separated with a vertical line. */ - public String marksToString(String studentName, double marks) { - return studentName + " | " + marks; - } - - private void appendUnmarkedStudent(StringBuilder stringBuilder, int studentIndex, Student student) { - stringBuilder.append("\n"); - stringBuilder.append(studentIndex); - stringBuilder.append(". "); - stringBuilder.append(student.getName()); - stringBuilder.append(" | "); - stringBuilder.append("NIL"); + public String marksToString(String studentName, double score) { + return studentName + " | " + score; } - private void appendMarkedStudent(String assessmentName, StringBuilder stringBuilder, int studentIndex, - Student student) { + private void appendStudentScore(StringBuilder stringBuilder, Student student, double score) { stringBuilder.append("\n"); - stringBuilder.append(studentIndex); - stringBuilder.append(". "); - stringBuilder.append(marksToString(student.getName(), student.getMarks(assessmentName))); + stringBuilder.append(marksToString(student.getName(), score)); } - private void sortAscending(Ui ui, Module module, String assessmentName, ArrayList students) { - StringBuilder stringBuilder = new StringBuilder(String.format(MESSAGE_LIST_MARKS_HEADER, assessmentName)); - int listIndex = 0; - List toRemove = new ArrayList<>(); - for (Student student : students) { - if (!student.marksExist(assessmentName)) { - listIndex += 1; - appendUnmarkedStudent(stringBuilder, listIndex, student); - toRemove.add(student); - } - } - students.removeAll(toRemove); - while (students.size() > 0) { - for (Student student : students) { - int currentMinimumScore = 10000; - if (student.marksExist(assessmentName) && (student.getMarks(assessmentName) < currentMinimumScore)) { - listIndex += 1; - appendMarkedStudent(assessmentName, stringBuilder, listIndex, student); - students.remove(student); - } - } + private void printAscending(Ui ui, ArrayList students, HashMap unsortedScores) { + StringBuilder stringBuilder = new StringBuilder(MESSAGE_LIST_MARKS_HEADER); + for (int i = 0; i < students.size(); i += 1) { + appendStudentScore(stringBuilder, students.get(i), unsortedScores.get(students.get(i))); } ui.printMessage(stringBuilder.toString()); } - private void sortDescending(Ui ui, Module module, String assessmentName, ArrayList students) { - StringBuilder stringBuilder = new StringBuilder(String.format(MESSAGE_LIST_MARKS_HEADER, assessmentName)); - int listIndex = 0; - for (Student student : students) { - if (!student.marksExist(assessmentName)) { - listIndex += 1; - appendUnmarkedStudent(stringBuilder, listIndex, student); - students.remove(student); - } - } - while (students.size() > 0) { - for (Student student : students) { - int currentMaximumScore = -1; - if (student.marksExist(assessmentName) && (student.getMarks(assessmentName) > currentMaximumScore)) { - listIndex += 1; - appendMarkedStudent(assessmentName, stringBuilder, listIndex, student); - students.remove(student); - } - } + private void printDescending(Ui ui, ArrayList students, HashMap unsortedScores) { + StringBuilder stringBuilder = new StringBuilder(MESSAGE_LIST_MARKS_HEADER); + for (int i = students.size() - 1; i >= 0; i -= 1) { + appendStudentScore(stringBuilder, students.get(i), unsortedScores.get(students.get(i))); } ui.printMessage(stringBuilder.toString()); } @@ -157,7 +119,6 @@ protected String getUsage() { MESSAGE_FORMAT_SORT_SCORES_USAGE, COMMAND_SORT_BY_SCORES, KEY_MODULE_CODE, - KEY_ASSESSMENT_NAME, KEY_SORT_ORDER ); } diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index bdf6e2e7cc..361b3c5030 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -134,17 +134,6 @@ public boolean marksExist(String assessmentName) { @Override public boolean verify() { - if (id.isEmpty() || name.isEmpty()) { - return false; - } - - /*//do this in module instead - for (String assessmentName : results.keySet()) { - if (!isMarksWithinRange(results.get(assessmentName))) { - return false; - } - }*/ - - return true; + return !id.isEmpty() && !name.isEmpty(); } } From efd34bff6ba63fbf4ac0688c9892f6b116beb818 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Tue, 26 Oct 2021 23:15:00 +0800 Subject: [PATCH 206/543] add welcome message --- src/main/java/taa/Ui.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index e34e7cbc77..79025e9be4 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -6,7 +6,14 @@ public class Ui { private static final String INPUT_PROMPT = "$ "; private static final String MESSAGE_BORDER = "------------------------------------------------------------"; - private static final String MESSAGE_WELCOME = "Welcome\nWhat can I do for you?"; + private static final String MESSAGE_WELCOME = "Welcome to\n" + "\n" + + ".___________. ___ ___ \n" + + "| | / \\ / \\ \n" + + "`---| |----` / ^ \\ / ^ \\ \n" + + " | | / /_\\ \\ / /_\\ \\ \n" + + " | | / _____ \\ / _____ \\ \n" + + " |__| /__/ \\__\\ /__/ \\__\\ \n" + "\n" + + "What can I do for you?"; private static final String MESSAGE_EXIT = "Bye. Hope to see you again soon!"; private static final String MESSAGE_FORMAT_EXCEPTION = "An exception has occurred:\n%s"; From 1d9d1419ee8bd2a2eb34e074898dcbdaf4fa8197 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Tue, 26 Oct 2021 23:20:33 +0800 Subject: [PATCH 207/543] fix formatting errors --- src/main/java/taa/Ui.java | 16 ++++++++-------- .../java/taa/command/SortByScoresCommand.java | 4 ++-- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index 79025e9be4..f1748f2821 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -6,14 +6,14 @@ public class Ui { private static final String INPUT_PROMPT = "$ "; private static final String MESSAGE_BORDER = "------------------------------------------------------------"; - private static final String MESSAGE_WELCOME = "Welcome to\n" + "\n" + - ".___________. ___ ___ \n" + - "| | / \\ / \\ \n" + - "`---| |----` / ^ \\ / ^ \\ \n" + - " | | / /_\\ \\ / /_\\ \\ \n" + - " | | / _____ \\ / _____ \\ \n" + - " |__| /__/ \\__\\ /__/ \\__\\ \n" + "\n" + - "What can I do for you?"; + private static final String MESSAGE_WELCOME = "Welcome to\n" + "\n" + + ".___________. ___ ___ \n" + + "| | / \\ / \\ \n" + + "`---| |----` / ^ \\ / ^ \\ \n" + + " | | / /_\\ \\ / /_\\ \\ \n" + + " | | / _____ \\ / _____ \\ \n" + + " |__| /__/ \\__\\ /__/ \\__\\ \n" + "\n" + + "What can I do for you?"; private static final String MESSAGE_EXIT = "Bye. Hope to see you again soon!"; private static final String MESSAGE_FORMAT_EXCEPTION = "An exception has occurred:\n%s"; diff --git a/src/main/java/taa/command/SortByScoresCommand.java b/src/main/java/taa/command/SortByScoresCommand.java index 38787c82ac..ab55ad83dd 100644 --- a/src/main/java/taa/command/SortByScoresCommand.java +++ b/src/main/java/taa/command/SortByScoresCommand.java @@ -11,8 +11,8 @@ import taa.student.Student; import taa.student.StudentList; import taa.util.Util; - -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; public class SortByScoresCommand extends Command { private static final String KEY_MODULE_CODE = "c"; From c77b79e1c5ed16f0cd166a03dab5603838f02f50 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Tue, 26 Oct 2021 23:26:29 +0800 Subject: [PATCH 208/543] fix io redicrection test issues --- text-ui-test/EXPECTED.TXT | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 9fabcd7265..99bcfd21e7 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,5 +1,13 @@ ------------------------------------------------------------ -Welcome +Welcome to + +.___________. ___ ___ +| | / \ / \ +`---| |----` / ^ \ / ^ \ + | | / /_\ \ / /_\ \ + | | / _____ \ / _____ \ + |__| /__/ \__\ /__/ \__\ + What can I do for you? ------------------------------------------------------------ $ ------------------------------------------------------------ From b4fef53fa0853d11a3bb6e4008cc129320091ecf Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Tue, 26 Oct 2021 23:36:32 +0800 Subject: [PATCH 209/543] remove welcome message --- src/main/java/taa/Ui.java | 9 +-------- text-ui-test/EXPECTED.TXT | 10 +--------- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index f1748f2821..e34e7cbc77 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -6,14 +6,7 @@ public class Ui { private static final String INPUT_PROMPT = "$ "; private static final String MESSAGE_BORDER = "------------------------------------------------------------"; - private static final String MESSAGE_WELCOME = "Welcome to\n" + "\n" - + ".___________. ___ ___ \n" - + "| | / \\ / \\ \n" - + "`---| |----` / ^ \\ / ^ \\ \n" - + " | | / /_\\ \\ / /_\\ \\ \n" - + " | | / _____ \\ / _____ \\ \n" - + " |__| /__/ \\__\\ /__/ \\__\\ \n" + "\n" - + "What can I do for you?"; + private static final String MESSAGE_WELCOME = "Welcome\nWhat can I do for you?"; private static final String MESSAGE_EXIT = "Bye. Hope to see you again soon!"; private static final String MESSAGE_FORMAT_EXCEPTION = "An exception has occurred:\n%s"; diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 99bcfd21e7..9fabcd7265 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,13 +1,5 @@ ------------------------------------------------------------ -Welcome to - -.___________. ___ ___ -| | / \ / \ -`---| |----` / ^ \ / ^ \ - | | / /_\ \ / /_\ \ - | | / _____ \ / _____ \ - |__| /__/ \__\ /__/ \__\ - +Welcome What can I do for you? ------------------------------------------------------------ $ ------------------------------------------------------------ From 6c751417514ea4c315fdfae98ac7ffe7d61e03d3 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Wed, 27 Oct 2021 01:12:51 +0800 Subject: [PATCH 210/543] implement set, delete and list comment for students --- src/main/java/taa/Parser.java | 39 +++------ src/main/java/taa/command/Command.java | 4 + .../taa/command/DeleteCommentCommand.java | 85 ++++++++++++++++++ .../java/taa/command/ListCommentCommand.java | 77 ++++++++++++++++ .../java/taa/command/SetCommentCommand.java | 87 +++++++++++++++++++ src/main/java/taa/student/Student.java | 10 +++ 6 files changed, 276 insertions(+), 26 deletions(-) create mode 100644 src/main/java/taa/command/DeleteCommentCommand.java create mode 100644 src/main/java/taa/command/ListCommentCommand.java create mode 100644 src/main/java/taa/command/SetCommentCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 2dc40326bc..1bded4b684 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,32 +1,7 @@ package taa; -import taa.command.AddAssessmentCommand; -import taa.command.AddModuleCommand; -import taa.command.AddStudentCommand; -import taa.command.AverageMarksCommand; -import taa.command.Command; -import taa.command.DeleteAssessmentCommand; -import taa.command.DeleteAttendanceCommand; -import taa.command.DeleteMarkCommand; -import taa.command.DeleteModuleCommand; -import taa.command.DeleteStudentCommand; -import taa.command.EditAssessmentCommand; -import taa.command.EditMarkCommand; -import taa.command.EditModuleCommand; -import taa.command.EditStudentCommand; -import taa.command.ExitCommand; -import taa.command.FindStudentCommand; -import taa.command.HelpCommand; -import taa.command.ListAssessmentsCommand; -import taa.command.ListAttendanceCommand; -import taa.command.ListMarksCommand; -import taa.command.ListModulesCommand; -import taa.command.ListStudentsCommand; -import taa.command.MedianMarkCommand; -import taa.command.SetAttendanceCommand; -import taa.command.SetMarksCommand; -import taa.command.SortByScoresCommand; +import taa.command.*; import taa.exception.TaaException; import java.util.ArrayList; @@ -143,6 +118,18 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new SortByScoresCommand(argument); break; + case Command.COMMAND_SET_COMMENT: + command = new SetCommentCommand(argument); + break; + + case Command.COMMAND_DELETE_COMMENT: + command = new DeleteCommentCommand(argument); + break; + + case Command.COMMAND_LIST_COMMENT: + command = new ListCommentCommand(argument); + break; + default: throw new TaaException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index a064491aab..749de842e7 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -33,6 +33,9 @@ public abstract class Command { public static final String COMMAND_EDIT_MARK = "edit_mark"; public static final String COMMAND_DELETE_MARK = "delete_mark"; public static final String COMMAND_SORT_BY_SCORES = "sort_by_scores"; + public static final String COMMAND_SET_COMMENT = "set_comment"; + public static final String COMMAND_DELETE_COMMENT = "delete_comment"; + public static final String COMMAND_LIST_COMMENT = "list_comment"; public static final String COMMAND_HELP = "help"; // Common messages @@ -45,6 +48,7 @@ public abstract class Command { protected static final String MESSAGE_NO_STUDENTS = "There are no students in this module"; protected static final String MESSAGE_NO_MARKS = "This student has not been marked yet."; protected static final String MESSAGE_ALREADY_MARKED = "This student has already been marked."; + protected static final String MESSAGE_NO_COMMENT_ADDED = "This student has no comment set"; // Common message formats protected static final String MESSAGE_FORMAT_GENERIC_USAGE = "%s"; diff --git a/src/main/java/taa/command/DeleteCommentCommand.java b/src/main/java/taa/command/DeleteCommentCommand.java new file mode 100644 index 0000000000..86cddb8c11 --- /dev/null +++ b/src/main/java/taa/command/DeleteCommentCommand.java @@ -0,0 +1,85 @@ +package taa.command; + +//@@author hozhenhong99 +import taa.storage.Storage; +import taa.exception.TaaException; +import taa.Ui; +import taa.module.Module; +import taa.module.ModuleList; +import taa.student.Student; +import taa.student.StudentList; +import taa.util.Util; + +public class DeleteCommentCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_STUDENT_INDEX = "s"; + private static final String[] DELETE_COMMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX}; + + private static final String MESSAGE_FORMAT_DELETE_COMMAND_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_DELETE_COMMENT = "Comment deleted from student:\n %s"; + + public DeleteCommentCommand(String argument) { + super(argument, DELETE_COMMENT_ARGUMENT_KEYS); + } + + @Override + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + if (!Util.isStringInteger(studentIndexInput)) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + } + + /** + * Executes the delete_comment command and deletes a comment from a student. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModuleWithCode(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + + String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); + assert Util.isStringInteger(studentIndexInput); + int studentIndex = Integer.parseInt(studentIndexInput) - 1; + + StudentList studentList = module.getStudentList(); + Student student = studentList.getStudentAt(studentIndex); + if (student == null) { + throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); + } + if (student.getComment().equals("")) { + throw new TaaException(MESSAGE_NO_COMMENT_ADDED); + } + + student.setComment(""); + + storage.save(moduleList); + ui.printMessage(String.format(MESSAGE_FORMAT_DELETE_COMMENT, student)); + } + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_DELETE_COMMAND_USAGE, + COMMAND_SET_COMMENT, + KEY_MODULE_CODE, + KEY_STUDENT_INDEX + ); + } +} \ No newline at end of file diff --git a/src/main/java/taa/command/ListCommentCommand.java b/src/main/java/taa/command/ListCommentCommand.java new file mode 100644 index 0000000000..6e12662690 --- /dev/null +++ b/src/main/java/taa/command/ListCommentCommand.java @@ -0,0 +1,77 @@ +package taa.command; + +//@@author hozhenhong99 +import taa.Ui; +import taa.attendance.AttendanceList; +import taa.exception.TaaException; +import taa.module.Module; +import taa.module.ModuleList; +import taa.storage.Storage; +import taa.student.Student; +import taa.student.StudentList; +import taa.util.Util; + +import java.util.ArrayList; + +public class ListCommentCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String[] LIST_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE}; + private static final String MESSAGE_LIST_COMMENT_HEADER = "Here is the list of all students and the comments:"; + + private static final String MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE = "%s %s/"; + + public ListCommentCommand(String argument) { + super(argument, LIST_ATTENDANCE_ARGUMENT_KEYS); + } + + @Override + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + } + + /** + * Executes the list_comment command and lists all students along with their comments. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModuleWithCode(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + + ArrayList students = module.getStudentList().getStudents(); + StringBuilder stringBuilder = new StringBuilder(MESSAGE_LIST_COMMENT_HEADER); + int studentIndex = 1; + for (Student student : students) { + stringBuilder.append("\n"); + stringBuilder.append(studentIndex); + stringBuilder.append(". "); + stringBuilder.append(student); + stringBuilder.append(" | "); + stringBuilder.append(student.getComment()); + studentIndex += 1; + } + ui.printMessage(stringBuilder.toString()); + } + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE, + COMMAND_LIST_ATTENDANCE, + KEY_MODULE_CODE + ); + } +} diff --git a/src/main/java/taa/command/SetCommentCommand.java b/src/main/java/taa/command/SetCommentCommand.java new file mode 100644 index 0000000000..68728906af --- /dev/null +++ b/src/main/java/taa/command/SetCommentCommand.java @@ -0,0 +1,87 @@ +package taa.command; + +//@@author hozhenhong99 +import taa.storage.Storage; +import taa.exception.TaaException; +import taa.Ui; +import taa.module.Module; +import taa.module.ModuleList; +import taa.student.Student; +import taa.student.StudentList; +import taa.util.Util; + +public class SetCommentCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_STUDENT_INDEX = "s"; + private static final String KEY_STUDENT_COMMENT = "t"; + private static final String[] SET_COMMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX, KEY_STUDENT_COMMENT}; + + private static final String MESSAGE_FORMAT_SET_COMMAND_USAGE = "%s %s/ %s/ " + + "%s/ results; public Student(String id, String name) { this.id = id; this.name = name; + this.comment = ""; this.attendanceList = new AttendanceList(); this.results = new HashMap<>(); } + public void setComment(String comment) { + this.comment = comment; + } + + public String getComment() { + return this.comment; + } + /** * Gets the AttendanceList object associated to the student. * From a9f67c92157e286b8105e7773a49e3df75f730f7 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Wed, 27 Oct 2021 01:15:40 +0800 Subject: [PATCH 211/543] edit importing of packages in parser --- src/main/java/taa/Parser.java | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 1bded4b684..fd44e62f7c 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,7 +1,35 @@ package taa; -import taa.command.*; +import taa.command.AddAssessmentCommand; +import taa.command.AddModuleCommand; +import taa.command.AddStudentCommand; +import taa.command.AverageMarksCommand; +import taa.command.Command; +import taa.command.DeleteAssessmentCommand; +import taa.command.DeleteAttendanceCommand; +import taa.command.DeleteMarkCommand; +import taa.command.DeleteModuleCommand; +import taa.command.DeleteStudentCommand; +import taa.command.EditAssessmentCommand; +import taa.command.EditMarkCommand; +import taa.command.EditModuleCommand; +import taa.command.EditStudentCommand; +import taa.command.ExitCommand; +import taa.command.FindStudentCommand; +import taa.command.HelpCommand; +import taa.command.ListAssessmentsCommand; +import taa.command.ListAttendanceCommand; +import taa.command.ListMarksCommand; +import taa.command.ListModulesCommand; +import taa.command.ListStudentsCommand; +import taa.command.MedianMarkCommand; +import taa.command.SetAttendanceCommand; +import taa.command.SetMarksCommand; +import taa.command.SortByScoresCommand; +import taa.command.SetCommentCommand; +import taa.command.DeleteCommentCommand; +import taa.command.ListCommentCommand; import taa.exception.TaaException; import java.util.ArrayList; From 7c78758238f2cb51edf88b8d17737965c8136de6 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Wed, 27 Oct 2021 01:18:34 +0800 Subject: [PATCH 212/543] fix formatting errors --- src/main/java/taa/command/SetCommentCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/command/SetCommentCommand.java b/src/main/java/taa/command/SetCommentCommand.java index 68728906af..eca035fbbb 100644 --- a/src/main/java/taa/command/SetCommentCommand.java +++ b/src/main/java/taa/command/SetCommentCommand.java @@ -16,8 +16,8 @@ public class SetCommentCommand extends Command { private static final String KEY_STUDENT_COMMENT = "t"; private static final String[] SET_COMMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX, KEY_STUDENT_COMMENT}; - private static final String MESSAGE_FORMAT_SET_COMMAND_USAGE = "%s %s/ %s/ " + - "%s/ Date: Wed, 27 Oct 2021 01:33:53 +0800 Subject: [PATCH 213/543] Add user stories in DG --- docs/DeveloperGuide.md | 144 +++++++++++++++++++++++------------------ 1 file changed, 82 insertions(+), 62 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 998d140c17..93b3d5b046 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -2,6 +2,11 @@ * [Acknowledgements](#acknowledgements) * [Design](#design) * [Implementation](#implementation) + * [Add Module](#add-module) + * [Add Student](#add-student) + * [Add Assessment](#add-assessment) + * [Set Marks](#set-marks) + * [Set Attendance](#set-attendance) * [Project scope](#product-scope) * [User Stories](#user-stories) * [Non-Functional Requirements](#non-functional-requirements) @@ -58,6 +63,8 @@ is returned. object into the list of modules. 5. Lastly, a message indicating that the module has been added will be printed out. +
+ ### Add Student The add student mechanism is facilitated by `AddStudentCommand`. It extends `Command` and uses `StudentList` which stores student internally as an ArrayList `students`. @@ -84,39 +91,8 @@ called to ensure that there is an existing module with code `CS2113T`. `a0217978j` and `jonny` respectively. Then, `StudentList#addModule` is called to add the newly created `Student` object into the `students` ArrayList within `StudentList`. -### Set Attendance -The set attendance mechanism is facilitated by SetAttendanceCommand. It extends `Command` and -uses `AttendanceList` which stores a student's lessons attendance as an -ArrayList `attendances`.
-`SetAttendanceCommand` implements the following methods: -* `SetAttendanceCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Performs operations for the command. - -`AttendanceList` implements the following methods: -* `AttendanceList#getSize()` - Returns the no. of attendance currently in the list. -* `AttendanceList#getAttendances()` - Returns an ArrayList containing all the attendances. -* `AttendanceList#getAttendance(lessonNumber:String)` - Returns an attendance with a particular lesson number. -* `AttendanceList#isValidIndex(index:int)` - Checks if an index is valid w.r.t the `attendances` ArrayList. -* `AttendanceList#addAttendance(attendance:Attendance)` - Adds an attendance to the `attendances` ArrayList. -* `AttendnaceList#getAttendnaceIndex(lessonNumInput:String)` - Returns the attendance index in the `attendances` -ArrayList. -* `AttendanceList#deleteAttendance(lessonNumInput:String)` - Deletes an attendance with a particular lesson number. -* `AttendanceList#sortAttendances` - Sorts the attendance in the `attendances` ArrayList in ascending order based on -lesson number. - -Below is an example scenario of how the set attendance feature behaves at each step: -* Step 1 - The user executes `set_attendance c/CS2113T s/1 l/1 p/1` to set an attendance to `Present` for student at -index `1`, lesson number `1` to set a student's attendance for a lesson. The `set_attendance` command calls the -`SetAttendanceCommand#execute` method. Within `SetAttendanceCommand#execute`, `AttendanceList#getAttendance("1")` is -called to ensure that there is no existing attendance with the -lesson number `1`for student at index `1`. -* Step 2 - If no existing attendance object with lesson number `1` for student at index `1` is found, a new -`Attendance` object -with lesson number `1` and attendance record `Present` is set as its lesson number and attendance record respectively. -Then, `AttendanceList#addAttendance` is called to add the newly created `Attendance` object into the `attendances` -ArrayList within `AttendanceList`. - ### Add Assessment The add assessment mechanism is facilitated by `AddAssessmentCommand`. It extends `Command` and uses `AssessmentList` which stores assessment internally as an ArrayList `assessments`.
@@ -127,10 +103,10 @@ which stores assessment internally as an ArrayList `assessments`.
`AssessmentList` implements the following methods: * `AssessmentList#getSize()` - Returns the no. of assessments currently in the list. * `AssessmentList#getAssessments()` - Returns an ArrayList containing all the assessments. -* `AssessmentList#getAssessment(assessmentName:String)` - Returns an assessment with a particular name specified by the +* `AssessmentList#getAssessment(assessmentName:String)` - Returns an assessment with a particular name specified by the user. * `AssessmentList#addAssessment(assessment:Assessment)` - Adds an assessment to the `assessments` ArrayList. -* `AssessmentList#deleteAssessment(assessmentName:String)` - Deletes an assessment with the name specified by the user +* `AssessmentList#deleteAssessment(assessmentName:String)` - Deletes an assessment with the name specified by the user from the `assessments` ArrayList. Below is an example scenario of how the add assessment feature behaves at each step: @@ -139,43 +115,81 @@ Below is an example scenario of how the add assessment feature behaves at each s `ModuleList#getModuleWithCode("cs2113t")` is called to ensure that there is an existing module with code `cs2113t`. * Step 2 - If an existing module with code `cs2113t` is found, the `MAXIMUM_MARKS` and `WEIGHTAGE` arguments are checked to ensure that they are valid. -* Step 3 - If the `MAXIMUM_MARKS` and `WEIGHTAGE` arguments are valid, a new `Assessment` object with name, +* Step 3 - If the `MAXIMUM_MARKS` and `WEIGHTAGE` arguments are valid, a new `Assessment` object with name, maximum marks and weightage set to `midterms`, `20` and `10` respectively is created under the existing `Module` with code `cs2113t`. Then, `AssessmentList#addAssessment` is called to add the newly created `Assessment` object into the `assessments` ArrayList within `AssessmentList`. * Step 4 - Within `AssessmentList#addAssessment`, the name of the newly created `Assessment` object is checked to ensure there is no existing assessment with name `midterms`. At the same time, the weightage of the newly created - `Assessment` object is also checked to ensure that the total weightage of the assessments in the `cs2113t` module + `Assessment` object is also checked to ensure that the total weightage of the assessments in the `cs2113t` module will not exceed 100 with the addition of the weightage of the newly created `Assessment` object. -* Step 5 - If the name and weightage of the newly created `Assessment` object are valid, the newly created `Assessment` +* Step 5 - If the name and weightage of the newly created `Assessment` object are valid, the newly created `Assessment` object is added into the `assessments` ArrayList within `AssessmentList`. +
+ ### Set Marks -The set marks mechanism is facilitated by `SetMarksCommand`. It extends `Command` and uses a `results` HashMap to store -`assessmentName` and the `marks` for it as a key-value pair.
+The set marks mechanism is facilitated by `SetMarksCommand`. It extends `Command` and uses a `results` HashMap to store +`assessmentName` and the `marks` for it as a key-value pair.
`SetMarksCommand` implements the following methods: -* `SetMarksCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Checks input for errors before calling the -`setMarks` command and saving the data. +* `SetMarksCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Checks input for errors before calling the + `setMarks` command and saving the data. * `SetMarksCommand#setMarks(ui:Ui, student:Student, assessmentName:String, marks:double)` - Puts a key-value pair with -`assessmentName` as key and `marks` as the value into the `results` HashMap of `student`. + `assessmentName` as key and `marks` as the value into the `results` HashMap of `student`. Below is an example scenario of how the set marks mechanism behaves at each step: * Precursor Step - The user must have executed the commands to create `module`, `assessment`, and `student` entities. -For purpose of this example, the user will have created `CS2113T` as the `module`, `Midterms` as the `assessment` with -a maximum mark of `100`, and `Jim Ho` as the `student`. + For purpose of this example, the user will have created `CS2113T` as the `module`, `Midterms` as the `assessment` with + a maximum mark of `100`, and `Jim Ho` as the `student`. * Step 1 - The user executes the `set_marks c/CS2113T s/1 a/Midterms m/50` command to set marks for student at index `1` -for the `Midterms` assessment under the `CS2113T` module. The `set_marks` command calls the `SetMarksCommand#execute` -method. Within `SetMarksCommand#execute`, `StudentList#getStudentAt("1")` is called to ensure that the student to be -marked (in this case student at index `1`) exists. + for the `Midterms` assessment under the `CS2113T` module. The `set_marks` command calls the `SetMarksCommand#execute` + method. Within `SetMarksCommand#execute`, `StudentList#getStudentAt("1")` is called to ensure that the student to be + marked (in this case student at index `1`) exists. * Step 2 - `AssessmentList#getAssessment(Midterms)` is then called to ensure that the `Midterms` assessment exists and -that the student has yet to be marked for it. -* Step 3 - `Assessment#getMaximumMarks();` is then called to ensure that the marks to be given for the `Midterms` -assessment do not exceed the maximum marks attributed to it. -* Step 4 - If the above steps do not output an error, the `SetMarksCommand#setMarks` command is then called, which in -turn calls the `Student#setMarks` command to put the key-value pair into the `results` HashMap of the student at index -`1`. + that the student has yet to be marked for it. +* Step 3 - `Assessment#getMaximumMarks();` is then called to ensure that the marks to be given for the `Midterms` + assessment do not exceed the maximum marks attributed to it. +* Step 4 - If the above steps do not output an error, the `SetMarksCommand#setMarks` command is then called, which in + turn calls the `Student#setMarks` command to put the key-value pair into the `results` HashMap of the student at index + `1`. + +
+### Set Attendance +The set attendance mechanism is facilitated by SetAttendanceCommand. It extends `Command` and +uses `AttendanceList` which stores a student's lessons attendance as an +ArrayList `attendances`. +
+ +`SetAttendanceCommand` implements the following methods: +* `SetAttendanceCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Performs operations for the command. + +`AttendanceList` implements the following methods: +* `AttendanceList#getSize()` - Returns the no. of attendance currently in the list. +* `AttendanceList#getAttendances()` - Returns an ArrayList containing all the attendances. +* `AttendanceList#getAttendance(lessonNumber:String)` - Returns an attendance with a particular lesson number. +* `AttendanceList#isValidIndex(index:int)` - Checks if an index is valid w.r.t the `attendances` ArrayList. +* `AttendanceList#addAttendance(attendance:Attendance)` - Adds an attendance to the `attendances` ArrayList. +* `AttendnaceList#getAttendnaceIndex(lessonNumInput:String)` - Returns the attendance index in the `attendances` +ArrayList. +* `AttendanceList#deleteAttendance(lessonNumInput:String)` - Deletes an attendance with a particular lesson number. +* `AttendanceList#sortAttendances` - Sorts the attendance in the `attendances` ArrayList in ascending order based on +lesson number. + +Below is an example scenario of how the set attendance feature behaves at each step: +* Step 1 - The user executes `set_attendance c/CS2113T s/1 l/1 p/1` to set an attendance to `Present` for student at +index `1`, lesson number `1` to set a student's attendance for a lesson. The `set_attendance` command calls the +`SetAttendanceCommand#execute` method. Within `SetAttendanceCommand#execute`, `AttendanceList#getAttendance("1")` is +called to ensure that there is no existing attendance with the +lesson number `1`for student at index `1`. +* Step 2 - If no existing attendance object with lesson number `1` for student at index `1` is found, a new +`Attendance` object +with lesson number `1` and attendance record `Present` is set as its lesson number and attendance record respectively. +Then, `AttendanceList#addAttendance` is called to add the newly created `Attendance` object into the `attendances` +ArrayList within `AttendanceList`. + +
## Product scope ### Target user profile @@ -194,20 +208,26 @@ turn calls the `Student#setMarks` command to put the key-value pair into the `re |Version| As a ... | I want to ... | So that I can ...| |--------|----------|---------------|------------------| -|v1.0|new user|see usage instructions|refer to them when I forget how to use the application| -|v2.0|user|find a to-do item by name|locate a to-do without having to go through the entire list| +|v1.0|Teaching Assistant|Add module|Keep track of all the modules that I am teaching| +|v1.0|Teaching Assistant|Add student|Keep track of students taking the module| +|v1.0|Teaching Assistant|Add assessment|Monitor what assessments there are in the module| +|v1.0|Teaching Assistant|Set marks|Record how much marks students score for the assessment| +|v1.0|Teaching Assistant|Set attendance|Monitor the attendance of students| +|v1.0|Teaching Assistant|Calculate the average marks of an assessment|Estimate the capabilities of students| +|v2.0|Teaching Assistant|Edit module|Change module details (e.g. code and name)| +|v2.0|Teaching Assistant|Delete module|Remove unnecessary data and reduce clutter| +|v2.0|Teaching Assistant|Edit student|Change any student's information| +|v2.0|Teaching Assistant|Delete student|Remove students who are no longer part of the class| +|v2.0|Teaching Assistant|Edit assessment|Change the name or weightage of the assessment| +|v2.0|Teaching Assistant|Delete assessment|Remove a particular assessment from the module| +|v2.0|Teaching Assistant|Edit marks|Modify the marks of the student for a particular assessment| +|v2.0|Teaching Assistant|Delete marks|Remove the marks entry of a student for a particular assessment| +|v2.0|Teaching Assistant|Delete attendance|Remove the attendance entry of a student| ## Non-Functional Requirements -1. Should work on any mainstream OS as long as it has Java 11 or above installed. +1. Should work on any mainstream OS as long as it has `Java 11` installed. 2. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse. ## Glossary * Mainstream OS: Windows, Linux, Unix, OS-X - - -## Method Summary - -Method | Description | - ------ | --------------- | -add_module | adds a module lol From c44c77c901f444afbc96ba3313ce63e0f7b0c22a Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 27 Oct 2021 01:56:42 +0800 Subject: [PATCH 214/543] Move commands into packages --- .settings/org.eclipse.buildship.core.prefs | 13 ----- src/main/java/taa/Parser.java | 52 +++++++++---------- src/main/java/taa/command/HelpCommand.java | 30 +++++++++++ .../AddAssessmentCommand.java | 3 +- .../DeleteAssessmentCommand.java | 3 +- .../EditAssessmentCommand.java | 3 +- .../ListAssessmentsCommand.java | 3 +- .../DeleteAttendanceCommand.java | 3 +- .../ListAttendanceCommand.java | 3 +- .../SetAttendanceCommand.java | 3 +- .../{ => mark}/AverageMarksCommand.java | 3 +- .../command/{ => mark}/DeleteMarkCommand.java | 3 +- .../command/{ => mark}/EditMarkCommand.java | 3 +- .../command/{ => mark}/ListMarksCommand.java | 3 +- .../command/{ => mark}/MedianMarkCommand.java | 5 +- .../command/{ => mark}/SetMarksCommand.java | 3 +- .../{ => module}/AddModuleCommand.java | 3 +- .../{ => module}/DeleteModuleCommand.java | 3 +- .../{ => module}/EditModuleCommand.java | 3 +- .../{ => module}/ListModulesCommand.java | 3 +- .../{ => student}/AddStudentCommand.java | 3 +- .../{ => student}/DeleteCommentCommand.java | 3 +- .../{ => student}/DeleteStudentCommand.java | 3 +- .../{ => student}/EditStudentCommand.java | 3 +- .../{ => student}/FindStudentCommand.java | 3 +- .../{ => student}/ListCommentCommand.java | 5 +- .../{ => student}/ListStudentsCommand.java | 3 +- .../{ => student}/SetCommentCommand.java | 7 +-- .../{ => student}/SortByScoresCommand.java | 3 +- .../java/taa/attendance/AttendanceTest.java | 2 - 30 files changed, 111 insertions(+), 72 deletions(-) delete mode 100644 .settings/org.eclipse.buildship.core.prefs rename src/main/java/taa/command/{ => assessment}/AddAssessmentCommand.java (98%) rename src/main/java/taa/command/{ => assessment}/DeleteAssessmentCommand.java (97%) rename src/main/java/taa/command/{ => assessment}/EditAssessmentCommand.java (99%) rename src/main/java/taa/command/{ => assessment}/ListAssessmentsCommand.java (97%) rename src/main/java/taa/command/{ => attendance}/DeleteAttendanceCommand.java (98%) rename src/main/java/taa/command/{ => attendance}/ListAttendanceCommand.java (98%) rename src/main/java/taa/command/{ => attendance}/SetAttendanceCommand.java (98%) rename src/main/java/taa/command/{ => mark}/AverageMarksCommand.java (98%) rename src/main/java/taa/command/{ => mark}/DeleteMarkCommand.java (98%) rename src/main/java/taa/command/{ => mark}/EditMarkCommand.java (98%) rename src/main/java/taa/command/{ => mark}/ListMarksCommand.java (98%) rename src/main/java/taa/command/{ => mark}/MedianMarkCommand.java (98%) rename src/main/java/taa/command/{ => mark}/SetMarksCommand.java (98%) rename src/main/java/taa/command/{ => module}/AddModuleCommand.java (98%) rename src/main/java/taa/command/{ => module}/DeleteModuleCommand.java (97%) rename src/main/java/taa/command/{ => module}/EditModuleCommand.java (98%) rename src/main/java/taa/command/{ => module}/ListModulesCommand.java (96%) rename src/main/java/taa/command/{ => student}/AddStudentCommand.java (97%) rename src/main/java/taa/command/{ => student}/DeleteCommentCommand.java (98%) rename src/main/java/taa/command/{ => student}/DeleteStudentCommand.java (98%) rename src/main/java/taa/command/{ => student}/EditStudentCommand.java (98%) rename src/main/java/taa/command/{ => student}/FindStudentCommand.java (98%) rename src/main/java/taa/command/{ => student}/ListCommentCommand.java (96%) rename src/main/java/taa/command/{ => student}/ListStudentsCommand.java (97%) rename src/main/java/taa/command/{ => student}/SetCommentCommand.java (95%) rename src/main/java/taa/command/{ => student}/SortByScoresCommand.java (98%) diff --git a/.settings/org.eclipse.buildship.core.prefs b/.settings/org.eclipse.buildship.core.prefs deleted file mode 100644 index 4664863da7..0000000000 --- a/.settings/org.eclipse.buildship.core.prefs +++ /dev/null @@ -1,13 +0,0 @@ -arguments= -auto.sync=false -build.scans.enabled=false -connection.gradle.distribution=GRADLE_DISTRIBUTION(WRAPPER) -connection.project.dir= -eclipse.preferences.version=1 -gradle.user.home= -java.home=C\:/Program Files/Amazon Corretto/jdk11.0.12_7 -jvm.arguments= -offline.mode=false -override.workspace.settings=true -show.console.view=true -show.executions.view=true diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index fd44e62f7c..196305603b 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,35 +1,35 @@ package taa; -import taa.command.AddAssessmentCommand; -import taa.command.AddModuleCommand; -import taa.command.AddStudentCommand; -import taa.command.AverageMarksCommand; +import taa.command.assessment.AddAssessmentCommand; +import taa.command.module.AddModuleCommand; +import taa.command.student.AddStudentCommand; +import taa.command.mark.AverageMarksCommand; import taa.command.Command; -import taa.command.DeleteAssessmentCommand; -import taa.command.DeleteAttendanceCommand; -import taa.command.DeleteMarkCommand; -import taa.command.DeleteModuleCommand; -import taa.command.DeleteStudentCommand; -import taa.command.EditAssessmentCommand; -import taa.command.EditMarkCommand; -import taa.command.EditModuleCommand; -import taa.command.EditStudentCommand; +import taa.command.assessment.DeleteAssessmentCommand; +import taa.command.attendance.DeleteAttendanceCommand; +import taa.command.mark.DeleteMarkCommand; +import taa.command.module.DeleteModuleCommand; +import taa.command.student.DeleteStudentCommand; +import taa.command.assessment.EditAssessmentCommand; +import taa.command.mark.EditMarkCommand; +import taa.command.module.EditModuleCommand; +import taa.command.student.EditStudentCommand; import taa.command.ExitCommand; -import taa.command.FindStudentCommand; +import taa.command.student.FindStudentCommand; import taa.command.HelpCommand; -import taa.command.ListAssessmentsCommand; -import taa.command.ListAttendanceCommand; -import taa.command.ListMarksCommand; -import taa.command.ListModulesCommand; -import taa.command.ListStudentsCommand; -import taa.command.MedianMarkCommand; -import taa.command.SetAttendanceCommand; -import taa.command.SetMarksCommand; -import taa.command.SortByScoresCommand; -import taa.command.SetCommentCommand; -import taa.command.DeleteCommentCommand; -import taa.command.ListCommentCommand; +import taa.command.assessment.ListAssessmentsCommand; +import taa.command.attendance.ListAttendanceCommand; +import taa.command.mark.ListMarksCommand; +import taa.command.module.ListModulesCommand; +import taa.command.student.ListStudentsCommand; +import taa.command.mark.MedianMarkCommand; +import taa.command.attendance.SetAttendanceCommand; +import taa.command.mark.SetMarksCommand; +import taa.command.student.SortByScoresCommand; +import taa.command.student.SetCommentCommand; +import taa.command.student.DeleteCommentCommand; +import taa.command.student.ListCommentCommand; import taa.exception.TaaException; import java.util.ArrayList; diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index 026aaca845..8129cc538f 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -1,6 +1,31 @@ package taa.command; import taa.Ui; +import taa.command.assessment.AddAssessmentCommand; +import taa.command.assessment.DeleteAssessmentCommand; +import taa.command.assessment.EditAssessmentCommand; +import taa.command.assessment.ListAssessmentsCommand; +import taa.command.attendance.DeleteAttendanceCommand; +import taa.command.attendance.ListAttendanceCommand; +import taa.command.attendance.SetAttendanceCommand; +import taa.command.mark.AverageMarksCommand; +import taa.command.mark.DeleteMarkCommand; +import taa.command.mark.EditMarkCommand; +import taa.command.mark.ListMarksCommand; +import taa.command.mark.MedianMarkCommand; +import taa.command.mark.SetMarksCommand; +import taa.command.module.AddModuleCommand; +import taa.command.module.DeleteModuleCommand; +import taa.command.module.EditModuleCommand; +import taa.command.module.ListModulesCommand; +import taa.command.student.AddStudentCommand; +import taa.command.student.DeleteStudentCommand; +import taa.command.student.EditStudentCommand; +import taa.command.student.FindStudentCommand; +import taa.command.student.ListCommentCommand; +import taa.command.student.ListStudentsCommand; +import taa.command.student.SetCommentCommand; +import taa.command.student.SortByScoresCommand; import taa.exception.TaaException; import taa.module.ModuleList; import taa.storage.Storage; @@ -18,6 +43,10 @@ public class HelpCommand extends Command { new EditStudentCommand(""), new DeleteStudentCommand(""), new FindStudentCommand(""), + new ListCommentCommand(""), + new SetCommentCommand(""), + new DeleteStudentCommand(""), + new SortByScoresCommand(""), new ListAssessmentsCommand(""), new AddAssessmentCommand(""), new EditAssessmentCommand(""), @@ -27,6 +56,7 @@ public class HelpCommand extends Command { new EditMarkCommand(""), new DeleteMarkCommand(""), new AverageMarksCommand(""), + new MedianMarkCommand(""), new ListAttendanceCommand(""), new SetAttendanceCommand(""), new DeleteAttendanceCommand(""), diff --git a/src/main/java/taa/command/AddAssessmentCommand.java b/src/main/java/taa/command/assessment/AddAssessmentCommand.java similarity index 98% rename from src/main/java/taa/command/AddAssessmentCommand.java rename to src/main/java/taa/command/assessment/AddAssessmentCommand.java index c0d7731249..ae2bdfa894 100644 --- a/src/main/java/taa/command/AddAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/AddAssessmentCommand.java @@ -1,5 +1,6 @@ -package taa.command; +package taa.command.assessment; +import taa.command.Command; import taa.storage.Storage; import taa.Ui; import taa.assessment.Assessment; diff --git a/src/main/java/taa/command/DeleteAssessmentCommand.java b/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java similarity index 97% rename from src/main/java/taa/command/DeleteAssessmentCommand.java rename to src/main/java/taa/command/assessment/DeleteAssessmentCommand.java index 4101373704..bf5d520036 100644 --- a/src/main/java/taa/command/DeleteAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java @@ -1,8 +1,9 @@ -package taa.command; +package taa.command.assessment; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; +import taa.command.Command; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; diff --git a/src/main/java/taa/command/EditAssessmentCommand.java b/src/main/java/taa/command/assessment/EditAssessmentCommand.java similarity index 99% rename from src/main/java/taa/command/EditAssessmentCommand.java rename to src/main/java/taa/command/assessment/EditAssessmentCommand.java index b6d8323acf..441161e892 100644 --- a/src/main/java/taa/command/EditAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/EditAssessmentCommand.java @@ -1,7 +1,8 @@ -package taa.command; +package taa.command.assessment; import taa.Ui; import taa.assessment.Assessment; +import taa.command.Command; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; diff --git a/src/main/java/taa/command/ListAssessmentsCommand.java b/src/main/java/taa/command/assessment/ListAssessmentsCommand.java similarity index 97% rename from src/main/java/taa/command/ListAssessmentsCommand.java rename to src/main/java/taa/command/assessment/ListAssessmentsCommand.java index 9cc0976705..f649528a97 100644 --- a/src/main/java/taa/command/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/assessment/ListAssessmentsCommand.java @@ -1,5 +1,6 @@ -package taa.command; +package taa.command.assessment; +import taa.command.Command; import taa.storage.Storage; import taa.Ui; import taa.assessment.AssessmentList; diff --git a/src/main/java/taa/command/DeleteAttendanceCommand.java b/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java similarity index 98% rename from src/main/java/taa/command/DeleteAttendanceCommand.java rename to src/main/java/taa/command/attendance/DeleteAttendanceCommand.java index 6ec9335fa1..59f4b0352a 100644 --- a/src/main/java/taa/command/DeleteAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java @@ -1,8 +1,9 @@ -package taa.command; +package taa.command.attendance; import taa.Ui; import taa.attendance.Attendance; import taa.attendance.AttendanceList; +import taa.command.Command; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; diff --git a/src/main/java/taa/command/ListAttendanceCommand.java b/src/main/java/taa/command/attendance/ListAttendanceCommand.java similarity index 98% rename from src/main/java/taa/command/ListAttendanceCommand.java rename to src/main/java/taa/command/attendance/ListAttendanceCommand.java index f6e68f80d1..9666fde0c1 100644 --- a/src/main/java/taa/command/ListAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/ListAttendanceCommand.java @@ -1,7 +1,8 @@ -package taa.command; +package taa.command.attendance; import taa.Ui; import taa.attendance.AttendanceList; +import taa.command.Command; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; diff --git a/src/main/java/taa/command/SetAttendanceCommand.java b/src/main/java/taa/command/attendance/SetAttendanceCommand.java similarity index 98% rename from src/main/java/taa/command/SetAttendanceCommand.java rename to src/main/java/taa/command/attendance/SetAttendanceCommand.java index 40461867b3..d4d558fa26 100644 --- a/src/main/java/taa/command/SetAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/SetAttendanceCommand.java @@ -1,6 +1,7 @@ -package taa.command; +package taa.command.attendance; import taa.attendance.AttendanceList; +import taa.command.Command; import taa.exception.TaaException; import taa.Ui; import taa.attendance.Attendance; diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/mark/AverageMarksCommand.java similarity index 98% rename from src/main/java/taa/command/AverageMarksCommand.java rename to src/main/java/taa/command/mark/AverageMarksCommand.java index 6a9c3f2cc8..105fadccb8 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/mark/AverageMarksCommand.java @@ -1,5 +1,6 @@ -package taa.command; +package taa.command.mark; +import taa.command.Command; import taa.storage.Storage; import taa.assessment.Assessment; import taa.exception.TaaException; diff --git a/src/main/java/taa/command/DeleteMarkCommand.java b/src/main/java/taa/command/mark/DeleteMarkCommand.java similarity index 98% rename from src/main/java/taa/command/DeleteMarkCommand.java rename to src/main/java/taa/command/mark/DeleteMarkCommand.java index fa06ac7373..cf16cfbde2 100644 --- a/src/main/java/taa/command/DeleteMarkCommand.java +++ b/src/main/java/taa/command/mark/DeleteMarkCommand.java @@ -1,8 +1,9 @@ -package taa.command; +package taa.command.mark; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; +import taa.command.Command; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; diff --git a/src/main/java/taa/command/EditMarkCommand.java b/src/main/java/taa/command/mark/EditMarkCommand.java similarity index 98% rename from src/main/java/taa/command/EditMarkCommand.java rename to src/main/java/taa/command/mark/EditMarkCommand.java index 96f8bca059..32b4347067 100644 --- a/src/main/java/taa/command/EditMarkCommand.java +++ b/src/main/java/taa/command/mark/EditMarkCommand.java @@ -1,8 +1,9 @@ -package taa.command; +package taa.command.mark; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; +import taa.command.Command; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; diff --git a/src/main/java/taa/command/ListMarksCommand.java b/src/main/java/taa/command/mark/ListMarksCommand.java similarity index 98% rename from src/main/java/taa/command/ListMarksCommand.java rename to src/main/java/taa/command/mark/ListMarksCommand.java index d22ddc579a..0fd44df459 100644 --- a/src/main/java/taa/command/ListMarksCommand.java +++ b/src/main/java/taa/command/mark/ListMarksCommand.java @@ -1,5 +1,6 @@ -package taa.command; +package taa.command.mark; +import taa.command.Command; import taa.storage.Storage; import taa.Ui; import taa.assessment.Assessment; diff --git a/src/main/java/taa/command/MedianMarkCommand.java b/src/main/java/taa/command/mark/MedianMarkCommand.java similarity index 98% rename from src/main/java/taa/command/MedianMarkCommand.java rename to src/main/java/taa/command/mark/MedianMarkCommand.java index 0f5c66922f..cd63311252 100644 --- a/src/main/java/taa/command/MedianMarkCommand.java +++ b/src/main/java/taa/command/mark/MedianMarkCommand.java @@ -1,8 +1,9 @@ -package taa.command; +package taa.command.mark; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; +import taa.command.Command; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; @@ -11,8 +12,6 @@ import taa.student.StudentList; import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedList; diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/mark/SetMarksCommand.java similarity index 98% rename from src/main/java/taa/command/SetMarksCommand.java rename to src/main/java/taa/command/mark/SetMarksCommand.java index 992a21a203..964ca3ef63 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/mark/SetMarksCommand.java @@ -1,5 +1,6 @@ -package taa.command; +package taa.command.mark; +import taa.command.Command; import taa.storage.Storage; import taa.Ui; import taa.assessment.Assessment; diff --git a/src/main/java/taa/command/AddModuleCommand.java b/src/main/java/taa/command/module/AddModuleCommand.java similarity index 98% rename from src/main/java/taa/command/AddModuleCommand.java rename to src/main/java/taa/command/module/AddModuleCommand.java index 03f5a58e23..6602668ab2 100644 --- a/src/main/java/taa/command/AddModuleCommand.java +++ b/src/main/java/taa/command/module/AddModuleCommand.java @@ -1,5 +1,6 @@ -package taa.command; +package taa.command.module; +import taa.command.Command; import taa.logger.TaaLogger; import taa.storage.Storage; import taa.exception.TaaException; diff --git a/src/main/java/taa/command/DeleteModuleCommand.java b/src/main/java/taa/command/module/DeleteModuleCommand.java similarity index 97% rename from src/main/java/taa/command/DeleteModuleCommand.java rename to src/main/java/taa/command/module/DeleteModuleCommand.java index 8a3e2d099c..110976f3c2 100644 --- a/src/main/java/taa/command/DeleteModuleCommand.java +++ b/src/main/java/taa/command/module/DeleteModuleCommand.java @@ -1,6 +1,7 @@ -package taa.command; +package taa.command.module; import taa.Ui; +import taa.command.Command; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; diff --git a/src/main/java/taa/command/EditModuleCommand.java b/src/main/java/taa/command/module/EditModuleCommand.java similarity index 98% rename from src/main/java/taa/command/EditModuleCommand.java rename to src/main/java/taa/command/module/EditModuleCommand.java index 0c33b33314..fe39197910 100644 --- a/src/main/java/taa/command/EditModuleCommand.java +++ b/src/main/java/taa/command/module/EditModuleCommand.java @@ -1,6 +1,7 @@ -package taa.command; +package taa.command.module; import taa.Ui; +import taa.command.Command; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; diff --git a/src/main/java/taa/command/ListModulesCommand.java b/src/main/java/taa/command/module/ListModulesCommand.java similarity index 96% rename from src/main/java/taa/command/ListModulesCommand.java rename to src/main/java/taa/command/module/ListModulesCommand.java index 16d7304be7..97383af75b 100644 --- a/src/main/java/taa/command/ListModulesCommand.java +++ b/src/main/java/taa/command/module/ListModulesCommand.java @@ -1,5 +1,6 @@ -package taa.command; +package taa.command.module; +import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/AddStudentCommand.java b/src/main/java/taa/command/student/AddStudentCommand.java similarity index 97% rename from src/main/java/taa/command/AddStudentCommand.java rename to src/main/java/taa/command/student/AddStudentCommand.java index 027b33b6af..fdb6f39285 100644 --- a/src/main/java/taa/command/AddStudentCommand.java +++ b/src/main/java/taa/command/student/AddStudentCommand.java @@ -1,6 +1,7 @@ -package taa.command; +package taa.command.student; //@@author hozhenhong99 +import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/DeleteCommentCommand.java b/src/main/java/taa/command/student/DeleteCommentCommand.java similarity index 98% rename from src/main/java/taa/command/DeleteCommentCommand.java rename to src/main/java/taa/command/student/DeleteCommentCommand.java index 86cddb8c11..f1e14f4fa2 100644 --- a/src/main/java/taa/command/DeleteCommentCommand.java +++ b/src/main/java/taa/command/student/DeleteCommentCommand.java @@ -1,6 +1,7 @@ -package taa.command; +package taa.command.student; //@@author hozhenhong99 +import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/DeleteStudentCommand.java b/src/main/java/taa/command/student/DeleteStudentCommand.java similarity index 98% rename from src/main/java/taa/command/DeleteStudentCommand.java rename to src/main/java/taa/command/student/DeleteStudentCommand.java index 06d3d1f61d..6047ec50fe 100644 --- a/src/main/java/taa/command/DeleteStudentCommand.java +++ b/src/main/java/taa/command/student/DeleteStudentCommand.java @@ -1,6 +1,7 @@ -package taa.command; +package taa.command.student; //@@author hozhenhong99 +import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/EditStudentCommand.java b/src/main/java/taa/command/student/EditStudentCommand.java similarity index 98% rename from src/main/java/taa/command/EditStudentCommand.java rename to src/main/java/taa/command/student/EditStudentCommand.java index 7343cac398..0e0ed5562c 100644 --- a/src/main/java/taa/command/EditStudentCommand.java +++ b/src/main/java/taa/command/student/EditStudentCommand.java @@ -1,6 +1,7 @@ -package taa.command; +package taa.command.student; //@@author hozhenhong99 +import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/FindStudentCommand.java b/src/main/java/taa/command/student/FindStudentCommand.java similarity index 98% rename from src/main/java/taa/command/FindStudentCommand.java rename to src/main/java/taa/command/student/FindStudentCommand.java index fd6cb09453..960d288fa3 100644 --- a/src/main/java/taa/command/FindStudentCommand.java +++ b/src/main/java/taa/command/student/FindStudentCommand.java @@ -1,6 +1,7 @@ -package taa.command; +package taa.command.student; //@@author hozhenhong99 +import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/ListCommentCommand.java b/src/main/java/taa/command/student/ListCommentCommand.java similarity index 96% rename from src/main/java/taa/command/ListCommentCommand.java rename to src/main/java/taa/command/student/ListCommentCommand.java index 6e12662690..8b37084ffe 100644 --- a/src/main/java/taa/command/ListCommentCommand.java +++ b/src/main/java/taa/command/student/ListCommentCommand.java @@ -1,8 +1,9 @@ -package taa.command; +package taa.command.student; //@@author hozhenhong99 import taa.Ui; import taa.attendance.AttendanceList; +import taa.command.Command; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; @@ -70,7 +71,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc protected String getUsage() { return String.format( MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE, - COMMAND_LIST_ATTENDANCE, + COMMAND_LIST_COMMENT, KEY_MODULE_CODE ); } diff --git a/src/main/java/taa/command/ListStudentsCommand.java b/src/main/java/taa/command/student/ListStudentsCommand.java similarity index 97% rename from src/main/java/taa/command/ListStudentsCommand.java rename to src/main/java/taa/command/student/ListStudentsCommand.java index 9c9508d7c6..f5b8251f6b 100644 --- a/src/main/java/taa/command/ListStudentsCommand.java +++ b/src/main/java/taa/command/student/ListStudentsCommand.java @@ -1,6 +1,7 @@ -package taa.command; +package taa.command.student; //@@author hozhenhong99 +import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/SetCommentCommand.java b/src/main/java/taa/command/student/SetCommentCommand.java similarity index 95% rename from src/main/java/taa/command/SetCommentCommand.java rename to src/main/java/taa/command/student/SetCommentCommand.java index eca035fbbb..94eaedbabd 100644 --- a/src/main/java/taa/command/SetCommentCommand.java +++ b/src/main/java/taa/command/student/SetCommentCommand.java @@ -1,6 +1,7 @@ -package taa.command; +package taa.command.student; //@@author hozhenhong99 +import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; @@ -17,8 +18,8 @@ public class SetCommentCommand extends Command { private static final String[] SET_COMMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX, KEY_STUDENT_COMMENT}; private static final String MESSAGE_FORMAT_SET_COMMAND_USAGE = "%s %s/ %s/ " - + "%s/"; + private static final String MESSAGE_FORMAT_SET_COMMENT = "Comment added to student:\n %s | %s"; public SetCommentCommand(String argument) { super(argument, SET_COMMENT_ARGUMENT_KEYS); diff --git a/src/main/java/taa/command/SortByScoresCommand.java b/src/main/java/taa/command/student/SortByScoresCommand.java similarity index 98% rename from src/main/java/taa/command/SortByScoresCommand.java rename to src/main/java/taa/command/student/SortByScoresCommand.java index ab55ad83dd..587118d778 100644 --- a/src/main/java/taa/command/SortByScoresCommand.java +++ b/src/main/java/taa/command/student/SortByScoresCommand.java @@ -1,9 +1,10 @@ -package taa.command; +package taa.command.student; //@@author hozhenhong99 import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; +import taa.command.Command; import taa.exception.TaaException; import taa.module.Module; import taa.module.ModuleList; diff --git a/src/test/java/taa/attendance/AttendanceTest.java b/src/test/java/taa/attendance/AttendanceTest.java index af67cec567..c15b19ede3 100644 --- a/src/test/java/taa/attendance/AttendanceTest.java +++ b/src/test/java/taa/attendance/AttendanceTest.java @@ -1,8 +1,6 @@ package taa.attendance; import org.junit.jupiter.api.Test; -import taa.attendance.Attendance; -import taa.command.SetAttendanceCommand; import static org.junit.jupiter.api.Assertions.assertEquals; From 51075c467ed23675b7914e208a10e452fa3b7461 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 27 Oct 2021 01:59:55 +0800 Subject: [PATCH 215/543] Update StudentDeserializer to include comment --- .../deserializer/AssessmentDeserializer.java | 4 +- .../AssessmentListDeserializer.java | 4 +- .../deserializer/AttendanceDeserializer.java | 4 +- .../AttendanceListDeserializer.java | 4 +- .../deserializer/ModuleDeserializer.java | 29 +++++++------- .../deserializer/ModuleListDeserializer.java | 4 +- .../deserializer/StudentDeserializer.java | 39 ++++++++++++------- .../deserializer/StudentListDeserializer.java | 4 +- 8 files changed, 50 insertions(+), 42 deletions(-) diff --git a/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java b/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java index 068be58ab4..968c5607c8 100644 --- a/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java +++ b/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java @@ -14,13 +14,13 @@ public class AssessmentDeserializer extends StorageDeserializer implements JsonD private static final String MEMBER_NAME = "name"; private static final String MEMBER_WEIGHTAGE = "weightage"; private static final String MEMBER_MAXIMUM_MARKS = "maximumMarks"; - private static final String[] MEMBERS = {MEMBER_NAME, MEMBER_MAXIMUM_MARKS, MEMBER_WEIGHTAGE}; + private static final String[] COMPULSORY_MEMBERS = {MEMBER_NAME, MEMBER_MAXIMUM_MARKS, MEMBER_WEIGHTAGE}; @Override public Assessment deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); - if (!hasMembers(jsonObject, MEMBERS)) { + if (!hasMembers(jsonObject, COMPULSORY_MEMBERS)) { return null; } diff --git a/src/main/java/taa/storage/deserializer/AssessmentListDeserializer.java b/src/main/java/taa/storage/deserializer/AssessmentListDeserializer.java index 17dc6c2dfc..883f0c1f33 100644 --- a/src/main/java/taa/storage/deserializer/AssessmentListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/AssessmentListDeserializer.java @@ -15,13 +15,13 @@ public class AssessmentListDeserializer extends StorageDeserializer implements JsonDeserializer { private static final String MEMBER_ASSESSMENTS = "assessments"; - private static final String[] MEMBERS = {MEMBER_ASSESSMENTS}; + private static final String[] COMPULSORY_MEMBERS = {MEMBER_ASSESSMENTS}; @Override public AssessmentList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); - if (!hasMembers(jsonObject, MEMBERS)) { + if (!hasMembers(jsonObject, COMPULSORY_MEMBERS)) { return null; } diff --git a/src/main/java/taa/storage/deserializer/AttendanceDeserializer.java b/src/main/java/taa/storage/deserializer/AttendanceDeserializer.java index 012b20bfaf..f7059e74f1 100644 --- a/src/main/java/taa/storage/deserializer/AttendanceDeserializer.java +++ b/src/main/java/taa/storage/deserializer/AttendanceDeserializer.java @@ -13,13 +13,13 @@ public class AttendanceDeserializer extends StorageDeserializer implements JsonDeserializer { private static final String MEMBER_LESSONNUMBER = "lessonNumber"; private static final String MEMBER_ISPRESENT = "isPresent"; - private static final String[] MEMBERS = {MEMBER_LESSONNUMBER, MEMBER_ISPRESENT}; + private static final String[] COMPULSORY_MEMBERS = {MEMBER_LESSONNUMBER, MEMBER_ISPRESENT}; @Override public Attendance deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); - if (!hasMembers(jsonObject, MEMBERS)) { + if (!hasMembers(jsonObject, COMPULSORY_MEMBERS)) { return null; } diff --git a/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java b/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java index 272048fd82..9b98e24278 100644 --- a/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java @@ -15,13 +15,13 @@ public class AttendanceListDeserializer extends StorageDeserializer implements JsonDeserializer { private static final String MEMBER_ATTENDANCES = "attendances"; - private static final String[] MEMBERS = {MEMBER_ATTENDANCES}; + private static final String[] COMPULSORY_MEMBERS = {MEMBER_ATTENDANCES}; @Override public AttendanceList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); - if (!hasMembers(jsonObject, MEMBERS)) { + if (!hasMembers(jsonObject, COMPULSORY_MEMBERS)) { return null; } diff --git a/src/main/java/taa/storage/deserializer/ModuleDeserializer.java b/src/main/java/taa/storage/deserializer/ModuleDeserializer.java index edf09c8c3e..053b8600cd 100644 --- a/src/main/java/taa/storage/deserializer/ModuleDeserializer.java +++ b/src/main/java/taa/storage/deserializer/ModuleDeserializer.java @@ -21,18 +21,13 @@ public class ModuleDeserializer extends StorageDeserializer implements JsonDeser private static final String MEMBER_NAME = "name"; private static final String MEMBER_STUDENTLIST = "studentList"; private static final String MEMBER_ASSESSMENTLIST = "assessmentList"; - private static final String[] MEMBERS = { - MEMBER_CODE, - MEMBER_NAME, - MEMBER_STUDENTLIST, - MEMBER_ASSESSMENTLIST - }; + private static final String[] COMPULSORY_MEMBERS = {MEMBER_CODE, MEMBER_NAME}; @Override public Module deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); - if (!hasMembers(jsonObject, MEMBERS)) { + if (!hasMembers(jsonObject, COMPULSORY_MEMBERS)) { return null; } @@ -50,18 +45,22 @@ public Module deserialize(JsonElement json, Type typeOfT, JsonDeserializationCon Gson gson = gsonBuilder.create(); JsonElement studentListJson = jsonObject.get(MEMBER_STUDENTLIST); - StudentList studentList = gson.fromJson(studentListJson, StudentList.class); - if (studentList != null) { - for (Student student : studentList.getStudents()) { - module.getStudentList().addStudent(student); + if (studentListJson != null) { + StudentList studentList = gson.fromJson(studentListJson, StudentList.class); + if (studentList != null) { + for (Student student : studentList.getStudents()) { + module.getStudentList().addStudent(student); + } } } JsonElement assessmentListJson = jsonObject.get(MEMBER_ASSESSMENTLIST); - AssessmentList assessmentList = gson.fromJson(assessmentListJson, AssessmentList.class); - if (assessmentList != null) { - for (Assessment assessment : assessmentList.getAssessments()) { - module.getAssessmentList().addAssessment(assessment); + if (assessmentListJson != null) { + AssessmentList assessmentList = gson.fromJson(assessmentListJson, AssessmentList.class); + if (assessmentList != null) { + for (Assessment assessment : assessmentList.getAssessments()) { + module.getAssessmentList().addAssessment(assessment); + } } } diff --git a/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java b/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java index a63a0d149b..60e5323668 100644 --- a/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java @@ -15,13 +15,13 @@ public class ModuleListDeserializer extends StorageDeserializer implements JsonDeserializer { private static final String MEMBER_MODULES = "modules"; - private static final String[] MEMBERS = {MEMBER_MODULES}; + private static final String[] COMPULSORY_MEMBERS = {MEMBER_MODULES}; @Override public ModuleList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); - if (!hasMembers(jsonObject, MEMBERS)) { + if (!hasMembers(jsonObject, COMPULSORY_MEMBERS)) { return null; } diff --git a/src/main/java/taa/storage/deserializer/StudentDeserializer.java b/src/main/java/taa/storage/deserializer/StudentDeserializer.java index 10a52cffda..b54702dd9a 100644 --- a/src/main/java/taa/storage/deserializer/StudentDeserializer.java +++ b/src/main/java/taa/storage/deserializer/StudentDeserializer.java @@ -18,20 +18,19 @@ public class StudentDeserializer extends StorageDeserializer implements JsonDeserializer { private static final String MEMBER_ID = "id"; private static final String MEMBER_NAME = "name"; + private static final String MEMBER_COMMENT = "comment"; private static final String MEMBER_ATTENDANCELIST = "attendanceList"; private static final String MEMBER_RESULTS = "results"; - private static final String[] MEMBERS = { + private static final String[] COMPULSORY_MEMBERS = { MEMBER_ID, - MEMBER_NAME, - MEMBER_ATTENDANCELIST, - MEMBER_RESULTS + MEMBER_NAME }; @Override public Student deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); - if (!hasMembers(jsonObject, MEMBERS)) { + if (!hasMembers(jsonObject, COMPULSORY_MEMBERS)) { return null; } @@ -43,24 +42,34 @@ public Student deserialize(JsonElement json, Type typeOfT, JsonDeserializationCo Student student = new Student(id, name); + JsonElement commentJson = jsonObject.get(MEMBER_COMMENT); + if (commentJson != null) { + String comment = commentJson.getAsString(); + student.setComment(comment); + } + GsonBuilder gsonBuilder = new GsonBuilder(); Gson gson = gsonBuilder.create(); JsonElement attendanceListJson = jsonObject.get(MEMBER_ATTENDANCELIST); - AttendanceList attendanceList = gson.fromJson(attendanceListJson, AttendanceList.class); - if (attendanceList != null) { - for (Attendance attendance : attendanceList.getAttendances()) { - student.getAttendanceList().addAttendance(attendance); + if (attendanceListJson != null) { + AttendanceList attendanceList = gson.fromJson(attendanceListJson, AttendanceList.class); + if (attendanceList != null) { + for (Attendance attendance : attendanceList.getAttendances()) { + student.getAttendanceList().addAttendance(attendance); + } } } JsonElement resultsJson = jsonObject.get(MEMBER_RESULTS); - Type resultsType = new TypeToken>(){}.getType(); - HashMap results = gson.fromJson(resultsJson, resultsType); - if (results != null) { - for (String key : results.keySet()) { - double value = results.get(key); - student.setMarks(key, value); + if (resultsJson != null) { + Type resultsType = new TypeToken>(){}.getType(); + HashMap results = gson.fromJson(resultsJson, resultsType); + if (results != null) { + for (String key : results.keySet()) { + double value = results.get(key); + student.setMarks(key, value); + } } } diff --git a/src/main/java/taa/storage/deserializer/StudentListDeserializer.java b/src/main/java/taa/storage/deserializer/StudentListDeserializer.java index a8890dcd71..32975c32eb 100644 --- a/src/main/java/taa/storage/deserializer/StudentListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/StudentListDeserializer.java @@ -15,13 +15,13 @@ public class StudentListDeserializer extends StorageDeserializer implements JsonDeserializer { private static final String MEMBER_STUDENTS = "students"; - private static final String[] MEMBERS = {MEMBER_STUDENTS}; + private static final String[] COMPULSORY_MEMBERS = {MEMBER_STUDENTS}; @Override public StudentList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); - if (!hasMembers(jsonObject, MEMBERS)) { + if (!hasMembers(jsonObject, COMPULSORY_MEMBERS)) { return null; } From 3f00b58616ceb521d6d90034feadcec96f737791 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 27 Oct 2021 02:01:07 +0800 Subject: [PATCH 216/543] Add client side file into ignore list --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index e18ae7a9a2..5c2466e007 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,4 @@ data/taa_data.json text-ui-test/data/taa_data.json taa.log* src/main/java/META-INF/MANIFEST.MF +.settings/ From ce7647a50ff0f3a443ab5f6ce27929bc51077cf3 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Wed, 27 Oct 2021 05:02:50 +0800 Subject: [PATCH 217/543] update setmarks->setmark and add setmark sequence diagram puml --- docs/diagrams/SetMarkSequenceDiagram.puml | 90 +++++++++++++++++++ src/main/java/taa/Parser.java | 4 +- src/main/java/taa/command/Command.java | 2 +- src/main/java/taa/command/HelpCommand.java | 2 +- ...tMarksCommand.java => SetMarkCommand.java} | 4 +- 5 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 docs/diagrams/SetMarkSequenceDiagram.puml rename src/main/java/taa/command/{SetMarksCommand.java => SetMarkCommand.java} (98%) diff --git a/docs/diagrams/SetMarkSequenceDiagram.puml b/docs/diagrams/SetMarkSequenceDiagram.puml new file mode 100644 index 0000000000..da3225bb2b --- /dev/null +++ b/docs/diagrams/SetMarkSequenceDiagram.puml @@ -0,0 +1,90 @@ +@startuml +!include style.puml + +Actor User as user +Participant ":Ui" as ui +Participant ":Taa" as taa +Participant "<>\nParser" as parser +Participant ":SetMarkCommand" as setMarkCommand +Participant ":ModuleList" as moduleList +Participant ":Module" as module +Participant ":AssessmentList" as assessmentList +Participant ":Assessment" as assessment +Participant ":StudentList" as studentList +Participant ":Student" as student +Participant ":Storage" as storage + +activate taa + +taa -> ui : getUserInput() +activate ui + +user -> ui : "set_mark c/CS2113T\ns/1 a/Midterms m/80" +ui --> taa : userInput:String +deactivate ui + +taa -> parser : parseUserInput(userInput) +activate parser + +create setMarkCommand +parser -> setMarkCommand +activate setMarkCommand +setMarkCommand -> parser +deactivate setMarkCommand + +parser --> taa : command:SetMarkCommand +deactivate parser + +taa -> setMarkCommand : checkArguments() +activate setMarkCommand + +setMarkCommand --> taa +deactivate setMarkCommand + +taa -> setMarkCommand : execute(moduleList:ModuleList, ui:Ui, storage:Storage) +activate setMarkCommand + +setMarkCommand -> moduleList : getModuleWithCode(moduleCode:String) +activate moduleList +moduleList --> setMarkCommand : module:Module +deactivate moduleList + +setMarkCommand -> module : getStudentList() +activate module +module --> setMarkCommand : studentList:StudentList +deactivate module + +setMarkCommand -> module : getAssessmentList() +activate module +module --> setMarkCommand : assessmentList:AssessmentList +deactivate module + +setMarkCommand -> assessmentList : getAssessment(assessmentName:String) +activate assessmentList +assessmentList --> setMarkCommand : assessment:Assessment +deactivate assessmentList + +setMarkCommand -> studentList : getStudentAt(studentIndex:Integer) +activate studentList +studentList --> setMarkCommand : student:Student +deactivate studentList + +setMarkCommand -> student : setMarks(assessmentName:String, marks:Double) +activate student +student --> setMarkCommand +deactivate student + +setMarkCommand -> storage : save(moduleList:ModuleList) +activate storage +storage --> setMarkCommand +deactivate storage + +setMarkCommand -> ui : printMessage("Marks set for ...") +activate ui +ui -> user : Display message:\n"Marks set for ..." +ui --> setMarkCommand +deactivate ui + +deactivate setMarkCommand + +@enduml \ No newline at end of file diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index fd44e62f7c..480f8a3376 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -25,7 +25,7 @@ import taa.command.ListStudentsCommand; import taa.command.MedianMarkCommand; import taa.command.SetAttendanceCommand; -import taa.command.SetMarksCommand; +import taa.command.SetMarkCommand; import taa.command.SortByScoresCommand; import taa.command.SetCommentCommand; import taa.command.DeleteCommentCommand; @@ -119,7 +119,7 @@ public static Command parseUserInput(String userInput) throws TaaException { break; case Command.COMMAND_SET_MARKS: - command = new SetMarksCommand(argument); + command = new SetMarkCommand(argument); break; case Command.COMMAND_EDIT_MARK: diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 749de842e7..8cb964bd6d 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -29,7 +29,7 @@ public abstract class Command { public static final String COMMAND_LIST_MARKS = "list_marks"; public static final String COMMAND_AVERAGE_MARKS = "average_marks"; public static final String COMMAND_MEDIAN_MARK = "median_mark"; - public static final String COMMAND_SET_MARKS = "set_marks"; + public static final String COMMAND_SET_MARKS = "set_mark"; public static final String COMMAND_EDIT_MARK = "edit_mark"; public static final String COMMAND_DELETE_MARK = "delete_mark"; public static final String COMMAND_SORT_BY_SCORES = "sort_by_scores"; diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index 026aaca845..6c04c0d102 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -23,7 +23,7 @@ public class HelpCommand extends Command { new EditAssessmentCommand(""), new DeleteAssessmentCommand(""), new ListMarksCommand(""), - new SetMarksCommand(""), + new SetMarkCommand(""), new EditMarkCommand(""), new DeleteMarkCommand(""), new AverageMarksCommand(""), diff --git a/src/main/java/taa/command/SetMarksCommand.java b/src/main/java/taa/command/SetMarkCommand.java similarity index 98% rename from src/main/java/taa/command/SetMarksCommand.java rename to src/main/java/taa/command/SetMarkCommand.java index 992a21a203..d9be6af1b8 100644 --- a/src/main/java/taa/command/SetMarksCommand.java +++ b/src/main/java/taa/command/SetMarkCommand.java @@ -14,7 +14,7 @@ /** * Class that deals with the command for the setting of marks. */ -public class SetMarksCommand extends Command { +public class SetMarkCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_ASSESSMENT_NAME = "a"; @@ -32,7 +32,7 @@ public class SetMarksCommand extends Command { + "Marks must be between %d and %,.2f (inclusive)"; private static final String MESSAGE_FORMAT_MARKS_ADDED = "Marks set for %s: %,.2f for %s"; - public SetMarksCommand(String argument) { + public SetMarkCommand(String argument) { super(argument, SET_MARKS_ARGUMENT_KEYS); } From 3e94da2562e8674520b67ae11e24fe93d33fb585 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Wed, 27 Oct 2021 05:04:04 +0800 Subject: [PATCH 218/543] add setmark png sequence diagram --- docs/diagrams/SetMarkSequenceDiagram.png | Bin 0 -> 73341 bytes 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 docs/diagrams/SetMarkSequenceDiagram.png diff --git a/docs/diagrams/SetMarkSequenceDiagram.png b/docs/diagrams/SetMarkSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..4d752248c2fb7191aacaa1971955716f52a5de6d GIT binary patch literal 73341 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 @AEORRG?d3i7t=V= z(j(OYI)t{Q&r6mpX_~loU}I-733`%qfn_WRfeewSoj=Ca22{GBj>s;VyVG4h5sRN_ znh1G7{W}XSld#9IFSaBj!fY0>3KT#( zj9vGsS9*&_Ed~`*vrpy7rMVfKZ?-HNtb?h3YBu%P<2`B(wl(SCtpqnAi29PUv0V?O zY&05=9diUHtb7dH24ufLzDUi(*EyP(9e>gY8BSQ%0A$iikk{Pt1(i?Jem<^>C@h;B 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 literal 0 HcmV?d00001 From cb8f7eaf798e07784cf56699523b151b769302de Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Wed, 27 Oct 2021 05:19:38 +0800 Subject: [PATCH 219/543] update DG with sequence diagram --- docs/DeveloperGuide.md | 41 +++++++++------------- docs/diagrams/SetMarkSequenceDiagram.png | Bin 73341 -> 71455 bytes docs/diagrams/SetMarkSequenceDiagram.puml | 1 - 3 files changed, 17 insertions(+), 25 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 998d140c17..01f42ba092 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -151,30 +151,23 @@ Below is an example scenario of how the add assessment feature behaves at each s object is added into the `assessments` ArrayList within `AssessmentList`. ### Set Marks -The set marks mechanism is facilitated by `SetMarksCommand`. It extends `Command` and uses a `results` HashMap to store -`assessmentName` and the `marks` for it as a key-value pair.
- -`SetMarksCommand` implements the following methods: -* `SetMarksCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Checks input for errors before calling the -`setMarks` command and saving the data. -* `SetMarksCommand#setMarks(ui:Ui, student:Student, assessmentName:String, marks:double)` - Puts a key-value pair with -`assessmentName` as key and `marks` as the value into the `results` HashMap of `student`. - -Below is an example scenario of how the set marks mechanism behaves at each step: -* Precursor Step - The user must have executed the commands to create `module`, `assessment`, and `student` entities. -For purpose of this example, the user will have created `CS2113T` as the `module`, `Midterms` as the `assessment` with -a maximum mark of `100`, and `Jim Ho` as the `student`. -* Step 1 - The user executes the `set_marks c/CS2113T s/1 a/Midterms m/50` command to set marks for student at index `1` -for the `Midterms` assessment under the `CS2113T` module. The `set_marks` command calls the `SetMarksCommand#execute` -method. Within `SetMarksCommand#execute`, `StudentList#getStudentAt("1")` is called to ensure that the student to be -marked (in this case student at index `1`) exists. -* Step 2 - `AssessmentList#getAssessment(Midterms)` is then called to ensure that the `Midterms` assessment exists and -that the student has yet to be marked for it. -* Step 3 - `Assessment#getMaximumMarks();` is then called to ensure that the marks to be given for the `Midterms` -assessment do not exceed the maximum marks attributed to it. -* Step 4 - If the above steps do not output an error, the `SetMarksCommand#setMarks` command is then called, which in -turn calls the `Student#setMarks` command to put the key-value pair into the `results` HashMap of the student at index -`1`. +The sequence diagram shown below illustrates how the `set_mark` command works: +![SetMarkSequenceDiagram](diagrams/SetMarkSequenceDiagram.png) + +Steps: +1. The `Taa` instance reads in a user input through the `Ui.getUserInput()` method. +2. The user input is then parsed using the `Parser.parseUserInput(userInput:String)` static method and a `Command` object + is returned. +3. `AddModuleCommand.checkArguments()` is then called to check if the arguments are valid. +4. After checking the arguments, `Command.execute(moduleList:ModuleList, ui:Ui, storage:Storage)` will be called. +5. The `module:Module` which the student and assessment belongs to is retrieved with +`getModuleWithCode(moduleCode:String)`. +6. Using `module:Module`, we are able to get the `studentList:StudentList` and `assessmentList:AssessmentList`. +7. The `student:Student` and `assessment:Assessment` are then retrieved from their lists using +`getStudentAt(studentIndex:Integer)` and `getAssessment(assessmentName:String)` respectively. +8. Finally, `setMarks(assessmentName:String, marks:Double)` is called to set the marks of the assessment in the +student's `results` HashMap. +9. A message will then be printed out to indicate to the user that the marks have been set successfully. ## Product scope diff --git a/docs/diagrams/SetMarkSequenceDiagram.png b/docs/diagrams/SetMarkSequenceDiagram.png index 4d752248c2fb7191aacaa1971955716f52a5de6d..641dba82f9d3103079ccffb0b9c70f5eec0a0df5 100644 GIT binary patch literal 71455 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 z +6P)mqaa7eCEIEi~C`ZB=;m@uCrfZx^{T`X9M^d`93(LYH3O^_H3Ku?|1l;rf$py>Pt zbi4pxLmhPLYfdH&mKF0niaFg>4L`N=56GEY0VsL8{_T?^@_ptc1v;G(kf@)V{7ZuQ z(+3DI{qlHB2J8IM$9Ig+AA;79s;H`5O(#iXwA4HQakZZ21Ny%pbS&WaW|Rc)N91nP z0&gz9B|HCf4tv}fdD0h%I>GFYUy7}px98P)R+GJmFcl)0!>;(Yw=imgW{Cgrb%xX4 zlTh8*a@v;=r#S6 z__YqS4XeqY5d9C?{mC)CM2vGj?EmHGRBl&kV!kIP3jIa?rly~SqCSpG5XXbQ@cP=n zXL_h=&67*075@`w9QQEY`6;tUapLd69h0bo_j`B|m^izSXN3Ai6zHV=eE>iFI_&mW z?_a_i`_JK^&U4H+{@10F{1~8-Gl^>81mq;>&j8(3Xt-U z{bu#6)f@mJL=pPk%GcWW{|I<{6(F;vMM8E~FLHQ3mN;~IwXpv1jEAQ1wW}G7Z*THl zJLisdZVKbloZ4@BPNURV)Q1<|2fV{VN(z4D-LsUz^>Y_=<7^vwb4{3~#`8fLviW+5 z`&Z8|-tW@A%W2+}`x7)`P=p-_8z@Sv?kAR}m8Eqd5K%lal4PV#N;+(x7(}vXh+E1Z1(~a$JTn(`OK zI?RQm)ZS}~1%@c;r@=md2u&zTV+T~!FkaABAmn{h!yWy@Y#ULNn?Lb~HRpX#=4<9r z#lM>N#8bwjm(pg9T57((f%^f<*D4PH^=%1+-nS8T0?~_TJ%C|9|+n_TEbx#WnN%E-)sT|xm2-^jB9y()_kJA`@_v8bzw38>zkj-}KES@8TfNKjF@PXuM*=$2Dvm!VfNg1oo0vr|7NywWaJDr%Q;g>a`v`X=yh6V8^t zc=bxK=$YU7FNqh7;lcr0{aVXfcW^IqMEegf;!t_^6yeK>7G5S(Cp+iH@UKY>Z^IHwqJ{W zOd?6Dsga?>QK$hCwkpzKyJnJ#hDH(uH(=3U+w%}iZ@oc~#pQ(_FyK+ZcTo#9VNvTZ z1?B)^tbzobazX=nIf9mSwL|FD3?e{h4tdM5SLeecBMYcJ`pbF?Cw61-|QXI%pd37_449Wk7H+LZSXO8%JpdxXi4FI<^YH#C#2cJc6hvnwtx z4has{H6%UdJ#pexFFT8*v$vqRzLJt>cxAS2MCe5j*IQGmw#n^YsRNIH-EaY&6XN$M z($zp27TUq(&#Co%CN7WHB-2I5XRY%2bpr-!?ThsUgpQw8w_u>Kv9X~D7xm=Hz6=e9aaVh?&$dL?6TA;q;>7-QVfVO@dvP3H? zUduS4Ze{0QLcy145mmwb*(PqU=(XA{Hv2EzpL3q~;ebEiN3(NB=XHO4xF+RP_&sYn zA)8X;wB@@xL2y{F7N>3ZYfxrIhtJVhmjVT5+Q{%<^HIO`_QLYnvp>8%=UixcRe07c z(m6LKa@8SEZ?G@)8y5)VROPj=D7vBilww+*(@u6PTg;%?HnhE9s=aK_`coVCR|(CX zeob40U$QZ2cfi%FYA^RMZ2r0F&|w%?(0*21q5oS}dZuk(gHZ5RkPwDietL+-f2^8 z5Ewk*q^x&Z)$qM{ zO{Rc;PTrj;W@E-qnHgSgI%{WjaXqE1teQ`^kv&`6)m_l|cEi^PD_h(pglsb8mTxwB znd>Yz5+<}iUQ};0yh6?Bp5-?#aS(r~ImzXYr)4MZSi+nlnEw%ZW#f#0ndST z27rV?jH3PCcNk|zOP>*wlBEkg`0b5r^`PHhm(trti$$kv{27xr9@v*`c>mH!oqrl# z6~CLngk|_=*#GlTIH?>sXlj0Nxl(14WsFk_oU-ceZ@hI2Lm+zJ>MdN~Za_kiRO2e7 z@Qz7>-JxV2UCrBxcm6NWccNNdj9mMUBojoW4J)sy(hFTHLO>%7$*gs2atYJVqdiOR z`S|EJ&bd%Li1xJWt@AP_lq}mpMjY&-;93~O z*EdnPq+ier;dyT<-A*(2EHn#8X z``3m?MU}_u$!}SnFG#345gVnaOOk4#8>}rVvV%P5G4G?!Ek}+VfpkX1rstWy-LLnn zBBHE1>M$C|5Wv{zUDbb&6CdKoSize?o(SB>#chuav zVV%A|N7N9da>xQ+8-!I!g{p$Wd9ZvN?IODHYos`}AxJaSgs?nbypY@F$|R8AxY0Gv zlf13yX;|0}j^hdM(i>is4P8U5B@+Nm5pPXXBNz}c4Jm#KDQjs==vsny_*G=H30>vK z0 z5q|i!HIDNX+A*Qg2=&&bOUdB{rXef{c5s7QrG`8%D!PNrp=GeUGP;vV#7ZHmA~*K| zXHaotL1+%NF0pl;Ly^%bYWjtku9SN5S2biuv4M9~U!2OA$C>nCpE;2}WEtBAaYnR(S#M-VecIe!^8E!=IKja^cYGs23XEGF$6wMN*aix7@+|BF(;=a zl@vTU+XPt&GKU5I9{ip{PagFxdCVz*#Q>(ZZZkwYPoA)M7Lq@^7xzNIl>*|9n)s91*aYdprhXDU0iaNU68kf1Knd>qkF78<3)7ER$;AQ<*gEw zh6kGBW&aX-2srT*YIY;2^PWC!fdDlpBZKQk(3{dFVCaz=?jZKMul+3ae1FQ7%n!zy zL!ln(7WcI|%#=9SrTmq#Z`usEuHj61pC62eK0*rsjp9p_8dqj9qlNpg#;`PEEi&6> z;1tW^`l9sel9p|Qy5bz($Ikt3y_}`J$6bkldTMs5<@~JR>}_LG@#PLuOxt;C79n5~ zCMx`F>7>+@L1F2fz`6@eQP;crm`~g7u#w!${CP_5XUoqs#%GvLZ#OQa)1lpw53=&= zO?WNV^fwE;TE#NzQLhs08*y%2qHeW%KCMRW7k_?TlIk{)tzBrxXTf}-ZSYu?Y{5Gl zSK?#UCzj6o=|Z4*Q(^^JEBm__Jd`Cnf37!Z*>*5hC(~R^EXmZrONzuB@agl)4V4&!}C`N#r-T*I`B0WE%IbqupVNJBfh9 zq?yHVCTsNIftvlshlvkfp8m%2^MtFEcsXTHTIxZ7bsOF@GP6L9Be86Py3_p!^pnT7sd1V5+LQJWaZRRXm2;c@+HoWheb8WZ1 z@VsAz>nG$P`!MqM+yvk~CIvC06KCAG2>(iipKpk;sQ2k%$AGdI2I^g6D>Ot?&i9L& z%@?O^oZnkt{0I|rU@`5?Z2j~$s9{?KReR`=uUvZgQLMuIZ>CgB_1xyWLj+l)A9K#b zg1@xGCY@McLYE3m&hO3%Z-|J>c+Or9tmPpdns(bEo8pXbX{)#M)#5-PpU?jy7`Nv zhRt_(`|>vT=tfg*z2iG{XD(ek?ahQGaB}Iam9)r*7No!1R$`dY(y;G)_t}(s(Pl{_ z3Ejes?xFG|o?M3BixRmR>y8EtbicBQ5D#>}uVc=B;>yBd zVorIxnr`-oN%z)BT0gS4isJr#_=vEcN!D;)=OmEkm;;j7rvLG)Zqd#}*LLqo_Rshu zahHAEfbFA^MkowLWz6u#_vhB>-0;*4Zas4r|%$ySK;k& zH%xBiGmqPAt2s+HQ~KB;&R|7P-vzCO)^8;&_$x%bU@HRT+1Jz4)6Y*B5h8$(UAuPa zt3JpAjI*Gy8uQRNx*TfI5Gkv=K)0CI%iExpVWYwJl#S&B`_pSZ!1ZE#8lsgm| zHUv$5J;YuG)=E)oowXh^aj`c1mQsAOhZZU=xn|6f#JXX-@`WeBAfW&*qO!BGB~&|Y zi;eS2|X>O2L>!)Uy8h`DwJ84%5rj-L?_S{ zqc74^3j!5Y(}9yCu3Ci#_(?~JDfeX4GkRK|v{Zk3Vde7WVIt@qQ~(qa#yTtRPN_J_f=fJaBq`x z#sF4_f;KSsl4BSAD=Nz@G##ba$hHO0J6!mb$w+!-?HMjVFN_3vwW9iCDq z)3TD=|06;XVPZt#l+8Lhy0FgxPKziIkn?_U{l)r!aEsK|Z3p(nnQyExJW_w1&iZv~ zWedlo%UcQ5m(MBUq0!DF!-xto}{*l|FGv_?kn@ASX<5u;TRfhE;UMs zQVyN?)RTYZ_E8$QC{<%}`^TfXRex$v^}M2XAe)MK?JQe3LH6xr7?dphLac`flzPa= zBIBN=sAfimbLdtY%2JEO0)pZmw74kN4D_~p<}g<1C9tL|p0^5p6^>f#6SbE(B9M9S z+IJ+@*4zwkXBSA-r@fAK^)>`H4Q3fOIDFgSlSX)=H8nPNh#43dbPCMQtaDK-7s)K# zwA$4VRw6k3>S}Azt7KQ7lfIN8hqe(%3@h}a!7M4`02)`B0%2O8$YwRj~$7QI%tmz>QUIlkO>46q%ismE0H+ z$sQz_Y?tP^1o%zXr%yXO*21jMMa;0`G>S4zY9*b`@!55V z`pbRR+Kb{%e%w0QxGRdzz}N0XP5bp$=Za@#%WAkAJF<6QoryGe7cZ}VYEq;*gOY!n!sH@18yVlp%hGi2*^hYp6E2NZ$w&l29w-zg{MVx>XpcDT0)6$4U7u_+?1SQQ!@oRA@*p^?6Jm!vZN z^Kg~iS)Ts#poxhIUJ3=D*o65}DBpB!a%mn5#?R_?pkKv%r#mh76Cq|pnQnw7p6X70^KN!|ow7m@0PO~9m?L>ou$8RrEG>HtRZ!a`e<@=kRiWqjLLItw|B5&Z zE?O&GJ@ou}|4Wb7*14^GBA**(ulu!Q@q|LbggCV>@laq|!VzD0*ovBJ$5Wj8r28@t zQKOOP{xh$f$(8HT_>wSs>WI>f&t{6GQ>x z@E}IVmaRO+xS+1)otTyO1|mb;ID68<0UbX}<-H79I>SA~xJm55H2ZWFuaqFP;8ZmIEA!|PSV-BBHxqR=9LPOod{uNj+h4idFEy>PjeU^?XJ4P zEbYgihty&~!!%aFGg?;p*f9}+%(1bth|6J7u^nBw!o#KJt&Ti?%C5#osO6=^<3b`; zQCn6jwB3HoomOzy%FRe?()sVd&@YN$4YbK0Do;rYUOb2Zwk4@udN2p=XS-zV z`aJrgF_tid%%z@PNHLSB6@po}N{UUwkPgfN9hb1oH@R6i(;W3&coN-BC}HbOsMY2$gz;h9eHbW!CVM9(~#dJqZ z$QUR;ATmJ-8Q0~o`7Mvut7#>=^TN{MA8!1zYUU-O-#il-3QXX<#6X=1ad1R?b9^PQ z(Ln=x%G&@?Tli4>eG(O=*o@jvS8Ju#uA!FJA!(ALM5oTFQwTw2D-ZMppgWJzNP%s1RzvAM4;d+gjp&-#I_Ve|$5Et)&>hYBytm-E+Qr=(e)_W%E z4{X1uCbvmdM0RYJrCMY3#cum7saxd+Jdgp55Nj0fKyXbjj<9XAvH4M( zRQc}WW$)f=*q#o~*2P~ZB_*$SC2uV%fB_}ah1CAU)B-z?O*RG`L|vtW$iG{aDX>3G zE{>z_VZWfr5uRnmqh%#H$avV3*a_^)UfmllqGg{U4#afo8(v~j6B1q#G9&hS-LG)D z2n!jlFRn_Hy<(o=|y}l zEArvP-PD-4INnX0_8F+BoYJPeC}`_Zh*qN}pYl~(Gh27gc=F8PPst|lNw3Vj`a?)D zTAGW>`$2i@@U1P4(LvV=t#X&>kqX&-hdsz+)YP@wU?!~44EF)=zM|reK-E0E;4{E2 zKzmg3C2H-Rn~KiBhqkah#VY@2zh$O~EPM;{{( z2y0(NoZ)LK63lc!)GF#C-KH&Rg4>sD9bX)0qpwXFG7~tUhQmJZ>LSsXr!wxq7b4;k z;n)jJUo`cjbfn_5AF;xsiU*si1!@eF9c;05!kcNam5JoqHd@j$WQKlBkk;2WG&E_+ z!Xw6e=jnq)$!!6n1((2WDtrw^u?EvRFn6p9;NmPE?N)&YNr zTSP>JlT$`Zu73puR)GXcRn^_@Y5l0Mq$JXXT4FcoRUt1gPqdb3*3sbUlVtBME5u7T zaKx8ATFD6GMEpXhZ9iw4sWSX{^Sm^zqzvLa3IjHANJi)Ns1-I|C^uIgmx4qb)O)BD zdAw9lP_$`$9`Y6iSy$!?-6m(6`zaTO zHh`a-+(fJ*|8eR6Q`Ee!XF$qdPS&z$PRIqk-Rp=KOk-!X+sw z{b%DxPST2numky%Y@S+rc=I%-T# z*BX5SRK^$|6IHpCPRe)RuK2TS`rN3;I^0dB^nUaT+Oa`-EFXD7QZyW$=dQeGR2h1t zlAcI2n0rl^OOAi?f2nc#%D=i)8It+Ij=ybH2$9|FPhoOcVmxK+Z$2JjZ1vs!oo(dC z75cOHH%9Hr9Ql_SbnCWr5&WQ(KOb5gO}zh9y2W0!>W9{)PqK8hO}N}qxy_v@H#&lS z2JS$#Xx&JFJ2!0`@y>K~X~b{-sc1FIyH0gKsWHosNOgw4_pM_*-9-M?#aS*R{Hs3~ z_2rA3CK-`Q=d${qO>L$uz5BMY-#cl&argyJ?0q^pm5x@--1@b4YKH7O%?#RzCbW&E zGop<6Cn*EH`oFv!a>V~MguZv~1ZS=l(C5KzD>hKIC?vZQralpsg{4c0$a#;un++hMVM(6jClF-rdGDSJBcHT+3iwHVwT>p98;QP%g7D+twCOZ-)hPOegcXbaRagkI zzH@YVNB*~!vurOoJpkAcw86IoXcNfq`N*1#$gyn8=jzS-3@$hTMn*miuAE#kNMq0+-Hg=&H+OuB9s?YwrGjCMuNVaTch*&>pIO+=2f?Ut^7K6 zNfK<6)(2zRCd5ss&~d}9V&L1#&W1i?F?;UotC`Z`l|DEm%;Q-1zb;XQ^V;1eO{s(5 zvf`Ov=dHCAdsUa~L~RiBs*i~461$>X;F=mYpnF|p{KfkBHImy0lu{tcwA@n#hz7m4z6E=Xgu^cEK%pJt6xut)EW)uZeOqj+kjz2Aa|XX{OF^Vgo3 zI%RxlkFng}|8ZOOoIi{tV(E$sN7(HEW9Q?7_4vQVlae2%d_CNA>^`Q1hS=;SEvjFx zAsV2?4;Hl}jnlWJ|>JA|2d?s`dX~WPmjZ=gv2Mh;Z(v^upA3nIz zaokN#0CA%?`R#R+K3UbLoiyFi2q*dd(Nw1dE8-Y_kDOjt1ejrcz@ z>BojKZ-$1q)inF`mDGn|bn}Rs77w@?%2!CFek)w6ccrCPaA}IAD;NpzML1 zd=;lAQ;JGt?VMGI(wh@CjwPTAqGC+)G0JrF=8*zCwkjgjQ`vNHuAvWh49!eKpw*Vk}LiK%U@ia=XRH~--QO2kE6nA1&4;B^+H5C8WMHP zaYg?<6dWTYQG-8oCZt%;hbsZ73;e9%NWx(GK;q17(dNV*2h6?HRxyMfD~! zsR@A05r7-kkFuE95a1L_aJ~O)yR%okWvLro)Lfu79^iU9O&Tb{@|2fgXdD8Eq6Vep zVpjhAf&!A|N|u_A{n47q;1tt}?(%YSv2k@95263JNey0E(FH$WY9~3%gWspGuMfRv zBA>q6DvU*{hSm|JqP2~wSxg3gA10Q$ZpELYtGN9K<)5qdIS_tVZFLw!&`k1K`OoA8 zBm+Q%j0^O5^r<%R2fsf!c&~w2&)2JmJlO@%jmXfj8D-M|c+6r6UE>TP&zLboe>G|M zr5gPVLd@lYen9WqxYe>t=;JwMs?qj&3wj?ue=ghapdD54vJX)|R%H}PQ5z+AHB=AN zeBP_`(;3tJ0Ek;XiOGQzttgEXo8z3Fod*VN2K)CSIF}DOj5azHaHwJO9c(TgD4Kl8 zYr7iu-;bw>Ed*5^Kqklx$(SsR%Fp+)%p1{_q5-hq!<;AuMa6Q<2LJEhzr(82DzuJU zO}d&sJ`hFTQ?w$lr6OQ6tz^ZEDbiB3 zT=$3KI{d7uNduy?;y=m~+UtE&g*F4W`vqb#)sTrx0fgT-bv4w%hScqp=ao#;=r+<# z{BO>ufTti7yfnOk8(B9)OZ{NmgUmg{UW^ABn=z6qyd18|Hr>C!Qk@HUnmmok930$ z%iqRM`C{t#6QY^x7!I5rm8Sh8i&hrz@4G$m(xt@K&8OR7Cs)`IkfYU;jB2cavgvYH z_b;Q$s7W(ug0br_dey^A*h=C97xNJ{UDRVI{^vhO=D6nDz3VA38L;f=v*2SSfR8|) z+AT~qix-TF21m%co9>RpIQyq;bS2Q5?aa(Wd5p_?gVzIt*qu%z>@GbxS|D7ycT5r1 zCjWL2o&7p(S}Z(g)9+-NZil-J0}PfIpQ0fcoDYAO=;qRGZj+J#>T!h~GOIuJr)xlY ze%GI9VM131>jHtfANcqFk>U{=D8qG=hd!bc$L1eLwZB#)LzZ9iP| z!#M&GF#h8V9H-4C-MWv%z|o%3i0Jt_L_}uFnRo7NNO`c+sM6G&Ac7|TQ%RK+>$Iu2 zl;i!k6>nCL%=YGF->Hsly?>_L(E)W$d}ZzTIkd>9TzB&5=!t`x+WR}1$4nCh%RENr zeo5;4>+Pd8e`1}DLXv5F_7*H&!tsRbX|<_&5EP+-BGyXO7_?Gx+V(V;%n@~x?UBPS zE~|Z#ejk3&zR%UfaptI~Q_U{*>a5#6rgS(b@>}!Qq(`2UEe%rJ8NC~m zMiO3N(V-{-001xvO)ka2x}2Q?KtuzLu@SH7fAdF47eKeTwzjsBQ42&{9g4$JEATmZ z!y9%Qekfende*$#8Ex!*(fktN#{RXI!Ox!k1V&LH!6BmkTFZUOv^Rh40=cGEuc*l* zvHVfVR2&pL$uW=F<|O-jdRkPc%_-tHt#zy@jn+yf0F*5p9O!9Xs0>j|Yz6PG!_7al zK_C26I8)w+ET1NF$8-GDa(BIaJkW0&_U@Q-GQ6`pQ>phwC5?bT23@`rbS`{YLzR({ z0rvyMqtV5s`FF2XwB$Z~hp=0Lpa5Fw06_6b3FXyQdrv6G^M%yQMc$yU27!4bN!>~^ zdCh=w+9bQMu&@7g?V79_c5oQ*UUfar>{?o!x>OCvQl?|l`}|{Q8~Ln z4c0+>#{~-(z!dyhMfl1u5RNyZz3CAPi#Q0;6Hg$G8E~j5ZERUBG8)u8AX88#6{Zff z>x+?&GG5wuPEu44jh)4Bt0ujl`t!QYp98rLh{JD2{&9&v1hMc1f9g5poNm-E+Fkf6 za&TJ)oW2H3dQZ&D1HJ23t6ju{l4~@`gzn}+em$P}l{4t3ucm=8hqerZFrva%DUbSo zelk~|c_atb6bao9JL8HIYINco=85Ui;{X)DJq|Y^&e2iaM4vgi)O)8l;pPR;+t=&~B_IRDs|Gs9N8kv)O3yQjpviedHLxfA8Id}Ug00)-;aPe$? z#dX@R&lsYVaH_srQWwjjq53GQhEF7!Or8Dch)@cpiF1L+Pg``Bpy3Al-y zaZkyj>taV=H<%!?UrI+z>$Sue1TIEnW`&tzVk6_{qEL4qvJW~(mJ#jGpNL_MYG^bF zAy`V|aE5UOuYX`Vy}Ngsrhpum=uM(|`Wv>IoN6`6&ZTHCHP*B*e!GlH1=p@WRS^dMzJeE$xiE_kE!lDLAC?jsRJh9D7^@{6?$m zL>fmZd1(0Y+f^Z@E;S$ALPJAKN=g7)hsALf5?^ywim7JnL}0|!{%>*3FGe%|r|dMr zA<_8);{V~Y(q37>Heei8fRhTe+iSB- zb!;qa-yQM@W};ym?^=$#9&AnfOI)*}C;rXR&&x zn4&e9O=`3*<*YIl=#Bu(ofP}ip>;7T+x1GryBdI*cEfe(JruP3|o)PNrW(gi}y-QeG1TB7ecO=)=o&xHmXadad+dN$~lniztn!dZP zi7aj$#!4KdGj*P8V#9$H^ZnCXVnp1V_;bjIEmzW(RANth&3&w2E%VK{Vn8N zi3T-oqoMFvP}FJ5t8rio3&0dkjh8?9GFOLeb%icurLL}St^|CNAV(3v13zcwKZ zkAqS6Ex!lFk_E+Z_3G7F#(fv;wr<@Ta`=8eEVCxK%m6z=c>aW{E%OTT3UmSCy2G#t zSpl5EEn9LQdHQ?ioJn$!39BwU#{H*8815i+*luH>yKO%aot8cSw`6-s0$O^Cc+F?z{mdj$ zdoaFr+e@1P>d<$;{ATJ2*C}*M#mCm#Xf}kSn47G^(WAE!`-6gs4pnQ!Y|EG=YiSG- zue0T^ikNOKZs0ls)S=fuJ*;5QiN-avypr@9t_qCz$sqF5$qq~+-#uSxyO#B|MunS^ zY9P-}PM*ff^r1z)6TjgfFUJGEA4(U0Qqq%kOIld^c9z-y3`LqZyFgqaeC-3gV9Jt4 z=#OGVqDN14lEuc@E*ZQhG|D*K$_QkM}qu+ z3V25Z=%PeQUqydIcNDE6oNba8q!G?G<8m-UdH#j9;h^hVu73|bY0=H!+1(^z=CGFh zlIc@mPAtzy?E)vI=MXCPu8aiag3e=R{ojM3Nic!Gr{*7V61sn!0sDWNzu0|1Ci5v$ zQY%ZeQBJC9tRgz^D%qhe)91@^n?qEcj7KKyuvJ4$#;BxVOd`U$KW`<}UyX*Ao8R6s z={$!f>O?&wxx2z(VeGCD_I*}sJz|zu5{tt@+kNdL$2Gt0z4qDUEq0B+JS;&U3u_v> zn^dR2+35Q06L?}U?rLgk;@-Jafx=`Ye^}M&{JPnyPSz9W;PIBE_(@aoId!ArQ3E)_ zpq-mgR19co%jcq&qz7*}(C^%H3B+Pdg^A&WRAx4~4v-~#dduiL z8Pei&6ba}na9NH>>hn5XSl&Mtdf9S*`vktpQqR~QhYud~;nJ3b|4$>+Sf9ep zq-W1Ak%*qPk z0cptyyXAUaS0~B&5IHbSPfw;JP8JqKXonR+4JSj7SWNb$JpU1EgPT~*B7OUzs%dXj zJ(upj_|$p)-lVOI-zEto&R0$L9w=-a*#f;CcsrTsO*`p!BqvmGwe1*&Jfo zJtGLsp0}7k{U{po#bALp#k8OJQ52sznll#NVjwgieG7*}tTCf?*h$s%ZH{)|RNALD z)6)(vm7eu;Q-52)v6)m-=qfY*prc2&pp}wptZp8nS2SKf{%T)zbac+JQ1TjqTELu< zepPO%YPsp7H(%m_p5VbG+ahB$>L7v8pG6d@){>OqDhU|r%n!ZJ(`qSmUHpsGt@Ng3 z$X%fw{6Md7_E*g8kxl_RJ)EuT?g6!^6vTP-d*!tKHE(d`CA3yUZ3ae^xV|6$KR zI|+$*uxfe{6XURnLrC36K9}N2iPw-b1i-n`W{UqnqjO}FC%bAJ`bK*TDnC*AUMx`&f=rD-R!rR zQdTj!tXne8asIUGRd0hocnP(VLRToi+cK8}etWDOs|q#e^13=oQdTva@2WrKqb#1# z++^=1&gkhV(Vbhqb2bli@8YGir!37XKdP--Txuz&*x(oOsFA9!^W36KJ~aDjL-;XP zQc1=e?xl=t3pZHS=H3*4k+xwWPuQ>z`fHBtu-hK$6A))(V{8aGU+Pt+lmN!*!+Nf2F^5>D?mOO%@wy z%d*ot8b(eJwbUzcwdil=F4*`y(Bfob*8X|<_W$}t$(QOq`0Z2%#44N33WU~tpzl7u zuUXR5g7HK5Y8KI2J%VL3%W~l&eRpBgZ+q9N9(=RG^?9S)mWLrjw;NEoC_AZn!%w&_ zDzDLnBI?7_@4qnUR(2Mr;0<%8wAm$GIS2g3KAK%TdaKr5f^}+!+}xEWbQfy|0v3qZ zX2^?j>D%sTXf}Jw*1~_?9K2?G{^RiEK3sk5{yo&GxZ3WndK4<=ZC2x#-_H8X6_C+l zOLp|_0vkt->@?Mp-ttpso+mf+=icgjZ8iOo%>)}~@9bOrXjw_q2%fBEqgnYZUdE=9 zHm5ex=C)EH%%}pofzY*^U{Afx%f6yM9 z1n=aPn_pLtACHquW-;J9iQZmcSL!Hy%plx-4)0hp@hjP@#jpAdn|GI0JI@s$befKH zHeb;h?miQ?ukGW*WtUIg+{dJQbl8I0UfoZ2J)tm}%JpXNPv_yT2ftUuIOnN$fV-gG?S`KZR%Wo=ke+_$@p6pXPnu~x-3CeGLl`Hn zH?$T5G&LYGkc2x@+VsiBju>)xT20>3Jrt#H>cX|cx=pIdR^~8qhA*H_lUUQ2h0Ty9 zKo53@)NocuL|pL&L=Nwk3YTjSa@B#t0pV{EWW%V7!_oL6xC&WWS(00R1@C;hCZF)U zh&a z4dvl6SP>I;sw7r%wggwzMLSqnYM>7mM)FMha5nTEfT1B!I+;anUV?QR5^@Ggbr^Z@ z?YYT%k1s+qLO(A1Ztz0G4LMbRX8&SP^(3?JKs_7Zhw6P+Muy(mvp*_RQ}xv)bk;OI zB%1dYhRJ#!e=WCj$&*=OWKJ+0Vd3(`CFC6n`WL{*Z2tg+rlYYaQ#bS{K?yk~D|@0@ zN~$q;a~sp>>2UYTgLCN-*54yT;CG^*C2s19IYs=)cgR#bE zv4=Z1Ej$a6z49^hdwIM;QrRWU@N=&;V!$;d+R~msP znFtsV(ItY~keQiDsP4E=F?t`|qo{a~q-D)d_OJlD7?&DW{a@Z5#0zL$m0VCdyWjl| z>q()zHsWDRSW$C4-n&v0Hs?gA^Pw;@Xi>amREzvz71Gz)1PjT}3u67r%6UfN%?dRF zaL&^Y^AEEC4p(Z-6Wh-hc)C2_N|&g|MMiSl@%RxYM3O@EhM^X8#5koNE!umad5TXn z4F3QZ=dRqP;#Q&_V3-247jSK1IuXu-s-X?69Gz_`uVYzceiR18LL>Yg?PK$J&n@^h z_5yj4Dr>p;OP0N@XMDkD81rnQ?UjSuOF>VyEaI`YLar%l$t4#reAkHVPp;u} zL!ccDG@lt)rVy@CsBY}q6Sd&5t$DLlWCY}bI!1WAJAc0&tgg&pj|4lD)R!;63>e&n zD+<9F|DJyut!p8_-XRD@Vln83_4W0zv@RQvaXgImyjt*ln3Ix%LT!D0#If-Hc9fAP zc|8+d$^OgmHGxvx*+NPx18y~*9v(5LGM4`13*Ln#?C-ZTGNZ?^^Oc{MhqDm{sW!?Q z1o4rVm*HXY%+0BKS-eSe5()^bc$u|!n!WhAkb)pHpSxwb z#&mco!wmEsoXtPDG26k$9?mX5s#HE@Wf21QAIVdy1U+$;D|RyAk~QR(Yj~rjJV+5* zBe{yim~iG>tpA}()3!HEV~+Q`SN1X4#yGDXAJb;Y1|NiF)`Q(w1#x4c1vCs>$nT!V zqRTPzHm6YfCC!e7^dvR$4%P&H zpsE$+E1j&{lJ8W@>c%9vrqd#7zVx}$dR;vQnS2e-Hmxrx)ONce z&Ze1d@8Q}U#oypD8pKZd>M~HgegBlb&cbyt&{$VT%zByS4@xEVn~RH$iDwYq*9EkY zFWv&h_mOZpToDiYqMbEK?8p8%w~8+xSE1ZSSMiK!d}M0?N!myZd3(=?Ze_b)2NSxe zfiK)Svk_J%ogjMZjQh>S#A8jh=NlJ+t0(>)f$MG1@*{@9OmsL|A{NPZnLLTf=g(`i z>9|2tNxM9ASLY2PCw%#S^$JtMsblf7!_#vP9P{~j^Ip(_ZFd5PGnjvg*!4EBDq#r! z!(=|b>8B##6uY7KPlP?a?U?9+ZCKKl*_nUhRs`?npSk6{HvjM0`8`s!c)OAeAs{W@ z26((Dg&*u=0g5-sQF1jzEpc@q(y(+HI;>@X2ge9Fw zjtZh9*qasZDEuqV-C3hvKU4DEPk2TMgKiV?D<*L8ENZZ4QVkEJ@6C0U7n%DNbdX>Gn;1E05dT{&lUt0Kcd;UNFF+!AgYpEKw4JxG%9LWzsq$CYJJQT^|-iK&tY!@ zOU3K~SrV+q4Py-@c5c36;YU6}TujD54boM^YHSnT)DFAd%^y1 zpEEK9%p32TPxJ5yH7H>ljym;~`Cy=Rh(y@!dyDAPA^4}jj-C{nWukxM#JRTf&Gu2W z@Kk@%GTBYUc}I8g9e$O*H|iMpF0?#+ueybW1u#d{`hol!ZC^Ylp7POrNa!k|E+B;e z!?BnH=9+9iclf>a1Hn4n(Z2vu*%wZ`-b3mQFuh<#KUGhq>%mCbB!~!6==ku5$?x_m zWK4dz=PAKSru4KIjPp+)%mzOCzSL5W@6bD9?i6L4ZzIa1EeZWuXGfwuZ%1L`RGIRc zaV60U+_)Lk*tCzx`?scY-v4o%IOuk!8&a*S2TwQ1g!So0ip<^4zJ-7Z@d%1q{O<9EE8c9ZVL zf4D|oNJjD*_5W;b+4hNP&?3>`7TJZpxhww3*L9m|ING5JXUE@=&{lohj(Q+yMQ)9< z=UYhlPo@9*pKAGr1K&x$X40IM^lp#Lq6gn`8xQqg*;B+jv=Pp%y785w+((x7>&2JG z4N=Ivu_Cb)o7i>h{+zt~m}>T1p9t$!indGnA%5%Ax@xCVY<5zw#3a3Ww@E114bg$L zlwFHuC&kXDd_CgZeYR^mUEU@cOM_Uenz$p>nqSpVnkt*E+bIphNFEDu&6(Kd%v{%2 z%N9t#OU%2yOMs;^gXz5>`ihD(5#h$>Ur#?1WOVF{d9qLyU{b#_qIOQV!Hu{I-yTyv zq%KRhgayeX*|h$ufL4;6t&JT?1W=a!>~U8d0bl*O;=I2K)=$9kfNL&HRh68u9Dc_T z<3P-%xA=1(Ou%Sn{NINL*=F40zii{RDBlSmpwVMdUbwu2)Rk6dI%C|3y?5MMCoS#@{iiZFIp;l3;d1mA9yTn`zlhx;=pN@NuT2Ax*ACu0t!WAe5|aY&!0bskSW5jOP!Ar zt5*;v8}ylZS;o6(CZy+Y`j*qi;SujDliDyH*x2SJ(1=>wc#wY%@xlCJUBk z$b|vsgbx?t0*uZdS&aR#5dwAtKU%`mtE42}FQI{to>2oxpPO)-V=t@1X3Cl3dsAZw zeI@cPxL78Gr*uZAdK-g`C5~^-w>Z zV^bH5XpCbKmlakJ3EVK`xY6irc|xglm3PzviYJGWCSj|#bI3vu*(3r?UcszTl~pE7 zwLbE0Y#v$@K%ZWLQkiLyqH=f_+?^ETT!#3+s;wD?NIS|YcXTd0Gt%(kaamn(F6;@= z<-!8BYgiBzBq;}ib>G!YLGS`(1@><`=Y3=!PmalzAEpqYF8pyXLX1?T+rFZ8IMTXD zYg|I^3gY48TSUKuXy+I)7%Da>ManYY)O4me^|4&PD*V~VPhg{q6@Qb_fWpQUQ(A2F zeZT=wpqK`lb)a6TtYPBdK4lwagLL&g)f>U(sgcVh9>+#R93;VPhanOO;JBCUB*%=R z;5o2LeEB|Up#Xu=uX8XpHC@Oo`h)?D$(^l5gv7w8P*I}%{vrmRkKbY|y0#I9dvKzL zuwb*apZERyy}-;i8HE^jH&ZU)_U6de`~_m*8A|a{V87<&<|X&VBDzpGcZoBPfnK7d zsA#p}E^>wkD{!flhY#PBi3>>^2svoSS!^a=>Mq8KQ%sBsgky*G;bKnS;*{Iw2grko zf?S^mnFUOPvFas-7G8{8Fj_L|Yq44|4jL1md-}{7hCodL%eG+4=n7PqosG@E<-Q@F zpF%jufnX^~d38Uo9A^oFdD2UpeKCg3Np+s;pLJFnC3hC5Wfg8?IJAgEM~OKd+&#?= zNDP3+m}nc~Nj-)9Q;%leU&I_9Kpn`T@>oBqUG>63zq_?Dtp^@(&T*e&1g8frpgVB0 z^=S#6&9EiX@YxrfyKmL8Qv>TiV0dAwB;dPy4o~Q|Q=!mG4_=pEIVKb$PiD zb{b}vD5`w+K2hNUBM>tLgn)a|&uE{mZAu>OtS!I3o)UBko?3_lwFB*jEK#M#U;-t( zkBSYS33n0UFiQzr<0GW3o*gKr)%<^&`|fxu|L||^ok~)fQAx^(>{T*KkwO_6+4E#4 ztB{gWD#{MY4t35!R>RlI&WIDTD-I#!80S3KeGWpth*j4Mrj;FsDacE`Xa0qY!YFwY0D}`=xy1U<&|* zxe(XVlS+i)fK~2L5m*?;#IU};ICZbNew{uErcH38vI)%lL+UD_dr69E&_hftkUZ8J z*ju5rRh2V4(y%*%=-1Sc*iuW_6hacMpBgN12ca~5M6;`zXsUEA91A{rEd^z-hoWw; zh-7TjnfZ&eo86q$=bS?2;utu3WPT*K2tSh&@%l-vcfp=HouD^jYh=S!XTM3a|}hy zc#dl;V=j-L9Z3EYE=N5aZdD`_P-d%~W8SzqWDK|Bk>-@{*12o3%qaX25DSsb_rusB zyuiS(f)d=Eey~XVVi$5F0~U)clab466;4B664SqY{xi`^F27IHB8za zRT$XD*?nk-wS*`Io?G>no{$Go^cTb1sO%dwPu6>Y6X2F9_}DWKWbHF0oDT8b1TqC%g*A_XipWX?&hi zFN1`7J@To3ZLH*csZT8BDH==qo5~mErQv)}ZQ~t-?)~=iOio)DT>Gv`S61a^t61K4 z1J*2!)liK_W8(iPXC2IyYHXlTExj22d}}EiET|D~xxl-A!tj7J=YPxOcwo&&9`Hek z#4ObXxvA;rykIYZQj!vkX9F15QR85~%|&Y)>bLw+e!>Y0LU9L&F@UCk?N||?3+CkD z37B{z2q{J5F*8We@mvYp&S4~aTiR?(<2K+vEL^gdT0;@*mjmfo4qDLc5%tpk}whXN1RaDu-BVveh8^7iHxP@YXn< z4p%v|^~T3y-6dmJlYNazPHkJ(fVHOslK@f~y6|E=plt=}u^ zU;#@L?$cpTPJc!GVIRzF9hO)GWno1n!lH9gz*mp$G{=?R^LYgnbtJvo67QB`>F&My zROGZa2f)bd>0BX}9oc{=Xth*0xN6LoKsn`LUt)>1wXs0}v--~nO7`ipY)0)s5{CBC zCa$cnfJFA(2TcM1y0V%%%*@`a3*kv#_LapT8fR|g=&c`n@i^Fw=wek9qNDWyE$cZ` z47^)Wunz`Q4xuF)#W(9h#gt_G*F9QL9mvKz{8jkI9m%}y14o6a>5;1Xk4W-uh;gJc zw}F?(-W}TnXE#?0HV@DEEH>Yf2xW$#U?xN@7M0zt5e6;@5J>4QJ8|yLzrGFCDsYD= zFu~|B8>}$lv%bJa&Gqeb7)LO2)dKI1G{Ihr3{`rhe=VUH-5qeV#ZP@8CH7Bm zP-V8n6yG%2esHA$nVR&ETl)E{zb1%3DoBl;e?=50ogZ@2SATbcVZY*Pp;Jru?mrK1 z_1K&?t*KV`sXq-^P&!(tP%xAF zj|awKjZksz8BMqL{kGfV6Ix2}_w!Q@CpXKwlIe3FtjA3dq)dRxX9j%{NB+l*Da3V8 z>6_o*m8JKb?iJ-qQni-MpT;su4Gnm$$%fGAPii`1-JaVexdwz}?elF1FwP2Y#%+56 zl-m9maIT&T3^w&&p^8z69Bx3+N?J!TYm3#TZ-X(ybnBN!si>vFF_bI z?L6Pj1RA3rm!UI+p_%$Is%`t01@KHq1Qo*V7c&(Xp2;6PHTF|xm482W`@agAEvj+C zpDci)u6p!6UBanDfHSJx1q?RCpX)4noVj3Fj$F6@Oo?0c_y4!)geSXUplsv}^rHeo z1?tGVPvA;$t{&BAaZa|#u^kq-X-dkKYnF7pm*epeLiidLV##U41FmvbaCb3@Fd^)8cmno{JFV??nC_jWUd4HwzTx|V33wP0D>+)>C8OEb82YP*deL*Q^VOI$@ z2~hMvj4_ykfr6Azgl5pRo^f>0o#b5q8H~YTz?y8if_JqjrMAan&C@F@YIjHX zj!jyw`V=6R!N<;CJmK*ih>8ccw!Wws3Pa0Tq8TH_09_Y!=E|SA+NpmWh?n3Gnu#nN z9tj?Mz!ji|{2bF`BJ-3eBj3&s@^=N-df{*8wZ0-;BShH*7bWbiQYK~2bY zrQ`vl9Q(c(W7R;Kk|Yk@Z?FV-X&0B)<@4vSl^%F<8FjNF$ErROEaa%&etH5ek6!#} z>gE?n>E>^(z`1aV;3oXN$%9Pbt(6&r-qqIjbyKXkHtNGRz$baF#owE-=RX*u<>TY? zm#h>49MgW)QM^^ECA%E{XIBPtvty4L`RUAXx@eS{0HHFeyZrEFAOKn@TlUm9!O8>t zapjcEMlc^;z*KLWpD!0r@WMsRx`?T5{nXRleJ(=exS(KTgCszHP9r_3U{C_jMgzTW ztRA{v0XY^B0e_Qe`j!`9GVa5%`SHDHTz1vXXa33TH-9ZW zeO-9KjyWbK20EBNaXi?eWLn~042*y@2GXWbc1hnLRKpMJ)Hn&Qyh&p)zqXu#9ssDG zK!1&taJ^wZ-hR|rqLK&ZJ0qMZwC5h)tA&94`(Yh2n~hCHF~xDf%MB57(c2xJ%m8#yE-eWaYPr!faDz(c5q%a>ID5ICH9pBE@m?Gf*e;oM|<5k@$7dGaWuK+_h3CCtP3`y-4RIk z#dw}9F4r7MsuAuD9|3swuLg+P{ym~Ul|_9CQ3y{f+}Uf1*JZl?^;U1Bb0w^UWY=Jz zdukz+kmeyxT=R^1X5GP0={DVGs7=vW9D}UA{pdNtmO2<00iZWJ(Bcdfd6-$qCSY!r zrfDzYN>0X0W2F`P>#z~b7!fBJFqoht9+w-myy!lA(hB&uAbEyzB@tU=>e6TfKKq_2n(AkWsmyo+|FW8%=-C$6Xe|4!nOqAiV4r2z3m4d!hFNz z*H3%Jl1ChXCW_Qhwntg}p&~yIvwCP@Y(@`UbmVePMmUK7_^0N9Q{+z_;^d?UO+D-l zMfaHtU^jN2=+ZA)IC) zjDxjX8>QIZ3aG=1MnkFABM^FX=imB~GZk05gB zH`{!UOi7j}ZAu3DP{H*$ttkX-g}1y{=~lQYRQb`t%fN0F0x4Oq@Sa{6Wy2r2vUJ10 zkpkNN!v&F-?eh9JiO)~j$}k51cqyCrf5^okZ08ZiexBxVNA<0&+FTa zNd_Mi1__tX{RCjSyv*v@*vq{S6>?VPqu4gp^{N4b>sGKF*U|~2dVY^wmCRDbEhw6{ zG3~UjQD1`?jZ|@&QAtAABktUv9!;+yFdGb_(HJ~UspdhN`d1ROJ##P%)pPGYbDEnf z3+ugW0stg`EHCe0&?H+e;q$79!?8mIAxX?$=-F?ZCCe@W|NYrP1v3Syzk&u6z<{x85y1$KYJhmHXe~G{1LAEClnOAbnua`zJrN+K01W?91mF}&*}L_w1j+Z; z1)Rzm({nh;WM7nNp}7|yA?m0Njk%E$*fD~j#L9}MXO;RJyTrry2&bszX)7=rZb~jJ z(!>21Qh6;>Di1*>ItK>_hyq>km`1;Xifqt()f*)t=x-v{4DtJ0)W}Af%xES7D;v7d z*ZKL{c&A1Bvl}w{o?x5}ZDIjpS#%=^8pXzMxeMqi@>)IV*a~ll{lm?7#u6|}rUWbr zJc1@?2Hn&4A}PEC-YL!Zt}GB9(#@Sj_1v?kxl3)H?7f5uclYy>af5h6tqoX)>C5Os zf;5mXRQ-WE1O#%W<7>Ave6Fi|z89RTJlAeHh6OJGXE2DUQBx8lOUf!#axEcPUMn2yCM`FC&@S~^% z@5ynxf{EKrZ94{5fd{!f6p-c2?XT}%;aYiutji5Gf26tmHgL*7?+r|bVgdMK;4s;aSJNH?>?;`i%NwL;1-WoeHr}4ttkCHzHgt`L-{dWuG1WYt=_EyfbgNW4ZxFP!z zNGQDiJ?_blMhP@qsl2Z1y|Dy}&dhk^yX=SNR!VcHKh1rmftb!H?^Zk8EZYtKVU0zVI|S1giw#R-Zh&6X$R529;MHom3X1RskWRTp8Q~ z@*SHb`?V&6?@;$lc#?}d1QMUss8rkZNU}lTq6hhxFO!=Zsc-Ph*;yaHAw*^TTaE)) zin3>P10n&(NSjz_DG1_nLd3T;Z{vV&mQe3=sDNk75%a z!uZU6?M6vNb-#%7xk#d~EoN(y@^vSsO7gV}-w(&e3ZY+marUc(kJ|97{`FP=Lv zgF8CFFUy!U3bYOzjV_ZUXrPujKrF37d^O?CukD@QP>@4p!pWg5y3i#xDnLN_7kdJ_ zWCkV*k*OKcdYJ~2KV|r5w@zg*dq~KvG z`3=D-KA4X`ADl}BfI9>x5Y$%Dk=_E(wT#D7jKi-)Bai28M%W2g47{V z_mi-4@km_w^MIe6zyq&Q0UpNIw(C2QB5@dgVV0gu>0O}a&x2LE6GKl>>`CzK6T}Hn z#oSpuDpKo6Gf<;^n$9YzcJ`$ue~}#O%p1QcSg)|iG{5Na!_;xZ+|-dW5;H4BuHT=1 z8^z|sx$Sc6$lCf?rg>ujytPKcfq0pK7aRXXf3wzy4|^PldIZ!yA6qResCiusl^nHWoxsZSJ|e>ZlttpV$!H-$&JZ!yQ$Jaqe$ zz(a0|#^kgQ=jdKlo^t8T^m05V7i7;|^$!jpthbj+1yXCInbn8`Z}!OGN5YMBGExA6&ThX~(?W6~OS& zlTfno<9>L%1LqVVUjgTQAft1>%wlcX#85fs_hDv-Z?2!tJV49lm>(wye+ekXAo-3G zbE;*M4?Qk(*i?FI3)=GLdBm~=)ER9`OC4D_vP>74yj(1Kb3M9QNrKP?oJ!rXBbwO$ z8ad{3<16n-1GIp|ZP#!eI>bY=JpETm1nT=a^C?uSq!V`MmEfAVn3xV{O_sA{_2fKn zZNZYiHnQz^`H`Rst|`#0LDFd>Xyw5BT-vDj;Q@u0U``%u=>TjPGR0}=J9TWau2nir zO(A=Ids@q$bKkU9dfi-m70fZ~i)Xb?|u z`LYnIRSc@zGkIz--Go#gSdh0BF_{k^J}fFKYSebFm>!7%>>lpmS$`6UDIWtlSu^RB zWq{UHt&jQzHl#cAH&Nh}(~E1761{F7nOaVqZMZJfE3@T7uTzmA{C>Z9kahN%XL)qd z`#@d-|_%jJZj3f6bfkPKpTgby@RcTs7ki(OKA z%jh8DB-SSY)(IA7W*7V^PNsVz7MXSUMK*|>gPVJ7Jmk?MeU~Q{&^C3^A;HQ>w}mye z?K;?}fZH+Lr$f2{v+6dN5&!HAmz_sbEuJyDbjWWuB0)Z}g$q?Y44*+^VpIqB%q_y& z9@?q?y!BhiI)Xm|i~}?0ZgVcw7uB6<>8024#nsgr%((bx@7|ZvXo8qz)PwvU-Z#7{ zn6bH|tsu>Jj=!&>iQLJVr$Irg>gpVJ;8}4*D=Yokv#$>oxOm4Ci+~}XviHZKE;=)$ z;SzdSay^E}2Crc3BB=ln-qbs4w{+)mtJwIspxE?Ut7nY4gct#%f*Zks>qgVC0jDSX zhn}de#Ls_*iJ3wW@-Mk1R9{yiJDo=2)HL**m~i!Y&~4moGHrQl34^>=pc2Bev7Dj! zaU5$FfJp}on0w@Ip(DU%E(D$(5JN!2YBewtXmjI)2e}*o(enWQc>M)Mu_9GDGgdd@fSDFin0ZKp^sNjJ_IY<^OF)l_O5| zH5e(dQ|nxbVE+v91Q2_rJ~E|+R^V%%_15?-QvXuL8B8^>L_iR%a9AX3ic>A6q^e3# z1PFQ>Dk@0CrOU^(>X3+tE9&Y_FqHsfx3H=3g$jXv1=VwI8vLmZ~lbO)E28?>Vuh#7E( z{+$|iXokYVaG*s1ej-RVqLCbsS0A~+Z&3Y}flqc7`20f96tZxEklE8VWuo&9I<50^ zW@yUW$82yS&5T16Z-T}wc!V2MfjkF2GI$gruFlQa1b>GvEY|-_3;0r*49b|ypEnva z_RQA?0MDjNd(7NM(#edtCXXO#YVTdAn&K)7#tCGWevzq$?j!IsavCw3+v?!hvuj3ihvp*kf&|z6A1?8(M4h&olKkTg=6v`uE|v{i$^U4H#t zw~8!JMLG&-8Ltd5#x-@S7oYYXL9euk{7`PrMwWuz#?nPonwIn!A|alg zK6OHc;JLszX-=782D8`sztZ@FqAUHINx)qy!kARRd%h*t>~i5d(_#Fr*;kn}&mdF% zJU{)uj`J-lS>{T<7nJur=W9ZK%4NcLx;;_ymI1Xp7_1*RXsX^$t>km`_aDB-dArf< zxhLhxT8>58Bj1h+ZZLd8VYz8GT7S8^y;%5fuh5dK62f-76MHo0F|!&*KlrPGixKSV7fd)K%HBro8nlrX$1#^W5@eb9juB*Mm-R?7#0>b z%LtQo{}s#3C~RZ!y*BPsyi%sPA-p%p)`0^&EpJQ%4junWcVe%*Tl;M~75%1HhEO^m z7fG%AGzi%?lan__PyTk)NM+s{`iDH!>`pwsE&$1@G!y$FRi_Zv*_eOctn@#<^U{2i zjuRUTJ{Fg5T0=mlR0SV=-pg9 zabD@-#Ybkz;$btg`hajAo=4irS2i>ywhSyMTqe@Z`kOHdZqaoQl_ci2hSZ(f$$?uD zPnhMj;7w12J%Y0OA7%bP8R4!z z(X#PrQimEQPJxaV>Y+vuKl&+hV!9#zLLZwtBO41etUYZPI(cXBdfeJJa&335i|)*V zhh)Ky*6(}p-LWS}Hy2$hHIb$iT@BPN{eZ-GmzR}*l}Wi`Ebn4^(@X*}iufx&v&A8- zN#77iJ&@{wcy2VI4Cy1m#v%zE)<6Pr=D5RPE57UY1(|&D2eYee7JP&~+2OHbq z+5Cg|+tuu{CCbiBr$pp=*RpRV(Bt+^sA7tXaQBKpd`ap-5sO;sx6ak7FZ|&Un>!t7 zz0HrW{=22+q&}6t;R7m|X_qyW{$nFir0MoM%-D4+?cphWss6fWVyKf^{MY#tCvJ&{ z3)pP$J|y-CEPwvdQq?AJEb!0+YuxqAh483SeBI5 zkP7mgH~F(xbqFzWGkWrFmpRY-bxnM0aKw<$tl)*tgH!lsrS;v?oZ&Qt5CaOzK0Wky1pPOnOHwM zQ|;AEO3bPltSk5?VRz%%*{y0X;iyk*2+!^AKD>?QOY!6FS9nU)nSZ?(J!Z%H__53G zj){-c4)lGZRuIN2B&;yf`KmNn3$q(L?zC~!O#}fOR;h=(^M#OD8%O318>tRtw+&6-k z>oF%08yoUo%XDob;BRT&J|=uQdn3z-5>4%wlDc!(E;xD` z_XbYGBMlt{OfH~07Iz#7A4R|@-(5$K-LLoybU4r)h7^|?91E210*@Pjdw|p1)1k|u zWP(Dq0i^^MuAtSI&ownQfglnVO>2ewJhiXO zc`JH7yzpa%7pJMKp=rR$00!Y#;M>vpb^=`PPMEu<4-8nD*9cu7>bPz10&fb~>Cns6 zh-5>8AD9}!7mOt_yVfZ|e4+seG@K~8_ zCN9lba_({R`Ge~?FRjSTis5G$lz$1g_uxGs;nSZthFX7Itn3(ri3Ai0EUc6{b z(?J0;U@pzj*$Wp3)-|y54Y@$kUjW~Yk1w8Hso!UyP)38O58$u?&r5(vUxDqV7Jm|w z?mZnAb-79pmQaIZ2a+wLR`2!Y)a-h`=F54;*2c37_7#iOhNtK@+cd1p`x&q~V*P;w z%(5FkK!JQob1L?t{a_@fdDGU*9|FLzDquHn2dK@lqabqw-xb9$fz(&8F6{2u{Zcy* zR=F9IAU{7mq~Pf(5-7j_(P{F#gP(=0K^~|Zffoz{^AKO)G3Y+!TLCH5YKeQ%q=W_b^Q5692`y6a+CLzv(z z%#gS-(w0b?#OOv0X?(iQ^Ui16?+10kmIhlk|Kph)0a8>?T@gdu&$}HTS{qMv&92nc z^ZAZjDoc_5kN2JH**!IDJi|v%aObi~v!6U&dS_q2P}!^G)EPBGhR(s1mrU7T!q?aJ zJl@Zq(lg~3d(zFB(RICY@c?Xy1n3PYbl35qThcBRN8EZ7GG-uJPWQwUBw1Tu3ndq407($VM0&; zeT84p@D>X0nJki2z_PQuRWZofo}`)bPNv+UFCF)4!@sa(L*q+-;*Sqpncmj@slI{u zO{FErICX3#dY_KV?8)`DA${D;OQCfbd8h{T%kFaR?nWc!&j5}U0btXTHG z>fZHqTlOyU6rPY=_MYwTcoy}0No|vXCqhC*wXwdzihFY=oXmg@Tz!9MpW>mm?p5xk zDC)Vpd32yY)Fj&hT3K{-zf_-2=DM_xe|u}UrXAtCx#;O+hSjNcCM97{cKDfqm8$;aJnU9Gfevk4*!D~@gK9K!W8n~mg~9};C*ep9{*S7Xsm+49tu zA(p$Sv(dx8sOlYac}BFW6f^z1Rf`Un9nuWH_}XOFQ;*!A@rz=Zx~_H9NK-uhwf9Tg z@{DF{%=J8LhO(i&d!#x)4Q=tR;IQGEb%jjJ+}{Ag!<`{sk!z(}M{H=X`MRct5m7>s z>2Cz$yGZ(>fgjyN(kEfHKaMI~QC;j>zW7}{q?Tr&GV9{?*IKj9v}bkkv~5zT@?WDL zGmke4HY-5|L6u*)ZQXi*u@`~KR58ij%@rSo+x9w#-*1I)y`}XQk}{$EvhqySyO4>Q zr~^2{w=M9!FIVrb@{(oxRH90y{A)nH4|YLCi5oO!QI~<|DrF06>w0vE(>GHd@~?ln zsw20_kxKW_a*J^82gAD$f8BLS1zpXpduZ(T;u8R_=5r|}&waf|$meIwZMPND8Qe=w zs@)wdYi{h_%w|l`BdvM6>ScmSw9eb}{hO9--QGg-w<5hgJ_o94>DKH(-f?KB#ET_c zz=v&j=t4v8%>5iyOu*9WfqZG_$N;TYJmh{Axmpzj zp2GIqMm^E-(JT(nY3VMby@r`ZsrZYR*}%4P^Yc-QZ&{PUmYVf;`40*^q}MT*lNvRj z&TkW~y|?Lz#y2{iol__O*c-q}4*9C}-$(g3sntA%u+ziWT`F&6;tXHg-)>t+{uh>& a#C06TSB^Aox>bSvkJB=Wr(T}a_4r@&awDJs literal 73341 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 @AEORRG?d3i7t=V= z(j(OYI)t{Q&r6mpX_~loU}I-733`%qfn_WRfeewSoj=Ca22{GBj>s;VyVG4h5sRN_ znh1G7{W}XSld#9IFSaBj!fY0>3KT#( zj9vGsS9*&_Ed~`*vrpy7rMVfKZ?-HNtb?h3YBu%P<2`B(wl(SCtpqnAi29PUv0V?O zY&05=9diUHtb7dH24ufLzDUi(*EyP(9e>gY8BSQ%0A$iikk{Pt1(i?Jem<^>C@h;B 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 diff --git a/docs/diagrams/SetMarkSequenceDiagram.puml b/docs/diagrams/SetMarkSequenceDiagram.puml index da3225bb2b..6ef54eeb08 100644 --- a/docs/diagrams/SetMarkSequenceDiagram.puml +++ b/docs/diagrams/SetMarkSequenceDiagram.puml @@ -9,7 +9,6 @@ Participant ":SetMarkCommand" as setMarkCommand Participant ":ModuleList" as moduleList Participant ":Module" as module Participant ":AssessmentList" as assessmentList -Participant ":Assessment" as assessment Participant ":StudentList" as studentList Participant ":Student" as student Participant ":Storage" as storage From 4313aeb07d09a3d3d283ae01feb2f97959a49503 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Wed, 27 Oct 2021 09:57:12 +0800 Subject: [PATCH 220/543] add sequence diagram for addstudentcommand --- docs/DeveloperGuide.md | 3 + docs/diagrams/AddStudentSequenceDiagram.png | Bin 0 -> 54423 bytes docs/diagrams/AddStudentSequenceDiagram.puml | 73 +++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 docs/diagrams/AddStudentSequenceDiagram.png create mode 100644 docs/diagrams/AddStudentSequenceDiagram.puml diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 89396d0908..967c326fdf 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -83,6 +83,9 @@ stores student internally as an ArrayList `students`. ArrayList. * `StudentList#findStudent(keyword:String)` - Returns an ArrayList of students containing the keyword +The sequence diagram shown below illustrates how the `add_student` command works: +![AddStudentSequenceDiagram](diagrams/AddStudentSequenceDiagram.png) + Below is an example scenario of how the add student feature behaves at each step:
* Step 1 - The user executes `add_student c/CS2113T i/a0217978j n/jonny` to add a student. The `add_student` command calls the `AddStudentCommand#execute` method. Within `AddStudentCommand#execute`, `ModuleList#getModule("CS2113T")` is diff --git a/docs/diagrams/AddStudentSequenceDiagram.png b/docs/diagrams/AddStudentSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..115375445278769be178f24f6d4a00a55b3c9365 GIT binary patch literal 54423 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 AyZ`_I literal 0 HcmV?d00001 diff --git a/docs/diagrams/AddStudentSequenceDiagram.puml b/docs/diagrams/AddStudentSequenceDiagram.puml new file mode 100644 index 0000000000..ceff8981d3 --- /dev/null +++ b/docs/diagrams/AddStudentSequenceDiagram.puml @@ -0,0 +1,73 @@ +@startuml +!include style.puml + +Actor User as user +Participant ":Ui" as ui +Participant ":Taa" as taa +Participant "<>\nParser" as parser +Participant ":AddStudentCommand" as addStudentCommand +Participant ":ModuleList" as moduleList +Participant ":Module" as module +Participant ":StudentList" as studentList +Participant ":Student" as student +Participant ":Storage" as storage + +activate taa + +taa -> ui : getUserInput() +activate ui + +user -> ui : "add_student c/CS2113T\n i/a12345x n/jon geh" +ui --> taa : userInput:String +deactivate ui + +taa -> parser : parseUserInput(userInput) +activate parser + +create addStudentCommand +parser -> addStudentCommand +activate addStudentCommand +addStudentCommand -> parser +deactivate addStudentCommand + +parser --> taa : command:addStudentCommand +deactivate parser + +taa -> addStudentCommand : checkArguments() +activate addStudentCommand + +addStudentCommand --> taa +deactivate addStudentCommand + +taa -> addStudentCommand : execute(moduleList:ModuleList, ui:Ui, storage:Storage) +activate addStudentCommand + +addStudentCommand -> moduleList : getModuleWithCode(moduleCode:String) +activate moduleList +moduleList --> addStudentCommand : module:Module +deactivate moduleList + +addStudentCommand -> module : getStudentList() +activate module +module --> addStudentCommand : studentList:StudentList +deactivate module + +addStudentCommand -> studentList : addStudent(Student student) +activate studentList +studentList --> addStudentCommand +deactivate studentList + +addStudentCommand -> storage : save(moduleList:ModuleList) +activate storage +storage --> addStudentCommand +deactivate storage + +addStudentCommand -> ui : printMessage("Student has been added ...") +activate ui +ui -> user : Display message:\n"Student has been added ..." +ui --> addStudentCommand +deactivate ui + +deactivate addStudentCommand + +@enduml \ No newline at end of file From a48d3698621c29e27fccb27ded00a99b4997b1e9 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Thu, 28 Oct 2021 14:35:23 +0800 Subject: [PATCH 221/543] add ascii for welcome message --- src/main/java/taa/Ui.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index e34e7cbc77..f1748f2821 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -6,7 +6,14 @@ public class Ui { private static final String INPUT_PROMPT = "$ "; private static final String MESSAGE_BORDER = "------------------------------------------------------------"; - private static final String MESSAGE_WELCOME = "Welcome\nWhat can I do for you?"; + private static final String MESSAGE_WELCOME = "Welcome to\n" + "\n" + + ".___________. ___ ___ \n" + + "| | / \\ / \\ \n" + + "`---| |----` / ^ \\ / ^ \\ \n" + + " | | / /_\\ \\ / /_\\ \\ \n" + + " | | / _____ \\ / _____ \\ \n" + + " |__| /__/ \\__\\ /__/ \\__\\ \n" + "\n" + + "What can I do for you?"; private static final String MESSAGE_EXIT = "Bye. Hope to see you again soon!"; private static final String MESSAGE_FORMAT_EXCEPTION = "An exception has occurred:\n%s"; From 997cc4118b81580cedccb65cb0a804728238c91d Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Thu, 28 Oct 2021 15:05:29 +0800 Subject: [PATCH 222/543] fix expected text to reflect correct welcome message --- text-ui-test/EXPECTED.TXT | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 9fabcd7265..99bcfd21e7 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -1,5 +1,13 @@ ------------------------------------------------------------ -Welcome +Welcome to + +.___________. ___ ___ +| | / \ / \ +`---| |----` / ^ \ / ^ \ + | | / /_\ \ / /_\ \ + | | / _____ \ / _____ \ + |__| /__/ \__\ /__/ \__\ + What can I do for you? ------------------------------------------------------------ $ ------------------------------------------------------------ From 0ede51ca045bcb27eb2ffbc528c9f881a5ca9689 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Thu, 28 Oct 2021 15:22:17 +0800 Subject: [PATCH 223/543] fix welcome message to remove whitespace --- src/main/java/taa/Ui.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index f1748f2821..f6d877bd9b 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -7,12 +7,12 @@ public class Ui { private static final String MESSAGE_BORDER = "------------------------------------------------------------"; private static final String MESSAGE_WELCOME = "Welcome to\n" + "\n" - + ".___________. ___ ___ \n" - + "| | / \\ / \\ \n" - + "`---| |----` / ^ \\ / ^ \\ \n" - + " | | / /_\\ \\ / /_\\ \\ \n" - + " | | / _____ \\ / _____ \\ \n" - + " |__| /__/ \\__\\ /__/ \\__\\ \n" + "\n" + + ".___________. ___ ___\n" + + "| | / \\ / \\\n" + + "`---| |----` / ^ \\ / ^ \\\n" + + " | | / /_\\ \\ / /_\\ \\\n" + + " | | / _____ \\ / _____ \\\n" + + " |__| /__/ \\__\\ /__/ \\__\\\n" + "\n" + "What can I do for you?"; private static final String MESSAGE_EXIT = "Bye. Hope to see you again soon!"; From 5b927a351524fe93fa12bbbc4c67feccd05df212 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 15:29:43 +0800 Subject: [PATCH 224/543] Split data file name and folder into seperate strings --- src/main/java/taa/Taa.java | 10 ++++++++-- src/main/java/taa/storage/Storage.java | 12 ++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index 982db9ad08..3830903d5e 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -6,8 +6,12 @@ import taa.module.ModuleList; import taa.storage.Storage; +import java.nio.file.Path; +import java.nio.file.Paths; + public class Taa { - private static final String DATA_FILENAME = "./data/taa_data.json"; + public static final String DATA_FOLDER = "./data"; + public static final String DATA_FILENAME = "taa_data.json"; private ModuleList moduleList; private final Ui ui; @@ -15,7 +19,9 @@ public class Taa { public Taa() { this.ui = new Ui(); - this.storage = new Storage(DATA_FILENAME); + + Path dataFilePath = Paths.get(DATA_FOLDER, DATA_FILENAME); + this.storage = new Storage(dataFilePath.toString()); } public Taa(boolean isLoggingEnabled) { diff --git a/src/main/java/taa/storage/Storage.java b/src/main/java/taa/storage/Storage.java index d4942782ec..b346b8a8f2 100644 --- a/src/main/java/taa/storage/Storage.java +++ b/src/main/java/taa/storage/Storage.java @@ -52,11 +52,11 @@ public ModuleList load() throws TaaException { moduleList = gson.fromJson(jsonReader, ModuleList.class); jsonReader.close(); } catch (FileNotFoundException e) { - throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_READ, filename)); + throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_READ, Util.getAbsolutePath(filename))); } catch (JsonIOException | IOException e) { - throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_READ_JSON, filename)); + throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_READ_JSON, Util.getAbsolutePath(filename))); } catch (JsonSyntaxException e) { - throw new TaaException(String.format(MESSAGE_FORMAT_JSON_SYNTAX_ERROR, filename)); + throw new TaaException(String.format(MESSAGE_FORMAT_JSON_SYNTAX_ERROR, Util.getAbsolutePath(filename))); } return moduleList; @@ -70,7 +70,7 @@ public ModuleList load() throws TaaException { */ public void save(ModuleList moduleList) throws TaaException { if (!Util.createFile(filename)) { - throw new TaaException(String.format(MESSAGE_FORMAT_FAIL_CREATE_FILE, filename)); + throw new TaaException(String.format(MESSAGE_FORMAT_FAIL_CREATE_FILE, Util.getAbsolutePath(filename))); } assert Util.fileExists(filename); @@ -82,9 +82,9 @@ public void save(ModuleList moduleList) throws TaaException { gson.toJson(moduleList, ModuleList.class, jsonWriter); jsonWriter.close(); } catch (IOException e) { - throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_WRITE, filename)); + throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_WRITE, Util.getAbsolutePath(filename))); } catch (JsonIOException e) { - throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_WRITE_JSON, filename)); + throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_WRITE_JSON, Util.getAbsolutePath(filename))); } } } From ad71a299d4bf2de28f917836a0a371103cecba53 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 15:30:38 +0800 Subject: [PATCH 225/543] Change Ui.getUserInput method to allow custom prompt --- src/main/java/taa/Ui.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index e34e7cbc77..642b2e8d94 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -23,17 +23,21 @@ public Ui() { * @return Non-empty user input. */ public String getUserInput() { + return getUserInput(INPUT_PROMPT, false); + } + + public String getUserInput(String inputPrompt, boolean allowEmpty) { String input; do { System.out.print(INPUT_PROMPT); input = scanner.nextLine(); - } while (input.trim().isEmpty()); - - assert !input.isEmpty(); + } while (input.trim().isEmpty() && !allowEmpty); return input; } + + /** * Prints message within borders. * From 7399df7fbc4cfe930365da2b9f9a621c488d0f97 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 15:32:08 +0800 Subject: [PATCH 226/543] Update Util.createFile method to create parent folder --- src/main/java/taa/util/Util.java | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java index 72b7b95072..6ba5f824fd 100644 --- a/src/main/java/taa/util/Util.java +++ b/src/main/java/taa/util/Util.java @@ -2,6 +2,8 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; +import java.nio.file.Paths; public class Util { /** @@ -79,7 +81,7 @@ public static boolean createFile(String filename) { boolean result; try { boolean hasCreatedDir = true; - if (parentFile != null) { + if (parentFile != null && !parentFile.exists()) { hasCreatedDir = parentFile.mkdirs(); } @@ -94,4 +96,27 @@ public static boolean createFile(String filename) { return result; } + + public static String getAbsolutePath(String pathStr) { + Path path = Paths.get(pathStr).toAbsolutePath().normalize(); + return path.toString(); + } + + public static boolean isFile(String path) { + if (!fileExists(path)) { + return false; + } + + File file = new File(path); + return file.isFile(); + } + + public static boolean isFolder(String path) { + if (!fileExists(path)) { + return false; + } + + File file = new File(path); + return file.isDirectory(); + } } From d4a0cf1587db1af92629ee009ce34b2664032076 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 15:32:23 +0800 Subject: [PATCH 227/543] Add archive command --- src/main/java/taa/Parser.java | 5 ++ src/main/java/taa/command/ArchiveCommand.java | 67 +++++++++++++++++++ src/main/java/taa/command/Command.java | 1 + src/main/java/taa/command/HelpCommand.java | 3 +- 4 files changed, 75 insertions(+), 1 deletion(-) create mode 100644 src/main/java/taa/command/ArchiveCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 7b2180a337..d199bd06aa 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,6 +1,7 @@ package taa; +import taa.command.ArchiveCommand; import taa.command.assessment.AddAssessmentCommand; import taa.command.module.AddModuleCommand; import taa.command.student.AddStudentCommand; @@ -158,6 +159,10 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new ListCommentCommand(argument); break; + case Command.COMMAND_ARCHIVE: + command = new ArchiveCommand(argument); + break; + default: throw new TaaException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/taa/command/ArchiveCommand.java b/src/main/java/taa/command/ArchiveCommand.java new file mode 100644 index 0000000000..f6bb3b9645 --- /dev/null +++ b/src/main/java/taa/command/ArchiveCommand.java @@ -0,0 +1,67 @@ +package taa.command; + +import taa.Taa; +import taa.Ui; +import taa.exception.TaaException; +import taa.module.ModuleList; +import taa.storage.Storage; +import taa.util.Util; + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class ArchiveCommand extends Command { + private static final String KEY_FILENAME = "f"; + private static final String[] ARCHIVE_ARGUMENT_KEYS = {KEY_FILENAME}; + + private static final String ARCHIVE_FOLDER_NAME = "archive"; + private static final String ARCHIVE_FILENAME_FORMAT = "taa_archive_%s.json"; + private static final String ARCHIVE_FILENAME_DATETIME_FORMAT = "yyyyMMdd'T'HHmmss_SSS"; + + private static final String MESSAGE_FORMAT_ARCHIVE_USAGE = "%s [%s/]"; + private static final String MESSAGE_FORMAT_ARCHIVE_SAVED = "Archive saved:\n %s"; + + public ArchiveCommand(String argument) { + super(argument, ARCHIVE_ARGUMENT_KEYS); + } + + @Override + public void checkArgument() throws TaaException { + // Nothing to check + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + String filename; + if (argumentMap.containsKey(KEY_FILENAME)) { + filename = argumentMap.get(KEY_FILENAME); + + if (Util.isFolder(filename)) { + Path filePath = Paths.get(filename, getDefaultArchiveFilename()); + filename = filePath.toString(); + } + } else { + Path filePath = Paths.get(Taa.DATA_FOLDER, ARCHIVE_FOLDER_NAME, getDefaultArchiveFilename()); + filename = filePath.toString(); + } + + Storage archiveStorage = new Storage(filename); + archiveStorage.save(moduleList); + + ui.printMessage(String.format(MESSAGE_FORMAT_ARCHIVE_SAVED, Util.getAbsolutePath(filename))); + } + + private String getDefaultArchiveFilename() { + SimpleDateFormat simpleDateFormat = new SimpleDateFormat(ARCHIVE_FILENAME_DATETIME_FORMAT); + String dateTimeStr = simpleDateFormat.format(new Date()); + + return String.format(ARCHIVE_FILENAME_FORMAT, dateTimeStr); + } + + @Override + protected String getUsage() { + return String.format(MESSAGE_FORMAT_ARCHIVE_USAGE, COMMAND_ARCHIVE, KEY_FILENAME); + } +} diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 8cb964bd6d..49ce450ef4 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -37,6 +37,7 @@ public abstract class Command { public static final String COMMAND_DELETE_COMMENT = "delete_comment"; public static final String COMMAND_LIST_COMMENT = "list_comment"; public static final String COMMAND_HELP = "help"; + public static final String COMMAND_ARCHIVE = "archive"; // Common messages protected static final String MESSAGE_UNKNOWN_USAGE = "Unknown usage."; diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index ab55e9b134..35bbb84238 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -61,7 +61,8 @@ public class HelpCommand extends Command { new SetAttendanceCommand(""), new DeleteAttendanceCommand(""), new ExitCommand(""), - new HelpCommand("") + new HelpCommand(""), + new ArchiveCommand("") }; public HelpCommand(String argument) { From d3dc9959a1f30dd6d5e65937bce6a89162f8d18b Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 15:32:32 +0800 Subject: [PATCH 228/543] Update ignore files --- .gitignore | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitignore b/.gitignore index 5c2466e007..293b0e51f7 100644 --- a/.gitignore +++ b/.gitignore @@ -17,8 +17,8 @@ text-ui-test/EXPECTED-UNIX.TXT text-ui-test/ACTUAL.TXT .classpath .project -data/taa_data.json -text-ui-test/data/taa_data.json +data/ +text-ui-test/data/ taa.log* src/main/java/META-INF/MANIFEST.MF .settings/ From 38eef1b4dc33790287db2973f7db9b4b1d85c3ab Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 15:51:07 +0800 Subject: [PATCH 229/543] Modify printMessage to allow printing without borders --- src/main/java/taa/Ui.java | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index 3672772944..9383d4a05c 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -36,7 +36,7 @@ public String getUserInput() { public String getUserInput(String inputPrompt, boolean allowEmpty) { String input; do { - System.out.print(INPUT_PROMPT); + System.out.print(inputPrompt); input = scanner.nextLine(); } while (input.trim().isEmpty() && !allowEmpty); @@ -51,9 +51,19 @@ public String getUserInput(String inputPrompt, boolean allowEmpty) { * @param message The message to print. */ public void printMessage(String message) { - System.out.println(MESSAGE_BORDER); + printMessage(message, true); + } + + public void printMessage(String message, boolean withBorders) { + if (withBorders) { + System.out.println(MESSAGE_BORDER); + } + System.out.println(message); - System.out.println(MESSAGE_BORDER); + + if (withBorders) { + System.out.println(MESSAGE_BORDER); + } } /** From 499337c861b3d21e80a14a7e564f7034b54eb01d Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 15:51:40 +0800 Subject: [PATCH 230/543] Add argument checking for archive command --- src/main/java/taa/command/ArchiveCommand.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/command/ArchiveCommand.java b/src/main/java/taa/command/ArchiveCommand.java index f6bb3b9645..6448db7fcf 100644 --- a/src/main/java/taa/command/ArchiveCommand.java +++ b/src/main/java/taa/command/ArchiveCommand.java @@ -20,6 +20,8 @@ public class ArchiveCommand extends Command { private static final String ARCHIVE_FILENAME_FORMAT = "taa_archive_%s.json"; private static final String ARCHIVE_FILENAME_DATETIME_FORMAT = "yyyyMMdd'T'HHmmss_SSS"; + private static final String MESSAGE_NO_DATA = "There is no data to archive."; + private static final String MESSAGE_FORMAT_ARCHIVE_USAGE = "%s [%s/]"; private static final String MESSAGE_FORMAT_ARCHIVE_SAVED = "Archive saved:\n %s"; @@ -29,11 +31,17 @@ public ArchiveCommand(String argument) { @Override public void checkArgument() throws TaaException { - // Nothing to check + if (!argument.isEmpty() && !argumentMap.containsKey(KEY_FILENAME)) { + throw new TaaException(getUsageMessage()); + } } @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + if (moduleList.getSize() <= 0) { + throw new TaaException(MESSAGE_NO_DATA); + } + String filename; if (argumentMap.containsKey(KEY_FILENAME)) { filename = argumentMap.get(KEY_FILENAME); From d7442359d55da84568ea2076fc7453b6fcac0815 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:21:04 +0800 Subject: [PATCH 231/543] Add check to create parent dir if missing --- src/main/java/taa/util/Util.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java index 6ba5f824fd..152a9c7be9 100644 --- a/src/main/java/taa/util/Util.java +++ b/src/main/java/taa/util/Util.java @@ -81,7 +81,7 @@ public static boolean createFile(String filename) { boolean result; try { boolean hasCreatedDir = true; - if (parentFile != null && !parentFile.exists()) { + if (parentFile != null && (!parentFile.exists() || !parentFile.isDirectory())) { hasCreatedDir = parentFile.mkdirs(); } From 6c59cf60659c63858fdb7894b7c66ff8f2ac64a4 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:21:15 +0800 Subject: [PATCH 232/543] Add printBorder() method --- src/main/java/taa/Ui.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index 9383d4a05c..d1eae0c891 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -43,7 +43,9 @@ public String getUserInput(String inputPrompt, boolean allowEmpty) { return input; } - + public void printBorder() { + System.out.println(MESSAGE_BORDER); + } /** * Prints message within borders. @@ -56,13 +58,13 @@ public void printMessage(String message) { public void printMessage(String message, boolean withBorders) { if (withBorders) { - System.out.println(MESSAGE_BORDER); + printBorder(); } System.out.println(message); if (withBorders) { - System.out.println(MESSAGE_BORDER); + printBorder(); } } From bd6b83fea151cebc0e7700665adb56758461931b Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:21:28 +0800 Subject: [PATCH 233/543] Change fail to create message --- src/main/java/taa/storage/Storage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/storage/Storage.java b/src/main/java/taa/storage/Storage.java index b346b8a8f2..dd13638921 100644 --- a/src/main/java/taa/storage/Storage.java +++ b/src/main/java/taa/storage/Storage.java @@ -17,7 +17,7 @@ import java.io.IOException; public class Storage { - private static final String MESSAGE_FORMAT_FAIL_CREATE_FILE = "Fail to create file - %s"; + private static final String MESSAGE_FORMAT_FAIL_CREATE_FILE = "Fail to create file/folder - %s"; private static final String MESSAGE_FORMAT_UNABLE_TO_OPEN_READ = "Unable to open file to read - %s"; private static final String MESSAGE_FORMAT_UNABLE_TO_OPEN_WRITE = "Unable to open file to write - %s"; private static final String MESSAGE_FORMAT_UNABLE_TO_READ_JSON = "Unable to read from JSON file - %s"; From 45684dc30043e3be81edf32fbfff76beac854543 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:21:52 +0800 Subject: [PATCH 234/543] Add method to clear modules in ModuleList --- src/main/java/taa/module/ModuleList.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index 7083c923ea..d494b1c9d2 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -85,6 +85,10 @@ public boolean deleteModule(Module module) { return modules.remove(module); } + public void deleteAllModules() { + modules.clear(); + } + @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(); From 004146754ee0da28424519b1a96d220eb2c1dde5 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:22:20 +0800 Subject: [PATCH 235/543] Add prompt to ask user to delete data --- src/main/java/taa/command/ArchiveCommand.java | 27 ++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/command/ArchiveCommand.java b/src/main/java/taa/command/ArchiveCommand.java index 6448db7fcf..a69d117dbd 100644 --- a/src/main/java/taa/command/ArchiveCommand.java +++ b/src/main/java/taa/command/ArchiveCommand.java @@ -24,6 +24,11 @@ public class ArchiveCommand extends Command { private static final String MESSAGE_FORMAT_ARCHIVE_USAGE = "%s [%s/]"; private static final String MESSAGE_FORMAT_ARCHIVE_SAVED = "Archive saved:\n %s"; + private static final String MESSAGE_FORMAT_CONFIRMATION_PROMPT = "Do you want to remove all data?\n" + + "WARNING: This action cannot be reversed.\n" + + "Type [%s] to continue: "; + + private static final String CONFIRM_VALUE = "yes"; public ArchiveCommand(String argument) { super(argument, ARCHIVE_ARGUMENT_KEYS); @@ -58,7 +63,27 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc Storage archiveStorage = new Storage(filename); archiveStorage.save(moduleList); - ui.printMessage(String.format(MESSAGE_FORMAT_ARCHIVE_SAVED, Util.getAbsolutePath(filename))); + ui.printBorder(); + + String savedMessage = String.format(MESSAGE_FORMAT_ARCHIVE_SAVED, Util.getAbsolutePath(filename)) + + "\n" + + "\n" + + String.format(MESSAGE_FORMAT_CONFIRMATION_PROMPT, CONFIRM_VALUE); + ui.printMessage(savedMessage, false); + + String userInput = ui.getUserInput(PROMPT_WITHIN_COMMAND, true); + String message; + if (userInput.equals(CONFIRM_VALUE)) { + moduleList.deleteAllModules(); + storage.save(moduleList); + + message = MESSAGE_DATA_REMOVED; + } else { + message = MESSAGE_ABORT; + } + + ui.printMessage(String.format("\n%s", message), false); + ui.printBorder(); } private String getDefaultArchiveFilename() { From bff9dd68675decfd5037b99f2becba5bd7f00a17 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:22:32 +0800 Subject: [PATCH 236/543] Add reset command --- src/main/java/taa/Parser.java | 5 ++ src/main/java/taa/command/Command.java | 5 ++ src/main/java/taa/command/ResetCommand.java | 56 +++++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 src/main/java/taa/command/ResetCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index d199bd06aa..80ce7af038 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -2,6 +2,7 @@ import taa.command.ArchiveCommand; +import taa.command.ResetCommand; import taa.command.assessment.AddAssessmentCommand; import taa.command.module.AddModuleCommand; import taa.command.student.AddStudentCommand; @@ -163,6 +164,10 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new ArchiveCommand(argument); break; + case Command.COMMAND_RESET: + command = new ResetCommand(argument); + break; + default: throw new TaaException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 49ce450ef4..3ee882bc2b 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -38,6 +38,9 @@ public abstract class Command { public static final String COMMAND_LIST_COMMENT = "list_comment"; public static final String COMMAND_HELP = "help"; public static final String COMMAND_ARCHIVE = "archive"; + public static final String COMMAND_RESET = "reset"; + + protected static final String PROMPT_WITHIN_COMMAND = "> "; // Common messages protected static final String MESSAGE_UNKNOWN_USAGE = "Unknown usage."; @@ -50,6 +53,8 @@ public abstract class Command { protected static final String MESSAGE_NO_MARKS = "This student has not been marked yet."; protected static final String MESSAGE_ALREADY_MARKED = "This student has already been marked."; protected static final String MESSAGE_NO_COMMENT_ADDED = "This student has no comment set"; + protected static final String MESSAGE_DATA_REMOVED = "All data have been removed."; + protected static final String MESSAGE_ABORT = "Abort."; // Common message formats protected static final String MESSAGE_FORMAT_GENERIC_USAGE = "%s"; diff --git a/src/main/java/taa/command/ResetCommand.java b/src/main/java/taa/command/ResetCommand.java new file mode 100644 index 0000000000..009248b105 --- /dev/null +++ b/src/main/java/taa/command/ResetCommand.java @@ -0,0 +1,56 @@ +package taa.command; + +import taa.Ui; +import taa.exception.TaaException; +import taa.module.ModuleList; +import taa.storage.Storage; + +public class ResetCommand extends Command { + private static final String MESSAGE_NO_DATA = "There is no data to reset."; + + private static final String MESSAGE_FORMAT_CONFIRMATION_PROMPT = "Are you sure that you want to remove all data?\n" + + "WARNING: This action cannot be reversed.\n" + + "Type [%s] to continue: "; + + private static final String CONFIRM_VALUE = "yes"; + + public ResetCommand(String argument) { + super(argument); + } + + @Override + public void checkArgument() throws TaaException { + if (!argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + if (moduleList.getSize() <= 0) { + throw new TaaException(MESSAGE_NO_DATA); + } + + ui.printBorder(); + ui.printMessage(String.format(MESSAGE_FORMAT_CONFIRMATION_PROMPT, CONFIRM_VALUE), false); + + String userInput = ui.getUserInput(PROMPT_WITHIN_COMMAND, true); + String message; + if (userInput.equals(CONFIRM_VALUE)) { + moduleList.deleteAllModules(); + storage.save(moduleList); + + message = MESSAGE_DATA_REMOVED; + } else { + message = MESSAGE_ABORT; + } + + ui.printMessage(String.format("\n%s", message), false); + ui.printBorder(); + } + + @Override + protected String getUsage() { + return null; + } +} From 55d82d5d3bac60626c7e15174a429fa398b7ab80 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:31:35 +0800 Subject: [PATCH 237/543] Add ResetCommand usage --- src/main/java/taa/command/ResetCommand.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/command/ResetCommand.java b/src/main/java/taa/command/ResetCommand.java index 009248b105..a37200fb35 100644 --- a/src/main/java/taa/command/ResetCommand.java +++ b/src/main/java/taa/command/ResetCommand.java @@ -51,6 +51,9 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc @Override protected String getUsage() { - return null; + return String.format( + MESSAGE_FORMAT_GENERIC_USAGE, + COMMAND_RESET + ); } } From 75732f123a2c23a7c6a7fab045b7882551aa278d Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:32:06 +0800 Subject: [PATCH 238/543] Add archive and reset into help command --- src/main/java/taa/command/HelpCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index 35bbb84238..200a3c28c2 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -62,7 +62,8 @@ public class HelpCommand extends Command { new DeleteAttendanceCommand(""), new ExitCommand(""), new HelpCommand(""), - new ArchiveCommand("") + new ArchiveCommand(""), + new ResetCommand("") }; public HelpCommand(String argument) { From 53e7f62db2da883e1721890bd3649c55ef181196 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:32:46 +0800 Subject: [PATCH 239/543] Update welcome message --- src/main/java/taa/Ui.java | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index d1eae0c891..6e9c6dd3dd 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -6,17 +6,18 @@ public class Ui { private static final String INPUT_PROMPT = "$ "; private static final String MESSAGE_BORDER = "------------------------------------------------------------"; - private static final String MESSAGE_WELCOME = "Welcome to\n" + "\n" - + ".___________. ___ ___\n" - + "| | / \\ / \\\n" - + "`---| |----` / ^ \\ / ^ \\\n" - + " | | / /_\\ \\ / /_\\ \\\n" - + " | | / _____ \\ / _____ \\\n" - + " |__| /__/ \\__\\ /__/ \\__\\\n" + "\n" - + "What can I do for you?"; private static final String MESSAGE_EXIT = "Bye. Hope to see you again soon!"; private static final String MESSAGE_FORMAT_EXCEPTION = "An exception has occurred:\n%s"; + private static final String MESSAGE_FORMAT_WELCOME = "Welcome to\n" + "\n" + + ".___________. ___ ___\n" + + "| | / \\ / \\\n" + + "`---| |----` / ^ \\ / ^ \\\n" + + " | | / /_\\ \\ / /_\\ \\\n" + + " | | / _____ \\ / _____ \\\n" + + " |__| /__/ \\__\\ /__/ \\__\\\n" + "\n" + + "What can I do for you?\n" + + "Enter \"%s\" to view the list of commands"; private final Scanner scanner; From 1d73d452d87e5e6e5cfa5fe3efc55eba2edfe3a0 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:33:02 +0800 Subject: [PATCH 240/543] Update welcome message --- src/main/java/taa/Ui.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index 6e9c6dd3dd..94c9048436 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -73,7 +73,7 @@ public void printMessage(String message, boolean withBorders) { * Prints the welcome message. */ public void printWelcomeMessage() { - printMessage(MESSAGE_WELCOME); + printMessage(String.format(MESSAGE_FORMAT_WELCOME, Command.COMMAND_HELP)); } /** From e0427d0947b16fcdda219ffec9eb33e72fe0b640 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:33:40 +0800 Subject: [PATCH 241/543] Add author tag --- src/main/java/taa/ClassChecker.java | 1 + src/main/java/taa/Parser.java | 2 +- src/main/java/taa/Taa.java | 1 + src/main/java/taa/Ui.java | 3 +++ src/main/java/taa/command/ArchiveCommand.java | 1 + src/main/java/taa/command/Command.java | 1 + src/main/java/taa/command/ExitCommand.java | 1 + src/main/java/taa/command/HelpCommand.java | 1 + src/main/java/taa/command/ResetCommand.java | 1 + src/main/java/taa/command/module/AddModuleCommand.java | 1 + src/main/java/taa/command/module/DeleteModuleCommand.java | 1 + src/main/java/taa/command/module/EditModuleCommand.java | 1 + src/main/java/taa/command/module/ListModulesCommand.java | 1 + src/main/java/taa/exception/TaaException.java | 1 + src/main/java/taa/logger/TaaLogger.java | 1 + src/main/java/taa/logger/TaaLoggerFormatter.java | 1 + src/main/java/taa/module/Module.java | 1 + src/main/java/taa/module/ModuleList.java | 1 + src/main/java/taa/storage/Storage.java | 1 + .../java/taa/storage/deserializer/AssessmentDeserializer.java | 1 + .../taa/storage/deserializer/AssessmentListDeserializer.java | 1 + .../java/taa/storage/deserializer/AttendanceDeserializer.java | 1 + .../taa/storage/deserializer/AttendanceListDeserializer.java | 1 + src/main/java/taa/storage/deserializer/ModuleDeserializer.java | 1 + .../java/taa/storage/deserializer/ModuleListDeserializer.java | 1 + .../java/taa/storage/deserializer/StorageDeserializer.java | 1 + .../java/taa/storage/deserializer/StudentDeserializer.java | 1 + .../java/taa/storage/deserializer/StudentListDeserializer.java | 1 + src/main/java/taa/util/Util.java | 1 + src/test/java/taa/ParserTest.java | 1 + 30 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/ClassChecker.java b/src/main/java/taa/ClassChecker.java index 349afb163c..b245420cd5 100644 --- a/src/main/java/taa/ClassChecker.java +++ b/src/main/java/taa/ClassChecker.java @@ -1,5 +1,6 @@ package taa; +//@@author leyondlee public interface ClassChecker { public abstract boolean verify(); } diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 80ce7af038..8db0c12562 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,6 +1,6 @@ package taa; - +//@@author leyondlee import taa.command.ArchiveCommand; import taa.command.ResetCommand; import taa.command.assessment.AddAssessmentCommand; diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index 3830903d5e..5319215c16 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -1,5 +1,6 @@ package taa; +//@@author leyondlee import taa.command.Command; import taa.exception.TaaException; import taa.logger.TaaLogger; diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index 94c9048436..0d4b9c2298 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -1,5 +1,8 @@ package taa; +//@@author leyondlee +import taa.command.Command; + import java.util.Scanner; public class Ui { diff --git a/src/main/java/taa/command/ArchiveCommand.java b/src/main/java/taa/command/ArchiveCommand.java index a69d117dbd..69dcb85023 100644 --- a/src/main/java/taa/command/ArchiveCommand.java +++ b/src/main/java/taa/command/ArchiveCommand.java @@ -1,5 +1,6 @@ package taa.command; +//@@author leyondlee import taa.Taa; import taa.Ui; import taa.exception.TaaException; diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 3ee882bc2b..fcf71325c8 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -1,5 +1,6 @@ package taa.command; +//@@author leyondlee import taa.storage.Storage; import taa.exception.TaaException; import taa.Parser; diff --git a/src/main/java/taa/command/ExitCommand.java b/src/main/java/taa/command/ExitCommand.java index 36d6778932..6da14c9070 100644 --- a/src/main/java/taa/command/ExitCommand.java +++ b/src/main/java/taa/command/ExitCommand.java @@ -1,5 +1,6 @@ package taa.command; +//@@author leyondlee import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index 200a3c28c2..fc793c1ed8 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -1,5 +1,6 @@ package taa.command; +//@@author leyondlee import taa.Ui; import taa.command.assessment.AddAssessmentCommand; import taa.command.assessment.DeleteAssessmentCommand; diff --git a/src/main/java/taa/command/ResetCommand.java b/src/main/java/taa/command/ResetCommand.java index a37200fb35..0ea4651773 100644 --- a/src/main/java/taa/command/ResetCommand.java +++ b/src/main/java/taa/command/ResetCommand.java @@ -1,5 +1,6 @@ package taa.command; +//@@author leyondlee import taa.Ui; import taa.exception.TaaException; import taa.module.ModuleList; diff --git a/src/main/java/taa/command/module/AddModuleCommand.java b/src/main/java/taa/command/module/AddModuleCommand.java index 6602668ab2..2092fc7a68 100644 --- a/src/main/java/taa/command/module/AddModuleCommand.java +++ b/src/main/java/taa/command/module/AddModuleCommand.java @@ -1,5 +1,6 @@ package taa.command.module; +//@@author leyondlee import taa.command.Command; import taa.logger.TaaLogger; import taa.storage.Storage; diff --git a/src/main/java/taa/command/module/DeleteModuleCommand.java b/src/main/java/taa/command/module/DeleteModuleCommand.java index 110976f3c2..06db050ad3 100644 --- a/src/main/java/taa/command/module/DeleteModuleCommand.java +++ b/src/main/java/taa/command/module/DeleteModuleCommand.java @@ -1,5 +1,6 @@ package taa.command.module; +//@@author leyondlee import taa.Ui; import taa.command.Command; import taa.exception.TaaException; diff --git a/src/main/java/taa/command/module/EditModuleCommand.java b/src/main/java/taa/command/module/EditModuleCommand.java index fe39197910..5a9eb81355 100644 --- a/src/main/java/taa/command/module/EditModuleCommand.java +++ b/src/main/java/taa/command/module/EditModuleCommand.java @@ -1,5 +1,6 @@ package taa.command.module; +//@@author leyondlee import taa.Ui; import taa.command.Command; import taa.exception.TaaException; diff --git a/src/main/java/taa/command/module/ListModulesCommand.java b/src/main/java/taa/command/module/ListModulesCommand.java index 97383af75b..1313686393 100644 --- a/src/main/java/taa/command/module/ListModulesCommand.java +++ b/src/main/java/taa/command/module/ListModulesCommand.java @@ -1,5 +1,6 @@ package taa.command.module; +//@@author leyondlee import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; diff --git a/src/main/java/taa/exception/TaaException.java b/src/main/java/taa/exception/TaaException.java index 4d7f49de09..e2b8cd3852 100644 --- a/src/main/java/taa/exception/TaaException.java +++ b/src/main/java/taa/exception/TaaException.java @@ -1,5 +1,6 @@ package taa.exception; +//@@author leyondlee public class TaaException extends Exception { public TaaException(String message) { super(message); diff --git a/src/main/java/taa/logger/TaaLogger.java b/src/main/java/taa/logger/TaaLogger.java index 8d4d0d1b76..52d11f5996 100644 --- a/src/main/java/taa/logger/TaaLogger.java +++ b/src/main/java/taa/logger/TaaLogger.java @@ -1,5 +1,6 @@ package taa.logger; +//@@author leyondlee import java.io.IOException; import java.util.logging.FileHandler; import java.util.logging.Level; diff --git a/src/main/java/taa/logger/TaaLoggerFormatter.java b/src/main/java/taa/logger/TaaLoggerFormatter.java index ddf39178b2..132413e29c 100644 --- a/src/main/java/taa/logger/TaaLoggerFormatter.java +++ b/src/main/java/taa/logger/TaaLoggerFormatter.java @@ -1,5 +1,6 @@ package taa.logger; +//@@author leyondlee import java.text.SimpleDateFormat; import java.util.Date; import java.util.logging.Formatter; diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/module/Module.java index f985156cf8..3a4594d0de 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/module/Module.java @@ -1,5 +1,6 @@ package taa.module; +//@@author leyondlee import taa.ClassChecker; import taa.assessment.Assessment; import taa.assessment.AssessmentList; diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java index d494b1c9d2..d5ea5f267c 100644 --- a/src/main/java/taa/module/ModuleList.java +++ b/src/main/java/taa/module/ModuleList.java @@ -1,5 +1,6 @@ package taa.module; +//@@author leyondlee import taa.ClassChecker; import java.util.ArrayList; diff --git a/src/main/java/taa/storage/Storage.java b/src/main/java/taa/storage/Storage.java index dd13638921..6cd83ab2e4 100644 --- a/src/main/java/taa/storage/Storage.java +++ b/src/main/java/taa/storage/Storage.java @@ -1,5 +1,6 @@ package taa.storage; +//@@author leyondlee import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonIOException; diff --git a/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java b/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java index 968c5607c8..58753d4e8d 100644 --- a/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java +++ b/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java @@ -1,5 +1,6 @@ package taa.storage.deserializer; +//@@author leyondlee import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; diff --git a/src/main/java/taa/storage/deserializer/AssessmentListDeserializer.java b/src/main/java/taa/storage/deserializer/AssessmentListDeserializer.java index 883f0c1f33..738a8a3208 100644 --- a/src/main/java/taa/storage/deserializer/AssessmentListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/AssessmentListDeserializer.java @@ -1,5 +1,6 @@ package taa.storage.deserializer; +//@@author leyondlee import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; diff --git a/src/main/java/taa/storage/deserializer/AttendanceDeserializer.java b/src/main/java/taa/storage/deserializer/AttendanceDeserializer.java index f7059e74f1..d4250a2850 100644 --- a/src/main/java/taa/storage/deserializer/AttendanceDeserializer.java +++ b/src/main/java/taa/storage/deserializer/AttendanceDeserializer.java @@ -1,5 +1,6 @@ package taa.storage.deserializer; +//@@author leyondlee import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; diff --git a/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java b/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java index 9b98e24278..6391519ec0 100644 --- a/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/AttendanceListDeserializer.java @@ -1,5 +1,6 @@ package taa.storage.deserializer; +//@@author leyondlee import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; diff --git a/src/main/java/taa/storage/deserializer/ModuleDeserializer.java b/src/main/java/taa/storage/deserializer/ModuleDeserializer.java index 053b8600cd..4bd1d75f68 100644 --- a/src/main/java/taa/storage/deserializer/ModuleDeserializer.java +++ b/src/main/java/taa/storage/deserializer/ModuleDeserializer.java @@ -1,5 +1,6 @@ package taa.storage.deserializer; +//@@author leyondlee import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializationContext; diff --git a/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java b/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java index 60e5323668..04bb5107e2 100644 --- a/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java @@ -1,5 +1,6 @@ package taa.storage.deserializer; +//@@author leyondlee import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; diff --git a/src/main/java/taa/storage/deserializer/StorageDeserializer.java b/src/main/java/taa/storage/deserializer/StorageDeserializer.java index e891dd1ca5..1300e10eeb 100644 --- a/src/main/java/taa/storage/deserializer/StorageDeserializer.java +++ b/src/main/java/taa/storage/deserializer/StorageDeserializer.java @@ -1,5 +1,6 @@ package taa.storage.deserializer; +//@@author leyondlee import com.google.gson.JsonObject; public abstract class StorageDeserializer { diff --git a/src/main/java/taa/storage/deserializer/StudentDeserializer.java b/src/main/java/taa/storage/deserializer/StudentDeserializer.java index b54702dd9a..0e80c36df4 100644 --- a/src/main/java/taa/storage/deserializer/StudentDeserializer.java +++ b/src/main/java/taa/storage/deserializer/StudentDeserializer.java @@ -1,5 +1,6 @@ package taa.storage.deserializer; +//@@author leyondlee import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonDeserializationContext; diff --git a/src/main/java/taa/storage/deserializer/StudentListDeserializer.java b/src/main/java/taa/storage/deserializer/StudentListDeserializer.java index 32975c32eb..0f40897261 100644 --- a/src/main/java/taa/storage/deserializer/StudentListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/StudentListDeserializer.java @@ -1,5 +1,6 @@ package taa.storage.deserializer; +//@@author leyondlee import com.google.gson.Gson; import com.google.gson.GsonBuilder; import com.google.gson.JsonArray; diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java index 152a9c7be9..4eeb4d6b18 100644 --- a/src/main/java/taa/util/Util.java +++ b/src/main/java/taa/util/Util.java @@ -1,5 +1,6 @@ package taa.util; +//@@author leyondlee import java.io.File; import java.io.IOException; import java.nio.file.Path; diff --git a/src/test/java/taa/ParserTest.java b/src/test/java/taa/ParserTest.java index 84bf4a1bd0..aac305c045 100644 --- a/src/test/java/taa/ParserTest.java +++ b/src/test/java/taa/ParserTest.java @@ -1,5 +1,6 @@ package taa; +//@@author leyondlee import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertTrue; From 97fc21d2d6460152b15d937db40ef19d8ecaa6a6 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:38:12 +0800 Subject: [PATCH 242/543] Update automatic ui testing file --- text-ui-test/EXPECTED.TXT | 1 + 1 file changed, 1 insertion(+) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 99bcfd21e7..a120d9b79d 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -9,6 +9,7 @@ Welcome to |__| /__/ \__\ /__/ \__\ What can I do for you? +Enter "help" to view the list of commands ------------------------------------------------------------ $ ------------------------------------------------------------ There are no modules in the list. From a9345929532741c4f534e0b7cda74ad5ae32d953 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 19:50:26 +0800 Subject: [PATCH 243/543] Remove redundant "public abstract" for ClassChecker.verify method --- src/main/java/taa/ClassChecker.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/ClassChecker.java b/src/main/java/taa/ClassChecker.java index b245420cd5..73c7fde1f6 100644 --- a/src/main/java/taa/ClassChecker.java +++ b/src/main/java/taa/ClassChecker.java @@ -2,5 +2,5 @@ //@@author leyondlee public interface ClassChecker { - public abstract boolean verify(); + boolean verify(); } From eee06b82fc0942f8b3af44ebe62bedba6cfd9586 Mon Sep 17 00:00:00 2001 From: Leyond Date: Thu, 28 Oct 2021 20:10:21 +0800 Subject: [PATCH 244/543] Update storage deserializer --- .../deserializer/ModuleListDeserializer.java | 2 +- .../storage/deserializer/StudentDeserializer.java | 15 +++++++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java b/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java index 04bb5107e2..e51893d14b 100644 --- a/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java @@ -27,7 +27,7 @@ public ModuleList deserialize(JsonElement json, Type typeOfT, JsonDeserializatio } JsonElement modulesJson = jsonObject.get(MEMBER_MODULES); - if (modulesJson == null || !modulesJson.isJsonArray()) { + if (!modulesJson.isJsonArray()) { return null; } diff --git a/src/main/java/taa/storage/deserializer/StudentDeserializer.java b/src/main/java/taa/storage/deserializer/StudentDeserializer.java index 0e80c36df4..e5f2a7b265 100644 --- a/src/main/java/taa/storage/deserializer/StudentDeserializer.java +++ b/src/main/java/taa/storage/deserializer/StudentDeserializer.java @@ -64,8 +64,7 @@ public Student deserialize(JsonElement json, Type typeOfT, JsonDeserializationCo JsonElement resultsJson = jsonObject.get(MEMBER_RESULTS); if (resultsJson != null) { - Type resultsType = new TypeToken>(){}.getType(); - HashMap results = gson.fromJson(resultsJson, resultsType); + HashMap results = convertResultsJson(gson, resultsJson); if (results != null) { for (String key : results.keySet()) { double value = results.get(key); @@ -80,4 +79,16 @@ public Student deserialize(JsonElement json, Type typeOfT, JsonDeserializationCo return student; } + + private HashMap convertResultsJson(Gson gson, JsonElement resultsJson) { + HashMap results; + try { + Type resultsType = new TypeToken>(){}.getType(); + results = gson.fromJson(resultsJson, resultsType); + } catch (JsonParseException e) { + results = null; + } + + return results; + } } From 8bbbbf58973df20d490b1f9faedf10bba99ba4d7 Mon Sep 17 00:00:00 2001 From: rachel Date: Thu, 28 Oct 2021 21:48:17 +0800 Subject: [PATCH 245/543] Try out plantuml sequence diagram --- .../AddAssessmentSequenceDiagram.puml | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 docs/diagrams/AddAssessmentSequenceDiagram.puml diff --git a/docs/diagrams/AddAssessmentSequenceDiagram.puml b/docs/diagrams/AddAssessmentSequenceDiagram.puml new file mode 100644 index 0000000000..17a34edd67 --- /dev/null +++ b/docs/diagrams/AddAssessmentSequenceDiagram.puml @@ -0,0 +1,23 @@ +@startuml +!include style.puml + +Actor User as user +Participant ":Ui" as ui +Participant ":Taa" as taa +Participant "<>\nParser" as parser +Participant ":Command" as command +Participant "<>\nUtil" as util +Participant ":ModuleList" as moduleList +Participant ":AssessmentList" as assessmentList +Participant ":Storage" as storage + +activate taa + +taa -> taa : loadModuleListFromStorage() +activate taa + +taa -> storage : load() +activate storage + +activate moduleList +@enduml \ No newline at end of file From 4c5524c84fc5cb8272138db7f5b3e339f74ab48b Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Thu, 28 Oct 2021 21:53:45 +0800 Subject: [PATCH 246/543] add lesson attendance --- .../SetAttendanceSequenceDiagram.puml | 11 +++ src/main/java/taa/Parser.java | 5 ++ src/main/java/taa/attendance/Attendance.java | 4 + .../java/taa/attendance/AttendanceList.java | 3 +- .../taa/attendance/LessonAttendanceList.java | 81 +++++++++++++++++ src/main/java/taa/command/Command.java | 1 + .../ListLessonAttendanceCommand.java | 89 +++++++++++++++++++ 7 files changed, 192 insertions(+), 2 deletions(-) create mode 100644 docs/diagrams/SetAttendanceSequenceDiagram.puml create mode 100644 src/main/java/taa/attendance/LessonAttendanceList.java create mode 100644 src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java diff --git a/docs/diagrams/SetAttendanceSequenceDiagram.puml b/docs/diagrams/SetAttendanceSequenceDiagram.puml new file mode 100644 index 0000000000..ac2c2d3913 --- /dev/null +++ b/docs/diagrams/SetAttendanceSequenceDiagram.puml @@ -0,0 +1,11 @@ +@startuml +'https://plantuml.com/sequence-diagram + +autonumber + +Alice -> Bob: Authentication Request +Bob --> Alice: Authentication Response + +Alice -> Bob: Another authentication Request +Alice <-- Bob: another authentication Response +@enduml \ No newline at end of file diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 7b2180a337..375c90af3d 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -2,6 +2,7 @@ import taa.command.assessment.AddAssessmentCommand; +import taa.command.attendance.ListLessonAttendanceCommand; import taa.command.module.AddModuleCommand; import taa.command.student.AddStudentCommand; import taa.command.mark.AverageMarksCommand; @@ -114,6 +115,10 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new ListAttendanceCommand(argument); break; + case Command.COMMAND_LIST_LESSON_ATTENDANCE: + command = new ListLessonAttendanceCommand(argument); + break; + case Command.COMMAND_DELETE_ATTENDANCE: command = new DeleteAttendanceCommand(argument); break; diff --git a/src/main/java/taa/attendance/Attendance.java b/src/main/java/taa/attendance/Attendance.java index 8971c935a2..e0a61f86cc 100644 --- a/src/main/java/taa/attendance/Attendance.java +++ b/src/main/java/taa/attendance/Attendance.java @@ -33,6 +33,10 @@ public int getLessonNumber() { return lessonNumber; } + public boolean getIsPresent(){ + return isPresent; + } + @Override public String toString() { String presentString = (isPresent) ? "Present" : "Absent"; diff --git a/src/main/java/taa/attendance/AttendanceList.java b/src/main/java/taa/attendance/AttendanceList.java index 869ead6b9e..eb64e43156 100644 --- a/src/main/java/taa/attendance/AttendanceList.java +++ b/src/main/java/taa/attendance/AttendanceList.java @@ -8,6 +8,7 @@ public class AttendanceList implements ClassChecker { private final ArrayList attendances; + public static int ATTENDANCE_NOT_FOUND = -1; public AttendanceList() { this.attendances = new ArrayList<>(); @@ -17,8 +18,6 @@ public int getSize() { return attendances.size(); } - public static int ATTENDANCE_NOT_FOUND = -1; - /** * Gets the list of attendances. Note: This returns a new ArrayList instance. * diff --git a/src/main/java/taa/attendance/LessonAttendanceList.java b/src/main/java/taa/attendance/LessonAttendanceList.java new file mode 100644 index 0000000000..f9f636d2ed --- /dev/null +++ b/src/main/java/taa/attendance/LessonAttendanceList.java @@ -0,0 +1,81 @@ +package taa.attendance; + +import taa.student.Student; +import taa.student.StudentList; + +import java.util.ArrayList; + +public class LessonAttendanceList { + private final ArrayList lessonAttendances; + + private static final String MESSAGE_FORMAT_LESSON_ATTENDANCE = "%s [%s]"; + private static final String MESSAGE_HEAD_COUNT = "Total Attendance for this lesson: %d/%d"; + private static int presentCount = 0; + + public LessonAttendanceList() { + this.lessonAttendances = new ArrayList<>(); + } + + public int getSize() { + return lessonAttendances.size(); + } + + /** + * Returns a String containing student name and student attendance for a lesson. + * + * @param student The student in the LessonAttendanceList. + * @param attendance The attendance object. + * @return student name and student attendance. + */ + public String getLessonAttendance(Student student, Attendance attendance) { + String presentString = (attendance.getIsPresent()) ? "Present" : "Absent"; + if (attendance.getIsPresent()) { + presentCount++; + } + return String.format(MESSAGE_FORMAT_LESSON_ATTENDANCE, student, presentString); + } + + /** + * Adds the LessonAttendance into the LessonAttendanceList. + * + * @param studentList The list of students in the module. + * @param lessonNumber The lesson number. + */ + public void setLessonAttendances(StudentList studentList, int lessonNumber) { + for (int i = 0; i < studentList.getSize(); i++) { + Student student = studentList.getStudentAt(i); + Attendance attendance = student.getAttendanceList().getAttendance(lessonNumber); + if (attendance != null) { + lessonAttendances.add(getLessonAttendance(student, attendance)); + } + } + } + + /** + * Gets the fraction of students present for the lesson. + * + * @return Fraction of students present for the lesson. + */ + private String getHeadCount() { + return String.format(MESSAGE_HEAD_COUNT, presentCount, getSize()); + } + + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < getSize(); i += 1) { + if (i > 0) { + stringBuilder.append("\n"); + } + + stringBuilder.append(i + 1); + stringBuilder.append(". "); + stringBuilder.append(lessonAttendances.get(i)); + } + stringBuilder.append("\n"); + stringBuilder.append(getHeadCount()); + + return stringBuilder.toString(); + } +} diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 8cb964bd6d..4a88f3d6b2 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -14,6 +14,7 @@ public abstract class Command { public static final String COMMAND_LIST_STUDENTS = "list_students"; public static final String COMMAND_LIST_ASSESSMENTS = "list_assessments"; public static final String COMMAND_LIST_ATTENDANCE = "list_attendance"; + public static final String COMMAND_LIST_LESSON_ATTENDANCE = "list_lesson_attendance"; public static final String COMMAND_ADD_MODULE = "add_module"; public static final String COMMAND_EDIT_MODULE = "edit_module"; public static final String COMMAND_DELETE_MODULE = "delete_module"; diff --git a/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java b/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java new file mode 100644 index 0000000000..2144b430f1 --- /dev/null +++ b/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java @@ -0,0 +1,89 @@ +package taa.command.attendance; + +import taa.Ui; +import taa.attendance.Attendance; +import taa.attendance.LessonAttendanceList; +import taa.command.Command; +import taa.exception.TaaException; +import taa.module.Module; +import taa.module.ModuleList; +import taa.storage.Storage; +import taa.student.StudentList; +import taa.util.Util; + +public class ListLessonAttendanceCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_LESSON_NUMBER = "l"; + private static final String[] LIST_LESSON_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_LESSON_NUMBER}; + + private static final String MESSAGE_FORMAT_LIST_LESSON_ATTENDANCE_USAGE = "%s %s/ %s/"; + protected static final String MESSAGE_FORMAT_NO_ATTENDANCE = "There is no recorded attendance for Lesson %s."; + private static final String MESSAGE_FORMAT_OUTPUT = "Class attendance for Lesson %s:\n%s"; + + public ListLessonAttendanceCommand(String argument) { + super(argument, LIST_LESSON_ATTENDANCE_ARGUMENT_KEYS); + } + + @Override + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + + String lessonNumberInput = argumentMap.get(KEY_LESSON_NUMBER); + if (!Util.isStringInteger(lessonNumberInput)) { + throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); + } + } + + /** + * Executes the list_lesson_attendance command and list all the attendance records of a lesson. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModuleWithCode(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + + String lessonNumberInput = argumentMap.get(KEY_LESSON_NUMBER); + assert Util.isStringInteger(lessonNumberInput); + int lessonNumber = Integer.parseInt(lessonNumberInput); + if (lessonNumber < Attendance.getMinLessonNumber()) { + throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); + } + + StudentList studentList = module.getStudentList(); + LessonAttendanceList lessonAttendances = new LessonAttendanceList(); + lessonAttendances.setLessonAttendances(studentList, lessonNumber); + + String message; + if (lessonAttendances.getSize() == 0) { + message = String.format(MESSAGE_FORMAT_NO_ATTENDANCE, lessonNumberInput); + } else { + message = String.format(MESSAGE_FORMAT_OUTPUT, lessonNumberInput, lessonAttendances); + } + + ui.printMessage(message); + } + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_LIST_LESSON_ATTENDANCE_USAGE, + COMMAND_LIST_LESSON_ATTENDANCE, + KEY_MODULE_CODE, + KEY_LESSON_NUMBER + ); + } +} From db1acb271b2907d9c7cd3bd4022d99b395d2d272 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Thu, 28 Oct 2021 21:56:48 +0800 Subject: [PATCH 247/543] fix checkstyle issues --- src/main/java/taa/attendance/Attendance.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/attendance/Attendance.java b/src/main/java/taa/attendance/Attendance.java index e0a61f86cc..0dd91d1817 100644 --- a/src/main/java/taa/attendance/Attendance.java +++ b/src/main/java/taa/attendance/Attendance.java @@ -33,7 +33,7 @@ public int getLessonNumber() { return lessonNumber; } - public boolean getIsPresent(){ + public boolean getIsPresent() { return isPresent; } From ff999e55f351dd8d143466412287a051a20728b1 Mon Sep 17 00:00:00 2001 From: rachel Date: Thu, 28 Oct 2021 22:18:47 +0800 Subject: [PATCH 248/543] Update edit assessment command because of a bug that causes new weightage to exceed 100 --- .../assessment/EditAssessmentCommand.java | 48 +++++++++++++------ 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/src/main/java/taa/command/assessment/EditAssessmentCommand.java b/src/main/java/taa/command/assessment/EditAssessmentCommand.java index 441161e892..0d302b2a20 100644 --- a/src/main/java/taa/command/assessment/EditAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/EditAssessmentCommand.java @@ -2,6 +2,7 @@ import taa.Ui; import taa.assessment.Assessment; +import taa.assessment.AssessmentList; import taa.command.Command; import taa.exception.TaaException; import taa.module.Module; @@ -9,6 +10,9 @@ import taa.storage.Storage; import taa.util.Util; +import java.lang.reflect.Array; +import java.util.ArrayList; + public class EditAssessmentCommand extends Command { private static final String KEY_MODULE_CODE = "c"; private static final String KEY_ASSESSMENT_NAME = "n"; @@ -100,6 +104,36 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc assert (argumentMap.containsKey(KEY_NEW_ASSESSMENT_NAME) || argumentMap.containsKey(KEY_NEW_MAXIMUM_MARKS) || argumentMap.containsKey(KEY_NEW_WEIGHTAGE)) : "a new value to edit should at least exist."; + String newWeightageString = argumentMap.getOrDefault(KEY_NEW_WEIGHTAGE, null); + if (newWeightageString != null) { + assert Util.isStringDouble(newWeightageString); + double newWeightage = Double.parseDouble(newWeightageString); + if (!Assessment.isWeightageWithinRange(newWeightage)) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) + ); + } + double totalNewWeightage = 0; + ArrayList assessments = module.getAssessmentList().getAssessments(); + for (Assessment a : assessments) { + if (a.getName() != name) { + totalNewWeightage += a.getWeightage(); + } + } + double newTotalNewWeightage = totalNewWeightage + newWeightage; + if (Assessment.isWeightageWithinRange(newTotalNewWeightage)) { + assessment.setWeightage(newWeightage); + } else { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) + ); + } + } + String newName = argumentMap.getOrDefault(KEY_NEW_ASSESSMENT_NAME, null); if (newName != null) { assessment.setName(newName); @@ -118,20 +152,6 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc assessment.setMaximumMarks(newMaximumMarks); } - String newWeightageString = argumentMap.getOrDefault(KEY_NEW_WEIGHTAGE, null); - if (newWeightageString != null) { - assert Util.isStringDouble(newWeightageString); - double newWeightage = Double.parseDouble(newWeightageString); - if (!Assessment.isWeightageWithinRange(newWeightage)) { - throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, - Assessment.WEIGHTAGE_RANGE[0], - Assessment.WEIGHTAGE_RANGE[1]) - ); - } - assessment.setWeightage(newWeightage); - } - assert storage != null : "storage should exist."; storage.save(moduleList); From 8383cc32c2289ded30fe433c3d98de0c0bda64e6 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Thu, 28 Oct 2021 22:30:27 +0800 Subject: [PATCH 249/543] add bug fix to present count --- src/main/java/taa/attendance/LessonAttendanceList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/attendance/LessonAttendanceList.java b/src/main/java/taa/attendance/LessonAttendanceList.java index f9f636d2ed..76e8eecadd 100644 --- a/src/main/java/taa/attendance/LessonAttendanceList.java +++ b/src/main/java/taa/attendance/LessonAttendanceList.java @@ -10,7 +10,7 @@ public class LessonAttendanceList { private static final String MESSAGE_FORMAT_LESSON_ATTENDANCE = "%s [%s]"; private static final String MESSAGE_HEAD_COUNT = "Total Attendance for this lesson: %d/%d"; - private static int presentCount = 0; + private int presentCount = 0; public LessonAttendanceList() { this.lessonAttendances = new ArrayList<>(); From 2ea8712965c27ec46688fcd348d91e526331771d Mon Sep 17 00:00:00 2001 From: rachel Date: Thu, 28 Oct 2021 22:54:21 +0800 Subject: [PATCH 250/543] Update delete assessment command to delete the assessment and marks in student --- .../command/assessment/DeleteAssessmentCommand.java | 12 ++++++++++++ src/main/java/taa/student/Student.java | 10 ++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java b/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java index bf5d520036..7d1ed75074 100644 --- a/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java @@ -8,6 +8,10 @@ import taa.module.Module; import taa.module.ModuleList; import taa.storage.Storage; +import taa.student.Student; +import taa.student.StudentList; + +import java.util.ArrayList; public class DeleteAssessmentCommand extends Command { private static final String KEY_MODULE_CODE = "c"; @@ -56,6 +60,14 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } + ArrayList students = module.getStudentList().getStudents(); + for (Student s : students) { + if (s.marksExist(name)) { + double marks = s.getMarks(name); + s.deleteAssessmentAndMarks(name, marks); + } + } + assert storage != null : "storage should exist."; storage.save(moduleList); diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index 4106ab279d..f6385a0148 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -99,6 +99,16 @@ public void deleteMark(String assessmentName) { results.remove(assessmentName); } + /** + * Deletes the assessment and marks for the assessment in the results HashMap. + * + * @param assessmentName Key of the hashmap. + * @param marks Value to be stored under the key given. + */ + public void deleteAssessmentAndMarks(String assessmentName, double marks) { + results.remove(assessmentName, marks); + } + /** * Gets the marks for the given assessment. * From d9a595bf6ddf96ae2e77acd13a4e3a5283cdd17f Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 29 Oct 2021 00:12:11 +0800 Subject: [PATCH 251/543] Change theme --- docs/_config.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_config.yml b/docs/_config.yml index c50ff38dab..277f1f2c51 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1 +1 @@ -theme: jekyll-theme-merlot \ No newline at end of file +theme: jekyll-theme-cayman From 8a508bc2882dde20e98241a7f34a7a40dc387ad7 Mon Sep 17 00:00:00 2001 From: rachel Date: Fri, 29 Oct 2021 03:01:24 +0800 Subject: [PATCH 252/543] create add assessment sequence diagram and update the DG with it --- docs/DeveloperGuide.md | 3 + .../diagrams/AddAssessmentSequenceDiagram.png | Bin 0 -> 53433 bytes .../AddAssessmentSequenceDiagram.puml | 68 ++++++++++++++++-- 3 files changed, 65 insertions(+), 6 deletions(-) create mode 100644 docs/diagrams/AddAssessmentSequenceDiagram.png diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 967c326fdf..eb84f3f08e 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -112,6 +112,9 @@ which stores assessment internally as an ArrayList `assessments`.
* `AssessmentList#deleteAssessment(assessmentName:String)` - Deletes an assessment with the name specified by the user from the `assessments` ArrayList. +The sequence diagram shown below illustrates how the `add_assessment` command works: +![AddAssessmentSequenceDiagram](diagrams/AddAssessmentSequenceDiagram.png) + Below is an example scenario of how the add assessment feature behaves at each step: * Step 1 - The user executes `add_assessment c/cs2113t n/midterms m/20 w/10` to add an assessment. The `add_assessment` command calls the `AddAssessmentCommand#execute` method. Within `AddAssessmentCommand#execute`, diff --git a/docs/diagrams/AddAssessmentSequenceDiagram.png b/docs/diagrams/AddAssessmentSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..0d272e03197e89a2f1942572d502308aee46e24d GIT binary patch literal 53433 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

lT^$md3-8h3^oA0B%%ppQ@HasuL7A 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 literal 0 HcmV?d00001 diff --git a/docs/diagrams/AddAssessmentSequenceDiagram.puml b/docs/diagrams/AddAssessmentSequenceDiagram.puml index 17a34edd67..7056aaaae3 100644 --- a/docs/diagrams/AddAssessmentSequenceDiagram.puml +++ b/docs/diagrams/AddAssessmentSequenceDiagram.puml @@ -5,19 +5,75 @@ Actor User as user Participant ":Ui" as ui Participant ":Taa" as taa Participant "<>\nParser" as parser -Participant ":Command" as command -Participant "<>\nUtil" as util +Participant ":AddAssessmentCommand" as addAssessmentCommand Participant ":ModuleList" as moduleList +Participant ":Module" as module Participant ":AssessmentList" as assessmentList +Participant ":Assessment" as assessment Participant ":Storage" as storage activate taa -taa -> taa : loadModuleListFromStorage() -activate taa +taa -> ui : getUserInput() +activate ui + +user -> ui : "add_assessment c/CS2113T\nn/Finals m/100 w/30" +ui --> taa : userInput:String +deactivate ui + +taa -> parser : parseUserInput(userInput) +activate parser + +create addAssessmentCommand +parser -> addAssessmentCommand +activate addAssessmentCommand +addAssessmentCommand -> parser +deactivate addAssessmentCommand + +parser --> taa : command:AddAssessmentCommand +deactivate parser + +taa -> addAssessmentCommand : checkArguments() +activate addAssessmentCommand + +addAssessmentCommand --> taa +deactivate addAssessmentCommand -taa -> storage : load() +taa -> addAssessmentCommand : execute(moduleList:ModuleList, ui:Ui, storage:Storage) +activate addAssessmentCommand + +addAssessmentCommand -> module +activate module +module --> addAssessmentCommand +deactivate module + +create assessment +addAssessmentCommand -> assessment +activate assessment +assessment --> addAssessmentCommand +deactivate assessment + +addAssessmentCommand -> assessmentList : getAssessmentList() +activate assessmentList +assessmentList --> addAssessmentCommand +deactivate assessmentList + +addAssessmentCommand -> assessmentList : addAssessment(assessment:Assessment) +activate assessmentList +assessmentList --> addAssessmentCommand +deactivate assessmentList + +addAssessmentCommand -> storage : save(moduleList:ModuleList) activate storage +storage --> addAssessmentCommand +deactivate storage + +addAssessmentCommand -> ui : printMessage("Assessment added to CS2113T: ...") +activate ui +ui -> user : Display message:\n"Assessment added to CS2113T: ..." +ui --> addAssessmentCommand +deactivate ui + +deactivate addAssessmentCommand -activate moduleList @enduml \ No newline at end of file From 62649e165e1b4e773c92928e36254eba85b3ae85 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 29 Oct 2021 20:18:31 +0800 Subject: [PATCH 253/543] Update UG to include archive and reset commands --- docs/UserGuide.md | 39 +++++++++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index eed9c7dde3..1be2af636b 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -27,6 +27,8 @@ If you can type fast, TAA can help keep track of your modules and students faste * [Deleting attendance for a particular lesson for a student: `delete_attendance`](#deleting-attendance-for-a-particular-lesson-for-a-student-delete_attendance) * [Viewing help: `help`](#viewing-help-help) * [Exiting the program: `exit`](#exiting-the-program-exit) + * [Archiving data: `archive`](#archiving-data-archive) + * [Resetting/Removing all data: `reset`](#resettingremoving-all-data-reset) * [FAQ](#faq) * [Command Summary](#command-summary) @@ -70,7 +72,9 @@ Format: `edit_module c/ [nc/] [n/ * `NEW_MODULE_CODE` [Optional] refers to the updated code of the module. * `NEW_MODULE_NAME` [Optional] refers to the updated name of the module. > 💡 **Note:**
-> Either `NEW_MODULE_CODE`, `NEW_MODULE_NAME`, or both must be provided. +> At least one optional field must be provided: +> * `NEW_MODULE_CODE` +> * `NEW_MODULE_NAME` Examples: * `edit_module c/CS2113T nc/cs2113t` @@ -187,15 +191,17 @@ Examples: ### Editing an assessment in a module: `edit_assessment` Edits an assessment of a module. -Format: `edit_assessment c/ n/ [nn/] [m/]` -* At least one of the optional fields must be provided. +Format: `edit_assessment c/ n/ [nn/] [m/] [w/]` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). * `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). -* `NEW_ASSESSMENT_NAME` refers to the new name of the assessment (e.g. Finals, Assignment 2, etc.). -* `NEW_MAXIMUM_MARKS` refers to the new maximum marks of the assessment (e.g. 50). -* `NEW_WEIGHTAGE` refers to the new weightage of the assessment (e.g. 20%). +* `NEW_ASSESSMENT_NAME` [Optional] refers to the new name of the assessment (e.g. Finals, Assignment 2, etc.). +* `NEW_MAXIMUM_MARKS` [Optional] refers to the new maximum marks of the assessment (e.g. 50). +* `NEW_WEIGHTAGE` [Optional] refers to the new weightage of the assessment (e.g. 20%). > 💡 **Note:**
-> TODO +> At least one optional field must be provided: +> * `NEW_ASSESSMENT_NAME` +> * `NEW_MAXIMUM_MARKS` +> * `NEW_WEIGHTAGE` Examples: * `edit_assessment c/CS2101 n/OP1 m/20 w/10` @@ -339,10 +345,27 @@ Format: `help`
### Exiting the program: `exit` -Exits the program +Exits the program. Format: `exit` +
+ +### Archiving data: `archive` +Saves the current program data to an archive. + +By default, archive file is stored in the `/data/archive` folder. + +Format: `archive [f/]` +* `FILENAME` [Optional] refers to the name of the file to save the archive as. + +
+ +### Resetting/Removing all data: `reset` +Removes all saved data from the current program. + +Format: `reset` + ## FAQ **Q**: How do I transfer my data to another computer? From 9559ff5f822a2979ad94b1f9d811d1df2d7cb253 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 29 Oct 2021 20:19:00 +0800 Subject: [PATCH 254/543] Fix activation bar --- docs/diagrams/ArchitectureSequenceDiagram.png | Bin 54066 -> 54075 bytes .../diagrams/ArchitectureSequenceDiagram.puml | 1 + 2 files changed, 1 insertion(+) diff --git a/docs/diagrams/ArchitectureSequenceDiagram.png b/docs/diagrams/ArchitectureSequenceDiagram.png index 48a8d1b5dd8a931119cee40e9e2b680d7e906aab..90e3db92d6919b5a32e90ba6f3a1b9036e07bb71 100644 GIT binary patch delta 1200 zcmV;h1W)_2rUSdC1CUvNj%id_bZ~58Zgh2RYybfO004NL?N-fh+c*%u3-CKk+e-p8 zfn_u~7=@A4X^N)tHmH;Ku-OAcF%A)lR7uKpcCqi?Aw`jrDi>WW(35?z$octZIGh>I zi8e%;s>nylGcIUeWel`=%GqJ*h@<3`8mZt$GX+FLh2K$fg*u#n@{$Mx&!;#1xnuD@ z3VHLL8#$tVpx5kQGy>hnAsgnA(teJ2F{f%Jj&kwR!xuXwL5|> zvs5ulX}jAfB1W5k9JJfSxQ2shbChIkP`m{m&KCKt7AO)>J@eAi}1J!ab$VIqtF3)R!s-mM8z4AwE?4a5MqmQR* zRTWHhgWEC|+?x6Fi2-w4`|n(#1IBBS?%Db&(6aS|hit=WW!TYRANq>1=HHLsG|N3WV$UC zTUaw!QK)x+#&wyKC-5qv>;~h=|4&BLJz_Xndze9bdM9Phi1?|IKOcCOG4WT|Yi*Q# ziiE9_qlER2={wsA(%qw(oWxgEKVp|6iWIPXAesDz;e~sWYj-D+S--OXj1s`#xfJFP zQZP7GoFK-(UD+l3S}{RcBknKpH0LV;6zkje0LyrPBR3Xm$^T}M9tGMJ$ujH4xFa=} zIePHo-2HyZkM^7CU1^{v;~%6KT+Hn&{e@@d0glF7kQ#(^{L|P)))~7eRc@}?#<&RB z1{b0b#Y#dSF-S{0+rTGA4H2u{T>@S)gL^5>o!t0c!HPSkwBJ##Xf3*%g?6*hZWh|j zLc3XiXg3S(W}#o3g|2dZM{X9Eu*MgaO9AQOWIRa^({yi141A;p#uJ#N)5-BPO=0=& z8Z3W5*?V_&30hVPC!Gv0UGY22MJe`^3$iBgsS<`4YziMsCN9oCGz54n)?7(92P7At z7g6B&)xjHXaC}ne3VdE9esn+$D(%oQg?X7CPL3wYB@PFb%>iH{nM(v#Pg8U)`3`vU zr5o42)#S730}p@!C$ss3C{7}e;2hB(@lOCU#@qSlaeA35>M?zWBb1Q?tH$p??@Y> zOjYEAQ|zN;3sSLxtZ#a)COW@{$OD1CPg7{IL`9b-^Ve zPGSgI6Fq-UbE5TRaxHKjIUTNa!*!OaED9nrhoJR%GuxHndF>4j)|qB9t8#YEwQ-Ol zOxJ;P+%j1(htl=fhJsMTm&CAoLxTiAus5+Y7(*^e77d&#S$LM6-Hn=_+iQ1#EwfZH zyV7>IQACdRa?oynFUB$KMVo^pW4-VedDvT&w_?~~Xu0e5R;zX(e(SlEB|PH#<%*jS zh>D|?1v56yUW>9aomkk+8YDLL0@mdtx5$_iD2Ogs4HF)w;$qQpr6%;Y>#Rc+H;5jr zGqgQwGBq4daKf`8Z&(UiVZ{%eyA4&#y?~2!VP9U>R7FRBFM8#-*4RO{J4Wx1)uJkx z=mxiCEVwoCXBiWpyIyOfPbz|5;O=XTAJUMm0 zKk}pfMtWBo>e28Q^o)zCeU(4*%-q4ja064rkPd$vyC^zgx1`F=C0iL60ehi^C`4FE z=sgB$ZhIMc&!{0{k-I~{BV}+arMZzSKPy;q!<6VluH5W{%AN#_tSJ|P7J)G28JUTrQ^}zI89;x>JqGcH`#f0 zaSmEm3Okz&4_WaW%snY~lQXg;@V*j;7ifR)QLM&fJkakoYMVJ;cnHDmcF7laB)g{pP0KkY@)mXlYAnm9) ziV)UNlQ5;~3X%Z;C1Cj~g0!RJC_-36O~RC_D@Xv~YeGdQt0000g zhyefq000<37ytkO0Du960RR9102n|R00000fC1$H0f@$zsSaG-*#H0l07*qoM6N<$ Ef{;HQrvLx| diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml index 44abb5fcd7..e7cf61678f 100644 --- a/docs/diagrams/ArchitectureSequenceDiagram.puml +++ b/docs/diagrams/ArchitectureSequenceDiagram.puml @@ -98,5 +98,6 @@ destroy command taa -[hidden]-> command end +deactivate taa @enduml \ No newline at end of file From e88b8aa7ed399a2d5885b334c2077a05b92ccda4 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 29 Oct 2021 20:20:00 +0800 Subject: [PATCH 255/543] Add newline at end of file --- docs/diagrams/ArchitectureSequenceDiagram.puml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml index e7cf61678f..de50d49f3d 100644 --- a/docs/diagrams/ArchitectureSequenceDiagram.puml +++ b/docs/diagrams/ArchitectureSequenceDiagram.puml @@ -100,4 +100,4 @@ taa -[hidden]-> command end deactivate taa -@enduml \ No newline at end of file +@enduml From a798620f9d995b219a70edaad702037d9394210e Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 00:46:08 +0800 Subject: [PATCH 256/543] Update parser to allow empty values, check for duplicated keys, add whitelist characters for values --- src/main/java/taa/Parser.java | 38 ++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 61c0a984e9..2d86fa9caf 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -33,14 +33,21 @@ import taa.command.student.SetCommentCommand; import taa.command.student.DeleteCommentCommand; import taa.command.student.ListCommentCommand; +import taa.exception.DuplicatedArgumentException; import taa.exception.TaaException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; +import java.util.regex.Matcher; +import java.util.regex.Pattern; public class Parser { + private static final String ARGUMENT_VALID_REGEX = "^[0-9a-zA-Z\\-_()\\s]+$"; + private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown Command"; + private static final String MESSAGE_INVALID_VALUE = "Invalid characters in value(s). Only alphanumeric characters, " + + "spaces, and some special characters are allowed.\nAllowed special characters: - _ ( )"; public static Command parseUserInput(String userInput) throws TaaException { String[] userInputSplit = splitFirstSpace(userInput); @@ -201,8 +208,10 @@ public static String[] splitFirstSpace(String string) { * @param string The string to parse. * @param argumentKeys The argument keys to find. * @return HashMap - argumentKey:argumentValue pair. + * @throws TaaException if there are any duplicated keys found within string or value is invalid. */ - public static HashMap getArgumentsFromString(String string, String[] argumentKeys) { + public static HashMap getArgumentsFromString(String string, String[] argumentKeys) + throws TaaException { if (argumentKeys == null || argumentKeys.length == 0) { return new HashMap<>(); } @@ -210,14 +219,25 @@ public static HashMap getArgumentsFromString(String string, Stri String argumentString = " " + string; HashMap argumentIndexMap = new HashMap<>(); ArrayList argumentIndexes = new ArrayList<>(); + ArrayList duplicatedKeys = new ArrayList<>(); for (String key : argumentKeys) { String searchString = String.format(" %s/", key); int index = argumentString.indexOf(searchString); if (index != -1) { argumentIndexMap.put(key, index); argumentIndexes.add(index); + + String trailingString = argumentString.substring(index + 3); + if (trailingString.contains(searchString)) { + duplicatedKeys.add(key); + } } } + + if (!duplicatedKeys.isEmpty()) { + throw new DuplicatedArgumentException(duplicatedKeys); + } + Collections.sort(argumentIndexes); HashMap result = new HashMap<>(); @@ -236,11 +256,23 @@ public static HashMap getArgumentsFromString(String string, Stri } value = value.trim(); - if (!value.isEmpty()) { - result.put(key, value); + if (!isValueValid(value)) { + throw new TaaException(MESSAGE_INVALID_VALUE); } + + result.put(key, value); } return result; } + + private static boolean isValueValid(String value) { + if (value.isEmpty()) { + return true; + } + + Pattern pattern = Pattern.compile(ARGUMENT_VALID_REGEX); + Matcher matcher = pattern.matcher(value); + return matcher.find(); + } } From c11dbbf5c73bdf27e6fe2e63d90558bda6454c79 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 00:46:43 +0800 Subject: [PATCH 257/543] Move command parsing method call into Taa --- src/main/java/taa/Taa.java | 1 + src/main/java/taa/command/Command.java | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index 5319215c16..020bf9d773 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -42,6 +42,7 @@ public void run() { try { Command command = Parser.parseUserInput(userInput); + command.parseArgument(); command.checkArgument(); command.execute(moduleList, ui, storage); isExit = command.isExit(); diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index d76a68b228..038ea6602d 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -76,7 +76,7 @@ public Command(String argument, String[] argumentKeys) { this.argument = argument; this.isExit = false; this.argumentKeys = argumentKeys; - this.argumentMap = Parser.getArgumentsFromString(argument, argumentKeys); + this.argumentMap = null; } protected abstract String getUsage(); @@ -85,6 +85,10 @@ public Command(String argument, String[] argumentKeys) { public abstract void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException; + public void parseArgument() throws TaaException { + argumentMap = Parser.getArgumentsFromString(argument, argumentKeys); + } + public boolean isExit() { return isExit; } From 0c723bc31f0dc3152949ad28b4ddd335db755c10 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 00:48:15 +0800 Subject: [PATCH 258/543] Handle invalid scanner line read --- src/main/java/taa/Ui.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index 0d4b9c2298..84daed77f8 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -3,6 +3,7 @@ //@@author leyondlee import taa.command.Command; +import java.util.NoSuchElementException; import java.util.Scanner; public class Ui { @@ -41,7 +42,12 @@ public String getUserInput(String inputPrompt, boolean allowEmpty) { String input; do { System.out.print(inputPrompt); - input = scanner.nextLine(); + + try { + input = scanner.nextLine(); + } catch (NoSuchElementException e) { + input = Command.COMMAND_EXIT; + } } while (input.trim().isEmpty() && !allowEmpty); return input; From 4fb81abbfa3ae55d528c5eaae80d6315ec66a396 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 00:48:48 +0800 Subject: [PATCH 259/543] Check for modules with same code when editing module --- src/main/java/taa/command/module/EditModuleCommand.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/taa/command/module/EditModuleCommand.java b/src/main/java/taa/command/module/EditModuleCommand.java index 5a9eb81355..0522d6912f 100644 --- a/src/main/java/taa/command/module/EditModuleCommand.java +++ b/src/main/java/taa/command/module/EditModuleCommand.java @@ -21,6 +21,7 @@ public class EditModuleCommand extends Command { private static final String MESSAGE_FORMAT_EDIT_MODULE_USAGE = "%s %s/ " + "[%s/] [%s/]"; private static final String MESSAGE_FORMAT_MODULE_EDITED = "Module edited:\n %s"; + private static final String MESSAGE_FORMAT_MODULE_EXISTS = "Module with code %s already exists."; public EditModuleCommand(String argument) { super(argument, EDIT_MODULE_ARGUMENT_KEYS); @@ -56,6 +57,10 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc assert (argumentMap.containsKey(KEY_NEW_MODULE_CODE) || argumentMap.containsKey(KEY_NEW_MODULE_NAME)); String newModuleCode = argumentMap.getOrDefault(KEY_NEW_MODULE_CODE, null); if (newModuleCode != null) { + if (moduleList.getModuleWithCode(newModuleCode) != null) { + throw new TaaException(String.format(MESSAGE_FORMAT_MODULE_EXISTS, newModuleCode)); + } + module.setCode(newModuleCode); } From 4896a7ab21773c75ec3b1ec28a3b63c2e2fe0eb8 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 00:49:22 +0800 Subject: [PATCH 260/543] Use variables for conditions to improve readability --- src/main/java/taa/util/Util.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java index 4eeb4d6b18..a59b2d85e0 100644 --- a/src/main/java/taa/util/Util.java +++ b/src/main/java/taa/util/Util.java @@ -83,7 +83,12 @@ public static boolean createFile(String filename) { try { boolean hasCreatedDir = true; if (parentFile != null && (!parentFile.exists() || !parentFile.isDirectory())) { - hasCreatedDir = parentFile.mkdirs(); + boolean parentFileExists = parentFile.exists(); + boolean parentFileIsDir = parentFile.isDirectory(); + boolean needCreateParent = !parentFileExists || !parentFileIsDir; + if (needCreateParent) { + hasCreatedDir = parentFile.mkdirs(); + } } if (hasCreatedDir) { From bce35d23af5979ded29537ec1c0cd9a1a03a9e4b Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 00:50:00 +0800 Subject: [PATCH 261/543] Explicitly return false if string is empty for isStringInteger, isStringDouble, isStringBoolean --- src/main/java/taa/util/Util.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java index a59b2d85e0..45b3b44b7f 100644 --- a/src/main/java/taa/util/Util.java +++ b/src/main/java/taa/util/Util.java @@ -14,6 +14,10 @@ public class Util { * @return true if string can convert to integer, else false. */ public static boolean isStringInteger(String string) { + if (string.isEmpty()) { + return false; + } + boolean isInt; try { int value = Integer.parseInt(string); @@ -32,6 +36,10 @@ public static boolean isStringInteger(String string) { * @return true if string can convert to double, else false. */ public static boolean isStringDouble(String string) { + if (string.isEmpty()) { + return false; + } + boolean isDouble; try { double value = Double.parseDouble(string); @@ -50,6 +58,10 @@ public static boolean isStringDouble(String string) { * @return true if string can convert to boolean, else false. */ public static boolean isStringBoolean(String string) { + if (string.isEmpty()) { + return false; + } + return string.equals("true") || string.equals("false"); } From c8e04e69a3a6d9e28cdf041c7489521d423fc3da Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 00:50:10 +0800 Subject: [PATCH 262/543] Update ParserTest --- src/test/java/taa/ParserTest.java | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/test/java/taa/ParserTest.java b/src/test/java/taa/ParserTest.java index aac305c045..7e606a300e 100644 --- a/src/test/java/taa/ParserTest.java +++ b/src/test/java/taa/ParserTest.java @@ -2,6 +2,7 @@ //@@author leyondlee import org.junit.jupiter.api.Test; +import taa.exception.TaaException; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -9,44 +10,44 @@ class ParserTest { @Test - void getArgumentsFromString_noKeys_expectEmpty() { - String inputString = "c/CS2113T n/Software Engineering and Object-oriented Programming"; + void getArgumentsFromString_noKeys_expectEmpty() throws TaaException { + String inputString = "c/CS2113T_-() n/Software Engineering and Object-oriented Programming_-()"; String[] keys = {}; assertTrue(Parser.getArgumentsFromString(inputString, keys).isEmpty()); } @Test - void getArgumentsFromString_oneKey_expectOneItem() { - String inputString = "c/CS2113T n/Software Engineering and Object-oriented Programming"; + void getArgumentsFromString_oneKey_expectOneItem() throws TaaException { + String inputString = "c/CS2113T_-() n/Software Engineering and Object-oriented Programming_-()"; String[] keys = {"n"}; assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 1); } @Test - void getArgumentsFromString_twoKeys_expectTwoItems() { - String inputString = "c/CS2113T n/Software Engineering and Object-oriented Programming"; + void getArgumentsFromString_twoKeys_expectTwoItems() throws TaaException { + String inputString = "c/CS2113T_-() n/Software Engineering and Object-oriented Programming_-()"; String[] keys = {"c","n"}; assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 2); } @Test - void getArgumentsFromString_threeKeys_expectThreeItems() { - String inputString = "c/CS2113T a/Midterms w/20"; + void getArgumentsFromString_threeKeys_expectThreeItems() throws TaaException { + String inputString = "c/CS2113T_-() a/Midterms_-() w/20_-()"; String[] keys = {"c", "a", "w"}; assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 3); } @Test - void getArgumentsFromString_OneKeyAndEmptyValue_expectZeroItems() { + void getArgumentsFromString_OneKeyAndEmptyValue_expectEmptyValue() throws TaaException { String inputString = "c/"; String[] keys = {"c"}; - assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 0); + assertEquals(Parser.getArgumentsFromString(inputString, keys).get("c"), ""); } @Test - void getArgumentsFromString_TwoKeyAndOneEmptyValue_expectOneItem() { + void getArgumentsFromString_TwoKeyAndOneEmptyValue_expectOneItem() throws TaaException { String inputString = "c/ n/Software Engineering and Object-oriented Programming"; String[] keys = {"c","n"}; - assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 1); + assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 2); } } From ed547d0276667f13a8be846bca4e3f3e8a02d196 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 00:50:28 +0800 Subject: [PATCH 263/543] Add DuplicatedArgumentException --- .../DuplicatedArgumentException.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 src/main/java/taa/exception/DuplicatedArgumentException.java diff --git a/src/main/java/taa/exception/DuplicatedArgumentException.java b/src/main/java/taa/exception/DuplicatedArgumentException.java new file mode 100644 index 0000000000..6aa50059a1 --- /dev/null +++ b/src/main/java/taa/exception/DuplicatedArgumentException.java @@ -0,0 +1,25 @@ +package taa.exception; + +import java.util.ArrayList; + +public class DuplicatedArgumentException extends TaaException { + private static final String MESSAGE_FORMAT_DUPLICATED_KEYS_FOUND = "Duplicated keys found: %s"; + + public DuplicatedArgumentException(ArrayList duplicatedKeys) { + super(generateMessage(duplicatedKeys)); + } + + private static String generateMessage(ArrayList duplicatedKeys) { + String duplicatedKeysStr = ""; + for (int i = 0; i < duplicatedKeys.size(); i += 1) { + String key = duplicatedKeys.get(i); + + if (i > 0) { + duplicatedKeysStr += ", "; + } + duplicatedKeysStr += key; + } + + return String.format(MESSAGE_FORMAT_DUPLICATED_KEYS_FOUND, duplicatedKeysStr); + } +} From 6f7e93bd515b65b6691a62a382fdb6d6314b828a Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 00:50:33 +0800 Subject: [PATCH 264/543] Add UtilTest --- src/test/java/taa/util/UtilTest.java | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 src/test/java/taa/util/UtilTest.java diff --git a/src/test/java/taa/util/UtilTest.java b/src/test/java/taa/util/UtilTest.java new file mode 100644 index 0000000000..2edc14b2f8 --- /dev/null +++ b/src/test/java/taa/util/UtilTest.java @@ -0,0 +1,23 @@ +package taa.util; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +class UtilTest { + + @Test + void isStringInteger_emptyString_expectFalse() { + assertFalse(Util.isStringInteger("")); + } + + @Test + void isStringDouble_emptyString_expectFalse() { + assertFalse(Util.isStringDouble("")); + } + + @Test + void isStringBoolean_emptyString_expectFalse() { + assertFalse(Util.isStringBoolean("")); + } +} \ No newline at end of file From 4f3752276bb75d16eb4ae24522973f3238362450 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 02:01:08 +0800 Subject: [PATCH 265/543] Refactor module related classes to class --- src/main/java/taa/Parser.java | 30 ++-- src/main/java/taa/Taa.java | 22 +-- .../java/taa/assessment/AssessmentList.java | 2 +- .../taa/attendance/LessonAttendanceList.java | 2 +- src/main/java/taa/classmodel/ClassList.java | 132 ++++++++++++++++++ .../ClassObject.java} | 28 ++-- src/main/java/taa/command/ArchiveCommand.java | 12 +- src/main/java/taa/command/Command.java | 16 +-- src/main/java/taa/command/ExitCommand.java | 6 +- src/main/java/taa/command/HelpCommand.java | 20 +-- src/main/java/taa/command/ResetCommand.java | 10 +- .../assessment/AddAssessmentCommand.java | 34 ++--- .../assessment/DeleteAssessmentCommand.java | 33 +++-- .../assessment/EditAssessmentCommand.java | 42 +++--- .../assessment/ListAssessmentsCommand.java | 32 ++--- .../attendance/DeleteAttendanceCommand.java | 30 ++-- .../attendance/ListAttendanceCommand.java | 26 ++-- .../ListLessonAttendanceCommand.java | 26 ++-- .../attendance/SetAttendanceCommand.java | 28 ++-- .../classcategory/AddClassCommand.java | 80 +++++++++++ .../classcategory/DeleteClassCommand.java | 59 ++++++++ .../classcategory/EditClassCommand.java | 88 ++++++++++++ .../ListClassesCommand.java} | 24 ++-- .../taa/command/mark/AverageMarksCommand.java | 38 ++--- .../taa/command/mark/DeleteMarkCommand.java | 30 ++-- .../taa/command/mark/EditMarkCommand.java | 30 ++-- .../taa/command/mark/ListMarksCommand.java | 36 ++--- .../taa/command/mark/MedianMarkCommand.java | 40 +++--- .../java/taa/command/mark/SetMarkCommand.java | 30 ++-- .../taa/command/module/AddModuleCommand.java | 80 ----------- .../command/module/DeleteModuleCommand.java | 59 -------- .../taa/command/module/EditModuleCommand.java | 87 ------------ .../command/student/AddStudentCommand.java | 32 ++--- .../command/student/DeleteCommentCommand.java | 28 ++-- .../command/student/DeleteStudentCommand.java | 34 ++--- .../command/student/EditStudentCommand.java | 30 ++-- .../command/student/FindStudentCommand.java | 30 ++-- .../command/student/ListCommentCommand.java | 29 ++-- .../command/student/ListStudentsCommand.java | 30 ++-- .../command/student/SetCommentCommand.java | 28 ++-- .../command/student/SortByScoresCommand.java | 29 ++-- src/main/java/taa/module/ModuleList.java | 132 ------------------ src/main/java/taa/storage/Storage.java | 26 ++-- ...alizer.java => ClassListDeserializer.java} | 28 ++-- ...izer.java => ClassObjectDeserializer.java} | 25 ++-- .../taa/assessment/AssessmentListTest.java | 40 +++--- 46 files changed, 863 insertions(+), 870 deletions(-) create mode 100644 src/main/java/taa/classmodel/ClassList.java rename src/main/java/taa/{module/Module.java => classmodel/ClassObject.java} (82%) create mode 100644 src/main/java/taa/command/classcategory/AddClassCommand.java create mode 100644 src/main/java/taa/command/classcategory/DeleteClassCommand.java create mode 100644 src/main/java/taa/command/classcategory/EditClassCommand.java rename src/main/java/taa/command/{module/ListModulesCommand.java => classcategory/ListClassesCommand.java} (60%) delete mode 100644 src/main/java/taa/command/module/AddModuleCommand.java delete mode 100644 src/main/java/taa/command/module/DeleteModuleCommand.java delete mode 100644 src/main/java/taa/command/module/EditModuleCommand.java delete mode 100644 src/main/java/taa/module/ModuleList.java rename src/main/java/taa/storage/deserializer/{ModuleListDeserializer.java => ClassListDeserializer.java} (53%) rename src/main/java/taa/storage/deserializer/{ModuleDeserializer.java => ClassObjectDeserializer.java} (73%) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 2d86fa9caf..ae000d13c1 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -5,18 +5,18 @@ import taa.command.ResetCommand; import taa.command.assessment.AddAssessmentCommand; import taa.command.attendance.ListLessonAttendanceCommand; -import taa.command.module.AddModuleCommand; +import taa.command.classcategory.AddClassCommand; import taa.command.student.AddStudentCommand; import taa.command.mark.AverageMarksCommand; import taa.command.Command; import taa.command.assessment.DeleteAssessmentCommand; import taa.command.attendance.DeleteAttendanceCommand; import taa.command.mark.DeleteMarkCommand; -import taa.command.module.DeleteModuleCommand; +import taa.command.classcategory.DeleteClassCommand; import taa.command.student.DeleteStudentCommand; import taa.command.assessment.EditAssessmentCommand; import taa.command.mark.EditMarkCommand; -import taa.command.module.EditModuleCommand; +import taa.command.classcategory.EditClassCommand; import taa.command.student.EditStudentCommand; import taa.command.ExitCommand; import taa.command.student.FindStudentCommand; @@ -24,7 +24,7 @@ import taa.command.assessment.ListAssessmentsCommand; import taa.command.attendance.ListAttendanceCommand; import taa.command.mark.ListMarksCommand; -import taa.command.module.ListModulesCommand; +import taa.command.classcategory.ListClassesCommand; import taa.command.student.ListStudentsCommand; import taa.command.mark.MedianMarkCommand; import taa.command.attendance.SetAttendanceCommand; @@ -64,20 +64,20 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new ExitCommand(argument); break; - case Command.COMMAND_LIST_MODULES: - command = new ListModulesCommand(argument); + case Command.COMMAND_LIST_CLASSES: + command = new ListClassesCommand(argument); break; - case Command.COMMAND_ADD_MODULE: - command = new AddModuleCommand(argument); + case Command.COMMAND_ADD_CLASS: + command = new AddClassCommand(argument); break; - case Command.COMMAND_EDIT_MODULE: - command = new EditModuleCommand(argument); + case Command.COMMAND_EDIT_CLASS: + command = new EditClassCommand(argument); break; - case Command.COMMAND_DELETE_MODULE: - command = new DeleteModuleCommand(argument); + case Command.COMMAND_DELETE_CLASS: + command = new DeleteClassCommand(argument); break; case Command.COMMAND_ADD_STUDENT: @@ -199,10 +199,10 @@ public static String[] splitFirstSpace(String string) { /** * Gets argument values specified by argumentKeys. Keys with empty values are not included in the returned HashMap. * e.g. - * string: "add_module c/CS2113T n/Software Engineering and Object-oriented Programming", argumentKeys: {"c","n"} + * string: "add_class c/CS2113T-F12 n/Class F12", argumentKeys: {"c","n"} * Result: HashMap( - * "c":"CS2113T", - * "n":"Software Engineering and Object-oriented Programming" + * "c":"CS2113T-F12", + * "n":"Class F12" * ) * * @param string The string to parse. diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index 020bf9d773..55911a2d48 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -1,10 +1,10 @@ package taa; //@@author leyondlee +import taa.classmodel.ClassList; import taa.command.Command; import taa.exception.TaaException; import taa.logger.TaaLogger; -import taa.module.ModuleList; import taa.storage.Storage; import java.nio.file.Path; @@ -14,7 +14,7 @@ public class Taa { public static final String DATA_FOLDER = "./data"; public static final String DATA_FILENAME = "taa_data.json"; - private ModuleList moduleList; + private ClassList classList; private final Ui ui; private final Storage storage; @@ -31,8 +31,8 @@ public Taa(boolean isLoggingEnabled) { } public void run() { - loadModuleListFromStorage(); - assert moduleList != null; + loadClassListFromStorage(); + assert classList != null; ui.printWelcomeMessage(); @@ -44,7 +44,7 @@ public void run() { Command command = Parser.parseUserInput(userInput); command.parseArgument(); command.checkArgument(); - command.execute(moduleList, ui, storage); + command.execute(classList, ui, storage); isExit = command.isExit(); } catch (TaaException e) { ui.printException(e.getMessage()); @@ -52,18 +52,18 @@ public void run() { } while (!isExit); } - private void loadModuleListFromStorage() { - ModuleList savedModuleList = null; + private void loadClassListFromStorage() { + ClassList savedClassList = null; try { - savedModuleList = storage.load(); + savedClassList = storage.load(); } catch (TaaException e) { ui.printException(e.getMessage()); } - if (savedModuleList == null) { - moduleList = new ModuleList(); + if (savedClassList == null) { + classList = new ClassList(); } else { - moduleList = savedModuleList; + classList = savedClassList; } } diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 425de73aca..eae2c42c16 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -25,7 +25,7 @@ public ArrayList getAssessments() { } /** - * Adds an assessment to the list of assessments in a particular module. + * Adds an assessment to the list of assessments in a particular class. * Does not add if assessment name already exists * or total weightage exceed the maximum weightage after adding. * diff --git a/src/main/java/taa/attendance/LessonAttendanceList.java b/src/main/java/taa/attendance/LessonAttendanceList.java index 76e8eecadd..049414ec85 100644 --- a/src/main/java/taa/attendance/LessonAttendanceList.java +++ b/src/main/java/taa/attendance/LessonAttendanceList.java @@ -38,7 +38,7 @@ public String getLessonAttendance(Student student, Attendance attendance) { /** * Adds the LessonAttendance into the LessonAttendanceList. * - * @param studentList The list of students in the module. + * @param studentList The list of students in the class. * @param lessonNumber The lesson number. */ public void setLessonAttendances(StudentList studentList, int lessonNumber) { diff --git a/src/main/java/taa/classmodel/ClassList.java b/src/main/java/taa/classmodel/ClassList.java new file mode 100644 index 0000000000..8587b7c891 --- /dev/null +++ b/src/main/java/taa/classmodel/ClassList.java @@ -0,0 +1,132 @@ +package taa.classmodel; + +//@@author leyondlee +import taa.ClassChecker; + +import java.util.ArrayList; + +public class ClassList implements ClassChecker { + private final ArrayList classes; + + public ClassList() { + this.classes = new ArrayList<>(); + } + + public int getSize() { + return classes.size(); + } + + /** + * Gets the list of classes. Note: This returns a new ArrayList instance. + * + * @return A new ArrayList containing all the classes. + */ + public ArrayList getClasses() { + return new ArrayList<>(classes); + } + + /** + * Checks if an index is valid with respect to the classes list. + * + * @param index The index to check. + * @return true if valid, else false. + */ + public boolean isValidIndex(int index) { + return (index >= 0 && index < getSize()); + } + + /** + * Adds a ClassObject object to the list of classes. + * + * @param classObject The ClassObject object to add. + */ + public void addClass(ClassObject classObject) { + classes.add(classObject); + } + + /** + * Gets a class at the specified index. + * + * @param index The index of the class. + * @return A ClassObject object if index is valid, else null. + */ + public ClassObject getClassAt(int index) { + if (isValidIndex(index)) { + return classes.get(index); + } + + return null; + } + + /** + * Gets the class from the list with the specified id. + * + * @param id The class id to search for. + * @return A Class object if found, else null. + */ + public ClassObject getClassWithId(String id) { + for (ClassObject classObject : classes) { + if (classObject.getId().equals(id)) { + return classObject; + } + } + + return null; + } + + /** + * Deletes a particular class from the list. + * + * @param classObject The class object to delete. + * @return true if successfully removed, else false. + */ + public boolean deleteClass(ClassObject classObject) { + assert classObject != null; + + return classes.remove(classObject); + } + + public void deleteAllClasses() { + classes.clear(); + } + + @Override + public String toString() { + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < getSize(); i += 1) { + if (i > 0) { + stringBuilder.append("\n"); + } + + stringBuilder.append(i + 1); + stringBuilder.append(". "); + stringBuilder.append(classes.get(i)); + } + + return stringBuilder.toString(); + } + + /** + * Checks if the variables in the class are valid. Filters out duplicate classes with the same class ID. + * + * @return Always returns true. + */ + @Override + public boolean verify() { + ArrayList classIds = new ArrayList<>(); + ArrayList duplicatedClassObjects = new ArrayList<>(); + for (ClassObject classObject : classes) { + if (classIds.contains(classObject.getId())) { + duplicatedClassObjects.add(classObject); + } else { + classIds.add(classObject.getId()); + } + } + + for (ClassObject classObject : duplicatedClassObjects) { + classes.remove(classObject); + } + + return true; + } +} diff --git a/src/main/java/taa/module/Module.java b/src/main/java/taa/classmodel/ClassObject.java similarity index 82% rename from src/main/java/taa/module/Module.java rename to src/main/java/taa/classmodel/ClassObject.java index 3a4594d0de..0cf9745171 100644 --- a/src/main/java/taa/module/Module.java +++ b/src/main/java/taa/classmodel/ClassObject.java @@ -1,4 +1,4 @@ -package taa.module; +package taa.classmodel; //@@author leyondlee import taa.ClassChecker; @@ -10,29 +10,29 @@ import java.util.ArrayList; import java.util.HashMap; -public class Module implements ClassChecker { - private String code; +public class ClassObject implements ClassChecker { + private String id; private String name; private final StudentList studentList; private final AssessmentList assessmentList; - public Module(String code, String name) { - this.code = code; + public ClassObject(String id, String name) { + this.id = id; this.name = name; this.studentList = new StudentList(); this.assessmentList = new AssessmentList(); } - public String getCode() { - return code; + public String getId() { + return id; } public String getName() { return name; } - public void setCode(String code) { - this.code = code; + public void setId(String id) { + this.id = id; } public void setName(String name) { @@ -40,7 +40,7 @@ public void setName(String name) { } /** - * Gets the StudentList object associated to the module. + * Gets the StudentList object. * * @return A StudentList object. */ @@ -49,7 +49,7 @@ public StudentList getStudentList() { } /** - * Gets the AssessmentList object associated to the module. + * Gets the AssessmentList object. * * @return A AssessmentList object. */ @@ -60,10 +60,10 @@ public AssessmentList getAssessmentList() { @Override public String toString() { if (name.isEmpty()) { - return code; + return id; } - return String.format("%s - %s", code, name); + return String.format("%s - %s", id, name); } /** @@ -73,7 +73,7 @@ public String toString() { */ @Override public boolean verify() { - if (code.isEmpty()) { + if (id.isEmpty()) { return false; } diff --git a/src/main/java/taa/command/ArchiveCommand.java b/src/main/java/taa/command/ArchiveCommand.java index 69dcb85023..7ffa22b395 100644 --- a/src/main/java/taa/command/ArchiveCommand.java +++ b/src/main/java/taa/command/ArchiveCommand.java @@ -4,7 +4,7 @@ import taa.Taa; import taa.Ui; import taa.exception.TaaException; -import taa.module.ModuleList; +import taa.classmodel.ClassList; import taa.storage.Storage; import taa.util.Util; @@ -43,8 +43,8 @@ public void checkArgument() throws TaaException { } @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (moduleList.getSize() <= 0) { + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + if (classList.getSize() <= 0) { throw new TaaException(MESSAGE_NO_DATA); } @@ -62,7 +62,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } Storage archiveStorage = new Storage(filename); - archiveStorage.save(moduleList); + archiveStorage.save(classList); ui.printBorder(); @@ -75,8 +75,8 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc String userInput = ui.getUserInput(PROMPT_WITHIN_COMMAND, true); String message; if (userInput.equals(CONFIRM_VALUE)) { - moduleList.deleteAllModules(); - storage.save(moduleList); + classList.deleteAllClasses(); + storage.save(classList); message = MESSAGE_DATA_REMOVED; } else { diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 038ea6602d..f4a6b033cd 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -1,24 +1,24 @@ package taa.command; //@@author leyondlee +import taa.classmodel.ClassList; import taa.storage.Storage; import taa.exception.TaaException; import taa.Parser; import taa.Ui; -import taa.module.ModuleList; import java.util.HashMap; public abstract class Command { public static final String COMMAND_EXIT = "exit"; - public static final String COMMAND_LIST_MODULES = "list_modules"; + public static final String COMMAND_LIST_CLASSES = "list_classes"; public static final String COMMAND_LIST_STUDENTS = "list_students"; public static final String COMMAND_LIST_ASSESSMENTS = "list_assessments"; public static final String COMMAND_LIST_ATTENDANCE = "list_attendance"; public static final String COMMAND_LIST_LESSON_ATTENDANCE = "list_lesson_attendance"; - public static final String COMMAND_ADD_MODULE = "add_module"; - public static final String COMMAND_EDIT_MODULE = "edit_module"; - public static final String COMMAND_DELETE_MODULE = "delete_module"; + public static final String COMMAND_ADD_CLASS = "add_class"; + public static final String COMMAND_EDIT_CLASS = "edit_class"; + public static final String COMMAND_DELETE_CLASS = "delete_class"; public static final String COMMAND_FIND_STUDENT = "find_student"; public static final String COMMAND_ADD_STUDENT = "add_student"; public static final String COMMAND_EDIT_STUDENT = "edit_student"; @@ -46,12 +46,12 @@ public abstract class Command { // Common messages protected static final String MESSAGE_UNKNOWN_USAGE = "Unknown usage."; - protected static final String MESSAGE_MODULE_NOT_FOUND = "Module not found."; + protected static final String MESSAGE_CLASS_NOT_FOUND = "Class not found."; protected static final String MESSAGE_INVALID_STUDENT_INDEX = "Invalid student index."; protected static final String MESSAGE_INVALID_LESSON_NUMBER = "Invalid lesson number."; protected static final String MESSAGE_INVALID_ASSESSMENT_NAME = "Invalid assessment name."; protected static final String MESSAGE_INVALID_MARKS = "Invalid marks."; - protected static final String MESSAGE_NO_STUDENTS = "There are no students in this module"; + protected static final String MESSAGE_NO_STUDENTS = "There are no students in this class"; protected static final String MESSAGE_NO_MARKS = "This student has not been marked yet."; protected static final String MESSAGE_ALREADY_MARKED = "This student has already been marked."; protected static final String MESSAGE_NO_COMMENT_ADDED = "This student has no comment set"; @@ -83,7 +83,7 @@ public Command(String argument, String[] argumentKeys) { public abstract void checkArgument() throws TaaException; - public abstract void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException; + public abstract void execute(ClassList classList, Ui ui, Storage storage) throws TaaException; public void parseArgument() throws TaaException { argumentMap = Parser.getArgumentsFromString(argument, argumentKeys); diff --git a/src/main/java/taa/command/ExitCommand.java b/src/main/java/taa/command/ExitCommand.java index 6da14c9070..28dd5ccc1b 100644 --- a/src/main/java/taa/command/ExitCommand.java +++ b/src/main/java/taa/command/ExitCommand.java @@ -1,10 +1,10 @@ package taa.command; //@@author leyondlee +import taa.classmodel.ClassList; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.module.ModuleList; public class ExitCommand extends Command { private static final String MESSAGE_FORMAT_EXIT_USAGE = "%s"; @@ -23,13 +23,13 @@ public void checkArgument() throws TaaException { /** * Executes the exit command and exits the program. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command. */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { ui.printExitMessage(); this.isExit = true; } diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index fc793c1ed8..75338dd323 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -2,6 +2,7 @@ //@@author leyondlee import taa.Ui; +import taa.classmodel.ClassList; import taa.command.assessment.AddAssessmentCommand; import taa.command.assessment.DeleteAssessmentCommand; import taa.command.assessment.EditAssessmentCommand; @@ -15,10 +16,10 @@ import taa.command.mark.ListMarksCommand; import taa.command.mark.MedianMarkCommand; import taa.command.mark.SetMarkCommand; -import taa.command.module.AddModuleCommand; -import taa.command.module.DeleteModuleCommand; -import taa.command.module.EditModuleCommand; -import taa.command.module.ListModulesCommand; +import taa.command.classcategory.AddClassCommand; +import taa.command.classcategory.DeleteClassCommand; +import taa.command.classcategory.EditClassCommand; +import taa.command.classcategory.ListClassesCommand; import taa.command.student.AddStudentCommand; import taa.command.student.DeleteStudentCommand; import taa.command.student.EditStudentCommand; @@ -28,17 +29,16 @@ import taa.command.student.SetCommentCommand; import taa.command.student.SortByScoresCommand; import taa.exception.TaaException; -import taa.module.ModuleList; import taa.storage.Storage; public class HelpCommand extends Command { private static final String MESSAGE_FORMAT_OUTPUT = "Available commands:\n%s"; private static final Command[] commands = { - new ListModulesCommand(""), - new AddModuleCommand(""), - new EditModuleCommand(""), - new DeleteModuleCommand(""), + new ListClassesCommand(""), + new AddClassCommand(""), + new EditClassCommand(""), + new DeleteClassCommand(""), new ListStudentsCommand(""), new AddStudentCommand(""), new EditStudentCommand(""), @@ -79,7 +79,7 @@ public void checkArgument() throws TaaException { } @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { StringBuilder stringBuilder = new StringBuilder(); for (int i = 0; i < commands.length; i += 1) { Command command = commands[i]; diff --git a/src/main/java/taa/command/ResetCommand.java b/src/main/java/taa/command/ResetCommand.java index 0ea4651773..375ba952c7 100644 --- a/src/main/java/taa/command/ResetCommand.java +++ b/src/main/java/taa/command/ResetCommand.java @@ -2,8 +2,8 @@ //@@author leyondlee import taa.Ui; +import taa.classmodel.ClassList; import taa.exception.TaaException; -import taa.module.ModuleList; import taa.storage.Storage; public class ResetCommand extends Command { @@ -27,8 +27,8 @@ public void checkArgument() throws TaaException { } @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - if (moduleList.getSize() <= 0) { + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + if (classList.getSize() <= 0) { throw new TaaException(MESSAGE_NO_DATA); } @@ -38,8 +38,8 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc String userInput = ui.getUserInput(PROMPT_WITHIN_COMMAND, true); String message; if (userInput.equals(CONFIRM_VALUE)) { - moduleList.deleteAllModules(); - storage.save(moduleList); + classList.deleteAllClasses(); + storage.save(classList); message = MESSAGE_DATA_REMOVED; } else { diff --git a/src/main/java/taa/command/assessment/AddAssessmentCommand.java b/src/main/java/taa/command/assessment/AddAssessmentCommand.java index ae2bdfa894..287dcc24e5 100644 --- a/src/main/java/taa/command/assessment/AddAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/AddAssessmentCommand.java @@ -1,22 +1,22 @@ package taa.command.assessment; +import taa.classmodel.ClassList; +import taa.classmodel.ClassObject; import taa.command.Command; import taa.storage.Storage; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; import taa.util.Util; public class AddAssessmentCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_ASSESSMENT_NAME = "n"; private static final String KEY_MAXIMUM_MARKS = "m"; private static final String KEY_WEIGHTAGE = "w"; private static final String[] ADD_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_ASSESSMENT_NAME, KEY_MAXIMUM_MARKS, KEY_WEIGHTAGE @@ -24,7 +24,7 @@ public class AddAssessmentCommand extends Command { private static final String MESSAGE_FAIL_TO_ADD = "Fail to add assessment."; - private static final String MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE = "%s %s/ %s/ " + private static final String MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE = "%s %s/ %s/ " + "%s/ %s/"; private static final String MESSAGE_FORMAT_INVALID_WEIGHTAGE = "Invalid weightage. " + "Weightage must be between %,.2f and %,.2f (inclusive)"; @@ -83,19 +83,19 @@ public void checkArgument() throws TaaException { } /** - * Executes the add_assessment command and adds an assessment to a particular module. + * Executes the add_assessment command and adds an assessment to a particular class. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String maximumMarksString = argumentMap.get(KEY_MAXIMUM_MARKS); @@ -111,7 +111,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc String name = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = new Assessment(name, maximumMarks, weightage); - AssessmentList assessmentList = module.getAssessmentList(); + AssessmentList assessmentList = classObject.getAssessmentList(); assert assessmentList != null : "assessment list should exist."; boolean isSuccessful = assessmentList.addAssessment(assessment); if (!isSuccessful) { @@ -119,11 +119,11 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } assert storage != null : "storage should exist."; - storage.save(moduleList); + storage.save(classList); assert ui != null : "ui should exist."; - ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_ADDED, moduleCode, - assessment, assessmentList.getSize(), module)); + ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_ADDED, classId, + assessment, assessmentList.getSize(), classObject)); } @Override @@ -131,7 +131,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE, COMMAND_ADD_ASSESSMENT, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_ASSESSMENT_NAME, KEY_MAXIMUM_MARKS, KEY_WEIGHTAGE diff --git a/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java b/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java index 7d1ed75074..5fe84defcc 100644 --- a/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java @@ -3,22 +3,21 @@ import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; +import taa.classmodel.ClassList; +import taa.classmodel.ClassObject; import taa.command.Command; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; import taa.storage.Storage; import taa.student.Student; -import taa.student.StudentList; import java.util.ArrayList; public class DeleteAssessmentCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_ASSESSMENT_NAME = "n"; - private static final String[] DELETE_ASSESSMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; + private static final String[] DELETE_ASSESSMENT_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_ASSESSMENT_NAME}; - private static final String MESSAGE_FORMAT_DELETE_ASSESSMENT_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_DELETE_ASSESSMENT_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_ASSESSMENT_DELETED = "Assessment removed from %s:\n %s"; public DeleteAssessmentCommand(String argument) { @@ -39,28 +38,28 @@ public void checkArgument() throws TaaException { /** * Executes the delete_assessment command and deletes an assessment with the specified assessment name. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String name = argumentMap.get(KEY_ASSESSMENT_NAME); - AssessmentList assessmentList = module.getAssessmentList(); + AssessmentList assessmentList = classObject.getAssessmentList(); assert assessmentList != null : "assessment list should exist."; Assessment assessment = assessmentList.deleteAssessment(name); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } - ArrayList students = module.getStudentList().getStudents(); + ArrayList students = classObject.getStudentList().getStudents(); for (Student s : students) { if (s.marksExist(name)) { double marks = s.getMarks(name); @@ -69,10 +68,10 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } assert storage != null : "storage should exist."; - storage.save(moduleList); + storage.save(classList); assert ui != null : "ui should exist."; - ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_DELETED, moduleCode, assessment)); + ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_DELETED, classId, assessment)); } @Override @@ -80,7 +79,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_DELETE_ASSESSMENT_USAGE, COMMAND_DELETE_ASSESSMENT, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_ASSESSMENT_NAME ); } diff --git a/src/main/java/taa/command/assessment/EditAssessmentCommand.java b/src/main/java/taa/command/assessment/EditAssessmentCommand.java index 0d302b2a20..c5dbbac230 100644 --- a/src/main/java/taa/command/assessment/EditAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/EditAssessmentCommand.java @@ -2,32 +2,30 @@ import taa.Ui; import taa.assessment.Assessment; -import taa.assessment.AssessmentList; +import taa.classmodel.ClassList; +import taa.classmodel.ClassObject; import taa.command.Command; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; import taa.storage.Storage; import taa.util.Util; -import java.lang.reflect.Array; import java.util.ArrayList; public class EditAssessmentCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_ASSESSMENT_NAME = "n"; private static final String KEY_NEW_ASSESSMENT_NAME = "nn"; private static final String KEY_NEW_MAXIMUM_MARKS = "m"; private static final String KEY_NEW_WEIGHTAGE = "w"; private static final String[] EDIT_ASSESSMENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_ASSESSMENT_NAME, KEY_NEW_ASSESSMENT_NAME, KEY_NEW_MAXIMUM_MARKS, KEY_NEW_WEIGHTAGE }; - private static final String MESSAGE_FORMAT_EDIT_ASSESSMENT_USAGE = "%s %s/ " + private static final String MESSAGE_FORMAT_EDIT_ASSESSMENT_USAGE = "%s %s/ " + "%s/ [%s/] [%s/] [%s/]"; private static final String MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE = "Invalid new weightage. " + "Weightage must be between %,.2f and %,.2f (inclusive)"; @@ -45,14 +43,14 @@ public void checkArgument() throws TaaException { throw new TaaException(getUsageMessage()); } - boolean hasModuleCode = argumentMap.containsKey(KEY_MODULE_CODE); + boolean hasClassId = argumentMap.containsKey(KEY_CLASS_ID); boolean hasAssessmentName = argumentMap.containsKey(KEY_ASSESSMENT_NAME); boolean hasNewAssessmentName = argumentMap.containsKey(KEY_NEW_ASSESSMENT_NAME); boolean hasNewMaximumMarks = argumentMap.containsKey(KEY_NEW_MAXIMUM_MARKS); boolean hasNewWeightage = argumentMap.containsKey(KEY_NEW_WEIGHTAGE); - boolean hasNecessaryArguments = hasModuleCode && hasAssessmentName + boolean hasOptionalArgument = hasClassId && hasAssessmentName && (hasNewAssessmentName || hasNewMaximumMarks || hasNewWeightage); - if (!hasNecessaryArguments) { + if (!hasOptionalArgument) { throw new TaaException(getMissingArgumentMessage()); } @@ -79,25 +77,25 @@ public void checkArgument() throws TaaException { } /** - * Executes the edit_assessment command and edits an assessment a particular module. + * Executes the edit_assessment command and edits an assessment a particular class. * The name, maximum marks and weightage of the assessment can be changed. * Some new values can be missing and the old values of them will not change. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String name = argumentMap.get(KEY_ASSESSMENT_NAME); - Assessment assessment = module.getAssessmentList().getAssessment(name); + Assessment assessment = classObject.getAssessmentList().getAssessment(name); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } @@ -116,7 +114,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc ); } double totalNewWeightage = 0; - ArrayList assessments = module.getAssessmentList().getAssessments(); + ArrayList assessments = classObject.getAssessmentList().getAssessments(); for (Assessment a : assessments) { if (a.getName() != name) { totalNewWeightage += a.getWeightage(); @@ -153,10 +151,10 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } assert storage != null : "storage should exist."; - storage.save(moduleList); + storage.save(classList); assert ui != null : "ui should exist."; - ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_EDITED, moduleCode, + ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_EDITED, classId, assessment)); } @@ -165,7 +163,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_EDIT_ASSESSMENT_USAGE, COMMAND_EDIT_ASSESSMENT, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_ASSESSMENT_NAME, KEY_NEW_ASSESSMENT_NAME, KEY_NEW_MAXIMUM_MARKS, diff --git a/src/main/java/taa/command/assessment/ListAssessmentsCommand.java b/src/main/java/taa/command/assessment/ListAssessmentsCommand.java index f649528a97..fca73f0a1b 100644 --- a/src/main/java/taa/command/assessment/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/assessment/ListAssessmentsCommand.java @@ -5,16 +5,16 @@ import taa.Ui; import taa.assessment.AssessmentList; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; +import taa.classmodel.ClassObject; +import taa.classmodel.ClassList; public class ListAssessmentsCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; - private static final String[] LIST_ASSESSMENTS_ARGUMENT_KEYS = {KEY_MODULE_CODE}; + private static final String KEY_CLASS_ID = "c"; + private static final String[] LIST_ASSESSMENTS_ARGUMENT_KEYS = {KEY_CLASS_ID}; - private static final String MESSAGE_LIST_EMPTY = "There are no assessments in the module."; + private static final String MESSAGE_LIST_EMPTY = "There are no assessments in the class."; - private static final String MESSAGE_FORMAT_LIST_ASSESSMENTS_USAGE = "%s %s/"; + private static final String MESSAGE_FORMAT_LIST_ASSESSMENTS_USAGE = "%s %s/"; private static final String MESSAGE_FORMAT_OUTPUT = "Assessments for %s:\n%s"; public ListAssessmentsCommand(String argument) { @@ -33,27 +33,27 @@ public void checkArgument() throws TaaException { } /** - * Executes the list_assessment command and list all the assessments of a particular module. + * Executes the list_assessment command and list all the assessments of a particular class. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String message; - AssessmentList assessmentList = module.getAssessmentList(); + AssessmentList assessmentList = classObject.getAssessmentList(); if (assessmentList.getSize() == 0) { message = MESSAGE_LIST_EMPTY; } else { - message = String.format(MESSAGE_FORMAT_OUTPUT, module, assessmentList); + message = String.format(MESSAGE_FORMAT_OUTPUT, classObject, assessmentList); } ui.printMessage(message); @@ -64,7 +64,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_LIST_ASSESSMENTS_USAGE, COMMAND_LIST_ASSESSMENTS, - KEY_MODULE_CODE + KEY_CLASS_ID ); } } diff --git a/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java b/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java index 59f4b0352a..54ea0696e4 100644 --- a/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java @@ -5,24 +5,24 @@ import taa.attendance.AttendanceList; import taa.command.Command; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; +import taa.classmodel.ClassObject; +import taa.classmodel.ClassList; import taa.storage.Storage; import taa.student.Student; import taa.util.Util; public class DeleteAttendanceCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_LESSON_NUMBER = "l"; private static final String[] DELETE_ATTENDANCE_ARGUMENT_KEYS = { - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_LESSON_NUMBER }; private static final String MESSAGE_FORMAT_DELETE_ATTENDANCE_USAGE = - "%s %s/ %s/ %s/"; + "%s %s/ %s/ %s/"; private static final String MESSAGE_FORMAT_ATTENDANCE_DELETED = "Attendance removed for %s:\n Lesson %s"; @@ -54,25 +54,25 @@ public void checkArgument() throws TaaException { /** * Executes the delete_attendance command and deletes a student's attendance from the attendanceList. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - Student student = module.getStudentList().getStudentAt(studentIndex); - assert studentIndex >= 0 && studentIndex < module.getStudentList().getSize(); + Student student = classObject.getStudentList().getStudentAt(studentIndex); + assert studentIndex >= 0 && studentIndex < classObject.getStudentList().getSize(); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } @@ -85,7 +85,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); } - storage.save(moduleList); + storage.save(classList); ui.printMessage(String.format(MESSAGE_FORMAT_ATTENDANCE_DELETED, student, lessonNumInput)); } @@ -94,7 +94,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_DELETE_ATTENDANCE_USAGE, COMMAND_DELETE_ATTENDANCE, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_LESSON_NUMBER ); diff --git a/src/main/java/taa/command/attendance/ListAttendanceCommand.java b/src/main/java/taa/command/attendance/ListAttendanceCommand.java index 9666fde0c1..f782a351e9 100644 --- a/src/main/java/taa/command/attendance/ListAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/ListAttendanceCommand.java @@ -2,21 +2,21 @@ import taa.Ui; import taa.attendance.AttendanceList; +import taa.classmodel.ClassList; +import taa.classmodel.ClassObject; import taa.command.Command; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; import taa.storage.Storage; import taa.student.Student; import taa.student.StudentList; import taa.util.Util; public class ListAttendanceCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_STUDENT_INDEX = "s"; - private static final String[] LIST_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX}; + private static final String[] LIST_ATTENDANCE_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_STUDENT_INDEX}; - private static final String MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE = "%s %s/ %s/"; protected static final String MESSAGE_FORMAT_NO_ATTENDANCE = "There is no recorded attendance for %s."; private static final String MESSAGE_FORMAT_OUTPUT = "Attendance for %s:\n%s"; @@ -43,24 +43,24 @@ public void checkArgument() throws TaaException { /** * Executes the list_attendance command and list all the attendance record of a student. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); @@ -82,7 +82,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE, COMMAND_LIST_ATTENDANCE, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX ); } diff --git a/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java b/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java index 2144b430f1..1185d31ad8 100644 --- a/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java @@ -3,20 +3,20 @@ import taa.Ui; import taa.attendance.Attendance; import taa.attendance.LessonAttendanceList; +import taa.classmodel.ClassList; +import taa.classmodel.ClassObject; import taa.command.Command; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; import taa.storage.Storage; import taa.student.StudentList; import taa.util.Util; public class ListLessonAttendanceCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_LESSON_NUMBER = "l"; - private static final String[] LIST_LESSON_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_LESSON_NUMBER}; + private static final String[] LIST_LESSON_ATTENDANCE_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_LESSON_NUMBER}; - private static final String MESSAGE_FORMAT_LIST_LESSON_ATTENDANCE_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_LIST_LESSON_ATTENDANCE_USAGE = "%s %s/ %s/"; protected static final String MESSAGE_FORMAT_NO_ATTENDANCE = "There is no recorded attendance for Lesson %s."; private static final String MESSAGE_FORMAT_OUTPUT = "Class attendance for Lesson %s:\n%s"; @@ -43,17 +43,17 @@ public void checkArgument() throws TaaException { /** * Executes the list_lesson_attendance command and list all the attendance records of a lesson. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String lessonNumberInput = argumentMap.get(KEY_LESSON_NUMBER); @@ -63,7 +63,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); } - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); LessonAttendanceList lessonAttendances = new LessonAttendanceList(); lessonAttendances.setLessonAttendances(studentList, lessonNumber); @@ -82,7 +82,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_LIST_LESSON_ATTENDANCE_USAGE, COMMAND_LIST_LESSON_ATTENDANCE, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_LESSON_NUMBER ); } diff --git a/src/main/java/taa/command/attendance/SetAttendanceCommand.java b/src/main/java/taa/command/attendance/SetAttendanceCommand.java index d4d558fa26..2fef47fdd8 100644 --- a/src/main/java/taa/command/attendance/SetAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/SetAttendanceCommand.java @@ -1,24 +1,24 @@ package taa.command.attendance; import taa.attendance.AttendanceList; +import taa.classmodel.ClassList; import taa.command.Command; import taa.exception.TaaException; import taa.Ui; import taa.attendance.Attendance; -import taa.module.Module; -import taa.module.ModuleList; +import taa.classmodel.ClassObject; import taa.storage.Storage; import taa.student.Student; import taa.student.StudentList; import taa.util.Util; public class SetAttendanceCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_LESSON_NUMBER = "l"; private static final String KEY_PRESENT = "p"; private static final String[] SET_ATTENDANCE_ARGUMENT_KEYS = { - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_LESSON_NUMBER, KEY_PRESENT @@ -33,7 +33,7 @@ public class SetAttendanceCommand extends Command { private static final String PRESENT_VALUE = "1"; private static final String ABSENT_VALUE = "0"; - private static final String MESSAGE_FORMAT_SET_ATTENDANCE_USAGE = "%s %s/ %s/ " + private static final String MESSAGE_FORMAT_SET_ATTENDANCE_USAGE = "%s %s/ %s/ " + "%s/ %s/"; public SetAttendanceCommand(String argument) { @@ -64,23 +64,23 @@ public void checkArgument() throws TaaException { /** * Executes the set_attendance command and sets the attendance of a student. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); @@ -117,7 +117,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc attendance.setPresent(isPresent); } - storage.save(moduleList); + storage.save(classList); ui.printMessage(String.format(MESSAGE_FORMAT_SET_ATTENDANCE, student.getName(), attendance)); } @@ -127,7 +127,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_SET_ATTENDANCE_USAGE, COMMAND_SET_ATTENDANCE, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_LESSON_NUMBER, KEY_PRESENT diff --git a/src/main/java/taa/command/classcategory/AddClassCommand.java b/src/main/java/taa/command/classcategory/AddClassCommand.java new file mode 100644 index 0000000000..89e9aa3aee --- /dev/null +++ b/src/main/java/taa/command/classcategory/AddClassCommand.java @@ -0,0 +1,80 @@ +package taa.command.classcategory; + +//@@author leyondlee +import taa.classmodel.ClassObject; +import taa.classmodel.ClassList; +import taa.command.Command; +import taa.logger.TaaLogger; +import taa.storage.Storage; +import taa.exception.TaaException; +import taa.Ui; + +public class AddClassCommand extends Command { + private static final String KEY_CLASS_ID = "i"; + private static final String KEY_CLASS_NAME = "n"; + private static final String[] ADD_CLASS_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_CLASS_NAME}; + + private static final String MESSAGE_INVALID_CLASS_ID = "Invalid class ID. Class ID cannot contain spaces"; + private static final String MESSAGE_CLASS_EXISTS = "Class already exists."; + + private static final String MESSAGE_FORMAT_ADD_CLASS_USAGE = "%s %s/ [%s/]"; + private static final String MESSAGE_FORMAT_CLASS_ADDED = "Class added:\n %s\nThere are %d classes in the list."; + + public AddClassCommand(String argument) { + super(argument, ADD_CLASS_ARGUMENT_KEYS); + } + + @Override + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!argumentMap.containsKey(KEY_CLASS_ID)) { + throw new TaaException(getMissingArgumentMessage()); + } + + String classId = argumentMap.get(KEY_CLASS_ID); + if (classId.contains(" ")) { + throw new TaaException(MESSAGE_INVALID_CLASS_ID); + } + } + + /** + * Executes the add_class command and adds a class. + * + * @param classList The list of classes. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ + @Override + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + assert argumentMap.containsKey(KEY_CLASS_ID); + String classId = argumentMap.get(KEY_CLASS_ID); + + ClassObject classObject = classList.getClassWithId(classId); + if (classObject != null) { + throw new TaaException(MESSAGE_CLASS_EXISTS); + } + + String name = argumentMap.getOrDefault(KEY_CLASS_NAME, ""); + classObject = new ClassObject(classId, name); + classList.addClass(classObject); + + TaaLogger.LOGGER.logInfo(String.format("Added class: %s", classObject)); + + storage.save(classList); + ui.printMessage(String.format(MESSAGE_FORMAT_CLASS_ADDED, classObject, classList.getSize())); + } + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_ADD_CLASS_USAGE, + COMMAND_ADD_CLASS, + KEY_CLASS_ID, + KEY_CLASS_NAME + ); + } +} diff --git a/src/main/java/taa/command/classcategory/DeleteClassCommand.java b/src/main/java/taa/command/classcategory/DeleteClassCommand.java new file mode 100644 index 0000000000..213e699c11 --- /dev/null +++ b/src/main/java/taa/command/classcategory/DeleteClassCommand.java @@ -0,0 +1,59 @@ +package taa.command.classcategory; + +//@@author leyondlee +import taa.Ui; +import taa.classmodel.ClassList; +import taa.classmodel.ClassObject; +import taa.command.Command; +import taa.exception.TaaException; +import taa.storage.Storage; + +public class DeleteClassCommand extends Command { + private static final String KEY_CLASS_ID = "c"; + private static final String[] DELETE_CLASS_ARGUMENT_KEYS = {KEY_CLASS_ID}; + + private static final String MESSAGE_FORMAT_DELETE_CLASS_USAGE = "%s %s/"; + private static final String MESSAGE_FORMAT_DELETE_FAILED = "Fail to delete class:\n %s"; + private static final String MESSAGE_FORMAT_CLASS_DELETED = "Class deleted:\n %s"; + + public DeleteClassCommand(String argument) { + super(argument, DELETE_CLASS_ARGUMENT_KEYS); + } + + @Override + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + } + + @Override + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + assert argumentMap.containsKey(KEY_CLASS_ID); + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); + } + + String message; + boolean isSuccessful = classList.deleteClass(classObject); + if (isSuccessful) { + message = String.format(MESSAGE_FORMAT_CLASS_DELETED, classObject); + } else { + message = String.format(MESSAGE_FORMAT_DELETE_FAILED, classObject); + } + + storage.save(classList); + ui.printMessage(message); + } + + @Override + protected String getUsage() { + return String.format(MESSAGE_FORMAT_DELETE_CLASS_USAGE, COMMAND_DELETE_CLASS, KEY_CLASS_ID); + } +} diff --git a/src/main/java/taa/command/classcategory/EditClassCommand.java b/src/main/java/taa/command/classcategory/EditClassCommand.java new file mode 100644 index 0000000000..7778217ff5 --- /dev/null +++ b/src/main/java/taa/command/classcategory/EditClassCommand.java @@ -0,0 +1,88 @@ +package taa.command.classcategory; + +//@@author leyondlee +import taa.Ui; +import taa.classmodel.ClassObject; +import taa.classmodel.ClassList; +import taa.command.Command; +import taa.exception.TaaException; +import taa.storage.Storage; + +public class EditClassCommand extends Command { + private static final String KEY_CLASS_ID = "c"; + private static final String KEY_NEW_CLASS_ID = "i"; + private static final String KEY_NEW_CLASS_NAME = "n"; + private static final String[] EDIT_CLASS_ARGUMENT_KEYS = { + KEY_CLASS_ID, + KEY_NEW_CLASS_ID, + KEY_NEW_CLASS_NAME + }; + + private static final String MESSAGE_FORMAT_EDIT_CLASS_USAGE = "%s %s/ " + + "[%s/] [%s/]"; + private static final String MESSAGE_FORMAT_CLASS_EDITED = "Class edited:\n %s"; + private static final String MESSAGE_FORMAT_CLASS_EXISTS = "CLASS_ID: %s already exists. " + + "Please use a different CLASS_ID."; + + public EditClassCommand(String argument) { + super(argument, EDIT_CLASS_ARGUMENT_KEYS); + } + + @Override + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!argumentMap.containsKey(KEY_CLASS_ID)) { + throw new TaaException(getMissingArgumentMessage()); + } + + boolean hasNewClassId = argumentMap.containsKey(KEY_NEW_CLASS_ID); + boolean hasNewClassName = argumentMap.containsKey(KEY_NEW_CLASS_NAME); + boolean hasOptionalArguments = (hasNewClassId || hasNewClassName); + if (!hasOptionalArguments) { + throw new TaaException(getMissingArgumentMessage()); + } + } + + @Override + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + assert argumentMap.containsKey(KEY_CLASS_ID); + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); + } + + assert (argumentMap.containsKey(KEY_NEW_CLASS_ID) || argumentMap.containsKey(KEY_NEW_CLASS_NAME)); + String newClassId = argumentMap.getOrDefault(KEY_NEW_CLASS_ID, null); + if (newClassId != null) { + if (classList.getClassWithId(newClassId) != null) { + throw new TaaException(String.format(MESSAGE_FORMAT_CLASS_EXISTS, newClassId)); + } + + classObject.setId(newClassId); + } + + String newClassName = argumentMap.getOrDefault(KEY_NEW_CLASS_NAME, null); + if (newClassName != null) { + classObject.setName(newClassName); + } + + storage.save(classList); + + ui.printMessage(String.format(MESSAGE_FORMAT_CLASS_EDITED, classObject)); + } + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_EDIT_CLASS_USAGE, + COMMAND_EDIT_CLASS, + KEY_CLASS_ID, + KEY_NEW_CLASS_ID, + KEY_NEW_CLASS_NAME + ); + } +} diff --git a/src/main/java/taa/command/module/ListModulesCommand.java b/src/main/java/taa/command/classcategory/ListClassesCommand.java similarity index 60% rename from src/main/java/taa/command/module/ListModulesCommand.java rename to src/main/java/taa/command/classcategory/ListClassesCommand.java index 1313686393..42857bad67 100644 --- a/src/main/java/taa/command/module/ListModulesCommand.java +++ b/src/main/java/taa/command/classcategory/ListClassesCommand.java @@ -1,18 +1,18 @@ -package taa.command.module; +package taa.command.classcategory; //@@author leyondlee import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.module.ModuleList; +import taa.classmodel.ClassList; -public class ListModulesCommand extends Command { - private static final String MESSAGE_LIST_EMPTY = "There are no modules in the list."; +public class ListClassesCommand extends Command { + private static final String MESSAGE_LIST_EMPTY = "There are no classes in the list."; - private static final String MESSAGE_FORMAT_OUTPUT = "Module list:\n%s"; + private static final String MESSAGE_FORMAT_OUTPUT = "Class list:\n%s"; - public ListModulesCommand(String argument) { + public ListClassesCommand(String argument) { super(argument); } @@ -24,20 +24,20 @@ public void checkArgument() throws TaaException { } /** - * Executes the list_modules command and lists all the modules. + * Executes the list_classes command and lists all the classes. * - * @param moduleList The list of modules. + * @param classList The ClassGroupList instance. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String message; - if (moduleList.getSize() == 0) { + if (classList.getSize() == 0) { message = MESSAGE_LIST_EMPTY; } else { - message = String.format(MESSAGE_FORMAT_OUTPUT, moduleList); + message = String.format(MESSAGE_FORMAT_OUTPUT, classList); } ui.printMessage(message); @@ -47,7 +47,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc protected String getUsage() { return String.format( MESSAGE_FORMAT_GENERIC_USAGE, - COMMAND_LIST_MODULES + COMMAND_LIST_CLASSES ); } } diff --git a/src/main/java/taa/command/mark/AverageMarksCommand.java b/src/main/java/taa/command/mark/AverageMarksCommand.java index 105fadccb8..dd1e480e53 100644 --- a/src/main/java/taa/command/mark/AverageMarksCommand.java +++ b/src/main/java/taa/command/mark/AverageMarksCommand.java @@ -1,13 +1,13 @@ package taa.command.mark; +import taa.classmodel.ClassObject; +import taa.classmodel.ClassList; import taa.command.Command; import taa.storage.Storage; import taa.assessment.Assessment; import taa.exception.TaaException; import taa.Ui; import taa.assessment.AssessmentList; -import taa.module.Module; -import taa.module.ModuleList; import taa.student.Student; import taa.student.StudentList; @@ -15,11 +15,11 @@ * Class that deals with the outputting of the average marks. */ public class AverageMarksCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_ASSESSMENT_NAME = "a"; - private static final String[] AVERAGE_MARKS_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; + private static final String[] AVERAGE_MARKS_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_ASSESSMENT_NAME}; - private static final String MESSAGE_FORMAT_AVERAGE_MARKS_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_AVERAGE_MARKS_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_AVERAGE_MARKS = "Average marks for %s is %,.2f"; private static final String MESSAGE_FORMAT_AVERAGE_MARKS_WITH_UNMARKED = "Average marks for %s is %,.2f\n" + "Note that %d student(s) have yet to be marked!"; @@ -42,41 +42,41 @@ public void checkArgument() throws TaaException { /** * Executes the average_marks command and displays the average mark of an assessment to the user. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); if (studentList.getSize() <= 0) { throw new TaaException(MESSAGE_NO_STUDENTS); } - AssessmentList assessmentList = module.getAssessmentList(); + AssessmentList assessmentList = classObject.getAssessmentList(); Assessment assessment = assessmentList.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } - printAverageMarks(ui, module, assessment); + printAverageMarks(ui, classObject, assessment); } /** - * Outputs the average marks of an assessment in a module. + * Outputs the average marks of an assessment in a class. * * @param ui The ui instance to handle interactions with the user. - * @param module The module the assessment belongs to. + * @param classObject The class the assessment belongs to. */ - private void printAverageMarks(Ui ui, Module module, Assessment assessment) { - StudentList studentList = module.getStudentList(); + private void printAverageMarks(Ui ui, ClassObject classObject, Assessment assessment) { + StudentList studentList = classObject.getStudentList(); String assessmentName = assessment.getName(); double classSize = studentList.getSize(); @@ -109,7 +109,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_AVERAGE_MARKS_USAGE, COMMAND_AVERAGE_MARKS, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_ASSESSMENT_NAME ); } diff --git a/src/main/java/taa/command/mark/DeleteMarkCommand.java b/src/main/java/taa/command/mark/DeleteMarkCommand.java index cf16cfbde2..1998cee80e 100644 --- a/src/main/java/taa/command/mark/DeleteMarkCommand.java +++ b/src/main/java/taa/command/mark/DeleteMarkCommand.java @@ -3,25 +3,25 @@ import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; +import taa.classmodel.ClassList; +import taa.classmodel.ClassObject; import taa.command.Command; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; import taa.storage.Storage; import taa.student.Student; import taa.student.StudentList; import taa.util.Util; public class DeleteMarkCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_ASSESSMENT_NAME = "a"; private static final String[] DELETE_MARK_ARGUMENT_KEYS = { - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_ASSESSMENT_NAME }; - private static final String MESSAGE_FORMAT_DELETE_MARKS_USAGE = "%s %s/ %s/ " + private static final String MESSAGE_FORMAT_DELETE_MARKS_USAGE = "%s %s/ %s/ " + "%s/"; private static final String MESSAGE_FORMAT_MARKS_DELETED = "Marks for student '%s' have been deleted for" + " assessment '%s'"; @@ -49,30 +49,30 @@ public void checkArgument() throws TaaException { /** * Executes the delete_marks command and deletes the marks of a student's assessment. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - AssessmentList assessmentList = module.getAssessmentList(); + AssessmentList assessmentList = classObject.getAssessmentList(); String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = assessmentList.getAssessment(assessmentName); if (assessment == null) { @@ -84,7 +84,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } deleteMark(ui, student, assessment); - storage.save(moduleList); + storage.save(classList); } /** @@ -109,7 +109,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_DELETE_MARKS_USAGE, COMMAND_DELETE_MARK, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_ASSESSMENT_NAME ); diff --git a/src/main/java/taa/command/mark/EditMarkCommand.java b/src/main/java/taa/command/mark/EditMarkCommand.java index 32b4347067..b01a05a7ff 100644 --- a/src/main/java/taa/command/mark/EditMarkCommand.java +++ b/src/main/java/taa/command/mark/EditMarkCommand.java @@ -3,28 +3,28 @@ import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; +import taa.classmodel.ClassList; +import taa.classmodel.ClassObject; import taa.command.Command; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; import taa.storage.Storage; import taa.student.Student; import taa.student.StudentList; import taa.util.Util; public class EditMarkCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_ASSESSMENT_NAME = "a"; private static final String KEY_NEW_MARKS = "m"; private static final String[] EDIT_MARKS_ARGUMENT_KEYS = { - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_ASSESSMENT_NAME, KEY_NEW_MARKS }; - private static final String MESSAGE_FORMAT_EDIT_MARKS_USAGE = "%s %s/ %s/ " + private static final String MESSAGE_FORMAT_EDIT_MARKS_USAGE = "%s %s/ %s/ " + "%s/ %s/"; private static final String MESSAGE_FORMAT_INVALID_MARKS = "Invalid Marks. " + "Marks must be between %d and %,.2f (inclusive)"; @@ -58,29 +58,29 @@ public void checkArgument() throws TaaException { /** * Executes the edit_marks command and edits the marks of a student's assessment. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - AssessmentList assessmentList = module.getAssessmentList(); + AssessmentList assessmentList = classObject.getAssessmentList(); String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = assessmentList.getAssessment(assessmentName); if (assessment == null) { @@ -100,7 +100,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } editMark(ui, student, assessment, marks); - storage.save(moduleList); + storage.save(classList); } /** @@ -128,7 +128,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_EDIT_MARKS_USAGE, COMMAND_EDIT_MARK, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_ASSESSMENT_NAME, KEY_NEW_MARKS diff --git a/src/main/java/taa/command/mark/ListMarksCommand.java b/src/main/java/taa/command/mark/ListMarksCommand.java index 0fd44df459..b6a3a0cfb0 100644 --- a/src/main/java/taa/command/mark/ListMarksCommand.java +++ b/src/main/java/taa/command/mark/ListMarksCommand.java @@ -1,13 +1,13 @@ package taa.command.mark; +import taa.classmodel.ClassObject; import taa.command.Command; import taa.storage.Storage; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; +import taa.classmodel.ClassList; import taa.student.Student; import taa.student.StudentList; @@ -15,14 +15,14 @@ * Class that deals with the command for the listing of marks. */ public class ListMarksCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_ASSESSMENT_NAME = "a"; - private static final String[] LIST_MARKS_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; + private static final String[] LIST_MARKS_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_ASSESSMENT_NAME}; private static final String MESSAGE_LIST_MARKS_HEADER = "Here is the list of students and " + "their marks for %s:"; private static final String MARKS_LIST_EMPTY = "There are no marks inputted!"; - private static final String MESSAGE_FORMAT_LIST_MARKS_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_LIST_MARKS_USAGE = "%s %s/ %s/"; public ListMarksCommand(String argument) { super(argument, LIST_MARKS_ARGUMENT_KEYS); @@ -42,31 +42,31 @@ public void checkArgument() throws TaaException { /** * Executes the list_marks command and list marks of students for an assessment. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); if (studentList.getSize() <= 0) { throw new TaaException(MESSAGE_NO_STUDENTS); } - AssessmentList assessmentList = module.getAssessmentList(); + AssessmentList assessmentList = classObject.getAssessmentList(); Assessment assessment = assessmentList.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } - listMarks(ui, module, assessment); + listMarks(ui, classObject, assessment); } /** @@ -84,10 +84,10 @@ public String marksToString(String studentName, double marks) { * Lists the student and the marks they attained for an assessment. * * @param ui The ui instance to handle interactions with the user. - * @param module The module that the student and assessment belong to. + * @param classObject The class that the student and assessment belong to. */ - private void listMarks(Ui ui, Module module, Assessment assessment) { - StudentList studentList = module.getStudentList(); + private void listMarks(Ui ui, ClassObject classObject, Assessment assessment) { + StudentList studentList = classObject.getStudentList(); String assessmentName = assessment.getName(); StringBuilder stringBuilder = new StringBuilder(String.format(MESSAGE_LIST_MARKS_HEADER, assessmentName)); @@ -126,7 +126,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_LIST_MARKS_USAGE, COMMAND_LIST_MARKS, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_ASSESSMENT_NAME ); } diff --git a/src/main/java/taa/command/mark/MedianMarkCommand.java b/src/main/java/taa/command/mark/MedianMarkCommand.java index cd63311252..d763a12dc9 100644 --- a/src/main/java/taa/command/mark/MedianMarkCommand.java +++ b/src/main/java/taa/command/mark/MedianMarkCommand.java @@ -3,10 +3,10 @@ import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; +import taa.classmodel.ClassObject; import taa.command.Command; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; +import taa.classmodel.ClassList; import taa.storage.Storage; import taa.student.Student; import taa.student.StudentList; @@ -19,11 +19,11 @@ import java.util.Map; public class MedianMarkCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_ASSESSMENT_NAME = "a"; - private static final String[] MEDIAN_MARKS_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; + private static final String[] MEDIAN_MARKS_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_ASSESSMENT_NAME}; - private static final String MESSAGE_FORMAT_MEDIAN_MARKS_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_MEDIAN_MARKS_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_MEDIAN_MARKS = "Median mark for %s is %,.2f"; private static final String MESSAGE_FORMAT_MEDIAN_MARKS_WITH_UNMARKED = "Median mark for %s is %,.2f\n" + "Note that %d student(s) have yet to be marked!"; @@ -46,47 +46,47 @@ public void checkArgument() throws TaaException { /** * Executes the median_marks command and displays the average mark of an assessment to the user. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); if (studentList.getSize() <= 0) { throw new TaaException(MESSAGE_NO_STUDENTS); } - AssessmentList assessmentList = module.getAssessmentList(); + AssessmentList assessmentList = classObject.getAssessmentList(); Assessment assessment = assessmentList.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } - ArrayList students = module.getStudentList().getStudents(); + ArrayList students = classObject.getStudentList().getStudents(); ArrayList studentsClone = new ArrayList<>(); for (Student student : students) { Student clonedStudent = new Student(student.getId(), student.getName()); clonedStudent.setMarks(assessment.getName(), student.getMarks(assessment.getName())); studentsClone.add(clonedStudent); } - printMedianMarks(ui, module, assessment, studentsClone); + printMedianMarks(ui, classObject, assessment, studentsClone); } /** - * Outputs the median marks of an assessment in a module. + * Outputs the median marks of an assessment in a class. * * @param ui The ui instance to handle interactions with the user. - * @param module The module the assessment belongs to. + * @param classObject The class the assessment belongs to. */ - private void printMedianMarks(Ui ui, Module module, Assessment assessment, ArrayList students) { - StudentList studentList = module.getStudentList(); + private void printMedianMarks(Ui ui, ClassObject classObject, Assessment assessment, ArrayList students) { + StudentList studentList = classObject.getStudentList(); String assessmentName = assessment.getName(); double classSize = studentList.getSize(); int printIterator = 1; @@ -130,7 +130,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_MEDIAN_MARKS_USAGE, COMMAND_MEDIAN_MARK, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_ASSESSMENT_NAME ); } diff --git a/src/main/java/taa/command/mark/SetMarkCommand.java b/src/main/java/taa/command/mark/SetMarkCommand.java index 9e7bc285a8..2375abc24f 100644 --- a/src/main/java/taa/command/mark/SetMarkCommand.java +++ b/src/main/java/taa/command/mark/SetMarkCommand.java @@ -1,13 +1,13 @@ package taa.command.mark; +import taa.classmodel.ClassObject; import taa.command.Command; import taa.storage.Storage; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; +import taa.classmodel.ClassList; import taa.student.Student; import taa.student.StudentList; import taa.util.Util; @@ -16,18 +16,18 @@ * Class that deals with the command for the setting of marks. */ public class SetMarkCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_ASSESSMENT_NAME = "a"; private static final String KEY_MARKS = "m"; private static final String[] SET_MARKS_ARGUMENT_KEYS = { - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_ASSESSMENT_NAME, KEY_MARKS }; - private static final String MESSAGE_FORMAT_SET_MARKS_USAGE = "%s %s/ %s/ " + private static final String MESSAGE_FORMAT_SET_MARKS_USAGE = "%s %s/ %s/ " + "%s/ %s/"; private static final String MESSAGE_FORMAT_INVALID_MARKS = "Invalid Marks. " + "Marks must be between %d and %,.2f (inclusive)"; @@ -61,29 +61,29 @@ public void checkArgument() throws TaaException { /** * Executes the set_marks command and sets the marks of a student's assessment. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - AssessmentList assessmentList = module.getAssessmentList(); + AssessmentList assessmentList = classObject.getAssessmentList(); String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = assessmentList.getAssessment(assessmentName); if (assessment == null) { @@ -102,7 +102,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc } setMarks(ui, student, assessment, marks); - storage.save(moduleList); + storage.save(classList); } /** @@ -129,7 +129,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_SET_MARKS_USAGE, COMMAND_SET_MARKS, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_ASSESSMENT_NAME, KEY_MARKS diff --git a/src/main/java/taa/command/module/AddModuleCommand.java b/src/main/java/taa/command/module/AddModuleCommand.java deleted file mode 100644 index 2092fc7a68..0000000000 --- a/src/main/java/taa/command/module/AddModuleCommand.java +++ /dev/null @@ -1,80 +0,0 @@ -package taa.command.module; - -//@@author leyondlee -import taa.command.Command; -import taa.logger.TaaLogger; -import taa.storage.Storage; -import taa.exception.TaaException; -import taa.Ui; -import taa.module.ModuleList; -import taa.module.Module; - -public class AddModuleCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; - private static final String KEY_MODULE_NAME = "n"; - private static final String[] ADD_MODULE_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_MODULE_NAME}; - - private static final String MESSAGE_INVALID_MODULE_CODE = "Invalid module code."; - private static final String MESSAGE_MODULE_EXISTS = "Module already exists."; - - private static final String MESSAGE_FORMAT_ADD_MODULE_USAGE = "%s %s/ [%s/]"; - private static final String MESSAGE_FORMAT_MODULE_ADDED = "Module added:\n %s\nThere are %d modules in the list."; - - public AddModuleCommand(String argument) { - super(argument, ADD_MODULE_ARGUMENT_KEYS); - } - - @Override - public void checkArgument() throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!argumentMap.containsKey(KEY_MODULE_CODE)) { - throw new TaaException(getMissingArgumentMessage()); - } - - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - if (moduleCode.contains(" ")) { - throw new TaaException(MESSAGE_INVALID_MODULE_CODE); - } - } - - /** - * Executes the add_module command and adds a module. - * - * @param moduleList The list of modules. - * @param ui The ui instance to handle interactions with the user. - * @param storage The storage instance to handle saving. - * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). - */ - @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - assert argumentMap.containsKey(KEY_MODULE_CODE); - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - - Module module = moduleList.getModuleWithCode(moduleCode); - if (module != null) { - throw new TaaException(MESSAGE_MODULE_EXISTS); - } - - String name = argumentMap.getOrDefault(KEY_MODULE_NAME, ""); - module = new Module(moduleCode, name); - moduleList.addModule(module); - - TaaLogger.LOGGER.logInfo(String.format("Added module: %s", module)); - - storage.save(moduleList); - ui.printMessage(String.format(MESSAGE_FORMAT_MODULE_ADDED, module, moduleList.getSize())); - } - - @Override - protected String getUsage() { - return String.format( - MESSAGE_FORMAT_ADD_MODULE_USAGE, - COMMAND_ADD_MODULE, - KEY_MODULE_CODE, - KEY_MODULE_NAME - ); - } -} diff --git a/src/main/java/taa/command/module/DeleteModuleCommand.java b/src/main/java/taa/command/module/DeleteModuleCommand.java deleted file mode 100644 index 06db050ad3..0000000000 --- a/src/main/java/taa/command/module/DeleteModuleCommand.java +++ /dev/null @@ -1,59 +0,0 @@ -package taa.command.module; - -//@@author leyondlee -import taa.Ui; -import taa.command.Command; -import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; -import taa.storage.Storage; - -public class DeleteModuleCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; - private static final String[] DELETE_MODULE_ARGUMENT_KEYS = {KEY_MODULE_CODE}; - - private static final String MESSAGE_FORMAT_DELETE_MODULE_USAGE = "%s %s/"; - private static final String MESSAGE_FORMAT_DELETE_FAILED = "Fail to delete module:\n %s"; - private static final String MESSAGE_FORMAT_MODULE_DELETED = "Module deleted:\n %s"; - - public DeleteModuleCommand(String argument) { - super(argument, DELETE_MODULE_ARGUMENT_KEYS); - } - - @Override - public void checkArgument() throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!hasAllArguments()) { - throw new TaaException(getMissingArgumentMessage()); - } - } - - @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - assert argumentMap.containsKey(KEY_MODULE_CODE); - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); - } - - String message; - boolean isSuccessful = moduleList.deleteModule(module); - if (isSuccessful) { - message = String.format(MESSAGE_FORMAT_MODULE_DELETED, module); - } else { - message = String.format(MESSAGE_FORMAT_DELETE_FAILED, module); - } - - storage.save(moduleList); - ui.printMessage(message); - } - - @Override - protected String getUsage() { - return String.format(MESSAGE_FORMAT_DELETE_MODULE_USAGE, COMMAND_DELETE_MODULE, KEY_MODULE_CODE); - } -} diff --git a/src/main/java/taa/command/module/EditModuleCommand.java b/src/main/java/taa/command/module/EditModuleCommand.java deleted file mode 100644 index 0522d6912f..0000000000 --- a/src/main/java/taa/command/module/EditModuleCommand.java +++ /dev/null @@ -1,87 +0,0 @@ -package taa.command.module; - -//@@author leyondlee -import taa.Ui; -import taa.command.Command; -import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; -import taa.storage.Storage; - -public class EditModuleCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; - private static final String KEY_NEW_MODULE_CODE = "nc"; - private static final String KEY_NEW_MODULE_NAME = "n"; - private static final String[] EDIT_MODULE_ARGUMENT_KEYS = { - KEY_MODULE_CODE, - KEY_NEW_MODULE_CODE, - KEY_NEW_MODULE_NAME - }; - - private static final String MESSAGE_FORMAT_EDIT_MODULE_USAGE = "%s %s/ " - + "[%s/] [%s/]"; - private static final String MESSAGE_FORMAT_MODULE_EDITED = "Module edited:\n %s"; - private static final String MESSAGE_FORMAT_MODULE_EXISTS = "Module with code %s already exists."; - - public EditModuleCommand(String argument) { - super(argument, EDIT_MODULE_ARGUMENT_KEYS); - } - - @Override - public void checkArgument() throws TaaException { - if (argument.isEmpty()) { - throw new TaaException(getUsageMessage()); - } - - if (!argumentMap.containsKey(KEY_MODULE_CODE)) { - throw new TaaException(getMissingArgumentMessage()); - } - - boolean hasNewModuleCode = argumentMap.containsKey(KEY_NEW_MODULE_CODE); - boolean hasNewModuleName = argumentMap.containsKey(KEY_NEW_MODULE_NAME); - boolean hasNecessaryArguments = (hasNewModuleCode || hasNewModuleName); - if (!hasNecessaryArguments) { - throw new TaaException(getMissingArgumentMessage()); - } - } - - @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - assert argumentMap.containsKey(KEY_MODULE_CODE); - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); - } - - assert (argumentMap.containsKey(KEY_NEW_MODULE_CODE) || argumentMap.containsKey(KEY_NEW_MODULE_NAME)); - String newModuleCode = argumentMap.getOrDefault(KEY_NEW_MODULE_CODE, null); - if (newModuleCode != null) { - if (moduleList.getModuleWithCode(newModuleCode) != null) { - throw new TaaException(String.format(MESSAGE_FORMAT_MODULE_EXISTS, newModuleCode)); - } - - module.setCode(newModuleCode); - } - - String newModuleName = argumentMap.getOrDefault(KEY_NEW_MODULE_NAME, null); - if (newModuleName != null) { - module.setName(newModuleName); - } - - storage.save(moduleList); - - ui.printMessage(String.format(MESSAGE_FORMAT_MODULE_EDITED, module)); - } - - @Override - protected String getUsage() { - return String.format( - MESSAGE_FORMAT_EDIT_MODULE_USAGE, - COMMAND_EDIT_MODULE, - KEY_MODULE_CODE, - KEY_NEW_MODULE_CODE, - KEY_NEW_MODULE_NAME - ); - } -} diff --git a/src/main/java/taa/command/student/AddStudentCommand.java b/src/main/java/taa/command/student/AddStudentCommand.java index fdb6f39285..a12afa5ffb 100644 --- a/src/main/java/taa/command/student/AddStudentCommand.java +++ b/src/main/java/taa/command/student/AddStudentCommand.java @@ -1,22 +1,22 @@ package taa.command.student; //@@author hozhenhong99 +import taa.classmodel.ClassList; +import taa.classmodel.ClassObject; import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.module.Module; -import taa.module.ModuleList; import taa.student.Student; import taa.student.StudentList; public class AddStudentCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_STUDENT_ID = "i"; private static final String KEY_STUDENT_NAME = "n"; - private static final String[] ADD_STUDENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_ID, KEY_STUDENT_NAME}; + private static final String[] ADD_STUDENT_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_STUDENT_ID, KEY_STUDENT_NAME}; - private static final String MESSAGE_FORMAT_ADD_STUDENT_USAGE = "%s %s/ %s/ " + private static final String MESSAGE_FORMAT_ADD_STUDENT_USAGE = "%s %s/ %s/ " + "%s/"; private static final String MESSAGE_STUDENT_ADDED_FORMAT = "Student has been added to %s:\n %s"; @@ -36,30 +36,30 @@ public void checkArgument() throws TaaException { } /** - * Executes the add_student command and adds a student to a particular module. + * Executes the add_student command and adds a student to a particular class. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentID = argumentMap.get(KEY_STUDENT_ID); String studentName = argumentMap.get(KEY_STUDENT_NAME); Student student = new Student(studentID, studentName); - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); studentList.addStudent(student); - storage.save(moduleList); - ui.printMessage(String.format(MESSAGE_STUDENT_ADDED_FORMAT, moduleCode, student)); + storage.save(classList); + ui.printMessage(String.format(MESSAGE_STUDENT_ADDED_FORMAT, classId, student)); } @Override @@ -67,7 +67,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_ADD_STUDENT_USAGE, COMMAND_ADD_STUDENT, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_ID, KEY_STUDENT_NAME ); diff --git a/src/main/java/taa/command/student/DeleteCommentCommand.java b/src/main/java/taa/command/student/DeleteCommentCommand.java index f1e14f4fa2..0cbcc1021f 100644 --- a/src/main/java/taa/command/student/DeleteCommentCommand.java +++ b/src/main/java/taa/command/student/DeleteCommentCommand.java @@ -1,22 +1,22 @@ package taa.command.student; //@@author hozhenhong99 +import taa.classmodel.ClassObject; +import taa.classmodel.ClassList; import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.module.Module; -import taa.module.ModuleList; import taa.student.Student; import taa.student.StudentList; import taa.util.Util; public class DeleteCommentCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_STUDENT_INDEX = "s"; - private static final String[] DELETE_COMMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX}; + private static final String[] DELETE_COMMENT_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_STUDENT_INDEX}; - private static final String MESSAGE_FORMAT_DELETE_COMMAND_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_DELETE_COMMAND_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_DELETE_COMMENT = "Comment deleted from student:\n %s"; public DeleteCommentCommand(String argument) { @@ -42,24 +42,24 @@ public void checkArgument() throws TaaException { /** * Executes the delete_comment command and deletes a comment from a student. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); @@ -70,7 +70,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc student.setComment(""); - storage.save(moduleList); + storage.save(classList); ui.printMessage(String.format(MESSAGE_FORMAT_DELETE_COMMENT, student)); } @@ -79,7 +79,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_DELETE_COMMAND_USAGE, COMMAND_SET_COMMENT, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX ); } diff --git a/src/main/java/taa/command/student/DeleteStudentCommand.java b/src/main/java/taa/command/student/DeleteStudentCommand.java index 6047ec50fe..1077733824 100644 --- a/src/main/java/taa/command/student/DeleteStudentCommand.java +++ b/src/main/java/taa/command/student/DeleteStudentCommand.java @@ -1,22 +1,22 @@ package taa.command.student; //@@author hozhenhong99 +import taa.classmodel.ClassObject; import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.module.Module; -import taa.module.ModuleList; +import taa.classmodel.ClassList; import taa.student.Student; import taa.student.StudentList; import taa.util.Util; public class DeleteStudentCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_STUDENT_INDEX = "s"; - private static final String[] DELETE_STUDENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX}; + private static final String[] DELETE_STUDENT_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_STUDENT_INDEX}; - private static final String MESSAGE_FORMAT_DELETE_STUDENT_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_DELETE_STUDENT_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_STUDENT_DELETED = "Student removed from %s:\n %s"; public DeleteStudentCommand(String argument) { @@ -40,34 +40,34 @@ public void checkArgument() throws TaaException { } /** - * Executes the delete_student command and deletes a student from the module. + * Executes the delete_student command and deletes a student from the class. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = module.getStudentList(); - assert studentIndex >= 0 && studentIndex < module.getStudentList().getSize(); + StudentList studentList = classObject.getStudentList(); + assert studentIndex >= 0 && studentIndex < classObject.getStudentList().getSize(); Student student = studentList.deleteStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - storage.save(moduleList); - ui.printMessage(String.format(MESSAGE_FORMAT_STUDENT_DELETED, moduleCode, student)); + storage.save(classList); + ui.printMessage(String.format(MESSAGE_FORMAT_STUDENT_DELETED, classId, student)); } @Override @@ -75,7 +75,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_DELETE_STUDENT_USAGE, COMMAND_DELETE_STUDENT, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX ); } diff --git a/src/main/java/taa/command/student/EditStudentCommand.java b/src/main/java/taa/command/student/EditStudentCommand.java index 0e0ed5562c..202c973d6c 100644 --- a/src/main/java/taa/command/student/EditStudentCommand.java +++ b/src/main/java/taa/command/student/EditStudentCommand.java @@ -1,29 +1,29 @@ package taa.command.student; //@@author hozhenhong99 +import taa.classmodel.ClassObject; +import taa.classmodel.ClassList; import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.module.Module; -import taa.module.ModuleList; import taa.student.Student; import taa.student.StudentList; import taa.util.Util; public class EditStudentCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_NEW_ID = "i"; private static final String KEY_NEW_NAME = "n"; private static final String[] EDIT_STUDENT_ARGUMENT_KEYS = { - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_NEW_ID, KEY_NEW_NAME }; - private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "%s %s/ %s/ " + private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "%s %s/ %s/ " + "%s/ %s/"; private static final String MESSAGE_FORMAT_STUDENT_EDITED = "Student updated:\n %s"; @@ -50,25 +50,25 @@ public void checkArgument() throws TaaException { /** * Executes the edit_student command and edits the particulars of a student. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = module.getStudentList(); - assert studentIndex >= 0 && studentIndex < module.getStudentList().getSize(); + StudentList studentList = classObject.getStudentList(); + assert studentIndex >= 0 && studentIndex < classObject.getStudentList().getSize(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); @@ -79,7 +79,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc student.setId(newId); student.setName(newName); - storage.save(moduleList); + storage.save(classList); ui.printMessage(String.format(MESSAGE_FORMAT_STUDENT_EDITED, student)); } @@ -88,7 +88,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_FIND_STUDENT_USAGE, COMMAND_EDIT_STUDENT, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_NEW_ID, KEY_NEW_NAME diff --git a/src/main/java/taa/command/student/FindStudentCommand.java b/src/main/java/taa/command/student/FindStudentCommand.java index 960d288fa3..facdae22a0 100644 --- a/src/main/java/taa/command/student/FindStudentCommand.java +++ b/src/main/java/taa/command/student/FindStudentCommand.java @@ -5,21 +5,21 @@ import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.module.Module; -import taa.module.ModuleList; +import taa.classmodel.ClassObject; +import taa.classmodel.ClassList; import taa.student.Student; import taa.student.StudentList; import java.util.ArrayList; public class FindStudentCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_KEYWORD = "k"; - private static final String[] FIND_STUDENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_KEYWORD}; + private static final String[] FIND_STUDENT_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_KEYWORD}; private static final String MESSAGE_NO_STUDENTS_FOUND = "There are no students matching your keyword."; - private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "%s %s/ %s/"; private static final String MESSAGE_FORMAT_STUDENT_FOUND_HEADER = "Here are the students in %s with \"%s\":"; public FindStudentCommand(String argument) { @@ -38,29 +38,29 @@ public void checkArgument() throws TaaException { } /** - * Executes the find_student command and finds students in the module based on a keyword. + * Executes the find_student command and finds students in the class based on a keyword. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String keyword = argumentMap.get(KEY_KEYWORD); - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); ArrayList studentsFound = studentList.findStudents(keyword); if (studentsFound.isEmpty()) { throw new TaaException(MESSAGE_NO_STUDENTS_FOUND); } - String header = String.format(MESSAGE_FORMAT_STUDENT_FOUND_HEADER, moduleCode, keyword); + String header = String.format(MESSAGE_FORMAT_STUDENT_FOUND_HEADER, classId, keyword); StringBuilder stringBuilder = new StringBuilder(header); for (int i = 0; i < studentsFound.size(); i += 1) { stringBuilder.append("\n"); @@ -77,7 +77,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_FIND_STUDENT_USAGE, COMMAND_FIND_STUDENT, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_KEYWORD ); } diff --git a/src/main/java/taa/command/student/ListCommentCommand.java b/src/main/java/taa/command/student/ListCommentCommand.java index 8b37084ffe..83002bc737 100644 --- a/src/main/java/taa/command/student/ListCommentCommand.java +++ b/src/main/java/taa/command/student/ListCommentCommand.java @@ -2,24 +2,21 @@ //@@author hozhenhong99 import taa.Ui; -import taa.attendance.AttendanceList; +import taa.classmodel.ClassList; +import taa.classmodel.ClassObject; import taa.command.Command; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; import taa.storage.Storage; import taa.student.Student; -import taa.student.StudentList; -import taa.util.Util; import java.util.ArrayList; public class ListCommentCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; - private static final String[] LIST_ATTENDANCE_ARGUMENT_KEYS = {KEY_MODULE_CODE}; + private static final String KEY_CLASS_ID = "c"; + private static final String[] LIST_ATTENDANCE_ARGUMENT_KEYS = {KEY_CLASS_ID}; private static final String MESSAGE_LIST_COMMENT_HEADER = "Here is the list of all students and the comments:"; - private static final String MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE = "%s %s/"; + private static final String MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE = "%s %s/"; public ListCommentCommand(String argument) { super(argument, LIST_ATTENDANCE_ARGUMENT_KEYS); @@ -39,20 +36,20 @@ public void checkArgument() throws TaaException { /** * Executes the list_comment command and lists all students along with their comments. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } - ArrayList students = module.getStudentList().getStudents(); + ArrayList students = classObject.getStudentList().getStudents(); StringBuilder stringBuilder = new StringBuilder(MESSAGE_LIST_COMMENT_HEADER); int studentIndex = 1; for (Student student : students) { @@ -72,7 +69,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_LIST_ATTENDANCE_USAGE, COMMAND_LIST_COMMENT, - KEY_MODULE_CODE + KEY_CLASS_ID ); } } diff --git a/src/main/java/taa/command/student/ListStudentsCommand.java b/src/main/java/taa/command/student/ListStudentsCommand.java index f5b8251f6b..3015004c8e 100644 --- a/src/main/java/taa/command/student/ListStudentsCommand.java +++ b/src/main/java/taa/command/student/ListStudentsCommand.java @@ -1,21 +1,21 @@ package taa.command.student; //@@author hozhenhong99 +import taa.classmodel.ClassList; import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.module.Module; -import taa.module.ModuleList; +import taa.classmodel.ClassObject; import taa.student.StudentList; public class ListStudentsCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; - private static final String[] LIST_STUDENT_ARGUMENT_KEYS = {KEY_MODULE_CODE}; + private static final String KEY_CLASS_ID = "c"; + private static final String[] LIST_STUDENT_ARGUMENT_KEYS = {KEY_CLASS_ID}; private static final String MESSAGE_NO_STUDENTS = "No students added yet!"; - private static final String MESSAGE_FORMAT_LIST_STUDENT_USAGE = "%s %s/"; + private static final String MESSAGE_FORMAT_LIST_STUDENT_USAGE = "%s %s/"; private static final String MESSAGE_FORMAT_OUTPUT = "Students for %s:\n%s"; public ListStudentsCommand(String argument) { @@ -34,27 +34,27 @@ public void checkArgument() throws TaaException { } /** - * Executes the list_student command and lists the students of a particular module. + * Executes the list_student command and lists the students of a particular class. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String message; - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); if (studentList.getSize() == 0) { message = MESSAGE_NO_STUDENTS; } else { - message = String.format(MESSAGE_FORMAT_OUTPUT, module, studentList); + message = String.format(MESSAGE_FORMAT_OUTPUT, classObject, studentList); } ui.printMessage(message); @@ -65,7 +65,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_LIST_STUDENT_USAGE, COMMAND_LIST_STUDENTS, - KEY_MODULE_CODE + KEY_CLASS_ID ); } } diff --git a/src/main/java/taa/command/student/SetCommentCommand.java b/src/main/java/taa/command/student/SetCommentCommand.java index 94eaedbabd..6b1471ee30 100644 --- a/src/main/java/taa/command/student/SetCommentCommand.java +++ b/src/main/java/taa/command/student/SetCommentCommand.java @@ -1,23 +1,23 @@ package taa.command.student; //@@author hozhenhong99 +import taa.classmodel.ClassObject; import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.module.Module; -import taa.module.ModuleList; +import taa.classmodel.ClassList; import taa.student.Student; import taa.student.StudentList; import taa.util.Util; public class SetCommentCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_STUDENT_INDEX = "s"; private static final String KEY_STUDENT_COMMENT = "t"; - private static final String[] SET_COMMENT_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_STUDENT_INDEX, KEY_STUDENT_COMMENT}; + private static final String[] SET_COMMENT_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_STUDENT_COMMENT}; - private static final String MESSAGE_FORMAT_SET_COMMAND_USAGE = "%s %s/ %s/ " + private static final String MESSAGE_FORMAT_SET_COMMAND_USAGE = "%s %s/ %s/ " + "%s/"; private static final String MESSAGE_FORMAT_SET_COMMENT = "Comment added to student:\n %s | %s"; @@ -44,24 +44,24 @@ public void checkArgument() throws TaaException { /** * Executes the set_comment command and sets the comment of a student. * - * @param moduleList The list of modules. + * @param classList The list of classes. * @param ui The ui instance to handle interactions with the user. * @param storage The storage instance to handle saving. * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). */ @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = module.getStudentList(); + StudentList studentList = classObject.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); @@ -71,7 +71,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc student.setComment(comment); - storage.save(moduleList); + storage.save(classList); ui.printMessage(String.format(MESSAGE_FORMAT_SET_COMMENT, student, comment)); } @@ -80,7 +80,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_SET_COMMAND_USAGE, COMMAND_SET_COMMENT, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_STUDENT_INDEX, KEY_STUDENT_COMMENT ); diff --git a/src/main/java/taa/command/student/SortByScoresCommand.java b/src/main/java/taa/command/student/SortByScoresCommand.java index 587118d778..bdb5d7b816 100644 --- a/src/main/java/taa/command/student/SortByScoresCommand.java +++ b/src/main/java/taa/command/student/SortByScoresCommand.java @@ -6,23 +6,22 @@ import taa.assessment.AssessmentList; import taa.command.Command; import taa.exception.TaaException; -import taa.module.Module; -import taa.module.ModuleList; +import taa.classmodel.ClassObject; +import taa.classmodel.ClassList; import taa.storage.Storage; import taa.student.Student; -import taa.student.StudentList; -import taa.util.Util; + import java.util.ArrayList; import java.util.HashMap; public class SortByScoresCommand extends Command { - private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_CLASS_ID = "c"; private static final String KEY_SORT_ORDER = "o"; private static final String[] SORT_SCORES_ARGUMENT_KEYS = { - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_SORT_ORDER }; - private static final String MESSAGE_FORMAT_SORT_SCORES_USAGE = "%s %s/ " + private static final String MESSAGE_FORMAT_SORT_SCORES_USAGE = "%s %s/ " + "%s/"; private static final String MESSAGE_LIST_MARKS_HEADER = "Here is the sorted list of students and their scores"; public static final String MESSAGE_INVALID_SORT_ORDER = "Please input a valid sort order."; @@ -43,19 +42,19 @@ public void checkArgument() throws TaaException { } @Override - public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { - String moduleCode = argumentMap.get(KEY_MODULE_CODE); - Module module = moduleList.getModuleWithCode(moduleCode); - if (module == null) { - throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + String classId = argumentMap.get(KEY_CLASS_ID); + ClassObject classObject = classList.getClassWithId(classId); + if (classObject == null) { + throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String order = argumentMap.get(KEY_SORT_ORDER); if (!order.equalsIgnoreCase("asc") && !order.equalsIgnoreCase("desc")) { throw new TaaException(MESSAGE_INVALID_SORT_ORDER); } - ArrayList students = module.getStudentList().getStudents(); - AssessmentList assessmentList = module.getAssessmentList(); + ArrayList students = classObject.getStudentList().getStudents(); + AssessmentList assessmentList = classObject.getAssessmentList(); HashMap unsortedScores = new HashMap<>(); ArrayList sortedStudents = new ArrayList<>(); for (Student student : students) { @@ -119,7 +118,7 @@ protected String getUsage() { return String.format( MESSAGE_FORMAT_SORT_SCORES_USAGE, COMMAND_SORT_BY_SCORES, - KEY_MODULE_CODE, + KEY_CLASS_ID, KEY_SORT_ORDER ); } diff --git a/src/main/java/taa/module/ModuleList.java b/src/main/java/taa/module/ModuleList.java deleted file mode 100644 index d5ea5f267c..0000000000 --- a/src/main/java/taa/module/ModuleList.java +++ /dev/null @@ -1,132 +0,0 @@ -package taa.module; - -//@@author leyondlee -import taa.ClassChecker; - -import java.util.ArrayList; - -public class ModuleList implements ClassChecker { - private final ArrayList modules; - - public ModuleList() { - this.modules = new ArrayList<>(); - } - - public int getSize() { - return modules.size(); - } - - /** - * Gets the list of modules. Note: This returns a new ArrayList instance. - * - * @return A new ArrayList containing all the modules. - */ - public ArrayList getModules() { - return new ArrayList<>(modules); - } - - /** - * Checks if an index is valid with respect to the modules list. - * - * @param index The index to check. - * @return true if valid, else false. - */ - public boolean isValidIndex(int index) { - return (index >= 0 && index < getSize()); - } - - /** - * Adds a Module object to the list of modules. - * - * @param module The Module object to add. - */ - public void addModule(Module module) { - modules.add(module); - } - - /** - * Gets a module at the specified index. - * - * @param index The index of the module. - * @return A module object if index is valid, else null. - */ - public Module getModuleAt(int index) { - if (isValidIndex(index)) { - return modules.get(index); - } - - return null; - } - - /** - * Gets the module from the list with the specified code. - * - * @param code The module code to search for. - * @return A Module object if found, else null. - */ - public Module getModuleWithCode(String code) { - for (Module module : modules) { - if (module.getCode().equals(code)) { - return module; - } - } - - return null; - } - - /** - * Deletes a particular module from the list. - * - * @param module The module object to delete. - * @return true if successfully removed, else false. - */ - public boolean deleteModule(Module module) { - assert module != null; - - return modules.remove(module); - } - - public void deleteAllModules() { - modules.clear(); - } - - @Override - public String toString() { - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < getSize(); i += 1) { - if (i > 0) { - stringBuilder.append("\n"); - } - - stringBuilder.append(i + 1); - stringBuilder.append(". "); - stringBuilder.append(modules.get(i)); - } - - return stringBuilder.toString(); - } - - /** - * Checks if the variables in the class are valid. Filters out duplicate modules with the same module code. - * - * @return Always returns true. - */ - @Override - public boolean verify() { - ArrayList moduleCodes = new ArrayList<>(); - ArrayList duplicatedModules = new ArrayList<>(); - for (Module module : modules) { - if (moduleCodes.contains(module.getCode())) { - duplicatedModules.add(module); - } else { - moduleCodes.add(module.getCode()); - } - } - - for (Module module : duplicatedModules) { - modules.remove(module); - } - - return true; - } -} diff --git a/src/main/java/taa/storage/Storage.java b/src/main/java/taa/storage/Storage.java index 6cd83ab2e4..61908df978 100644 --- a/src/main/java/taa/storage/Storage.java +++ b/src/main/java/taa/storage/Storage.java @@ -7,9 +7,9 @@ import com.google.gson.JsonSyntaxException; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; +import taa.classmodel.ClassList; import taa.exception.TaaException; -import taa.module.ModuleList; -import taa.storage.deserializer.ModuleListDeserializer; +import taa.storage.deserializer.ClassListDeserializer; import taa.util.Util; import java.io.FileNotFoundException; @@ -32,25 +32,25 @@ public Storage(String filename) { } /** - * Load the module list from the file. + * Load the class list from the file. * - * @return A ModuleList object after parsing from the file. + * @return A ClassList object after parsing from the file. * @throws TaaException if fail to open, read, or parse the file. */ - public ModuleList load() throws TaaException { + public ClassList load() throws TaaException { if (!Util.fileExists(filename)) { return null; } GsonBuilder gsonBuilder = new GsonBuilder(); - gsonBuilder.registerTypeAdapter(ModuleList.class, new ModuleListDeserializer()); + gsonBuilder.registerTypeAdapter(ClassList.class, new ClassListDeserializer()); Gson gson = gsonBuilder.create(); - ModuleList moduleList; + ClassList classList; try { FileReader fileReader = new FileReader(filename); JsonReader jsonReader = new JsonReader(fileReader); - moduleList = gson.fromJson(jsonReader, ModuleList.class); + classList = gson.fromJson(jsonReader, ClassList.class); jsonReader.close(); } catch (FileNotFoundException e) { throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_READ, Util.getAbsolutePath(filename))); @@ -60,16 +60,16 @@ public ModuleList load() throws TaaException { throw new TaaException(String.format(MESSAGE_FORMAT_JSON_SYNTAX_ERROR, Util.getAbsolutePath(filename))); } - return moduleList; + return classList; } /** - * Saves a ModuleList object to the file. + * Saves a ClassList object to the file. * - * @param moduleList The ModuleList object to save. + * @param classList The ClassList object to save. * @throws TaaException if fail to create, open, or write to the file. */ - public void save(ModuleList moduleList) throws TaaException { + public void save(ClassList classList) throws TaaException { if (!Util.createFile(filename)) { throw new TaaException(String.format(MESSAGE_FORMAT_FAIL_CREATE_FILE, Util.getAbsolutePath(filename))); } @@ -80,7 +80,7 @@ public void save(ModuleList moduleList) throws TaaException { try { FileWriter fileWriter = new FileWriter(filename); JsonWriter jsonWriter = new JsonWriter(fileWriter); - gson.toJson(moduleList, ModuleList.class, jsonWriter); + gson.toJson(classList, ClassList.class, jsonWriter); jsonWriter.close(); } catch (IOException e) { throw new TaaException(String.format(MESSAGE_FORMAT_UNABLE_TO_OPEN_WRITE, Util.getAbsolutePath(filename))); diff --git a/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java b/src/main/java/taa/storage/deserializer/ClassListDeserializer.java similarity index 53% rename from src/main/java/taa/storage/deserializer/ModuleListDeserializer.java rename to src/main/java/taa/storage/deserializer/ClassListDeserializer.java index e51893d14b..7d56708959 100644 --- a/src/main/java/taa/storage/deserializer/ModuleListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/ClassListDeserializer.java @@ -9,45 +9,45 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import taa.module.ModuleList; -import taa.module.Module; +import taa.classmodel.ClassList; +import taa.classmodel.ClassObject; import java.lang.reflect.Type; -public class ModuleListDeserializer extends StorageDeserializer implements JsonDeserializer { - private static final String MEMBER_MODULES = "modules"; - private static final String[] COMPULSORY_MEMBERS = {MEMBER_MODULES}; +public class ClassListDeserializer extends StorageDeserializer implements JsonDeserializer { + private static final String MEMBER_CLASSES = "classes"; + private static final String[] COMPULSORY_MEMBERS = {MEMBER_CLASSES}; @Override - public ModuleList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + public ClassList deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); if (!hasMembers(jsonObject, COMPULSORY_MEMBERS)) { return null; } - JsonElement modulesJson = jsonObject.get(MEMBER_MODULES); + JsonElement modulesJson = jsonObject.get(MEMBER_CLASSES); if (!modulesJson.isJsonArray()) { return null; } GsonBuilder gsonBuilder = new GsonBuilder(); - gsonBuilder.registerTypeAdapter(Module.class, new ModuleDeserializer()); + gsonBuilder.registerTypeAdapter(ClassObject.class, new ClassObjectDeserializer()); Gson gson = gsonBuilder.create(); - ModuleList moduleList = new ModuleList(); + ClassList classList = new ClassList(); JsonArray modulesJsonArray = modulesJson.getAsJsonArray(); for (JsonElement moduleJson : modulesJsonArray) { - Module module = gson.fromJson(moduleJson, Module.class); - if (module != null) { - moduleList.addModule(module); + ClassObject classObject = gson.fromJson(moduleJson, ClassObject.class); + if (classObject != null) { + classList.addClass(classObject); } } - if (!moduleList.verify()) { + if (!classList.verify()) { return null; } - return moduleList; + return classList; } } diff --git a/src/main/java/taa/storage/deserializer/ModuleDeserializer.java b/src/main/java/taa/storage/deserializer/ClassObjectDeserializer.java similarity index 73% rename from src/main/java/taa/storage/deserializer/ModuleDeserializer.java rename to src/main/java/taa/storage/deserializer/ClassObjectDeserializer.java index 4bd1d75f68..77fb820378 100644 --- a/src/main/java/taa/storage/deserializer/ModuleDeserializer.java +++ b/src/main/java/taa/storage/deserializer/ClassObjectDeserializer.java @@ -10,35 +10,34 @@ import com.google.gson.JsonParseException; import taa.assessment.Assessment; import taa.assessment.AssessmentList; -import taa.module.Module; +import taa.classmodel.ClassObject; import taa.student.Student; import taa.student.StudentList; -import taa.util.Util; import java.lang.reflect.Type; -public class ModuleDeserializer extends StorageDeserializer implements JsonDeserializer { - private static final String MEMBER_CODE = "code"; +public class ClassObjectDeserializer extends StorageDeserializer implements JsonDeserializer { + private static final String MEMBER_ID = "id"; private static final String MEMBER_NAME = "name"; private static final String MEMBER_STUDENTLIST = "studentList"; private static final String MEMBER_ASSESSMENTLIST = "assessmentList"; - private static final String[] COMPULSORY_MEMBERS = {MEMBER_CODE, MEMBER_NAME}; + private static final String[] COMPULSORY_MEMBERS = {MEMBER_ID, MEMBER_NAME}; @Override - public Module deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + public ClassObject deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); if (!hasMembers(jsonObject, COMPULSORY_MEMBERS)) { return null; } - JsonElement codeJson = jsonObject.get(MEMBER_CODE); - String code = codeJson.getAsString(); + JsonElement idJson = jsonObject.get(MEMBER_ID); + String id = idJson.getAsString(); JsonElement nameJson = jsonObject.get(MEMBER_NAME); String name = nameJson.getAsString(); - Module module = new Module(code, name); + ClassObject classObject = new ClassObject(id, name); GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(StudentList.class, new StudentListDeserializer()); @@ -50,7 +49,7 @@ public Module deserialize(JsonElement json, Type typeOfT, JsonDeserializationCon StudentList studentList = gson.fromJson(studentListJson, StudentList.class); if (studentList != null) { for (Student student : studentList.getStudents()) { - module.getStudentList().addStudent(student); + classObject.getStudentList().addStudent(student); } } } @@ -60,15 +59,15 @@ public Module deserialize(JsonElement json, Type typeOfT, JsonDeserializationCon AssessmentList assessmentList = gson.fromJson(assessmentListJson, AssessmentList.class); if (assessmentList != null) { for (Assessment assessment : assessmentList.getAssessments()) { - module.getAssessmentList().addAssessment(assessment); + classObject.getAssessmentList().addAssessment(assessment); } } } - if (!module.verify()) { + if (!classObject.verify()) { return null; } - return module; + return classObject; } } diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index c24b06ad1a..18ee4fc74e 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -3,9 +3,9 @@ import org.junit.jupiter.api.Test; import taa.Parser; import taa.Ui; +import taa.classmodel.ClassList; import taa.command.Command; import taa.exception.TaaException; -import taa.module.ModuleList; import taa.storage.Storage; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -25,18 +25,18 @@ void addAssessment_newAssessmentArguments_assessmentAddedCorrectly() { void addAssessment_userInput_assessmentAddedCorrectly() throws TaaException { Ui ui = new Ui(); Storage storage = new Storage("./data/taa_data.json"); - ModuleList moduleList = new ModuleList(); + ClassList classList = new ClassList(); String moduleInput = "add_module c/cs2113t n/software engineering"; String assessmentInput = "add_assessment c/cs2113t n/Midterms m/50 w/20"; Command command1 = Parser.parseUserInput(moduleInput); - command1.execute(moduleList, ui, storage); + command1.execute(classList, ui, storage); Command command2 = Parser.parseUserInput(assessmentInput); - command2.execute(moduleList, ui, storage); - assertEquals("Midterms", moduleList.getModuleWithCode("cs2113t") + command2.execute(classList, ui, storage); + assertEquals("Midterms", classList.getClassWithId("cs2113t") .getAssessmentList().getAssessment("Midterms").getName()); - assertEquals(50, moduleList.getModuleWithCode("cs2113t") + assertEquals(50, classList.getClassWithId("cs2113t") .getAssessmentList().getAssessment("Midterms").getMaximumMarks()); - assertEquals(20, moduleList.getModuleWithCode("cs2113t") + assertEquals(20, classList.getClassWithId("cs2113t") .getAssessmentList().getAssessment("Midterms").getWeightage()); } @@ -54,19 +54,19 @@ void deleteAssessment_deleteAssessmentArguments_assessmentDeletedCorrectly() thr void deleteAssessment_userInput_emptyAssessmentList() throws TaaException { Ui ui = new Ui(); Storage storage = new Storage("./data/taa_data.json"); - ModuleList moduleList = new ModuleList(); + ClassList classList = new ClassList(); String moduleInput = "add_module c/cs2113t n/software engineering"; String assessmentInput = "add_assessment c/cs2113t n/Midterms m/50 w/20"; String deleteAssessmentInput = "delete_assessment c/cs2113t n/Midterms"; Command command1 = Parser.parseUserInput(moduleInput); - command1.execute(moduleList, ui, storage); + command1.execute(classList, ui, storage); Command command2 = Parser.parseUserInput(assessmentInput); - command2.execute(moduleList, ui, storage); + command2.execute(classList, ui, storage); Command command3 = Parser.parseUserInput(deleteAssessmentInput); - command3.execute(moduleList, ui, storage); + command3.execute(classList, ui, storage); assertEquals( new AssessmentList().getSize(), - moduleList.getModuleWithCode("cs2113t").getAssessmentList().getSize() + classList.getClassWithId("cs2113t").getAssessmentList().getSize() ); } @@ -74,30 +74,30 @@ void deleteAssessment_userInput_emptyAssessmentList() throws TaaException { void editAssessment_userInputFourEdits_assessmentEditedCorrectly() throws TaaException { Ui ui = new Ui(); Storage storage = new Storage("./data/taa_data.json"); - ModuleList moduleList = new ModuleList(); + ClassList classList = new ClassList(); String moduleInput = "add_module c/cs2113t n/software engineering"; String assessmentInput = "add_assessment c/cs2113t n/Midterms m/50 w/20"; String editAssessment1 = "edit_assessment c/cs2113t n/midterms nn/finals"; Command command1 = Parser.parseUserInput(moduleInput); - command1.execute(moduleList, ui, storage); + command1.execute(classList, ui, storage); Command command2 = Parser.parseUserInput(assessmentInput); - command2.execute(moduleList, ui, storage); - Assessment assessment = moduleList.getModuleWithCode("cs2113t").getAssessmentList() + command2.execute(classList, ui, storage); + Assessment assessment = classList.getClassWithId("cs2113t").getAssessmentList() .getAssessment("midterms"); Command command3 = Parser.parseUserInput(editAssessment1); - command3.execute(moduleList, ui, storage); + command3.execute(classList, ui, storage); assertEquals("finals", assessment.getName()); String editAssessment2 = "edit_assessment c/cs2113t n/finals m/100"; Command command4 = Parser.parseUserInput(editAssessment2); - command4.execute(moduleList, ui, storage); + command4.execute(classList, ui, storage); assertEquals(100, assessment.getMaximumMarks()); String editAssessment3 = "edit_assessment c/cs2113t n/finals w/50"; Command command5 = Parser.parseUserInput(editAssessment3); - command5.execute(moduleList, ui, storage); + command5.execute(classList, ui, storage); assertEquals(50, assessment.getWeightage()); String editAssessment4 = "edit_assessment c/cs2113t n/finals nn/midterms m/50 w/20"; Command command6 = Parser.parseUserInput(editAssessment4); - command6.execute(moduleList, ui, storage); + command6.execute(classList, ui, storage); assertEquals("midterms", assessment.getName()); assertEquals(50, assessment.getMaximumMarks()); assertEquals(20, assessment.getWeightage()); From 2efc3bc4ce715d9deb6deab17937862fe09b20c0 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 02:19:13 +0800 Subject: [PATCH 266/543] Update UG to change module to class --- docs/UserGuide.md | 296 +++++++++++++++++++++++----------------------- 1 file changed, 148 insertions(+), 148 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 1be2af636b..e9bfd75527 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,22 +1,22 @@ # User Guide -Teaching Assistant's Assistant (TAA) is a Command Line Interface (CLI) application for keeping track of modules and students. -If you can type fast, TAA can help keep track of your modules and students faster than traditional Graphical User Interface (GUI) apps. +Teaching Assistant's Assistant (TAA) is a Command Line Interface (CLI) application for keeping track of classes and students. +If you can type fast, TAA can help keep track of your classes and students faster than traditional Graphical User Interface (GUI) apps. * [Quick Start](#quick-start) * [Features](#features) - * [Listing all modules: `list_modules`](#listing-all-modules-list_modules) - * [Adding a module: `add_module`](#adding-a-module-add_module) - * [Editing a module: `edit_module`](#editing-a-module-edit_module) - * [Deleting a module: `delete_module`](#deleting-a-module-delete_module) - * [Listing all students in a module: `list_students`](#listing-all-students-in-a-module-list_students) - * [Adding a student to a module: `add_student`](#adding-a-student-to-a-module-add_student) - * [Editing a student's information in a module: `edit_student`](#editing-a-students-information-in-a-module-edit_student) - * [Deleting a student from a module: `delete_student`](#deleting-a-student-from-a-module-delete_student) - * [Finding students in a module given a keyword: `find_student`](#finding-students-in-a-module-given-a-keyword-find_student) - * [Listing all assessments in a module: `list_assessments`](#listing-all-assessments-in-a-module-list_assessments) - * [Adding an assessment to a module: `add_assessment`](#adding-an-assessment-to-a-module-add_assessment) - * [Editing an assessment in a module: `edit_assessment`](#editing-an-assessment-in-a-module-edit_assessment) - * [Deleting an assessment from a module: `delete_assessment`](#deleting-an-assessment-from-a-module-delete_assessment) + * [Listing all classes: `list_class`](#listing-all-classes-list_classes) + * [Adding a class: `add_class`](#adding-a-class-add_class) + * [Editing a class: `edit_class`](#editing-a-class-edit_class) + * [Deleting a class: `delete_class`](#deleting-a-class-delete_class) + * [Listing all students in a class: `list_students`](#listing-all-students-in-a-class-list_students) + * [Adding a student to a class: `add_student`](#adding-a-student-to-a-class-add_student) + * [Editing a student's information in a class: `edit_student`](#editing-a-students-information-in-a-class-edit_student) + * [Deleting a student from a class: `delete_student`](#deleting-a-student-from-a-class-delete_student) + * [Finding students in a class given a keyword: `find_student`](#finding-students-in-a-class-given-a-keyword-find_student) + * [Listing all assessments in a class: `list_assessments`](#listing-all-assessments-in-a-class-list_assessments) + * [Adding an assessment to a class: `add_assessment`](#adding-an-assessment-to-a-class-add_assessment) + * [Editing an assessment in a class: `edit_assessment`](#editing-an-assessment-in-a-class-edit_assessment) + * [Deleting an assessment from a class: `delete_assessment`](#deleting-an-assessment-from-a-class-delete_assessment) * [Listing marks for an assessment: `list_marks`](#listing-marks-for-an-assessment-list_marks) * [Setting marks for a student's assessment: `set_marks`](#setting-marks-for-a-students-assessment-set_marks) * [Editing marks for a student's assessment: `edit_mark`](#editing-marks-for-a-students-assessment-edit_mark) @@ -43,156 +43,156 @@ If you can type fast, TAA can help keep track of your modules and students faste ## Features -### Listing all modules: `list_modules` -Displays the list of all modules in the module list. +### Listing all classes: `list_classes` +Displays the list of all classes in the class list. -Format: `list_modules` +Format: `list_classes`
-### Adding a module: `add_module` -Adds a module to the module list. +### Adding a class: `add_class` +Adds a class to the class list. -Format: `add_module c/ [n/]` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `MODULE_NAME` [Optional] refers to the name of the module to be added. +Format: `add_class c/ [n/]` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_NAME` [Optional] refers to the name of the class to be added. Examples: -* `add_module c/CS2113T n/Software Engineering and Object-oriented Programming` -* `add_module n/Effective Communication for Computing Professionals c/CS2101` -* `add_module c/CS2102` +* `add_class c/CS2113T-F12 n/Tutorial Group F12` +* `add_class n/Sectional Group C03 c/CS2101-C03` +* `add_class c/CS2102`
-### Editing a module: `edit_module` -Edits the code or name of an existing module. +### Editing a class: `edit_class` +Edits the code or name of an existing class. -Format: `edit_module c/ [nc/] [n/]` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `NEW_MODULE_CODE` [Optional] refers to the updated code of the module. -* `NEW_MODULE_NAME` [Optional] refers to the updated name of the module. +Format: `edit_class c/ [i/] [n/]` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `NEW_CLASS_ID` [Optional] refers to the updated id of the class. **Cannot contain whitespaces.** +* `NEW_CLASS_NAME` [Optional] refers to the updated name of the class. > 💡 **Note:**
> At least one optional field must be provided: -> * `NEW_MODULE_CODE` -> * `NEW_MODULE_NAME` +> * `NEW_CLASS_ID` +> * `NEW_CLASS_NAME` Examples: -* `edit_module c/CS2113T nc/cs2113t` -* `edit_module c/CS2113T n/software engineering` -* `edit_module c/CS2113T nc/cs2113t n/software engineering` +* `edit_class c/CS2113T-F12 i/cs2113t-f12` +* `edit_class c/CS2113T-F12 n/Class F12` +* `edit_class c/CS2113T-F12 i/CS2113T-F13 n/Class-F13 of Software Engineering`
-### Deleting a module: `delete_module` -Deletes an existing module from the module list. +### Deleting a class: `delete_class` +Deletes an existing class from the class list. -Format: `delete_module c/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +Format: `delete_class c/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** Examples: -* `delete_module c/CS2113T` -* `delete_module c/CS2101` +* `delete_class c/CS2113T-F12` +* `delete_class c/CS2101-C03`
-### Listing all students in a module: `list_students` -Shows a list of all students in a particular module. +### Listing all students in a class: `list_students` +Shows a list of all students in a particular class. -Format: `list_students c/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +Format: `list_students c/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** Examples: -* `list_students c/CS2113T` -* `list_students c/CS2101` +* `list_students c/CS2113T-F12` +* `list_students c/CS2101-C03`
-### Adding a student to a module: `add_student` -Adds a student to a particular module +### Adding a student to a class: `add_student` +Adds a student to a particular class. -Format: `add_student c/ i/ n/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +Format: `add_student c/ i/ n/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** * `STUDENT_ID` refers to the ID of the student (e.g. A0217978J). * `STUDENT_NAME` refers to the name of the student (e.g. Jon Lim). Examples: -* `add_student c/cs2113t i/a0212345x n/Jon Lim` -* `add_student c/cs2113t n/Jonny Lims i/a1234567i` +* `add_student c/CS2113T-F12 i/a0212345x n/Jon Lim` +* `add_student c/CS2101-C03 n/Jonny Lims i/a1234567i`
-### Editing a student's information in a module: `edit_student` -Edits student information from a particular module +### Editing a student's information in a class: `edit_student` +Edits student information from a particular class -Format: `edit_student c/ s/ i/ n/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +Format: `edit_student c/ s/ i/ n/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `STUDENT_ID` refers to the updated ID of the student (e.g. A0217978J). * `STUDENT_NAME` refers to the updated name of the student (e.g. Jon Limbs). Examples: -* `edit_student c/cs2113t s/1 i/a03452345x n/Jon Lim` -* `edit_student c/cs2113t s/5 n/Jonny Lims i/a120067i` +* `edit_student c/CS2113T-F12 s/1 i/a03452345x n/Jon Lim` +* `edit_student c/CS2101-C03 s/5 n/Jonny Lims i/a120067i`
-### Deleting a student from a module: `delete_student` -Deletes student information from a particular module. +### Deleting a student from a class: `delete_student` +Deletes student information from a particular class. -Format: `delete_student c/ s/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +Format: `delete_student c/ s/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `STUDENT_INDEX` refers to the index of the student in the student list of the class. Examples: -* `delete_student c/cs2113t s/1` +* `delete_student c/CS2113T-F12 s/1`
-### Finding students in a module given a keyword: `find_student` -Displays all students in the module matching the keyword along with their index. +### Finding students in a class given a keyword: `find_student` +Displays all students in the class matching the keyword along with their index. -Format: `find_student c/ k/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `KEYWORD` refers to the keyword used to search the student list of the module. +Format: `find_student c/ k/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `KEYWORD` refers to the keyword used to search the student list of the class. Examples: -* `find_student c/CS2113T k/123` -* `find_students c/CS2101 k/Jon` +* `find_student c/CS2113T-F12 k/123` +* `find_student c/CS2101-C03 k/Jon`
-### Listing all assessments in a module: `list_assessments` -List all assessments in a module. +### Listing all assessments in a class: `list_assessments` +List all assessments in a class. -Format: `list_assessments c/` -* MODULE_CODE refers to the code of the module (e.g. CS2113T). +Format: `list_assessments c/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** Examples: -* `list_assessments c/CS2113T` -* `list_assessments c/CS2101` +* `list_assessments c/CS2113T-F12` +* `list_assessments c/CS2101-C03`
-### Adding an assessment to a module: `add_assessment` -Adds an assessment to a module. +### Adding an assessment to a class: `add_assessment` +Adds an assessment to a class. -Format: `add_assessment c/ n/ m/ w/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +Format: `add_assessment c/ n/ m/ w/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** * `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). * `MAXIMUM_MARKS` refers to the maximum marks of the assessment (e.g. 100). * `WEIGHTAGE` refers to the weightage of the assessment (e.g. 10%). Examples: -* `add_assessment c/CS2101 n/OP1 m/20 w/10` -* `add_assessment c/CS2101 n/OP2 m/25 w/15` +* `add_assessment c/CS2101-C03 n/OP1 m/20 w/10` +* `add_assessment c/CS2101-C03 n/OP2 m/25 w/15`
-### Editing an assessment in a module: `edit_assessment` -Edits an assessment of a module. +### Editing an assessment in a class: `edit_assessment` +Edits an assessment of a class. -Format: `edit_assessment c/ n/ [nn/] [m/] [w/]` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +Format: `edit_assessment c/ n/ [nn/] [m/] [w/]` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** * `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). * `NEW_ASSESSMENT_NAME` [Optional] refers to the new name of the assessment (e.g. Finals, Assignment 2, etc.). * `NEW_MAXIMUM_MARKS` [Optional] refers to the new maximum marks of the assessment (e.g. 50). @@ -204,43 +204,43 @@ Format: `edit_assessment c/ n/ [nn/ * `NEW_WEIGHTAGE` Examples: -* `edit_assessment c/CS2101 n/OP1 m/20 w/10` -* `edit_assessment c/CS2101 n/OP2 nn/UGDG` +* `edit_assessment c/CS2101-C03 n/OP1 m/20 w/10` +* `edit_assessment c/CS2101-C03 n/OP2 nn/UGDG`
-### Deleting an assessment from a module: `delete_assessment` -Deletes an assessment of a module. +### Deleting an assessment from a class: `delete_assessment` +Deletes an assessment of a class. -Format: `delete_assessment c/ n/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +Format: `delete_assessment c/ n/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** * `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). Examples: -* `delete_assessment c/CS2101 n/OP1` -* `delete_assessment c/CS2101 n/OP2` +* `delete_assessment c/CS2101-C03 n/OP1` +* `delete_assessment c/CS2101-C03 n/OP2`
### Listing marks for an assessment: `list_marks` Lists all students and their marks for an assessment. -Format: `list_marks c/ a/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +Format: `list_marks c/ a/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** * `ASSESSMENT_NAME` refers to the name of the assessment whose marks are to be listed. Examples: -* `list_marks c/CS2113T a/Midterms` -* `list_marks c/CS2101 a/Oral Presentation` +* `list_marks c/CS2113T-F12 a/Midterms` +* `list_marks c/CS2101-C03 a/Oral Presentation`
### Setting marks for a student's assessment: `set_marks` Adds a student's marks for an assessment. -Format: `set_marks c/ s/ a/ m/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +Format: `set_marks c/ s/ a/ m/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `ASSESSMENT_NAME` refers to the name of the particular assessment. * `MARKS` refers to the marks given for the assessment. @@ -253,24 +253,24 @@ Examples: ### Editing marks for a student's assessment: `edit_mark` Edits a student's mark for an assessment. -Format: `edit_mark c/ s/ a/ m/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +Format: `edit_mark c/ s/ a/ m/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `ASSESSMENT_NAME` refers to the name of the particular assessment. * `NEW_MARKS` refers to the new marks to be given for the assessment. Examples: -* `edit_mark c/CS2113T s/1 a/Midterms m/80.6` -* `edit_mark c/CS2101 s/3 a/Oral Presentation m/90` +* `edit_mark c/CS2113T-F12 s/1 a/Midterms m/80.6` +* `edit_mark c/CS2101-C03 s/3 a/Oral Presentation m/90`
### Deleting marks for a student's assessment: `delete_mark` Deletes a student's marks for an assessment. -Format: `set_marks c/ s/ a/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in student list of the module. +Format: `set_marks c/ s/ a/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `STUDENT_INDEX` refers to the index of the student in student list of the class. * `ASSESSMENT_NAME` refers to the name of the particular assessment. Examples: @@ -283,8 +283,8 @@ Examples: Computes and prints the average marks for an assessment. If there are unmarked students, the average will be computed within the marked students only. -Format: `set_marks c/ a/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +Format: `set_marks c/ a/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** * `ASSESSMENT_NAME` refers to the name of the particular assessment. Examples: @@ -297,8 +297,8 @@ Examples: Computes and prints the median mark for an assessment. If there are unmarked students, the median will be computed within the marked students only. -Format: `set_marks c/ a/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +Format: `set_marks c/ a/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** * `ASSESSMENT_NAME` refers to the name of the particular assessment. Examples: @@ -310,18 +310,18 @@ Examples: ### Listing attendance for a particular student: `list_attendance` Lists a student's attendance. -Format: `list_attendance c/ s/ s/ ### Setting attendance for a particular lesson for a student: `set_attendance` Sets a student's attendance for a lesson. -Format: `set_attendance c/ s/ l/ p/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +Format: `set_attendance c/ s/ l/ p/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `LESSON_NUMBER` refers to the lesson number. * `PRESENT` refers to the whether a student is present. (`1` for present, `0` for not present) @@ -330,9 +330,9 @@ Format: `set_attendance c/ s/ l/ p/

s/ l/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). -* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +Format: `delete_attendance c/ s/ l/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `LESSON_NUMBER` refers to the lesson number.
@@ -378,26 +378,26 @@ Format: `reset` Action | Format | ------ | --------------- | -Listing all modules | `list_modules` -Adding a module | `add_module c/ [n/]` -Editing a module | `edit_module c/ [nc/] [n/]` -Deleting a module | `delete_module c/` -Listing all students in a module | `list_students c/` -Adding a student to a module | `add_student c/ i/ n/` -Editing a student's information in a module | `edit_student c/ s/ i/ n/` -Deleting a student from a module | `delete_student c/ s/` -Finding students in a module given a keyword | `find_student c/ k/` -Listing all assessments in a module | `list_assessments c/` -Adding an assessment to a module | `add_assessment c/ n/ m/ w/` -Editing an assessment in a module | `edit_assessment c/ n/ [nn/] [m/]` -Deleting an assessment from a module | `delete_assessment c/ n/` -Listing marks for an assessment: | `list_marks c/ a/` -Setting marks for a student's assessment | `set_marks c/ s/ a/ m/` -Editing marks for a student's assessment | `edit_mark c/ s/ a/ m/` -Deleting marks for a student's assessment | `delete_mark c/ s/ a/` -Viewing average marks for an assessment | `average_marks c/ a/` -Listing attendance for a particular student | `list_attendance c/ s/` -Setting attendance for a particular lesson for a student | `set_attendance c/ s/ l/ p/` -Deleting attendance for a particular lesson for a student | `delete_attendance c/ s/ l/` +Listing all classes | `list_classes` +Adding a class | `add_class c/ [n/]` +Editing a class | `edit_class c/ [nc/] [n/]` +Deleting a class | `delete_class c/` +Listing all students in a class | `list_students c/` +Adding a student to a class | `add_student c/ i/ n/` +Editing a student's information in a class | `edit_student c/ s/ i/ n/` +Deleting a student from a class | `delete_student c/ s/` +Finding students in a class given a keyword | `find_student c/ k/` +Listing all assessments in a class | `list_assessments c/` +Adding an assessment to a class | `add_assessment c/ n/ m/ w/` +Editing an assessment in a class | `edit_assessment c/ n/ [nn/] [m/]` +Deleting an assessment from a class | `delete_assessment c/ n/` +Listing marks for an assessment: | `list_marks c/ a/` +Setting marks for a student's assessment | `set_marks c/ s/ a/ m/` +Editing marks for a student's assessment | `edit_mark c/ s/ a/ m/` +Deleting marks for a student's assessment | `delete_mark c/ s/ a/` +Viewing average marks for an assessment | `average_marks c/ a/` +Listing attendance for a particular student | `list_attendance c/ s/` +Setting attendance for a particular lesson for a student | `set_attendance c/ s/ l/ p/` +Deleting attendance for a particular lesson for a student | `delete_attendance c/ s/ l/` Viewing help | `help` Exiting the program | `exit` From ebe1d36256e643a20e66ae87b5288a96f9e9162b Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 02:39:00 +0800 Subject: [PATCH 267/543] Change module to class in DG --- docs/DeveloperGuide.md | 22 +++--- docs/diagrams/AddClassSequenceDiagram.png | Bin 0 -> 22898 bytes docs/diagrams/AddClassSequenceDiagram.puml | 39 ++++++++++ docs/diagrams/AddModuleSequenceDiagram.png | Bin 42870 -> 0 bytes docs/diagrams/AddModuleSequenceDiagram.puml | 67 ------------------ docs/diagrams/ArchitectureDiagram.png | Bin 16400 -> 16173 bytes docs/diagrams/ArchitectureDiagram.puml | 4 +- .../diagrams/ArchitectureSequenceDiagram.puml | 28 ++++---- 8 files changed, 64 insertions(+), 96 deletions(-) create mode 100644 docs/diagrams/AddClassSequenceDiagram.png create mode 100644 docs/diagrams/AddClassSequenceDiagram.puml delete mode 100644 docs/diagrams/AddModuleSequenceDiagram.png delete mode 100644 docs/diagrams/AddModuleSequenceDiagram.puml diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index eb84f3f08e..50af23dbe8 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -34,8 +34,8 @@ The _Architecture Diagram_ shown above illustrates the high-level design of the * Handles input parsing and determines which command to run. * `Command` * Defines how a command is to be executed. -* `ModuleList` - * Contains a list of `Module` objects currently being managed by the app. +* `ClassList` + * Contains a list of `ClassObject` objects currently being managed by the app. * `Util` * Contains useful methods (e.g. Check if a string is integer/double, convert string to integer/double). * `Storage` @@ -49,19 +49,15 @@ The _Architecture Diagram_ shown above illustrates the high-level design of the The _Architecture Sequence Diagram_ shown above shows how the components usually interact with each other. ## Implementation -### Add Module -The sequence diagram shown below illustrates how the `add_module` command works: -![AddModuleSequenceDiagram](diagrams/AddModuleSequenceDiagram.png) +### Add Class +The sequence diagram shown below illustrates how the `add_class` command works: +![AddClassSequenceDiagram](diagrams/AddClassSequenceDiagram.png) Steps: -1. The `Taa` instance reads in a user input through the `Ui.getUserInput()` method. -2. The user input is then parsed using the `Parser.parseUserInput(userInput:String)` static method and a `Command` object -is returned. -3. `AddModuleCommand.checkArguments()` is then called to check if the arguments are valid. -4. After checking the arguments, `Command.execute(moduleList:ModuleList, ui:Ui, storage:Storage)` will be called. A new -`Module` object is created and the `ModuleList.addModule(module:Module)` method is invoked to add the `Module` -object into the list of modules. -5. Lastly, a message indicating that the module has been added will be printed out. +1. The `Taa` instance reads in a user input and calls `AddClassCommand.execute(classList:ClassList, ui:Ui, storage:Storage)`. +4. A new `ClassObject` object is created and the `ClassList.addClass(classObject:ClassObject)` method is invoked to add the `ClassObject` +object into the list of classes. +5. Lastly, a message indicating that the class has been added will be printed out.
diff --git a/docs/diagrams/AddClassSequenceDiagram.png b/docs/diagrams/AddClassSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..79b351a49e466eace504ebf04385a042974ac308 GIT binary patch literal 22898 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 PgCNzOu6{1-oD!M<`bI9u literal 0 HcmV?d00001 diff --git a/docs/diagrams/AddClassSequenceDiagram.puml b/docs/diagrams/AddClassSequenceDiagram.puml new file mode 100644 index 0000000000..17eed79996 --- /dev/null +++ b/docs/diagrams/AddClassSequenceDiagram.puml @@ -0,0 +1,39 @@ +@startuml +!include style.puml + +Actor User as user +Participant ":Taa" as taa +Participant ":AddClassCommand" as addClassCommand +Participant ":ClassList" as classList +Participant ":ClassObject" as classObject +Participant ":Storage" as storage + +user -> taa : "add_class c/CS2113T-F12\nn/Tutorial Group F12" +activate taa + +taa -> addClassCommand : execute(classList:ClassList,\nui:Ui, storage:Storage) +activate addClassCommand + +create classObject +addClassCommand -> classObject +activate classObject +classObject --> addClassCommand : classObject:ClassObject +deactivate classObject + +addClassCommand -> classList : addClass(classObject) +activate classList +classList --> addClassCommand +deactivate classList + +addClassCommand -> storage : save(classList) +activate storage +storage --> addClassCommand +deactivate storage + +addClassCommand --> taa +deactivate addClassCommand + +taa --> user +deactivate taa + +@enduml \ No newline at end of file diff --git a/docs/diagrams/AddModuleSequenceDiagram.png b/docs/diagrams/AddModuleSequenceDiagram.png deleted file mode 100644 index d2deebb3f480f1ce2a1f1f05c552c4cee067494a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42870 zcmcG$bwE_x_dbjuAxNkoN+T+W0#ed7BA`ghfV7H8Ni%eZA}OdK-7*ZRbc+E<*U+Vd z#L(Tty9Y4uy`S&zpZA~370#S<_TFo)=ULBMYn~}9%90Y(5aZzBklvJ&R>i?NdKU)= z*N+Gn{Knx#gAn*}$?nEoI|EBAr^kkm>~LfaEevh$+ZjG&df>!lY-eXB%*AE(_`Zc5 z%=|H@fu;G0t3q@*IC!ciYIp5^{2u2BxQ%1%th$2IfFwnwc7w<3H<8lb6y<(Ce&--; zaK1|?2%M!55vwQFd(C>v$&#RZE=D~G)=hPlUp}w3#1vaTa(HBOp6aF=4FUZ$9yOnw z8-c1A;bV%J&msJ8*l&$$y*ujfOPN4#79t+I^qL4?cRku6_?ZByhVPlcbE)@*MN^N2 z+3=N7m4w6+P{;IKZ0ub(3QHh(eA18kM3q-~?Ssxsyo#l21Pl=gv+rr(#}=--zN@F; zap^H(R$IKFa)l(v;47ZJ?CYae_iJ9Z^k|$&NA%?0hXn{nwA_C-`{2Apew^2wf@ocl zgzgaW+ld?N=x67TSNY>p2VKy)Qa0IipW1EJK1YZ&p9Imh7V84oJa(cPR2Wbx;_dljv>186rRT6Sgvw1*{<7pJ+VkqA zpPpbJi7K{ubh*Aw_?tUg|T^~~|IX7wa9w}%0AaY`jYcuU9ckIxSW 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

n1HfvE@q5XLM5(|tJ<~U<)ug+n`dZH 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\nParser" as parser -Participant ":AddModuleCommand" as addModuleCommand -Participant ":ModuleList" as moduleList -Participant ":Module" as module -Participant ":Storage" as storage - -activate taa - -taa -> ui : getUserInput() -activate ui - -user -> ui : "add_module c/CS2113T\nn/Software Engineering" -ui --> taa : userInput:String -deactivate ui - -taa -> parser : parseUserInput(userInput) -activate parser - -create addModuleCommand -parser -> addModuleCommand -activate addModuleCommand -addModuleCommand -> parser -deactivate addModuleCommand - -parser --> taa : command:AddModuleCommand -deactivate parser - -taa -> addModuleCommand : checkArguments() -activate addModuleCommand - -addModuleCommand --> taa -deactivate addModuleCommand - -taa -> addModuleCommand : execute(moduleList:ModuleList, ui:Ui, storage:Storage) -activate addModuleCommand - -create module -addModuleCommand -> module -activate module -module --> addModuleCommand -deactivate module - -addModuleCommand -> moduleList : addModule(module:Module) -activate moduleList -moduleList --> addModuleCommand -deactivate moduleList - -addModuleCommand -> storage : save(moduleList:ModuleList) -activate storage -storage --> addModuleCommand -deactivate storage - -addModuleCommand -> ui : printMessage("Module added: ...") -activate ui -ui -> user : Display message:\n"Module added: ..." -ui --> addModuleCommand -deactivate ui - -deactivate addModuleCommand - -@enduml \ No newline at end of file diff --git a/docs/diagrams/ArchitectureDiagram.png b/docs/diagrams/ArchitectureDiagram.png index 9c9aa0fbbdd17b39d0298fe24ab59d8b08bb89a1..a408f098a060e556557a88dd6e616688d798134a 100644 GIT binary patch literal 16173 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 literal 16400 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 Cv=lf1 diff --git a/docs/diagrams/ArchitectureDiagram.puml b/docs/diagrams/ArchitectureDiagram.puml index e457636052..762394f214 100644 --- a/docs/diagrams/ArchitectureDiagram.puml +++ b/docs/diagrams/ArchitectureDiagram.puml @@ -21,7 +21,7 @@ Package " "<>{ Class Storage #DarkGoldenRod Class Main #IndianRed Class Command #DarkSlateBlue - Class ModuleList #DarkRed + Class ClassList #DarkRed Class Parser #Navy Class Util #LightSeaGreen } @@ -36,6 +36,6 @@ Command -up-> UI Command -down-> Storage Storage -up-> Taa Storage <-down-> File -Command <-right-> ModuleList +Command <-right-> ClassList @enduml diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml index de50d49f3d..9cfedeca10 100644 --- a/docs/diagrams/ArchitectureSequenceDiagram.puml +++ b/docs/diagrams/ArchitectureSequenceDiagram.puml @@ -7,24 +7,24 @@ Participant ":Taa" as taa Participant "<>\nParser" as parser Participant ":Command" as command Participant "<>\nUtil" as util -Participant ":ModuleList" as moduleList +Participant ":ClassList" as classList Participant ":Storage" as storage activate taa -taa -> taa : loadModuleListFromStorage() +taa -> taa : loadClassListFromStorage() activate taa taa -> storage : load() activate storage -create moduleList -storage -> moduleList -activate moduleList -moduleList --> storage -deactivate moduleList +create classList +storage -> classList +activate classList +classList --> storage +deactivate classList -storage --> taa : moduleList:ModuleList +storage --> taa : classList:ClassList deactivate storage taa --> taa @@ -61,7 +61,7 @@ deactivate util command --> taa deactivate command -taa -> command : execute(moduleList:ModuleList, ui:Ui,\n\tstorage:Storage) +taa -> command : execute(classList:ClassList,\n\tui:Ui, storage:Storage) activate command command -> util @@ -69,12 +69,12 @@ activate util util --> command deactivate util -command -> moduleList -activate moduleList -moduleList --> command -deactivate moduleList +command -> classList +activate classList +classList --> command +deactivate classList -command -> storage : save(moduleList:ModuleList) +command -> storage : save(classList) activate storage storage --> command deactivate storage From 602fe45954de8e6503cfc7fec4732dedb9688755 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 02:40:57 +0800 Subject: [PATCH 268/543] Update ArchitectureSequenceDiagram.png --- docs/diagrams/ArchitectureSequenceDiagram.png | Bin 54075 -> 52688 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/docs/diagrams/ArchitectureSequenceDiagram.png b/docs/diagrams/ArchitectureSequenceDiagram.png index 90e3db92d6919b5a32e90ba6f3a1b9036e07bb71..d4a2578d2346f8bda89c715caeb3b1dd622b1d62 100644 GIT binary patch literal 52688 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 literal 54075 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 Date: Sun, 31 Oct 2021 02:42:49 +0800 Subject: [PATCH 269/543] Update table of contents --- docs/DeveloperGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 50af23dbe8..3969536124 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -2,7 +2,7 @@ * [Acknowledgements](#acknowledgements) * [Design](#design) * [Implementation](#implementation) - * [Add Module](#add-module) + * [Add Class](#add-class) * [Add Student](#add-student) * [Add Assessment](#add-assessment) * [Set Marks](#set-marks) From 3f50466ab8c1599a0c70774e43f59d4ba50dd729 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 02:43:13 +0800 Subject: [PATCH 270/543] Fix wrong input in AddClassSequenceDiagram --- docs/diagrams/AddClassSequenceDiagram.png | Bin 22898 -> 22884 bytes docs/diagrams/AddClassSequenceDiagram.puml | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/diagrams/AddClassSequenceDiagram.png b/docs/diagrams/AddClassSequenceDiagram.png index 79b351a49e466eace504ebf04385a042974ac308..be0941d4851d4f5260add4253b8b6b79619874b4 100644 GIT binary patch literal 22884 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 PgCNzOu6{1-oD!M<`bI9u diff --git a/docs/diagrams/AddClassSequenceDiagram.puml b/docs/diagrams/AddClassSequenceDiagram.puml index 17eed79996..cebb1d80d4 100644 --- a/docs/diagrams/AddClassSequenceDiagram.puml +++ b/docs/diagrams/AddClassSequenceDiagram.puml @@ -8,7 +8,7 @@ Participant ":ClassList" as classList Participant ":ClassObject" as classObject Participant ":Storage" as storage -user -> taa : "add_class c/CS2113T-F12\nn/Tutorial Group F12" +user -> taa : "add_class i/CS2113T-F12\nn/Tutorial Group F12" activate taa taa -> addClassCommand : execute(classList:ClassList,\nui:Ui, storage:Storage) From 99a97efbd3736a202688fd466079bce10c05dc05 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 02:45:31 +0800 Subject: [PATCH 271/543] Add AddClassCommand object deletion in AddClassSequenceDiagram --- docs/diagrams/AddClassSequenceDiagram.png | Bin 22884 -> 23423 bytes docs/diagrams/AddClassSequenceDiagram.puml | 2 ++ 2 files changed, 2 insertions(+) diff --git a/docs/diagrams/AddClassSequenceDiagram.png b/docs/diagrams/AddClassSequenceDiagram.png index be0941d4851d4f5260add4253b8b6b79619874b4..5bb12769b2d09f6161105d78feb8a38e735634f9 100644 GIT binary patch literal 23423 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 literal 22884 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 taa deactivate addClassCommand +taa -[hidden]-> addClassCommand +destroy addClassCommand taa --> user deactivate taa From 1764cc395efb09c13f9085c9f2386c25e1c47fc4 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 02:50:32 +0800 Subject: [PATCH 272/543] Update automatic ui testing files --- text-ui-test/EXPECTED.TXT | 12 ++++++------ text-ui-test/input.txt | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index a120d9b79d..308ece4245 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -12,16 +12,16 @@ What can I do for you? Enter "help" to view the list of commands ------------------------------------------------------------ $ ------------------------------------------------------------ -There are no modules in the list. +There are no classes in the list. ------------------------------------------------------------ $ ------------------------------------------------------------ -Module added: - CS2113T - Software Engineering and Object-oriented Programming -There are 1 modules in the list. +Class added: + CS2113T-F12 - Tutorial Group F12 +There are 1 classes in the list. ------------------------------------------------------------ $ ------------------------------------------------------------ -Module list: -1. CS2113T - Software Engineering and Object-oriented Programming +Class list: +1. CS2113T-F12 - Tutorial Group F12 ------------------------------------------------------------ $ ------------------------------------------------------------ An exception has occurred: diff --git a/text-ui-test/input.txt b/text-ui-test/input.txt index d54660ce29..70c344e6ac 100644 --- a/text-ui-test/input.txt +++ b/text-ui-test/input.txt @@ -1,5 +1,5 @@ -list_modules -add_module c/CS2113T n/Software Engineering and Object-oriented Programming -list_modules +list_classes +add_class i/CS2113T-F12 n/Tutorial Group F12 +list_classes invalid_command exit \ No newline at end of file From 8bb4e9215af27fa1f83c9b2042b414ab63ea1c71 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 02:52:41 +0800 Subject: [PATCH 273/543] Remove wildcard import --- src/test/java/taa/util/UtilTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/taa/util/UtilTest.java b/src/test/java/taa/util/UtilTest.java index 2edc14b2f8..495f6a5107 100644 --- a/src/test/java/taa/util/UtilTest.java +++ b/src/test/java/taa/util/UtilTest.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.assertFalse; class UtilTest { From e820cde62ad9aff29308a0c42d7b16a82c553cb5 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 03:00:24 +0800 Subject: [PATCH 274/543] Update AssessmentListTest --- .../taa/assessment/AssessmentListTest.java | 60 +++++++++++++------ 1 file changed, 41 insertions(+), 19 deletions(-) diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index 18ee4fc74e..7ae0b01020 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -26,17 +26,21 @@ void addAssessment_userInput_assessmentAddedCorrectly() throws TaaException { Ui ui = new Ui(); Storage storage = new Storage("./data/taa_data.json"); ClassList classList = new ClassList(); - String moduleInput = "add_module c/cs2113t n/software engineering"; - String assessmentInput = "add_assessment c/cs2113t n/Midterms m/50 w/20"; - Command command1 = Parser.parseUserInput(moduleInput); + String classInput = "add_class i/cs2113t_f12 n/software engineering (class-f12)"; + String assessmentInput = "add_assessment c/cs2113t_f12 n/Midterms m/50 w/20"; + Command command1 = Parser.parseUserInput(classInput); + command1.parseArgument(); + command1.checkArgument(); command1.execute(classList, ui, storage); Command command2 = Parser.parseUserInput(assessmentInput); + command2.parseArgument(); + command2.checkArgument(); command2.execute(classList, ui, storage); - assertEquals("Midterms", classList.getClassWithId("cs2113t") + assertEquals("Midterms", classList.getClassWithId("cs2113t_f12") .getAssessmentList().getAssessment("Midterms").getName()); - assertEquals(50, classList.getClassWithId("cs2113t") + assertEquals(50, classList.getClassWithId("cs2113t_f12") .getAssessmentList().getAssessment("Midterms").getMaximumMarks()); - assertEquals(20, classList.getClassWithId("cs2113t") + assertEquals(20, classList.getClassWithId("cs2113t_f12") .getAssessmentList().getAssessment("Midterms").getWeightage()); } @@ -55,18 +59,24 @@ void deleteAssessment_userInput_emptyAssessmentList() throws TaaException { Ui ui = new Ui(); Storage storage = new Storage("./data/taa_data.json"); ClassList classList = new ClassList(); - String moduleInput = "add_module c/cs2113t n/software engineering"; - String assessmentInput = "add_assessment c/cs2113t n/Midterms m/50 w/20"; - String deleteAssessmentInput = "delete_assessment c/cs2113t n/Midterms"; - Command command1 = Parser.parseUserInput(moduleInput); + String classInput = "add_class i/cs2113t_f12 n/software engineering (F_12)"; + String assessmentInput = "add_assessment c/cs2113t_f12 n/Midterms m/50 w/20"; + String deleteAssessmentInput = "delete_assessment c/cs2113t_f12 n/Midterms"; + Command command1 = Parser.parseUserInput(classInput); + command1.parseArgument(); + command1.checkArgument(); command1.execute(classList, ui, storage); Command command2 = Parser.parseUserInput(assessmentInput); + command2.parseArgument(); + command2.checkArgument(); command2.execute(classList, ui, storage); Command command3 = Parser.parseUserInput(deleteAssessmentInput); + command3.parseArgument(); + command3.checkArgument(); command3.execute(classList, ui, storage); assertEquals( new AssessmentList().getSize(), - classList.getClassWithId("cs2113t").getAssessmentList().getSize() + classList.getClassWithId("cs2113t_f12").getAssessmentList().getSize() ); } @@ -75,28 +85,40 @@ void editAssessment_userInputFourEdits_assessmentEditedCorrectly() throws TaaExc Ui ui = new Ui(); Storage storage = new Storage("./data/taa_data.json"); ClassList classList = new ClassList(); - String moduleInput = "add_module c/cs2113t n/software engineering"; - String assessmentInput = "add_assessment c/cs2113t n/Midterms m/50 w/20"; - String editAssessment1 = "edit_assessment c/cs2113t n/midterms nn/finals"; - Command command1 = Parser.parseUserInput(moduleInput); + String classInput = "add_class i/cs2113t-f12 n/software engineering class F12"; + String assessmentInput = "add_assessment c/cs2113t-f12 n/Midterms m/50 w/20"; + String editAssessment1 = "edit_assessment c/cs2113t-f12 n/midterms nn/finals"; + Command command1 = Parser.parseUserInput(classInput); + command1.parseArgument(); + command1.checkArgument(); command1.execute(classList, ui, storage); Command command2 = Parser.parseUserInput(assessmentInput); + command2.parseArgument(); + command2.checkArgument(); command2.execute(classList, ui, storage); - Assessment assessment = classList.getClassWithId("cs2113t").getAssessmentList() + Assessment assessment = classList.getClassWithId("cs2113t-f12").getAssessmentList() .getAssessment("midterms"); Command command3 = Parser.parseUserInput(editAssessment1); + command3.parseArgument(); + command3.checkArgument(); command3.execute(classList, ui, storage); assertEquals("finals", assessment.getName()); - String editAssessment2 = "edit_assessment c/cs2113t n/finals m/100"; + String editAssessment2 = "edit_assessment c/cs2113t-f12 n/finals m/100"; Command command4 = Parser.parseUserInput(editAssessment2); + command4.parseArgument(); + command4.checkArgument(); command4.execute(classList, ui, storage); assertEquals(100, assessment.getMaximumMarks()); - String editAssessment3 = "edit_assessment c/cs2113t n/finals w/50"; + String editAssessment3 = "edit_assessment c/cs2113t-f12 n/finals w/50"; Command command5 = Parser.parseUserInput(editAssessment3); + command5.parseArgument(); + command5.checkArgument(); command5.execute(classList, ui, storage); assertEquals(50, assessment.getWeightage()); - String editAssessment4 = "edit_assessment c/cs2113t n/finals nn/midterms m/50 w/20"; + String editAssessment4 = "edit_assessment c/cs2113t-f12 n/finals nn/midterms m/50 w/20"; Command command6 = Parser.parseUserInput(editAssessment4); + command6.parseArgument(); + command6.checkArgument(); command6.execute(classList, ui, storage); assertEquals("midterms", assessment.getName()); assertEquals(50, assessment.getMaximumMarks()); From 659b4c27e16a435037f8b01168cef2432c0eecc3 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 03:06:23 +0800 Subject: [PATCH 275/543] Fix checkstyle --- .../taa/assessment/AssessmentListTest.java | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index 7ae0b01020..61cf605faf 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -27,15 +27,17 @@ void addAssessment_userInput_assessmentAddedCorrectly() throws TaaException { Storage storage = new Storage("./data/taa_data.json"); ClassList classList = new ClassList(); String classInput = "add_class i/cs2113t_f12 n/software engineering (class-f12)"; - String assessmentInput = "add_assessment c/cs2113t_f12 n/Midterms m/50 w/20"; Command command1 = Parser.parseUserInput(classInput); command1.parseArgument(); command1.checkArgument(); command1.execute(classList, ui, storage); + + String assessmentInput = "add_assessment c/cs2113t_f12 n/Midterms m/50 w/20"; Command command2 = Parser.parseUserInput(assessmentInput); command2.parseArgument(); command2.checkArgument(); command2.execute(classList, ui, storage); + assertEquals("Midterms", classList.getClassWithId("cs2113t_f12") .getAssessmentList().getAssessment("Midterms").getName()); assertEquals(50, classList.getClassWithId("cs2113t_f12") @@ -49,6 +51,7 @@ void deleteAssessment_deleteAssessmentArguments_assessmentDeletedCorrectly() thr AssessmentList assessments = new AssessmentList(); assessments.addAssessment(new Assessment("Midterms", 50, 20)); Assessment assessment = assessments.deleteAssessment("Midterms"); + assertEquals("Midterms", assessment.getName()); assertEquals(50, assessment.getMaximumMarks()); assertEquals(20, assessment.getWeightage()); @@ -60,20 +63,23 @@ void deleteAssessment_userInput_emptyAssessmentList() throws TaaException { Storage storage = new Storage("./data/taa_data.json"); ClassList classList = new ClassList(); String classInput = "add_class i/cs2113t_f12 n/software engineering (F_12)"; - String assessmentInput = "add_assessment c/cs2113t_f12 n/Midterms m/50 w/20"; - String deleteAssessmentInput = "delete_assessment c/cs2113t_f12 n/Midterms"; Command command1 = Parser.parseUserInput(classInput); command1.parseArgument(); command1.checkArgument(); command1.execute(classList, ui, storage); + + String assessmentInput = "add_assessment c/cs2113t_f12 n/Midterms m/50 w/20"; Command command2 = Parser.parseUserInput(assessmentInput); command2.parseArgument(); command2.checkArgument(); command2.execute(classList, ui, storage); + + String deleteAssessmentInput = "delete_assessment c/cs2113t_f12 n/Midterms"; Command command3 = Parser.parseUserInput(deleteAssessmentInput); command3.parseArgument(); command3.checkArgument(); command3.execute(classList, ui, storage); + assertEquals( new AssessmentList().getSize(), classList.getClassWithId("cs2113t_f12").getAssessmentList().getSize() @@ -86,40 +92,46 @@ void editAssessment_userInputFourEdits_assessmentEditedCorrectly() throws TaaExc Storage storage = new Storage("./data/taa_data.json"); ClassList classList = new ClassList(); String classInput = "add_class i/cs2113t-f12 n/software engineering class F12"; - String assessmentInput = "add_assessment c/cs2113t-f12 n/Midterms m/50 w/20"; - String editAssessment1 = "edit_assessment c/cs2113t-f12 n/midterms nn/finals"; Command command1 = Parser.parseUserInput(classInput); command1.parseArgument(); command1.checkArgument(); command1.execute(classList, ui, storage); + + String assessmentInput = "add_assessment c/cs2113t-f12 n/Midterms m/50 w/20"; Command command2 = Parser.parseUserInput(assessmentInput); command2.parseArgument(); command2.checkArgument(); command2.execute(classList, ui, storage); Assessment assessment = classList.getClassWithId("cs2113t-f12").getAssessmentList() .getAssessment("midterms"); + + String editAssessment1 = "edit_assessment c/cs2113t-f12 n/midterms nn/finals"; Command command3 = Parser.parseUserInput(editAssessment1); command3.parseArgument(); command3.checkArgument(); command3.execute(classList, ui, storage); assertEquals("finals", assessment.getName()); + String editAssessment2 = "edit_assessment c/cs2113t-f12 n/finals m/100"; Command command4 = Parser.parseUserInput(editAssessment2); command4.parseArgument(); command4.checkArgument(); command4.execute(classList, ui, storage); assertEquals(100, assessment.getMaximumMarks()); + String editAssessment3 = "edit_assessment c/cs2113t-f12 n/finals w/50"; Command command5 = Parser.parseUserInput(editAssessment3); command5.parseArgument(); command5.checkArgument(); command5.execute(classList, ui, storage); assertEquals(50, assessment.getWeightage()); + String editAssessment4 = "edit_assessment c/cs2113t-f12 n/finals nn/midterms m/50 w/20"; Command command6 = Parser.parseUserInput(editAssessment4); command6.parseArgument(); command6.checkArgument(); command6.execute(classList, ui, storage); + assertEquals("midterms", assessment.getName()); assertEquals(50, assessment.getMaximumMarks()); assertEquals(20, assessment.getWeightage()); From 4a03ffc0569bac572d805365191338d4602c9ed8 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 03:08:08 +0800 Subject: [PATCH 276/543] Fix checkstyle --- src/test/java/taa/assessment/AssessmentListTest.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index 61cf605faf..ab40246d52 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -102,14 +102,14 @@ void editAssessment_userInputFourEdits_assessmentEditedCorrectly() throws TaaExc command2.parseArgument(); command2.checkArgument(); command2.execute(classList, ui, storage); - Assessment assessment = classList.getClassWithId("cs2113t-f12").getAssessmentList() - .getAssessment("midterms"); String editAssessment1 = "edit_assessment c/cs2113t-f12 n/midterms nn/finals"; Command command3 = Parser.parseUserInput(editAssessment1); command3.parseArgument(); command3.checkArgument(); command3.execute(classList, ui, storage); + Assessment assessment = classList.getClassWithId("cs2113t-f12").getAssessmentList() + .getAssessment("midterms"); assertEquals("finals", assessment.getName()); String editAssessment2 = "edit_assessment c/cs2113t-f12 n/finals m/100"; @@ -131,7 +131,7 @@ void editAssessment_userInputFourEdits_assessmentEditedCorrectly() throws TaaExc command6.parseArgument(); command6.checkArgument(); command6.execute(classList, ui, storage); - + assertEquals("midterms", assessment.getName()); assertEquals(50, assessment.getMaximumMarks()); assertEquals(20, assessment.getWeightage()); From f068e6f9a5ea445276f2d1d514383283f3e6c8e6 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 03:14:33 +0800 Subject: [PATCH 277/543] Update ParserTest --- src/test/java/taa/ParserTest.java | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/test/java/taa/ParserTest.java b/src/test/java/taa/ParserTest.java index 7e606a300e..69c8cbbf0c 100644 --- a/src/test/java/taa/ParserTest.java +++ b/src/test/java/taa/ParserTest.java @@ -2,10 +2,12 @@ //@@author leyondlee import org.junit.jupiter.api.Test; +import taa.exception.DuplicatedArgumentException; import taa.exception.TaaException; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; class ParserTest { @@ -50,4 +52,29 @@ void getArgumentsFromString_TwoKeyAndOneEmptyValue_expectOneItem() throws TaaExc String[] keys = {"c","n"}; assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 2); } + + @Test + void getArgumentsFromString_duplicatedKeys_expectDuplicatedArgumentException() { + String inputString = "c/ n/Software Engineering and Object-oriented Programming c/Test"; + String[] keys = {"c","n"}; + assertThrows(DuplicatedArgumentException.class, ()->{ + Parser.getArgumentsFromString(inputString, keys); + }); + } + + @Test + void getArgumentsFromString_illegalCharacters_expectTaaException() { + String inputString = "c/hello&world n/Software Engineering and Object-oriented Programming"; + String[] keys = {"c","n"}; + assertThrows(TaaException.class, ()->{ + Parser.getArgumentsFromString(inputString, keys); + }); + } + + @Test + void getArgumentsFromString_legalCharacters_expectTwoItems() throws TaaException { + String inputString = "c/3654964apfaAFDao_()- n/65496494 649684aofaoAFAOFH9af_-(f0ew7r0FA_)f"; + String[] keys = {"c","n"}; + assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 2); + } } From bd02cb7f5e847e06029e05c01729621beaba0407 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 03:16:03 +0800 Subject: [PATCH 278/543] Update AssessmentListTest --- src/test/java/taa/assessment/AssessmentListTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index ab40246d52..74301c270a 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -109,7 +109,7 @@ void editAssessment_userInputFourEdits_assessmentEditedCorrectly() throws TaaExc command3.checkArgument(); command3.execute(classList, ui, storage); Assessment assessment = classList.getClassWithId("cs2113t-f12").getAssessmentList() - .getAssessment("midterms"); + .getAssessment("finals"); assertEquals("finals", assessment.getName()); String editAssessment2 = "edit_assessment c/cs2113t-f12 n/finals m/100"; From 3ddf201191319f0cd66d2fc6e8ad938fecbf4b0e Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 03:21:46 +0800 Subject: [PATCH 279/543] Fix checkstyle --- src/test/java/taa/ParserTest.java | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/test/java/taa/ParserTest.java b/src/test/java/taa/ParserTest.java index 69c8cbbf0c..00f2bdcb00 100644 --- a/src/test/java/taa/ParserTest.java +++ b/src/test/java/taa/ParserTest.java @@ -57,18 +57,14 @@ void getArgumentsFromString_TwoKeyAndOneEmptyValue_expectOneItem() throws TaaExc void getArgumentsFromString_duplicatedKeys_expectDuplicatedArgumentException() { String inputString = "c/ n/Software Engineering and Object-oriented Programming c/Test"; String[] keys = {"c","n"}; - assertThrows(DuplicatedArgumentException.class, ()->{ - Parser.getArgumentsFromString(inputString, keys); - }); + assertThrows(DuplicatedArgumentException.class, () -> Parser.getArgumentsFromString(inputString, keys)); } @Test void getArgumentsFromString_illegalCharacters_expectTaaException() { String inputString = "c/hello&world n/Software Engineering and Object-oriented Programming"; String[] keys = {"c","n"}; - assertThrows(TaaException.class, ()->{ - Parser.getArgumentsFromString(inputString, keys); - }); + assertThrows(TaaException.class, () -> Parser.getArgumentsFromString(inputString, keys)); } @Test From 9a8fc10757ea13d3bc30baafebf2d1b0817ecc08 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 03:23:45 +0800 Subject: [PATCH 280/543] Check if values contain valid characters --- src/main/java/taa/Parser.java | 2 +- src/main/java/taa/assessment/Assessment.java | 4 +++- src/main/java/taa/classmodel/ClassObject.java | 5 +++++ src/main/java/taa/student/Student.java | 3 ++- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index ae000d13c1..a55afc5f3c 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -266,7 +266,7 @@ public static HashMap getArgumentsFromString(String string, Stri return result; } - private static boolean isValueValid(String value) { + public static boolean isValueValid(String value) { if (value.isEmpty()) { return true; } diff --git a/src/main/java/taa/assessment/Assessment.java b/src/main/java/taa/assessment/Assessment.java index ff244df86a..ce5521721b 100644 --- a/src/main/java/taa/assessment/Assessment.java +++ b/src/main/java/taa/assessment/Assessment.java @@ -1,6 +1,7 @@ package taa.assessment; import taa.ClassChecker; +import taa.Parser; public class Assessment implements ClassChecker { public static final double[] WEIGHTAGE_RANGE = {0, 100}; @@ -73,7 +74,8 @@ public String toString() { */ @Override public boolean verify() { - if (name.isEmpty() || !isWeightageWithinRange(weightage) || maximumMarks < MINIMUM_MARKS) { + if (name.isEmpty() || !Parser.isValueValid(name) || !isWeightageWithinRange(weightage) + || maximumMarks < MINIMUM_MARKS) { return false; } diff --git a/src/main/java/taa/classmodel/ClassObject.java b/src/main/java/taa/classmodel/ClassObject.java index 0cf9745171..5f4e1945e6 100644 --- a/src/main/java/taa/classmodel/ClassObject.java +++ b/src/main/java/taa/classmodel/ClassObject.java @@ -2,6 +2,7 @@ //@@author leyondlee import taa.ClassChecker; +import taa.Parser; import taa.assessment.Assessment; import taa.assessment.AssessmentList; import taa.student.Student; @@ -77,6 +78,10 @@ public boolean verify() { return false; } + if (!Parser.isValueValid(id) || !Parser.isValueValid(id)) { + return false; + } + assert (assessmentList != null && studentList != null); HashMap assessmentMap = new HashMap<>(); diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index f6385a0148..170f9cb374 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -2,6 +2,7 @@ //@@author hozhenhong99 import taa.ClassChecker; +import taa.Parser; import taa.assessment.Assessment; import taa.assessment.AssessmentList; import taa.attendance.AttendanceList; @@ -154,6 +155,6 @@ public boolean marksExist(String assessmentName) { @Override public boolean verify() { - return !id.isEmpty() && !name.isEmpty(); + return !id.isEmpty() && !name.isEmpty() && Parser.isValueValid(id) && Parser.isValueValid(name); } } From 457f93e66af5bb75b82c01b25c1a07ee432b2eeb Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 19:02:35 +0800 Subject: [PATCH 281/543] Refactor ClassObject to TeachingClass --- src/main/java/taa/Parser.java | 8 ++-- src/main/java/taa/Taa.java | 2 +- src/main/java/taa/command/ArchiveCommand.java | 2 +- src/main/java/taa/command/Command.java | 2 +- src/main/java/taa/command/ExitCommand.java | 2 +- src/main/java/taa/command/HelpCommand.java | 10 ++--- src/main/java/taa/command/ResetCommand.java | 2 +- .../assessment/AddAssessmentCommand.java | 12 ++--- .../assessment/DeleteAssessmentCommand.java | 12 ++--- .../assessment/EditAssessmentCommand.java | 12 ++--- .../assessment/ListAssessmentsCommand.java | 12 ++--- .../attendance/DeleteAttendanceCommand.java | 12 ++--- .../attendance/ListAttendanceCommand.java | 10 ++--- .../ListLessonAttendanceCommand.java | 10 ++--- .../attendance/SetAttendanceCommand.java | 10 ++--- .../taa/command/mark/AverageMarksCommand.java | 20 ++++----- .../taa/command/mark/DeleteMarkCommand.java | 12 ++--- .../taa/command/mark/EditMarkCommand.java | 12 ++--- .../taa/command/mark/ListMarksCommand.java | 20 ++++----- .../taa/command/mark/MedianMarkCommand.java | 22 +++++----- .../java/taa/command/mark/SetMarkCommand.java | 12 ++--- .../command/student/AddStudentCommand.java | 10 ++--- .../command/student/DeleteCommentCommand.java | 10 ++--- .../command/student/DeleteStudentCommand.java | 12 ++--- .../command/student/EditStudentCommand.java | 12 ++--- .../command/student/FindStudentCommand.java | 10 ++--- .../command/student/ListCommentCommand.java | 10 ++--- .../command/student/ListStudentsCommand.java | 12 ++--- .../command/student/SetCommentCommand.java | 10 ++--- .../command/student/SortByScoresCommand.java | 12 ++--- .../AddClassCommand.java | 18 ++++---- .../DeleteClassCommand.java | 16 +++---- .../EditClassCommand.java | 16 +++---- .../ListClassesCommand.java | 4 +- src/main/java/taa/storage/Storage.java | 2 +- .../deserializer/ClassListDeserializer.java | 12 ++--- .../deserializer/ClassObjectDeserializer.java | 16 +++---- .../ClassList.java | 44 +++++++++---------- .../TeachingClass.java} | 6 +-- .../taa/assessment/AssessmentListTest.java | 2 +- 40 files changed, 225 insertions(+), 225 deletions(-) rename src/main/java/taa/command/{classcategory => teachingclass}/AddClassCommand.java (86%) rename src/main/java/taa/command/{classcategory => teachingclass}/DeleteClassCommand.java (83%) rename src/main/java/taa/command/{classcategory => teachingclass}/EditClassCommand.java (89%) rename src/main/java/taa/command/{classcategory => teachingclass}/ListClassesCommand.java (95%) rename src/main/java/taa/{classmodel => teachingclass}/ClassList.java (67%) rename src/main/java/taa/{classmodel/ClassObject.java => teachingclass/TeachingClass.java} (95%) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index a55afc5f3c..3078bed7bb 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -5,18 +5,18 @@ import taa.command.ResetCommand; import taa.command.assessment.AddAssessmentCommand; import taa.command.attendance.ListLessonAttendanceCommand; -import taa.command.classcategory.AddClassCommand; +import taa.command.teachingclass.AddClassCommand; import taa.command.student.AddStudentCommand; import taa.command.mark.AverageMarksCommand; import taa.command.Command; import taa.command.assessment.DeleteAssessmentCommand; import taa.command.attendance.DeleteAttendanceCommand; import taa.command.mark.DeleteMarkCommand; -import taa.command.classcategory.DeleteClassCommand; +import taa.command.teachingclass.DeleteClassCommand; import taa.command.student.DeleteStudentCommand; import taa.command.assessment.EditAssessmentCommand; import taa.command.mark.EditMarkCommand; -import taa.command.classcategory.EditClassCommand; +import taa.command.teachingclass.EditClassCommand; import taa.command.student.EditStudentCommand; import taa.command.ExitCommand; import taa.command.student.FindStudentCommand; @@ -24,7 +24,7 @@ import taa.command.assessment.ListAssessmentsCommand; import taa.command.attendance.ListAttendanceCommand; import taa.command.mark.ListMarksCommand; -import taa.command.classcategory.ListClassesCommand; +import taa.command.teachingclass.ListClassesCommand; import taa.command.student.ListStudentsCommand; import taa.command.mark.MedianMarkCommand; import taa.command.attendance.SetAttendanceCommand; diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index 55911a2d48..9c7d6761a2 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -1,7 +1,7 @@ package taa; //@@author leyondlee -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.command.Command; import taa.exception.TaaException; import taa.logger.TaaLogger; diff --git a/src/main/java/taa/command/ArchiveCommand.java b/src/main/java/taa/command/ArchiveCommand.java index 7ffa22b395..143bcf2645 100644 --- a/src/main/java/taa/command/ArchiveCommand.java +++ b/src/main/java/taa/command/ArchiveCommand.java @@ -4,7 +4,7 @@ import taa.Taa; import taa.Ui; import taa.exception.TaaException; -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.storage.Storage; import taa.util.Util; diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index f4a6b033cd..f783c30f51 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -1,7 +1,7 @@ package taa.command; //@@author leyondlee -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.storage.Storage; import taa.exception.TaaException; import taa.Parser; diff --git a/src/main/java/taa/command/ExitCommand.java b/src/main/java/taa/command/ExitCommand.java index 28dd5ccc1b..f4935f260d 100644 --- a/src/main/java/taa/command/ExitCommand.java +++ b/src/main/java/taa/command/ExitCommand.java @@ -1,7 +1,7 @@ package taa.command; //@@author leyondlee -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index 75338dd323..e69f5f0bce 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -2,7 +2,7 @@ //@@author leyondlee import taa.Ui; -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.command.assessment.AddAssessmentCommand; import taa.command.assessment.DeleteAssessmentCommand; import taa.command.assessment.EditAssessmentCommand; @@ -16,10 +16,10 @@ import taa.command.mark.ListMarksCommand; import taa.command.mark.MedianMarkCommand; import taa.command.mark.SetMarkCommand; -import taa.command.classcategory.AddClassCommand; -import taa.command.classcategory.DeleteClassCommand; -import taa.command.classcategory.EditClassCommand; -import taa.command.classcategory.ListClassesCommand; +import taa.command.teachingclass.AddClassCommand; +import taa.command.teachingclass.DeleteClassCommand; +import taa.command.teachingclass.EditClassCommand; +import taa.command.teachingclass.ListClassesCommand; import taa.command.student.AddStudentCommand; import taa.command.student.DeleteStudentCommand; import taa.command.student.EditStudentCommand; diff --git a/src/main/java/taa/command/ResetCommand.java b/src/main/java/taa/command/ResetCommand.java index 375ba952c7..f8010293b3 100644 --- a/src/main/java/taa/command/ResetCommand.java +++ b/src/main/java/taa/command/ResetCommand.java @@ -2,7 +2,7 @@ //@@author leyondlee import taa.Ui; -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.exception.TaaException; import taa.storage.Storage; diff --git a/src/main/java/taa/command/assessment/AddAssessmentCommand.java b/src/main/java/taa/command/assessment/AddAssessmentCommand.java index 287dcc24e5..aefe2d054e 100644 --- a/src/main/java/taa/command/assessment/AddAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/AddAssessmentCommand.java @@ -1,7 +1,7 @@ package taa.command.assessment; -import taa.classmodel.ClassList; -import taa.classmodel.ClassObject; +import taa.teachingclass.ClassList; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.storage.Storage; import taa.Ui; @@ -93,8 +93,8 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -111,7 +111,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep String name = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = new Assessment(name, maximumMarks, weightage); - AssessmentList assessmentList = classObject.getAssessmentList(); + AssessmentList assessmentList = teachingClass.getAssessmentList(); assert assessmentList != null : "assessment list should exist."; boolean isSuccessful = assessmentList.addAssessment(assessment); if (!isSuccessful) { @@ -123,7 +123,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assert ui != null : "ui should exist."; ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_ADDED, classId, - assessment, assessmentList.getSize(), classObject)); + assessment, assessmentList.getSize(), teachingClass)); } @Override diff --git a/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java b/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java index 5fe84defcc..10d92e4561 100644 --- a/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java @@ -3,8 +3,8 @@ import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; -import taa.classmodel.ClassList; -import taa.classmodel.ClassObject; +import taa.teachingclass.ClassList; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.exception.TaaException; import taa.storage.Storage; @@ -46,20 +46,20 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String name = argumentMap.get(KEY_ASSESSMENT_NAME); - AssessmentList assessmentList = classObject.getAssessmentList(); + AssessmentList assessmentList = teachingClass.getAssessmentList(); assert assessmentList != null : "assessment list should exist."; Assessment assessment = assessmentList.deleteAssessment(name); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } - ArrayList students = classObject.getStudentList().getStudents(); + ArrayList students = teachingClass.getStudentList().getStudents(); for (Student s : students) { if (s.marksExist(name)) { double marks = s.getMarks(name); diff --git a/src/main/java/taa/command/assessment/EditAssessmentCommand.java b/src/main/java/taa/command/assessment/EditAssessmentCommand.java index c5dbbac230..75403aca48 100644 --- a/src/main/java/taa/command/assessment/EditAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/EditAssessmentCommand.java @@ -2,8 +2,8 @@ import taa.Ui; import taa.assessment.Assessment; -import taa.classmodel.ClassList; -import taa.classmodel.ClassObject; +import taa.teachingclass.ClassList; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.exception.TaaException; import taa.storage.Storage; @@ -89,13 +89,13 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String name = argumentMap.get(KEY_ASSESSMENT_NAME); - Assessment assessment = classObject.getAssessmentList().getAssessment(name); + Assessment assessment = teachingClass.getAssessmentList().getAssessment(name); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } @@ -114,7 +114,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep ); } double totalNewWeightage = 0; - ArrayList assessments = classObject.getAssessmentList().getAssessments(); + ArrayList assessments = teachingClass.getAssessmentList().getAssessments(); for (Assessment a : assessments) { if (a.getName() != name) { totalNewWeightage += a.getWeightage(); diff --git a/src/main/java/taa/command/assessment/ListAssessmentsCommand.java b/src/main/java/taa/command/assessment/ListAssessmentsCommand.java index fca73f0a1b..e5a15a47dc 100644 --- a/src/main/java/taa/command/assessment/ListAssessmentsCommand.java +++ b/src/main/java/taa/command/assessment/ListAssessmentsCommand.java @@ -5,8 +5,8 @@ import taa.Ui; import taa.assessment.AssessmentList; import taa.exception.TaaException; -import taa.classmodel.ClassObject; -import taa.classmodel.ClassList; +import taa.teachingclass.TeachingClass; +import taa.teachingclass.ClassList; public class ListAssessmentsCommand extends Command { private static final String KEY_CLASS_ID = "c"; @@ -43,17 +43,17 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String message; - AssessmentList assessmentList = classObject.getAssessmentList(); + AssessmentList assessmentList = teachingClass.getAssessmentList(); if (assessmentList.getSize() == 0) { message = MESSAGE_LIST_EMPTY; } else { - message = String.format(MESSAGE_FORMAT_OUTPUT, classObject, assessmentList); + message = String.format(MESSAGE_FORMAT_OUTPUT, teachingClass, assessmentList); } ui.printMessage(message); diff --git a/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java b/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java index 54ea0696e4..ba6482afa6 100644 --- a/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java @@ -5,8 +5,8 @@ import taa.attendance.AttendanceList; import taa.command.Command; import taa.exception.TaaException; -import taa.classmodel.ClassObject; -import taa.classmodel.ClassList; +import taa.teachingclass.TeachingClass; +import taa.teachingclass.ClassList; import taa.storage.Storage; import taa.student.Student; import taa.util.Util; @@ -62,8 +62,8 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -71,8 +71,8 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - Student student = classObject.getStudentList().getStudentAt(studentIndex); - assert studentIndex >= 0 && studentIndex < classObject.getStudentList().getSize(); + Student student = teachingClass.getStudentList().getStudentAt(studentIndex); + assert studentIndex >= 0 && studentIndex < teachingClass.getStudentList().getSize(); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } diff --git a/src/main/java/taa/command/attendance/ListAttendanceCommand.java b/src/main/java/taa/command/attendance/ListAttendanceCommand.java index f782a351e9..c1373aba1c 100644 --- a/src/main/java/taa/command/attendance/ListAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/ListAttendanceCommand.java @@ -2,8 +2,8 @@ import taa.Ui; import taa.attendance.AttendanceList; -import taa.classmodel.ClassList; -import taa.classmodel.ClassObject; +import taa.teachingclass.ClassList; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.exception.TaaException; import taa.storage.Storage; @@ -51,8 +51,8 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -60,7 +60,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); diff --git a/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java b/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java index 1185d31ad8..79a1f5314c 100644 --- a/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java @@ -3,8 +3,8 @@ import taa.Ui; import taa.attendance.Attendance; import taa.attendance.LessonAttendanceList; -import taa.classmodel.ClassList; -import taa.classmodel.ClassObject; +import taa.teachingclass.ClassList; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.exception.TaaException; import taa.storage.Storage; @@ -51,8 +51,8 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -63,7 +63,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep throw new TaaException(MESSAGE_INVALID_LESSON_NUMBER); } - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); LessonAttendanceList lessonAttendances = new LessonAttendanceList(); lessonAttendances.setLessonAttendances(studentList, lessonNumber); diff --git a/src/main/java/taa/command/attendance/SetAttendanceCommand.java b/src/main/java/taa/command/attendance/SetAttendanceCommand.java index 2fef47fdd8..df4984534e 100644 --- a/src/main/java/taa/command/attendance/SetAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/SetAttendanceCommand.java @@ -1,12 +1,12 @@ package taa.command.attendance; import taa.attendance.AttendanceList; -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.command.Command; import taa.exception.TaaException; import taa.Ui; import taa.attendance.Attendance; -import taa.classmodel.ClassObject; +import taa.teachingclass.TeachingClass; import taa.storage.Storage; import taa.student.Student; import taa.student.StudentList; @@ -71,8 +71,8 @@ public void checkArgument() throws TaaException { */ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -80,7 +80,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); diff --git a/src/main/java/taa/command/mark/AverageMarksCommand.java b/src/main/java/taa/command/mark/AverageMarksCommand.java index dd1e480e53..d98270e2ae 100644 --- a/src/main/java/taa/command/mark/AverageMarksCommand.java +++ b/src/main/java/taa/command/mark/AverageMarksCommand.java @@ -1,7 +1,7 @@ package taa.command.mark; -import taa.classmodel.ClassObject; -import taa.classmodel.ClassList; +import taa.teachingclass.TeachingClass; +import taa.teachingclass.ClassList; import taa.command.Command; import taa.storage.Storage; import taa.assessment.Assessment; @@ -50,33 +50,33 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); if (studentList.getSize() <= 0) { throw new TaaException(MESSAGE_NO_STUDENTS); } - AssessmentList assessmentList = classObject.getAssessmentList(); + AssessmentList assessmentList = teachingClass.getAssessmentList(); Assessment assessment = assessmentList.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } - printAverageMarks(ui, classObject, assessment); + printAverageMarks(ui, teachingClass, assessment); } /** * Outputs the average marks of an assessment in a class. * * @param ui The ui instance to handle interactions with the user. - * @param classObject The class the assessment belongs to. + * @param teachingClass The class the assessment belongs to. */ - private void printAverageMarks(Ui ui, ClassObject classObject, Assessment assessment) { - StudentList studentList = classObject.getStudentList(); + private void printAverageMarks(Ui ui, TeachingClass teachingClass, Assessment assessment) { + StudentList studentList = teachingClass.getStudentList(); String assessmentName = assessment.getName(); double classSize = studentList.getSize(); diff --git a/src/main/java/taa/command/mark/DeleteMarkCommand.java b/src/main/java/taa/command/mark/DeleteMarkCommand.java index 1998cee80e..d71400ebe5 100644 --- a/src/main/java/taa/command/mark/DeleteMarkCommand.java +++ b/src/main/java/taa/command/mark/DeleteMarkCommand.java @@ -3,8 +3,8 @@ import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; -import taa.classmodel.ClassList; -import taa.classmodel.ClassObject; +import taa.teachingclass.ClassList; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.exception.TaaException; import taa.storage.Storage; @@ -57,8 +57,8 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -66,13 +66,13 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - AssessmentList assessmentList = classObject.getAssessmentList(); + AssessmentList assessmentList = teachingClass.getAssessmentList(); String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = assessmentList.getAssessment(assessmentName); if (assessment == null) { diff --git a/src/main/java/taa/command/mark/EditMarkCommand.java b/src/main/java/taa/command/mark/EditMarkCommand.java index b01a05a7ff..c4d083d415 100644 --- a/src/main/java/taa/command/mark/EditMarkCommand.java +++ b/src/main/java/taa/command/mark/EditMarkCommand.java @@ -3,8 +3,8 @@ import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; -import taa.classmodel.ClassList; -import taa.classmodel.ClassObject; +import taa.teachingclass.ClassList; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.exception.TaaException; import taa.storage.Storage; @@ -66,21 +66,21 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - AssessmentList assessmentList = classObject.getAssessmentList(); + AssessmentList assessmentList = teachingClass.getAssessmentList(); String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = assessmentList.getAssessment(assessmentName); if (assessment == null) { diff --git a/src/main/java/taa/command/mark/ListMarksCommand.java b/src/main/java/taa/command/mark/ListMarksCommand.java index b6a3a0cfb0..f1d2cc5a01 100644 --- a/src/main/java/taa/command/mark/ListMarksCommand.java +++ b/src/main/java/taa/command/mark/ListMarksCommand.java @@ -1,13 +1,13 @@ package taa.command.mark; -import taa.classmodel.ClassObject; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.storage.Storage; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; import taa.exception.TaaException; -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.student.Student; import taa.student.StudentList; @@ -50,23 +50,23 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); if (studentList.getSize() <= 0) { throw new TaaException(MESSAGE_NO_STUDENTS); } - AssessmentList assessmentList = classObject.getAssessmentList(); + AssessmentList assessmentList = teachingClass.getAssessmentList(); Assessment assessment = assessmentList.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } - listMarks(ui, classObject, assessment); + listMarks(ui, teachingClass, assessment); } /** @@ -84,10 +84,10 @@ public String marksToString(String studentName, double marks) { * Lists the student and the marks they attained for an assessment. * * @param ui The ui instance to handle interactions with the user. - * @param classObject The class that the student and assessment belong to. + * @param teachingClass The class that the student and assessment belong to. */ - private void listMarks(Ui ui, ClassObject classObject, Assessment assessment) { - StudentList studentList = classObject.getStudentList(); + private void listMarks(Ui ui, TeachingClass teachingClass, Assessment assessment) { + StudentList studentList = teachingClass.getStudentList(); String assessmentName = assessment.getName(); StringBuilder stringBuilder = new StringBuilder(String.format(MESSAGE_LIST_MARKS_HEADER, assessmentName)); diff --git a/src/main/java/taa/command/mark/MedianMarkCommand.java b/src/main/java/taa/command/mark/MedianMarkCommand.java index d763a12dc9..82c57554cb 100644 --- a/src/main/java/taa/command/mark/MedianMarkCommand.java +++ b/src/main/java/taa/command/mark/MedianMarkCommand.java @@ -3,10 +3,10 @@ import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; -import taa.classmodel.ClassObject; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.exception.TaaException; -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.storage.Storage; import taa.student.Student; import taa.student.StudentList; @@ -54,39 +54,39 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); if (studentList.getSize() <= 0) { throw new TaaException(MESSAGE_NO_STUDENTS); } - AssessmentList assessmentList = classObject.getAssessmentList(); + AssessmentList assessmentList = teachingClass.getAssessmentList(); Assessment assessment = assessmentList.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } - ArrayList students = classObject.getStudentList().getStudents(); + ArrayList students = teachingClass.getStudentList().getStudents(); ArrayList studentsClone = new ArrayList<>(); for (Student student : students) { Student clonedStudent = new Student(student.getId(), student.getName()); clonedStudent.setMarks(assessment.getName(), student.getMarks(assessment.getName())); studentsClone.add(clonedStudent); } - printMedianMarks(ui, classObject, assessment, studentsClone); + printMedianMarks(ui, teachingClass, assessment, studentsClone); } /** * Outputs the median marks of an assessment in a class. * * @param ui The ui instance to handle interactions with the user. - * @param classObject The class the assessment belongs to. + * @param teachingClass The class the assessment belongs to. */ - private void printMedianMarks(Ui ui, ClassObject classObject, Assessment assessment, ArrayList students) { - StudentList studentList = classObject.getStudentList(); + private void printMedianMarks(Ui ui, TeachingClass teachingClass, Assessment assessment, ArrayList students) { + StudentList studentList = teachingClass.getStudentList(); String assessmentName = assessment.getName(); double classSize = studentList.getSize(); int printIterator = 1; diff --git a/src/main/java/taa/command/mark/SetMarkCommand.java b/src/main/java/taa/command/mark/SetMarkCommand.java index 2375abc24f..83e0b3697f 100644 --- a/src/main/java/taa/command/mark/SetMarkCommand.java +++ b/src/main/java/taa/command/mark/SetMarkCommand.java @@ -1,13 +1,13 @@ package taa.command.mark; -import taa.classmodel.ClassObject; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.storage.Storage; import taa.Ui; import taa.assessment.Assessment; import taa.assessment.AssessmentList; import taa.exception.TaaException; -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.student.Student; import taa.student.StudentList; import taa.util.Util; @@ -69,21 +69,21 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String studentIndexInput = argumentMap.get(KEY_STUDENT_INDEX); assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - AssessmentList assessmentList = classObject.getAssessmentList(); + AssessmentList assessmentList = teachingClass.getAssessmentList(); String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = assessmentList.getAssessment(assessmentName); if (assessment == null) { diff --git a/src/main/java/taa/command/student/AddStudentCommand.java b/src/main/java/taa/command/student/AddStudentCommand.java index a12afa5ffb..dfddfd0c73 100644 --- a/src/main/java/taa/command/student/AddStudentCommand.java +++ b/src/main/java/taa/command/student/AddStudentCommand.java @@ -1,8 +1,8 @@ package taa.command.student; //@@author hozhenhong99 -import taa.classmodel.ClassList; -import taa.classmodel.ClassObject; +import taa.teachingclass.ClassList; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; @@ -46,8 +46,8 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -55,7 +55,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep String studentName = argumentMap.get(KEY_STUDENT_NAME); Student student = new Student(studentID, studentName); - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); studentList.addStudent(student); storage.save(classList); diff --git a/src/main/java/taa/command/student/DeleteCommentCommand.java b/src/main/java/taa/command/student/DeleteCommentCommand.java index 0cbcc1021f..c7635d9fbc 100644 --- a/src/main/java/taa/command/student/DeleteCommentCommand.java +++ b/src/main/java/taa/command/student/DeleteCommentCommand.java @@ -1,8 +1,8 @@ package taa.command.student; //@@author hozhenhong99 -import taa.classmodel.ClassObject; -import taa.classmodel.ClassList; +import taa.teachingclass.TeachingClass; +import taa.teachingclass.ClassList; import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; @@ -50,8 +50,8 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -59,7 +59,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); diff --git a/src/main/java/taa/command/student/DeleteStudentCommand.java b/src/main/java/taa/command/student/DeleteStudentCommand.java index 1077733824..7e18970d67 100644 --- a/src/main/java/taa/command/student/DeleteStudentCommand.java +++ b/src/main/java/taa/command/student/DeleteStudentCommand.java @@ -1,12 +1,12 @@ package taa.command.student; //@@author hozhenhong99 -import taa.classmodel.ClassObject; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.student.Student; import taa.student.StudentList; import taa.util.Util; @@ -50,8 +50,8 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -59,8 +59,8 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = classObject.getStudentList(); - assert studentIndex >= 0 && studentIndex < classObject.getStudentList().getSize(); + StudentList studentList = teachingClass.getStudentList(); + assert studentIndex >= 0 && studentIndex < teachingClass.getStudentList().getSize(); Student student = studentList.deleteStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); diff --git a/src/main/java/taa/command/student/EditStudentCommand.java b/src/main/java/taa/command/student/EditStudentCommand.java index 202c973d6c..229bc251e7 100644 --- a/src/main/java/taa/command/student/EditStudentCommand.java +++ b/src/main/java/taa/command/student/EditStudentCommand.java @@ -1,8 +1,8 @@ package taa.command.student; //@@author hozhenhong99 -import taa.classmodel.ClassObject; -import taa.classmodel.ClassList; +import taa.teachingclass.TeachingClass; +import taa.teachingclass.ClassList; import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; @@ -58,8 +58,8 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -67,8 +67,8 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = classObject.getStudentList(); - assert studentIndex >= 0 && studentIndex < classObject.getStudentList().getSize(); + StudentList studentList = teachingClass.getStudentList(); + assert studentIndex >= 0 && studentIndex < teachingClass.getStudentList().getSize(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); diff --git a/src/main/java/taa/command/student/FindStudentCommand.java b/src/main/java/taa/command/student/FindStudentCommand.java index facdae22a0..64933f82c3 100644 --- a/src/main/java/taa/command/student/FindStudentCommand.java +++ b/src/main/java/taa/command/student/FindStudentCommand.java @@ -5,8 +5,8 @@ import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.classmodel.ClassObject; -import taa.classmodel.ClassList; +import taa.teachingclass.TeachingClass; +import taa.teachingclass.ClassList; import taa.student.Student; import taa.student.StudentList; @@ -48,13 +48,13 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String keyword = argumentMap.get(KEY_KEYWORD); - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); ArrayList studentsFound = studentList.findStudents(keyword); if (studentsFound.isEmpty()) { throw new TaaException(MESSAGE_NO_STUDENTS_FOUND); diff --git a/src/main/java/taa/command/student/ListCommentCommand.java b/src/main/java/taa/command/student/ListCommentCommand.java index 83002bc737..4169c31360 100644 --- a/src/main/java/taa/command/student/ListCommentCommand.java +++ b/src/main/java/taa/command/student/ListCommentCommand.java @@ -2,8 +2,8 @@ //@@author hozhenhong99 import taa.Ui; -import taa.classmodel.ClassList; -import taa.classmodel.ClassObject; +import taa.teachingclass.ClassList; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.exception.TaaException; import taa.storage.Storage; @@ -44,12 +44,12 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } - ArrayList students = classObject.getStudentList().getStudents(); + ArrayList students = teachingClass.getStudentList().getStudents(); StringBuilder stringBuilder = new StringBuilder(MESSAGE_LIST_COMMENT_HEADER); int studentIndex = 1; for (Student student : students) { diff --git a/src/main/java/taa/command/student/ListStudentsCommand.java b/src/main/java/taa/command/student/ListStudentsCommand.java index 3015004c8e..e3be534da6 100644 --- a/src/main/java/taa/command/student/ListStudentsCommand.java +++ b/src/main/java/taa/command/student/ListStudentsCommand.java @@ -1,12 +1,12 @@ package taa.command.student; //@@author hozhenhong99 -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.classmodel.ClassObject; +import taa.teachingclass.TeachingClass; import taa.student.StudentList; public class ListStudentsCommand extends Command { @@ -44,17 +44,17 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String message; - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); if (studentList.getSize() == 0) { message = MESSAGE_NO_STUDENTS; } else { - message = String.format(MESSAGE_FORMAT_OUTPUT, classObject, studentList); + message = String.format(MESSAGE_FORMAT_OUTPUT, teachingClass, studentList); } ui.printMessage(message); diff --git a/src/main/java/taa/command/student/SetCommentCommand.java b/src/main/java/taa/command/student/SetCommentCommand.java index 6b1471ee30..9258963765 100644 --- a/src/main/java/taa/command/student/SetCommentCommand.java +++ b/src/main/java/taa/command/student/SetCommentCommand.java @@ -1,12 +1,12 @@ package taa.command.student; //@@author hozhenhong99 -import taa.classmodel.ClassObject; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.student.Student; import taa.student.StudentList; import taa.util.Util; @@ -52,8 +52,8 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -61,7 +61,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assert Util.isStringInteger(studentIndexInput); int studentIndex = Integer.parseInt(studentIndexInput) - 1; - StudentList studentList = classObject.getStudentList(); + StudentList studentList = teachingClass.getStudentList(); Student student = studentList.getStudentAt(studentIndex); if (student == null) { throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); diff --git a/src/main/java/taa/command/student/SortByScoresCommand.java b/src/main/java/taa/command/student/SortByScoresCommand.java index bdb5d7b816..bce598eac1 100644 --- a/src/main/java/taa/command/student/SortByScoresCommand.java +++ b/src/main/java/taa/command/student/SortByScoresCommand.java @@ -6,8 +6,8 @@ import taa.assessment.AssessmentList; import taa.command.Command; import taa.exception.TaaException; -import taa.classmodel.ClassObject; -import taa.classmodel.ClassList; +import taa.teachingclass.TeachingClass; +import taa.teachingclass.ClassList; import taa.storage.Storage; import taa.student.Student; @@ -44,8 +44,8 @@ public void checkArgument() throws TaaException { @Override public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -53,8 +53,8 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep if (!order.equalsIgnoreCase("asc") && !order.equalsIgnoreCase("desc")) { throw new TaaException(MESSAGE_INVALID_SORT_ORDER); } - ArrayList students = classObject.getStudentList().getStudents(); - AssessmentList assessmentList = classObject.getAssessmentList(); + ArrayList students = teachingClass.getStudentList().getStudents(); + AssessmentList assessmentList = teachingClass.getAssessmentList(); HashMap unsortedScores = new HashMap<>(); ArrayList sortedStudents = new ArrayList<>(); for (Student student : students) { diff --git a/src/main/java/taa/command/classcategory/AddClassCommand.java b/src/main/java/taa/command/teachingclass/AddClassCommand.java similarity index 86% rename from src/main/java/taa/command/classcategory/AddClassCommand.java rename to src/main/java/taa/command/teachingclass/AddClassCommand.java index 89e9aa3aee..90301171d9 100644 --- a/src/main/java/taa/command/classcategory/AddClassCommand.java +++ b/src/main/java/taa/command/teachingclass/AddClassCommand.java @@ -1,8 +1,8 @@ -package taa.command.classcategory; +package taa.command.teachingclass; //@@author leyondlee -import taa.classmodel.ClassObject; -import taa.classmodel.ClassList; +import taa.teachingclass.TeachingClass; +import taa.teachingclass.ClassList; import taa.command.Command; import taa.logger.TaaLogger; import taa.storage.Storage; @@ -53,19 +53,19 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assert argumentMap.containsKey(KEY_CLASS_ID); String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject != null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass != null) { throw new TaaException(MESSAGE_CLASS_EXISTS); } String name = argumentMap.getOrDefault(KEY_CLASS_NAME, ""); - classObject = new ClassObject(classId, name); - classList.addClass(classObject); + teachingClass = new TeachingClass(classId, name); + classList.addClass(teachingClass); - TaaLogger.LOGGER.logInfo(String.format("Added class: %s", classObject)); + TaaLogger.LOGGER.logInfo(String.format("Added class: %s", teachingClass)); storage.save(classList); - ui.printMessage(String.format(MESSAGE_FORMAT_CLASS_ADDED, classObject, classList.getSize())); + ui.printMessage(String.format(MESSAGE_FORMAT_CLASS_ADDED, teachingClass, classList.getSize())); } @Override diff --git a/src/main/java/taa/command/classcategory/DeleteClassCommand.java b/src/main/java/taa/command/teachingclass/DeleteClassCommand.java similarity index 83% rename from src/main/java/taa/command/classcategory/DeleteClassCommand.java rename to src/main/java/taa/command/teachingclass/DeleteClassCommand.java index 213e699c11..365ca354d3 100644 --- a/src/main/java/taa/command/classcategory/DeleteClassCommand.java +++ b/src/main/java/taa/command/teachingclass/DeleteClassCommand.java @@ -1,9 +1,9 @@ -package taa.command.classcategory; +package taa.command.teachingclass; //@@author leyondlee import taa.Ui; -import taa.classmodel.ClassList; -import taa.classmodel.ClassObject; +import taa.teachingclass.ClassList; +import taa.teachingclass.TeachingClass; import taa.command.Command; import taa.exception.TaaException; import taa.storage.Storage; @@ -35,17 +35,17 @@ public void checkArgument() throws TaaException { public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { assert argumentMap.containsKey(KEY_CLASS_ID); String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } String message; - boolean isSuccessful = classList.deleteClass(classObject); + boolean isSuccessful = classList.deleteClass(teachingClass); if (isSuccessful) { - message = String.format(MESSAGE_FORMAT_CLASS_DELETED, classObject); + message = String.format(MESSAGE_FORMAT_CLASS_DELETED, teachingClass); } else { - message = String.format(MESSAGE_FORMAT_DELETE_FAILED, classObject); + message = String.format(MESSAGE_FORMAT_DELETE_FAILED, teachingClass); } storage.save(classList); diff --git a/src/main/java/taa/command/classcategory/EditClassCommand.java b/src/main/java/taa/command/teachingclass/EditClassCommand.java similarity index 89% rename from src/main/java/taa/command/classcategory/EditClassCommand.java rename to src/main/java/taa/command/teachingclass/EditClassCommand.java index 7778217ff5..5d5d4e583a 100644 --- a/src/main/java/taa/command/classcategory/EditClassCommand.java +++ b/src/main/java/taa/command/teachingclass/EditClassCommand.java @@ -1,9 +1,9 @@ -package taa.command.classcategory; +package taa.command.teachingclass; //@@author leyondlee import taa.Ui; -import taa.classmodel.ClassObject; -import taa.classmodel.ClassList; +import taa.teachingclass.TeachingClass; +import taa.teachingclass.ClassList; import taa.command.Command; import taa.exception.TaaException; import taa.storage.Storage; @@ -50,8 +50,8 @@ public void checkArgument() throws TaaException { public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { assert argumentMap.containsKey(KEY_CLASS_ID); String classId = argumentMap.get(KEY_CLASS_ID); - ClassObject classObject = classList.getClassWithId(classId); - if (classObject == null) { + TeachingClass teachingClass = classList.getClassWithId(classId); + if (teachingClass == null) { throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } @@ -62,17 +62,17 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep throw new TaaException(String.format(MESSAGE_FORMAT_CLASS_EXISTS, newClassId)); } - classObject.setId(newClassId); + teachingClass.setId(newClassId); } String newClassName = argumentMap.getOrDefault(KEY_NEW_CLASS_NAME, null); if (newClassName != null) { - classObject.setName(newClassName); + teachingClass.setName(newClassName); } storage.save(classList); - ui.printMessage(String.format(MESSAGE_FORMAT_CLASS_EDITED, classObject)); + ui.printMessage(String.format(MESSAGE_FORMAT_CLASS_EDITED, teachingClass)); } @Override diff --git a/src/main/java/taa/command/classcategory/ListClassesCommand.java b/src/main/java/taa/command/teachingclass/ListClassesCommand.java similarity index 95% rename from src/main/java/taa/command/classcategory/ListClassesCommand.java rename to src/main/java/taa/command/teachingclass/ListClassesCommand.java index 42857bad67..bfb63cb688 100644 --- a/src/main/java/taa/command/classcategory/ListClassesCommand.java +++ b/src/main/java/taa/command/teachingclass/ListClassesCommand.java @@ -1,11 +1,11 @@ -package taa.command.classcategory; +package taa.command.teachingclass; //@@author leyondlee import taa.command.Command; import taa.storage.Storage; import taa.exception.TaaException; import taa.Ui; -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; public class ListClassesCommand extends Command { private static final String MESSAGE_LIST_EMPTY = "There are no classes in the list."; diff --git a/src/main/java/taa/storage/Storage.java b/src/main/java/taa/storage/Storage.java index 61908df978..46c266617d 100644 --- a/src/main/java/taa/storage/Storage.java +++ b/src/main/java/taa/storage/Storage.java @@ -7,7 +7,7 @@ import com.google.gson.JsonSyntaxException; import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.exception.TaaException; import taa.storage.deserializer.ClassListDeserializer; import taa.util.Util; diff --git a/src/main/java/taa/storage/deserializer/ClassListDeserializer.java b/src/main/java/taa/storage/deserializer/ClassListDeserializer.java index 7d56708959..9f58f7752b 100644 --- a/src/main/java/taa/storage/deserializer/ClassListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/ClassListDeserializer.java @@ -9,8 +9,8 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; -import taa.classmodel.ClassList; -import taa.classmodel.ClassObject; +import taa.teachingclass.ClassList; +import taa.teachingclass.TeachingClass; import java.lang.reflect.Type; @@ -32,15 +32,15 @@ public ClassList deserialize(JsonElement json, Type typeOfT, JsonDeserialization } GsonBuilder gsonBuilder = new GsonBuilder(); - gsonBuilder.registerTypeAdapter(ClassObject.class, new ClassObjectDeserializer()); + gsonBuilder.registerTypeAdapter(TeachingClass.class, new ClassObjectDeserializer()); Gson gson = gsonBuilder.create(); ClassList classList = new ClassList(); JsonArray modulesJsonArray = modulesJson.getAsJsonArray(); for (JsonElement moduleJson : modulesJsonArray) { - ClassObject classObject = gson.fromJson(moduleJson, ClassObject.class); - if (classObject != null) { - classList.addClass(classObject); + TeachingClass teachingClass = gson.fromJson(moduleJson, TeachingClass.class); + if (teachingClass != null) { + classList.addClass(teachingClass); } } diff --git a/src/main/java/taa/storage/deserializer/ClassObjectDeserializer.java b/src/main/java/taa/storage/deserializer/ClassObjectDeserializer.java index 77fb820378..717e48ceaa 100644 --- a/src/main/java/taa/storage/deserializer/ClassObjectDeserializer.java +++ b/src/main/java/taa/storage/deserializer/ClassObjectDeserializer.java @@ -10,13 +10,13 @@ import com.google.gson.JsonParseException; import taa.assessment.Assessment; import taa.assessment.AssessmentList; -import taa.classmodel.ClassObject; +import taa.teachingclass.TeachingClass; import taa.student.Student; import taa.student.StudentList; import java.lang.reflect.Type; -public class ClassObjectDeserializer extends StorageDeserializer implements JsonDeserializer { +public class ClassObjectDeserializer extends StorageDeserializer implements JsonDeserializer { private static final String MEMBER_ID = "id"; private static final String MEMBER_NAME = "name"; private static final String MEMBER_STUDENTLIST = "studentList"; @@ -24,7 +24,7 @@ public class ClassObjectDeserializer extends StorageDeserializer implements Json private static final String[] COMPULSORY_MEMBERS = {MEMBER_ID, MEMBER_NAME}; @Override - public ClassObject deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) + public TeachingClass deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { JsonObject jsonObject = json.getAsJsonObject(); if (!hasMembers(jsonObject, COMPULSORY_MEMBERS)) { @@ -37,7 +37,7 @@ public ClassObject deserialize(JsonElement json, Type typeOfT, JsonDeserializati JsonElement nameJson = jsonObject.get(MEMBER_NAME); String name = nameJson.getAsString(); - ClassObject classObject = new ClassObject(id, name); + TeachingClass teachingClass = new TeachingClass(id, name); GsonBuilder gsonBuilder = new GsonBuilder(); gsonBuilder.registerTypeAdapter(StudentList.class, new StudentListDeserializer()); @@ -49,7 +49,7 @@ public ClassObject deserialize(JsonElement json, Type typeOfT, JsonDeserializati StudentList studentList = gson.fromJson(studentListJson, StudentList.class); if (studentList != null) { for (Student student : studentList.getStudents()) { - classObject.getStudentList().addStudent(student); + teachingClass.getStudentList().addStudent(student); } } } @@ -59,15 +59,15 @@ public ClassObject deserialize(JsonElement json, Type typeOfT, JsonDeserializati AssessmentList assessmentList = gson.fromJson(assessmentListJson, AssessmentList.class); if (assessmentList != null) { for (Assessment assessment : assessmentList.getAssessments()) { - classObject.getAssessmentList().addAssessment(assessment); + teachingClass.getAssessmentList().addAssessment(assessment); } } } - if (!classObject.verify()) { + if (!teachingClass.verify()) { return null; } - return classObject; + return teachingClass; } } diff --git a/src/main/java/taa/classmodel/ClassList.java b/src/main/java/taa/teachingclass/ClassList.java similarity index 67% rename from src/main/java/taa/classmodel/ClassList.java rename to src/main/java/taa/teachingclass/ClassList.java index 8587b7c891..eedc031915 100644 --- a/src/main/java/taa/classmodel/ClassList.java +++ b/src/main/java/taa/teachingclass/ClassList.java @@ -1,4 +1,4 @@ -package taa.classmodel; +package taa.teachingclass; //@@author leyondlee import taa.ClassChecker; @@ -6,7 +6,7 @@ import java.util.ArrayList; public class ClassList implements ClassChecker { - private final ArrayList classes; + private final ArrayList classes; public ClassList() { this.classes = new ArrayList<>(); @@ -21,7 +21,7 @@ public int getSize() { * * @return A new ArrayList containing all the classes. */ - public ArrayList getClasses() { + public ArrayList getClasses() { return new ArrayList<>(classes); } @@ -38,10 +38,10 @@ public boolean isValidIndex(int index) { /** * Adds a ClassObject object to the list of classes. * - * @param classObject The ClassObject object to add. + * @param teachingClass The ClassObject object to add. */ - public void addClass(ClassObject classObject) { - classes.add(classObject); + public void addClass(TeachingClass teachingClass) { + classes.add(teachingClass); } /** @@ -50,7 +50,7 @@ public void addClass(ClassObject classObject) { * @param index The index of the class. * @return A ClassObject object if index is valid, else null. */ - public ClassObject getClassAt(int index) { + public TeachingClass getClassAt(int index) { if (isValidIndex(index)) { return classes.get(index); } @@ -64,10 +64,10 @@ public ClassObject getClassAt(int index) { * @param id The class id to search for. * @return A Class object if found, else null. */ - public ClassObject getClassWithId(String id) { - for (ClassObject classObject : classes) { - if (classObject.getId().equals(id)) { - return classObject; + public TeachingClass getClassWithId(String id) { + for (TeachingClass teachingClass : classes) { + if (teachingClass.getId().equals(id)) { + return teachingClass; } } @@ -77,13 +77,13 @@ public ClassObject getClassWithId(String id) { /** * Deletes a particular class from the list. * - * @param classObject The class object to delete. + * @param teachingClass The class object to delete. * @return true if successfully removed, else false. */ - public boolean deleteClass(ClassObject classObject) { - assert classObject != null; + public boolean deleteClass(TeachingClass teachingClass) { + assert teachingClass != null; - return classes.remove(classObject); + return classes.remove(teachingClass); } public void deleteAllClasses() { @@ -114,17 +114,17 @@ public String toString() { @Override public boolean verify() { ArrayList classIds = new ArrayList<>(); - ArrayList duplicatedClassObjects = new ArrayList<>(); - for (ClassObject classObject : classes) { - if (classIds.contains(classObject.getId())) { - duplicatedClassObjects.add(classObject); + ArrayList duplicatedTeachingClasses = new ArrayList<>(); + for (TeachingClass teachingClass : classes) { + if (classIds.contains(teachingClass.getId())) { + duplicatedTeachingClasses.add(teachingClass); } else { - classIds.add(classObject.getId()); + classIds.add(teachingClass.getId()); } } - for (ClassObject classObject : duplicatedClassObjects) { - classes.remove(classObject); + for (TeachingClass teachingClass : duplicatedTeachingClasses) { + classes.remove(teachingClass); } return true; diff --git a/src/main/java/taa/classmodel/ClassObject.java b/src/main/java/taa/teachingclass/TeachingClass.java similarity index 95% rename from src/main/java/taa/classmodel/ClassObject.java rename to src/main/java/taa/teachingclass/TeachingClass.java index 5f4e1945e6..5f9febec3f 100644 --- a/src/main/java/taa/classmodel/ClassObject.java +++ b/src/main/java/taa/teachingclass/TeachingClass.java @@ -1,4 +1,4 @@ -package taa.classmodel; +package taa.teachingclass; //@@author leyondlee import taa.ClassChecker; @@ -11,13 +11,13 @@ import java.util.ArrayList; import java.util.HashMap; -public class ClassObject implements ClassChecker { +public class TeachingClass implements ClassChecker { private String id; private String name; private final StudentList studentList; private final AssessmentList assessmentList; - public ClassObject(String id, String name) { + public TeachingClass(String id, String name) { this.id = id; this.name = name; this.studentList = new StudentList(); diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index 74301c270a..71e679bd0c 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -3,7 +3,7 @@ import org.junit.jupiter.api.Test; import taa.Parser; import taa.Ui; -import taa.classmodel.ClassList; +import taa.teachingclass.ClassList; import taa.command.Command; import taa.exception.TaaException; import taa.storage.Storage; From b5c0f254a4d9627c304f5e74925568e050093829 Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 19:05:57 +0800 Subject: [PATCH 282/543] Refactor ClassObject to TeachingClass --- docs/DeveloperGuide.md | 8 ++++---- docs/diagrams/AddClassSequenceDiagram.png | Bin 23423 -> 23262 bytes docs/diagrams/AddClassSequenceDiagram.puml | 14 +++++++------- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 3969536124..d1ae7bc31a 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -35,7 +35,7 @@ The _Architecture Diagram_ shown above illustrates the high-level design of the * `Command` * Defines how a command is to be executed. * `ClassList` - * Contains a list of `ClassObject` objects currently being managed by the app. + * Contains a list of `TeachingClass` objects currently being managed by the app. * `Util` * Contains useful methods (e.g. Check if a string is integer/double, convert string to integer/double). * `Storage` @@ -55,9 +55,9 @@ The sequence diagram shown below illustrates how the `add_class` command works: Steps: 1. The `Taa` instance reads in a user input and calls `AddClassCommand.execute(classList:ClassList, ui:Ui, storage:Storage)`. -4. A new `ClassObject` object is created and the `ClassList.addClass(classObject:ClassObject)` method is invoked to add the `ClassObject` -object into the list of classes. -5. Lastly, a message indicating that the class has been added will be printed out. +2. A new `TeachingClass` object is created and the `ClassList.addClass(teachingClass:TeachingClass)` method is invoked +to add the `TeachingClass` object into the list of classes. +3. Lastly, a message indicating that the class has been added will be printed out.
diff --git a/docs/diagrams/AddClassSequenceDiagram.png b/docs/diagrams/AddClassSequenceDiagram.png index 5bb12769b2d09f6161105d78feb8a38e735634f9..35ac2438d0a5c789a0906e8f1c68748dbb63883f 100644 GIT binary patch literal 23262 zcmce;c|6qL`#(&QB5AXf(1z>@$zG`>TP0fzvhT8QW26$Yg|ai+D6;R2LH4b&B>Rkg z?Auso82rwNmiOoV`F`);<9^)tUzm9<=UnGH*Y&)f*Yohdt1L%LeUh4tjEq+P_Ko{w zWEA(v$jBr2?*X6m*DHB~A6$+%H60CYAG=u@n>dom8QU1!KXNoSI&I)~+RV}MvABT1 zW2;9tj!xEA{D!vHM=pw;A|u;VZT>*harbjFa_|_}xS0p{RC+HSh84WtdOW53^2Xcx zeROV77mQD5IY0Q2=_{yIBbav6z%;AB%Y)uF4yh#+lo(B!4_KdyQcF%tjLR;1B}64qDQbIp@Ce5>(>`)10*1r1-5V{z z!*YE*F*k$%tY77$3^SM5{*$rCz|)Gdy!u5l&uTD7Oty6}=YxTCO3`JFpAS(XY~49`HW$@q6Q z4Sw1>s9HU+x}{mt<5s|Tm z{+KSGM)K?ARmslOW5>jJ-U{@t8EcnWO>J3gs~n9Bh+Wvva0Pc=exB|rY=8|96MeTY zJ<1zK=FPUR_U)XkqadXv=3IY3{r+5T`@U+yAKZ+qKG&W~*~>E?Pp2`z(I8vcP>7IR zzY8h%C^}qZANx`V9c)>?(2M?jv2eiQ^_~L5?1whv6|W%yXATOLD4YH#6r zS)VF`s$W~3ZCZ`j&Bv|-nq*`eaQPe89=Phx^wU6(cXZ1t#m zaW~6!Vme_~CIOFnd{Falx*fKpZ^?o!>`@x(_z8*rSq3Ha*k<_VLRH)|0b&Grgh7}F zL42*5bXmEW(iFi}DDs#ckL~oPC}FV8>x-=!KG}It2$}${GFvBIMU*?X{jMQ;q?An5 zf|K>z^uc2^aID&b1skl623#?~8PkHJ-!SlZ^~u<5(={yMWYne4SXo$JE+IXDjI*#8 zC-S`m3lU0iv9Dp9ILV0oHX7onBg6_Hp#?um$k`R;ctfi>MMflt9^CdL<_PIqd|ZhXW)M?a?NJy4_ds`{qxqpq zNNLQSvU8-b=fzw+q!Hh!z^{i3`(_A8PZ`X4Ll4v9d65N}H0cVNK^v4WYK9ak_ws{_ zUtmz%S7(AriEOe2dtB<@kT|tEF!z{rHQt|N2|68HRv?kG(1DZ-lo_!mdX$71>27+I zyq{lnCaow@uH9YwN7stK#yY>(hxc2n`IwF2)mq7htx-e4`cyMK=|RLh;U3aI@UrN4 zdi>3nGRnek_Q33{GHu%y5lvWvUYCVzOsvwlpkr%Fq&5ZEhE)UbohK03 z;jKxM{mBMI|KU6T_)}*Enk>^*DMW8fCocslUw)f4<4(xRSESGS!NFSP^(ACgVVZW}34`v12-Gu)ADDKSK5 z))6rL$dF~@d5yeLtg=_8KuaXp32U~z7e3over9@Lylg?I@&xtZ$<7IT&^(bqZ4b2 z@<49nFfMqGLWDL`mwWML&?eI*9&f#)(bC!DZ`#?6_6^w^4e}J9qRP1{1Ma`@N_(_2 zsa$N2z~|%kh6z&Bgw5qzE9CoW^>fw8?Yr>^nA*I|*>=gpw6t3Xt46=CM;G!dc*DS; z@0~7a@Ky45*sFV=YotcfqYbx#jc3u)phF?J7jnw1BErGj@sb%9KPbJ9k4Ik~yAnmY z)_pMHrgtAV+hxjcM_lDUzGBApjU;4znQ!l_YlRBHi7QGFe^O8wof^M0ps`1)z2?7+ zHTDM%LPWUAPD7xKY*H)Qo@qzG_C_AkQ`Ms=JMurg?s-B+{t$6&b1TGltD_6FZGBzA(QJd zSW<4Ez9`eF1k|wJSA#VkNIBcy|Nc_#C8#N4-MFz>um2$IY>SX}lifv{rJNIz0egzn z&RMOmqzNj&yh&QDMd^_nj(^|8dl;JIlK;>#aj1o*YSvLUp zTTXUEvGJXF^R-@#u4u%_(4?dVwy_}}6-RiyIvcNDU?bu>Putz?brI6M?o)WC45Bzk zPH8^{>+;JnamTvm7xuhKb<4`Npf`y-9ze3G<7{8;P5=E- zA&iCzkQFGKG@b@I`J<|KD%D~sk7LMVV13YIc>Q~4`2ib~9!Ei?9J|Hw*0RO)v;67D zwq)*>!AdvRI&UsP!x;>NpPlf$?36qfAaEHcQC94(0!&HJ{MPwncB5WpGgTq-5Te+9 zIl!Jr1Ba545s~sNc1CFz@GIOod7;K$L?hXwznJpv+cSfMkNo{N3T*YRDYl6|(9^qO ziw+@p<&hS}dAj8o=jD0|&7wt7LBSbuXR9)k<~gse^%FC_1)~zEM(u$y>h$0^+d`}E z4EL4ko@`@2DX`vBy47AD1jCwZ;4>ukRI^r?$56wvNAG(q6tBP}sU zyb>&WfN{UH>ueDhlozY#xg4#xwZ=(A%qyT0uX&Cfa1!wv4(go2WRz8Bl%YBIk<1h; zLyO}y+}s+To|dVqb>ZZgU|yTsN+{K@K=JEzHAl)2AN?2(!SIX`$R!u+AjZbMZicn+ zIWK(WaTr-qQO11iV+TqNxo@JUgvKJy$^F0?wxrKZ2DkB3kNjxPY&C7Jag9QwdI%iW z9f?&SfEKYWM(W1YzqjNyr?{o_p4D@SpLG)@Q%3Z%)d=ws#XtxBIXU8`H(dICj5|`6 z*cD)Q3kDU@LUTALe3vT|t%;j+H_rQOUsLWnjUDZ%g41$BYImR zN|Xs8_O!O(F?XaRY_ArLMm*0zx~l{h*g!Z`KBW@;{N@|(ga^cHD&i8Q`iW)9i0-yD zeQ|lr;j-yPg#;$J_;Q()d(}%pnJ0#|moE#WFR(Rg2#9Ze8wY z`Ms9Sl-Z^C@u=Y$!K|&at&L!&t&KU`Iw>4sagoJ7d~;(sXx;o`qmVmNf5arIUr#aP zEm80ya9lR%<2_#bW*U!0<~B)@$6?EAb2%g6R?x|_Wh28bXg8%mLio~0g{{NGIi>~m zxFHMaOW96J&2sh{#np?B0jSV}Ooz9KI8|eeIhgO=RP{%Tz9*rFSvQ-tlL@d9Nj7G^ zN7*`WE2=|r-Yc$u&XIS{sQrADa?D?Ad1CQJ4ZL?2T{>CKn5+_YQS$uABqa@uV=RyS zT>3pVHIG~mAy3|U8X8;j>cV#h$#J%w=}I)TMcVxaP201BCH3nBcD4itVuy!I$`)!e zsHxTASF+^O2P}~C0U*{lZREJE_7_+P9P5)>?c=`F6ER98(2cs;iFmaud4{lU#X4iL z-)0_`tgs74q#j9*-C}cTPmqf2uPQnF~zgLx9kia>OWukVp)J6%{?YVoab}X)oI3Ug={W_IOMHk zHB#+{U-)OOCzoVCrj?S%w7fbaYUX8g*6Zd|XLyofyZlU7N9a`WkHtUs*`jhpfU#tt zng(vxYGEZ7nnkh$;n z`}V|;a)+RHhyC%&!_3#&ZFt;Qd`%PkUf)~s}c39#mDR2_A zorrkM3p%#bsDM;LcJ_?t+LC7B#UN2}dU}a1B9>9Y(Jx}oEK9Qgz=2XBA-%D!jpoJ@ zV%8mlFyz~h3SOT*y_U+oJEsnncXT=4mvD9(DXw~mzSje=Q1OY&YhSd`^-1y<1%?DWAyLZ{^yBA@!M4(g{SI^0I9PGQkqFW-Q z&|CX$x;rFJq9DKpMwE%Lht-Ga&8LdOu?34DnvQyXatsheaWw1D$oiVbc|RF5Nm62L z5BOpiwiPl`!<-S|w;#JO`uPn{VT^4XX$!tbB^CNkO;Qv3ZJ^qoZiGXdA11V#-Ur?Qp%_*;LXOi5^HT6nmv`_{&2F|+k!&tjK3-D=b8*V7r;QqP0n zo01^_9gAkmx9m*vT+a{Z#PDy)evwjc&zkt)JUv zg=4nQi5aCRo9YtWr%(G~`irkd-jUF1(FuE4H?i3k*5HwsnR$1!94>^tN2pZ)ZH-Zl zGWVev%Xc2jFSU_S)-pc9dKU?o*9bN4?1Ox861RCiAF72(EP-;c%&(D^A+Rgo<9 z3uZ}MQOBK|55v4b6uPDoyE0;d#n)D57hg{$gor{BGpQLFsQP;UkPyc3RE-SXVn=f| zH8pwp`j_-Pcukw-@%JIRg^vdV1dxY?1~`eA+im#&1^g1!>Pnnv@K~8LO|`t_FIMYd z)jxdPC@(ye#f1A}JIAk5G)pirFhILcrSSyt3JPYudv_hyUFPK_IG{~WPhamg&jx#A zPDcVFT8Z%H0j=Y8X^W3k2S9Wua*qIKXD;XqYbkb01$zu2z04KWbF;iPl2g4UjjHJ$ z$RK9X{6b<$@IFZpZsZgt1tW<;InnUQX@eSexPr0G-ORVJF$JEqa#XJdMpqLhMGENgV`-?V_tBm_e)Q;B>2e;9GVpPc1J-%G)L#dU)v-_59JZdk+ed zIf;c?FF{*)|1Upac9({}pa}fyF7O$tn4fnTCy;)A_f6QY_&s<2G?hhR>(&ofpw7?_ zu;19vWI#4)f4=wf5;Pc!W+I-tPp*6Y`I9sI68Yt_gA(XsDF5$1u>NmPCk_vbXaab7#z7A=9n-Q`ar!` z|6A)D6c0os~1{^qd%Uf9rszW;YR?(WiqDBIxOGj;^ zTvIh3J`^|o76;sQkw8wd53&418@iF5oqa;cL~?EXy@4nC9NMmyrTCnvaxmCNgI|5< zgAzPfy6uK*%+-^Tb{g!%N`>Or!BF+cu~Q7)q18U@7VC8$`>q>u6JEVlERPL zcH+~_Om))gbt1=OTUg)5@~V&;V`^GX|tg#;;&u&}VR=gt`#8fv6HWam)0 zbEgJGx_s+ifYDW*S(Cz(8X6lpm12$`Inr9@wN>h|`cl5ge}Zppbkyg?ix=HchYUHlZG43rcO@hi5x8^lWTw zoSc?Ho&bTpY9s`<^nPh+DJ6wl`c=H|#D~wHRg+CjO*_ATH!?Ds&sR}wP*SuFU3FH7 z;2rGOR904oLL~)1v#%0XdTjwFt2F2COx*AA z#VWGzqqp;$;lr_2!^7!mX>XKnSy@eM=y_IC)rPPob1E$)O%7ED6w42D^k~Oje02TJ zorWK2+Ih?|$`#2r1a4UxI}F%%r-^39_m&$81ZHCZ`+ zsK9lijeX|BLLEeDapkp3IK{q$Ey^+JT!-1m-dVUmkC0TReDY*Jx$MEKkYJVbgN~y#T^? zj2gethKUlV)-WoMKyGQ8YnhLa$TBkeQY?O5K}m`7$)R6?aKiyX6|*K?6?#rC>ElQ1 zzQU|epKf11VP|It_u3R=gDzAvlE!vhO+#afW0WJQ;KF>`rAwEJ9VZOLxcr)B@B_~T z4QuM^wQ@|%Whz5K;*5*qtzi*&{Pg*A=tojkm6Hot$TF;DbsGs)k=b~l&faeO!!b+* z*{!@<0s(uZ?x@fM|8u$Dzds-wKYhLYFvZ=-bKObePfWhXCIAyGE-rGZCe?8a*K@+- zBwYAyLtty|@V4-zBo%l99FFR20ydBte;pfzHn@KMy1KeL1QL($+XtNNGF-^?+fz!K zkrDr6oZ?QCxy~~^Gytdf6}S(+f(~|9SC@aRnxlu-8k_UrNy_hm&3~E8Sv`YX zY~Ybu??#P8&gKGaDY(X^5{*7(i$8nz?1=5+dZXTETar>NNJe@^5zUGr&r`pAK@0~= zv zXSs!i9RU>Ui3T}pb*fWE!ce09+~5mZX6N~VYZ@IdU%mv6=5J?VkwRny)_&^k<~6{J z&O9H~ms_%9X{9nI5jub5#`|3ku zTRg#0L|*_h^M?-~>gwvcy1LX-)$2v7uQp!kZfQBawV2_IO}ByAT&RW4kHy;No41es z(6*KGT+7wDb_xAy9_=wF*x3Ob2VLqhWlC~^D^aUd--aNKswz@WATK&i{iv65U*Czw z#T`1HpJ(7BBTEzQdLA<($XRRBK6_6NRAKaw9ZLLD{{dON8@HCg%NhYvc%j`DioHBScg+t`HP%*@FOJ70Hl za$=Eiel2sfBSNw4`-+NvHZUS67og=^Zv@yD=|P%wslPD)yt>}YhLPicQeQcte|@?IHRtLf*` zKZ7E);6;)VG5f=Zs@!{1Khk2yPxA2afV$60=UT8_@TusCh#TNM)69o(`2`C4j`37cQ;u!F{^xcc?6;677cd z)ks@?ixZ<^;Kkd}D#;JUGt3q6>msgL_XukZg;!Ts8%R1$J|F}avu)1%8nn4;>o__( zK6>=X&5iJyOLaT}>_?{~M~-CA3{%Wx*tFUhxKAb3Hc_=FtH`*__K~m|cz2`J?IgLg z=BWTbpcAh>L*j>Ml=|hYR4Df{|3V56RtGqGLwdV>AzmBHAP#JhhI5n+Z-zl`w0%@C zHeVd6M;tgd41BU=wwUMAC3~>vp}ZVH1=XWtW1wmh<>$8nj_HW1MV9t61l^$HROkU1 zqJJrh@IZf9!iUGI@Kibsl)fQ2F`hmo}fpwd}13YYL`Hhn|`IWg;8< zWBMa?c05hbzJ1Y(@6H#Pi#b3Ug1noJdx9K0`6ueOmh~6}h@F1SR*Fr7I6FJtazu;o zm}vj}K@7ew6+@|w}*JyrG+Gl}vu+N_45VK0j zw$Aq;n;0tbi^{97%WBZ0n~gBwoCCa|ZfM=Bf8Z;-#I!w4RIl@NeRD~WTK_u~E%+M$ z3e+rn{TtcF%w+gQp(CQ!I*nCMGqp2tT#Rdc$n4}eH@Hez6g)%@?Ym!^K7RQ$6>eqxrEEL7m`p=to9>6TccDHX!;*{gTaqcHaE>Zj{qV(y+_c_v+ z?~f+`nH})<&l9VH*6pXXjEGU-hCr5g4T}-_OYKD>LB+CxCe6e;W=+R+&`)F_o@o z!Q_zTk04-7Bp=MT>b_(*bYo+>;9+j&;Jr$n=~~D8XAf=Gg`RW4c)G-1wgyd!BG&~2 zF_pO%&!lz1_}6~#oqV^9_MLjp^dto&M5lV^@LzLYyRWDi2x}Msu^3(ERR&wpc6>i9 zO}8>UIS>#KP~tR|@4h^V!=l*49nA*Hy&EI=j3_KLMI7du3pU(-o!1rH9#_OFFLALI z+xo7m!p_d#oFEmen`7CT&M2V!dTM`!6nrARC(lwtON*-}qJ-YU(sFd<`GI5i@88e2 z=}+lzacnDOoB6OF`xt~wKp(Aj->OkMCG(Js?D2D2Mq|>h+W{N4_26^ZdErtyfwz`MJ5mQc_YPB6)z2vkxl>d4DTt z$Ri*y5R~EPIr8Mrwyq2IKUcVY`wA4FNeo-{ijIypnD&*M;?U9DVG(9JZfa#h#eMa! z);>wM2OvH#FK?~8rju|h_>`FC4_-0DVw2U`{?yb|r|@j-1um{oL+f(}#i>zIOlVer z!BTCQzPY(Mv#1R(H+S2zC^R)NFpwWod^kLb??@?IyV4cdmf3HV4{U3b-E?p-MHSft zP;r$OU!Vy-C5mSTG2so^I6dAJRKWWp__QNlzdp|~x=sLWljBI;5rgK5_GBy;i>n9N z9e^>v`j(a!1Ofr7g+(Q!tqM-CRs13S_KkdOo=c%jv9s#4+~VTJnVFdg1hnBbm;I$( zMoby{#XCya+JAh*j81o|%KuorxYI*GNdoi@AXv3_2QBkuzc4n|v{+stiV8A8GBv>c zgipDuirM!K*p4%`sLf7y=a3T0g9qPVosm7nA`S+Mb;fwim4fUPpc!6p2^4EkdjQ!N zk1>HPK5Q+wzA^)F2X{$0sF~$%+&EkkBjvFI%8aTm#{zqeqM{`qE)Lc96YWQB00pDx_N}BHCO3$#z(AZcqQ3 zbV|%-UK9k~6urUb_RL4*4!Pt;lixqDaor~~-WNk>K$fyYCn4yL5NTQTiYIM>iO+j6 zvvnEI_7$yh9p&fUDX8*6nAKMYVRl(GR@9bN28MuvU3vP|e~-Q(WM@+K?}ls=X|?^9 z?N84A@;E?3`6fH)s|zNkUcR)!{hH`={qi5JTIT?>1A2*#Dvoa}HIlV8DTQ1wW68C)f z_T|9*M#0T5KXNVN1S1@)*j~}n(WxjZg4?Mq`)(ZOi34k&;4y0sNSix%?r3R6M~!p< z??XGbD?t(e!0rC@cN7$A15dOAcv~I7*a%TmS5Hbx0u?gGYik4hEk3;DD8=k9U*na) zL%_dc;Cm=+SaVR&M!Grl#QrOwGHVF6(v}=7stjE{^R(>ku!4rvd+Qe?ni5W`vLMn^`fYHI`JXVd|N^P0))b35VWKFE0>x7(2-J6UrA97sq6r z_Sz%iH2J*~2z@}!npMjh?hz~IU;@w<;2mz=y7lm3Ow@O7Uf${c5|_?&2pqOHu{_o3 zMO>)O9%+>ADX@jp!4Ls7G&|%AU&1_D-wlwpJA`Iep&AgUH>oGum-9Fjqh5uDWrLan zZ1n~(HekHt86V>%T+)G7z}^Q8wbAK$PtU`mM>;w>Zf;_1r(|F{$}8io&s;R1L2ov!(ds9|0d zsa6MjJ}exn!H2B2y{CB8dA6^+)We13LJRyC&!4{$NKSV8uBPN5d7(du{3)hJdLUbz zt?l_CSB(26VO&x((_f;oDF$g@4oXQ)722jy&LY3t0IpMX;oU=!seuCo@dTa{yTr$5 zJzNuX^X5(a%^u4PdKr_A=^WIE5ip6hby{D`Ct2S^fJj(WKqE-xN*0(pW^geFsPztC z=yU%{k@?f`pi|)H=7yMyzHEK69|t(1a2GLOI<~R2UJ#eV!oxv~le%{aqQ~<)m`2Ge zE?%><%VJWA7gs~N&HBm^-$s3(jVLfi4D$*Iz(G+L2M6^sk$`hksS%9~Co&KE)|M0- zH%5RYS}%1wL}n9@aKjy9m8>h9%0RA7jz;Q5*mmMZ&v-7i%7Jmy?=H{m;}K6k5Q5W# z)7?!#?SW`D|5+deNx{>jwR23GojM_)v0tQaSEQXh`)3=YK?C0X{w!DR;*Ln|^zH`w^5p3b3vi&sAVu+7p*X z0CqCCU&4dj`ioe>#fdq%GVA~M2~dp74isXHhv z`ZH~|;=H9unMmf$R+0~$CETQrLr#$wxS*mTI)G$ z+K;JKqKht%)_oP3MNBguj`kh{_?rYqcL49n=YTeI2hs>uR%z$yE`c)QeLd%=vA)7E zA|Ak64VkHZ=#|l1!9((O{!H;Ku+-5;Slz*$&AU6G{YODHsG#0BSY%yuSYZ8((C<{@ z@N@C-FO%JPH5DWK@(opN(AIICd}|M`9WKYwkb+b%Xh2*Pb(h{az8B7;hgCoj#r0NS zpQAy##fKa^K!W=Uq&i?p^%BHKKhaGF^J#is+vOx0CFlD*eGl0a_9du3-5OVP`qM?^ zdSCjOj}%DGq{4uAJ7=lXJJNrzVMaQ228tpxlVx{q+9`@QU%>7pr6yin-8w|Ya{cPY!Y?35Os+FhEis|6>vD18GYdFTW;Sq?QYiyCDWu5nZ) zseoB~z7AK#*?tpM8~f(P3onBOnAkGRByklA=wwhQJ<*b4Z&xETp$F3&_#$wrzz8BG znPWVZB)#S2*!pm|5jIYkh8!O!obo0WRWiRXzS6p4oTu2=GLsNj*IFF8(SqwPNyOp~ zlALGbwW0=jl-g}j=*i&6I*>IXj3ar>1<2tWglslrV)k-2fYtHmLYsk;enefa;yD57!pZG|2P-H&WUeBl-#c-@W9jNnA((9VmGrEFqOXGTTr7n&-I?0)tEwByu4WL-6 zf&$$ZpyX!j>V9mj*KQ57d4-lh@~1TbKDFx3Ha0W6t&85%-|SBhO57CfYkls%hgv~? z*G1sPiZ*d56(toof9GK1kF>_Huzi!xQnPw@k&B~WA;{}jcK%ene6VAqJv;p%# zZAJ^|BW%}4Y-~%c$ICYJyh9uu^aj)3%#Pvpo1(OXPibu}cdqC1%xgo3{NdJFTxym2n}{Yzop3h0VcTT%DYJfF9H@WKLOelHnh23pU!k19}w-WQ&cB zE_DLN%*l|H)Kwj)4mE?gS1sBlNKL$rTYJ(*+ZCWht1aA9whXvU7QxMR4CWQ?$dSP} zZzM+7imUMuVI8+uK-lPNn4(?bc>gcYm;JrxQtpots@D@TASIW#^$AAio#}6IV;lGi zD$b=@7EaL-p6?y>CtXtGU-MW}iHNYB&=@FXnd_+9R&<2~TBSks3hFve>YN$@nX0Ci zVqcZa7V&|beo}Zb$yc_+?LQ*hYq2>nLm-|~SMzLlGLQTZ0hkRFJ^eks4BIHj5|J5# zqK02^aF~>y@u-UwMoDy83P!Z;QTi6&o98^EP}~e*Ij<+ZdBx+m@N4OV^Swl@!};EA zItOquJ3E%k0bM#raCKSkHYL=E0K#*=Lu1Z=q2igCedY7#Xv9Wa+H}fCp+k;(9PG4` z&Q|Z4Y%$2|-%zou!!nz8>CVT{T|n5OSWuMu?6tz9!IPq#)w^CsBB1_yO9U^Wnn+Mt zxI7D7Ob=>TJe@i;T$1tdjjmdrugmQo6%FE;s7&*>O$xYP$;wA^3gr4h--$FPs$v0> zQpywsdyWyGBfg-W5+JFGLFd$P@N4eSP#Ta@5iD55Z_M@N-6xG?B*@%ktT8Xo1GmWU zr5+jeoo}2V`HU1;|IP>Fgut2j2_sL>!M>spTrf~loZV6QG=W(T?WmhdkJ}cFya27J zP4sGwkFPI?9+fg%ML!%1YSd93)KEf4Mnd6O%(!mpP=o*+z#wj{N?g}ci|jE8XDhZ7 z-Qr?|q*aWbO~Ec>)LA6*;bOQ)gcG{S z|GMeC(Ktfy?s}4v|88_UBn2;}ahFE@%89?f1o=1t#O>~qpV1%Wc%1-mt?EA$F$=i+ z=ZtQVvJ;8k+|FVka^r#%P-sdixM|A{()yV*fk_bWu{kc+P}mdy$R}Xuyu(Ul&(ov7 z=r6zqSI_^KRLzAWo^_YzUEwG1CuOB=l5_cY0)?lhT|qG)-_p5(8?kts`i-Bc+kt7l zdi{^|Ny0%Pt#tgw)ZUb&e1+t1*;z3%*7s~Wj`VwgNiwNCA&IGEP242-BY8`vaGZND z!!Mxo`xXFl0_a*u4`T(p5>)K__g+i|$Z}`CU)@&8*OZe|2L$D2HUBZ=$7s(d$nXhn z*QQVjhQAXhcbp4b;+zrbp(DXJ|28f)wx4QT0zkCdQ$>c>0BX3godx_4@)x?ACk|08 zJqsXRP!GsqHnN=J|Hm^V4RNh_cOl7K17VL_)%NplXB#K)9S}w~&$Kb{F7>dc)$ZGW z-|~qXB_Ms3WG*l*5*|HsxcrO3?gKylHTYf7`~S*To73C8hf1E=Bm3&h@wtHP3N4vK zmMFzu29>T3!Zj;y)ynocgUJ$4(byy+cDBl~EethFT{b$Y%&`Gl=X85A3KXbSnr3EZhbfAJC+>}o zjxNOe{?@t(Usf!R9srYM`?>NhdqwuWM{X=XXZ`le?JyQ@Aoh_w+Zx z+&NMj95qtn4%AHox`;xXesQ#RoxGUq#4YfSY^7lelMo-yQCGZcg0-^fq}k zW_$8@Y|YZY=%LjBeRPVMDp>{oL#d{^n#6WhEDYC<8r`^YLrv`s)6}@Qkn`w0rKpQ% z*x8K%8QEhf6ffL1BNjDB?Irs&EO;hK4Ui;fn7<6-WCl3<09!zL_}90!wE@A-_wV0z zOWo_=kho~N6YMkTxf`_iM%O=QWMH2Gp+kNB^XJb2McMeqtvx(Cnybd1rTzWTMmLb9 z;6vrMX_KSjw|XiKZ7}pi!p+iMpJ8?Q;8HwvZT!UEJ-kW821*N#X z*)#zg1*jNa&OAp6J6!qz7V^i-M}kYwA`|RJ3c>sVBe@+iJK#Vn#lXlIu#jus4%!lT zRaJ8U{QdCZyx<8I76@P_b#E_^vF&GUB3w zr&!cL`s3;iU)H_if2I;wHDqQavsjE57lSaAOg9@kK9PJ{f16X-i6LK8i>zxK)Kz%F z`N6HFvaLm+KgDYj6ZaYh3ffF|**{98{_}yCnDwv{#bz@SQnSt09@?N0JJfwa)Zn-- zmLfCMjOv;^$i#J27ex~?msQC$-pRg8i4h8ul^H>8^ee$SIU_q zuq>yq{%6e$GCrtsqbbh-z8i4(P_mqt0y|hNkz2A1&&q0v9K4+mk~&#bhw;wuC62s9NVpIpFrj{RhhPNO7t(BGX1nR=Ib`%YTUbv@$?zx(5Cy4kAA+-9WXRM zLCpgnEaTlb|5p7EBA)$0YyAxH*VL}ek*ozIvwxy*`fm~>+6lC>J$CKq*uld0FiK}O zHyr3Kioicl=mjAl#}oy~_t^B|k3dDG2uMRZu%AC>xHT-zD{}IQOi4XnpDDoE>d9DE zuj39Wjn=ICPDOp#ZJMlyd!m(4>IQg0npXCJF zR#JOcOz-a9i;m-W`^9y8fcDex$hoSnbk9rc&ZEyfPK${}&#BAMz-rcOPvZGJSnJ7_ zel3#?U^(UG<$<_8D=RBiJ?&^X;Aeqc6$n~qVr`LJ%#7{z(w=KzuvY^?blfNSYAOnS zLswT9BwbfmR|A6~u&Mp(ft(hxHktax&i83l#+NUON=iY&!N{%6byU0rCx?=4D(J_x zeUJw{?8f>kro<&9YGfS<0hN3YvEcdA^~!XW8!DJ>5qAAfo#v^4Q3w5G(wPMyzVvjX z<9(RxhdBT=`i+ZO`@Ctk(XZkTSZx5!1)wqltqJ$)m-LIA$ueuLA#LsLsVOP=tC#tc z!hr}kVk070r*?_M)%5QM@cm8wNC=^!8|Zd{n16C|5;UzrRIK_iVXYJ|E+QdOl9co! zqrO)foWfWJq82@bs~sSqiO!=RPDw6*S0$;@)Cn+MAYTDWu3A=)rpVQD5O^i=3;g(~ zQA652jDNYhS}MqED;I#Ffqsyl)Uk+52=wzCfFv?anXL<5^Eh^lL-Dq}e0Q-E&s^~c zby7Ic3j;0Mal;vDkEQVnW@+gw4r7WS4~`-dOViRJB^E9h<}LmM3kbn66o^JE46>AX zln4|DLKK)5nJ}p*z$t(2q&Fg)h)chE$k{9h4jdTlKfnf5QT_>vKO4tP4v2NocRg+h zpq0}6E$i=}?g1GP@Du(aCVhT1q*lY%EOZk6jQcqpfe-b4;GZ{!R<60AV0#OQ{T zo-t`lwOg2*Pk^&TK%o*59{zsgktMF5LXA@)m``uZcZq{D+-}6vf9ocN!aWa zvDEz#=xVFNU@$ec4iq>=0JOlKMQ-!9(5q0)PX!ikUCPz5wMW6UjBs3t93_BEt}$%h z+O4^rcGHf?T`M3oB;ps=wBSJ5@((~jdL*&m1;d9%#1?pp4W1KS_B>tCYz?GfEgvE` z%BjA)e(~noPVJYj?eGVC54Wx?9BYUSlA7&rS>|8WTcKbpH&lAGU4`z%TR#T!fG`DR z{OwI!o8Bx=(Yed&P65&<^hNvX|B))MlZoY6>*=oB6&)#nwb$e+>U7%l$(ZsT&A_#C z#-u;xJLLvHfqwxC*nkPY3Q zGXnXP>dYUdKDoCjRBSL(58Y1cjKIx`sSjU0bwG#|wn%EI?J}ui3j*_*i&@Z?lYHy( zNX1vW)sg=6lPgC}Nb@JDx_&k<;K#gtE0;j;W%q4Se^<&4i7LVnO6@C)(mAI`Zbt#Q z@QO}fec|IyW`BK+^!EJn_-W?gC1n7F$eJd9+4jOS(o3zpCA9uBClF=)frw8hwrpGG zF(=Q#KXb&phuOHR74HQ`oT46se?#F(yNA~9U9{SNK8`6h@|!vR|<{8lP<;cn% zw?(IElkW*#xMA6NGt8gfYeN6ij$cz3eM)H|b3I+d=%$*oA1`012u29DsF3gFkoy|=2SAy(0IosA z#Lb7k>)mdu`ReM_Zi4SThYSD4g74B8%1TTdGi!6wm50K+)52O;xB`_ag{c;@d4xs(3GxKh z%RB(Iq=VYt>`guo;9kN)*1qP7ovvN#4rDu%Qav}@Ek5KAdYA8KDCSugG@o4sXPl<5 z>FwebW4y#EvddY}FV_aPd9D8q6%GM7RW1sQNOF^3EaKCY-)W?ffgDOB*DNe1!TAAvA`loO28W-4vm{Hi{n}qJ0HHNB+z|x4O=@4V(R9a%(#4!- zb|U6|AwP-QG();J(9<5)$ z7JxnS;8fCRWN@WnvnYs;iec0PNd+bFirgr&atWf`R zI&j3WI*N@Xl5T|B|&X*;lc%gGVYR&TKT*Bp676IZ~zKEW=6(> z$Aj0qZ?gcr9wM``q`EK)4j;?`x)z92&&a+wCGL1z@f#3}R6M0LXj(42%kpcP%%G8-AxZMieApg$_nF&CC%dSi^zh*E_u=U=HUS_u`bN1#W%e=EcgA9=SX2~5V4*B(y(e}1r}3hF^yjA3G(#% zo?8YH<&t@{2&DJbQ&7jKi4@3A;&9u=7bNBY1AI^D-C(clOsTdU(G{{(_*71>r4$~5 zH2ir7S(KXYuDpV*WFTwI`y7zlZ39c+Z87|uX0ZhjHUQj{@h7KYnF2_zQKu+S9MNI176oKS)(8O>@+4F~_^EiDY!6Czugyv-DC+}<0~>cabT zo@6-O>}&4`z6LScg5H zb7Bj(&A1^>KNqZF@(}y6Ic32TD8;1B|Any4)9oyObWjG4QyuEDySBJJG=*j*dQUxe2*+auov@Cc2o(&5ga;H_)F@l=Bz{G1a7t(At z*jB4#objVcMo$)XkktA1adzOziPQN|+S4q#x4+-r4^%IKrru-ITVZageG2W~?eBqW z)IhyE&|omEcNaCaz5n?ZsguTs|J#0lSy(IC#5pg%hJSkY{Q~gRGqj(l@>9<4;y1zl z2UrxvmWvwqA_G|u?lB#i2J zrvfD@yR>N_JtriX8BBqhF8)gms23T%Z{Mqw&V3AAp#4*d7PUVP6t9!Ad!}T(>Fw_i z2jgF4FHpKH;jp;~k&Oj^TFl&Eoqb8T@_LW`=G^)F*s?%twiPWtvh{7xTgEG2T#HC$ zG3#m%gS%jou~yMP&r5Ox*T_A+crvqATWVi|1Gvw{@PjjEooHI|`EsNB@73FFrd5_+ zdYZRBvG|VJH&1mJ zUwiib_Xlk|cAI~jr84g^uunbb&Xkss^8_d_?8ccxVhl-JYM`<5UGHC zzz1Fdpi}Opi?u+OLwsU%gYBiZI5;s*g#$XG#lR52TxHh^tn7fB;_@v%{SyAc203cv lD_D#n0Js(t=w=3V?%#U1ukD^J&Re5FvYxJfF6*2Ung9=*Kh*#L literal 23423 zcmce;WmuJK*ENg*C@In)pc|w^LQ+6VRHURqnnj6px1w|@(g=ujcZYO$hje$xqP}wx z*1n(ndEevsj(7jq;EL-yW1e%4G3L1NkPs6_MIu0ggM&kT_EhjC9NaY~IJhgpH?D$L z=I}Sszz-^OA$fC6BV!u_h_*SLFvJjIs%{R^x~pMxSJ&L!n3I9Q*g)OT+~SP^y{6F{ zj0YTd;NY%S>q*O-U%n1^1zg5DVntd~eE7jF$AZtN#!D)S9{iXH=r$pgkh@uy(y^It zjG~4bp28YBS>1u6hihD1q5-+;!%JkFT|;|6tj4~qtqSUeEj;od+Vu2#&_;^zoVV71 zH!m0s-&IlD_?tX}G@ow;T4)S9y3O+suD-nAay1RYy54j@@O;83qfZv_-m{@fcgt|N zcBt-^9x__96wR{!N#KWvY9^zu2qAFF50Is5odQCh!9$IF4A#H8WS7g|9!LE4-RwuT z!s*D)>U;K(nfY2h6x`4jsqe$S0=kI@pY&y8S8fTo7$^bgeK zigxnhag0=o^4y05CD`+jU?A ze}q_M;RR3Lj`NOCl*T`=CHs!8s|2-#Ln5S^(}|0o>OH}{L99zwVV31=M?e$K524jQ zNf3amFr(T=410hVhHu=ELC&f+W=hU4TSf7LDz)*!Eb^6mm_rTBu2Mxz(pOF^zjF_b zh%&N~YIZ#K(eg%8i5gyuGVjrGq>GE)Mc|shiJKoyViQX;uDgyR)i{oJB45&EUbm`8 zyo9f$r}XwZa%K`gyolbuyAV=K{D;@ePSiMA4%ZD35cXa!7QIRnzbP_HE43umkdx_L zZZI3%dXyb{I@kKh#{|ugTvLA1-i+$|k3EFQlC|O=&iaK_2_)9zMden@CG^*EnIG&D zFQ~kzkJgHu81>1N#gCdJxM@56iJt1!9RJq)1LHs@6Pw-gQfDiTMrOT&+eM{cq@AbO zj-}E~LUkzN4JowB8ahZnYr{hyJXc<8Ak};&Q-ps*?VUH-Z5?r*=cE-^t_2&(MBFLQ zg@cplebsN3vYq)KWtFbvVf#0Dbx;>!NU%_r${60J{i^nPc(@`O=jJW`+jsZ;4@gX>*;`t8 za!NwA+FDM^qqZi@Oe2d{B6W0#Eh)n9!h@p&M|LZg2=)_>E1LEi_~C!G2^>>!H2?bN zzG_f!Z%^bA+1gUU=;2~P(z0rw4(ZSb*k`|UoqUG$-k;lyQVt_}$VsQ0Se%8y+7>f} zefF+*J7h4l)Md>o^!rk#&oTMQ*2bV}`MTXM!_pQX4y0LE4t8U>Peu^@lmez|Bdxst zQ*s_-Xw=f;;z^vL!F!(^N+pCqeDE1(aeK< zSZ1+qcgv>jXpVf{OMD z;oj6wS~0^uP&)la!BW3D(ra&juR=-nJw9tbnNnn0+>cwZZ{uy`(;nI$)UtiI6c0_y z_>MxT^og#$ugmZT>|JkgZKD0^;nWuBWa!)uc8I#BNcPO2;t(qA%FY-@%}k|A2;kR_ z#8SFu`X5THlB#cEH&~^EEx>wY0R-O>6BGOzEoq|^M72K(+X?5oX#oY&U!Lk|pX7+-e5+gMe8Iw6RktyCA9ib!BdX@Y z;;^BBsOdKqW@t1G0~M)$V);Svm{CJG? z*FTAyvjd`5)oX+F4yWT)v$MUAQ_vR(hvO~TVBeBx*HqY*IUZK)%gXOJmHmx^65DQ>7x<=+TZNFJ5w<;oMp$%0HT5&LC9G0~l&Z_Twqkfvr zL)b}w{pBQwgYE_m1+S=?23PJpwkRnz9-wLh6( z%geGgh!7fNGI;g|C3a#vqHoURuGxPYr^8u7c(c4Gm4A|;8Lyg{-s!rO1-oPB{f(4{ zE>l~vr7d=U4hPn235^j2>Fxi7M%k|ihIh$Cg^mV6M*EdUrH#}W{@c*rD9m;z1jI*K zyeo@{?1nx<(-Mnn{jSF}m$sDibe4j|ekR_$S0`Q$5=yeSiCKXUmv8o8ZaNDI9UHS( z-{&T{d+op6Rqtic7yW^~8vSw$9J0R_;KxTHyWP?hl4()c-Fw%~@4t-m22sZBWw%NnAin{m(7j%_=H^D6yzr_t^o&2_l zgU9{pL`u23Jh~lu`1nptuTm#`20rGtuH*Z27?rjEqrr(nlIPUg9skH@tFP21(b1pn zY#DEh&s9u*m>^~aD$_i=`=h<&+ zHZR*7HSxl2r=lLJO3tdP64z;W)EzCYw|0LTNNxyi*_ID-upBcQhzXw}NukT=sk5)i z|DIo+UzeZc^OmTzMXy>rq!n6O?be@z?DV2VX1Rh2%u~L?k&$~;3{D5CUpVtLJ9|@9v0mE{IGr3&QBigGDvg%fDDYQVlrrFK zvHW=5Pmgl*CK@ubkKbB>#S)T+|ET1fH={=f6>6u1hMh47^PK{|#K#hMzBdI{ydEnT zbwiU}D?hB~Ju!JAE&V!wV|n?53jO#(!=Pt#5O;r>-JEu7SW@ubwqR0ti;alZM`%_@ zxB5gWAk)iILLgaatO%>G$kd zMCOF$;i`lTr7M$hC6#Z~F)v*Z`~ty zGZxxiTo9BG`zzWs89Y9HT45+>{{ne*v07Vttb=;*zTB0c3)LadDaUi#=}mAt99GS? zQBR1xa?RG`<_^nf!CJ4~p8lToL>2KUhL=s4p(P(ASY}ssz}uU*w$AcC!UECpLAyBp ztNosXEiQ$_?kH{U-GMLm5k%iz&_^9-TV!SJvS{{5{m8PeH8k0NSgC4;e?-Kgv=JX} z$ZoDn#D%c485v1w0dieg%Rjc9v=LU-6cXI4-HH~bu*A34y%QI#olVx`)|12^@r2lR z-ZH3e%+YScDKjz~npU7LoEht|cVk)UkZG`r45i|a7yn!gQk{x61~-wb-%y1O+sJ3zk%YX(>GKF! zTK%!My^N1ZKwx^fLVB_pY{O-lignK-`BuV5hVq6Eqx{v)RA0Zfy)~zb_QTWt`f!bA zgVI9laQQgZ3i)HpMQ;}f)L(Q+`S)czGV-3kgW;!$`?Swwc!n4 z>SrM4FwNZmxHIN-`fyYycsM!PY12`%6Nix@vX1m0MQK?_de%6-`0iGxm1w8afw`!t zf1V3e^VtfwhP!$CA;?qEF1rm|4_el+FD;F=F)By5Re#L!g<8Le`n8EKqPVN6Snsgd zU+taZNt2=21NCo{NqK3JH+rPVtk;V{jD*cl-grF_8JDNFz8AK!P0dzG1==CK%X#g| zETarmgY+ANd^i zobP7qO-w`SDDn`l)xwW%JuFqC8!SA=YHOszJQ7An%Y#I(`$}sLH5fID2b~0X zkJcGHJg(`q+B)OKTJ;oLyl0QfHvOuQqg|RY`cZw%SmMW?`Sjw4US3<$vD(j6wR z`Gp4#yNllO1I8WeH+#J8DrCQmoTsqWrimMRNu_z z(2nvwz6u;-V;Rg&MLF!|hv14&EmwFu9W+1M*&Q6zZwdKYx^`?nH&Z5p-o-`mXkT$B z0ev!fw0D?gnGh}cFw*yxS?=%g7vCPK8^4wAXG^fBoyJ)NE4{%BLth0xL%pp|j>Kg7 zH_AC>N;!ObY}yvzzhBxX!bpAdqnO`2=d?OAC*2m=RWvFT0fIlAxNw6#ESO`(p*sq7 z@RV9M?YTOxqh*)$82p0XNJ4!3)Z^J1gKXr*W`_126ngpfB@jz5<(#Y*Nlw{azU2Gf zIZzwOJkd~j+T@ekKR@l>;?*_N+2*A1$u*qapZk9ox}Fn33fB6VS_Lotk5K!(Z0kEGvmS>{D` zI8-4bCa&uWhNQ`V?=BPPJDK$Tzm6@5Dl{E-GU8T%+p(}1? zX6D0(4>Yo=Y7SX_0_fc4Cr1aMKKuGPlf|}z-0>f9?z6!3FI-mp!(%G63}Y6vEqxSG z_Qq`yZadAlz+{GymM8t^vQr%nca18JcW3zS^YE0%#tI${WT^6vs=uC@oAWa9ca!E= z5r(0Uzp-#q*AB_4^%kfnin+R@Uj=$vLeUeQ8o!6fx4(D;Z)wtCrjV~*?HcW+irsyB zFc+1PmNw(^W+?aO%bUo^n6G7|rPq0$3MEJEeuE|N|A>}{ki0$I-6_9 zUmk@-MMVV!1cZdJzwV>u=}MNNsooS(9eqpo-*7VD42y0@bZP0Mjj7ciB^ebbwlYUC z+;+R}$*;%1za4WtT$$PMk_dX%yugtLJJ)}0lHqeX2WDl$*{xC-(I65)l{ANJ>&DFjRi})Ls4r-D$tN$ZQS?85x&W{(*K29*=MK3&sD& zVG2!cSMvHbG&RH7j2v4Z_S34Czw(}&okhcYaF?AuNBIY-j;hN4|{+cA2(PRDaq}TQDxgpiD>KTn>GcYw@Z&+nU0$VZEC@ae(*N}fNd_BAFw33TgDg*~9aeM_o{kCt$2wZlvf8fby{d2P8S}YrlsOOkE86c-(Gn14MsX-)*ZL!b=*;(wJYx^=>;dE-z zuUud-$W)G!5~^ama9_4NQ-67Tp*u&XJ(A6cm~d^Z;&j-kqBV%uY_`Q4pBcd2d*zR4 zrVPt=WLrNjA-aJBrP~?v$<}PHjfh#>Ti;~ytsT;W)x^RLpu$9d#8ZuR(6AMMWonwe z-%sco=Q44()lbHrNxvtNPANaLttFHhoVUAmW@ct?DEL)}bc(rZfj&2~uBHpPp-l?= z2Fil`GjaS?z|HYsCOC|g?GBc_Q0;CE@kVa!B!}P{zr%YKrdA|4f}cUyv(L1Qsp{ln z-k+{~^X5$q42;gs&J@|SNf(fdzX|&p{wUs2GAg_8d99jHptiOalR^vy9eu4oV+63WHSVxz{AgQ5QYs$@bsQl_0hW{ zgT|Lr&6(o%+^akeP%Q`qq}f#YtQe5v?bqjcPi>w*e{N&LvE)Aa-MFLUGnEt*6B9KJ zjg*v>0;CSHmfF=$Yo`CxeG&P}&!M6CgoGj}$sTXYx7xVSAFac!73g+OE)VAL(#L)Z z4z5QEYx}~*yHSI=)R%TR>BW#MLfN!A(>&K6l|jsCp9!txS}Vuv zy`xX?(|^K#j1ji^kOq#$pMTZ$0RCX`Q(RrJdepwd2v~y{GnOdVAv3H2;eF%d;f6lep(%$iOb+8m{TqlJcGxVXZmr%<>4LaMc(fa#8hHQ27Gf5p4bFGTTXtda&35LgrC7EZHK?>lCf9g zgU6`R7QsQtYS7T$j%)Gw#fz4LF~?@kF^4@OZe90YPHb%KFup9$31W_XS$%!|1hFqK z5IM@B2~m!=-J)zBm4E;w86C8@w7hunV*1!}Wk^O=)>A@3K|xE4Y|ZI-ryreXf4tHK zQAqlMeWt6+^J5>?FovG>+*p2BEalJae~;^P@l&?jvcX{X*todjk&hI5u5`zXffHNh*Vo6QUge3r`tS;2r;L{-zm8C@hnFH|-HB{s>OT&gu^? za&qm?7@-(6N-C9(+4G_l=h_JEo1DXnX zj3+3`8@(AtvtiY4=qdFI4_OTcGS}DFK@tw6k@MWBs;U|`EJ+g$X9ZEXG>}D_GPhr1 z`=i(bxi~^zXhY&r65{Fcnp2LBE4RvSwESSb(>>`2ul^WhVIQo&@KbE2rECt{jAU=E z*N?Eg=l@tr8@}-N&)DdB7giTEb{D?!9!>PyUk8h_Ia>1W|MH3$bu-#|g<1Im*~#@% zF`cZrx#F)=V~N!+d4j5Q^Z?9-)o3(Txk`T#vCX67U~8^dmCo)z)R@^Rd+Z(0px4={ za0UEGMTE1s(>fwSipJ`O*>;nlXapui+CD#;7nQkp^1!AVf7Q2FYhq$zlCbUMWUrz? zzgHiml3)f1V>PMza}g0EP!=q5olZ|+@D#u)5cABMb>42ow(fp8E?B3mpU9h$jA>&1 zOVl0t9P_o3HsDpnzCH07%7%FDcS>2r%(gPAFpWq*ecDiLvD8DFB9{RUwV!Q`sjF}m z3K8daGegBT79ACpUUxj|8U+P~mlFt%$G7W(jqS3kCR^FYN}-D>y+ZAw%sQOr^U)`q zcB02$PbBT1)^AjT$_Z%rH;bjdXV0EZW_ah!#|U{LpxvSD(*Or5(BJBISW%|9; zS!8R83y7e%RHHg4Z8Xw7TI(6p&Iy|xs3eA^8+8E`;-2u=kHw1ocu(Xv?$FWFf-IY0 zi3N5)R^9$)0WJ-##5!^jRWK);He&l}5HPwXRf zsZIDGS_RX^9;%%x@J?e>lSVJL(o1_3efd>9G^9lzyP*2Vb{116eg5y`4+cxo`T&Cgt85AS}c;`+(Pja zeBd3)Zt@QmRZ?>Db3!mnI6b^qRSu8?ZWE|RTzq^ytX${tS~RQ+TX>KnfJ~yIq}0s0 zthzydM=3fzT`XsPp*un9<;zb20e0K->V;HqiO&|+M)-#gkqU2?FkO%|^GH&(Uv^qn z%h&yXuh98sn0Osn0dtZbf>oIA}<~nzNd~o&C1N|$P8NSibG~t1~JHG zxtyr_cw5*Tk5Q*B0+o<;dTx%;@Oj7BW_tyL%U;=7$!v%p5m$VVoSSlq<&2BItMEU% zF{&Vmx}ft|uaEQXs9|P4qPg2~_b0AQLM{!aGAF`=|BI} z`H{3k&xS-plVY_t%E-v*g+mw9%rw*G=(4!MB=Y`pIBvbs0GE{lNgb?YEzWgu;i{x> zAO%h#k|*M9KR?*0$_UO#p=M%737b*4@)qGIU|-y_P;3vHvSj4-On71ex}(eaQ>G-g zUyToW-n20Pg`ttY2iZ-&dXb;)O|`G9^Q2*YTYG~<#cph(_BEhOC<<3l-(#7wwJ%2xE_DK|;rN!A-G1qs8sSwSL*&$-Zg&8a6OH4}qZTCsJq z|B25a*WtqxLwsfHPDyYL30kUVgCYvFFuaV${b9`oIdTKfD0_|WxkdQ-Dlgxw^Ak0b zzvzl9P5M$+7%lVi6V}eff_j#DmgsMAwhj1~81FMgE#}0ox$eYhl7Yp@Pp?DovGA2` zf96X-McM2;d0cSR{jZn56POcpNWyVXdtW9^ct|MSUd>yB`RzDx3-+wS%d8E0os`-i zaEV}Ddw2-G{0I8dc}nm*C1vw>YV!#pVOX*R%u4nvG6N^fb>n&e@>2h4LiCi{|NCgD znwT;Xz95)mJx1r4x>ydtxKjBNt`NO>P9YZ2fwo{Ul&g2NzcJJ)^6nk2buT4xz9u{6 zEkvjJj;}W{$#eC4lkN6ajY>CM@eh65N|27sX{|czSXSG`Syuds{d7 zmEmn_az*;~iTqkHsC_d013_FB^IWRXAY3l1)jK@)g_hE_=Ey3r&&q~!n9aU}N3QWJ zDk>6iMVW9APuXwsTiMS-f_v;-ZG)N02fq86ijGcHOw8BYyYz6iq&Z}aFDCgC${!-`g^xRK?*D9gW? z2xASlm(wvh)#FhQO_dGZ7TxlgEdAB#k~|GI0h_e6Y8lv-E#3V_nG zvN&9&*fg^4=*#jJ*;YP9&q#z>$>Se(8Cm?Up)6ifx8^=RJC*nb107Be!7#}{9 zoRU&IUT8A)>C-0|bW!OvmZ%`wiQY?j000M&(uO*1p)v-%iojP;^KL8t`~-loWoiv) zLoX&{VUhMe9XmZHA>^>#rYzF}s?Pp^m_#sqOa?K_h%|tJ8NFCJt&uzqocHhF=in$3 z_9NEtm$4=l_SI7Ia(8cNZU#h8_@9np##bLayu7%K$DQ{-2I}hR>6J1}blTpez_~ce zT?k*;IJ#-*uV3Xvou|aa#FSE2P9sWlDln*V$H>ucy-n&W0&;y`ObkCWWz)N=D*jHn zek9j${jqZH6gBIpQChA{uq6O|-s9y}m3o(%_fkrV%VJRwg+P{W+Y&`iePHWb`3x@* z6B!vl?%jW+$PhY${{H^U%gcbA<$F?M45;z(UCBx!G%TFhYUiDEsBZNX z6?*by_9rDk0YoS+A)&vgXT4BKGyw{hQ+qPFmE=?h4_6RiCESJ@Kr|s6t z>IH5Srv<+-L%4IH#h{Aim1oZs^0C6QSA1gPe0s^MK0xPyrR=SZwIkLVX*eEj)B_sC zl|`1q3UI;TI6&?-sE4on(;Jd?78c#SBOum3N7Fo~Fj|SZ9&dCuadUGfUUNV7V!frnXSNW%Qd2 z!}9&^h%3Su%zI4iv#SAzp+73fVA9m7<@lUEjKWKIK_Tx%`*`Ow^El#p70QdI&6$a0 z2cIi9mu9_&fO2c>C4y`yn^B~t`+H2UUzr)-Swj|_zd?hMLK8rEhCm^4e&PzthagqJ z;2{<$1lYyvG2g)N(ZE2J(s7ZnYd>YTfU@|Q^(;|u8*7+cR6ua=YHVDr98gejn2t%D~lg zf$X@5TyNkacyu+p`&FPAQMpEADqKBetDqMitYVu~SQsLsnE=Qiw_W~zp9eWtELdn2 zfR2VbpQstNJ=Q#5xh@3d2zDi3LM;JUo;QI0^MZFW03m&~0EbR7g3C(m2mqpvuL6jp zMoj|G0o`qF?e$e`9R(TvLO{TYXnJ$8@IAbX{DP-nW7Va3W6<^1c{lNJaBxUSD&7pU z#yMj9GDt{Eo7WRrTw3JRK=Zzs#7>|X_A zFJFic=d@hjuOl>a7Yz&wBB!7L!rG|A-VXq^u)`;b;*G}2+j$OC_s3uAP6{ZNT5kYt z%erEN zb(?%UiXdA$0Wr8Oinl_e))SBu5BLE^K;kuye`-3J@HN6dAg*ixSr>W!oY-MoGAj?z zl-apCaKvKctfBXsfDa0eOnvDVG*QgB%37MSK z=;JV*cE?-pOCzLlmUqJzPdzHm9fbf{#y>o~M6L3wrCO@is~l}q60nmRaZ1wCSZmkd zoIkuse+H)#18~G5$y#%E{+r>T;9xHjg}3*Uk*dKGaWI)qHvomx-Q69i_&kX!DK=ZP zM^Zw&3@HIMS1l|oN}T}m1>)!Q^fbsQ?%0E$?9-BysTmtsvCVG|lai1bjFp#xR8Tth z*{udCZ+u*B6cG*%IrLQkTq&$%_wdG;Q_|96IapZyGh#XXCMHJ1a&46EWIAqQ(-z1n zNl8gxI4vf5llx)J!0B}|$by>nzEJolzY_zmji{q(ileO>qw<3%D0MY8(sFWM*gHV6 zms3!na@5*^zyubynR{6jua1%de3EZSd41cN3U+``fV|k))}|fT*pno+kZo|dyOMf~ z!+0DnB^}_C;E<60je3$T|A|d~6BCn#g$2-JIvRE2Y2bv1hcD%YG+~*L_LKTOszU4y zhXi8MAbELtfz6?<(`gCG0_!fzn$=r-*Y57}y8Hxaq-4K;e?1F+BCDP_9Eid|NNFVA z$aXf&SEXhj|cg;mP@n|*Nx?H7Fb(nfhcs5Xl5=*)iAyE2*=#`Thnpt-G04KED z>6HU^oNTAsHDc;u25tG6nV-!IxwrPlU9rzV;Vo5_m$yD#DG(ME^d{kr+&PH0{VVzM z0=}9k`K{P|;ZtZR70)eNYU*OZAAm^B0oc^>;ocVCPW-?w3=^@w8De?emkPE4NJrWq z$k89p+@pI{xW14OHR~WXQ;%GsQl6fiC{6gl zJ`XkN@{?}1_TRz&IjX;LD~3svu52(fRhA9IDDs}p@0|=lJwSG4sJQ*@D}H`z-#0&_ zktC9SmN&9*1174jT=YBOuo#+{Kqn@$d5q4hV&71qKUM(Q$-2N>>^4C7<7fc+6Ku-_ z`10SC0A^Aq(&f69V!P&fvag{2tO65eDxd1Z1>4LhbjbaiMDX<{t?y-Vqqq+ih*`wbil-xXsm##MdPskND!YkPbdShRH|EPw zw(#L+4&g8&g-eD3FVXVpz3;oJ2HvkKqd1Mt*#cgw90z&?VZ}tCL)OH^D=!f=XexfE z!BtH4*PUxVOieOi6ySe39N(&8z}U+6mbqtPamp`MfEg9bQAT^-N`k}6Ng*dXzr$6Q zPitMQajG1&X$nVfWhYDPlMkV6?GiyY`t+db^!9Qgoi&2U%(0?3)|+U{6prkaR~x+X z;sB+EgeJIVxA0!>#`(%zA?QV43+)}Nj{KqBQj9iL8?Hmy{OI9l$O+(RebE_VfK)Mx z+;$Wa6bOjjpnmfvoDoq)|E5FkSg7GzQX-*{Hspy+C4+m@Qnl+4#LeX1c7yZ}j zvP1ZttfQ7atv7Zy_5rBg5Fw*PL8~Y8;Q{fXJ=Owowp~YG@7cRce*6`r_WUmqw zHrFS1tVTJg$!C*0I{X1lOI581@yk#yc|b|jqy~07QXJ%Mf>7}6#5p5adH~ZMZ&X1%d+iN5=yR}e6bnW2aHH{g9l-wHj zwN%AGzz>a@noPyNK&OERPR)U*jk-CI#;Lwf5!f?QT3B8$5MIX2pIf3}Z5;wdU=U@d zHKeAtR5q!_E(JX`LfPATI1lb`V$dLr|WtaLeG$O13RkhfVY80ue zax6@WvZzrJlp-mLheg9#ZA0%Nw2dNJL}uyFw1}U4%j3@?*D~rJpA$RDz*7`(VpyBehkQ4?lo8h=oG)Fw=kUu>ab?UP> zSe{;9?1eW+Bs-ABB$o4`7>dqVn_=b|&x_Xy)*2B=On+r`TLswhz3@&^Q4YL%nSE^J zWS6B}(m=!|yO~I7sG(Vst{C`IrQAzK@fyPR?Wt6<=OT7R#kN+KyR~EGWC$tACpKHH z0w>!E3NRlOt+aIR46q_stmF%BRNfz+ZTRR?aq8F&oOH)0d)@Ibp7q_S{&c@WA#=Px z^(vsz0l2CW^!oK<$E$L{rL0k(uiYv#Sys@OMp_P~_M&Tal4iTiumDi}3=!t9f(r3A z6btj6=xY^D_P|PufkAg06VY+A(e(I}QbGFs@ZRG3`U7C~=@Rw+WqvyRgqNCfx|j`O z$8@JxdB4B$WY3AW3W;wASg87KQYp3U@YxIptj3PlJrV}wfPc5t#xDzAF&{5 zJCEbZQJdW=J|+$hCooo@Li-7L_Un1u)Vw?h`+HC!p-!NS1d}0QSm2@>y_+hWt>XI( zY16N%|9J8c7nmWml7QgntYP_EPAZJ1rC}JWtq7GR(SHidiO7I@qQa{7d6d9en(!&G zf^5StAkahNqS$r0rRDlvl5n-Opr|`5gR=4PB`jb6{arqV*`(jA(EQI@c{aMY*)38( z^YDcEO-}`whn?!T-~DN@-z_Immv9P9n4u0~4vd z%me1o%gKQI(%&hi71-*zqkK^d;XDU_rim-dFM$_EhM1LA1!}Eto_mwP&M{XU-(Mo= z?ZaP_yLz1#8pkKh$A4DJy`nAx=*m@`_iAg9 z4*Fkb@c-~@?f+qU0DzPIs!CvvrF$7oyORkQ_jGm^s$iL?e0l?RJI9Ugi>-Y8JqGp# zviC6jQ?b8rk^SzfbuyrGBHcbKL8?cWSmRdad@uqL{7oRfpJTFL7lNV3KW?r~bS8NG z|2N}57s?_r`Yv+Y_YvUQHEZYI1JXkAo8f#|6CHHS82DZ781KY>VK?FDGH(Rl6Y>`! z9Y9+E29b)5Izo+z0j~^9{k3bK@sD40Nk$KDE+0e`+WwTM&r=FflV4Y*grp=!iZtj( zD@jU9zIs*acnqy4wo8qTeJ`9gBmxLyp1=+g5)$A}*|s~2fb_2bzYSndO8Ex(=olrt z3svgiHg{m5^>~X)Buzt<^;!pm;{~L#piEix09{tYv2tbZmr6>9(4~y6av8gg+%G^_ zpqI~ld=wHM&IKcdd%2z&%MQ+;zMXB?bOY`6o1H(e6R7$xeVTI784#=cWMn{C5fm2A zP|Wj0*VfT-d;k9ZhYz*&^+v<_K6u_hC3S$ZtRb`gFvncWEL;9jQUJtdO!61(X0zUS z(_gx}x&XazXlQ`7Ac3l3FX5ES7pyC*119^McHQRSjK+T!UJW)>H%w!GMhtZYl~lZz zmX@@vENC%izjQ|T{3lvGiU+8FfZ+pUu9tVN(q-_Og-3k?m;%F3#_OQSJxV+}d= z)&x<0up5cvK2Rw+I5>d40n??F8Mv6vWN`vZHSp_%%XX*!nTE|puxkB3t`4vzG&eP| zxIj6hi;ERed&k7#Nj@1}?(BchtXZZf>S4mw57x zE&yFcbq@#xz`Qu^qC!lEOHACBpGuULpjzvJE@8SY;^O=6J#7R3IT-$JPhbMJuJ|pB z@4q)r?;$AQGoC3c60%Nb<`p3S_S)Cg<1CF;@UG>cW^1@x0PW@$4h}hjO#;wd_<}QA zH~FBt4<{!l(eAL{b=1m}R8%Bb!$kL2W=A3MnuspD7zRiun|1GKYf@c)@dN4#Fb!F0 zXCJP$VK=D>_ZLl^ z&}6)myLaWeFD#$Kj{Mg@=+6ro$%X#r{y-9j9)#)d)Sp1u2hk~^5wPg4jh5L-kf-CRCkHQ3e$A=5zPD4OPOH8EfQ|I-(H9YQ$N(jU|9+OEy6QlA05lP8T z(9EhuGXOS@!@adR7gu4fb8) z%LzTRqow(znS-b1wFH|qn(ThK8&tC65iwWnUcimaGu_w zx?rwf;OVgb)@z%aSZ6I#VLDLBdwQHQ7N5;?T6o1_`&wF*<$)Lf z7?v?ict?d^jN@5~Q^7Le@M~5j%qcsqptrj&A||{46g+%;cU=)Rq8X?d&)__9`=wWI zeV>^plN3fSSR39@ZP&^zWCRW9#FjfqxM&wn)hAIe?ma&1=K?C+DGX>lt`jEn^$L%L z2hf}F{yu*ZYWGdH_VqGI8~+PRXENaagN+N;%sG$uk0(keeAVXsR}6p;=Wkda((y#2 zc}2nyaz=0O-2@!|m#k6w;oHaYK#hCn8q8xxF5FAR1!rs>$4+#{S?MoP1l;)ga}&T5 z!J51Ro#-wbt0*5_CvLi)Mn92BwN1>84L$BDoqA5jCZOC67||w0(LNh*ZHB z_^nJ`-p0N1-Me@6%EhTFWl-=`5IABLtHn#;7{@EbPyFgNXXy(I2??cQX>uilqe@S& zQsH>4>BkLhIaS|eSK>fEF0Hn#A?}~yGb=P^`Q%#h@^R*Uku)2Js~vM!FDmzrt2)O& z2*93F1cYA3$nzrI3g!kN05EjC7M4jJ>I7pbFd9oIPD)F208Im%vE;JE0^p->h-8$x zWzfAYhcwU})=vTF@N-YK|J6YL)AQPNqq-72ny@ll;I~&)T+BI&(TunH4;L2~85tQZ zEiDg^<8c0)nsLwzQE}Lj8D*fS2c{nl@W2_EA`sVG5z~eMiWva~$wsvh^jNIjRv;k1 z0gX56fqE6d95r{>KL6EjnQ?)BLoI&KkZHZ4u{&=~vJ8PfztVV?J%26-1hfJI0t00v zC9^bYkv0y7+JTY*dIOuArhOO>-%qFkw~8Qk%)KDS5%?5OV3Y!2C;Zaw%3Jxfkqyz; zr%tihkCx%mkRc$PaCj@DSX#Zixn7M9j95Gr6gq&zYxrAfw?%|TMX3TKBbotlsM-7T zC~5;K*U{ehrcdQ|;MGq8Fiz4Ae}P+*WtElbs9k|$8wl4~ZNNJ^UkS6XCT^6w7N3mw zl;E)$zIyqxYqm8Uz=WEsuCQk&fGJ?+7`Say1R}s_?vtma)cCys7DqwB>#!<~*v7fM z0kd(UY>E{a{@5=D&7#G@910Q^?jg_s2Z05)SQ8v|wRQntmY%ayCW$-ouX3 zxPgYI9q98?HMj#-3=z@pj61}YYdsSYnR3YTo}iaMIB&&B$nKp127`(iMI>O1Ci#RU zyOIbRVPWWugBoBD0qy5IS!ei9-~oTPaNwI1eCsdW`Gt7!tsB2iw>D^f13)#HsV?B? zSe}Tdp`lTJysOlAuv)S<|EGKPY*2-so}R#&Aohh5!v%yRZtqJFx(eI%LQ4vH-*loJ zEP<_X5kB8waC5}0eS>Fs9GrNCgw#~;KnJja0|C`utN={}LWg%?Hb0~=<}VU(!$9AJ z<*qZk42)?ezI0lXR#8y_=ytj>K&bWs*cX6^K)3v4QLZ8e(eGca><hclWpo22)2}pyDr?2}jx>_dJ zl7`mSOH3gp|3(l6w95mKap|WWWKHi=Pymy^X-72Q%Y zIB<(t=M8pp4;ZRIjCNG>OLQ_=^Y))uXq_~Jj#yc5geAw2I8JZrvmRtK2D_3KZ}e164t}f`1A!^hZi3sAK=* z`+SbDQLIOv@1-7iGRTz-$UGNV(Hv`972&?M zoW4vlLUF1Ls&bB{5`=IZ9n4RKEA6bwzkr8sp;QjsQz2d#08&eJ&eAM^sbs)Crz3M# zqCGg9#)zBsEw=^r--fkdlt!t-J^S}!%S)GX@2boVvzeDLr=6fP#E_dIbszMi zT^VTob1kc46w-uqoS3VhtiSWl+t#k$ttk9->=(3iaQeD4xJaB0{xMU2?ERm1I!2LC zxlpTS5F8sIM!Ldkw~%dQ_k9K>HH{N0Fgv?Z?_T?}UFN~5xZasADnKGq!SohYn?+m@ zGAp=k?lQJN9H4gd92Ejgt8gKRZFiE4Ju2C6ob^d;iGauTeG=mo=R5|$(K%qh0EPEr z;7L}79vy8g=W9xaUb&TlWqkcl(1=t%LlPaiKm$((p4Cd_i$cECz~R_SUq<|~Wx$MR zoIipFkCPouD*#UXFSXM6&MWrEFhe+q5V7Fskhq^wI;F-BbBh0&T#$TSZk|1c@<+Z0 zJxFpan0@{KF>Jnd7uMKzJhEPyzt6|l_o@@60Qegt*iGJ985YgpSo#MehGVHvi3!i( zJMYc^%q;xQg(uLZz11HnL}l;OBTDD$Er$w>+PRk32l!No4PKtD)F#Klw*U3$5M|J% zy=*P`A=d+B0X%%^L^2!SBABM@EqhYP$jN7CXOrKJOFL@mRUbsy+y2?;Gi_>XLj#Tl zWMnTtzp?x`gd`*9)|stn?eiz3G)Mt^JY73I=IuKGN|Hj91@HiaCpSq+Nr8N`3R?D? z*ua~xv6zwpx-fq`8Y%Tj%YlvVMiz2ybtN7eK@dbkqT+eSefzhyUbr~|*fj6V22F<; zpYo{wbg!MyXS${-_`XO`PhX$5w)Up27pSnnde}Gi&QLx}1O9Y*&4VIR%`2-7xWT}X zeqy(PurN-Ywmao9P|TK}Dp5APJa{NdNWI1i=xz5bzgn~7Rr3|oGAly>zT0*5y(ybD zldI`(|I3+nE=f1&{qCCSen0SDR!(k9Uwf*~2UxJ#mcS!LPC!gZJ##h&Tsj*YV+D^aD&x{=cF}t^)e!1!_(&=s zAOJktKrz}MKbLx35rlT;J6+_Mfyf0sEXe@&`1;P~i2=pQY5&y&O82xjITSRs*}Slq zr$I8x%0z3(F|3m%YC@3%A0{W%P!JcgTgt82Jx~*0`Tw|qH1aak`mA%*Z&2<;DNdb z-CF}r!afu$b?XPNF6Ii_g-AMaYS#Zt>fl_fCR%avDHV@dk zmylDJS-C6D!l{paQMV7CUuYQP?0|LOE`52UlzezSfQt?N zw05Y05#WUAq5^Nn-T6cr&`$$GhCT4kpEvJ;5VA4d5p^1b!StwX@WIZoCc$=&uy7iX zfKvJ9XfEK=RX8^}&#y4>RzR5G1e`Kw*E$>aAD8Of0s_v0j-Rh0C}r|4ZE~0X12{Cc zm50|IBENo<%{niCK^d2w5nmT%#Ha2&?H!US0LwjWefw_u7qf$$#{-@Jwr0h<(p6L| zB}G8;`?p|V35`J|pnI--PlMcGp7CSUeP(`FlGAnOl`goqo{mIskA4U3f<$y9JwFw%fB@PVzP4n7L5V`UA zl4`nBI&IOG{9qpee>_RSUDA!3xyD}S8{bF4f6lU#Ow0t&Lv>;*6k z5cjM9J6_fKbp3gj|M`>h(IH=u=M&!%x_pNTxYnTwJcJJc&$+hM}d3C`bHq?}>N$5R&Se@$rF|qOS1JQdcx7hLja)ym- zVDyDKsc^jO*Gi3JBixl~I?XKAafm#gM>HMFr5gVyL;|L)o_oCb6pu?FM+|u7xXkJT zejZ2sUc8VSksbK(Vs7V;hMY%x;y3Ua?Y!cH>ep+{28{pTn5IffEHdVr!v|US3>k{N z02-PFb|C|2HqNt4Kj3SyzqjSS1j97o@Eq{u07wW6KFyz(x?Q@x`aiSp(UZpW@Ba3A zy3+WTgRQ^1Se0%8m;YyOUY9vJ2g8wjoWLfqy~4&h$STK37ttfB(HQ`za%nfZsMhc-xsp=e@S^l@x}12Topt z_ljB_p82M>&Eh!#+ysMYK7$sTa}=~qooTUgfm*RDq6NKf2c!jkAw10{Jz(-q(Q}-r zEAU=u8DDeseU@aQ-T>Nv4l7m|majWg_eb1xru4%(3@AgmO)Jh+IQu>evrsn?iq2~< z(njr0Y`w(nZZx|;!Se7w+v*P;W<2XaJ@bPnuQ?$H6GPLE`90xjN4BRiG{_*^R&lD(&yxkiSChWz^asT8emsOmQ44er%HExSx zfym*Xt!GCw>%gXcEsaK3S%p{C(W>d1sLGzj*(?GkI${S_UH4d?)s=1+kySleO^E3 zudkbZ>ervkkzelK_1|ssb>1xC4%6PA`4bNA1lFPvLLs74<>L0JEk9rT{;1E53&~3R zd4Sz(`+pD9Z!J|ccyNUQX(JynCW7}12JNVgf9I^9f|OGu4;;D;Jm43xo4@!Am+0Adt9v8f?U!b^&>3}p`q34 diff --git a/docs/diagrams/AddClassSequenceDiagram.puml b/docs/diagrams/AddClassSequenceDiagram.puml index 43d99c8883..d08302cbac 100644 --- a/docs/diagrams/AddClassSequenceDiagram.puml +++ b/docs/diagrams/AddClassSequenceDiagram.puml @@ -5,7 +5,7 @@ Actor User as user Participant ":Taa" as taa Participant ":AddClassCommand" as addClassCommand Participant ":ClassList" as classList -Participant ":ClassObject" as classObject +Participant ":TeachingClass" as teachingClass Participant ":Storage" as storage user -> taa : "add_class i/CS2113T-F12\nn/Tutorial Group F12" @@ -14,13 +14,13 @@ activate taa taa -> addClassCommand : execute(classList:ClassList,\nui:Ui, storage:Storage) activate addClassCommand -create classObject -addClassCommand -> classObject -activate classObject -classObject --> addClassCommand : classObject:ClassObject -deactivate classObject +create teachingClass +addClassCommand -> teachingClass +activate teachingClass +teachingClass --> addClassCommand : teachingClass:TeachingClass +deactivate teachingClass -addClassCommand -> classList : addClass(classObject) +addClassCommand -> classList : addClass(teachingClass) activate classList classList --> addClassCommand deactivate classList From 1d35c69e0cbe8421cb5c46c4aae310712ec551ad Mon Sep 17 00:00:00 2001 From: Leyond Date: Sun, 31 Oct 2021 19:08:17 +0800 Subject: [PATCH 283/543] Fix checkstyle --- src/main/java/taa/command/mark/MedianMarkCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/command/mark/MedianMarkCommand.java b/src/main/java/taa/command/mark/MedianMarkCommand.java index 82c57554cb..778f039e8c 100644 --- a/src/main/java/taa/command/mark/MedianMarkCommand.java +++ b/src/main/java/taa/command/mark/MedianMarkCommand.java @@ -85,7 +85,8 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep * @param ui The ui instance to handle interactions with the user. * @param teachingClass The class the assessment belongs to. */ - private void printMedianMarks(Ui ui, TeachingClass teachingClass, Assessment assessment, ArrayList students) { + private void printMedianMarks(Ui ui, TeachingClass teachingClass, Assessment assessment, + ArrayList students) { StudentList studentList = teachingClass.getStudentList(); String assessmentName = assessment.getName(); double classSize = studentList.getSize(); From 4b6840c8820f62727735c9724223f42a6fc870ac Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 1 Nov 2021 18:36:51 +0800 Subject: [PATCH 284/543] Update accepted characters to include dot --- src/main/java/taa/Parser.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 3078bed7bb..4e1fb3a8d7 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -43,11 +43,11 @@ import java.util.regex.Pattern; public class Parser { - private static final String ARGUMENT_VALID_REGEX = "^[0-9a-zA-Z\\-_()\\s]+$"; + private static final String ARGUMENT_VALID_REGEX = "^[0-9a-zA-Z\\-_()\\s.]+$"; private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown Command"; private static final String MESSAGE_INVALID_VALUE = "Invalid characters in value(s). Only alphanumeric characters, " - + "spaces, and some special characters are allowed.\nAllowed special characters: - _ ( )"; + + "spaces, and some special characters are allowed.\nAllowed special characters: - _ ( ) ."; public static Command parseUserInput(String userInput) throws TaaException { String[] userInputSplit = splitFirstSpace(userInput); From 4c24182b0591fb796f7f3253bb1b1a69ed563e82 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 1 Nov 2021 18:58:11 +0800 Subject: [PATCH 285/543] Handle scanner exception --- src/main/java/taa/Ui.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index 84daed77f8..26866af08b 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -45,7 +45,7 @@ public String getUserInput(String inputPrompt, boolean allowEmpty) { try { input = scanner.nextLine(); - } catch (NoSuchElementException e) { + } catch (NoSuchElementException | IllegalStateException e) { input = Command.COMMAND_EXIT; } } while (input.trim().isEmpty() && !allowEmpty); From 4381e6e0169206459eb7c880319ed010b5c809ad Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 1 Nov 2021 19:07:05 +0800 Subject: [PATCH 286/543] Change getUserInput to return null if fail --- src/main/java/taa/Ui.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/Ui.java b/src/main/java/taa/Ui.java index 26866af08b..da8e0dba32 100644 --- a/src/main/java/taa/Ui.java +++ b/src/main/java/taa/Ui.java @@ -32,12 +32,19 @@ public Ui() { /** * Gets a non-empty user input. * - * @return Non-empty user input. + * @return A non-empty string if successful, else null. */ public String getUserInput() { return getUserInput(INPUT_PROMPT, false); } + /** + * Gets a user input. + * + * @param inputPrompt The prompt to display before asking for user input. + * @param allowEmpty true to allow empty user input, else false. + * @return A string if successful, else null. + */ public String getUserInput(String inputPrompt, boolean allowEmpty) { String input; do { @@ -46,7 +53,7 @@ public String getUserInput(String inputPrompt, boolean allowEmpty) { try { input = scanner.nextLine(); } catch (NoSuchElementException | IllegalStateException e) { - input = Command.COMMAND_EXIT; + return null; } } while (input.trim().isEmpty() && !allowEmpty); From 5c24014fb836c7ed949062bd7776ee2210b8f56e Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 1 Nov 2021 19:07:19 +0800 Subject: [PATCH 287/543] Handle fail user input --- src/main/java/taa/Taa.java | 3 +++ src/main/java/taa/command/ArchiveCommand.java | 2 +- src/main/java/taa/command/ResetCommand.java | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/Taa.java b/src/main/java/taa/Taa.java index 9c7d6761a2..06718223a9 100644 --- a/src/main/java/taa/Taa.java +++ b/src/main/java/taa/Taa.java @@ -39,6 +39,9 @@ public void run() { boolean isExit = false; do { String userInput = ui.getUserInput(); + if (userInput == null) { + userInput = Command.COMMAND_EXIT; + } try { Command command = Parser.parseUserInput(userInput); diff --git a/src/main/java/taa/command/ArchiveCommand.java b/src/main/java/taa/command/ArchiveCommand.java index 143bcf2645..4a9088da6c 100644 --- a/src/main/java/taa/command/ArchiveCommand.java +++ b/src/main/java/taa/command/ArchiveCommand.java @@ -74,7 +74,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep String userInput = ui.getUserInput(PROMPT_WITHIN_COMMAND, true); String message; - if (userInput.equals(CONFIRM_VALUE)) { + if (userInput != null && userInput.equals(CONFIRM_VALUE)) { classList.deleteAllClasses(); storage.save(classList); diff --git a/src/main/java/taa/command/ResetCommand.java b/src/main/java/taa/command/ResetCommand.java index f8010293b3..2d1bd1f3b7 100644 --- a/src/main/java/taa/command/ResetCommand.java +++ b/src/main/java/taa/command/ResetCommand.java @@ -37,7 +37,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep String userInput = ui.getUserInput(PROMPT_WITHIN_COMMAND, true); String message; - if (userInput.equals(CONFIRM_VALUE)) { + if (userInput != null && userInput.equals(CONFIRM_VALUE)) { classList.deleteAllClasses(); storage.save(classList); From dfe13d44065206733786c9370c79cc9084ba4a94 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 1 Nov 2021 19:42:22 +0800 Subject: [PATCH 288/543] Update parser to generate regex pattern based on constant --- src/main/java/taa/Parser.java | 59 ++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 4e1fb3a8d7..3350804cba 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -43,11 +43,13 @@ import java.util.regex.Pattern; public class Parser { - private static final String ARGUMENT_VALID_REGEX = "^[0-9a-zA-Z\\-_()\\s.]+$"; + private static final String ARGUMENT_VALID_REGEX = "0-9a-zA-Z\\s"; + private static final char[] VALID_SPECIAL_CHARACTERS = {'-', '_', '(', ')', '.'}; private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown Command"; - private static final String MESSAGE_INVALID_VALUE = "Invalid characters in value(s). Only alphanumeric characters, " - + "spaces, and some special characters are allowed.\nAllowed special characters: - _ ( ) ."; + + private static final String MESSAGE_FORMAT_INVALID_VALUE = "Invalid characters in value(s). Only alphanumeric " + + "characters, spaces, and certain special characters are allowed.\nAllowed special characters: %s"; public static Command parseUserInput(String userInput) throws TaaException { String[] userInputSplit = splitFirstSpace(userInput); @@ -257,7 +259,7 @@ public static HashMap getArgumentsFromString(String string, Stri value = value.trim(); if (!isValueValid(value)) { - throw new TaaException(MESSAGE_INVALID_VALUE); + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_VALUE, getSpecialCharactersAsString())); } result.put(key, value); @@ -271,8 +273,55 @@ public static boolean isValueValid(String value) { return true; } - Pattern pattern = Pattern.compile(ARGUMENT_VALID_REGEX); + StringBuilder stringBuilder = new StringBuilder("^["); + stringBuilder.append(ARGUMENT_VALID_REGEX); + for (char c : VALID_SPECIAL_CHARACTERS) { + stringBuilder.append(convertToRegexPattern(c)); + } + stringBuilder.append("]+$"); + String regexStr = stringBuilder.toString(); + + Pattern pattern = Pattern.compile(regexStr); Matcher matcher = pattern.matcher(value); return matcher.find(); } + + private static String convertToRegexPattern(char c) { + boolean needEscape; + switch (c) { + case '^': + case '-': + case '[': + case ']': + case '.': + needEscape = true; + break; + + default: + needEscape = false; + } + + String patternStr; + if (needEscape) { + patternStr = String.format("\\%c", c); + } else { + patternStr = String.format("%c", c); + } + + return patternStr; + } + + private static String getSpecialCharactersAsString() { + char[] validSpecialCharacters = VALID_SPECIAL_CHARACTERS; + + StringBuilder stringBuilder = new StringBuilder(); + for (int i = 0; i < validSpecialCharacters.length; i += 1) { + if (i > 0) { + stringBuilder.append(" "); + } + stringBuilder.append(validSpecialCharacters[i]); + } + + return stringBuilder.toString(); + } } From d486a2f5867d0f9c4fae83a6bc4242e576cbf473 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Mon, 1 Nov 2021 22:59:26 +0800 Subject: [PATCH 289/543] add sequence diagrams and author tag --- .../DeleteAttendanceSequenceDiagram.png | Bin 0 -> 66003 bytes .../DeleteAttendanceSequenceDiagram.puml | 82 ++++++++++++++ .../ListAttendanceSequenceDiagram.png | Bin 0 -> 71091 bytes .../ListAttendanceSequenceDiagram.puml | 91 +++++++++++++++ .../ListLessonAttendanceSequenceDiagram.png | Bin 0 -> 72097 bytes .../ListLessonAttendanceSequenceDiagram.puml | 91 +++++++++++++++ .../diagrams/SetAttendanceSequenceDiagram.png | Bin 0 -> 87345 bytes .../SetAttendanceSequenceDiagram.puml | 106 +++++++++++++++++- src/main/java/taa/attendance/Attendance.java | 1 + .../java/taa/attendance/AttendanceList.java | 2 +- .../taa/attendance/LessonAttendanceList.java | 1 + .../attendance/DeleteAttendanceCommand.java | 1 + .../attendance/ListAttendanceCommand.java | 1 + .../ListLessonAttendanceCommand.java | 1 + .../attendance/SetAttendanceCommand.java | 1 + 15 files changed, 371 insertions(+), 7 deletions(-) create mode 100644 docs/diagrams/DeleteAttendanceSequenceDiagram.png create mode 100644 docs/diagrams/DeleteAttendanceSequenceDiagram.puml create mode 100644 docs/diagrams/ListAttendanceSequenceDiagram.png create mode 100644 docs/diagrams/ListAttendanceSequenceDiagram.puml create mode 100644 docs/diagrams/ListLessonAttendanceSequenceDiagram.png create mode 100644 docs/diagrams/ListLessonAttendanceSequenceDiagram.puml create mode 100644 docs/diagrams/SetAttendanceSequenceDiagram.png diff --git a/docs/diagrams/DeleteAttendanceSequenceDiagram.png b/docs/diagrams/DeleteAttendanceSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..e458fa559cd64b5f71fbba437cc347ca7f79a78a GIT binary patch literal 66003 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
y2FSJBHt#A)>yfiqLc4cSxg#K&d?4vCp6T!v8 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\nParser" as parser +Participant ":DeleteAttendanceCommand" as deleteAttendanceCommand +Participant ":ModuleList" as moduleList +Participant ":Module" as module +Participant ":StudentList" as studentList +Participant ":Student" as student +Participant ":AttendanceList" as attendanceList +Participant ":Storage" as storage + +activate taa + +taa -> ui : getUserInput() +activate ui + +user -> ui : "delete_attendance c/CS2113T\ns/1 l/1" +ui --> taa : userInput:String +deactivate ui + +taa -> parser : parseUserInput(userInput) +activate parser + +create deleteAttendanceCommand +parser -> deleteAttendanceCommand +activate deleteAttendanceCommand +deleteAttendanceCommand -> parser +deactivate deleteAttendanceCommand + +parser --> taa : deleteAttendanceCommand:command +deactivate parser + +taa -> deleteAttendanceCommand : checkArgument() +activate deleteAttendanceCommand + +deleteAttendanceCommand --> taa +deactivate deleteAttendanceCommand + +taa -> deleteAttendanceCommand : execute(moduleList:ModuleList, ui:Ui, storage:Storage) +activate deleteAttendanceCommand + +deleteAttendanceCommand -> moduleList : getModuleWithCode(moduleCode:String) +activate moduleList +moduleList --> deleteAttendanceCommand : module:Module +deactivate moduleList + +deleteAttendanceCommand -> module : getStudentList() +activate module +module -> studentList : getStudentAt(studentIndex:int) +deactivate module +activate studentList +studentList --> deleteAttendanceCommand : student:StudentList +deactivate studentList + +deleteAttendanceCommand -> student : getAttendanceList() +activate student +student --> deleteAttendanceCommand : attendanceList:AttendanceList +deactivate student + +deleteAttendanceCommand -> attendanceList : deleteAttendance(lessonNumber:int) +activate attendanceList +attendanceList --> deleteAttendanceCommand : attendance:Attendance +deactivate attendanceList + +deleteAttendanceCommand -> storage : save(moduleList:ModuleList) +activate storage +storage --> deleteAttendanceCommand +deactivate storage + +deleteAttendanceCommand -> ui : printMessage("Attendance removed for ...") +activate ui +ui -> user : Display message:\n"Attendance removed for ..." +ui --> deleteAttendanceCommand +deactivate ui + +deactivate deleteAttendanceCommand + +@enduml \ No newline at end of file diff --git a/docs/diagrams/ListAttendanceSequenceDiagram.png b/docs/diagrams/ListAttendanceSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..65e714354f5971f9fafe9fbb8dc645739639fcab GIT binary patch literal 71091 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 literal 0 HcmV?d00001 diff --git a/docs/diagrams/ListAttendanceSequenceDiagram.puml b/docs/diagrams/ListAttendanceSequenceDiagram.puml new file mode 100644 index 0000000000..30a27074cf --- /dev/null +++ b/docs/diagrams/ListAttendanceSequenceDiagram.puml @@ -0,0 +1,91 @@ +@startuml +!include style.puml + +Actor User as user +Participant ":Ui" as ui +Participant ":Taa" as taa +Participant "<>\nParser" as parser +Participant ":ListAttendanceCommand" as listAttendanceCommand +Participant ":ModuleList" as moduleList +Participant ":Module" as module +Participant ":StudentList" as studentList +Participant ":Student" as student +Participant ":AttendanceList" as attendanceList + +activate taa + +taa -> ui : getUserInput() +activate ui + +user -> ui : "list_attendance c/CS2113T\ns/1" +ui --> taa : userInput:String +deactivate ui + +taa -> parser : parseUserInput(userInput) +activate parser + +create listAttendanceCommand +parser -> listAttendanceCommand +activate listAttendanceCommand +listAttendanceCommand -> parser +deactivate listAttendanceCommand + +parser --> taa : listAttendanceCommand:command +deactivate parser + +taa -> listAttendanceCommand : checkArgument() +activate listAttendanceCommand + +listAttendanceCommand --> taa +deactivate listAttendanceCommand + +taa -> listAttendanceCommand : execute(moduleList:ModuleList, ui:Ui, storage:Storage) +activate listAttendanceCommand + +listAttendanceCommand -> moduleList : getModuleWithCode(moduleCode:String) +activate moduleList +moduleList --> listAttendanceCommand : module:Module +deactivate moduleList + + +listAttendanceCommand -> module : getStudentList() +activate module +module --> listAttendanceCommand : studentList:StudentList +deactivate module + +listAttendanceCommand -> studentList : getStudentAt(studentIndex:int) +activate studentList +studentList --> listAttendanceCommand : student:StudentList +deactivate studentList + +listAttendanceCommand -> student : getAttendanceList() +activate student +student --> listAttendanceCommand : attendanceList:AttendanceList +deactivate student + +listAttendanceCommand -> attendanceList : getSize() +activate attendanceList +attendanceList --> listAttendanceCommand : size:int +deactivate attendanceList + +alt#Gold #Pink size==0 + listAttendanceCommand -> ui : printMessage("There is no recorded attendance ...") + activate ui + ui -> user : Display message:\n"There is no recorded ..." + ui --> listAttendanceCommand + deactivate ui + + + +else #LightGreen else + listAttendanceCommand -> ui : printMessage("Attendance for ...") + activate ui + ui -> user : Display message:\n"Attendance for ..." + ui --> listAttendanceCommand + deactivate ui +end + +deactivate listAttendanceCommand + + +@enduml \ No newline at end of file diff --git a/docs/diagrams/ListLessonAttendanceSequenceDiagram.png b/docs/diagrams/ListLessonAttendanceSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..e9c350c9893194f3403a944e2181d38fa1e56b88 GIT binary patch literal 72097 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 MO>\nParser" as parser +Participant ":ListLessonAttendanceCommand" as listLessonAttendanceCommand +Participant ":ModuleList" as moduleList +Participant ":Module" as module +Participant ":LessonAttendanceList" as lessonAttendanceList +Participant ":AttendanceList" as attendanceList + +activate taa + +taa -> ui : getUserInput() +activate ui + +user -> ui : "list_lesson_attendance c/CS2113T\nl/1" +ui --> taa : userInput:String +deactivate ui + +taa -> parser : parseUserInput(userInput) +activate parser + +create listLessonAttendanceCommand +parser -> listLessonAttendanceCommand +activate listLessonAttendanceCommand +listLessonAttendanceCommand -> parser +deactivate listLessonAttendanceCommand + +parser --> taa : listLessonAttendanceCommand:command +deactivate parser + +taa -> listLessonAttendanceCommand : checkArgument() +activate listLessonAttendanceCommand + +listLessonAttendanceCommand --> taa +deactivate listLessonAttendanceCommand + +taa -> listLessonAttendanceCommand : execute(moduleList:ModuleList, ui:Ui, storage:Storage) +activate listLessonAttendanceCommand + +listLessonAttendanceCommand -> moduleList : getModuleWithCode(moduleCode:String) +activate moduleList +moduleList --> listLessonAttendanceCommand : module:Module +deactivate moduleList + + +listLessonAttendanceCommand -> module : getStudentList() +activate module +module --> listLessonAttendanceCommand : studentList:StudentList +deactivate module + +create lessonAttendanceList +listLessonAttendanceCommand -> lessonAttendanceList : new LessonAttendanceList() +activate lessonAttendanceList +lessonAttendanceList --> listLessonAttendanceCommand : lessonAttendances:lessonAttendanceList +deactivate lessonAttendanceList + +listLessonAttendanceCommand -> lessonAttendanceList : setLessonAttendances(studentList:StudentList, lessonNumber:int) +activate lessonAttendanceList +lessonAttendanceList --> listLessonAttendanceCommand : +deactivate lessonAttendanceList + +listLessonAttendanceCommand -> attendanceList : getSize() +activate attendanceList +attendanceList --> listLessonAttendanceCommand : size:int +deactivate attendanceList + +alt#Gold #Pink size==0 + listLessonAttendanceCommand -> ui : printMessage("There is no recorded attendance ...") + activate ui + ui -> user : Display message:\n"There is no recorded ..." + ui --> listLessonAttendanceCommand + deactivate ui + + + +else #LightGreen else + listLessonAttendanceCommand -> ui : printMessage("Class attendance for Lesson ...") + activate ui + ui -> user : Display message:\n("Class attendance for Lesson ...") + ui --> listLessonAttendanceCommand + deactivate ui +end + +deactivate listLessonAttendanceCommand + + +@enduml \ No newline at end of file diff --git a/docs/diagrams/SetAttendanceSequenceDiagram.png b/docs/diagrams/SetAttendanceSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..8c65bb4bb4b4a96feff931260aa77d957fe93004 GIT binary patch literal 87345 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�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񜽝GZMy2Xfp}ZWtGz^v zR^o4%hpz?X;l0qH#9z!C)8h$*rgvGW>aD966nUb;Y{5W_tYLWql%3Dep)x`tBra=< zCOAW-eE33lclQOw-I@i))E)qZIVL6s>^5rz*a1uee^^#hLU5GldVeq_wPMF zulghCT6omDu$mZTp%z2WYWeeAeW?~Vdi5~W`q;;;8AySYloTM;vUWh4lY;wf0aAk) zZ`-@kjyJNUi`)K^o$~0$o+GkhXsN4JQQ%XK!jPPxtfCmUk|Ef|E|45Oo ziG2u>QMP)vN=lQ2!v;++n&crwP-n@u>rMab-4i%BrvneEP}pJSZf|sC$XRS+LW106 zyH9W)@Jl@{IWC}b!=ewXdP}*vjt`OcpvKq01AI*j&O>y1zqGqcWy}(wP)70xt0L>W z=X$DiAc@Y%bcdI^G-Kf?KqA(vAAT>N1I6*?k*z>0!?@f%-~zq*u>HW7(O&qEYeF2O zpv@#ZE-voHivoeT*jV((n_N|`pwG9LwL%F6i(AD7%~_wTwJ>&&)yO6t#lGC!+^`WK zp>l9=Ks`ewSQM8y|Flx1AG_?#*zz}33cK`Z4deCb-EPLSVE9`i$rFVOkuJ5Jof(4K z>9p41)&1Jea$1AYDoK{-UWiZ(F!0%>tilpv;A(FYc zX;ZnmDJ^p{jZaX!W>~~GrvLEW^lf?pvH8ji$@lyC=TcE{UIBd~QT`ud_zUCXcDFtr zWC^V)H{&-`uz$Oh!N2)KlBbUte1Rl>>@#~zH#TRdwuW|ev&Y>CcX%<}`=mj~BCrZ_ zTD5`kp96EU&GbMwZ||wXeiPQM2b$nT_nYfx*0c+KjYZX1gY$?}F4~r_rwc=;3mi%u z&lpRMut)xMuJKBHA${y2{Y8<*>XG6jR8-KFpg-vrS_`A(k57g_ar5}Vf75HVJ({al z6s&M-iu)Bb9-~BoR#+#t+NqyykXm;aB)eB5XpE5Q=j*@HH~tU*(gh?v9*E@JaD0{8 zC;jJ0v!}ObHLFq?8p4QxdJZD`Bv+CA5AUB%U|eVU{|kgv~vR{rTpC+1E_~6g+Jv^bS5*JEe2| zpu4Xs=R~gy3<}bqy>Ahx59$X7254+sC&;l(c3i#t)~DzSTMd?P+%})H=TsrmCerK@ z<1f92aj>F%DWlhKSXJ7#YRn8WcVxq#&=O%GpCkgWYA`f>vjcdxry5p)q4F-$un(@EWsJxlZ@iop z!keaiX8U~^w#7rQ0|Uc8GrfTh^4kqK#T)H@ec*H%P8@&$`=Q9?Mnq#bX2=)Y@v-!kP9-JNtik z`I5u>POxZN|IovmyAP&+wc^au%Sgi!@?01gc7hMs+*jKKp$mHM%ONoC`@jDsO+H-Y XvufAwpOG$ghLehCjwc*7{QG|afzUO0 literal 0 HcmV?d00001 diff --git a/docs/diagrams/SetAttendanceSequenceDiagram.puml b/docs/diagrams/SetAttendanceSequenceDiagram.puml index ac2c2d3913..c881367699 100644 --- a/docs/diagrams/SetAttendanceSequenceDiagram.puml +++ b/docs/diagrams/SetAttendanceSequenceDiagram.puml @@ -1,11 +1,105 @@ @startuml -'https://plantuml.com/sequence-diagram +!include style.puml -autonumber +Actor User as user +Participant ":Ui" as ui +Participant ":Taa" as taa +Participant "<>\nParser" as parser +Participant ":SetAttendanceCommand" as setAttendanceCommand +Participant ":ModuleList" as moduleList +Participant ":Module" as module +Participant ":StudentList" as studentList +Participant ":Student" as student +Participant ":AttendanceList" as attendanceList +Participant ":Attendance" as attendance +Participant ":Storage" as storage -Alice -> Bob: Authentication Request -Bob --> Alice: Authentication Response +activate taa + +taa -> ui : getUserInput() +activate ui + +user -> ui : "set_attendance c/CS2113T\ns/1 l/1 p/1" +ui --> taa : userInput:String +deactivate ui + +taa -> parser : parseUserInput(userInput) +activate parser + +create setAttendanceCommand +parser -> setAttendanceCommand +activate setAttendanceCommand +setAttendanceCommand -> parser +deactivate setAttendanceCommand + +parser --> taa : setAttendanceCommand:command +deactivate parser + +taa -> setAttendanceCommand : checkArgument() +activate setAttendanceCommand + +setAttendanceCommand --> taa +deactivate setAttendanceCommand + +taa -> setAttendanceCommand : execute(moduleList:ModuleList, ui:Ui, storage:Storage) +activate setAttendanceCommand + +setAttendanceCommand -> moduleList : getModuleWithCode(moduleCode:String) +activate moduleList +moduleList --> setAttendanceCommand : module:Module +deactivate moduleList + + +setAttendanceCommand -> module : getStudentList() +activate module +module --> setAttendanceCommand : studentList:StudentList +deactivate module + +setAttendanceCommand -> studentList : getStudentAt(studentIndex:int) +activate studentList +studentList --> setAttendanceCommand : student:StudentList +deactivate studentList + +setAttendanceCommand -> student : getAttendanceList() +activate student +student --> setAttendanceCommand : attendanceList:AttendanceList +deactivate student + +setAttendanceCommand -> attendanceList : getAttendance(lessonNumber:int) +activate attendanceList +attendanceList --> setAttendanceCommand : attendance:Attendance +deactivate attendanceList + +alt#Gold #LightGreen attendance==null + create attendance + setAttendanceCommand -> attendance : new Attendance(lessonNumber:int, isPresent:boolean) + activate attendance + attendance --> setAttendanceCommand : attendance:Attendance + deactivate attendance + + setAttendanceCommand -> attendanceList : addAttendance(attendance:Attendance) + activate attendanceList + attendanceList --> setAttendanceCommand + deactivate attendanceList + +else #LightBlue else + setAttendanceCommand -> attendance : setPresent(isPresent:boolean) + activate attendance + attendance --> setAttendanceCommand : + deactivate attendance +end + +setAttendanceCommand -> storage : save(moduleList:ModuleList) +activate storage +storage --> setAttendanceCommand +deactivate storage + +setAttendanceCommand -> ui : printMessage("Attendance set for ...") +activate ui +ui -> user : Display message:\n"Attendance set for ..." +ui --> setAttendanceCommand +deactivate ui + +deactivate setAttendanceCommand -Alice -> Bob: Another authentication Request -Alice <-- Bob: another authentication Response @enduml \ No newline at end of file diff --git a/src/main/java/taa/attendance/Attendance.java b/src/main/java/taa/attendance/Attendance.java index 0dd91d1817..0889411043 100644 --- a/src/main/java/taa/attendance/Attendance.java +++ b/src/main/java/taa/attendance/Attendance.java @@ -1,5 +1,6 @@ package taa.attendance; +//@@author daknam2001 import taa.ClassChecker; public class Attendance implements ClassChecker { diff --git a/src/main/java/taa/attendance/AttendanceList.java b/src/main/java/taa/attendance/AttendanceList.java index eb64e43156..69802db8a7 100644 --- a/src/main/java/taa/attendance/AttendanceList.java +++ b/src/main/java/taa/attendance/AttendanceList.java @@ -1,6 +1,6 @@ package taa.attendance; - +//@@author daknam2001 import taa.ClassChecker; import java.util.ArrayList; diff --git a/src/main/java/taa/attendance/LessonAttendanceList.java b/src/main/java/taa/attendance/LessonAttendanceList.java index 76e8eecadd..b5df30472c 100644 --- a/src/main/java/taa/attendance/LessonAttendanceList.java +++ b/src/main/java/taa/attendance/LessonAttendanceList.java @@ -1,5 +1,6 @@ package taa.attendance; +//@@author daknam2001 import taa.student.Student; import taa.student.StudentList; diff --git a/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java b/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java index 59f4b0352a..fa52c37910 100644 --- a/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/DeleteAttendanceCommand.java @@ -1,5 +1,6 @@ package taa.command.attendance; +//@@author daknam2001 import taa.Ui; import taa.attendance.Attendance; import taa.attendance.AttendanceList; diff --git a/src/main/java/taa/command/attendance/ListAttendanceCommand.java b/src/main/java/taa/command/attendance/ListAttendanceCommand.java index 9666fde0c1..9340d0d9d4 100644 --- a/src/main/java/taa/command/attendance/ListAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/ListAttendanceCommand.java @@ -1,5 +1,6 @@ package taa.command.attendance; +//@@author daknam2001 import taa.Ui; import taa.attendance.AttendanceList; import taa.command.Command; diff --git a/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java b/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java index 2144b430f1..c0822c0412 100644 --- a/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/ListLessonAttendanceCommand.java @@ -1,5 +1,6 @@ package taa.command.attendance; +//@@author daknam2001 import taa.Ui; import taa.attendance.Attendance; import taa.attendance.LessonAttendanceList; diff --git a/src/main/java/taa/command/attendance/SetAttendanceCommand.java b/src/main/java/taa/command/attendance/SetAttendanceCommand.java index d4d558fa26..762fe81ddf 100644 --- a/src/main/java/taa/command/attendance/SetAttendanceCommand.java +++ b/src/main/java/taa/command/attendance/SetAttendanceCommand.java @@ -1,5 +1,6 @@ package taa.command.attendance; +//@@author daknam2001 import taa.attendance.AttendanceList; import taa.command.Command; import taa.exception.TaaException; From 47be31d93e6960fbfee0993d75cdae123bd8a844 Mon Sep 17 00:00:00 2001 From: Kong Dak Nam Date: Mon, 1 Nov 2021 23:06:22 +0800 Subject: [PATCH 290/543] add set attendance sequence diagram to dg --- docs/DeveloperGuide.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index eb84f3f08e..2baec78e62 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -175,6 +175,9 @@ ArrayList. * `AttendanceList#sortAttendances` - Sorts the attendance in the `attendances` ArrayList in ascending order based on lesson number. +The sequence diagram shown below illustrates how the `set_attendance` command works: +![SetAttendanceSequenceDiagram](diagrams/SetAttendanceSequenceDiagram.png) + Below is an example scenario of how the set attendance feature behaves at each step: * Step 1 - The user executes `set_attendance c/CS2113T s/1 l/1 p/1` to set an attendance to `Present` for student at index `1`, lesson number `1` to set a student's attendance for a lesson. The `set_attendance` command calls the From fc699e49228143348b192ad8f0ae57149e0ff59e Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Tue, 2 Nov 2021 16:28:27 +0800 Subject: [PATCH 291/543] update UG --- docs/UserGuide.md | 64 +++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 62 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index eed9c7dde3..bdb099abcf 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -22,9 +22,13 @@ If you can type fast, TAA can help keep track of your modules and students faste * [Editing marks for a student's assessment: `edit_mark`](#editing-marks-for-a-students-assessment-edit_mark) * [Deleting marks for a student's assessment: `delete_mark`](#deleting-marks-for-a-students-assessment-delete_mark) * [Viewing average marks for an assessment: `average_marks`](#viewing-average-marks-for-an-assessment-average_marks) + * [Sorting and listing students in a module by their overall score: `sort_by_scores`](#sorting-and-listing-students-in-a-module-by-their-overall-score-sort_by_scores) * [Listing attendance for a particular student: `list_attendance`](#listing-attendance-for-a-particular-student-list_attendance) * [Setting attendance for a particular lesson for a student: `set_attendance`](#setting-attendance-for-a-particular-lesson-for-a-student-set_attendance) * [Deleting attendance for a particular lesson for a student: `delete_attendance`](#deleting-attendance-for-a-particular-lesson-for-a-student-delete_attendance) + * [Setting comment for a particular student: `set_comment`](#setting-comment-for-a-particular-student-set_comment) + * [Deleting comment for a particular student: `delete_comment`](#deleting-comment-for-a-particular-student-delete_comment) + * [Listing comments for all students in a module `list_comment`](#listing-comments-for-all-students-in-a-module-list_comment) * [Viewing help: `help`](#viewing-help-help) * [Exiting the program: `exit`](#exiting-the-program-exit) * [FAQ](#faq) @@ -301,6 +305,20 @@ Examples:
+### Sorting and listing students in a module by their overall score: `sort_by_scores` +Sorts and lists students in a module by their overall score according to the desired format. +Only marks currently added to students will be taken into consideration for their scores. + +Format: `sort_by_scores c/ o/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `ORDER` refers to the sorting order. `asc` for ascending and `desc` for descending. + +Examples: +* `sort_by_scores c/CS2113T o/asc` +* `sort_by_scores c/CS2101 o/desc` + +
+ ### Listing attendance for a particular student: `list_attendance` Lists a student's attendance. @@ -331,6 +349,46 @@ Format: `delete_attendance c/ s/ l/`
+### Setting comment for a particular student: `set_comment` +Sets a comment for a student. + +Format: `set_comment c/ s/ t/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +* `COMMENT` refers to the comment to be set. +> 💡 **Note:**
+> The new comment will overwrite any previous comment set + +Examples: +* `set_comment c/CS2113t s/1 t/Doing well in class` +* `set_comment c/CS2113t s/1 t/Needs help understanding java` + +
+ +### Deleting comment for a particular student: `delete_comment` +Deletes the comment for a student. + +Format: `delete_comment c/ s/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `STUDENT_INDEX` refers to the index of the student in the student list of the module. + +Examples: +* `delete_comment c/CS2113T s/1` +* `delete_comment c/CS2113T s/5` + +
+ +### Listing comments for all students in a module: `list_comment` +List comments for all students in a module + +Format: `list_comment c/` + +Examples: +* `list_comment c/CS2113T` +* `list_comment c/CS2101` + +
+ ### Viewing help: `help` Displays the list of available commands and how to use them. @@ -351,8 +409,6 @@ Format: `exit` ## Command Summary -{Give a 'cheat sheet' of commands here} - Action | Format | ------ | --------------- | Listing all modules | `list_modules` @@ -373,8 +429,12 @@ Setting marks for a student's assessment | `set_marks c/ s/ s/ a/ m/` Deleting marks for a student's assessment | `delete_mark c/ s/ a/` Viewing average marks for an assessment | `average_marks c/ a/` +Sorting and listing students by overall score | `sort_by_scores c/ o/` Listing attendance for a particular student | `list_attendance c/ s/` Setting attendance for a particular lesson for a student | `set_attendance c/ s/ l/ p/` Deleting attendance for a particular lesson for a student | `delete_attendance c/ s/ l/` +Setting comment for a particular student | `set_comment c/ s/ t/` +Deleting comment for a particular student | `delete_comment c/ s/` +List comments for all students in a module | `list_comment c/` Viewing help | `help` Exiting the program | `exit` From 5524d57ab58812d1ce2f642d514b628cecd6db82 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Tue, 2 Nov 2021 16:39:06 +0800 Subject: [PATCH 292/543] edit user guide for set_mark --- docs/UserGuide.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index eed9c7dde3..f23869559c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -18,7 +18,7 @@ If you can type fast, TAA can help keep track of your modules and students faste * [Editing an assessment in a module: `edit_assessment`](#editing-an-assessment-in-a-module-edit_assessment) * [Deleting an assessment from a module: `delete_assessment`](#deleting-an-assessment-from-a-module-delete_assessment) * [Listing marks for an assessment: `list_marks`](#listing-marks-for-an-assessment-list_marks) - * [Setting marks for a student's assessment: `set_marks`](#setting-marks-for-a-students-assessment-set_marks) + * [Setting mark for a student's assessment: `set_mark`](#setting-mark-for-a-students-assessment-set_mark) * [Editing marks for a student's assessment: `edit_mark`](#editing-marks-for-a-students-assessment-edit_mark) * [Deleting marks for a student's assessment: `delete_mark`](#deleting-marks-for-a-students-assessment-delete_mark) * [Viewing average marks for an assessment: `average_marks`](#viewing-average-marks-for-an-assessment-average_marks) @@ -229,18 +229,18 @@ Examples:
-### Setting marks for a student's assessment: `set_marks` +### Setting mark for a student's assessment: `set_mark` Adds a student's marks for an assessment. -Format: `set_marks c/ s/ a/ m/` +Format: `set_mark c/ s/ a/ m/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). * `STUDENT_INDEX` refers to the index of the student in the student list of the module. * `ASSESSMENT_NAME` refers to the name of the particular assessment. * `MARKS` refers to the marks given for the assessment. Examples: -* `set_marks c/CS2113T s/1 a/Midterms m/70.6` -* `set_marks c/CS2101 s/3 a/Oral Presentation m/80` +* `set_mark c/CS2113T s/1 a/Midterms m/70.6` +* `set_mark c/CS2101 s/3 a/Oral Presentation m/80`
@@ -369,7 +369,7 @@ Adding an assessment to a module | `add_assessment c/ n/ n/ [nn/] [m/]` Deleting an assessment from a module | `delete_assessment c/ n/` Listing marks for an assessment: | `list_marks c/ a/` -Setting marks for a student's assessment | `set_marks c/ s/ a/ m/` +Setting marks for a student's assessment | `set_mark c/ s/ a/ m/` Editing marks for a student's assessment | `edit_mark c/ s/ a/ m/` Deleting marks for a student's assessment | `delete_mark c/ s/ a/` Viewing average marks for an assessment | `average_marks c/ a/` From fd98fa1107d497f25cad7dfe7214b946c125074e Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Tue, 2 Nov 2021 16:44:32 +0800 Subject: [PATCH 293/543] fix format for user guide for median_mark and average_marks --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 5088e6dc2f..cfab6504fc 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -301,7 +301,7 @@ Examples: Computes and prints the median mark for an assessment. If there are unmarked students, the median will be computed within the marked students only. -Format: `set_marks c/ a/` +Format: `median_mark c/ a/` * `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** * `ASSESSMENT_NAME` refers to the name of the particular assessment. From 83687dacb2148aceb7d16b17472672c874624283 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Tue, 2 Nov 2021 16:45:14 +0800 Subject: [PATCH 294/543] update commands to use class id --- docs/UserGuide.md | 63 +++++++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 29 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 64788a4b18..77bb9f2857 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -103,11 +103,11 @@ Examples: Shows a list of all students in a particular class. Format: `list_students c/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). **Cannot contain whitespaces.** Examples: -* `list_students c/CS2113T-F12` -* `list_students c/CS2101-C03` +* `list_students c/CS2113T-F11` +* `list_students c/CS2101-C04`
@@ -115,13 +115,13 @@ Examples: Adds a student to a particular class. Format: `add_student c/ i/ n/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). **Cannot contain whitespaces.** * `STUDENT_ID` refers to the ID of the student (e.g. A0217978J). * `STUDENT_NAME` refers to the name of the student (e.g. Jon Lim). Examples: -* `add_student c/CS2113T-F12 i/a0212345x n/Jon Lim` -* `add_student c/CS2101-C03 n/Jonny Lims i/a1234567i` +* `add_student c/CS2113T-F11 i/a0212345x n/Jon Lim` +* `add_student c/CS2101-C04 n/Jonny Lims i/a1234567i`
@@ -129,14 +129,14 @@ Examples: Edits student information from a particular class Format: `edit_student c/ s/ i/ n/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). **Cannot contain whitespaces.** * `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `STUDENT_ID` refers to the updated ID of the student (e.g. A0217978J). * `STUDENT_NAME` refers to the updated name of the student (e.g. Jon Limbs). Examples: -* `edit_student c/CS2113T-F12 s/1 i/a03452345x n/Jon Lim` -* `edit_student c/CS2101-C03 s/5 n/Jonny Lims i/a120067i` +* `edit_student c/CS2113T-F11 s/1 i/a03452345x n/Jon Lim` +* `edit_student c/CS2101-D03 s/5 n/Jonny Lims i/a120067i`
@@ -144,11 +144,11 @@ Examples: Deletes student information from a particular class. Format: `delete_student c/ s/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). **Cannot contain whitespaces.** * `STUDENT_INDEX` refers to the index of the student in the student list of the class. Examples: -* `delete_student c/CS2113T-F12 s/1` +* `delete_student c/CS2113T-F11 s/1`
@@ -156,12 +156,12 @@ Examples: Displays all students in the class matching the keyword along with their index. Format: `find_student c/ k/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). **Cannot contain whitespaces.** * `KEYWORD` refers to the keyword used to search the student list of the class. Examples: -* `find_student c/CS2113T-F12 k/123` -* `find_student c/CS2101-C03 k/Jon` +* `find_student c/CS2113T-F11 k/123` +* `find_student c/CS2101-D03 k/Jon`
@@ -315,13 +315,13 @@ Examples: Sorts and lists students in a module by their overall score according to the desired format. Only marks currently added to students will be taken into consideration for their scores. -Format: `sort_by_scores c/ o/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +Format: `sort_by_scores c/ o/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** * `ORDER` refers to the sorting order. `asc` for ascending and `desc` for descending. Examples: -* `sort_by_scores c/CS2113T o/asc` -* `sort_by_scores c/CS2101 o/desc` +* `sort_by_scores c/CS2113T-F12 o/asc` +* `sort_by_scores c/CS2113T-F12 o/desc`
@@ -358,40 +358,41 @@ Format: `delete_attendance c/ s/ l/` ### Setting comment for a particular student: `set_comment` Sets a comment for a student. -Format: `set_comment c/ s/ t/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +Format: `set_comment c/ s/ t/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** * `STUDENT_INDEX` refers to the index of the student in the student list of the module. * `COMMENT` refers to the comment to be set. > 💡 **Note:**
> The new comment will overwrite any previous comment set Examples: -* `set_comment c/CS2113t s/1 t/Doing well in class` -* `set_comment c/CS2113t s/1 t/Needs help understanding java` +* `set_comment c/CS2113T-F12 s/1 t/Doing well in class` +* `set_comment c/CS2113T-F12 s/1 t/Needs help understanding java`
### Deleting comment for a particular student: `delete_comment` Deletes the comment for a student. -Format: `delete_comment c/ s/` -* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +Format: `delete_comment c/ s/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** * `STUDENT_INDEX` refers to the index of the student in the student list of the module. Examples: -* `delete_comment c/CS2113T s/1` -* `delete_comment c/CS2113T s/5` +* `delete_comment c/CS2113T-F12 s/1` +* `delete_comment c/CS2113T-F12 s/5`
### Listing comments for all students in a module: `list_comment` List comments for all students in a module -Format: `list_comment c/` +Format: `list_comment c/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** Examples: -* `list_comment c/CS2113T` -* `list_comment c/CS2101` +* `list_comment c/CS2113T-F12` +* `list_comment c/CS2101-D03`
@@ -452,9 +453,13 @@ Setting marks for a student's assessment | `set_marks c/ s/ s/ a/ m/` Deleting marks for a student's assessment | `delete_mark c/ s/ a/` Viewing average marks for an assessment | `average_marks c/ a/` +Sorting and listing students by overall score | `sort_by_scores c/ o/` Listing attendance for a particular student | `list_attendance c/ s/` Setting attendance for a particular lesson for a student | `set_attendance c/ s/ l/ p/` Deleting attendance for a particular lesson for a student | `delete_attendance c/ s/ l/` +Setting comment for a particular student | `set_comment c/ s/ t/` +Deleting comment for a particular student | `delete_comment c/ s/` +List comments for all students in a module | `list_comment c/` Viewing help | `help` Exiting the program | `exit` From 232ee055d039a3ead6f4bab896abc2eb67c1f6f2 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Tue, 2 Nov 2021 16:45:56 +0800 Subject: [PATCH 295/543] fix format for delete_mark in ug --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index cfab6504fc..05d0cddccd 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -272,7 +272,7 @@ Examples: ### Deleting marks for a student's assessment: `delete_mark` Deletes a student's marks for an assessment. -Format: `set_marks c/ s/ a/` +Format: `delete_mark c/ s/ a/` * `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** * `STUDENT_INDEX` refers to the index of the student in student list of the class. * `ASSESSMENT_NAME` refers to the name of the particular assessment. From f53adc24f7f1068d093e399b2ffa27395b30a98e Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Tue, 2 Nov 2021 16:58:04 +0800 Subject: [PATCH 296/543] fix command summary to be more clear which command is for which object --- docs/UserGuide.md | 68 +++++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 46 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 05d0cddccd..40f74c6ed7 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -434,51 +434,27 @@ Format: `reset` Action | Format | ------ | --------------- | -<<<<<<< HEAD -Listing all modules | `list_modules` -Adding a module | `add_module c/ [n/]` -Editing a module | `edit_module c/ [nc/] [n/]` -Deleting a module | `delete_module c/` -Listing all students in a module | `list_students c/` -Adding a student to a module | `add_student c/ i/ n/` -Editing a student's information in a module | `edit_student c/ s/ i/ n/` -Deleting a student from a module | `delete_student c/ s/` -Finding students in a module given a keyword | `find_student c/ k/` -Listing all assessments in a module | `list_assessments c/` -Adding an assessment to a module | `add_assessment c/ n/ m/ w/` -Editing an assessment in a module | `edit_assessment c/ n/ [nn/] [m/]` -Deleting an assessment from a module | `delete_assessment c/ n/` -Listing marks for an assessment: | `list_marks c/ a/` -Setting marks for a student's assessment | `set_mark c/ s/ a/ m/` -Editing marks for a student's assessment | `edit_mark c/ s/ a/ m/` -Deleting marks for a student's assessment | `delete_mark c/ s/ a/` -Viewing average marks for an assessment | `average_marks c/ a/` -Listing attendance for a particular student | `list_attendance c/ s/` -Setting attendance for a particular lesson for a student | `set_attendance c/ s/ l/ p/` -Deleting attendance for a particular lesson for a student | `delete_attendance c/ s/ l/` -======= -Listing all classes | `list_classes` -Adding a class | `add_class c/ [n/]` -Editing a class | `edit_class c/ [nc/] [n/]` -Deleting a class | `delete_class c/` -Listing all students in a class | `list_students c/` -Adding a student to a class | `add_student c/ i/ n/` -Editing a student's information in a class | `edit_student c/ s/ i/ n/` -Deleting a student from a class | `delete_student c/ s/` -Finding students in a class given a keyword | `find_student c/ k/` -Listing all assessments in a class | `list_assessments c/` -Adding an assessment to a class | `add_assessment c/ n/ m/ w/` -Editing an assessment in a class | `edit_assessment c/ n/ [nn/] [m/]` -Deleting an assessment from a class | `delete_assessment c/ n/` -Listing marks for an assessment: | `list_marks c/ a/` -Setting marks for a student's assessment | `set_marks c/ s/ a/ m/` -Editing marks for a student's assessment | `edit_mark c/ s/ a/ m/` -Deleting marks for a student's assessment | `delete_mark c/ s/ a/` -Viewing average marks for an assessment | `average_marks c/ a/` -Listing attendance for a particular student | `list_attendance c/ s/` -Setting attendance for a particular lesson for a student | `set_attendance c/ s/ l/ p/` -Deleting attendance for a particular lesson for a student | `delete_attendance c/ s/ l/` - ->>>>>>> d70490d5dd9fb6e131f55b99a49be2a7a92b3478 +Listing all **classes** | `list_classes` +Adding a **class** | `add_class c/ [n/]` +Editing a **class** | `edit_class c/ [nc/] [n/]` +Deleting a **class** | `delete_class c/` +Listing all **students** in a class | `list_students c/` +Adding a **student** to a class | `add_student c/ i/ n/` +Editing a **student's** information in a class | `edit_student c/ s/ i/ n/` +Deleting a **student** from a class | `delete_student c/ s/` +Finding **students** in a class given a keyword | `find_student c/ k/` +Listing all **assessments** in a class | `list_assessments c/` +Adding an **assessment** to a class | `add_assessment c/ n/ m/ w/` +Editing an **assessment** in a class | `edit_assessment c/ n/ [nn/] [m/]` +Deleting an **assessment** from a class | `delete_assessment c/ n/` +Listing **marks** for an assessment: | `list_marks c/ a/` +Setting **marks** for a student's assessment | `set_mark c/ s/ a/ m/` +Editing **marks** for a student's assessment | `edit_mark c/ s/ a/ m/` +Deleting **marks** for a student's assessment | `delete_mark c/ s/ a/` +Viewing the median **mark** for an assessment | `median_mark c/ a/` +Viewing average **marks** for an assessment | `average_marks c/ a/` +Listing **attendance** for a particular student | `list_attendance c/ s/` +Setting **attendance** for a particular lesson for a student | `set_attendance c/ s/ l/ p/` +Deleting **attendance** for a particular lesson for a student | `delete_attendance c/ s/ l/` Viewing help | `help` Exiting the program | `exit` From 96dc2f50445f2bdb376bbd10c19decc6bb2a8298 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Tue, 2 Nov 2021 17:02:28 +0800 Subject: [PATCH 297/543] add median_mark to features list in ug --- docs/UserGuide.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 61ca13f5ec..2ad7ed17b2 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -22,6 +22,7 @@ If you can type fast, TAA can help keep track of your classes and students faste * [Editing marks for a student's assessment: `edit_mark`](#editing-marks-for-a-students-assessment-edit_mark) * [Deleting marks for a student's assessment: `delete_mark`](#deleting-marks-for-a-students-assessment-delete_mark) * [Viewing average marks for an assessment: `average_marks`](#viewing-average-marks-for-an-assessment-average_marks) + * [Viewing median mark for an assessment: `median_mark`](#viewing-median-mark-for-an-assessment-median_mark) * [Sorting and listing students in a module by their overall score: `sort_by_scores`](#sorting-and-listing-students-in-a-module-by-their-overall-score-sort_by_scores) * [Listing attendance for a particular student: `list_attendance`](#listing-attendance-for-a-particular-student-list_attendance) * [Setting attendance for a particular lesson for a student: `set_attendance`](#setting-attendance-for-a-particular-lesson-for-a-student-set_attendance) @@ -452,8 +453,8 @@ Listing **marks** for an assessment: | `list_marks c/ a/ s/ a/ m/` Editing **marks** for a student's assessment | `edit_mark c/ s/ a/ m/` Deleting **marks** for a student's assessment | `delete_mark c/ s/ a/` -Viewing the median **mark** for an assessment | `median_mark c/ a/` Viewing average **marks** for an assessment | `average_marks c/ a/` +Viewing the median **mark** for an assessment | `median_mark c/ a/` Listing **attendance** for a particular student | `list_attendance c/ s/` Setting **attendance** for a particular lesson for a student | `set_attendance c/ s/ l/ p/` Deleting **attendance** for a particular lesson for a student | `delete_attendance c/ s/ l/` From 599d10484c81d412beb272b6db1f173a5c2b09c2 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Tue, 2 Nov 2021 17:03:56 +0800 Subject: [PATCH 298/543] prevent adding of student when id already exists --- src/main/java/taa/command/student/AddStudentCommand.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/taa/command/student/AddStudentCommand.java b/src/main/java/taa/command/student/AddStudentCommand.java index dfddfd0c73..01b0909ef7 100644 --- a/src/main/java/taa/command/student/AddStudentCommand.java +++ b/src/main/java/taa/command/student/AddStudentCommand.java @@ -19,6 +19,7 @@ public class AddStudentCommand extends Command { private static final String MESSAGE_FORMAT_ADD_STUDENT_USAGE = "%s %s/ %s/ " + "%s/"; private static final String MESSAGE_STUDENT_ADDED_FORMAT = "Student has been added to %s:\n %s"; + public static final String MESSAGE_ID_ALREADY_EXISTS = "A student with that ID already exists"; public AddStudentCommand(String argument) { super(argument, ADD_STUDENT_ARGUMENT_KEYS); @@ -56,6 +57,11 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep Student student = new Student(studentID, studentName); StudentList studentList = teachingClass.getStudentList(); + for (Student students : studentList.getStudents()) { + if (students.getId().equals(studentID)) { + throw new TaaException(MESSAGE_ID_ALREADY_EXISTS); + } + } studentList.addStudent(student); storage.save(classList); From 3b668bdb5c4ccd4101ffd1a59fe465607b1170d7 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Tue, 2 Nov 2021 17:09:59 +0800 Subject: [PATCH 299/543] update add student command --- src/main/java/taa/command/student/AddStudentCommand.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/command/student/AddStudentCommand.java b/src/main/java/taa/command/student/AddStudentCommand.java index 01b0909ef7..29af6ee5a3 100644 --- a/src/main/java/taa/command/student/AddStudentCommand.java +++ b/src/main/java/taa/command/student/AddStudentCommand.java @@ -65,7 +65,8 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep studentList.addStudent(student); storage.save(classList); - ui.printMessage(String.format(MESSAGE_STUDENT_ADDED_FORMAT, classId, student)); + String message = String.format(MESSAGE_STUDENT_ADDED_FORMAT, classId, student); + ui.printMessage(message); } @Override From f039fd96e60e504f3a231e136979b2aeb7be03d3 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Tue, 2 Nov 2021 17:48:00 +0800 Subject: [PATCH 300/543] add images for mark commands in user guide --- docs/UserGuide.md | 20 ++++++++++++++++++++ docs/images/average_marks_all_marked.png | Bin 0 -> 2738 bytes docs/images/average_marks_with_unmarked.png | Bin 0 -> 4041 bytes docs/images/delete_mark.png | Bin 0 -> 3952 bytes docs/images/edit_mark.png | Bin 0 -> 3693 bytes docs/images/list_marks.png | Bin 0 -> 6284 bytes docs/images/set_mark.png | Bin 0 -> 3195 bytes docs/median_mark_all_marked.png | Bin 0 -> 2610 bytes docs/median_mark_with_unmarked.png | Bin 0 -> 3867 bytes 9 files changed, 20 insertions(+) create mode 100644 docs/images/average_marks_all_marked.png create mode 100644 docs/images/average_marks_with_unmarked.png create mode 100644 docs/images/delete_mark.png create mode 100644 docs/images/edit_mark.png create mode 100644 docs/images/list_marks.png create mode 100644 docs/images/set_mark.png create mode 100644 docs/median_mark_all_marked.png create mode 100644 docs/median_mark_with_unmarked.png diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 2ad7ed17b2..d4d90af665 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -238,6 +238,8 @@ Examples: * `list_marks c/CS2113T-F12 a/Midterms` * `list_marks c/CS2101-C03 a/Oral Presentation` +Expected Output:
+![img.png](images/list_marks.png)
### Setting mark for a student's assessment: `set_mark` @@ -253,6 +255,8 @@ Examples: * `set_mark c/CS2113T s/1 a/Midterms m/70.6` * `set_mark c/CS2101 s/3 a/Oral Presentation m/80` +Expected Output:
+![set_mark.png](images/set_mark.png)
### Editing marks for a student's assessment: `edit_mark` @@ -268,6 +272,8 @@ Examples: * `edit_mark c/CS2113T-F12 s/1 a/Midterms m/80.6` * `edit_mark c/CS2101-C03 s/3 a/Oral Presentation m/90` +Expected Output:
+![edit_mark.png](images/edit_mark.png)
### Deleting marks for a student's assessment: `delete_mark` @@ -282,6 +288,8 @@ Examples: * `delete_mark c/CS2113T s/1 a/Midterms` * `delete_mark c/CS2101 s/3 a/Oral Presentation` +Expected Output:
+![delete_mark.png](images/delete_mark.png)
### Viewing average marks for an assessment: `average_marks` @@ -296,6 +304,12 @@ Examples: * `average_marks c/CS2113T a/Midterms` * `average_marks c/CS2101 a/Oral Presentation` +Expected Output:
+(Some students unmarked)
+![average_marks_with_unmarked.png](images/average_marks_with_unmarked.png) +
+(All students marked)
+![average_marks_all_marked.png](images/average_marks_all_marked.png)
### Viewing median mark for an assessment: `median_mark` @@ -310,6 +324,12 @@ Examples: * `median_mark c/CS2113T a/Midterms` * `median_mark c/CS2101 a/Oral Presentation` +Expected Output:
+(Some students unmarked)
+![img.png](median_mark_with_unmarked.png) +
+(All students marked)
+![img.png](median_mark_all_marked.png)
### Sorting and listing students in a module by their overall score: `sort_by_scores` diff --git a/docs/images/average_marks_all_marked.png b/docs/images/average_marks_all_marked.png new file mode 100644 index 0000000000000000000000000000000000000000..aff7ddeeb2f567d97d2f97bdeb5c132a9af4f344 GIT binary patch literal 2738 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 gH_ZQfKsz5YTprXL^#A|> literal 0 HcmV?d00001 diff --git a/docs/images/delete_mark.png b/docs/images/delete_mark.png new file mode 100644 index 0000000000000000000000000000000000000000..e8b6dd1d5a926d374ea8e1c7efc7c44f0e977a6c GIT binary patch literal 3952 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 literal 0 HcmV?d00001 diff --git a/docs/images/edit_mark.png b/docs/images/edit_mark.png new file mode 100644 index 0000000000000000000000000000000000000000..36329337dc5b60959049af8a46383b7f2af17c4d GIT binary patch literal 3693 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 literal 0 HcmV?d00001 diff --git a/docs/images/list_marks.png b/docs/images/list_marks.png new file mode 100644 index 0000000000000000000000000000000000000000..ee9b57bf6d62a5acf2a79bf93a02487ad5ae1c28 GIT binary patch literal 6284 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 literal 0 HcmV?d00001 diff --git a/docs/images/set_mark.png b/docs/images/set_mark.png new file mode 100644 index 0000000000000000000000000000000000000000..98828fb62d77a46bdc0cc67287c6ec63dabbd626 GIT binary patch literal 3195 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 CQf7|; literal 0 HcmV?d00001 diff --git a/docs/median_mark_all_marked.png b/docs/median_mark_all_marked.png new file mode 100644 index 0000000000000000000000000000000000000000..5a9893a17d773d218c7464f9840e4739df8052e2 GIT binary patch literal 2610 zcmbW(e>~HR8VB(2SaqhN=v?PutvW*`N#Z0w7fuH|)Tt98qx5rrZ1ZEfnJwy+yyB!Q zzb3BgBxDiWkS!EBoNZYdMw2mPwh=RYXS?ck@BQQ6b6>A}??2D$^WXD4e?0HklW{oU z(0T(i0{{Tl`+o2JBLG08EBS{nR6zkibB zTXA?tSkxWE+Q_YwUd8r$Eo*QyA5gcvPg8Xx#ORGL)1e7=D4{r;%jHgp$l81E?(P8K zY4<%301|FM*8`r{|21y+Ot#>2{7s2#>iD5&)=|p)I7Oj>mTIkvw=hzE6pBzvO z8iLQ)F*^27rB7W^?dVlM#sZ$Ad8k~!%fccIcM-NnX{Fbvoa!E)%IT^E31S4TYuve| zV028vhno-5E~MSNGwUSsFEgjfucSs6QX^%VI{r?u{kf~p5^pahg(vvWK_>@z`dT5gR+C1td zX-4os$}Pw)f*+Z9HW0Z#9x#UR;70m42XC)}>=0zV#gWFe>06#}c7UA^*1f$=pAXgMIZW+iyrr#JU(3NOstN}-7KE-#i1qaV6vQ6%MxF& zBapxbCd*7fGy9f;d8xImxqFhb30kzAxmiKj+mvIwJ(IBU1y$l{{LZvxAD?xsnMHuB zFIAhWOfk=lII%%V)9>y4T1eIkuhS&96QPMy_hhQMzBAcP!VwwA7kU;7<1EKL_~S{6 z)0|kbcx&%+cuA$;oN$T5y;2^hr9NM2-mAR5xC*CNR0=mm(t{#=fv)mZl!!x{LiKLI zoanzlwSxl!Cp37@N_t9n4R5F6STU_fsIGXD-+ZBPlHvMdG2TG%i$AZkUS|K3ko&ls zyNgI3oEiJGyvWem{c@a{farv(tSJI5!7oW?1j>-(1sK5E*Q5^Y`PuiG{f6WEls?E+ zZ@`}jZJ9wPKWMQsq-@K-2^9R)%nH#p;Fa`YSL@2w<{WR`K_|$*UdFgkcERu7PLv&N zdm*AmTR4#SQkAjDeP6N#bzRdIor31Xit`5j zIk6rR@qX)B_Ow-SmCMdIY(wvPE>dnzAzDj6H*6i&ptpTYG@xzw$=QDlQ;Y}?l%-$u z;~^%nvZ&@dy4}0+M+xK{?8)-072KFm(L-ez!DHQ!vaB(cf8fm`87r>0P+X$Q#0aVcxI)wAWL|f+!qe1KhUc`VP^PM6FSGNxn`n zcpo$ILWPiwN9c}F=HG)LBiFFRo#=U#&qTC?Z|1$s96zZi!a$rVq4I z%&bc+U%mxva}-eq4^x5eH1;0?O)# zfBQY8uq#v$^m&Mh=roqAUa?V{Se)5lkINjY+?|n2k8~n@T=D zqH^TW%+yC3k_a84i?X#Qzg_}hh}ROV8vBxyeXJ5=!;nLg*|w;-mbr~z#ftZ3Db$ga zF1JY2d(%FYq(c1@$1uoDH25P<@t#~bM@SqzSF}Oy2#$)AiaT=Rk&N`a9bzq3Y*WF} z1#nBG{@sD@sLUlvVWvQ^hwTm-xSUL7X-(_duIG^%_-2+Z{#T8Yf*#LoLEF z)?N~wc3k~_(7&H1wQ*r%`v;P$pWN)(&*HN%9v}4Mc+ZCv4XLil>;i97Iy8E&?=FiMcw~-#z}R&0wW59x>bT%CK<{ zt87xEjPf{@a#8yX)<|dd&PTH=Cp7~HSi6MbD7-~cx}2*HY({;7p!^6^RIrFFR(NLC!Uj&H z$KkTmKMpMT5fatdi}~yk4Grybq@*mn)b-o;6N#S<^7CFkpHikd3?gQhi~83*?`aMl zGf8OvbU%-Kp~ag3fP%UHKZx^h4wXTRHBVD#_0@lWsi+?Xc{Wp}5J0*CW(H6UZ~sx$ aYSzfU5t&<)d_H}IfUi%0clE)Dw7&sl1~KCR literal 0 HcmV?d00001 diff --git a/docs/median_mark_with_unmarked.png b/docs/median_mark_with_unmarked.png new file mode 100644 index 0000000000000000000000000000000000000000..c425b315630f47f47857803a05d21c2654b16b1f GIT binary patch literal 3867 zcmbW3doG9?sY3MFKwA$D!IuoLE1pYv%c%~eP^Ba zJ)sHR0fj&ynw}@!{2&mOxwZ90^$lzKUh@+b0?}f7x*ZEhMsZ7h9&s$SZbu=S3#|91 zmHp64WoKN1jRhUP(Qxdf`aJLSS>9LtQl7o5dO7`-ZzUC6Whp19)U^o6#SNPyA&?tc zM@cFWi0L}aS~^KR-C)fy{%0f8hXl}D2ZX8ZvDU5rDJI;eVPE)~fYKxlvwuJ4f8}4! zkjRp#7h>n*X6KLz!Lf`1i6}Hwn;KfcL6C9 zb0~Xr13d*EZ(D_XUA-|->9%LQ=g9Z;MwFwxMpo2=(34J5zO>rp(~y}+8_}$DzwrhA zSzM#@*YI80tfe&6Od9X@WUNw@*KhhzvnOpzl#+MC=s5Hx+dmLjsjyGwybKp7(0c@p zD1e9>sxlvvP^Tp+lPm2DA;yb8L`X;A_R8ve>AJTe7DyWAsm*|DRdw@|J9#D9Cq|cp zHVq%)zy4W8=n`d?ebn07>)S@gfNMqB+icfMV`mIVXrjDAJQwAfoP>!*<{Y2VskXcX zpL}7%p0$%b<%N-oc7-6>m%z~eMFFlP zIszL6fdWGas4|NHccd%?T4d9x?*{zy;-O>N4S&|@*1f%|QZ2P||6EUD4^dcVxVwty z`~|0~3L{^PS~&2h)dJkhXoIY3qTaXo#l8bAe(8edt4h=NFRpH4!rViN;WX})?9n6= z9M}q?fj~OFLEgeR`rVeGH8n`NDL>Lkg)B$T0R37$80^T1u8nHkw7%JsN6l9=jZI<- z!@p`uc7!j8F;K54%5t4i$Q#QOBM;`XHnQLN4&a;6^n zD!!D0ds!|u3qL?&{b3hH%}K7FwhS+pJZ6>%*Wb`Sy)kjLw(`8zwxidlt&sA)Uf+I2 zLVARMTyApz!v^QIpB)A-}sMZizI*&-r zC61TS?#1LrFcJsF*m!C;2pz7KstK4zEGA;C%*b(ij(P7cG6?o2IKDM_+<7GC;+WZkybd)2gIe+~RebtEEipdpw_8cXwov#UT@wgVI zWjH!Mv7E+7XMi!8+7R!bIyXTec3W1^5y~UAjAvYq>l(jW)9h3s|M1igKp=13cG1@O zrgQUO8{MX~L0IEQUQT$9#-CyMC! zlta9zcqkS3P4uemdP}|R*?=-jtxS*2S+gbCgUwCD#pKQJzY@($ z*68ILoHGhPDbR(n583hkRiu?lL|?ez&7|d0v@|pY`!9 z*jOGq;};DZw50$HEeNbqcaDd>d8#L_E$+Sb?eD$k56O+`H=Uwap+58#fqG>zaAWU)j#3!1t27U zUo9fH3k)xy2YFA=C)IMEK9dx5TW6dea?0}kIbx^IER@q-i=y^LEWiVs4GOB>%>jV!40r zguE&8Au+;Ckc9Z~ZOD%fQJBx^$1P|oHTBiuI6qSR^mRFE4Be%bU4DC8-;Kiz{WA3q zq3zPyzEARVxI-C1IUSjmhwJtiwo%*mF{VDx^usuwx;PMX8DnrI==B81~vOCu3-YR)BVIg6P?_=I7!FLEMMz{((}U8?91pt zU)p~tU%%o2PwzezSG@o%XedGiHen*So!W@}^#J$UU($y7kAz&ZsP_qOSud(w*s%OR zciKfe*I==+T3(FKGruL#xUj_+U;CTu=*F(pFfqvvI~_vcJ#6qYt5VB;WPCO2+$DCZ z(K6-ENZ{YeBV=^HHmYgn zNUi=yC&X3}+B?lWnjwn+vd zBn60qLvXpRc!B;JT8z~GkG90xP3x!lAA<=Q#V&5*ktbc@cN_`<*Mm?AKTaay7Xez5 zgT3JNYTxcg#g?48>-vhg@ZaA!r>t*LFrslx&|Gr;SToB6UpB9>vV(RV$d#A@v{?xI zlw)s-4}msxULI4%jS~o_l`Es$W!jkA?`>!+Jf1P_PG&`XK0|Vbzns#K$U3vV4ATwV z$EN-UT<)H6kl4fNy`nMj5CQ?(=I1piQ7&3??<5R0=Yxe}4ESuG5kzSJWaA-5o$xkeMDIh((qy^z##U3l#oPawDH3LCd&jLt4-T+2~F* z3n*A}d^{$g+)r`pOq7%p;+hf$?~>EPPPIpl!R`X@&J){Qz8wD5d9%`lzp-rzJhC(- zB~)%t9}n!U(0w0lCvZM2(o=RQ7H^NSiRh4_Zgt0~`IN z&Afppu|*6h0;j4dDsqcoF;iqCE6h3MVeW?>-{&IKWF(A9we{BYYL8Ju=;|+r=_2}L zU@MW*5e%afIz@4%oL@1U!mu)AS227W4u0A-y$WqQhLdF-b7~A z^4VT9dz7nvP=Vu6;+}{sdU~Z;PMOlH{XP+^ctPoc9fu}*SCH)7_g8yo&-^BYo5lT?}h*e7H1BgzsieF;72V6R(X&%0>bX{iXs4S2_<}qP6Y*B3^UVW! zK}M&DUJNu6gc|QcV0~aVmlfL;8^HW&An6L!5Vinz3!(UZxPs zNQwfvfzYD7n+3Orz0->%;yX&l!*o_#e~j?aS!k@Qn)%0cCjzR_cx=4;F7lpnL+XcZ zJl-Bqy#*gJ9cXA9UD9|2U)T~YQ%laW<78CKqxD$wpW-x-KN`x2MEo1EX(|}Qo!dUW z`eHlQ3Q3po4foWAh`E`Eh#rer{%XA}pG$mv2uyHU5$wKz5iwee;%@Gr zXLt0McQ5gHzzS7#Snd>n8Pf3E%X&mJa7al23M|jKhYY*iiU20Xc~@r!H@6)mu6=MU zvshX}?ERLv3+4@1aQ;hHiW*eaWS=Jalwkz+mCdwCOrS`OT{Cu%AGJdJ>z5(K*Am}= z4RXZqut8ykPaey>Mzfifi8ljnIzST{i><;M!EU;MLGi|-TRB)aQmc#-;p+sp%P94q zF5E%%@x*hsVvG0duIo~6fYA@t)FEQ*F4}U?OjM8Ro4@*gdKm_IZMcD0-?<5Pf*J`k zE-}rgc7g^oj0!+ft_sn*@vke?e;2ZUE?sNgY6N!dG&LhLY5Yo6>6#Gn?ddxIb~&SU bDOD`>4UgiU&A(XVEyUB^*R9U=;;sJ#$1St& literal 0 HcmV?d00001 From 414e1f320c1f5e4bdc7e8ea84fa95d5771ba0c22 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 18:07:27 +0800 Subject: [PATCH 301/543] Change AddModule diagrams to AddClass --- docs/DeveloperGuide.md | 2 +- docs/diagrams/AddClassSequenceDiagram.png | Bin 0 -> 23262 bytes docs/diagrams/AddClassSequenceDiagram.puml | 41 +++++++++++ docs/diagrams/AddModuleSequenceDiagram.png | Bin 42870 -> 0 bytes docs/diagrams/AddModuleSequenceDiagram.puml | 67 ------------------ docs/diagrams/ArchitectureSequenceDiagram.png | Bin 54066 -> 52695 bytes .../diagrams/ArchitectureSequenceDiagram.puml | 31 ++++---- 7 files changed, 58 insertions(+), 83 deletions(-) create mode 100644 docs/diagrams/AddClassSequenceDiagram.png create mode 100644 docs/diagrams/AddClassSequenceDiagram.puml delete mode 100644 docs/diagrams/AddModuleSequenceDiagram.png delete mode 100644 docs/diagrams/AddModuleSequenceDiagram.puml diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 2baec78e62..162ebacdd4 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -51,7 +51,7 @@ The _Architecture Sequence Diagram_ shown above shows how the components usually ## Implementation ### Add Module The sequence diagram shown below illustrates how the `add_module` command works: -![AddModuleSequenceDiagram](diagrams/AddModuleSequenceDiagram.png) +![AddClassSequenceDiagram](diagrams/AddClassSequenceDiagram.png) Steps: 1. The `Taa` instance reads in a user input through the `Ui.getUserInput()` method. diff --git a/docs/diagrams/AddClassSequenceDiagram.png b/docs/diagrams/AddClassSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..35ac2438d0a5c789a0906e8f1c68748dbb63883f GIT binary patch literal 23262 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 literal 0 HcmV?d00001 diff --git a/docs/diagrams/AddClassSequenceDiagram.puml b/docs/diagrams/AddClassSequenceDiagram.puml new file mode 100644 index 0000000000..d08302cbac --- /dev/null +++ b/docs/diagrams/AddClassSequenceDiagram.puml @@ -0,0 +1,41 @@ +@startuml +!include style.puml + +Actor User as user +Participant ":Taa" as taa +Participant ":AddClassCommand" as addClassCommand +Participant ":ClassList" as classList +Participant ":TeachingClass" as teachingClass +Participant ":Storage" as storage + +user -> taa : "add_class i/CS2113T-F12\nn/Tutorial Group F12" +activate taa + +taa -> addClassCommand : execute(classList:ClassList,\nui:Ui, storage:Storage) +activate addClassCommand + +create teachingClass +addClassCommand -> teachingClass +activate teachingClass +teachingClass --> addClassCommand : teachingClass:TeachingClass +deactivate teachingClass + +addClassCommand -> classList : addClass(teachingClass) +activate classList +classList --> addClassCommand +deactivate classList + +addClassCommand -> storage : save(classList) +activate storage +storage --> addClassCommand +deactivate storage + +addClassCommand --> taa +deactivate addClassCommand +taa -[hidden]-> addClassCommand +destroy addClassCommand + +taa --> user +deactivate taa + +@enduml \ No newline at end of file diff --git a/docs/diagrams/AddModuleSequenceDiagram.png b/docs/diagrams/AddModuleSequenceDiagram.png deleted file mode 100644 index d2deebb3f480f1ce2a1f1f05c552c4cee067494a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 42870 zcmcG$bwE_x_dbjuAxNkoN+T+W0#ed7BA`ghfV7H8Ni%eZA}OdK-7*ZRbc+E<*U+Vd z#L(Tty9Y4uy`S&zpZA~370#S<_TFo)=ULBMYn~}9%90Y(5aZzBklvJ&R>i?NdKU)= z*N+Gn{Knx#gAn*}$?nEoI|EBAr^kkm>~LfaEevh$+ZjG&df>!lY-eXB%*AE(_`Zc5 z%=|H@fu;G0t3q@*IC!ciYIp5^{2u2BxQ%1%th$2IfFwnwc7w<3H<8lb6y<(Ce&--; zaK1|?2%M!55vwQFd(C>v$&#RZE=D~G)=hPlUp}w3#1vaTa(HBOp6aF=4FUZ$9yOnw z8-c1A;bV%J&msJ8*l&$$y*ujfOPN4#79t+I^qL4?cRku6_?ZByhVPlcbE)@*MN^N2 z+3=N7m4w6+P{;IKZ0ub(3QHh(eA18kM3q-~?Ssxsyo#l21Pl=gv+rr(#}=--zN@F; zap^H(R$IKFa)l(v;47ZJ?CYae_iJ9Z^k|$&NA%?0hXn{nwA_C-`{2Apew^2wf@ocl zgzgaW+ld?N=x67TSNY>p2VKy)Qa0IipW1EJK1YZ&p9Imh7V84oJa(cPR2Wbx;_dljv>186rRT6Sgvw1*{<7pJ+VkqA zpPpbJi7K{ubh*Aw_?tUg|T^~~|IX7wa9w}%0AaY`jYcuU9ckIxSW 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


###Students @@ -178,6 +179,7 @@ Examples: * `find_student c/CS2101-D03 k/Jon`
+
### Assessments @@ -258,6 +260,7 @@ Expected Output:
![img.png](images/marks/list_marks.png)
+
#### Setting mark for a student's assessment: `set_mark` Adds a student's marks for an assessment. @@ -367,6 +370,7 @@ Examples: * `sort_by_scores c/CS2113T-F12 o/desc`
+
### Attendance @@ -413,6 +417,7 @@ Examples: * `list_comment c/CS2101-D03`
+
#### Setting comment for a particular student: `set_comment` Sets a comment for a student. @@ -474,6 +479,8 @@ Removes all saved data from the current program. Format: `reset` +
+ ## FAQ **Q**: How do I transfer my data to another computer? From 48835c1be372ddbb647f0a51417335105e9b541a Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 3 Nov 2021 19:36:30 +0800 Subject: [PATCH 324/543] Add missing horizontal lines --- docs/UserGuide.md | 60 ++++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 32 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 307f655103..a4247eb7f0 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -4,23 +4,23 @@ If you can type fast, TAA can help keep track of your classes and students faste * [Quick Start](#quick-start) * [Features](#features) - * [Classes](#classes) + * [Class](#class) * [Listing all classes: `list_classes`](#listing-all-classes-list_classes) * [Adding a class: `add_class`](#adding-a-class-add_class) * [Editing a class: `edit_class`](#editing-a-class-edit_class) * [Deleting a class: `delete_class`](#deleting-a-class-delete_class) - * [Students](#students) + * [Student](#student) * [Listing all students in a class: `list_students`](#listing-all-students-in-a-class-list_students) * [Adding a student to a class: `add_student`](#adding-a-student-to-a-class-add_student) * [Editing a student's information in a class: `edit_student`](#editing-a-students-information-in-a-class-edit_student) * [Deleting a student from a class: `delete_student`](#deleting-a-student-from-a-class-delete_student) * [Finding students in a class given a keyword: `find_student`](#finding-students-in-a-class-given-a-keyword-find_student) - * [Assessments](#assessments) + * [Assessment](#assessment) * [Listing all assessments in a class: `list_assessments`](#listing-all-assessments-in-a-class-list_assessments) * [Adding an assessment to a class: `add_assessment`](#adding-an-assessment-to-a-class-add_assessment) * [Editing an assessment in a class: `edit_assessment`](#editing-an-assessment-in-a-class-edit_assessment) * [Deleting an assessment from a class: `delete_assessment`](#deleting-an-assessment-from-a-class-delete_assessment) - * [Marks](#marks) + * [Mark](#mark) * [Listing marks for an assessment: `list_marks`](#listing-marks-for-an-assessment-list_marks) * [Setting mark for a student's assessment: `set_mark`](#setting-mark-for-a-students-assessment-set_mark) * [Editing mark for a student's assessment: `edit_mark`](#editing-mark-for-a-students-assessment-edit_mark) @@ -32,11 +32,11 @@ If you can type fast, TAA can help keep track of your classes and students faste * [Listing attendance for a particular student: `list_attendance`](#listing-attendance-for-a-particular-student-list_attendance) * [Setting attendance for a particular lesson for a student: `set_attendance`](#setting-attendance-for-a-particular-lesson-for-a-student-set_attendance) * [Deleting attendance for a particular lesson for a student: `delete_attendance`](#deleting-attendance-for-a-particular-lesson-for-a-student-delete_attendance) - * [Comments](#comments) + * [Comment](#comment) * [Listing comments for all students in a class: `list_comment`](#listing-comments-for-all-students-in-a-class-list_comment) * [Setting comment for a particular student: `set_comment`](#setting-comment-for-a-particular-student-set_comment) * [Deleting comment for a particular student: `delete_comment`](#deleting-comment-for-a-particular-student-delete_comment) - * [Others](#others) + * [Other](#other) * [Viewing help: `help`](#viewing-help-help) * [Exiting the program: `exit`](#exiting-the-program-exit) * [Archiving data: `archive`](#archiving-data-archive) @@ -55,8 +55,7 @@ If you can type fast, TAA can help keep track of your classes and students faste ## Features -### Classes - +### Class #### Listing all classes: `list_classes` Displays the list of all classes in the class list. @@ -112,8 +111,7 @@ Examples:

-###Students - +### Student #### Listing all students in a class: `list_students` Shows a list of all students in a particular class. @@ -181,8 +179,7 @@ Examples:

-### Assessments - +### Assessment #### Listing all assessments in a class: `list_assessments` List all assessments in a class. @@ -243,8 +240,9 @@ Examples: * `delete_assessment c/CS2101-C03 n/OP2`
+
-### Marks +### Mark #### Listing marks for an assessment: `list_marks` Lists all students and their marks for an assessment. @@ -373,7 +371,6 @@ Examples:
### Attendance - #### Listing attendance for a particular student: `list_attendance` Lists a student's attendance. @@ -403,9 +400,9 @@ Format: `delete_attendance c/ s/ l/` * `LESSON_NUMBER` refers to the lesson number.
+
-### Comments - +### Comment #### Listing comments for all students in a class: `list_comment` List comments for all students in a class @@ -448,8 +445,7 @@ Examples:
-### Others - +### Other #### Viewing help: `help` Displays the list of available commands and how to use them. @@ -504,20 +500,20 @@ Assessment | Listing all assessments in a class | `list_assessments c/ Assessment | Adding an assessment to a class | `add_assessment c/ n/ m/ w/` Assessment | Editing an assessment in a class | `edit_assessment c/ n/ [nn/] [m/]` Assessment | Deleting an assessment from a class | `delete_assessment c/ n/` -Marks | Listing marks for an assessment: | `list_marks c/ a/` -Marks | Setting mark for a student's assessment | `set_mark c/ s/ a/ m/` -Marks | Editing mark for a student's assessment | `edit_mark c/ s/ a/ m/` -Marks | Deleting mark for a student's assessment | `delete_mark c/ s/ a/` -Marks | Viewing average marks for an assessment | `average_marks c/ a/` -Marks | Viewing the median mark for an assessment | `median_mark c/ a/` -Marks | Sorting and listing students in a class by their overall score | `sort_by_scores c/ o/` +Mark | Listing marks for an assessment: | `list_marks c/ a/` +Mark | Setting mark for a student's assessment | `set_mark c/ s/ a/ m/` +Mark | Editing mark for a student's assessment | `edit_mark c/ s/ a/ m/` +Mark | Deleting mark for a student's assessment | `delete_mark c/ s/ a/` +Mark | Viewing average marks for an assessment | `average_marks c/ a/` +Mark | Viewing the median mark for an assessment | `median_mark c/ a/` +Mark | Sorting and listing students in a class by their overall score | `sort_by_scores c/ o/` Attendance | Listing attendance for a particular student | `list_attendance c/ s/` Attendance | Setting attendance for a particular lesson for a student | `set_attendance c/ s/ l/ p/` Attendance | Deleting attendance for a particular lesson for a student | `delete_attendance c/ s/ l/` -Comments | Listing comments for all students in a class | `list_comment c/` -Comments | Setting comment for a particular student | `set_comment c/ s/ t/` -Comments | Deleting comment for a particular student | `delete_comment c/ s/` -Others | Viewing help | `help` -Others | Exiting the program | `exit` -Others | Archiving data | `archive` -Others | Resetting/Removing all data | `reset` +Comment | Listing comments for all students in a class | `list_comment c/` +Comment | Setting comment for a particular student | `set_comment c/ s/ t/` +Comment | Deleting comment for a particular student | `delete_comment c/ s/` +Other | Viewing help | `help` +Other | Exiting the program | `exit` +Other | Archiving data | `archive` +Other | Resetting/Removing all data | `reset` From 71a2fa5f05866a19a0e50c029bad739b17f6131f Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 3 Nov 2021 19:37:30 +0800 Subject: [PATCH 325/543] Add missing horizontal lines --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index a4247eb7f0..4233ac5e17 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -414,7 +414,6 @@ Examples: * `list_comment c/CS2101-D03`
-
#### Setting comment for a particular student: `set_comment` Sets a comment for a student. @@ -444,6 +443,7 @@ Examples: * `delete_comment c/CS2113T-F12 s/5`
+
### Other #### Viewing help: `help` From 4c9ea0566a0e6f31e5ef415da50e38849b845597 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 3 Nov 2021 19:39:57 +0800 Subject: [PATCH 326/543] Update edit_class command --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 4233ac5e17..af4e0e829d 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -489,7 +489,7 @@ Category | Action | Format | ----- | ------ | --------------- | Class | Listing all classes | `list_classes` Class | Adding a class | `add_class i/ [n/]` -Class | Editing a class | `edit_class c/ [nc/] [n/]` +Class | Editing a class | `edit_class c/ [i/] [n/]` Class | Deleting a class | `delete_class c/` Student | Listing all students in a class | `list_students c/` Student | Adding a student to a class | `add_student c/ i/ n/` From 800791032bfba38a41152306f0aad57ecf40d32b Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 3 Nov 2021 19:45:02 +0800 Subject: [PATCH 327/543] Update help command --- src/main/java/taa/command/HelpCommand.java | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index 21f01429cc..18cae2a5e9 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -2,6 +2,7 @@ //@@author leyondlee import taa.Ui; +import taa.command.comment.DeleteCommentCommand; import taa.teachingclass.ClassList; import taa.command.assessment.AddAssessmentCommand; import taa.command.assessment.DeleteAssessmentCommand; @@ -40,7 +41,8 @@ public class HelpCommand extends Command { private static final String STRING_ASSESSMENT = "Assessment"; private static final String STRING_MARK = "Mark"; private static final String STRING_ATTENDANCE = "Attendance"; - private static final String STRING_OTHERS = "Others"; + private static final String STRING_COMMENT = "Comment"; + private static final String STRING_OTHER = "Other"; private static final String MESSAGE_OUTPUT_HEADER = "Available commands:"; @@ -69,10 +71,7 @@ private static void initCommandUsages() { new AddStudentCommand(""), new EditStudentCommand(""), new DeleteStudentCommand(""), - new FindStudentCommand(""), - new ListCommentCommand(""), - new SetCommentCommand(""), - new SortByScoresCommand(""), + new FindStudentCommand("") }; commandUsages.put(STRING_STUDENT, getUsagesFromCommands(studentCommands)); @@ -91,6 +90,7 @@ private static void initCommandUsages() { new DeleteMarkCommand(""), new AverageMarksCommand(""), new MedianMarkCommand(""), + new SortByScoresCommand("") }; commandUsages.put(STRING_MARK, getUsagesFromCommands(markCommands)); @@ -101,13 +101,20 @@ private static void initCommandUsages() { }; commandUsages.put(STRING_ATTENDANCE, getUsagesFromCommands(attendanceCommands)); + Command[] commentCommands = { + new ListCommentCommand(""), + new SetCommentCommand(""), + new DeleteCommentCommand("") + }; + commandUsages.put(STRING_COMMENT, getUsagesFromCommands(commentCommands)); + Command[] othersCommands = { new ExitCommand(""), new HelpCommand(""), new ArchiveCommand(""), new ResetCommand("") }; - commandUsages.put(STRING_OTHERS, getUsagesFromCommands(othersCommands)); + commandUsages.put(STRING_OTHER, getUsagesFromCommands(othersCommands)); } private static ArrayList getUsagesFromCommands(Command[] commands) { From 24fa1ddc0a9d12193641d347961abf48f9a8870b Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 3 Nov 2021 19:48:46 +0800 Subject: [PATCH 328/543] Update argument keys for assessment commands --- .../taa/command/assessment/DeleteAssessmentCommand.java | 2 +- .../java/taa/command/assessment/EditAssessmentCommand.java | 6 +++--- .../java/taa/command/teachingclass/EditClassCommand.java | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java b/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java index 10d92e4561..cee68578bd 100644 --- a/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/DeleteAssessmentCommand.java @@ -14,7 +14,7 @@ public class DeleteAssessmentCommand extends Command { private static final String KEY_CLASS_ID = "c"; - private static final String KEY_ASSESSMENT_NAME = "n"; + private static final String KEY_ASSESSMENT_NAME = "a"; private static final String[] DELETE_ASSESSMENT_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_ASSESSMENT_NAME}; private static final String MESSAGE_FORMAT_DELETE_ASSESSMENT_USAGE = "%s %s/ %s/"; diff --git a/src/main/java/taa/command/assessment/EditAssessmentCommand.java b/src/main/java/taa/command/assessment/EditAssessmentCommand.java index c2796987e2..4256321b16 100644 --- a/src/main/java/taa/command/assessment/EditAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/EditAssessmentCommand.java @@ -14,8 +14,8 @@ public class EditAssessmentCommand extends Command { private static final String KEY_CLASS_ID = "c"; - private static final String KEY_ASSESSMENT_NAME = "n"; - private static final String KEY_NEW_ASSESSMENT_NAME = "nn"; + private static final String KEY_ASSESSMENT_NAME = "a"; + private static final String KEY_NEW_ASSESSMENT_NAME = "n"; private static final String KEY_NEW_MAXIMUM_MARKS = "m"; private static final String KEY_NEW_WEIGHTAGE = "w"; private static final String[] EDIT_ASSESSMENT_ARGUMENT_KEYS = { @@ -27,7 +27,7 @@ public class EditAssessmentCommand extends Command { }; private static final String MESSAGE_FORMAT_EDIT_ASSESSMENT_USAGE = "%s %s/ " - + "%s/ [%s/] [%s/] [%s/]"; + + "%s/ [%s/ | %s/ | %s/]"; private static final String MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE = "Invalid new weightage. " + "Weightage must be between %,.2f and %,.2f (inclusive)"; private static final String MESSAGE_FORMAT_INVALID_NEW_TOTAL_WEIGHTAGE = "Invalid new weightage. " diff --git a/src/main/java/taa/command/teachingclass/EditClassCommand.java b/src/main/java/taa/command/teachingclass/EditClassCommand.java index d1ebdb99cd..10c6640556 100644 --- a/src/main/java/taa/command/teachingclass/EditClassCommand.java +++ b/src/main/java/taa/command/teachingclass/EditClassCommand.java @@ -19,7 +19,7 @@ public class EditClassCommand extends Command { }; private static final String MESSAGE_FORMAT_EDIT_CLASS_USAGE = "%s %s/ " - + "[%s/] [%s/]"; + + "[%s/ | %s/]"; private static final String MESSAGE_FORMAT_CLASS_EDITED = "Class edited:\n %s"; private static final String MESSAGE_FORMAT_CLASS_EXISTS = "CLASS_ID: %s already exists. " + "Please use a different CLASS_ID."; From 74e7f1bac0d1173b3b1f3428b463274295dec43d Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 3 Nov 2021 20:00:43 +0800 Subject: [PATCH 329/543] Update edit_class, edit_assessment, delete_assessment commands in UG --- docs/UserGuide.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index af4e0e829d..81798b95d9 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -82,7 +82,7 @@ Examples: #### Editing a class: `edit_class` Edits the code or name of an existing class. -Format: `edit_class c/ [i/] [n/]` +Format: `edit_class c/ [i/ | n/]` * `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `NEW_CLASS_ID` [Optional] refers to the updated id of the class. * `NEW_CLASS_NAME` [Optional] refers to the updated name of the class. @@ -210,7 +210,7 @@ Examples: #### Editing an assessment in a class: `edit_assessment` Edits an assessment of a class. -Format: `edit_assessment c/ n/ [nn/] [m/] [w/]` +Format: `edit_assessment c/ a/ [n/ | m/ | w/]` * `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). * `NEW_ASSESSMENT_NAME` [Optional] refers to the new name of the assessment (e.g. Finals, Assignment 2, etc.). @@ -231,7 +231,7 @@ Examples: #### Deleting an assessment from a class: `delete_assessment` Deletes an assessment of a class. -Format: `delete_assessment c/ n/` +Format: `delete_assessment c/ a/` * `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). @@ -489,7 +489,7 @@ Category | Action | Format | ----- | ------ | --------------- | Class | Listing all classes | `list_classes` Class | Adding a class | `add_class i/ [n/]` -Class | Editing a class | `edit_class c/ [i/] [n/]` +Class | Editing a class | `edit_class c/ [i/ \| n/]` Class | Deleting a class | `delete_class c/` Student | Listing all students in a class | `list_students c/` Student | Adding a student to a class | `add_student c/ i/ n/` @@ -498,8 +498,8 @@ Student | Deleting a student from a class | `delete_student c/ s/ k/` Assessment | Listing all assessments in a class | `list_assessments c/` Assessment | Adding an assessment to a class | `add_assessment c/ n/ m/ w/` -Assessment | Editing an assessment in a class | `edit_assessment c/ n/ [nn/] [m/]` -Assessment | Deleting an assessment from a class | `delete_assessment c/ n/` +Assessment | Editing an assessment in a class | `edit_assessment c/ a/ [n/ \| m/ \| w/]` +Assessment | Deleting an assessment from a class | `delete_assessment c/ a/` Mark | Listing marks for an assessment: | `list_marks c/ a/` Mark | Setting mark for a student's assessment | `set_mark c/ s/ a/ m/` Mark | Editing mark for a student's assessment | `edit_mark c/ s/ a/ m/` From fb81b6b67765bb98a4635fe2301b710289b35266 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 3 Nov 2021 20:01:34 +0800 Subject: [PATCH 330/543] Update AssessmentListTest --- src/test/java/taa/assessment/AssessmentListTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/test/java/taa/assessment/AssessmentListTest.java b/src/test/java/taa/assessment/AssessmentListTest.java index 71e679bd0c..aac428d720 100644 --- a/src/test/java/taa/assessment/AssessmentListTest.java +++ b/src/test/java/taa/assessment/AssessmentListTest.java @@ -74,7 +74,7 @@ void deleteAssessment_userInput_emptyAssessmentList() throws TaaException { command2.checkArgument(); command2.execute(classList, ui, storage); - String deleteAssessmentInput = "delete_assessment c/cs2113t_f12 n/Midterms"; + String deleteAssessmentInput = "delete_assessment c/cs2113t_f12 a/Midterms"; Command command3 = Parser.parseUserInput(deleteAssessmentInput); command3.parseArgument(); command3.checkArgument(); @@ -103,7 +103,7 @@ void editAssessment_userInputFourEdits_assessmentEditedCorrectly() throws TaaExc command2.checkArgument(); command2.execute(classList, ui, storage); - String editAssessment1 = "edit_assessment c/cs2113t-f12 n/midterms nn/finals"; + String editAssessment1 = "edit_assessment c/cs2113t-f12 a/midterms n/finals"; Command command3 = Parser.parseUserInput(editAssessment1); command3.parseArgument(); command3.checkArgument(); @@ -112,21 +112,21 @@ void editAssessment_userInputFourEdits_assessmentEditedCorrectly() throws TaaExc .getAssessment("finals"); assertEquals("finals", assessment.getName()); - String editAssessment2 = "edit_assessment c/cs2113t-f12 n/finals m/100"; + String editAssessment2 = "edit_assessment c/cs2113t-f12 a/finals m/100"; Command command4 = Parser.parseUserInput(editAssessment2); command4.parseArgument(); command4.checkArgument(); command4.execute(classList, ui, storage); assertEquals(100, assessment.getMaximumMarks()); - String editAssessment3 = "edit_assessment c/cs2113t-f12 n/finals w/50"; + String editAssessment3 = "edit_assessment c/cs2113t-f12 a/finals w/50"; Command command5 = Parser.parseUserInput(editAssessment3); command5.parseArgument(); command5.checkArgument(); command5.execute(classList, ui, storage); assertEquals(50, assessment.getWeightage()); - String editAssessment4 = "edit_assessment c/cs2113t-f12 n/finals nn/midterms m/50 w/20"; + String editAssessment4 = "edit_assessment c/cs2113t-f12 a/finals n/midterms m/50 w/20"; Command command6 = Parser.parseUserInput(editAssessment4); command6.parseArgument(); command6.checkArgument(); From 87489c6014e71fa2743d7803fe3940eea9dae090 Mon Sep 17 00:00:00 2001 From: Ho Zhen Hong Date: Wed, 3 Nov 2021 20:04:01 +0800 Subject: [PATCH 331/543] update student ID to uppercase only --- docs/UserGuide.md | 6 ++++++ src/main/java/taa/command/student/AddStudentCommand.java | 2 +- src/main/java/taa/command/student/EditStudentCommand.java | 8 +++++++- 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index af4e0e829d..eb5cac57f3 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -136,6 +136,9 @@ Examples: * `add_student c/CS2113T-F11 i/a0212345x n/Jon Lim` * `add_student c/CS2101-C04 n/Jonny Lims i/a1234567i` +> 💡 **Note:**
+> `STUDENT_ID` will be converted to uppercase. +
#### Editing a student's information in a class: `edit_student` @@ -151,6 +154,9 @@ Examples: * `edit_student c/CS2113T-F11 s/1 i/a03452345x n/Jon Lim` * `edit_student c/CS2101-D03 s/5 n/Jonny Lims i/a120067i` +> 💡 **Note:**
+> `STUDENT_ID` will be converted to uppercase. +
#### Deleting a student from a class: `delete_student` diff --git a/src/main/java/taa/command/student/AddStudentCommand.java b/src/main/java/taa/command/student/AddStudentCommand.java index 29af6ee5a3..7a2f9ee2ca 100644 --- a/src/main/java/taa/command/student/AddStudentCommand.java +++ b/src/main/java/taa/command/student/AddStudentCommand.java @@ -52,7 +52,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } - String studentID = argumentMap.get(KEY_STUDENT_ID); + String studentID = argumentMap.get(KEY_STUDENT_ID).toUpperCase(); String studentName = argumentMap.get(KEY_STUDENT_NAME); Student student = new Student(studentID, studentName); diff --git a/src/main/java/taa/command/student/EditStudentCommand.java b/src/main/java/taa/command/student/EditStudentCommand.java index 229bc251e7..5da3371e95 100644 --- a/src/main/java/taa/command/student/EditStudentCommand.java +++ b/src/main/java/taa/command/student/EditStudentCommand.java @@ -26,6 +26,7 @@ public class EditStudentCommand extends Command { private static final String MESSAGE_FORMAT_FIND_STUDENT_USAGE = "%s %s/ %s/ " + "%s/ %s/"; private static final String MESSAGE_FORMAT_STUDENT_EDITED = "Student updated:\n %s"; + public static final String MESSAGE_ID_ALREADY_EXISTS = "A student with that ID already exists"; public EditStudentCommand(String argument) { super(argument, EDIT_STUDENT_ARGUMENT_KEYS); @@ -74,8 +75,13 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - String newId = argumentMap.get(KEY_NEW_ID); + String newId = argumentMap.get(KEY_NEW_ID).toUpperCase(); String newName = argumentMap.get(KEY_NEW_NAME); + for (Student students : studentList.getStudents()) { + if (students.getId().equals(newId)) { + throw new TaaException(MESSAGE_ID_ALREADY_EXISTS); + } + } student.setId(newId); student.setName(newName); From 007b94d3140063734f17717b8d47a90d6c9b0265 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 3 Nov 2021 20:38:49 +0800 Subject: [PATCH 332/543] Allow commas for values --- src/main/java/taa/Parser.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index c038f17f7c..9806b533cc 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -44,7 +44,7 @@ public class Parser { private static final String ARGUMENT_VALID_REGEX = "0-9a-zA-Z\\s"; - private static final char[] VALID_SPECIAL_CHARACTERS = {'-', '_', '(', ')', '.'}; + private static final char[] VALID_SPECIAL_CHARACTERS = {'-', '_', '(', ')', '.', ','}; private static final String MESSAGE_UNKNOWN_COMMAND = "Unknown Command"; From 4ff555064eb08e4642261a46ee2c803d45fe03b7 Mon Sep 17 00:00:00 2001 From: rachel Date: Fri, 5 Nov 2021 01:43:39 +0800 Subject: [PATCH 333/543] Edit edit_assessment command to allow changing of assessment name to the same name but with different casing. Refactor add_assessment and edit_assessment commands. Yet to test --- .../java/taa/assessment/AssessmentList.java | 6 +- .../assessment/AddAssessmentCommand.java | 76 ++++++++------- .../assessment/EditAssessmentCommand.java | 96 ++++++++++++------- 3 files changed, 105 insertions(+), 73 deletions(-) diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 653d12a6b8..61d553b26e 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -86,10 +86,10 @@ public double totalWeightageForEditAssessmentCommand(String assessmentName) { return totalWeightage; } - public boolean checkRepeatedName(String newAssessmentName) { + public boolean checkRepeatedName(Assessment assessment, String newAssessmentName) { for (Assessment a : assessments) { - if (a.getName().equalsIgnoreCase(newAssessmentName)) { - return false; + if (a.getName().equalsIgnoreCase(newAssessmentName) && (a != assessment)) { + return false; } } return true; diff --git a/src/main/java/taa/command/assessment/AddAssessmentCommand.java b/src/main/java/taa/command/assessment/AddAssessmentCommand.java index c874af53c9..9af944510b 100644 --- a/src/main/java/taa/command/assessment/AddAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/AddAssessmentCommand.java @@ -61,14 +61,6 @@ public void checkArgument() throws TaaException { ); } - int maximumMarks = Integer.parseInt(maximumMarksString); - if (maximumMarks < Assessment.MINIMUM_MARKS) { - throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS, - Assessment.MINIMUM_MARKS) - ); - } - String weightageString = argumentMap.get(KEY_WEIGHTAGE); if (!Util.isStringDouble(weightageString)) { throw new TaaException(String.format( @@ -77,15 +69,6 @@ public void checkArgument() throws TaaException { Assessment.WEIGHTAGE_RANGE[1]) ); } - - double weightage = Double.parseDouble(weightageString); - if (!Assessment.isWeightageWithinRange(weightage)) { - throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_WEIGHTAGE, - Assessment.WEIGHTAGE_RANGE[0], - Assessment.WEIGHTAGE_RANGE[1]) - ); - } } /** @@ -104,17 +87,51 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } + int maximumMarks = checkAndGetMaximumMarks(); + String name = argumentMap.get(KEY_ASSESSMENT_NAME); + double weightage = checkAndGetWeightage(name, teachingClass); + + Assessment assessment = new Assessment(name, maximumMarks, weightage); + + AssessmentList assessmentList = teachingClass.getAssessmentList(); + assert assessmentList != null : "assessment list should exist."; + boolean isSuccessful = assessmentList.addAssessment(assessment); + if (!isSuccessful) { + throw new TaaException(MESSAGE_FAIL_TO_ADD); + } + + assert storage != null : "storage should exist."; + storage.save(classList); + + assert ui != null : "ui should exist."; + ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_ADDED, classId, + assessment, assessmentList.getSize(), teachingClass)); + } + + public int checkAndGetMaximumMarks() throws TaaException { String maximumMarksString = argumentMap.get(KEY_MAXIMUM_MARKS); assert Util.isStringInteger(maximumMarksString); int maximumMarks = Integer.parseInt(maximumMarksString); - assert maximumMarks >= Assessment.MINIMUM_MARKS; - - String name = argumentMap.get(KEY_ASSESSMENT_NAME); + if (maximumMarks < Assessment.MINIMUM_MARKS) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS, + Assessment.MINIMUM_MARKS) + ); + } + return maximumMarks; + } + public double checkAndGetWeightage(String name, TeachingClass teachingClass) throws TaaException { String weightageString = argumentMap.get(KEY_WEIGHTAGE); assert Util.isStringDouble(weightageString); double weightage = Double.parseDouble(weightageString); - assert Assessment.isWeightageWithinRange(weightage); + if (!Assessment.isWeightageWithinRange(weightage)) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) + ); + } ArrayList assessments = teachingClass.getAssessmentList().getAssessments(); double totalWeightage = 0; for (Assessment a : assessments) { @@ -128,22 +145,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep if (!Assessment.isWeightageWithinRange(newTotalWeightage)) { throw new TaaException(MESSAGE_FORMAT_INVALID_TOTAL_WEIGHTAGE); } - - Assessment assessment = new Assessment(name, maximumMarks, weightage); - - AssessmentList assessmentList = teachingClass.getAssessmentList(); - assert assessmentList != null : "assessment list should exist."; - boolean isSuccessful = assessmentList.addAssessment(assessment); - if (!isSuccessful) { - throw new TaaException(MESSAGE_FAIL_TO_ADD); - } - - assert storage != null : "storage should exist."; - storage.save(classList); - - assert ui != null : "ui should exist."; - ui.printMessage(String.format(MESSAGE_FORMAT_ASSESSMENT_ADDED, classId, - assessment, assessmentList.getSize(), teachingClass)); + return weightage; } @Override diff --git a/src/main/java/taa/command/assessment/EditAssessmentCommand.java b/src/main/java/taa/command/assessment/EditAssessmentCommand.java index 4256321b16..a1a88576d9 100644 --- a/src/main/java/taa/command/assessment/EditAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/EditAssessmentCommand.java @@ -67,13 +67,6 @@ public void checkArgument() throws TaaException { Assessment.MINIMUM_MARKS) ); } - int newMaximumMarks = Integer.parseInt(newMaximumMarksString); - if (newMaximumMarks < Assessment.MINIMUM_MARKS) { - throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS, - Assessment.MINIMUM_MARKS) - ); - } } String newWeightageString = argumentMap.getOrDefault(KEY_NEW_WEIGHTAGE, null); @@ -85,14 +78,6 @@ public void checkArgument() throws TaaException { Assessment.WEIGHTAGE_RANGE[1]) ); } - double newWeightage = Double.parseDouble(newWeightageString); - if (!Assessment.isWeightageWithinRange(newWeightage)) { - throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, - Assessment.WEIGHTAGE_RANGE[0], - Assessment.WEIGHTAGE_RANGE[1]) - ); - } } } @@ -115,41 +100,42 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep } String name = argumentMap.get(KEY_ASSESSMENT_NAME); - Assessment assessment = teachingClass.getAssessmentList().getAssessment(name); AssessmentList assessmentList = teachingClass.getAssessmentList(); + Assessment assessment = assessmentList.getAssessment(name); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } assert (argumentMap.containsKey(KEY_NEW_ASSESSMENT_NAME) || argumentMap.containsKey(KEY_NEW_MAXIMUM_MARKS) || argumentMap.containsKey(KEY_NEW_WEIGHTAGE)) : "a new value to edit should at least exist."; + String newWeightageString = argumentMap.getOrDefault(KEY_NEW_WEIGHTAGE, null); + boolean hasValidNewWeightage = false; if (newWeightageString != null) { - assert Util.isStringDouble(newWeightageString); - double newWeightage = Double.parseDouble(newWeightageString); - assert Assessment.isWeightageWithinRange(newWeightage); - double totalWeightage = assessmentList.totalWeightageForEditAssessmentCommand(name); - double totalNewWeightage = totalWeightage + newWeightage; - if (!Assessment.isWeightageWithinRange(totalNewWeightage)) { - throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_NEW_TOTAL_WEIGHTAGE)); - } - assessment.setWeightage(newWeightage); + hasValidNewWeightage = checkWeightage(newWeightageString, assessmentList, name); } String newMaximumMarksString = argumentMap.getOrDefault(KEY_NEW_MAXIMUM_MARKS, null); + boolean hasValidNewMaximumMarks = false; if (newMaximumMarksString != null) { - assert Util.isStringInteger(newMaximumMarksString); - int newMaximumMarks = Integer.parseInt(newMaximumMarksString); - assert newMaximumMarks >= Assessment.MINIMUM_MARKS; - assessment.setMaximumMarks(newMaximumMarks); + hasValidNewMaximumMarks = checkMaximumMarks(newMaximumMarksString); } String newName = argumentMap.getOrDefault(KEY_NEW_ASSESSMENT_NAME, null); + boolean hasValidNewName = false; if (newName != null) { - boolean isValidNewName = assessmentList.checkRepeatedName(newName); - if (!isValidNewName) { - throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_NEW_NAME)); - } + hasValidNewName = checkNewName(newName, assessmentList, assessment); + } + + if (hasValidNewWeightage) { + double newWeightage = Double.parseDouble(newWeightageString); + assessment.setWeightage(newWeightage); + } + if (hasValidNewMaximumMarks) { + int newMaximumMarks = Integer.parseInt(newMaximumMarksString); + assessment.setMaximumMarks(newMaximumMarks); + } + if (hasValidNewName) { assessment.setName(newName); } @@ -161,6 +147,50 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assessment)); } + public boolean checkWeightage(String newWeightageString, AssessmentList assessmentList, String name) throws TaaException { + assert Util.isStringDouble(newWeightageString); + double newWeightage = Double.parseDouble(newWeightageString); + if (!Assessment.isWeightageWithinRange(newWeightage)) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) + ); + } + double totalWeightage = 0; + ArrayList assessments = assessmentList.getAssessments(); + for (Assessment a : assessments) { + if (!a.getName().equalsIgnoreCase(name)) { + totalWeightage += a.getWeightage(); + } + } + double totalNewWeightage = totalWeightage + newWeightage; + if (!Assessment.isWeightageWithinRange(totalNewWeightage)) { + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_NEW_TOTAL_WEIGHTAGE)); + } + return true; + } + + public boolean checkMaximumMarks(String newMaximumMarksString) throws TaaException { + assert Util.isStringInteger(newMaximumMarksString); + int newMaximumMarks = Integer.parseInt(newMaximumMarksString); + if (newMaximumMarks < Assessment.MINIMUM_MARKS) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS, + Assessment.MINIMUM_MARKS) + ); + } + return true; + } + + public boolean checkNewName(String newName, AssessmentList assessmentList, Assessment assessment) throws TaaException { + boolean isValidNewName = assessmentList.checkRepeatedName(assessment, newName); + if (!isValidNewName) { + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_NEW_NAME)); + } + return true; + } + @Override protected String getUsage() { return String.format( From 7a282649cf2e2de82498615a949238cb08bf9dbe Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 5 Nov 2021 15:49:13 +0800 Subject: [PATCH 334/543] Move string check to deserializer --- src/main/java/taa/assessment/Assessment.java | 4 +--- .../deserializer/AssessmentDeserializer.java | 5 +++++ .../deserializer/StudentDeserializer.java | 10 ++++++---- .../deserializer/TeachingClassDeserializer.java | 5 +++++ src/main/java/taa/student/Student.java | 16 ++++++---------- .../java/taa/teachingclass/TeachingClass.java | 5 ----- 6 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/main/java/taa/assessment/Assessment.java b/src/main/java/taa/assessment/Assessment.java index adc02dc991..9da36758dc 100644 --- a/src/main/java/taa/assessment/Assessment.java +++ b/src/main/java/taa/assessment/Assessment.java @@ -1,7 +1,6 @@ package taa.assessment; import taa.ClassChecker; -import taa.Parser; public class Assessment implements ClassChecker { public static final double[] WEIGHTAGE_RANGE = {0, 100}; @@ -74,8 +73,7 @@ public String toString() { */ @Override public boolean verify() { - if (name.isEmpty() || !Parser.isValueValid(name) || !isWeightageWithinRange(weightage) - || maximumMarks < MINIMUM_MARKS) { + if (name.isEmpty() || !isWeightageWithinRange(weightage) || maximumMarks < MINIMUM_MARKS) { return false; } diff --git a/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java b/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java index 58753d4e8d..ad8f68ce58 100644 --- a/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java +++ b/src/main/java/taa/storage/deserializer/AssessmentDeserializer.java @@ -6,6 +6,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; +import taa.Parser; import taa.assessment.Assessment; import taa.util.Util; @@ -28,6 +29,10 @@ public Assessment deserialize(JsonElement json, Type typeOfT, JsonDeserializatio JsonElement nameJson = jsonObject.get(MEMBER_NAME); String name = nameJson.getAsString(); + if (!Parser.isValueValid(name)) { + return null; + } + JsonElement weightageJson = jsonObject.get(MEMBER_WEIGHTAGE); if (!Util.isStringDouble(weightageJson.getAsString())) { return null; diff --git a/src/main/java/taa/storage/deserializer/StudentDeserializer.java b/src/main/java/taa/storage/deserializer/StudentDeserializer.java index e5f2a7b265..34523aa2a8 100644 --- a/src/main/java/taa/storage/deserializer/StudentDeserializer.java +++ b/src/main/java/taa/storage/deserializer/StudentDeserializer.java @@ -9,6 +9,7 @@ import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.reflect.TypeToken; +import taa.Parser; import taa.attendance.Attendance; import taa.attendance.AttendanceList; import taa.student.Student; @@ -22,10 +23,7 @@ public class StudentDeserializer extends StorageDeserializer implements JsonDese private static final String MEMBER_COMMENT = "comment"; private static final String MEMBER_ATTENDANCELIST = "attendanceList"; private static final String MEMBER_RESULTS = "results"; - private static final String[] COMPULSORY_MEMBERS = { - MEMBER_ID, - MEMBER_NAME - }; + private static final String[] COMPULSORY_MEMBERS = {MEMBER_ID, MEMBER_NAME}; @Override public Student deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) @@ -41,6 +39,10 @@ public Student deserialize(JsonElement json, Type typeOfT, JsonDeserializationCo JsonElement nameJson = jsonObject.get(MEMBER_NAME); String name = nameJson.getAsString(); + if (!Parser.isValueValid(id) || !Parser.isValueValid(name)) { + return null; + } + Student student = new Student(id, name); JsonElement commentJson = jsonObject.get(MEMBER_COMMENT); diff --git a/src/main/java/taa/storage/deserializer/TeachingClassDeserializer.java b/src/main/java/taa/storage/deserializer/TeachingClassDeserializer.java index a788e15ac3..abe4f10119 100644 --- a/src/main/java/taa/storage/deserializer/TeachingClassDeserializer.java +++ b/src/main/java/taa/storage/deserializer/TeachingClassDeserializer.java @@ -8,6 +8,7 @@ import com.google.gson.JsonElement; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; +import taa.Parser; import taa.assessment.Assessment; import taa.assessment.AssessmentList; import taa.teachingclass.TeachingClass; @@ -37,6 +38,10 @@ public TeachingClass deserialize(JsonElement json, Type typeOfT, JsonDeserializa JsonElement nameJson = jsonObject.get(MEMBER_NAME); String name = nameJson.getAsString(); + if (!Parser.isValueValid(id) || !Parser.isValueValid(name)) { + return null; + } + TeachingClass teachingClass = new TeachingClass(id, name); GsonBuilder gsonBuilder = new GsonBuilder(); diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index 170f9cb374..b3366f78f6 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -2,11 +2,7 @@ //@@author hozhenhong99 import taa.ClassChecker; -import taa.Parser; -import taa.assessment.Assessment; -import taa.assessment.AssessmentList; import taa.attendance.AttendanceList; -import taa.exception.TaaException; import java.util.HashMap; @@ -21,9 +17,9 @@ public class Student implements ClassChecker { private final HashMap results; public Student(String id, String name) { - this.id = id; - this.name = name; - this.comment = ""; + setId(id); + setName(name); + setComment(""); this.attendanceList = new AttendanceList(); this.results = new HashMap<>(); } @@ -69,7 +65,7 @@ public String getName() { * @param id the student ID of the student */ public void setId(String id) { - this.id = id; + this.id = id.toUpperCase(); } /** @@ -140,7 +136,7 @@ public HashMap getResults() { */ @Override public String toString() { - return String.format("%s (%s)", id, name); + return String.format("%s - %s", id, name); } /** @@ -155,6 +151,6 @@ public boolean marksExist(String assessmentName) { @Override public boolean verify() { - return !id.isEmpty() && !name.isEmpty() && Parser.isValueValid(id) && Parser.isValueValid(name); + return !id.isEmpty() && !name.isEmpty(); } } diff --git a/src/main/java/taa/teachingclass/TeachingClass.java b/src/main/java/taa/teachingclass/TeachingClass.java index 5e3a11b8b1..0b37b2a50b 100644 --- a/src/main/java/taa/teachingclass/TeachingClass.java +++ b/src/main/java/taa/teachingclass/TeachingClass.java @@ -2,7 +2,6 @@ //@@author leyondlee import taa.ClassChecker; -import taa.Parser; import taa.assessment.Assessment; import taa.assessment.AssessmentList; import taa.student.Student; @@ -78,10 +77,6 @@ public boolean verify() { return false; } - if (!Parser.isValueValid(id) || !Parser.isValueValid(name)) { - return false; - } - assert (assessmentList != null && studentList != null); HashMap assessmentMap = new HashMap<>(); From 4b35c98bdc882c57aa42d42dfc9e0ac98603fb88 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 5 Nov 2021 15:49:46 +0800 Subject: [PATCH 335/543] Add getStudentWithId method in StudentList --- src/main/java/taa/student/StudentList.java | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index 6bcb70f630..941706ed8c 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -94,6 +94,16 @@ public ArrayList findStudents(String keyword) { return studentsFound; } + public Student getStudentWithId(String id) { + for (Student student : students) { + if (student.getId().equalsIgnoreCase(id)) { + return student; + } + } + + return null; + } + @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(); From 8fe3b3676596f85a370b05fe2789f3ae401f51aa Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 5 Nov 2021 15:50:36 +0800 Subject: [PATCH 336/543] Use getStudentWithId in AddStudentCommand and EditStudentCommand instead of loop --- .../java/taa/command/student/AddStudentCommand.java | 12 ++++++------ .../java/taa/command/student/EditStudentCommand.java | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/taa/command/student/AddStudentCommand.java b/src/main/java/taa/command/student/AddStudentCommand.java index 7a2f9ee2ca..564435d0b0 100644 --- a/src/main/java/taa/command/student/AddStudentCommand.java +++ b/src/main/java/taa/command/student/AddStudentCommand.java @@ -52,16 +52,16 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep throw new TaaException(MESSAGE_CLASS_NOT_FOUND); } - String studentID = argumentMap.get(KEY_STUDENT_ID).toUpperCase(); + String studentId = argumentMap.get(KEY_STUDENT_ID); String studentName = argumentMap.get(KEY_STUDENT_NAME); - Student student = new Student(studentID, studentName); StudentList studentList = teachingClass.getStudentList(); - for (Student students : studentList.getStudents()) { - if (students.getId().equals(studentID)) { - throw new TaaException(MESSAGE_ID_ALREADY_EXISTS); - } + Student student = studentList.getStudentWithId(studentId); + if (student != null) { + throw new TaaException(MESSAGE_ID_ALREADY_EXISTS); } + + student = new Student(studentId, studentName); studentList.addStudent(student); storage.save(classList); diff --git a/src/main/java/taa/command/student/EditStudentCommand.java b/src/main/java/taa/command/student/EditStudentCommand.java index 5da3371e95..8e49d7dc7a 100644 --- a/src/main/java/taa/command/student/EditStudentCommand.java +++ b/src/main/java/taa/command/student/EditStudentCommand.java @@ -75,13 +75,13 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep throw new TaaException(MESSAGE_INVALID_STUDENT_INDEX); } - String newId = argumentMap.get(KEY_NEW_ID).toUpperCase(); + String newId = argumentMap.get(KEY_NEW_ID); String newName = argumentMap.get(KEY_NEW_NAME); - for (Student students : studentList.getStudents()) { - if (students.getId().equals(newId)) { - throw new TaaException(MESSAGE_ID_ALREADY_EXISTS); - } + Student existingStudent = studentList.getStudentWithId(newId); + if (existingStudent != null && existingStudent != student) { + throw new TaaException(MESSAGE_ID_ALREADY_EXISTS); } + student.setId(newId); student.setName(newName); From 1c8080f85f31534556e092b4a32ad64833cf62a6 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 5 Nov 2021 15:51:46 +0800 Subject: [PATCH 337/543] Add checking of duplicated students in StudentList.verify() method --- src/main/java/taa/student/StudentList.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/main/java/taa/student/StudentList.java b/src/main/java/taa/student/StudentList.java index 941706ed8c..6374ada599 100644 --- a/src/main/java/taa/student/StudentList.java +++ b/src/main/java/taa/student/StudentList.java @@ -122,6 +122,20 @@ public String toString() { @Override public boolean verify() { + ArrayList studentIds = new ArrayList<>(); + ArrayList duplicatedStudents = new ArrayList<>(); + for (Student student : students) { + if (studentIds.contains(student.getId())) { + duplicatedStudents.add(student); + } else { + studentIds.add(student.getId()); + } + } + + for (Student student : duplicatedStudents) { + students.remove(student); + } + return true; } } From 15bfd149e4a6a076f3dd791c16252913e9461426 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 5 Nov 2021 16:01:04 +0800 Subject: [PATCH 338/543] Make note placement consistent --- docs/UserGuide.md | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 2ccd82d483..fe66c6d3d2 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -129,6 +129,7 @@ Adds a student to a particular class. Format: `add_student c/ i/ n/` * `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). + * Case-insensitive * `STUDENT_ID` refers to the ID of the student (e.g. A0217978J). * `STUDENT_NAME` refers to the name of the student (e.g. Jon Lim). @@ -136,9 +137,6 @@ Examples: * `add_student c/CS2113T-F11 i/a0212345x n/Jon Lim` * `add_student c/CS2101-C04 n/Jonny Lims i/a1234567i` -> 💡 **Note:**
-> `STUDENT_ID` will be converted to uppercase. -
#### Editing a student's information in a class: `edit_student` @@ -154,9 +152,6 @@ Examples: * `edit_student c/CS2113T-F11 s/1 i/a03452345x n/Jon Lim` * `edit_student c/CS2101-D03 s/5 n/Jonny Lims i/a120067i` -> 💡 **Note:**
-> `STUDENT_ID` will be converted to uppercase. -
#### Deleting a student from a class: `delete_student` @@ -428,12 +423,12 @@ Format: `set_comment c/ s/ t/` * `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `COMMENT` refers to the comment to be set. -> 💡 **Note:**
-> The new comment will overwrite any previous comment set Examples: * `set_comment c/CS2113T-F12 s/1 t/Doing well in class` * `set_comment c/CS2113T-F12 s/1 t/Needs help understanding java` +> 💡 **Note:**
+> The new comment will overwrite any previous comment set
From 42fea57575983653a23a8ceac259a5d253086f4d Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 5 Nov 2021 16:01:38 +0800 Subject: [PATCH 339/543] Update StudentTest --- src/test/java/taa/StudentTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/java/taa/StudentTest.java b/src/test/java/taa/StudentTest.java index a48e2b4d6b..087836ee6a 100644 --- a/src/test/java/taa/StudentTest.java +++ b/src/test/java/taa/StudentTest.java @@ -10,7 +10,7 @@ public class StudentTest { @Test public void testStringConversion() { - assertEquals("A1234567B (Jon Lim)", new Student("A1234567B", "Jon Lim").toString()); + assertEquals("A1234567B - Jon Lim", new Student("A1234567B", "Jon Lim").toString()); } @Test From 39d96e0ac0cf7248787d1ecdac62400aafafc14c Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 5 Nov 2021 16:15:28 +0800 Subject: [PATCH 340/543] Use StringBuilder to create string for duplicated keys --- .../java/taa/exception/DuplicatedArgumentException.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/taa/exception/DuplicatedArgumentException.java b/src/main/java/taa/exception/DuplicatedArgumentException.java index 6aa50059a1..8d0188efdb 100644 --- a/src/main/java/taa/exception/DuplicatedArgumentException.java +++ b/src/main/java/taa/exception/DuplicatedArgumentException.java @@ -10,16 +10,16 @@ public DuplicatedArgumentException(ArrayList duplicatedKeys) { } private static String generateMessage(ArrayList duplicatedKeys) { - String duplicatedKeysStr = ""; + StringBuilder duplicatedKeysStr = new StringBuilder(); for (int i = 0; i < duplicatedKeys.size(); i += 1) { String key = duplicatedKeys.get(i); if (i > 0) { - duplicatedKeysStr += ", "; + duplicatedKeysStr.append(", "); } - duplicatedKeysStr += key; + duplicatedKeysStr.append(key); } - return String.format(MESSAGE_FORMAT_DUPLICATED_KEYS_FOUND, duplicatedKeysStr); + return String.format(MESSAGE_FORMAT_DUPLICATED_KEYS_FOUND, duplicatedKeysStr.toString()); } } From b64d4b1bd32e1769a963428c359c724773972e47 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 5 Nov 2021 16:17:46 +0800 Subject: [PATCH 341/543] Add FileCreationException --- src/main/java/taa/exception/FileCreationException.java | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/main/java/taa/exception/FileCreationException.java diff --git a/src/main/java/taa/exception/FileCreationException.java b/src/main/java/taa/exception/FileCreationException.java new file mode 100644 index 0000000000..236c6500fe --- /dev/null +++ b/src/main/java/taa/exception/FileCreationException.java @@ -0,0 +1,9 @@ +package taa.exception; + +public class FileCreationException extends TaaException { + private static final String MESSAGE_FORMAT_FAIL_CREATE_FILE = "Fail to create file - %s"; + + public FileCreationException(String filename) { + super(String.format(MESSAGE_FORMAT_FAIL_CREATE_FILE, filename)); + } +} From 4648435bd2ecd86816db32605c8f2928878bad7b Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 5 Nov 2021 16:18:10 +0800 Subject: [PATCH 342/543] Throw FileCreationException when fail to create file --- src/main/java/taa/util/Util.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java index 45b3b44b7f..cb9fa4c8e4 100644 --- a/src/main/java/taa/util/Util.java +++ b/src/main/java/taa/util/Util.java @@ -1,6 +1,8 @@ package taa.util; //@@author leyondlee +import taa.exception.FileCreationException; + import java.io.File; import java.io.IOException; import java.nio.file.Path; @@ -81,11 +83,11 @@ public static boolean fileExists(String filename) { * Creates a file and parent directories (if necessary). * * @param filename The file to create. - * @return true if file already exists or successfully created, else false. + * @throws FileCreationException if fail to create file. */ - public static boolean createFile(String filename) { + public static void createFile(String filename) throws FileCreationException { if (fileExists(filename)) { - return true; + return; } File file = new File(filename); @@ -112,7 +114,9 @@ public static boolean createFile(String filename) { result = false; } - return result; + if (!result) { + throw new FileCreationException(filename); + } } public static String getAbsolutePath(String pathStr) { From 0a2925bd1920628b72928c92f81f59ee8a45f783 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 5 Nov 2021 16:20:07 +0800 Subject: [PATCH 343/543] Remove result check for Util.createFile method --- src/main/java/taa/storage/Storage.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/main/java/taa/storage/Storage.java b/src/main/java/taa/storage/Storage.java index 46c266617d..d51d38b773 100644 --- a/src/main/java/taa/storage/Storage.java +++ b/src/main/java/taa/storage/Storage.java @@ -18,7 +18,6 @@ import java.io.IOException; public class Storage { - private static final String MESSAGE_FORMAT_FAIL_CREATE_FILE = "Fail to create file/folder - %s"; private static final String MESSAGE_FORMAT_UNABLE_TO_OPEN_READ = "Unable to open file to read - %s"; private static final String MESSAGE_FORMAT_UNABLE_TO_OPEN_WRITE = "Unable to open file to write - %s"; private static final String MESSAGE_FORMAT_UNABLE_TO_READ_JSON = "Unable to read from JSON file - %s"; @@ -70,9 +69,7 @@ public ClassList load() throws TaaException { * @throws TaaException if fail to create, open, or write to the file. */ public void save(ClassList classList) throws TaaException { - if (!Util.createFile(filename)) { - throw new TaaException(String.format(MESSAGE_FORMAT_FAIL_CREATE_FILE, Util.getAbsolutePath(filename))); - } + Util.createFile(filename); assert Util.fileExists(filename); From 4abf13fef8ef3f2e34069765274a2c5d5e51fd76 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 5 Nov 2021 16:32:40 +0800 Subject: [PATCH 344/543] Add JavaDoc to methods --- src/main/java/taa/Parser.java | 8 ++++++++ src/main/java/taa/teachingclass/TeachingClass.java | 7 +++++++ src/main/java/taa/util/Util.java | 3 ++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 9806b533cc..5ad53c01e1 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -1,6 +1,7 @@ package taa; //@@author leyondlee + import taa.command.ArchiveCommand; import taa.command.ResetCommand; import taa.command.assessment.AddAssessmentCommand; @@ -289,6 +290,13 @@ public static boolean isValueValid(String value) { return matcher.find(); } + /** + * Converts character into a regex pattern string. Character is escaped if needed. + * Note: This method is not complete and may not escape all characters which may need to be escaped. + * + * @param c The character to convert. + * @return A regex pattern string. + */ private static String convertToRegexPattern(char c) { boolean needEscape; switch (c) { diff --git a/src/main/java/taa/teachingclass/TeachingClass.java b/src/main/java/taa/teachingclass/TeachingClass.java index 0b37b2a50b..26cb50a1cb 100644 --- a/src/main/java/taa/teachingclass/TeachingClass.java +++ b/src/main/java/taa/teachingclass/TeachingClass.java @@ -1,6 +1,7 @@ package taa.teachingclass; //@@author leyondlee + import taa.ClassChecker; import taa.assessment.Assessment; import taa.assessment.AssessmentList; @@ -108,6 +109,12 @@ public boolean verify() { return true; } + /** + * Checks if the ID is valid. ID is valid if it is not empty and does not contain any spaces. + * + * @param id The ID to check. + * @return true if ID is valid, else false. + */ public static boolean isValidId(String id) { return !id.isEmpty() && !id.contains(" "); } diff --git a/src/main/java/taa/util/Util.java b/src/main/java/taa/util/Util.java index cb9fa4c8e4..946e4d90f4 100644 --- a/src/main/java/taa/util/Util.java +++ b/src/main/java/taa/util/Util.java @@ -1,6 +1,7 @@ package taa.util; //@@author leyondlee + import taa.exception.FileCreationException; import java.io.File; @@ -80,7 +81,7 @@ public static boolean fileExists(String filename) { } /** - * Creates a file and parent directories (if necessary). + * Creates a file and parent directories (if necessary). This method has no effect if the file already exists. * * @param filename The file to create. * @throws FileCreationException if fail to create file. From fa48242e7ea4a10433d9fd36298ac11bd837860f Mon Sep 17 00:00:00 2001 From: rachel Date: Fri, 5 Nov 2021 18:31:26 +0800 Subject: [PATCH 345/543] update checkstyle --- src/main/java/taa/assessment/AssessmentList.java | 2 +- .../java/taa/command/assessment/EditAssessmentCommand.java | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 61d553b26e..2629ee2a29 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -89,7 +89,7 @@ public double totalWeightageForEditAssessmentCommand(String assessmentName) { public boolean checkRepeatedName(Assessment assessment, String newAssessmentName) { for (Assessment a : assessments) { if (a.getName().equalsIgnoreCase(newAssessmentName) && (a != assessment)) { - return false; + return false; } } return true; diff --git a/src/main/java/taa/command/assessment/EditAssessmentCommand.java b/src/main/java/taa/command/assessment/EditAssessmentCommand.java index a1a88576d9..536f600914 100644 --- a/src/main/java/taa/command/assessment/EditAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/EditAssessmentCommand.java @@ -147,7 +147,8 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assessment)); } - public boolean checkWeightage(String newWeightageString, AssessmentList assessmentList, String name) throws TaaException { + public boolean checkWeightage(String newWeightageString, AssessmentList assessmentList, String name) + throws TaaException { assert Util.isStringDouble(newWeightageString); double newWeightage = Double.parseDouble(newWeightageString); if (!Assessment.isWeightageWithinRange(newWeightage)) { @@ -183,7 +184,8 @@ public boolean checkMaximumMarks(String newMaximumMarksString) throws TaaExcepti return true; } - public boolean checkNewName(String newName, AssessmentList assessmentList, Assessment assessment) throws TaaException { + public boolean checkNewName(String newName, AssessmentList assessmentList, Assessment assessment) + throws TaaException { boolean isValidNewName = assessmentList.checkRepeatedName(assessment, newName); if (!isValidNewName) { throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_NEW_NAME)); From 93563ca5f1bdedd186e9c557841090373fe0f035 Mon Sep 17 00:00:00 2001 From: Leyond Date: Fri, 5 Nov 2021 19:10:26 +0800 Subject: [PATCH 346/543] Remove method explanations --- docs/DeveloperGuide.md | 83 +++++++++--------------------------------- 1 file changed, 18 insertions(+), 65 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 98daf10050..5b18f58322 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -53,75 +53,47 @@ The _Architecture Sequence Diagram_ shown above shows how the components usually The sequence diagram shown below illustrates how the `add_class` command works: ![AddClassSequenceDiagram](diagrams/AddClassSequenceDiagram.png) -Steps: -1. The `Taa` instance reads in a user input and calls `AddClassCommand.execute(classList:ClassList, ui:Ui, storage:Storage)`. -2. A new `TeachingClass` object is created and the `ClassList.addClass(teachingClass:TeachingClass)` method is invoked -to add the `TeachingClass` object into the list of classes. -3. Lastly, a message indicating that the class has been added will be printed out. +Below is an example scenario of how the add class feature behaves at each step:
+* Step 1 - The user executes `add_class i/CS2113T-F12 n/Tutorial Group F12` to add a class. The `add_class` command calls the +`AddClassCommand.execute` method. +* Step 2 - Within `AddClassCommand.execute`, `ClassList.getModule("CS2113T-F12")` is called to ensure that +there is no existing class with ID `CS2113T-F12`. +* Step 3 - If no existing class with ID `CS2113T-F12` is found, a new `TeachingClass` object with ID and name set to `CS2113T-F12` +and `Tutorial Group F12` respectively. +* Step 4 - Then, `ClassList.addClass` is called to add the newly created `TeachingClass` object into the `classes` ArrayList +within `ClassList`.
### Add Student -The add student mechanism is facilitated by `AddStudentCommand`. It extends `Command` and uses `StudentList` which -stores student internally as an ArrayList `students`. -
- -`AddStudentCommand` implements the following methods: -* `AddStudentCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Performs operations for the command. - -`StudentList` implements the following methods: -* `StudentList#getSize()` - Returns the no. of students currently in the list. -* `StudentList#getStudents()` - Returns an ArrayList containing all the students. -* `StudentList#getStudentAt(index:int)` - Returns a student with the particular index. -* `StudentList#isValidIndex(index:int)` - Checks if an index is valid w.r.t the `students` ArrayList. -* `StudentList#addStudent(student:Student)` - Adds a student to the `students` ArrayList. -* `StudentList#deleteStudent(index:int)` - Deletes the `student` object at the specified `index` within the `students` -ArrayList. -* `StudentList#findStudent(keyword:String)` - Returns an ArrayList of students containing the keyword - The sequence diagram shown below illustrates how the `add_student` command works: ![AddStudentSequenceDiagram](diagrams/AddStudentSequenceDiagram.png) Below is an example scenario of how the add student feature behaves at each step:
* Step 1 - The user executes `add_student c/CS2113T i/a0217978j n/jonny` to add a student. The `add_student` command -calls the `AddStudentCommand#execute` method. Within `AddStudentCommand#execute`, `ModuleList#getModule("CS2113T")` is +calls the `AddStudentCommand.execute` method. Within `AddStudentCommand.execute`, `ModuleList.getModule("CS2113T")` is called to ensure that there is an existing module with code `CS2113T`. * Step 2 - If an existing module with code `CS2113T` is found, a new `Student` object with id and name set to -`a0217978j` and `jonny` respectively. Then, `StudentList#addModule` is called to add the newly created `Student` +`a0217978j` and `jonny` respectively. Then, `StudentList.addModule` is called to add the newly created `Student` object into the `students` ArrayList within `StudentList`.
### Add Assessment -The add assessment mechanism is facilitated by `AddAssessmentCommand`. It extends `Command` and uses `AssessmentList` -which stores assessment internally as an ArrayList `assessments`.
- -`AddAssessmentCommand` implements the following methods: -* `AddAssessmentCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Performs operations for the command. - -`AssessmentList` implements the following methods: -* `AssessmentList#getSize()` - Returns the no. of assessments currently in the list. -* `AssessmentList#getAssessments()` - Returns an ArrayList containing all the assessments. -* `AssessmentList#getAssessment(assessmentName:String)` - Returns an assessment with a particular name specified by the - user. -* `AssessmentList#addAssessment(assessment:Assessment)` - Adds an assessment to the `assessments` ArrayList. -* `AssessmentList#deleteAssessment(assessmentName:String)` - Deletes an assessment with the name specified by the user - from the `assessments` ArrayList. - The sequence diagram shown below illustrates how the `add_assessment` command works: ![AddAssessmentSequenceDiagram](diagrams/AddAssessmentSequenceDiagram.png) Below is an example scenario of how the add assessment feature behaves at each step: * Step 1 - The user executes `add_assessment c/cs2113t n/midterms m/20 w/10` to add an assessment. The `add_assessment` - command calls the `AddAssessmentCommand#execute` method. Within `AddAssessmentCommand#execute`, - `ModuleList#getModuleWithCode("cs2113t")` is called to ensure that there is an existing module with code `cs2113t`. + command calls the `AddAssessmentCommand.execute` method. Within `AddAssessmentCommand.execute`, + `ModuleList.getModuleWithCode("cs2113t")` is called to ensure that there is an existing module with code `cs2113t`. * Step 2 - If an existing module with code `cs2113t` is found, the `MAXIMUM_MARKS` and `WEIGHTAGE` arguments are checked to ensure that they are valid. * Step 3 - If the `MAXIMUM_MARKS` and `WEIGHTAGE` arguments are valid, a new `Assessment` object with name, maximum marks and weightage set to `midterms`, `20` and `10` respectively is created under the existing `Module` with - code `cs2113t`. Then, `AssessmentList#addAssessment` is called to add the newly created `Assessment` object into the + code `cs2113t`. Then, `AssessmentList.addAssessment` is called to add the newly created `Assessment` object into the `assessments` ArrayList within `AssessmentList`. -* Step 4 - Within `AssessmentList#addAssessment`, the name of the newly created `Assessment` object is checked to ensure +* Step 4 - Within `AssessmentList.addAssessment`, the name of the newly created `Assessment` object is checked to ensure there is no existing assessment with name `midterms`. At the same time, the weightage of the newly created `Assessment` object is also checked to ensure that the total weightage of the assessments in the `cs2113t` module will not exceed 100 with the addition of the weightage of the newly created `Assessment` object. @@ -149,41 +121,22 @@ Steps: student's `results` HashMap. 9. A message will then be printed out to indicate to the user that the marks have been set successfully. - -### Set Attendance -The set attendance mechanism is facilitated by SetAttendanceCommand. It extends `Command` and -uses `AttendanceList` which stores a student's lessons attendance as an -ArrayList `attendances`.
-`SetAttendanceCommand` implements the following methods: -* `SetAttendanceCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Performs operations for the command. - -`AttendanceList` implements the following methods: -* `AttendanceList#getSize()` - Returns the no. of attendance currently in the list. -* `AttendanceList#getAttendances()` - Returns an ArrayList containing all the attendances. -* `AttendanceList#getAttendance(lessonNumber:String)` - Returns an attendance with a particular lesson number. -* `AttendanceList#isValidIndex(index:int)` - Checks if an index is valid w.r.t the `attendances` ArrayList. -* `AttendanceList#addAttendance(attendance:Attendance)` - Adds an attendance to the `attendances` ArrayList. -* `AttendnaceList#getAttendnaceIndex(lessonNumInput:String)` - Returns the attendance index in the `attendances` -ArrayList. -* `AttendanceList#deleteAttendance(lessonNumInput:String)` - Deletes an attendance with a particular lesson number. -* `AttendanceList#sortAttendances` - Sorts the attendance in the `attendances` ArrayList in ascending order based on -lesson number. - +### Set Attendance The sequence diagram shown below illustrates how the `set_attendance` command works: ![SetAttendanceSequenceDiagram](diagrams/SetAttendanceSequenceDiagram.png) Below is an example scenario of how the set attendance feature behaves at each step: * Step 1 - The user executes `set_attendance c/CS2113T s/1 l/1 p/1` to set an attendance to `Present` for student at index `1`, lesson number `1` to set a student's attendance for a lesson. The `set_attendance` command calls the -`SetAttendanceCommand#execute` method. Within `SetAttendanceCommand#execute`, `AttendanceList#getAttendance("1")` is +`SetAttendanceCommand.execute` method. Within `SetAttendanceCommand.execute`, `AttendanceList.getAttendance("1")` is called to ensure that there is no existing attendance with the lesson number `1`for student at index `1`. * Step 2 - If no existing attendance object with lesson number `1` for student at index `1` is found, a new `Attendance` object with lesson number `1` and attendance record `Present` is set as its lesson number and attendance record respectively. -Then, `AttendanceList#addAttendance` is called to add the newly created `Attendance` object into the `attendances` +Then, `AttendanceList.addAttendance` is called to add the newly created `Attendance` object into the `attendances` ArrayList within `AttendanceList`.
From 0f9ca3c3945fdb3447f819ad2502d83fe4a95d85 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Fri, 5 Nov 2021 22:08:55 +0800 Subject: [PATCH 347/543] edit sequence diagram and add author --- docs/diagrams/SetMarkSequenceDiagram.png | Bin 71455 -> 48164 bytes docs/diagrams/SetMarkSequenceDiagram.puml | 44 ++++-------------- .../taa/command/mark/AverageMarksCommand.java | 1 + .../taa/command/mark/DeleteMarkCommand.java | 1 + .../taa/command/mark/EditMarkCommand.java | 1 + .../taa/command/mark/ListMarksCommand.java | 1 + .../taa/command/mark/MedianMarkCommand.java | 1 + .../java/taa/command/mark/SetMarkCommand.java | 1 + 8 files changed, 15 insertions(+), 35 deletions(-) diff --git a/docs/diagrams/SetMarkSequenceDiagram.png b/docs/diagrams/SetMarkSequenceDiagram.png index 641dba82f9d3103079ccffb0b9c70f5eec0a0df5..31243b51049fc889f26f1db79c448d674b483986 100644 GIT binary patch literal 48164 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�Y@~z)|II2d9-Uz2JSrn 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

n1HfvE@q5XLM5(|tJ<~U<)ug+n`dZH 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\nParser" as parser -Participant ":AddModuleCommand" as addModuleCommand -Participant ":ModuleList" as moduleList -Participant ":Module" as module -Participant ":Storage" as storage - -activate taa - -taa -> ui : getUserInput() -activate ui - -user -> ui : "add_module c/CS2113T\nn/Software Engineering" -ui --> taa : userInput:String -deactivate ui - -taa -> parser : parseUserInput(userInput) -activate parser - -create addModuleCommand -parser -> addModuleCommand -activate addModuleCommand -addModuleCommand -> parser -deactivate addModuleCommand - -parser --> taa : command:AddModuleCommand -deactivate parser - -taa -> addModuleCommand : checkArguments() -activate addModuleCommand - -addModuleCommand --> taa -deactivate addModuleCommand - -taa -> addModuleCommand : execute(moduleList:ModuleList, ui:Ui, storage:Storage) -activate addModuleCommand - -create module -addModuleCommand -> module -activate module -module --> addModuleCommand -deactivate module - -addModuleCommand -> moduleList : addModule(module:Module) -activate moduleList -moduleList --> addModuleCommand -deactivate moduleList - -addModuleCommand -> storage : save(moduleList:ModuleList) -activate storage -storage --> addModuleCommand -deactivate storage - -addModuleCommand -> ui : printMessage("Module added: ...") -activate ui -ui -> user : Display message:\n"Module added: ..." -ui --> addModuleCommand -deactivate ui - -deactivate addModuleCommand - -@enduml \ No newline at end of file diff --git a/docs/diagrams/ArchitectureSequenceDiagram.png b/docs/diagrams/ArchitectureSequenceDiagram.png index 48a8d1b5dd8a931119cee40e9e2b680d7e906aab..0ba660a130b2306883e8df2aff27ed6306762ebb 100644 GIT binary patch literal 52695 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 literal 54066 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\nParser" as parser Participant ":Command" as command Participant "<>\nUtil" as util -Participant ":ModuleList" as moduleList +Participant ":ClassList" as classList Participant ":Storage" as storage activate taa -taa -> taa : loadModuleListFromStorage() +taa -> taa : loadClassListFromStorage() activate taa taa -> storage : load() activate storage -create moduleList -storage -> moduleList -activate moduleList -moduleList --> storage -deactivate moduleList +create classList +storage -> classList +activate classList +classList --> storage +deactivate classList -storage --> taa : moduleList:ModuleList +storage --> taa : classList:ClassList deactivate storage taa --> taa @@ -61,7 +61,7 @@ deactivate util command --> taa deactivate command -taa -> command : execute(moduleList:ModuleList, ui:Ui,\n\tstorage:Storage) +taa -> command : execute(classList:ClassList,\n\tui:Ui, storage:Storage) activate command command -> util @@ -69,12 +69,12 @@ activate util util --> command deactivate util -command -> moduleList -activate moduleList -moduleList --> command -deactivate moduleList +command -> classList +activate classList +classList --> command +deactivate classList -command -> storage : save(moduleList:ModuleList) +command -> storage : save(classList) activate storage storage --> command deactivate storage @@ -98,5 +98,6 @@ destroy command taa -[hidden]-> command end +deactivate taa -@enduml \ No newline at end of file +@enduml From f411882fe47e5201780ad55c055e39cf241eb5ff Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 18:10:26 +0800 Subject: [PATCH 302/543] Remove merge conflict line --- docs/DeveloperGuide.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 58f6fb8722..98daf10050 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -51,7 +51,6 @@ The _Architecture Sequence Diagram_ shown above shows how the components usually ## Implementation ### Add Class The sequence diagram shown below illustrates how the `add_class` command works: ->>>>>>> upstream/master ![AddClassSequenceDiagram](diagrams/AddClassSequenceDiagram.png) Steps: From e602c0a69c0d65459d90867f4b56f448e449aa55 Mon Sep 17 00:00:00 2001 From: rachel Date: Tue, 2 Nov 2021 18:55:40 +0800 Subject: [PATCH 303/543] Refactor assessment-related code to be shorter and fix issue of duplicate names in assessment list when editing assessment --- .../java/taa/assessment/AssessmentList.java | 24 ++++++- .../assessment/EditAssessmentCommand.java | 71 ++++++++++--------- 2 files changed, 59 insertions(+), 36 deletions(-) diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index eae2c42c16..8f081fe359 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -43,8 +43,9 @@ public boolean addAssessment(Assessment assessment) { } double newTotalWeightage = totalWeightage + assessment.getWeightage(); - if (!Assessment.isWeightageWithinRange(newTotalWeightage) - || assessment.getMaximumMarks() < Assessment.MINIMUM_MARKS) { + boolean isWeightageValid = Assessment.isWeightageWithinRange(newTotalWeightage); + boolean isMaximumMarksValid = assessment.getMaximumMarks() >= Assessment.MINIMUM_MARKS; + if (!isWeightageValid || !isMaximumMarksValid) { return false; } @@ -88,6 +89,25 @@ public Assessment getAssessment(String assessmentName) { return null; } + public double totalWeightageForEditAssessmentCommand(String assessmentName) { + double totalWeightage = 0; + for (Assessment a : assessments) { + if (!a.getName().equalsIgnoreCase(assessmentName)) { + totalWeightage += a.getWeightage(); + } + } + return totalWeightage; + } + + public boolean checkRepeatedName(String newAssessmentName) { + for (Assessment a : assessments) { + if (a.getName().equalsIgnoreCase(newAssessmentName)) { + return false; + } + } + return true; + } + @Override public String toString() { StringBuilder stringBuilder = new StringBuilder(); diff --git a/src/main/java/taa/command/assessment/EditAssessmentCommand.java b/src/main/java/taa/command/assessment/EditAssessmentCommand.java index 75403aca48..c2796987e2 100644 --- a/src/main/java/taa/command/assessment/EditAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/EditAssessmentCommand.java @@ -2,6 +2,7 @@ import taa.Ui; import taa.assessment.Assessment; +import taa.assessment.AssessmentList; import taa.teachingclass.ClassList; import taa.teachingclass.TeachingClass; import taa.command.Command; @@ -29,8 +30,12 @@ public class EditAssessmentCommand extends Command { + "%s/ [%s/] [%s/] [%s/]"; private static final String MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE = "Invalid new weightage. " + "Weightage must be between %,.2f and %,.2f (inclusive)"; + private static final String MESSAGE_FORMAT_INVALID_NEW_TOTAL_WEIGHTAGE = "Invalid new weightage. " + + "Total new weightage exceeds 100%%."; private static final String MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS = "Invalid new maximum marks. " + "Maximum marks must be larger than %d (inclusive)"; + private static final String MESSAGE_FORMAT_INVALID_NEW_NAME = "Invalid new name. " + + "An assessment with the same name already exists."; private static final String MESSAGE_FORMAT_ASSESSMENT_EDITED = "Assessment in %s updated:\n %s"; public EditAssessmentCommand(String argument) { @@ -62,6 +67,13 @@ public void checkArgument() throws TaaException { Assessment.MINIMUM_MARKS) ); } + int newMaximumMarks = Integer.parseInt(newMaximumMarksString); + if (newMaximumMarks < Assessment.MINIMUM_MARKS) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS, + Assessment.MINIMUM_MARKS) + ); + } } String newWeightageString = argumentMap.getOrDefault(KEY_NEW_WEIGHTAGE, null); @@ -73,6 +85,14 @@ public void checkArgument() throws TaaException { Assessment.WEIGHTAGE_RANGE[1]) ); } + double newWeightage = Double.parseDouble(newWeightageString); + if (!Assessment.isWeightageWithinRange(newWeightage)) { + throw new TaaException(String.format( + MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, + Assessment.WEIGHTAGE_RANGE[0], + Assessment.WEIGHTAGE_RANGE[1]) + ); + } } } @@ -96,6 +116,7 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep String name = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = teachingClass.getAssessmentList().getAssessment(name); + AssessmentList assessmentList = teachingClass.getAssessmentList(); if (assessment == null) { throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); } @@ -106,50 +127,32 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep if (newWeightageString != null) { assert Util.isStringDouble(newWeightageString); double newWeightage = Double.parseDouble(newWeightageString); - if (!Assessment.isWeightageWithinRange(newWeightage)) { - throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, - Assessment.WEIGHTAGE_RANGE[0], - Assessment.WEIGHTAGE_RANGE[1]) - ); - } - double totalNewWeightage = 0; - ArrayList assessments = teachingClass.getAssessmentList().getAssessments(); - for (Assessment a : assessments) { - if (a.getName() != name) { - totalNewWeightage += a.getWeightage(); - } - } - double newTotalNewWeightage = totalNewWeightage + newWeightage; - if (Assessment.isWeightageWithinRange(newTotalNewWeightage)) { - assessment.setWeightage(newWeightage); - } else { - throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_NEW_WEIGHTAGE, - Assessment.WEIGHTAGE_RANGE[0], - Assessment.WEIGHTAGE_RANGE[1]) - ); + assert Assessment.isWeightageWithinRange(newWeightage); + double totalWeightage = assessmentList.totalWeightageForEditAssessmentCommand(name); + double totalNewWeightage = totalWeightage + newWeightage; + if (!Assessment.isWeightageWithinRange(totalNewWeightage)) { + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_NEW_TOTAL_WEIGHTAGE)); } - } - - String newName = argumentMap.getOrDefault(KEY_NEW_ASSESSMENT_NAME, null); - if (newName != null) { - assessment.setName(newName); + assessment.setWeightage(newWeightage); } String newMaximumMarksString = argumentMap.getOrDefault(KEY_NEW_MAXIMUM_MARKS, null); if (newMaximumMarksString != null) { assert Util.isStringInteger(newMaximumMarksString); int newMaximumMarks = Integer.parseInt(newMaximumMarksString); - if (newMaximumMarks < Assessment.MINIMUM_MARKS) { - throw new TaaException(String.format( - MESSAGE_FORMAT_INVALID_NEW_MAXIMUM_MARKS, - Assessment.MINIMUM_MARKS) - ); - } + assert newMaximumMarks >= Assessment.MINIMUM_MARKS; assessment.setMaximumMarks(newMaximumMarks); } + String newName = argumentMap.getOrDefault(KEY_NEW_ASSESSMENT_NAME, null); + if (newName != null) { + boolean isValidNewName = assessmentList.checkRepeatedName(newName); + if (!isValidNewName) { + throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_NEW_NAME)); + } + assessment.setName(newName); + } + assert storage != null : "storage should exist."; storage.save(classList); From d5198eaac2a2a0c55dccb2f7b48a163952778e23 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 18:57:05 +0800 Subject: [PATCH 304/543] Refactor ClassObjectDeserializer to TeachingClassDeserializer --- ...lassObjectDeserializer.java => TeachingClassDeserializer.java} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/main/java/taa/storage/deserializer/{ClassObjectDeserializer.java => TeachingClassDeserializer.java} (100%) diff --git a/src/main/java/taa/storage/deserializer/ClassObjectDeserializer.java b/src/main/java/taa/storage/deserializer/TeachingClassDeserializer.java similarity index 100% rename from src/main/java/taa/storage/deserializer/ClassObjectDeserializer.java rename to src/main/java/taa/storage/deserializer/TeachingClassDeserializer.java From 2244e22710adde1b028964b5bee35ec43cac6f1f Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 18:57:46 +0800 Subject: [PATCH 305/543] Add parameter to include/exclude empty values for getArgumentsFromString --- src/main/java/taa/Parser.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 3350804cba..4eee8ac8c4 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -212,8 +212,8 @@ public static String[] splitFirstSpace(String string) { * @return HashMap - argumentKey:argumentValue pair. * @throws TaaException if there are any duplicated keys found within string or value is invalid. */ - public static HashMap getArgumentsFromString(String string, String[] argumentKeys) - throws TaaException { + public static HashMap getArgumentsFromString(String string, String[] argumentKeys, + boolean includeEmptyValues) throws TaaException { if (argumentKeys == null || argumentKeys.length == 0) { return new HashMap<>(); } @@ -262,7 +262,10 @@ public static HashMap getArgumentsFromString(String string, Stri throw new TaaException(String.format(MESSAGE_FORMAT_INVALID_VALUE, getSpecialCharactersAsString())); } - result.put(key, value); + boolean canAdd = includeEmptyValues || !value.isEmpty(); + if (canAdd) { + result.put(key, value); + } } return result; From 92ed1373ac59273cf33c2435308155b2f1b3964b Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 18:57:58 +0800 Subject: [PATCH 306/543] Update ParserTest --- src/test/java/taa/ParserTest.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/test/java/taa/ParserTest.java b/src/test/java/taa/ParserTest.java index 00f2bdcb00..4fadd7b3a4 100644 --- a/src/test/java/taa/ParserTest.java +++ b/src/test/java/taa/ParserTest.java @@ -15,62 +15,63 @@ class ParserTest { void getArgumentsFromString_noKeys_expectEmpty() throws TaaException { String inputString = "c/CS2113T_-() n/Software Engineering and Object-oriented Programming_-()"; String[] keys = {}; - assertTrue(Parser.getArgumentsFromString(inputString, keys).isEmpty()); + assertTrue(Parser.getArgumentsFromString(inputString, keys, false).isEmpty()); } @Test void getArgumentsFromString_oneKey_expectOneItem() throws TaaException { String inputString = "c/CS2113T_-() n/Software Engineering and Object-oriented Programming_-()"; String[] keys = {"n"}; - assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 1); + assertEquals(Parser.getArgumentsFromString(inputString, keys, false).size(), 1); } @Test void getArgumentsFromString_twoKeys_expectTwoItems() throws TaaException { String inputString = "c/CS2113T_-() n/Software Engineering and Object-oriented Programming_-()"; String[] keys = {"c","n"}; - assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 2); + assertEquals(Parser.getArgumentsFromString(inputString, keys, false).size(), 2); } @Test void getArgumentsFromString_threeKeys_expectThreeItems() throws TaaException { String inputString = "c/CS2113T_-() a/Midterms_-() w/20_-()"; String[] keys = {"c", "a", "w"}; - assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 3); + assertEquals(Parser.getArgumentsFromString(inputString, keys, false).size(), 3); } @Test void getArgumentsFromString_OneKeyAndEmptyValue_expectEmptyValue() throws TaaException { String inputString = "c/"; String[] keys = {"c"}; - assertEquals(Parser.getArgumentsFromString(inputString, keys).get("c"), ""); + assertEquals(Parser.getArgumentsFromString(inputString, keys, true).get("c"), ""); } @Test void getArgumentsFromString_TwoKeyAndOneEmptyValue_expectOneItem() throws TaaException { String inputString = "c/ n/Software Engineering and Object-oriented Programming"; String[] keys = {"c","n"}; - assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 2); + assertEquals(Parser.getArgumentsFromString(inputString, keys, false).size(), 1); } @Test void getArgumentsFromString_duplicatedKeys_expectDuplicatedArgumentException() { String inputString = "c/ n/Software Engineering and Object-oriented Programming c/Test"; String[] keys = {"c","n"}; - assertThrows(DuplicatedArgumentException.class, () -> Parser.getArgumentsFromString(inputString, keys)); + assertThrows(DuplicatedArgumentException.class, + () -> Parser.getArgumentsFromString(inputString, keys, true)); } @Test void getArgumentsFromString_illegalCharacters_expectTaaException() { String inputString = "c/hello&world n/Software Engineering and Object-oriented Programming"; String[] keys = {"c","n"}; - assertThrows(TaaException.class, () -> Parser.getArgumentsFromString(inputString, keys)); + assertThrows(TaaException.class, () -> Parser.getArgumentsFromString(inputString, keys, true)); } @Test void getArgumentsFromString_legalCharacters_expectTwoItems() throws TaaException { String inputString = "c/3654964apfaAFDao_()- n/65496494 649684aofaoAFAOFH9af_-(f0ew7r0FA_)f"; String[] keys = {"c","n"}; - assertEquals(Parser.getArgumentsFromString(inputString, keys).size(), 2); + assertEquals(Parser.getArgumentsFromString(inputString, keys, true).size(), 2); } } From 4226d81132d3b5be84bdb04cff4963cdb097b167 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 18:58:27 +0800 Subject: [PATCH 307/543] Add constructor for including empty values when parsing argument --- src/main/java/taa/command/Command.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index f783c30f51..bfd0af1212 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -67,16 +67,22 @@ public abstract class Command { protected boolean isExit; protected String[] argumentKeys; protected HashMap argumentMap; + protected boolean includeEmptyValues; public Command(String argument) { this(argument, null); } public Command(String argument, String[] argumentKeys) { + this(argument, argumentKeys, false); + } + + public Command(String argument, String[] argumentKeys, boolean includeEmptyValues) { this.argument = argument; this.isExit = false; this.argumentKeys = argumentKeys; this.argumentMap = null; + this.includeEmptyValues = includeEmptyValues; } protected abstract String getUsage(); @@ -86,7 +92,7 @@ public Command(String argument, String[] argumentKeys) { public abstract void execute(ClassList classList, Ui ui, Storage storage) throws TaaException; public void parseArgument() throws TaaException { - argumentMap = Parser.getArgumentsFromString(argument, argumentKeys); + argumentMap = Parser.getArgumentsFromString(argument, argumentKeys, includeEmptyValues); } public boolean isExit() { From 35c1464c6e179cdb3a5ef9d9223b4c7fe3642de9 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 18:59:33 +0800 Subject: [PATCH 308/543] Set id to lower case and add method to check if it is valid --- src/main/java/taa/teachingclass/TeachingClass.java | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/taa/teachingclass/TeachingClass.java b/src/main/java/taa/teachingclass/TeachingClass.java index 5f9febec3f..85c7cece7e 100644 --- a/src/main/java/taa/teachingclass/TeachingClass.java +++ b/src/main/java/taa/teachingclass/TeachingClass.java @@ -18,7 +18,7 @@ public class TeachingClass implements ClassChecker { private final AssessmentList assessmentList; public TeachingClass(String id, String name) { - this.id = id; + this.id = id.toLowerCase(); this.name = name; this.studentList = new StudentList(); this.assessmentList = new AssessmentList(); @@ -64,7 +64,7 @@ public String toString() { return id; } - return String.format("%s - %s", id, name); + return String.format("[%s] %s", id, name); } /** @@ -74,11 +74,11 @@ public String toString() { */ @Override public boolean verify() { - if (id.isEmpty()) { + if (!isValidId(id)) { return false; } - if (!Parser.isValueValid(id) || !Parser.isValueValid(id)) { + if (!Parser.isValueValid(id) || !Parser.isValueValid(name)) { return false; } @@ -112,4 +112,8 @@ public boolean verify() { return true; } + + public static boolean isValidId(String id) { + return !id.isEmpty() && !id.contains(" "); + } } From 09186f79589b8112edd47b32cd75b898b930995f Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 18:59:57 +0800 Subject: [PATCH 309/543] Ignore case when searching for TeachingClass --- src/main/java/taa/teachingclass/ClassList.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/teachingclass/ClassList.java b/src/main/java/taa/teachingclass/ClassList.java index eedc031915..fad2e44671 100644 --- a/src/main/java/taa/teachingclass/ClassList.java +++ b/src/main/java/taa/teachingclass/ClassList.java @@ -66,7 +66,7 @@ public TeachingClass getClassAt(int index) { */ public TeachingClass getClassWithId(String id) { for (TeachingClass teachingClass : classes) { - if (teachingClass.getId().equals(id)) { + if (teachingClass.getId().equalsIgnoreCase(id)) { return teachingClass; } } From b1ab0ac56808883c562062ef03e6129aa389c064 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 19:01:05 +0800 Subject: [PATCH 310/543] Refactor ClassObjectDeserializer to TeachingClassDeserializer --- .../java/taa/storage/deserializer/ClassListDeserializer.java | 2 +- .../taa/storage/deserializer/TeachingClassDeserializer.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/taa/storage/deserializer/ClassListDeserializer.java b/src/main/java/taa/storage/deserializer/ClassListDeserializer.java index 9f58f7752b..f328261695 100644 --- a/src/main/java/taa/storage/deserializer/ClassListDeserializer.java +++ b/src/main/java/taa/storage/deserializer/ClassListDeserializer.java @@ -32,7 +32,7 @@ public ClassList deserialize(JsonElement json, Type typeOfT, JsonDeserialization } GsonBuilder gsonBuilder = new GsonBuilder(); - gsonBuilder.registerTypeAdapter(TeachingClass.class, new ClassObjectDeserializer()); + gsonBuilder.registerTypeAdapter(TeachingClass.class, new TeachingClassDeserializer()); Gson gson = gsonBuilder.create(); ClassList classList = new ClassList(); diff --git a/src/main/java/taa/storage/deserializer/TeachingClassDeserializer.java b/src/main/java/taa/storage/deserializer/TeachingClassDeserializer.java index 717e48ceaa..a788e15ac3 100644 --- a/src/main/java/taa/storage/deserializer/TeachingClassDeserializer.java +++ b/src/main/java/taa/storage/deserializer/TeachingClassDeserializer.java @@ -16,7 +16,7 @@ import java.lang.reflect.Type; -public class ClassObjectDeserializer extends StorageDeserializer implements JsonDeserializer { +public class TeachingClassDeserializer extends StorageDeserializer implements JsonDeserializer { private static final String MEMBER_ID = "id"; private static final String MEMBER_NAME = "name"; private static final String MEMBER_STUDENTLIST = "studentList"; From f48fed63bb114d33d05bfc6ec041ea2eee177626 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 19:01:43 +0800 Subject: [PATCH 311/543] Check if CLASS_ID argument is valid --- .../java/taa/command/teachingclass/AddClassCommand.java | 7 ++++--- .../java/taa/command/teachingclass/EditClassCommand.java | 6 ++++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/main/java/taa/command/teachingclass/AddClassCommand.java b/src/main/java/taa/command/teachingclass/AddClassCommand.java index 90301171d9..2b1793a1e1 100644 --- a/src/main/java/taa/command/teachingclass/AddClassCommand.java +++ b/src/main/java/taa/command/teachingclass/AddClassCommand.java @@ -14,14 +14,15 @@ public class AddClassCommand extends Command { private static final String KEY_CLASS_NAME = "n"; private static final String[] ADD_CLASS_ARGUMENT_KEYS = {KEY_CLASS_ID, KEY_CLASS_NAME}; - private static final String MESSAGE_INVALID_CLASS_ID = "Invalid class ID. Class ID cannot contain spaces"; + private static final String MESSAGE_INVALID_CLASS_ID = "Invalid class ID. Class ID cannot be empty or " + + "contain spaces."; private static final String MESSAGE_CLASS_EXISTS = "Class already exists."; private static final String MESSAGE_FORMAT_ADD_CLASS_USAGE = "%s %s/ [%s/]"; private static final String MESSAGE_FORMAT_CLASS_ADDED = "Class added:\n %s\nThere are %d classes in the list."; public AddClassCommand(String argument) { - super(argument, ADD_CLASS_ARGUMENT_KEYS); + super(argument, ADD_CLASS_ARGUMENT_KEYS, true); } @Override @@ -35,7 +36,7 @@ public void checkArgument() throws TaaException { } String classId = argumentMap.get(KEY_CLASS_ID); - if (classId.contains(" ")) { + if (!TeachingClass.isValidId(classId)) { throw new TaaException(MESSAGE_INVALID_CLASS_ID); } } diff --git a/src/main/java/taa/command/teachingclass/EditClassCommand.java b/src/main/java/taa/command/teachingclass/EditClassCommand.java index 5d5d4e583a..d1ebdb99cd 100644 --- a/src/main/java/taa/command/teachingclass/EditClassCommand.java +++ b/src/main/java/taa/command/teachingclass/EditClassCommand.java @@ -58,8 +58,10 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep assert (argumentMap.containsKey(KEY_NEW_CLASS_ID) || argumentMap.containsKey(KEY_NEW_CLASS_NAME)); String newClassId = argumentMap.getOrDefault(KEY_NEW_CLASS_ID, null); if (newClassId != null) { - if (classList.getClassWithId(newClassId) != null) { - throw new TaaException(String.format(MESSAGE_FORMAT_CLASS_EXISTS, newClassId)); + TeachingClass existingTeachingClass = classList.getClassWithId(newClassId); + boolean isSameTeachingClass = teachingClass == existingTeachingClass; + if (existingTeachingClass != null && !isSameTeachingClass) { + throw new TaaException(String.format(MESSAGE_FORMAT_CLASS_EXISTS, existingTeachingClass.getId())); } teachingClass.setId(newClassId); From e29c19fdea6f7beeb354ea8841a3fb1d804b0dd3 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 19:08:50 +0800 Subject: [PATCH 312/543] Fix incorrect title --- docs/UserGuide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 2ad7ed17b2..612f539168 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -4,7 +4,7 @@ If you can type fast, TAA can help keep track of your classes and students faste * [Quick Start](#quick-start) * [Features](#features) - * [Listing all classes: `list_class`](#listing-all-classes-list_classes) + * [Listing all classes: `list_classes`](#listing-all-classes-list_classes) * [Adding a class: `add_class`](#adding-a-class-add_class) * [Editing a class: `edit_class`](#editing-a-class-edit_class) * [Deleting a class: `delete_class`](#deleting-a-class-delete_class) From 73a5956e8431dfae799de6f83d4547b22f794945 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 19:09:21 +0800 Subject: [PATCH 313/543] Change "module" to "class" --- docs/UserGuide.md | 88 ++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 612f539168..a95822c6de 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -23,13 +23,13 @@ If you can type fast, TAA can help keep track of your classes and students faste * [Deleting marks for a student's assessment: `delete_mark`](#deleting-marks-for-a-students-assessment-delete_mark) * [Viewing average marks for an assessment: `average_marks`](#viewing-average-marks-for-an-assessment-average_marks) * [Viewing median mark for an assessment: `median_mark`](#viewing-median-mark-for-an-assessment-median_mark) - * [Sorting and listing students in a module by their overall score: `sort_by_scores`](#sorting-and-listing-students-in-a-module-by-their-overall-score-sort_by_scores) + * [Sorting and listing students in a class by their overall score: `sort_by_scores`](#sorting-and-listing-students-in-a-class-by-their-overall-score-sort_by_scores) * [Listing attendance for a particular student: `list_attendance`](#listing-attendance-for-a-particular-student-list_attendance) * [Setting attendance for a particular lesson for a student: `set_attendance`](#setting-attendance-for-a-particular-lesson-for-a-student-set_attendance) * [Deleting attendance for a particular lesson for a student: `delete_attendance`](#deleting-attendance-for-a-particular-lesson-for-a-student-delete_attendance) * [Setting comment for a particular student: `set_comment`](#setting-comment-for-a-particular-student-set_comment) * [Deleting comment for a particular student: `delete_comment`](#deleting-comment-for-a-particular-student-delete_comment) - * [Listing comments for all students in a module `list_comment`](#listing-comments-for-all-students-in-a-module-list_comment) + * [Listing comments for all students in a class `list_comment`](#listing-comments-for-all-students-in-a-class-list_comment) * [Viewing help: `help`](#viewing-help-help) * [Exiting the program: `exit`](#exiting-the-program-exit) * [Archiving data: `archive`](#archiving-data-archive) @@ -59,7 +59,9 @@ Format: `list_classes` Adds a class to the class list. Format: `add_class c/ [n/]` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). + * Case-insensitive + * Cannot contain whitespaces * `CLASS_NAME` [Optional] refers to the name of the class to be added. Examples: @@ -73,8 +75,8 @@ Examples: Edits the code or name of an existing class. Format: `edit_class c/ [i/] [n/]` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** -* `NEW_CLASS_ID` [Optional] refers to the updated id of the class. **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). +* `NEW_CLASS_ID` [Optional] refers to the updated id of the class. * `NEW_CLASS_NAME` [Optional] refers to the updated name of the class. > 💡 **Note:**
> At least one optional field must be provided: @@ -92,7 +94,7 @@ Examples: Deletes an existing class from the class list. Format: `delete_class c/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). Examples: * `delete_class c/CS2113T-F12` @@ -104,7 +106,7 @@ Examples: Shows a list of all students in a particular class. Format: `list_students c/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). Examples: * `list_students c/CS2113T-F11` @@ -116,7 +118,7 @@ Examples: Adds a student to a particular class. Format: `add_student c/ i/ n/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). * `STUDENT_ID` refers to the ID of the student (e.g. A0217978J). * `STUDENT_NAME` refers to the name of the student (e.g. Jon Lim). @@ -130,7 +132,7 @@ Examples: Edits student information from a particular class Format: `edit_student c/ s/ i/ n/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). * `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `STUDENT_ID` refers to the updated ID of the student (e.g. A0217978J). * `STUDENT_NAME` refers to the updated name of the student (e.g. Jon Limbs). @@ -145,7 +147,7 @@ Examples: Deletes student information from a particular class. Format: `delete_student c/ s/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). * `STUDENT_INDEX` refers to the index of the student in the student list of the class. Examples: @@ -157,7 +159,7 @@ Examples: Displays all students in the class matching the keyword along with their index. Format: `find_student c/ k/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F11). * `KEYWORD` refers to the keyword used to search the student list of the class. Examples: @@ -170,7 +172,7 @@ Examples: List all assessments in a class. Format: `list_assessments c/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). Examples: * `list_assessments c/CS2113T-F12` @@ -182,7 +184,7 @@ Examples: Adds an assessment to a class. Format: `add_assessment c/ n/ m/ w/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). * `MAXIMUM_MARKS` refers to the maximum marks of the assessment (e.g. 100). * `WEIGHTAGE` refers to the weightage of the assessment (e.g. 10%). @@ -197,7 +199,7 @@ Examples: Edits an assessment of a class. Format: `edit_assessment c/ n/ [nn/] [m/] [w/]` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). * `NEW_ASSESSMENT_NAME` [Optional] refers to the new name of the assessment (e.g. Finals, Assignment 2, etc.). * `NEW_MAXIMUM_MARKS` [Optional] refers to the new maximum marks of the assessment (e.g. 50). @@ -218,7 +220,7 @@ Examples: Deletes an assessment of a class. Format: `delete_assessment c/ n/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `ASSESSMENT_NAME` refers to the name of the assessment (e.g. Midterm, Assignment 1, etc.). Examples: @@ -231,7 +233,7 @@ Examples: Lists all students and their marks for an assessment. Format: `list_marks c/ a/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `ASSESSMENT_NAME` refers to the name of the assessment whose marks are to be listed. Examples: @@ -244,7 +246,7 @@ Examples: Adds a student's marks for an assessment. Format: `set_mark c/ s/ a/ m/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `ASSESSMENT_NAME` refers to the name of the particular assessment. * `MARKS` refers to the marks given for the assessment. @@ -259,7 +261,7 @@ Examples: Edits a student's mark for an assessment. Format: `edit_mark c/ s/ a/ m/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `ASSESSMENT_NAME` refers to the name of the particular assessment. * `NEW_MARKS` refers to the new marks to be given for the assessment. @@ -274,7 +276,7 @@ Examples: Deletes a student's marks for an assessment. Format: `delete_mark c/ s/ a/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `STUDENT_INDEX` refers to the index of the student in student list of the class. * `ASSESSMENT_NAME` refers to the name of the particular assessment. @@ -289,7 +291,7 @@ Computes and prints the average marks for an assessment. If there are unmarked s within the marked students only. Format: `average_marks c/ a/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `ASSESSMENT_NAME` refers to the name of the particular assessment. Examples: @@ -303,7 +305,7 @@ Computes and prints the median mark for an assessment. If there are unmarked stu within the marked students only. Format: `median_mark c/ a/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `ASSESSMENT_NAME` refers to the name of the particular assessment. Examples: @@ -312,12 +314,12 @@ Examples:
-### Sorting and listing students in a module by their overall score: `sort_by_scores` -Sorts and lists students in a module by their overall score according to the desired format. +### Sorting and listing students in a class by their overall score: `sort_by_scores` +Sorts and lists students in a class by their overall score according to the desired format. Only marks currently added to students will be taken into consideration for their scores. Format: `sort_by_scores c/ o/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `ORDER` refers to the sorting order. `asc` for ascending and `desc` for descending. Examples: @@ -330,7 +332,7 @@ Examples: Lists a student's attendance. Format: `list_attendance c/ s/ @@ -339,7 +341,7 @@ Format: `list_attendance c/ s/ s/ l/ p/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `LESSON_NUMBER` refers to the lesson number. * `PRESENT` refers to the whether a student is present. (`1` for present, `0` for not present) @@ -350,18 +352,30 @@ Format: `set_attendance c/ s/ l/ p/ s/ l/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `LESSON_NUMBER` refers to the lesson number.
+### Listing comments for all students in a class: `list_comment` +List comments for all students in a class + +Format: `list_comment c/` +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). + +Examples: +* `list_comment c/CS2113T-F12` +* `list_comment c/CS2101-D03` + +
+ ### Setting comment for a particular student: `set_comment` Sets a comment for a student. Format: `set_comment c/ s/ t/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** -* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). +* `STUDENT_INDEX` refers to the index of the student in the student list of the class. * `COMMENT` refers to the comment to be set. > 💡 **Note:**
> The new comment will overwrite any previous comment set @@ -376,8 +390,8 @@ Examples: Deletes the comment for a student. Format: `delete_comment c/ s/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** -* `STUDENT_INDEX` refers to the index of the student in the student list of the module. +* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). +* `STUDENT_INDEX` refers to the index of the student in the student list of the class. Examples: * `delete_comment c/CS2113T-F12 s/1` @@ -385,18 +399,6 @@ Examples:
-### Listing comments for all students in a module: `list_comment` -List comments for all students in a module - -Format: `list_comment c/` -* `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). **Cannot contain whitespaces.** - -Examples: -* `list_comment c/CS2113T-F12` -* `list_comment c/CS2101-D03` - -
- ### Viewing help: `help` Displays the list of available commands and how to use them. From bd6cecf6bc2eee695bb469bcddf8d892ba816b9e Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 19:21:31 +0800 Subject: [PATCH 314/543] Update EXPECTED.txt --- text-ui-test/EXPECTED.TXT | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text-ui-test/EXPECTED.TXT b/text-ui-test/EXPECTED.TXT index 308ece4245..9cc7b53928 100644 --- a/text-ui-test/EXPECTED.TXT +++ b/text-ui-test/EXPECTED.TXT @@ -16,12 +16,12 @@ There are no classes in the list. ------------------------------------------------------------ $ ------------------------------------------------------------ Class added: - CS2113T-F12 - Tutorial Group F12 + [cs2113t-f12] Tutorial Group F12 There are 1 classes in the list. ------------------------------------------------------------ $ ------------------------------------------------------------ Class list: -1. CS2113T-F12 - Tutorial Group F12 +1. [cs2113t-f12] Tutorial Group F12 ------------------------------------------------------------ $ ------------------------------------------------------------ An exception has occurred: From 756510d99b5d6685f636948fa387190fb9a45210 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 2 Nov 2021 20:31:43 +0800 Subject: [PATCH 315/543] Change output format of HelpCommand for readability --- src/main/java/taa/command/HelpCommand.java | 149 ++++++++++++++------- 1 file changed, 103 insertions(+), 46 deletions(-) diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index e69f5f0bce..7ce984c002 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -31,44 +31,92 @@ import taa.exception.TaaException; import taa.storage.Storage; +import java.util.ArrayList; +import java.util.LinkedHashMap; + public class HelpCommand extends Command { - private static final String MESSAGE_FORMAT_OUTPUT = "Available commands:\n%s"; - - private static final Command[] commands = { - new ListClassesCommand(""), - new AddClassCommand(""), - new EditClassCommand(""), - new DeleteClassCommand(""), - new ListStudentsCommand(""), - new AddStudentCommand(""), - new EditStudentCommand(""), - new DeleteStudentCommand(""), - new FindStudentCommand(""), - new ListCommentCommand(""), - new SetCommentCommand(""), - new DeleteStudentCommand(""), - new SortByScoresCommand(""), - new ListAssessmentsCommand(""), - new AddAssessmentCommand(""), - new EditAssessmentCommand(""), - new DeleteAssessmentCommand(""), - new ListMarksCommand(""), - new SetMarkCommand(""), - new EditMarkCommand(""), - new DeleteMarkCommand(""), - new AverageMarksCommand(""), - new MedianMarkCommand(""), - new ListAttendanceCommand(""), - new SetAttendanceCommand(""), - new DeleteAttendanceCommand(""), - new ExitCommand(""), - new HelpCommand(""), - new ArchiveCommand(""), - new ResetCommand("") - }; + private static final String STRING_CLASS = "Class"; + private static final String STRING_STUDENT = "Student"; + private static final String STRING_ASSESSMENT = "Assessment"; + private static final String STRING_MARK = "Mark"; + private static final String STRING_ATTENDANCE = "Attendance"; + private static final String STRING_OTHERS = "Others"; + + private static final String MESSAGE_OUTPUT_HEADER = "Available commands:"; + + private static final LinkedHashMap> commandUsages = new LinkedHashMap<>(); public HelpCommand(String argument) { super(argument); + initCommandUsages(); + } + + private static void initCommandUsages() { + if (!commandUsages.isEmpty()) { + return; + } + + Command[] classCommands = { + new ListClassesCommand(""), + new AddClassCommand(""), + new EditClassCommand(""), + new DeleteClassCommand(""), + }; + commandUsages.put(STRING_CLASS, getUsagesFromCommands(classCommands)); + + Command[] studentCommands = { + new ListStudentsCommand(""), + new AddStudentCommand(""), + new EditStudentCommand(""), + new DeleteStudentCommand(""), + new FindStudentCommand(""), + new ListCommentCommand(""), + new SetCommentCommand(""), + new SortByScoresCommand(""), + }; + commandUsages.put(STRING_STUDENT, getUsagesFromCommands(studentCommands)); + + Command[] assessmentCommands = { + new ListAssessmentsCommand(""), + new AddAssessmentCommand(""), + new EditAssessmentCommand(""), + new DeleteAssessmentCommand("") + }; + commandUsages.put(STRING_ASSESSMENT, getUsagesFromCommands(assessmentCommands)); + + Command[] markCommands = { + new ListMarksCommand(""), + new SetMarkCommand(""), + new EditMarkCommand(""), + new DeleteMarkCommand(""), + new AverageMarksCommand(""), + new MedianMarkCommand(""), + }; + commandUsages.put(STRING_MARK, getUsagesFromCommands(markCommands)); + + Command[] attendanceCommands = { + new ListAttendanceCommand(""), + new SetAttendanceCommand(""), + new DeleteAttendanceCommand("") + }; + commandUsages.put(STRING_ATTENDANCE, getUsagesFromCommands(attendanceCommands)); + + Command[] othersCommands = { + new ExitCommand(""), + new HelpCommand(""), + new ArchiveCommand(""), + new ResetCommand("") + }; + commandUsages.put(STRING_OTHERS, getUsagesFromCommands(othersCommands)); + } + + private static ArrayList getUsagesFromCommands(Command[] commands) { + ArrayList usages = new ArrayList<>(); + for (Command command : commands) { + usages.add(command.getUsage()); + } + + return usages; } @Override @@ -78,22 +126,31 @@ public void checkArgument() throws TaaException { } } - @Override - public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { - StringBuilder stringBuilder = new StringBuilder(); - for (int i = 0; i < commands.length; i += 1) { - Command command = commands[i]; + private String getStringForCommandGroup(String name) { + if (!commandUsages.containsKey(name)) { + return ""; + } + + StringBuilder stringBuilder = new StringBuilder(name); + stringBuilder.append(":"); + for (String string : commandUsages.get(name)) { + stringBuilder.append("\n"); + stringBuilder.append(" - "); + stringBuilder.append(string); + } - if (i > 0) { - stringBuilder.append("\n"); - } + return stringBuilder.toString(); + } - stringBuilder.append("- "); - stringBuilder.append(command.getUsage()); + @Override + public void execute(ClassList classList, Ui ui, Storage storage) throws TaaException { + StringBuilder stringBuilder = new StringBuilder(MESSAGE_OUTPUT_HEADER); + for (String name : commandUsages.keySet()) { + stringBuilder.append("\n\n"); + stringBuilder.append(getStringForCommandGroup(name)); } - String message = String.format(MESSAGE_FORMAT_OUTPUT, stringBuilder.toString()); - ui.printMessage(message); + ui.printMessage(stringBuilder.toString()); } @Override From 6b5ac8f9e59680d30064c9562a2d9005a6d04fc4 Mon Sep 17 00:00:00 2001 From: rachel Date: Tue, 2 Nov 2021 21:42:08 +0800 Subject: [PATCH 316/543] Fix misleading error messages associated with invalid assessment name and weightage in add_assessment command --- .../java/taa/assessment/AssessmentList.java | 17 ++------------ .../assessment/AddAssessmentCommand.java | 22 ++++++++++++++++++- 2 files changed, 23 insertions(+), 16 deletions(-) diff --git a/src/main/java/taa/assessment/AssessmentList.java b/src/main/java/taa/assessment/AssessmentList.java index 8f081fe359..653d12a6b8 100644 --- a/src/main/java/taa/assessment/AssessmentList.java +++ b/src/main/java/taa/assessment/AssessmentList.java @@ -33,21 +33,8 @@ public ArrayList getAssessments() { * @return true if success, else false. */ public boolean addAssessment(Assessment assessment) { - double totalWeightage = 0; - for (Assessment a : assessments) { - if (a.getName().equalsIgnoreCase(assessment.getName())) { - return false; - } - - totalWeightage += a.getWeightage(); - } - - double newTotalWeightage = totalWeightage + assessment.getWeightage(); - boolean isWeightageValid = Assessment.isWeightageWithinRange(newTotalWeightage); - boolean isMaximumMarksValid = assessment.getMaximumMarks() >= Assessment.MINIMUM_MARKS; - if (!isWeightageValid || !isMaximumMarksValid) { - return false; - } + assert assessment.getMaximumMarks() >= Assessment.MINIMUM_MARKS; + assert Assessment.isWeightageWithinRange(assessment.getWeightage()); assessments.add(assessment); return true; diff --git a/src/main/java/taa/command/assessment/AddAssessmentCommand.java b/src/main/java/taa/command/assessment/AddAssessmentCommand.java index aefe2d054e..c874af53c9 100644 --- a/src/main/java/taa/command/assessment/AddAssessmentCommand.java +++ b/src/main/java/taa/command/assessment/AddAssessmentCommand.java @@ -10,6 +10,8 @@ import taa.exception.TaaException; import taa.util.Util; +import java.util.ArrayList; + public class AddAssessmentCommand extends Command { private static final String KEY_CLASS_ID = "c"; private static final String KEY_ASSESSMENT_NAME = "n"; @@ -26,8 +28,12 @@ public class AddAssessmentCommand extends Command { private static final String MESSAGE_FORMAT_ADD_ASSESSMENT_USAGE = "%s %s/ %s/ " + "%s/ %s/"; + private static final String MESSAGE_FORMAT_INVALID_NAME = "Invalid assessment name. " + + "Assessment already exists."; private static final String MESSAGE_FORMAT_INVALID_WEIGHTAGE = "Invalid weightage. " + "Weightage must be between %,.2f and %,.2f (inclusive)"; + private static final String MESSAGE_FORMAT_INVALID_TOTAL_WEIGHTAGE = "Invalid new weightage. " + + "Total new weightage exceeds 100%."; private static final String MESSAGE_FORMAT_INVALID_MAXIMUM_MARKS = "Invalid maximum marks. " + "Maximum marks must be larger than %d (inclusive)"; private static final String MESSAGE_FORMAT_ASSESSMENT_ADDED = "Assessment added to %s:\n" @@ -103,12 +109,26 @@ public void execute(ClassList classList, Ui ui, Storage storage) throws TaaExcep int maximumMarks = Integer.parseInt(maximumMarksString); assert maximumMarks >= Assessment.MINIMUM_MARKS; + String name = argumentMap.get(KEY_ASSESSMENT_NAME); + String weightageString = argumentMap.get(KEY_WEIGHTAGE); assert Util.isStringDouble(weightageString); double weightage = Double.parseDouble(weightageString); assert Assessment.isWeightageWithinRange(weightage); + ArrayList assessments = teachingClass.getAssessmentList().getAssessments(); + double totalWeightage = 0; + for (Assessment a : assessments) { + if (a.getName().equalsIgnoreCase(name)) { + throw new TaaException(MESSAGE_FORMAT_INVALID_NAME); + } + + totalWeightage += a.getWeightage(); + } + double newTotalWeightage = totalWeightage + weightage; + if (!Assessment.isWeightageWithinRange(newTotalWeightage)) { + throw new TaaException(MESSAGE_FORMAT_INVALID_TOTAL_WEIGHTAGE); + } - String name = argumentMap.get(KEY_ASSESSMENT_NAME); Assessment assessment = new Assessment(name, maximumMarks, weightage); AssessmentList assessmentList = teachingClass.getAssessmentList(); From 5bbf2f09e5e3d6c3c76252e8bee2a8693a2fbb4b Mon Sep 17 00:00:00 2001 From: rachel Date: Tue, 2 Nov 2021 21:47:06 +0800 Subject: [PATCH 317/543] Fix lower end of the weightage range so that weightage of 0 is no longer allowed --- src/main/java/taa/assessment/Assessment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/assessment/Assessment.java b/src/main/java/taa/assessment/Assessment.java index ce5521721b..adc02dc991 100644 --- a/src/main/java/taa/assessment/Assessment.java +++ b/src/main/java/taa/assessment/Assessment.java @@ -24,7 +24,7 @@ public Assessment(String name, int maximumMarks, double weightage) { * @return true if valid, else false. */ public static boolean isWeightageWithinRange(double weightage) { - return (weightage >= WEIGHTAGE_RANGE[0] && weightage <= WEIGHTAGE_RANGE[1]); + return (weightage > WEIGHTAGE_RANGE[0] && weightage <= WEIGHTAGE_RANGE[1]); } public String getName() { From bfc217e53f47df1cd22a133e60706559e33bf08f Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Wed, 3 Nov 2021 01:50:55 +0800 Subject: [PATCH 318/543] edit add_class format and increase readability of user guide --- docs/UserGuide.md | 136 ++++++++++++++++++++++++++-------------------- 1 file changed, 76 insertions(+), 60 deletions(-) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index a7393318de..d03760fd17 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -4,36 +4,43 @@ If you can type fast, TAA can help keep track of your classes and students faste * [Quick Start](#quick-start) * [Features](#features) - * [Listing all classes: `list_classes`](#listing-all-classes-list_classes) - * [Adding a class: `add_class`](#adding-a-class-add_class) - * [Editing a class: `edit_class`](#editing-a-class-edit_class) - * [Deleting a class: `delete_class`](#deleting-a-class-delete_class) - * [Listing all students in a class: `list_students`](#listing-all-students-in-a-class-list_students) - * [Adding a student to a class: `add_student`](#adding-a-student-to-a-class-add_student) - * [Editing a student's information in a class: `edit_student`](#editing-a-students-information-in-a-class-edit_student) - * [Deleting a student from a class: `delete_student`](#deleting-a-student-from-a-class-delete_student) - * [Finding students in a class given a keyword: `find_student`](#finding-students-in-a-class-given-a-keyword-find_student) - * [Listing all assessments in a class: `list_assessments`](#listing-all-assessments-in-a-class-list_assessments) - * [Adding an assessment to a class: `add_assessment`](#adding-an-assessment-to-a-class-add_assessment) - * [Editing an assessment in a class: `edit_assessment`](#editing-an-assessment-in-a-class-edit_assessment) - * [Deleting an assessment from a class: `delete_assessment`](#deleting-an-assessment-from-a-class-delete_assessment) - * [Listing marks for an assessment: `list_marks`](#listing-marks-for-an-assessment-list_marks) - * [Setting mark for a student's assessment: `set_mark`](#setting-mark-for-a-students-assessment-set_mark) - * [Editing marks for a student's assessment: `edit_mark`](#editing-marks-for-a-students-assessment-edit_mark) - * [Deleting marks for a student's assessment: `delete_mark`](#deleting-marks-for-a-students-assessment-delete_mark) - * [Viewing average marks for an assessment: `average_marks`](#viewing-average-marks-for-an-assessment-average_marks) - * [Viewing median mark for an assessment: `median_mark`](#viewing-median-mark-for-an-assessment-median_mark) - * [Sorting and listing students in a class by their overall score: `sort_by_scores`](#sorting-and-listing-students-in-a-class-by-their-overall-score-sort_by_scores) - * [Listing attendance for a particular student: `list_attendance`](#listing-attendance-for-a-particular-student-list_attendance) - * [Setting attendance for a particular lesson for a student: `set_attendance`](#setting-attendance-for-a-particular-lesson-for-a-student-set_attendance) - * [Deleting attendance for a particular lesson for a student: `delete_attendance`](#deleting-attendance-for-a-particular-lesson-for-a-student-delete_attendance) - * [Setting comment for a particular student: `set_comment`](#setting-comment-for-a-particular-student-set_comment) - * [Deleting comment for a particular student: `delete_comment`](#deleting-comment-for-a-particular-student-delete_comment) - * [Listing comments for all students in a class `list_comment`](#listing-comments-for-all-students-in-a-class-list_comment) - * [Viewing help: `help`](#viewing-help-help) - * [Exiting the program: `exit`](#exiting-the-program-exit) - * [Archiving data: `archive`](#archiving-data-archive) - * [Resetting/Removing all data: `reset`](#resettingremoving-all-data-reset) + * [Classes](#classes) + * [Listing all classes: `list_classes`](#listing-all-classes-list_classes) + * [Adding a class: `add_class`](#adding-a-class-add_class) + * [Editing a class: `edit_class`](#editing-a-class-edit_class) + * [Deleting a class: `delete_class`](#deleting-a-class-delete_class) + * [Students](#students) + * [Listing all students in a class: `list_students`](#listing-all-students-in-a-class-list_students) + * [Adding a student to a class: `add_student`](#adding-a-student-to-a-class-add_student) + * [Editing a student's information in a class: `edit_student`](#editing-a-students-information-in-a-class-edit_student) + * [Deleting a student from a class: `delete_student`](#deleting-a-student-from-a-class-delete_student) + * [Finding students in a class given a keyword: `find_student`](#finding-students-in-a-class-given-a-keyword-find_student) + * [Assessments](#assessments) + * [Listing all assessments in a class: `list_assessments`](#listing-all-assessments-in-a-class-list_assessments) + * [Adding an assessment to a class: `add_assessment`](#adding-an-assessment-to-a-class-add_assessment) + * [Editing an assessment in a class: `edit_assessment`](#editing-an-assessment-in-a-class-edit_assessment) + * [Deleting an assessment from a class: `delete_assessment`](#deleting-an-assessment-from-a-class-delete_assessment) + * [Marks](#marks) + * [Listing marks for an assessment: `list_marks`](#listing-marks-for-an-assessment-list_marks) + * [Setting mark for a student's assessment: `set_mark`](#setting-mark-for-a-students-assessment-set_mark) + * [Editing marks for a student's assessment: `edit_mark`](#editing-marks-for-a-students-assessment-edit_mark) + * [Deleting marks for a student's assessment: `delete_mark`](#deleting-marks-for-a-students-assessment-delete_mark) + * [Viewing average marks for an assessment: `average_marks`](#viewing-average-marks-for-an-assessment-average_marks) + * [Viewing median mark for an assessment: `median_mark`](#viewing-median-mark-for-an-assessment-median_mark) + * [Sorting and listing students in a class by their overall score: `sort_by_scores`](#sorting-and-listing-students-in-a-class-by-their-overall-score-sort_by_scores) + * [Attendance](#attendance) + * [Listing attendance for a particular student: `list_attendance`](#listing-attendance-for-a-particular-student-list_attendance) + * [Setting attendance for a particular lesson for a student: `set_attendance`](#setting-attendance-for-a-particular-lesson-for-a-student-set_attendance) + * [Deleting attendance for a particular lesson for a student: `delete_attendance`](#deleting-attendance-for-a-particular-lesson-for-a-student-delete_attendance) + * [Comments](#comments) + * [Setting comment for a particular student: `set_comment`](#setting-comment-for-a-particular-student-set_comment) + * [Deleting comment for a particular student: `delete_comment`](#deleting-comment-for-a-particular-student-delete_comment) + * [Listing comments for all students in a class `list_comment`](#listing-comments-for-all-students-in-a-class-list_comment) + * [Useful Features](#useful-features) + * [Viewing help: `help`](#viewing-help-help) + * [Exiting the program: `exit`](#exiting-the-program-exit) + * [Archiving data: `archive`](#archiving-data-archive) + * [Resetting/Removing all data: `reset`](#resettingremoving-all-data-reset) * [FAQ](#faq) * [Command Summary](#command-summary) @@ -47,6 +54,7 @@ If you can type fast, TAA can help keep track of your classes and students faste 6. Enter `help` to display the list of available commands. See [Features](#features) for more information. ## Features +## Classes ### Listing all classes: `list_classes` Displays the list of all classes in the class list. @@ -58,16 +66,16 @@ Format: `list_classes` ### Adding a class: `add_class` Adds a class to the class list. -Format: `add_class c/ [n/]` +Format: `add_class i/ [n/]` * `CLASS_ID` refers to the id of the class (e.g. CS2113T-F12). * Case-insensitive * Cannot contain whitespaces * `CLASS_NAME` [Optional] refers to the name of the class to be added. Examples: -* `add_class c/CS2113T-F12 n/Tutorial Group F12` -* `add_class n/Sectional Group C03 c/CS2101-C03` -* `add_class c/CS2102` +* `add_class i/CS2113T-F12 n/Tutorial Group F12` +* `add_class n/Sectional Group C03 i/CS2101-C03` +* `add_class i/CS2102`
@@ -102,6 +110,7 @@ Examples:
+##Students ### Listing all students in a class: `list_students` Shows a list of all students in a particular class. @@ -168,6 +177,7 @@ Examples:
+## Assessments ### Listing all assessments in a class: `list_assessments` List all assessments in a class. @@ -229,6 +239,7 @@ Examples:
+## Marks ### Listing marks for an assessment: `list_marks` Lists all students and their marks for an assessment. @@ -348,6 +359,7 @@ Examples:
+## Attendance ### Listing attendance for a particular student: `list_attendance` Lists a student's attendance. @@ -378,6 +390,7 @@ Format: `delete_attendance c/ s/ l/`
+## Comments ### Listing comments for all students in a class: `list_comment` List comments for all students in a class @@ -419,6 +432,7 @@ Examples:
+## Useful Features ### Viewing help: `help` Displays the list of available commands and how to use them. @@ -456,29 +470,31 @@ Format: `reset` ## Command Summary -Action | Format | - ------ | --------------- | -Listing all **classes** | `list_classes` -Adding a **class** | `add_class c/ [n/]` -Editing a **class** | `edit_class c/ [nc/] [n/]` -Deleting a **class** | `delete_class c/` -Listing all **students** in a class | `list_students c/` -Adding a **student** to a class | `add_student c/ i/ n/` -Editing a **student's** information in a class | `edit_student c/ s/ i/ n/` -Deleting a **student** from a class | `delete_student c/ s/` -Finding **students** in a class given a keyword | `find_student c/ k/` -Listing all **assessments** in a class | `list_assessments c/` -Adding an **assessment** to a class | `add_assessment c/ n/ m/ w/` -Editing an **assessment** in a class | `edit_assessment c/ n/ [nn/] [m/]` -Deleting an **assessment** from a class | `delete_assessment c/ n/` -Listing **marks** for an assessment: | `list_marks c/ a/` -Setting **marks** for a student's assessment | `set_mark c/ s/ a/ m/` -Editing **marks** for a student's assessment | `edit_mark c/ s/ a/ m/` -Deleting **marks** for a student's assessment | `delete_mark c/ s/ a/` -Viewing average **marks** for an assessment | `average_marks c/ a/` -Viewing the median **mark** for an assessment | `median_mark c/ a/` -Listing **attendance** for a particular student | `list_attendance c/ s/` -Setting **attendance** for a particular lesson for a student | `set_attendance c/ s/ l/ p/` -Deleting **attendance** for a particular lesson for a student | `delete_attendance c/ s/ l/` -Viewing help | `help` -Exiting the program | `exit` +Category | Action | Format | + ----- | ------ | --------------- | +Class | Listing all **classes** | `list_classes` +Class | Adding a **class** | `add_class i/ [n/]` +Class | Editing a **class** | `edit_class c/ [nc/] [n/]` +Class | Deleting a **class** | `delete_class c/` +Student | Listing all **students** in a class | `list_students c/` +Student | Adding a **student** to a class | `add_student c/ i/ n/` +Student | Editing a **student's** information in a class | `edit_student c/ s/ i/ n/` +Student | Deleting a **student** from a class | `delete_student c/ s/` +Student | Finding **students** in a class given a keyword | `find_student c/ k/` +Assessment | Listing all **assessments** in a class | `list_assessments c/` +Assessment | Adding an **assessment** to a class | `add_assessment c/ n/ m/ w/` +Assessment | Editing an **assessment** in a class | `edit_assessment c/ n/ [nn/] [m/]` +Assessment | Deleting an **assessment** from a class | `delete_assessment c/ n/` +Marks | Listing **marks** for an assessment: | `list_marks c/ a/` +Marks | Setting **mark** for a student's assessment | `set_mark c/ s/ a/ m/` +Marks | Editing **mark** for a student's assessment | `edit_mark c/ s/ a/ m/` +Marks | Deleting **mark** for a student's assessment | `delete_mark c/ s/ a/` +Marks | Viewing average **marks** for an assessment | `average_marks c/ a/` +Marks | Viewing the median **mark** for an assessment | `median_mark c/ a/` +Attendance | Listing **attendance** for a particular student | `list_attendance c/ s/` +Attendance | Setting **attendance** for a particular lesson for a student | `set_attendance c/ s/ l/ p/` +Attendance | Deleting **attendance** for a particular lesson for a student | `delete_attendance c/ s/ l/` +Useful Features | Viewing help | `help` +Useful Features | Exiting the program | `exit` +Useful Features | Archiving data | `archive` +Useful Features | Resetting/Removing all data | `reset` \ No newline at end of file From ca1e2c90d5a355d331eb92f441f7ee73f192f05e Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Wed, 3 Nov 2021 01:56:17 +0800 Subject: [PATCH 319/543] repackage images --- docs/UserGuide.md | 12 ++++++------ .../{ => Marks_Images}/average_marks_all_marked.png | Bin .../average_marks_with_unmarked.png | Bin docs/images/{ => Marks_Images}/delete_mark.png | Bin docs/images/{ => Marks_Images}/edit_mark.png | Bin docs/images/{ => Marks_Images}/list_marks.png | Bin docs/images/{ => Marks_Images}/set_mark.png | Bin 7 files changed, 6 insertions(+), 6 deletions(-) rename docs/images/{ => Marks_Images}/average_marks_all_marked.png (100%) rename docs/images/{ => Marks_Images}/average_marks_with_unmarked.png (100%) rename docs/images/{ => Marks_Images}/delete_mark.png (100%) rename docs/images/{ => Marks_Images}/edit_mark.png (100%) rename docs/images/{ => Marks_Images}/list_marks.png (100%) rename docs/images/{ => Marks_Images}/set_mark.png (100%) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index d03760fd17..7670d4633c 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -252,7 +252,7 @@ Examples: * `list_marks c/CS2101-C03 a/Oral Presentation` Expected Output:
-![img.png](images/list_marks.png) +![img.png](images/Marks_Images/list_marks.png)
### Setting mark for a student's assessment: `set_mark` @@ -269,7 +269,7 @@ Examples: * `set_mark c/CS2101 s/3 a/Oral Presentation m/80` Expected Output:
-![set_mark.png](images/set_mark.png) +![set_mark.png](images/Marks_Images/set_mark.png)
### Editing marks for a student's assessment: `edit_mark` @@ -286,7 +286,7 @@ Examples: * `edit_mark c/CS2101-C03 s/3 a/Oral Presentation m/90` Expected Output:
-![edit_mark.png](images/edit_mark.png) +![edit_mark.png](images/Marks_Images/edit_mark.png)
### Deleting marks for a student's assessment: `delete_mark` @@ -302,7 +302,7 @@ Examples: * `delete_mark c/CS2101 s/3 a/Oral Presentation` Expected Output:
-![delete_mark.png](images/delete_mark.png) +![delete_mark.png](images/Marks_Images/delete_mark.png)
### Viewing average marks for an assessment: `average_marks` @@ -319,10 +319,10 @@ Examples: Expected Output:
(Some students unmarked)
-![average_marks_with_unmarked.png](images/average_marks_with_unmarked.png) +![average_marks_with_unmarked.png](images/Marks_Images/average_marks_with_unmarked.png)
(All students marked)
-![average_marks_all_marked.png](images/average_marks_all_marked.png) +![average_marks_all_marked.png](images/Marks_Images/average_marks_all_marked.png)
### Viewing median mark for an assessment: `median_mark` diff --git a/docs/images/average_marks_all_marked.png b/docs/images/Marks_Images/average_marks_all_marked.png similarity index 100% rename from docs/images/average_marks_all_marked.png rename to docs/images/Marks_Images/average_marks_all_marked.png diff --git a/docs/images/average_marks_with_unmarked.png b/docs/images/Marks_Images/average_marks_with_unmarked.png similarity index 100% rename from docs/images/average_marks_with_unmarked.png rename to docs/images/Marks_Images/average_marks_with_unmarked.png diff --git a/docs/images/delete_mark.png b/docs/images/Marks_Images/delete_mark.png similarity index 100% rename from docs/images/delete_mark.png rename to docs/images/Marks_Images/delete_mark.png diff --git a/docs/images/edit_mark.png b/docs/images/Marks_Images/edit_mark.png similarity index 100% rename from docs/images/edit_mark.png rename to docs/images/Marks_Images/edit_mark.png diff --git a/docs/images/list_marks.png b/docs/images/Marks_Images/list_marks.png similarity index 100% rename from docs/images/list_marks.png rename to docs/images/Marks_Images/list_marks.png diff --git a/docs/images/set_mark.png b/docs/images/Marks_Images/set_mark.png similarity index 100% rename from docs/images/set_mark.png rename to docs/images/Marks_Images/set_mark.png From 7ff623bd2d2eaa87b3d70f290ec2860ffa7ea6a6 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 3 Nov 2021 18:42:13 +0800 Subject: [PATCH 320/543] Move comment commands into comment package --- src/main/java/taa/Parser.java | 6 +++--- src/main/java/taa/command/HelpCommand.java | 4 ++-- .../command/{student => comment}/DeleteCommentCommand.java | 2 +- .../command/{student => comment}/ListCommentCommand.java | 2 +- .../taa/command/{student => comment}/SetCommentCommand.java | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) rename src/main/java/taa/command/{student => comment}/DeleteCommentCommand.java (99%) rename src/main/java/taa/command/{student => comment}/ListCommentCommand.java (98%) rename src/main/java/taa/command/{student => comment}/SetCommentCommand.java (99%) diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 4eee8ac8c4..c038f17f7c 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -30,9 +30,9 @@ import taa.command.attendance.SetAttendanceCommand; import taa.command.mark.SetMarkCommand; import taa.command.student.SortByScoresCommand; -import taa.command.student.SetCommentCommand; -import taa.command.student.DeleteCommentCommand; -import taa.command.student.ListCommentCommand; +import taa.command.comment.SetCommentCommand; +import taa.command.comment.DeleteCommentCommand; +import taa.command.comment.ListCommentCommand; import taa.exception.DuplicatedArgumentException; import taa.exception.TaaException; diff --git a/src/main/java/taa/command/HelpCommand.java b/src/main/java/taa/command/HelpCommand.java index 7ce984c002..21f01429cc 100644 --- a/src/main/java/taa/command/HelpCommand.java +++ b/src/main/java/taa/command/HelpCommand.java @@ -24,9 +24,9 @@ import taa.command.student.DeleteStudentCommand; import taa.command.student.EditStudentCommand; import taa.command.student.FindStudentCommand; -import taa.command.student.ListCommentCommand; +import taa.command.comment.ListCommentCommand; import taa.command.student.ListStudentsCommand; -import taa.command.student.SetCommentCommand; +import taa.command.comment.SetCommentCommand; import taa.command.student.SortByScoresCommand; import taa.exception.TaaException; import taa.storage.Storage; diff --git a/src/main/java/taa/command/student/DeleteCommentCommand.java b/src/main/java/taa/command/comment/DeleteCommentCommand.java similarity index 99% rename from src/main/java/taa/command/student/DeleteCommentCommand.java rename to src/main/java/taa/command/comment/DeleteCommentCommand.java index c7635d9fbc..b7d2bc581b 100644 --- a/src/main/java/taa/command/student/DeleteCommentCommand.java +++ b/src/main/java/taa/command/comment/DeleteCommentCommand.java @@ -1,4 +1,4 @@ -package taa.command.student; +package taa.command.comment; //@@author hozhenhong99 import taa.teachingclass.TeachingClass; diff --git a/src/main/java/taa/command/student/ListCommentCommand.java b/src/main/java/taa/command/comment/ListCommentCommand.java similarity index 98% rename from src/main/java/taa/command/student/ListCommentCommand.java rename to src/main/java/taa/command/comment/ListCommentCommand.java index 4169c31360..2b268713d3 100644 --- a/src/main/java/taa/command/student/ListCommentCommand.java +++ b/src/main/java/taa/command/comment/ListCommentCommand.java @@ -1,4 +1,4 @@ -package taa.command.student; +package taa.command.comment; //@@author hozhenhong99 import taa.Ui; diff --git a/src/main/java/taa/command/student/SetCommentCommand.java b/src/main/java/taa/command/comment/SetCommentCommand.java similarity index 99% rename from src/main/java/taa/command/student/SetCommentCommand.java rename to src/main/java/taa/command/comment/SetCommentCommand.java index 9258963765..c384f3fa63 100644 --- a/src/main/java/taa/command/student/SetCommentCommand.java +++ b/src/main/java/taa/command/comment/SetCommentCommand.java @@ -1,4 +1,4 @@ -package taa.command.student; +package taa.command.comment; //@@author hozhenhong99 import taa.teachingclass.TeachingClass; From 53bc71921404db01496b51c055eda9c83570ffdb Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 3 Nov 2021 18:42:45 +0800 Subject: [PATCH 321/543] Set id as lowercase in TeachingClass --- src/main/java/taa/teachingclass/TeachingClass.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/taa/teachingclass/TeachingClass.java b/src/main/java/taa/teachingclass/TeachingClass.java index 85c7cece7e..5e3a11b8b1 100644 --- a/src/main/java/taa/teachingclass/TeachingClass.java +++ b/src/main/java/taa/teachingclass/TeachingClass.java @@ -18,8 +18,8 @@ public class TeachingClass implements ClassChecker { private final AssessmentList assessmentList; public TeachingClass(String id, String name) { - this.id = id.toLowerCase(); - this.name = name; + setId(id); + setName(name); this.studentList = new StudentList(); this.assessmentList = new AssessmentList(); } @@ -33,7 +33,7 @@ public String getName() { } public void setId(String id) { - this.id = id; + this.id = id.toLowerCase(); } public void setName(String name) { From 2fd5a102548ece85a9db771fb043a6a7eb86e344 Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 3 Nov 2021 19:28:31 +0800 Subject: [PATCH 322/543] Fix spacing between sections and add comments in Command Summary --- docs/UserGuide.md | 166 ++++++++++-------- .../average_marks_all_marked.png | Bin .../average_marks_with_unmarked.png | Bin .../{Marks_Images => marks}/delete_mark.png | Bin .../{Marks_Images => marks}/edit_mark.png | Bin .../{Marks_Images => marks}/list_marks.png | Bin .../marks}/median_mark_all_marked.png | Bin .../marks}/median_mark_with_unmarked.png | Bin .../{Marks_Images => marks}/set_mark.png | Bin 9 files changed, 91 insertions(+), 75 deletions(-) rename docs/images/{Marks_Images => marks}/average_marks_all_marked.png (100%) rename docs/images/{Marks_Images => marks}/average_marks_with_unmarked.png (100%) rename docs/images/{Marks_Images => marks}/delete_mark.png (100%) rename docs/images/{Marks_Images => marks}/edit_mark.png (100%) rename docs/images/{Marks_Images => marks}/list_marks.png (100%) rename docs/{ => images/marks}/median_mark_all_marked.png (100%) rename docs/{ => images/marks}/median_mark_with_unmarked.png (100%) rename docs/images/{Marks_Images => marks}/set_mark.png (100%) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7670d4633c..cd5845853a 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -23,8 +23,8 @@ If you can type fast, TAA can help keep track of your classes and students faste * [Marks](#marks) * [Listing marks for an assessment: `list_marks`](#listing-marks-for-an-assessment-list_marks) * [Setting mark for a student's assessment: `set_mark`](#setting-mark-for-a-students-assessment-set_mark) - * [Editing marks for a student's assessment: `edit_mark`](#editing-marks-for-a-students-assessment-edit_mark) - * [Deleting marks for a student's assessment: `delete_mark`](#deleting-marks-for-a-students-assessment-delete_mark) + * [Editing mark for a student's assessment: `edit_mark`](#editing-mark-for-a-students-assessment-edit_mark) + * [Deleting mark for a student's assessment: `delete_mark`](#deleting-mark-for-a-students-assessment-delete_mark) * [Viewing average marks for an assessment: `average_marks`](#viewing-average-marks-for-an-assessment-average_marks) * [Viewing median mark for an assessment: `median_mark`](#viewing-median-mark-for-an-assessment-median_mark) * [Sorting and listing students in a class by their overall score: `sort_by_scores`](#sorting-and-listing-students-in-a-class-by-their-overall-score-sort_by_scores) @@ -33,10 +33,10 @@ If you can type fast, TAA can help keep track of your classes and students faste * [Setting attendance for a particular lesson for a student: `set_attendance`](#setting-attendance-for-a-particular-lesson-for-a-student-set_attendance) * [Deleting attendance for a particular lesson for a student: `delete_attendance`](#deleting-attendance-for-a-particular-lesson-for-a-student-delete_attendance) * [Comments](#comments) + * [Listing comments for all students in a class: `list_comment`](#listing-comments-for-all-students-in-a-class-list_comment) * [Setting comment for a particular student: `set_comment`](#setting-comment-for-a-particular-student-set_comment) * [Deleting comment for a particular student: `delete_comment`](#deleting-comment-for-a-particular-student-delete_comment) - * [Listing comments for all students in a class `list_comment`](#listing-comments-for-all-students-in-a-class-list_comment) - * [Useful Features](#useful-features) + * [Others](#others) * [Viewing help: `help`](#viewing-help-help) * [Exiting the program: `exit`](#exiting-the-program-exit) * [Archiving data: `archive`](#archiving-data-archive) @@ -54,16 +54,17 @@ If you can type fast, TAA can help keep track of your classes and students faste 6. Enter `help` to display the list of available commands. See [Features](#features) for more information. ## Features -## Classes -### Listing all classes: `list_classes` +### Classes + +#### Listing all classes: `list_classes` Displays the list of all classes in the class list. Format: `list_classes`
-### Adding a class: `add_class` +#### Adding a class: `add_class` Adds a class to the class list. Format: `add_class i/ [n/]` @@ -79,7 +80,7 @@ Examples:
-### Editing a class: `edit_class` +#### Editing a class: `edit_class` Edits the code or name of an existing class. Format: `edit_class c/ [i/] [n/]` @@ -98,7 +99,7 @@ Examples:
-### Deleting a class: `delete_class` +#### Deleting a class: `delete_class` Deletes an existing class from the class list. Format: `delete_class c/` @@ -110,8 +111,9 @@ Examples:
-##Students -### Listing all students in a class: `list_students` +###Students + +#### Listing all students in a class: `list_students` Shows a list of all students in a particular class. Format: `list_students c/` @@ -123,7 +125,7 @@ Examples:
-### Adding a student to a class: `add_student` +#### Adding a student to a class: `add_student` Adds a student to a particular class. Format: `add_student c/ i/ n/` @@ -137,7 +139,7 @@ Examples:
-### Editing a student's information in a class: `edit_student` +#### Editing a student's information in a class: `edit_student` Edits student information from a particular class Format: `edit_student c/ s/ i/ n/` @@ -152,7 +154,7 @@ Examples:
-### Deleting a student from a class: `delete_student` +#### Deleting a student from a class: `delete_student` Deletes student information from a particular class. Format: `delete_student c/ s/` @@ -164,7 +166,7 @@ Examples:
-### Finding students in a class given a keyword: `find_student` +#### Finding students in a class given a keyword: `find_student` Displays all students in the class matching the keyword along with their index. Format: `find_student c/ k/` @@ -177,8 +179,9 @@ Examples:
-## Assessments -### Listing all assessments in a class: `list_assessments` +### Assessments + +#### Listing all assessments in a class: `list_assessments` List all assessments in a class. Format: `list_assessments c/` @@ -190,7 +193,7 @@ Examples:
-### Adding an assessment to a class: `add_assessment` +#### Adding an assessment to a class: `add_assessment` Adds an assessment to a class. Format: `add_assessment c/ n/ m/ w/` @@ -205,7 +208,7 @@ Examples:
-### Editing an assessment in a class: `edit_assessment` +#### Editing an assessment in a class: `edit_assessment` Edits an assessment of a class. Format: `edit_assessment c/ n/ [nn/] [m/] [w/]` @@ -226,7 +229,7 @@ Examples:
-### Deleting an assessment from a class: `delete_assessment` +#### Deleting an assessment from a class: `delete_assessment` Deletes an assessment of a class. Format: `delete_assessment c/ n/` @@ -239,8 +242,8 @@ Examples:
-## Marks -### Listing marks for an assessment: `list_marks` +### Marks +#### Listing marks for an assessment: `list_marks` Lists all students and their marks for an assessment. Format: `list_marks c/ a/` @@ -252,10 +255,11 @@ Examples: * `list_marks c/CS2101-C03 a/Oral Presentation` Expected Output:
-![img.png](images/Marks_Images/list_marks.png) +![img.png](images/marks/list_marks.png) +
-### Setting mark for a student's assessment: `set_mark` +#### Setting mark for a student's assessment: `set_mark` Adds a student's marks for an assessment. Format: `set_mark c/ s/ a/ m/` @@ -269,10 +273,11 @@ Examples: * `set_mark c/CS2101 s/3 a/Oral Presentation m/80` Expected Output:
-![set_mark.png](images/Marks_Images/set_mark.png) +![set_mark.png](images/marks/set_mark.png) +
-### Editing marks for a student's assessment: `edit_mark` +#### Editing mark for a student's assessment: `edit_mark` Edits a student's mark for an assessment. Format: `edit_mark c/ s/ a/ m/` @@ -286,10 +291,11 @@ Examples: * `edit_mark c/CS2101-C03 s/3 a/Oral Presentation m/90` Expected Output:
-![edit_mark.png](images/Marks_Images/edit_mark.png) +![edit_mark.png](images/marks/edit_mark.png) +
-### Deleting marks for a student's assessment: `delete_mark` +#### Deleting mark for a student's assessment: `delete_mark` Deletes a student's marks for an assessment. Format: `delete_mark c/ s/ a/` @@ -302,10 +308,11 @@ Examples: * `delete_mark c/CS2101 s/3 a/Oral Presentation` Expected Output:
-![delete_mark.png](images/Marks_Images/delete_mark.png) +![delete_mark.png](images/marks/delete_mark.png) +
-### Viewing average marks for an assessment: `average_marks` +#### Viewing average marks for an assessment: `average_marks` Computes and prints the average marks for an assessment. If there are unmarked students, the average will be computed within the marked students only. @@ -319,13 +326,14 @@ Examples: Expected Output:
(Some students unmarked)
-![average_marks_with_unmarked.png](images/Marks_Images/average_marks_with_unmarked.png) -
+![average_marks_with_unmarked.png](images/marks/average_marks_with_unmarked.png) + (All students marked)
-![average_marks_all_marked.png](images/Marks_Images/average_marks_all_marked.png) +![average_marks_all_marked.png](images/marks/average_marks_all_marked.png) +
-### Viewing median mark for an assessment: `median_mark` +#### Viewing median mark for an assessment: `median_mark` Computes and prints the median mark for an assessment. If there are unmarked students, the median will be computed within the marked students only. @@ -339,13 +347,14 @@ Examples: Expected Output:
(Some students unmarked)
-![img.png](median_mark_with_unmarked.png) -
+![img.png](images/marks/median_mark_with_unmarked.png) + (All students marked)
-![img.png](median_mark_all_marked.png) +![img.png](images/marks/median_mark_all_marked.png) +
-### Sorting and listing students in a class by their overall score: `sort_by_scores` +#### Sorting and listing students in a class by their overall score: `sort_by_scores` Sorts and lists students in a class by their overall score according to the desired format. Only marks currently added to students will be taken into consideration for their scores. @@ -359,8 +368,9 @@ Examples:
-## Attendance -### Listing attendance for a particular student: `list_attendance` +### Attendance + +#### Listing attendance for a particular student: `list_attendance` Lists a student's attendance. Format: `list_attendance c/ s/ s/ -### Setting attendance for a particular lesson for a student: `set_attendance` +#### Setting attendance for a particular lesson for a student: `set_attendance` Sets a student's attendance for a lesson. Format: `set_attendance c/ s/ l/ p/` @@ -380,7 +390,7 @@ Format: `set_attendance c/ s/ l/ p/ -### Deleting attendance for a particular lesson for a student: `delete_attendance` +#### Deleting attendance for a particular lesson for a student: `delete_attendance` Deletes a student's attendance for a lesson. Format: `delete_attendance c/ s/ l/` @@ -390,8 +400,9 @@ Format: `delete_attendance c/ s/ l/`
-## Comments -### Listing comments for all students in a class: `list_comment` +### Comments + +#### Listing comments for all students in a class: `list_comment` List comments for all students in a class Format: `list_comment c/` @@ -403,7 +414,7 @@ Examples:
-### Setting comment for a particular student: `set_comment` +#### Setting comment for a particular student: `set_comment` Sets a comment for a student. Format: `set_comment c/ s/ t/` @@ -419,7 +430,7 @@ Examples:
-### Deleting comment for a particular student: `delete_comment` +#### Deleting comment for a particular student: `delete_comment` Deletes the comment for a student. Format: `delete_comment c/ s/` @@ -432,15 +443,16 @@ Examples:
-## Useful Features -### Viewing help: `help` +### Others + +#### Viewing help: `help` Displays the list of available commands and how to use them. Format: `help`
-### Exiting the program: `exit` +#### Exiting the program: `exit` Exits the program. Format: `exit` @@ -472,29 +484,33 @@ Format: `reset` Category | Action | Format | ----- | ------ | --------------- | -Class | Listing all **classes** | `list_classes` -Class | Adding a **class** | `add_class i/ [n/]` -Class | Editing a **class** | `edit_class c/ [nc/] [n/]` -Class | Deleting a **class** | `delete_class c/` -Student | Listing all **students** in a class | `list_students c/` -Student | Adding a **student** to a class | `add_student c/ i/ n/` -Student | Editing a **student's** information in a class | `edit_student c/ s/ i/ n/` -Student | Deleting a **student** from a class | `delete_student c/ s/` -Student | Finding **students** in a class given a keyword | `find_student c/ k/` -Assessment | Listing all **assessments** in a class | `list_assessments c/` -Assessment | Adding an **assessment** to a class | `add_assessment c/ n/ m/ w/` -Assessment | Editing an **assessment** in a class | `edit_assessment c/ n/ [nn/] [m/]` -Assessment | Deleting an **assessment** from a class | `delete_assessment c/ n/` -Marks | Listing **marks** for an assessment: | `list_marks c/ a/` -Marks | Setting **mark** for a student's assessment | `set_mark c/ s/ a/ m/` -Marks | Editing **mark** for a student's assessment | `edit_mark c/ s/ a/ m/` -Marks | Deleting **mark** for a student's assessment | `delete_mark c/ s/ a/` -Marks | Viewing average **marks** for an assessment | `average_marks c/ a/` -Marks | Viewing the median **mark** for an assessment | `median_mark c/ a/` -Attendance | Listing **attendance** for a particular student | `list_attendance c/ s/` -Attendance | Setting **attendance** for a particular lesson for a student | `set_attendance c/ s/ l/ p/` -Attendance | Deleting **attendance** for a particular lesson for a student | `delete_attendance c/ s/ l/` -Useful Features | Viewing help | `help` -Useful Features | Exiting the program | `exit` -Useful Features | Archiving data | `archive` -Useful Features | Resetting/Removing all data | `reset` \ No newline at end of file +Class | Listing all classes | `list_classes` +Class | Adding a class | `add_class i/ [n/]` +Class | Editing a class | `edit_class c/ [nc/] [n/]` +Class | Deleting a class | `delete_class c/` +Student | Listing all students in a class | `list_students c/` +Student | Adding a student to a class | `add_student c/ i/ n/` +Student | Editing a student's information in a class | `edit_student c/ s/ i/ n/` +Student | Deleting a student from a class | `delete_student c/ s/` +Student | Finding students in a class given a keyword | `find_student c/ k/` +Assessment | Listing all assessments in a class | `list_assessments c/` +Assessment | Adding an assessment to a class | `add_assessment c/ n/ m/ w/` +Assessment | Editing an assessment in a class | `edit_assessment c/ n/ [nn/] [m/]` +Assessment | Deleting an assessment from a class | `delete_assessment c/ n/` +Marks | Listing marks for an assessment: | `list_marks c/ a/` +Marks | Setting mark for a student's assessment | `set_mark c/ s/ a/ m/` +Marks | Editing mark for a student's assessment | `edit_mark c/ s/ a/ m/` +Marks | Deleting mark for a student's assessment | `delete_mark c/ s/ a/` +Marks | Viewing average marks for an assessment | `average_marks c/ a/` +Marks | Viewing the median mark for an assessment | `median_mark c/ a/` +Marks | Sorting and listing students in a class by their overall score | `sort_by_scores c/ o/` +Attendance | Listing attendance for a particular student | `list_attendance c/ s/` +Attendance | Setting attendance for a particular lesson for a student | `set_attendance c/ s/ l/ p/` +Attendance | Deleting attendance for a particular lesson for a student | `delete_attendance c/ s/ l/` +Comments | Listing comments for all students in a class | `list_comment c/` +Comments | Setting comment for a particular student | `set_comment c/ s/ t/` +Comments | Deleting comment for a particular student | `delete_comment c/ s/` +Others | Viewing help | `help` +Others | Exiting the program | `exit` +Others | Archiving data | `archive` +Others | Resetting/Removing all data | `reset` diff --git a/docs/images/Marks_Images/average_marks_all_marked.png b/docs/images/marks/average_marks_all_marked.png similarity index 100% rename from docs/images/Marks_Images/average_marks_all_marked.png rename to docs/images/marks/average_marks_all_marked.png diff --git a/docs/images/Marks_Images/average_marks_with_unmarked.png b/docs/images/marks/average_marks_with_unmarked.png similarity index 100% rename from docs/images/Marks_Images/average_marks_with_unmarked.png rename to docs/images/marks/average_marks_with_unmarked.png diff --git a/docs/images/Marks_Images/delete_mark.png b/docs/images/marks/delete_mark.png similarity index 100% rename from docs/images/Marks_Images/delete_mark.png rename to docs/images/marks/delete_mark.png diff --git a/docs/images/Marks_Images/edit_mark.png b/docs/images/marks/edit_mark.png similarity index 100% rename from docs/images/Marks_Images/edit_mark.png rename to docs/images/marks/edit_mark.png diff --git a/docs/images/Marks_Images/list_marks.png b/docs/images/marks/list_marks.png similarity index 100% rename from docs/images/Marks_Images/list_marks.png rename to docs/images/marks/list_marks.png diff --git a/docs/median_mark_all_marked.png b/docs/images/marks/median_mark_all_marked.png similarity index 100% rename from docs/median_mark_all_marked.png rename to docs/images/marks/median_mark_all_marked.png diff --git a/docs/median_mark_with_unmarked.png b/docs/images/marks/median_mark_with_unmarked.png similarity index 100% rename from docs/median_mark_with_unmarked.png rename to docs/images/marks/median_mark_with_unmarked.png diff --git a/docs/images/Marks_Images/set_mark.png b/docs/images/marks/set_mark.png similarity index 100% rename from docs/images/Marks_Images/set_mark.png rename to docs/images/marks/set_mark.png From d11c833100a4fcad2df169121ab3c5efebdd12da Mon Sep 17 00:00:00 2001 From: Leyond Date: Wed, 3 Nov 2021 19:31:42 +0800 Subject: [PATCH 323/543] Add horizontal lines between each category --- docs/UserGuide.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/UserGuide.md b/docs/UserGuide.md index cd5845853a..307f655103 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -110,6 +110,7 @@ Examples: * `delete_class c/CS2101-C03`
+

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 literal 28022 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 diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml index 26b22e026c..0c4dcde1df 100644 --- a/docs/diagrams/ArchitectureSequenceDiagram.puml +++ b/docs/diagrams/ArchitectureSequenceDiagram.puml @@ -1,45 +1,121 @@ @startuml +!include style.puml Actor User as user -Participant ":UI" as ui +Participant ":Ui" as ui Participant ":Taa" as taa +Participant "<>\nParser" as parser Participant ":Command" as command -Participant ":ModuleList" as modulelist +Participant "<>\nUtil" as util +Participant ":ModuleList" as moduleList Participant ":Storage" as storage -note left of modulelist: Model +activate taa + +taa -> taa : loadModuleListFromStorage() +activate taa + +taa -> storage : load() +activate storage + +create moduleList +storage -> moduleList +activate moduleList +moduleList --> storage +deactivate moduleList + +storage --> taa : moduleList:ModuleList +deactivate storage + +taa --> taa +deactivate taa -user -> ui : "add_module c/CS2113T\nn/Software Engineering" +loop !isExit +taa -> ui : getUserInput() activate ui -ui -> taa -activate taa +user -> ui : User input command +ui --> taa : userInput:String +deactivate ui + +taa -> parser : parseUserInput(userInput:String) +activate parser -taa -> command : execute() +create command +parser -> command activate command +command --> parser +deactivate command -command -> modulelist : addModule(module) -activate modulelist +parser --> taa : command:Command +deactivate parser -modulelist --> command -deactivate modulelist +taa -> command : checkArgument() +activate command -command -> storage : save(moduleList) -activate storage +command -> util +activate util +util --> command +deactivate util + +alt Exception +command --> taa : throw :TaaException +taa -> ui : printException(message:String) +activate ui +ui -> user : Display Exception message +ui --> taa +deactivate ui +else else +command --> taa +deactivate command + +taa -> command : execute(moduleList:ModuleList, ui:Ui,\n\tstorage:Storage) +activate command + +command -> util +activate util +util --> command +deactivate util + +command -> moduleList +activate moduleList +moduleList --> command +deactivate moduleList + +alt Exception +command --> taa : throw :TaaException +taa -> ui : printException(message:String) +activate ui +ui -> user : Display Exception message +ui --> taa +deactivate ui + +else else +command -> storage : save(moduleList:ModuleList) +activate storage storage --> command deactivate storage -command -> ui : printMessage(...) +command -> ui : printMessage(message:String) +activate ui +ui -> user : Display message ui --> command +deactivate ui command --> taa deactivate command -taa --> ui -deactivate taa +taa -> command : isExit() +activate command +command --> taa : isExit:boolean +deactivate command -ui --> user -deactivate ui +taa -[hidden]-> command +destroy command +taa -[hidden]-> command + +end +end @enduml \ No newline at end of file From c2ff5b7e2d2bc5803aba04728938911cf58df650 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 22:00:45 +0800 Subject: [PATCH 196/543] Add sequence diagram for add module command --- docs/diagrams/AddModuleSequenceDiagram.png | Bin 0 -> 71753 bytes docs/diagrams/AddModuleSequenceDiagram.puml | 92 ++++++++++++++++++++ docs/diagrams/style.puml | 27 ++++++ 3 files changed, 119 insertions(+) create mode 100644 docs/diagrams/AddModuleSequenceDiagram.png create mode 100644 docs/diagrams/AddModuleSequenceDiagram.puml create mode 100644 docs/diagrams/style.puml diff --git a/docs/diagrams/AddModuleSequenceDiagram.png b/docs/diagrams/AddModuleSequenceDiagram.png new file mode 100644 index 0000000000000000000000000000000000000000..58ec7d1ff984873a0da571f8b2e5bf7ac4d5a8bf GIT binary patch literal 71753 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 literal 0 HcmV?d00001 diff --git a/docs/diagrams/AddModuleSequenceDiagram.puml b/docs/diagrams/AddModuleSequenceDiagram.puml new file mode 100644 index 0000000000..9f7c3a923a --- /dev/null +++ b/docs/diagrams/AddModuleSequenceDiagram.puml @@ -0,0 +1,92 @@ +@startuml +!include style.puml + +Actor User as user +Participant ":Ui" as ui +Participant ":Taa" as taa +Participant "<>\nParser" as parser +Participant ":AddModuleCommand" as addModuleCommand +Participant ":ModuleList" as moduleList +Participant ":Module" as module +Participant ":Storage" as storage + +activate taa + +taa -> ui : getUserInput() +activate ui + +user -> ui : "add_module c/CS2113T\nn/Software Engineering" +ui --> taa : userInput:String +deactivate ui + +taa -> parser : parseUserInput(userInput) +activate parser + +create addModuleCommand +parser -> addModuleCommand +activate addModuleCommand +addModuleCommand -> parser +deactivate addModuleCommand + +parser --> taa : command:AddModuleCommand +deactivate parser + +taa -> addModuleCommand : checkArguments() +activate addModuleCommand +alt Exception +addModuleCommand --> taa : throw :TaaException +taa -> ui : printException(message:String) +activate ui +ui -> user : Display Exception message +ui --> taa +deactivate ui + +else else +addModuleCommand --> taa +deactivate addModuleCommand + +taa -> addModuleCommand : execute(moduleList:ModuleList, ui:Ui, storage:Storage) +activate addModuleCommand + +addModuleCommand -> moduleList : getModuleWithCode(moduleCode:String) +activate moduleList + +moduleList --> addModuleCommand : module:Module +deactivate moduleList + +alt module != null +addModuleCommand --> taa : throw :TaaException +taa -> ui : printException(message:String) +activate ui +ui -> user : Display Exception message +ui --> taa +deactivate ui + +else else +create module +addModuleCommand -> module +activate module +module --> addModuleCommand +deactivate module + +addModuleCommand -> moduleList : addModule(module:Module) +activate moduleList +moduleList --> addModuleCommand +deactivate moduleList + +addModuleCommand -> storage : save(moduleList:ModuleList) +activate storage +storage --> addModuleCommand +deactivate storage + +addModuleCommand -> ui : printMessage("Module added: ...") +activate ui +ui -> user : Display message:\n"Module added: ..." +ui --> addModuleCommand +deactivate ui + +deactivate addModuleCommand +end +end + +@enduml \ No newline at end of file diff --git a/docs/diagrams/style.puml b/docs/diagrams/style.puml new file mode 100644 index 0000000000..8b0d631dc1 --- /dev/null +++ b/docs/diagrams/style.puml @@ -0,0 +1,27 @@ +skinparam Shadowing false + +skinparam Actor { + FontName Arial +} + +skinparam Sequence { + MessageAlign center + BoxFontSize 15 + BoxPadding 0 + BoxFontColor #FFFFFF + FontName Arial +} + +skinparam Participant { + Padding 20 +} + +skinparam MinClassWidth 50 +skinparam ParticipantPadding 10 +skinparam Shadowing false +skinparam DefaultTextAlignment center +skinparam packageStyle Rectangle + +hide footbox +hide members +hide circle \ No newline at end of file From 1098980e6d80ba07ae3f850c2eff41a0530cd603 Mon Sep 17 00:00:00 2001 From: Leyond Date: Mon, 25 Oct 2021 22:01:26 +0800 Subject: [PATCH 197/543] Update add module explanation in DG --- docs/DeveloperGuide.md | 72 ++++++++++++++++++------------------------ 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index f182bc8e92..d80aa0240e 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -14,65 +14,53 @@ ## Design ### Architecture ![ArchitectureDiagram](diagrams/ArchitectureDiagram.png) -
-_Figure 1. Architecture Diagram_
-
-The _Architecture Diagram_ shown above explains the high-level design of the Application.
-
+ +The _Architecture Diagram_ shown above illustrates the high-level design of the Application. + **Overview of components** * `Main` - * On app launch: Creates and runs an instance of `Duke`. + * On app launch: Creates and runs an instance of `Taa`. * `UI` * Handles UI operations. * `Taa` * On creation: Initializes the `UI` and `Storage` components. - * On run: Loads data saved in `Storage`, receives and processes user input from `UI`. + * On run: Loads persistent data from `Storage`, receives user input from `UI`, and uses `Parser` to parse the user input. +* `Parser` + * Handles input parsing and determines which command to run. * `Command` * Defines how a command is to be executed. -* `Model` - * Represents a collection of classes that holds the data of the application in-memory. - * Includes: `ModuleList`, `Modules`, `StudentList` , `Student`, `AssessmentList` , `Assessment`, `AttendanceList` -, `Attendance` +* `ModuleList` + * Contains a list of `Module` objects currently being managed by the app. +* `Util` + * Contains useful methods (e.g. Check if a string is integer/double, convert string to integer/double). * `Storage` * Handles data storage operations (e.g. Reading from and writing to data file). -* `Commons` - * Represents a collection of classes used by other components. - * `Parser`: Used to translate user input into a `Command` and to parse an argument string into its various values. - * `Util`: Contains utility functions used by other classes.
-**Interactions between components** -
- +**Interaction between components** ![ArchitectureSequenceDiagram](diagrams/ArchitectureSequenceDiagram.png) -
-_Figure 2. An example of interactions between components for `add_module c/CS2113T n/Software Engineering`._ + +The _Architecture Sequence Diagram_ shown above shows how the components usually interact with each other. ## Implementation ### Add Module -The add module mechanism is facilitated by `AddModuleCommand`. It extends `Command` and uses `ModuleList` which stores -module internally as an ArrayList `modules`.
- -`AddModuleCommand` implements the following methods: -* `AddModuleCommand#execute(moduleList:ModuleList, ui:Ui, storage:Storage)` - Performs operations for the command. - -`ModuleList` implements the following methods: -* `ModuleList#getSize()` - Returns the no. of modules currently in the list. -* `ModuleList#getModules()` - Returns an ArrayList containing all the modules. -* `ModuleList#getModule(code:String)` - Returns a module with a particular code. -* `ModuleList#isValidIndex(index:int)` - Checks if an index is valid w.r.t the `modules` ArrayList. -* `ModuleList#addModule(module:Module)` - Adds a module to the `modules` ArrayList. -* `ModuleList#getModuleAt(index:int)` - Returns a `Module` object at the specified `index` within the `modules` -ArrayList. - -Below is an example scenario of how the add module feature behaves at each step:
-* Step 1 - The user executes `add_module c/CS2113T n/Software Engineering` to add a module. The `add_module` command -calls the `AddModuleCommand#execute` method. Within `AddModuleCommand#execute`, `ModuleList#getModule("CS2113T")` is -called to ensure that there is no existing module with code `CS2113T`. -* Step 2 - If no existing module with code `CS2113T` is found, a new `Module` object with code and name set to `CS2113T` -and `Software Engineering` respectively. Then, `ModuleList#addModule` is called to add the newly created `Module` -object into the `modules` ArrayList within `ModuleList`. +The sequence diagram shown below illustrates how the `add_module` command works: +![AddModuleSequenceDiagram](diagrams/AddModuleSequenceDiagram.png) + +Steps: +1. The `Taa` instance reads in a user input through the `Ui.getUserInput()` method. +2. The user input is then parsed using the `Parser.parseUserInput(userInput:String)` static method and a `Command` object +is returned. +3. `AddModuleCommand.checkArguments()` is then called to check if the arguments are valid. **If an exception occurs, the exception +message will be printed out and the command execution ends here.** +4. After checking the arguments, `Command.execute(moduleList:ModuleList, ui:Ui, storage:Storage)` will be called. +5. Within `AddModuleCommand.checkArguments()`, `ModuleList.getModuleWithCode(moduleCode:String)` is called and will return a +`Module` object if a module with the `moduleCode` is found. **If `ModuleList.getModuleWithCode(moduleCode:String)` returns +an object, an exception will occur (the exception message will be printed out) and the command execution ends here.** +6. A new `Module` object is created and the `ModuleList.addModule(module:Module)` method be invoked to add the `Module` +object into the list of modules. +7. Lastly, a message indicating that the module has been added will be printed out. ### Add Student The add student mechanism is facilitated by `AddStudentCommand`. It extends `Command` and uses `StudentList` which From 4b92356f5f8db6501bcc21aeaa27d4357f43fe6d Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Mon, 25 Oct 2021 22:42:06 +0800 Subject: [PATCH 198/543] added sort scores --- src/main/java/taa/Parser.java | 5 + src/main/java/taa/command/Command.java | 7 +- .../java/taa/command/DeleteMarkCommand.java | 21 ++- .../java/taa/command/EditMarkCommand.java | 20 +++ .../java/taa/command/SortByScoresCommand.java | 164 ++++++++++++++++++ src/main/java/taa/student/Student.java | 1 + 6 files changed, 214 insertions(+), 4 deletions(-) create mode 100644 src/main/java/taa/command/SortByScoresCommand.java diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index 9b04b596e8..d711a1a68f 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -25,6 +25,7 @@ import taa.command.ListStudentsCommand; import taa.command.SetAttendanceCommand; import taa.command.SetMarksCommand; +import taa.command.SortByScoresCommand; import taa.exception.TaaException; import java.util.ArrayList; @@ -133,6 +134,10 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new ListMarksCommand(argument); break; + case Command.COMMAND_SORT_BY_SCORES: + command = new SortByScoresCommand(argument); + break; + default: throw new TaaException(MESSAGE_UNKNOWN_COMMAND); } diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index 6475cbf54a..d36ebe3e6f 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -14,8 +14,6 @@ public abstract class Command { public static final String COMMAND_LIST_STUDENTS = "list_students"; public static final String COMMAND_LIST_ASSESSMENTS = "list_assessments"; public static final String COMMAND_LIST_ATTENDANCE = "list_attendance"; - public static final String COMMAND_LIST_MARKS = "list_marks"; - public static final String COMMAND_AVERAGE_MARKS = "average_marks"; public static final String COMMAND_ADD_MODULE = "add_module"; public static final String COMMAND_EDIT_MODULE = "edit_module"; public static final String COMMAND_DELETE_MODULE = "delete_module"; @@ -27,10 +25,13 @@ public abstract class Command { public static final String COMMAND_DELETE_ATTENDANCE = "delete_attendance"; public static final String COMMAND_ADD_ASSESSMENT = "add_assessment"; public static final String COMMAND_DELETE_ASSESSMENT = "delete_assessment"; + public static final String COMMAND_EDIT_ASSESSMENT = "edit_assessment"; + public static final String COMMAND_LIST_MARKS = "list_marks"; + public static final String COMMAND_AVERAGE_MARKS = "average_marks"; public static final String COMMAND_SET_MARKS = "set_marks"; public static final String COMMAND_EDIT_MARK = "edit_mark"; - public static final String COMMAND_EDIT_ASSESSMENT = "edit_assessment"; public static final String COMMAND_DELETE_MARK = "delete_mark"; + public static final String COMMAND_SORT_BY_SCORES = "sort_by_scores"; public static final String COMMAND_HELP = "help"; // Common messages diff --git a/src/main/java/taa/command/DeleteMarkCommand.java b/src/main/java/taa/command/DeleteMarkCommand.java index ca3976495b..b760a92982 100644 --- a/src/main/java/taa/command/DeleteMarkCommand.java +++ b/src/main/java/taa/command/DeleteMarkCommand.java @@ -45,6 +45,14 @@ public void checkArgument() throws TaaException { } } + /** + * Executes the delete_marks command and deletes the marks of a student's assessment. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { String moduleCode = argumentMap.get(KEY_MODULE_CODE); @@ -78,12 +86,23 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc storage.save(moduleList); } + /** + * Deletes marks from the results hashmap for the student. + * + * @param ui The ui instance to handle interactions with the user. + * @param student The student whose marks are to be deleted. + * @param assessmentName The name of the assessment to delete marks for. + */ private void deleteMark(Ui ui, Student student, String assessmentName) { student.deleteMark(assessmentName); ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_DELETED, student, assessmentName)); } - + /** + * Returns the usage message of the delete marks command. + * + * @return String which contains the usage message. + */ @Override protected String getUsage() { return String.format( diff --git a/src/main/java/taa/command/EditMarkCommand.java b/src/main/java/taa/command/EditMarkCommand.java index 6900b668c9..1f4d852cda 100644 --- a/src/main/java/taa/command/EditMarkCommand.java +++ b/src/main/java/taa/command/EditMarkCommand.java @@ -54,6 +54,14 @@ public void checkArgument() throws TaaException { } } + /** + * Executes the edit_marks command and edits the marks of a student's assessment. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ @Override public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { String moduleCode = argumentMap.get(KEY_MODULE_CODE); @@ -94,6 +102,13 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc storage.save(moduleList); } + /** + * Edits marks in the results hashmap of the student. + * + * @param ui The ui instance to handle interactions with the user. + * @param student The student whose marks are to be edited. + * @param assessmentName The name of the assessment to edit marks for. + */ private void editMark(Ui ui, Student student, String assessmentName, double newMarks) { double previousMark = student.getMarks(assessmentName); student.deleteMark(assessmentName); @@ -101,6 +116,11 @@ private void editMark(Ui ui, Student student, String assessmentName, double newM ui.printMessage(String.format(MESSAGE_FORMAT_MARKS_EDITED, student, previousMark, newMarks, assessmentName)); } + /** + * Returns the usage message of the edit marks command. + * + * @return String which contains the usage message. + */ @Override protected String getUsage() { return String.format( diff --git a/src/main/java/taa/command/SortByScoresCommand.java b/src/main/java/taa/command/SortByScoresCommand.java new file mode 100644 index 0000000000..d010707d64 --- /dev/null +++ b/src/main/java/taa/command/SortByScoresCommand.java @@ -0,0 +1,164 @@ +package taa.command; + +import taa.Ui; +import taa.assessment.Assessment; +import taa.assessment.AssessmentList; +import taa.exception.TaaException; +import taa.module.Module; +import taa.module.ModuleList; +import taa.storage.Storage; +import taa.student.Student; +import taa.student.StudentList; +import taa.util.Util; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +public class SortByScoresCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_ASSESSMENT_NAME = "a"; + private static final String KEY_SORT_ORDER = "o"; + private static final String[] SORT_SCORES_ARGUMENT_KEYS = { + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME, + KEY_SORT_ORDER + }; + private static final String MESSAGE_FORMAT_SORT_SCORES_USAGE = "%s %s/ %s/ " + + "%s/"; + private static final String MESSAGE_LIST_MARKS_HEADER = "Here is the sorted list of students and " + + "their marks for %s:"; + + public SortByScoresCommand(String argument) { + super(argument, SORT_SCORES_ARGUMENT_KEYS); + } + + @Override + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + } + + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModuleWithCode(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + AssessmentList assessmentList = module.getAssessmentList(); + String assessmentName = argumentMap.get(KEY_ASSESSMENT_NAME); + Assessment assessment = assessmentList.getAssessment(assessmentName); + if (assessment == null) { + throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); + } + String order = argumentMap.get(KEY_SORT_ORDER); + if (!order.equalsIgnoreCase("asc") && !order.equalsIgnoreCase("desc")) { + throw new TaaException("Please input a valid sort order."); + } + ArrayList studentList = module.getStudentList().getStudents(); + ArrayList studentListClone = new ArrayList<>(); + for (Student student : studentList) { + Student clonedStudent = new Student(student.getId(), student.getName()); + studentListClone.add(clonedStudent); + } + + if (order.equalsIgnoreCase("asc")) { + sortAscending(ui, module, assessmentName, studentListClone); + } + else if (order.equalsIgnoreCase("desc")) { + sortDescending(ui, module, assessmentName, studentListClone); + } + } + + /** + * Returns a string with the student name and the marks associated with the student. + * + * @param studentName Name of the student. + * @param marks Marks of the student. + * @return String with the name and marks of the student separated with a vertical line. + */ + public String marksToString(String studentName, double marks) { + return studentName + " | " + marks; + } + + private void appendUnmarkedStudent(StringBuilder stringBuilder, int studentIndex, Student student) { + stringBuilder.append("\n"); + stringBuilder.append(studentIndex); + stringBuilder.append(". "); + stringBuilder.append(student.getName()); + stringBuilder.append(" | "); + stringBuilder.append("NIL"); + } + + private void appendMarkedStudent(String assessmentName, StringBuilder stringBuilder, int studentIndex, Student student) { + stringBuilder.append("\n"); + stringBuilder.append(studentIndex); + stringBuilder.append(". "); + stringBuilder.append(marksToString(student.getName(), student.getMarks(assessmentName))); + } + + private void sortAscending(Ui ui, Module module, String assessmentName, ArrayList students) { + StringBuilder stringBuilder = new StringBuilder(String.format(MESSAGE_LIST_MARKS_HEADER, assessmentName)); + int listIndex = 0; + List toRemove = new ArrayList<>(); + for (Student student : students) { + if (!student.marksExist(assessmentName)) { + listIndex += 1; + appendUnmarkedStudent(stringBuilder, listIndex, student); + toRemove.add(student); + } + } + students.removeAll(toRemove); + while (students.size() > 0) { + for (Student student : students) { + int current_minimum_score = 10000; + if (student.marksExist(assessmentName) && (student.getMarks(assessmentName) < current_minimum_score)) { + listIndex += 1; + appendMarkedStudent(assessmentName, stringBuilder, listIndex, student); + students.remove(student); + } + } + } + ui.printMessage(stringBuilder.toString()); + } + + private void sortDescending(Ui ui, Module module, String assessmentName, ArrayList students) { + StringBuilder stringBuilder = new StringBuilder(String.format(MESSAGE_LIST_MARKS_HEADER, assessmentName)); + int listIndex = 0; + for (Student student : students) { + if (!student.marksExist(assessmentName)) { + listIndex += 1; + appendUnmarkedStudent(stringBuilder, listIndex, student); + students.remove(student); + } + } + while (students.size() > 0) { + for (Student student : students) { + int current_maximum_score = -1; + if (student.marksExist(assessmentName) && (student.getMarks(assessmentName) > current_maximum_score)) { + listIndex += 1; + appendMarkedStudent(assessmentName, stringBuilder, listIndex, student); + students.remove(student); + } + } + } + ui.printMessage(stringBuilder.toString()); + } + + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_SORT_SCORES_USAGE, + COMMAND_SORT_BY_SCORES, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME, + KEY_SORT_ORDER + ); + } +} diff --git a/src/main/java/taa/student/Student.java b/src/main/java/taa/student/Student.java index f6f35a91c3..bdf6e2e7cc 100644 --- a/src/main/java/taa/student/Student.java +++ b/src/main/java/taa/student/Student.java @@ -5,6 +5,7 @@ import taa.assessment.Assessment; import taa.assessment.AssessmentList; import taa.attendance.AttendanceList; +import taa.exception.TaaException; import java.util.HashMap; From 076088b73eb6dd90710f3c56f3c2e8fb36287914 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Mon, 25 Oct 2021 22:48:07 +0800 Subject: [PATCH 199/543] GRADLED --- src/main/java/taa/command/SortByScoresCommand.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/java/taa/command/SortByScoresCommand.java b/src/main/java/taa/command/SortByScoresCommand.java index d010707d64..592b46da83 100644 --- a/src/main/java/taa/command/SortByScoresCommand.java +++ b/src/main/java/taa/command/SortByScoresCommand.java @@ -70,8 +70,7 @@ public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaExc if (order.equalsIgnoreCase("asc")) { sortAscending(ui, module, assessmentName, studentListClone); - } - else if (order.equalsIgnoreCase("desc")) { + } else if (order.equalsIgnoreCase("desc")) { sortDescending(ui, module, assessmentName, studentListClone); } } @@ -96,7 +95,8 @@ private void appendUnmarkedStudent(StringBuilder stringBuilder, int studentIndex stringBuilder.append("NIL"); } - private void appendMarkedStudent(String assessmentName, StringBuilder stringBuilder, int studentIndex, Student student) { + private void appendMarkedStudent(String assessmentName, StringBuilder stringBuilder, int studentIndex, + Student student) { stringBuilder.append("\n"); stringBuilder.append(studentIndex); stringBuilder.append(". "); @@ -117,8 +117,8 @@ private void sortAscending(Ui ui, Module module, String assessmentName, ArrayLis students.removeAll(toRemove); while (students.size() > 0) { for (Student student : students) { - int current_minimum_score = 10000; - if (student.marksExist(assessmentName) && (student.getMarks(assessmentName) < current_minimum_score)) { + int currentMinimumScore = 10000; + if (student.marksExist(assessmentName) && (student.getMarks(assessmentName) < currentMinimumScore)) { listIndex += 1; appendMarkedStudent(assessmentName, stringBuilder, listIndex, student); students.remove(student); @@ -140,8 +140,8 @@ private void sortDescending(Ui ui, Module module, String assessmentName, ArrayLi } while (students.size() > 0) { for (Student student : students) { - int current_maximum_score = -1; - if (student.marksExist(assessmentName) && (student.getMarks(assessmentName) > current_maximum_score)) { + int currentMaximumScore = -1; + if (student.marksExist(assessmentName) && (student.getMarks(assessmentName) > currentMaximumScore)) { listIndex += 1; appendMarkedStudent(assessmentName, stringBuilder, listIndex, student); students.remove(student); From 6152cf432eff62098f514e7948380a8f046ff0f8 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Tue, 26 Oct 2021 00:29:56 +0800 Subject: [PATCH 200/543] Add MedianMarkCommand, edit AverageMarksCommand to only average marked students, and update user guide accordingly --- docs/UserGuide.md | 17 ++- src/main/java/taa/Parser.java | 5 + .../java/taa/command/AverageMarksCommand.java | 2 +- src/main/java/taa/command/Command.java | 1 + .../java/taa/command/MedianMarkCommand.java | 138 ++++++++++++++++++ 5 files changed, 161 insertions(+), 2 deletions(-) create mode 100644 src/main/java/taa/command/MedianMarkCommand.java diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 8d40c02ca1..eed9c7dde3 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -274,7 +274,8 @@ Examples:
### Viewing average marks for an assessment: `average_marks` -Computes and prints the average marks for an assessment. +Computes and prints the average marks for an assessment. If there are unmarked students, the average will be computed +within the marked students only. Format: `set_marks c/ a/` * `MODULE_CODE` refers to the code of the module (e.g. CS2113T). @@ -286,6 +287,20 @@ Examples:
+### Viewing median mark for an assessment: `median_mark` +Computes and prints the median mark for an assessment. If there are unmarked students, the median will be computed +within the marked students only. + +Format: `set_marks c/ a/` +* `MODULE_CODE` refers to the code of the module (e.g. CS2113T). +* `ASSESSMENT_NAME` refers to the name of the particular assessment. + +Examples: +* `median_mark c/CS2113T a/Midterms` +* `median_mark c/CS2101 a/Oral Presentation` + +
+ ### Listing attendance for a particular student: `list_attendance` Lists a student's attendance. diff --git a/src/main/java/taa/Parser.java b/src/main/java/taa/Parser.java index d711a1a68f..2dc40326bc 100644 --- a/src/main/java/taa/Parser.java +++ b/src/main/java/taa/Parser.java @@ -23,6 +23,7 @@ import taa.command.ListMarksCommand; import taa.command.ListModulesCommand; import taa.command.ListStudentsCommand; +import taa.command.MedianMarkCommand; import taa.command.SetAttendanceCommand; import taa.command.SetMarksCommand; import taa.command.SortByScoresCommand; @@ -130,6 +131,10 @@ public static Command parseUserInput(String userInput) throws TaaException { command = new AverageMarksCommand(argument); break; + case Command.COMMAND_MEDIAN_MARK: + command = new MedianMarkCommand(argument); + break; + case Command.COMMAND_LIST_MARKS: command = new ListMarksCommand(argument); break; diff --git a/src/main/java/taa/command/AverageMarksCommand.java b/src/main/java/taa/command/AverageMarksCommand.java index eb48f80904..6a9c3f2cc8 100644 --- a/src/main/java/taa/command/AverageMarksCommand.java +++ b/src/main/java/taa/command/AverageMarksCommand.java @@ -89,7 +89,7 @@ private void printAverageMarks(Ui ui, Module module, Assessment assessment) { } } - double averageMarks = totalMarks / classSize; + double averageMarks = totalMarks / (classSize - unmarkedStudents); if (unmarkedStudents <= 0) { ui.printMessage(String.format(MESSAGE_FORMAT_AVERAGE_MARKS, assessmentName, averageMarks)); } else { diff --git a/src/main/java/taa/command/Command.java b/src/main/java/taa/command/Command.java index d36ebe3e6f..a064491aab 100644 --- a/src/main/java/taa/command/Command.java +++ b/src/main/java/taa/command/Command.java @@ -28,6 +28,7 @@ public abstract class Command { public static final String COMMAND_EDIT_ASSESSMENT = "edit_assessment"; public static final String COMMAND_LIST_MARKS = "list_marks"; public static final String COMMAND_AVERAGE_MARKS = "average_marks"; + public static final String COMMAND_MEDIAN_MARK = "median_mark"; public static final String COMMAND_SET_MARKS = "set_marks"; public static final String COMMAND_EDIT_MARK = "edit_mark"; public static final String COMMAND_DELETE_MARK = "delete_mark"; diff --git a/src/main/java/taa/command/MedianMarkCommand.java b/src/main/java/taa/command/MedianMarkCommand.java new file mode 100644 index 0000000000..9af4357a2b --- /dev/null +++ b/src/main/java/taa/command/MedianMarkCommand.java @@ -0,0 +1,138 @@ +package taa.command; + +import taa.Ui; +import taa.assessment.Assessment; +import taa.assessment.AssessmentList; +import taa.exception.TaaException; +import taa.module.Module; +import taa.module.ModuleList; +import taa.storage.Storage; +import taa.student.Student; +import taa.student.StudentList; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class MedianMarkCommand extends Command { + private static final String KEY_MODULE_CODE = "c"; + private static final String KEY_ASSESSMENT_NAME = "a"; + private static final String[] MEDIAN_MARKS_ARGUMENT_KEYS = {KEY_MODULE_CODE, KEY_ASSESSMENT_NAME}; + + private static final String MESSAGE_FORMAT_MEDIAN_MARKS_USAGE = "%s %s/ %s/"; + private static final String MESSAGE_FORMAT_MEDIAN_MARKS = "Median mark for %s is %,.2f"; + private static final String MESSAGE_FORMAT_MEDIAN_MARKS_WITH_UNMARKED = "Median mark for %s is %,.2f\n" + + "Note that %d student(s) have yet to be marked!"; + + public MedianMarkCommand(String argument) { + super(argument, MEDIAN_MARKS_ARGUMENT_KEYS); + } + + @Override + public void checkArgument() throws TaaException { + if (argument.isEmpty()) { + throw new TaaException(getUsageMessage()); + } + + if (!hasAllArguments()) { + throw new TaaException(getMissingArgumentMessage()); + } + } + + /** + * Executes the median_marks command and displays the average mark of an assessment to the user. + * + * @param moduleList The list of modules. + * @param ui The ui instance to handle interactions with the user. + * @param storage The storage instance to handle saving. + * @throws TaaException If the user inputs an invalid command or has missing/invalid argument(s). + */ + @Override + public void execute(ModuleList moduleList, Ui ui, Storage storage) throws TaaException { + String moduleCode = argumentMap.get(KEY_MODULE_CODE); + Module module = moduleList.getModuleWithCode(moduleCode); + if (module == null) { + throw new TaaException(MESSAGE_MODULE_NOT_FOUND); + } + + StudentList studentList = module.getStudentList(); + if (studentList.getSize() <= 0) { + throw new TaaException(MESSAGE_NO_STUDENTS); + } + + AssessmentList assessmentList = module.getAssessmentList(); + Assessment assessment = assessmentList.getAssessment(argumentMap.get(KEY_ASSESSMENT_NAME)); + if (assessment == null) { + throw new TaaException(MESSAGE_INVALID_ASSESSMENT_NAME); + } + ArrayList students = module.getStudentList().getStudents(); + ArrayList studentsClone = new ArrayList<>(); + for (Student student : students) { + Student clonedStudent = new Student(student.getId(), student.getName()); + clonedStudent.setMarks(assessment.getName(), student.getMarks(assessment.getName())); + studentsClone.add(clonedStudent); + } + printMedianMarks(ui, module, assessment, studentsClone); + } + + /** + * Outputs the median marks of an assessment in a module. + * + * @param ui The ui instance to handle interactions with the user. + * @param module The module the assessment belongs to. + */ + private void printMedianMarks(Ui ui, Module module, Assessment assessment, ArrayList students) { + StudentList studentList = module.getStudentList(); + String assessmentName = assessment.getName(); + double classSize = studentList.getSize(); + int printIterator = 1; + double median = 0; + double unmarkedStudents = 0; + HashMap unsortedResults = new HashMap<>(); + for (Student student : students) { + unsortedResults.put(student, student.getMarks(assessmentName)); + if (student.getMarks(assessmentName) < 0) { + unmarkedStudents += 1; + } + } + List> list = new LinkedList<>(unsortedResults.entrySet()); + list.sort(Map.Entry.comparingByValue()); + HashMap sortedResults = new LinkedHashMap<>(); + for (Map.Entry item : list) { + sortedResults.put(item.getKey(), item.getValue()); + } + int medianCutOff = (int) Math.round(((classSize - unmarkedStudents) / 2) + unmarkedStudents); + for (Map.Entry entry : sortedResults.entrySet()) { + if (printIterator == medianCutOff) { + median = entry.getValue(); + } + printIterator += 1; + } + if (unmarkedStudents <= 0) { + ui.printMessage(String.format(MESSAGE_FORMAT_MEDIAN_MARKS, assessmentName, median)); + } else { + ui.printMessage(String.format(MESSAGE_FORMAT_MEDIAN_MARKS_WITH_UNMARKED, + assessmentName, median, (int) unmarkedStudents)); + } + } + + /** + * Returns the usage message of the command. + * + * @return String which contains the usage message. + */ + @Override + protected String getUsage() { + return String.format( + MESSAGE_FORMAT_MEDIAN_MARKS_USAGE, + COMMAND_MEDIAN_MARK, + KEY_MODULE_CODE, + KEY_ASSESSMENT_NAME + ); + } +} From 2837d425c25275fc55603ed4c62419338ce16b09 Mon Sep 17 00:00:00 2001 From: Jon-the-MELON Date: Tue, 26 Oct 2021 00:34:51 +0800 Subject: [PATCH 201/543] Fix formatting errors --- src/main/java/taa/command/MedianMarkCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/taa/command/MedianMarkCommand.java b/src/main/java/taa/command/MedianMarkCommand.java index 9af4357a2b..0f5c66922f 100644 --- a/src/main/java/taa/command/MedianMarkCommand.java +++ b/src/main/java/taa/command/MedianMarkCommand.java @@ -100,13 +100,13 @@ private void printMedianMarks(Ui ui, Module module, Assessment assessment, Array unmarkedStudents += 1; } } + int medianCutOff = (int) Math.round(((classSize - unmarkedStudents) / 2) + unmarkedStudents); List> list = new LinkedList<>(unsortedResults.entrySet()); list.sort(Map.Entry.comparingByValue()); HashMap sortedResults = new LinkedHashMap<>(); for (Map.Entry item : list) { sortedResults.put(item.getKey(), item.getValue()); } - int medianCutOff = (int) Math.round(((classSize - unmarkedStudents) / 2) + unmarkedStudents); for (Map.Entry entry : sortedResults.entrySet()) { if (printIterator == medianCutOff) { median = entry.getValue(); From 9f7f0524aa5ed385dcd957c96381bd1ed6cac478 Mon Sep 17 00:00:00 2001 From: Leyond Date: Tue, 26 Oct 2021 14:01:19 +0800 Subject: [PATCH 202/543] Make sequence diagrams simplier --- docs/diagrams/AddModuleSequenceDiagram.png | Bin 71753 -> 48032 bytes docs/diagrams/AddModuleSequenceDiagram.puml | 19 ------------------ docs/diagrams/ArchitectureSequenceDiagram.png | Bin 75382 -> 54066 bytes .../diagrams/ArchitectureSequenceDiagram.puml | 19 ------------------ 4 files changed, 38 deletions(-) diff --git a/docs/diagrams/AddModuleSequenceDiagram.png b/docs/diagrams/AddModuleSequenceDiagram.png index 58ec7d1ff984873a0da571f8b2e5bf7ac4d5a8bf..ad20b28b9fdbc9575c1e1368960a2841367ae7e2 100644 GIT binary patch literal 48032 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 literal 71753 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 diff --git a/docs/diagrams/AddModuleSequenceDiagram.puml b/docs/diagrams/AddModuleSequenceDiagram.puml index 9f7c3a923a..7c5ff0ce84 100644 --- a/docs/diagrams/AddModuleSequenceDiagram.puml +++ b/docs/diagrams/AddModuleSequenceDiagram.puml @@ -33,15 +33,7 @@ deactivate parser taa -> addModuleCommand : checkArguments() activate addModuleCommand -alt Exception -addModuleCommand --> taa : throw :TaaException -taa -> ui : printException(message:String) -activate ui -ui -> user : Display Exception message -ui --> taa -deactivate ui -else else addModuleCommand --> taa deactivate addModuleCommand @@ -54,15 +46,6 @@ activate moduleList moduleList --> addModuleCommand : module:Module deactivate moduleList -alt module != null -addModuleCommand --> taa : throw :TaaException -taa -> ui : printException(message:String) -activate ui -ui -> user : Display Exception message -ui --> taa -deactivate ui - -else else create module addModuleCommand -> module activate module @@ -86,7 +69,5 @@ ui --> addModuleCommand deactivate ui deactivate addModuleCommand -end -end @enduml \ No newline at end of file diff --git a/docs/diagrams/ArchitectureSequenceDiagram.png b/docs/diagrams/ArchitectureSequenceDiagram.png index 895f6b8bce3423a1ee6d0fffb6a9167183a1bb9c..48a8d1b5dd8a931119cee40e9e2b680d7e906aab 100644 GIT binary patch literal 54066 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