diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 0f072953ea..ebde276cf4 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -2,8 +2,11 @@ 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) | Jia Ern | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Zhu Zeyu | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Jane Ng | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Don Joe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | Ron John | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) ![](https://via.placeholder.com/100.png?text=Photo) | John Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) -![](https://via.placeholder.com/100.png?text=Photo) | Don Roe | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Jiayi Zhang | [Github](https://github.com/) | [Portfolio](docs/team/johndoe.md) +![](https://via.placeholder.com/100.png?text=Photo) | Tan Yan An | [Github](https://github.com/Darticune) | [Portfolio](docs/team/yanAn.md) diff --git a/docs/_config.yml b/docs/_config.yml new file mode 100644 index 0000000000..c741881743 --- /dev/null +++ b/docs/_config.yml @@ -0,0 +1 @@ +theme: jekyll-theme-slate \ No newline at end of file diff --git a/questions.txt b/questions.txt new file mode 100644 index 0000000000..3ac230ec09 --- /dev/null +++ b/questions.txt @@ -0,0 +1 @@ +[Q] da | [A] da diff --git a/src/main/java/Kaji.java b/src/main/java/Kaji.java new file mode 100644 index 0000000000..6fca5db1fe --- /dev/null +++ b/src/main/java/Kaji.java @@ -0,0 +1,58 @@ +import access.Access; +import commands.Command; +import exception.InvalidInputException; +import manager.admin.Admin; +import manager.chapter.CardList; +import parser.Parser; +import storage.Storage; +import ui.Ui; + +import java.io.FileNotFoundException; +import java.io.IOException; + +public class Kaji { + private CardList cards; + private Ui ui; + private Access access; + private Storage storage; + + + public Kaji(String filePath) { + ui = new Ui(); + cards = new CardList(); + storage = new Storage(filePath); + try { + Admin admin = new Admin(storage.loadModule()); + access = new Access(admin); + } catch (FileNotFoundException e) { + storage.createAdmin(); + access = new Access(); + } + } + + public void run() { + ui.showWelcome(); + ui.showHelpList(); + boolean isExit = false; + Storage.getFileContents(cards); + while (!isExit) { + try { + ui.showLevel(access); + String fullCommand = ui.readCommand(); + Command c = Parser.parse(fullCommand); + c.execute(cards, ui, access, storage); + ui.printEmptyLine(); + Storage.writeToFile(cards); + isExit = c.isExit(); + } catch (InvalidInputException e) { + System.out.println("Invalid input given.\n"); + } catch (IOException e) { + System.out.println(" Something went wrong: " + e.getMessage()); + } + } + } + + public static void main(String[] args) { + new Kaji("data/admin").run(); + } +} diff --git a/src/main/java/access/Access.java b/src/main/java/access/Access.java new file mode 100644 index 0000000000..a553ba9c36 --- /dev/null +++ b/src/main/java/access/Access.java @@ -0,0 +1,161 @@ +package access; + +import manager.admin.Admin; +import manager.chapter.Chapter; +import manager.module.Module; + +public class Access { + protected String level; + protected String adminLevel; + protected String moduleLevel; + protected String chapterLevel; + protected Chapter chapter; + protected Module module; + protected Admin admin; + protected boolean isAdminLevel; + protected boolean isModuleLevel; + protected boolean isChapterLevel; + + public Access(Admin admin) { + this.admin = admin; + this.module = null; + this.chapter = null; + this.level = "admin"; + this.adminLevel = "admin"; + this.moduleLevel = ""; + this.chapterLevel = ""; + this.isAdminLevel = true; + this.isModuleLevel = false; + this.isChapterLevel = false; + } + + public Access() { + this.level = "admin"; + this.adminLevel = "admin"; + this.moduleLevel = ""; + this.chapterLevel = ""; + this.module = null; + this.chapter = null; + this.admin = new Admin(); + this.isAdminLevel = true; + this.isModuleLevel = false; + this.isChapterLevel = false; + } + + public String getModuleLevel() { + return moduleLevel; + } + + public String getLevel() { + return level; + } + + public String getChapterLevel() { + return chapterLevel; + } + + public Module getModule() { + return module; + } + + public Chapter getChapter() { + return chapter; + } + + public Admin getAdmin() { + return admin; + } + + public void setAdmin(Admin admin) { + this.admin = admin; + } + + public void setModule(Module module) { + this.module = module; + } + + public void setChapter(Chapter chapter) { + this.chapter = chapter; + } + + public boolean isAdminLevel() { + return isAdminLevel; + } + + public boolean isModuleLevel() { + return isModuleLevel; + } + + public boolean isChapterLevel() { + return isChapterLevel; + } + + public void setModuleLevel(String moduleLevel) { + if (isChapterLevel) { + System.out.println("Sorry, you currently are in the chapter level."); + return; + } + + if (isModuleLevel) { + if (!(moduleLevel.equals(""))) { + System.out.println("Sorry, you are already in the module level, " + + "please go back to admin level first."); + return; + } + + String replacement = "/" + this.moduleLevel; + this.level = level.replace(replacement, ""); + this.moduleLevel = moduleLevel; + this.module = null; + this.isModuleLevel = false; + this.isAdminLevel = true; + return; + } + + if (isAdminLevel) { + if (moduleLevel.equals("")) { + System.out.println("Sorry, you are already in the admin level."); + return; + } + this.moduleLevel = moduleLevel; + this.level = level + "/" + moduleLevel; + this.module = new Module(moduleLevel); + this.isModuleLevel = true; + this.isAdminLevel = false; + } + } + + public void setChapterLevel(String chapterLevel) { + if (isAdminLevel) { //wrong level + System.out.println("Sorry, you currently are in the admin level."); + return; + } + + if (isChapterLevel) { + if (!(chapterLevel.equals(""))) { + System.out.println("Sorry, you are already in the chapter level, " + + "please go back to module level first."); + return; + } + String replacement = "/" + this.chapterLevel; + this.level = level.replace(replacement, ""); + this.chapterLevel = chapterLevel; + this.chapter = null; + this.isChapterLevel = false; + this.isModuleLevel = true; + return; + } + + if (isModuleLevel) { + if (chapterLevel.equals("")) { + System.out.println("Sorry, you are already in the module level."); + return; + } + this.chapterLevel = chapterLevel; + this.level = level + "/" + chapterLevel; + this.chapter = new Chapter(chapterLevel); + this.isChapterLevel = true; + this.isModuleLevel = false; + } + } +} \ No newline at end of file diff --git a/src/main/java/commands/AddChapterCommand.java b/src/main/java/commands/AddChapterCommand.java new file mode 100644 index 0000000000..b421450b8a --- /dev/null +++ b/src/main/java/commands/AddChapterCommand.java @@ -0,0 +1,41 @@ +package commands; + +import manager.chapter.CardList; +import manager.chapter.Chapter; +import manager.module.ChapterList; +import manager.module.Module; +import access.Access; +import storage.Storage; +import ui.Ui; + +public class AddChapterCommand extends Command { + public static final String COMMAND_WORD = "addchapter"; + private final Chapter chapter; + + public AddChapterCommand(String chapterCode) { + this.chapter = new Chapter(chapterCode); + } + + @Override + public void execute(CardList cards, Ui ui, Access access, Storage storage) { + if (access.isAdminLevel() || access.isChapterLevel()) { + System.out.println("Sorry, you currently are in the admin/chapter level, " + + "please go to module level first."); + return; + } + + Module newModule = access.getModule(); + ChapterList chapters = newModule.getChapters(); + chapters.addChapter(chapter); + int chapterCount = chapters.getChapterCount(); + ui.showChapterAdded(chapter, chapterCount); + access.setModule(newModule); + storage.createChapter(chapter.getChapterName(), access.getModuleLevel()); + } + + @Override + public boolean isExit() { + return false; + } +} + diff --git a/src/main/java/commands/AddCommand.java b/src/main/java/commands/AddCommand.java new file mode 100644 index 0000000000..a04fbf43e2 --- /dev/null +++ b/src/main/java/commands/AddCommand.java @@ -0,0 +1,41 @@ +package commands; + +import access.Access; +import manager.card.Card; +import manager.chapter.CardList; +import storage.Storage; +import ui.Ui; + +public class AddCommand extends Command { + public static final String COMMAND_WORD = "add"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a flashcard to the schedule manager. \n" + + "Parameters: q:QUESTION | a:ANSWER\n" + + "Example: " + COMMAND_WORD + " q:What is the result of one plus one | a:two\n"; + + public static final String QUESTION_ANSWER_PREFIX = " \\| "; + public static final String QUESTION_PREFIX = "q:"; + public static final String ANSWER_PREFIX = "a:"; + + private final Card card; + + public AddCommand(String question, String answer) { + this.card = new Card(question, answer); + } + + @Override + public void execute(CardList cards, Ui ui, Access access, Storage storage) { + if (access.getChapterLevel().equals("")) { + System.out.println("Sorry, you currently are in the wrong level, please enter chapter level first."); + return; + } + cards.addCard(card); + int cardCount = cards.getCardCount(); + ui.showCardAdded(cards.getCard(cardCount - 1), cardCount); + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/commands/AddModuleCommand.java b/src/main/java/commands/AddModuleCommand.java new file mode 100644 index 0000000000..c9a3759f21 --- /dev/null +++ b/src/main/java/commands/AddModuleCommand.java @@ -0,0 +1,40 @@ +package commands; + +import access.Access; +import manager.admin.Admin; +import manager.admin.ModuleList; +import manager.chapter.CardList; +import manager.module.Module; +import storage.Storage; +import ui.Ui; + +public class AddModuleCommand extends Command { + public static final String COMMAND_WORD = "addmodule"; + private final Module module; + + public AddModuleCommand(String moduleCode) { + this.module = new Module(moduleCode); + } + + @Override + public void execute(CardList cards, Ui ui, Access access, Storage storage) { + if (access.isModuleLevel() || access.isChapterLevel()) { + System.out.println("Sorry, you currently are in the module/chapter level, " + + "please go to admin level first."); + return; + } + + Admin newAdmin = access.getAdmin(); + ModuleList modules = newAdmin.getModules(); + modules.addModule(module); + int moduleCount = modules.getModuleCount(); + ui.showModuleAdded(module, moduleCount); + access.setAdmin(newAdmin); + storage.createModule(module.getModuleName()); + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/commands/BackChapterCommand.java b/src/main/java/commands/BackChapterCommand.java new file mode 100644 index 0000000000..ef26ff1bce --- /dev/null +++ b/src/main/java/commands/BackChapterCommand.java @@ -0,0 +1,20 @@ +package commands; + +import access.Access; +import manager.chapter.CardList; +import storage.Storage; +import ui.Ui; + +public class BackChapterCommand extends Command { + public static final String COMMAND_WORD = "backchapter"; + + @Override + public void execute(CardList cards, Ui ui, Access access, Storage storage) { + access.setChapterLevel(""); + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/commands/BackModuleCommand.java b/src/main/java/commands/BackModuleCommand.java new file mode 100644 index 0000000000..c5fe3afd2b --- /dev/null +++ b/src/main/java/commands/BackModuleCommand.java @@ -0,0 +1,20 @@ +package commands; + +import access.Access; +import manager.chapter.CardList; +import storage.Storage; +import ui.Ui; + +public class BackModuleCommand extends Command { + public static final String COMMAND_WORD = "backmodule"; + + @Override + public void execute(CardList cards, Ui ui, Access access, Storage storage) { + access.setModuleLevel(""); + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/commands/Command.java b/src/main/java/commands/Command.java new file mode 100644 index 0000000000..b20f77ff33 --- /dev/null +++ b/src/main/java/commands/Command.java @@ -0,0 +1,13 @@ +package commands; + +import access.Access; +import manager.chapter.CardList; +import storage.Storage; +import ui.Ui; + +public abstract class Command { + + public abstract void execute(CardList cards, Ui ui, Access access, Storage storage); + + public abstract boolean isExit(); +} diff --git a/src/main/java/commands/ExitCommand.java b/src/main/java/commands/ExitCommand.java new file mode 100644 index 0000000000..94fc24a056 --- /dev/null +++ b/src/main/java/commands/ExitCommand.java @@ -0,0 +1,23 @@ +package commands; + +import access.Access; +import manager.chapter.CardList; +import storage.Storage; +import ui.Ui; + +public class ExitCommand extends Command { + public static final String COMMAND_WORD = "exit"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Exits the program. \n" + + "Example: " + COMMAND_WORD + "\n"; + + @Override + public void execute(CardList cards, Ui ui, Access access, Storage storage) { + ui.showExit(); + } + + @Override + public boolean isExit() { + return true; + } +} diff --git a/src/main/java/commands/GoChapterCommand.java b/src/main/java/commands/GoChapterCommand.java new file mode 100644 index 0000000000..82a023a16e --- /dev/null +++ b/src/main/java/commands/GoChapterCommand.java @@ -0,0 +1,54 @@ +package commands; + +import manager.card.Card; +import manager.chapter.CardList; +import access.Access; +import manager.chapter.Chapter; +import manager.module.ChapterList; +import storage.Storage; +import ui.Ui; + +import java.io.FileNotFoundException; +import java.util.ArrayList; + +public class GoChapterCommand extends Command { + public static final String COMMAND_WORD = "gochapter"; + String chapterCode; + + public GoChapterCommand(String chapterCode) { + this.chapterCode = chapterCode; + } + + @Override + public void execute(CardList cards, Ui ui, Access access, Storage storage) { + boolean isLevelExist = false; + ChapterList chapters = access.getModule().getChapters(); + ArrayList allChapters = chapters.getAllChapters(); + for (Chapter chapter : allChapters) { + if (chapterCode.equalsIgnoreCase(chapter.getChapterName())) { + access.setChapterLevel(chapterCode); + isLevelExist = true; + try { + ArrayList allCards = storage.loadCard(access.getModuleLevel(), chapter.getChapterName()); + if (allCards.size() == 0) { + System.out.println("This is a new chapter, you can try to add flashcards inside!"); + } + chapter.setCards(allCards); + access.setChapter(chapter); + } catch (FileNotFoundException e) { + System.out.println("The chapter file cannot be found."); + } + break; + } + } + if (isLevelExist == false) { + System.out.println("Sorry, I cannot find this chapter, please add this chapter first"); + } + } + + @Override + public boolean isExit() { + return false; + } +} + diff --git a/src/main/java/commands/GoModuleCommand.java b/src/main/java/commands/GoModuleCommand.java new file mode 100644 index 0000000000..026f59ced7 --- /dev/null +++ b/src/main/java/commands/GoModuleCommand.java @@ -0,0 +1,53 @@ +package commands; + +import access.Access; +import manager.admin.ModuleList; +import manager.chapter.CardList; +import manager.chapter.Chapter; +import manager.module.Module; +import storage.Storage; +import ui.Ui; + +import java.io.FileNotFoundException; +import java.util.ArrayList; + +public class GoModuleCommand extends Command { + public static final String COMMAND_WORD = "gomodule"; + String moduleCode; + + public GoModuleCommand(String moduleCode) { + this.moduleCode = moduleCode; + } + + @Override + public void execute(CardList cards, Ui ui, Access access, Storage storage) { + boolean isLevelExist = false; + ModuleList modules = access.getAdmin().getModules(); + ArrayList allModules = modules.getAllModules(); + for (Module module : allModules) { + if (moduleCode.equalsIgnoreCase(module.getModuleName())) { + access.setModuleLevel(moduleCode); + isLevelExist = true; + try { + ArrayList chapters = storage.loadChapter(module.getModuleName()); + if (chapters.size() == 0) { + System.out.println("This is a new module, you can try to add chapters inside!"); + } + module.setChapters(chapters); + access.setModule(module); + } catch (FileNotFoundException e) { + System.out.println("The module folder cannot be found."); + } + break; + } + } + if (isLevelExist == false) { + System.out.println("Sorry, I cannot find this module, please add this module first"); + } + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/commands/HelpCommand.java b/src/main/java/commands/HelpCommand.java new file mode 100644 index 0000000000..fb8be27fd4 --- /dev/null +++ b/src/main/java/commands/HelpCommand.java @@ -0,0 +1,23 @@ +package commands; + +import access.Access; +import manager.chapter.CardList; +import storage.Storage; +import ui.Ui; + +public class HelpCommand extends Command { + public static final String COMMAND_WORD = "help"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows a list of commands available. \n" + + "Example: " + COMMAND_WORD + "\n"; + + @Override + public void execute(CardList cards, Ui ui, Access access, Storage storage) { + ui.showHelpList(); + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/commands/ListCommand.java b/src/main/java/commands/ListCommand.java new file mode 100644 index 0000000000..537d721f7e --- /dev/null +++ b/src/main/java/commands/ListCommand.java @@ -0,0 +1,28 @@ +package commands; + +import access.Access; +import manager.card.Card; +import manager.chapter.CardList; +import storage.Storage; +import ui.Ui; + +import java.util.ArrayList; + +public class ListCommand extends Command { + public static final String COMMAND_WORD = "list"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Shows a list of flashcards available. \n" + + "Example: " + COMMAND_WORD + "\n"; + + @Override + public void execute(CardList cards, Ui ui, Access access, Storage storage) { + ArrayList allCards = cards.getAllCards(); + int cardCount = cards.getCardCount(); + ui.showCardList(allCards, cardCount); + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/commands/RemoveCommand.java b/src/main/java/commands/RemoveCommand.java new file mode 100644 index 0000000000..ad4fd7027b --- /dev/null +++ b/src/main/java/commands/RemoveCommand.java @@ -0,0 +1,40 @@ +package commands; + +import access.Access; +import manager.card.Card; +import manager.chapter.CardList; +import storage.Storage; +import ui.Ui; + +public class RemoveCommand extends Command { + public static final String COMMAND_WORD = "remove"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + + ": Removes flashcard based on a specified index in the list. \n" + + "Parameters: INDEX\n" + "Example: " + COMMAND_WORD + " 2\n"; + + public static final String MESSAGE_SUCCESS = "The following flashcard has been removed:\n"; + public static final String MESSAGE_INVALID_INDEX = "The flashcard is not found, please try again."; + + private final int removeIndex; + + public RemoveCommand(int removeIndex) { + this.removeIndex = removeIndex; + } + + @Override + public void execute(CardList cards, Ui ui, Access access, Storage storage) { + try { + Card card = cards.getCard(removeIndex); + ui.showToUser(MESSAGE_SUCCESS + card.toString()); + cards.removeCard(removeIndex); + } catch (IndexOutOfBoundsException e) { + ui.showToUser(MESSAGE_INVALID_INDEX); + } + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/commands/ReviseCommand.java b/src/main/java/commands/ReviseCommand.java new file mode 100644 index 0000000000..404616fec6 --- /dev/null +++ b/src/main/java/commands/ReviseCommand.java @@ -0,0 +1,116 @@ +package commands; + +import access.Access; +import manager.card.Card; +import manager.chapter.CardList; +import manager.chapter.Chapter; +import scheduler.Scheduler; +import storage.Storage; +import ui.Ui; + +import java.util.ArrayList; + + +/** + * Starts revision for a particular chapter. + */ +public class ReviseCommand extends Command { + public static final String COMMAND_WORD = "revise"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Starts revision based on a particular chapter. \n" + + "Parameters: CHAPTER_NAME\n" + "Example: " + COMMAND_WORD + " Polymorphism\n"; + + public static final String MESSAGE_SUCCESS = "You have completed revision for %1$s."; + public static final String MESSAGE_NO_CARDS_IN_CHAPTER = "You currently have no cards in %1$s."; + public static final String MESSAGE_NO_CARDS_DUE = "You have no cards due for revision in %1$s today."; + public static final String MESSAGE_SHOW_ANSWER_PROMPT = "\n[enter s to show answer]"; + public static final String MESSAGE_SHOW_RATING_PROMPT = "How well did you do for this card?\n" + + "[enter e(easy), m(medium), h(hard), c(cannot answer)]"; + public static final String EASY = "e"; + public static final String MEDIUM = "m"; + public static final String HARD = "h"; + public static final String CANNOT_ANSWER = "c"; + + private final Chapter toRevise; + + public ReviseCommand(String toRevise) { + this.toRevise = new Chapter(toRevise); + } + + @Override + public void execute(CardList cards, Ui ui, Access access, Storage storage) { + ArrayList allCards = cards.getAllCards(); + ArrayList repeatCards = new ArrayList<>(); + int cardCount = cards.getCardCount(); + if (cardCount == 0) { + ui.showToUser(String.format(MESSAGE_NO_CARDS_IN_CHAPTER, toRevise)); + return; + } + ui.showToUser("The revision for " + toRevise + " will start now:"); + int count = 1; + for (Card c : allCards) { + if (Scheduler.isDeadlineDue(c.getDueBy())) { + ui.showToUser("\nQuestion " + count + ":"); + ui.showCard(c); + String input = ui.getRating(); + repeatCards = rateCard(ui, repeatCards, c, input); + count++; + } + } + if (count == 1) { + ui.showToUser(String.format(MESSAGE_NO_CARDS_DUE, toRevise)); + return; + } + + repeatRevision(ui, repeatCards, count); + ui.showToUser(String.format(MESSAGE_SUCCESS, toRevise)); + } + + public static ArrayList rateCard(Ui ui, ArrayList repeatCards, Card c, String input) { + boolean isInvalid = true; + while (isInvalid) { + switch (input.toLowerCase()) { + case EASY: + c.setDueBy(Scheduler.computeEasyDeadline(c.getPreviousInterval())); + isInvalid = false; + break; + case MEDIUM: + c.setDueBy(Scheduler.computeMediumDeadline(c.getPreviousInterval())); + isInvalid = false; + break; + case HARD: + c.setDueBy(Scheduler.computeHardDeadline(c.getPreviousInterval())); + isInvalid = false; + break; + case CANNOT_ANSWER: + repeatCards.add(c); + isInvalid = false; + break; + default: + ui.showToUser("You have entered an invalid input, please try again."); + input = ui.getRating(); + } + } + return repeatCards; + } + + private void repeatRevision(Ui ui, ArrayList cards, int count) { + while (cards.size() != 0) { + System.out.println(cards.size()); + ArrayList repeatCards = new ArrayList<>(); + for (Card c : cards) { + ui.showToUser("\nQuestion " + count + ":"); + ui.showCard(c); + String input = ui.getRating(); + repeatCards = rateCard(ui, repeatCards, c, input); + count++; + } + cards = new ArrayList<>(repeatCards); + } + } + + @Override + public boolean isExit() { + return false; + } +} diff --git a/src/main/java/exception/InvalidFileFormatException.java b/src/main/java/exception/InvalidFileFormatException.java new file mode 100644 index 0000000000..bc6cc54e1d --- /dev/null +++ b/src/main/java/exception/InvalidFileFormatException.java @@ -0,0 +1,4 @@ +package exception; + +public class InvalidFileFormatException extends Exception { +} diff --git a/src/main/java/exception/InvalidInputException.java b/src/main/java/exception/InvalidInputException.java new file mode 100644 index 0000000000..1ef1ba5156 --- /dev/null +++ b/src/main/java/exception/InvalidInputException.java @@ -0,0 +1,4 @@ +package exception; + +public class InvalidInputException extends Exception { +} diff --git a/src/main/java/manager/admin/Admin.java b/src/main/java/manager/admin/Admin.java new file mode 100644 index 0000000000..50ef275714 --- /dev/null +++ b/src/main/java/manager/admin/Admin.java @@ -0,0 +1,23 @@ +package manager.admin; + +import manager.module.Module; + +import java.util.ArrayList; + +public class Admin { + protected ModuleList modules; + + //if there is no storage + public Admin() { + modules = new ModuleList(); + } + + //if there is storage + public Admin(ArrayList modules) { + this.modules = new ModuleList(modules); + } + + public ModuleList getModules() { + return modules; + } +} diff --git a/src/main/java/manager/admin/ModuleList.java b/src/main/java/manager/admin/ModuleList.java new file mode 100644 index 0000000000..fa9c6e1ab1 --- /dev/null +++ b/src/main/java/manager/admin/ModuleList.java @@ -0,0 +1,29 @@ +package manager.admin; + +import manager.module.Module; + +import java.util.ArrayList; + +public class ModuleList { + private final ArrayList modules; + + public ModuleList() { + modules = new ArrayList<>(); + } + + public ModuleList(ArrayList modules) { + this.modules = modules; + } + + public void addModule(Module module) { + modules.add(module); + } + + public ArrayList getAllModules() { + return modules; + } + + public int getModuleCount() { + return modules.size(); + } +} diff --git a/src/main/java/manager/card/Card.java b/src/main/java/manager/card/Card.java new file mode 100644 index 0000000000..89fbf69b0f --- /dev/null +++ b/src/main/java/manager/card/Card.java @@ -0,0 +1,41 @@ +package manager.card; + +import java.time.LocalDate; + +public class Card { + private String question; + private String answer; + private int previousInterval; + private LocalDate dueBy; + + public Card(String question, String answer) { + this.question = question; + this.answer = answer; + this.dueBy = LocalDate.now(); + this.previousInterval = 1; + } + + public String getQuestion() { + return "[Q] " + question; + } + + public String getAnswer() { + return "[A] " + answer; + } + + public LocalDate getDueBy() { + return dueBy; + } + + public int getPreviousInterval() { + return previousInterval; + } + + public void setDueBy(LocalDate newDueBy) { + dueBy = newDueBy; + } + + public String toString() { + return "[Q] " + question + " | [A] " + answer; + } +} diff --git a/src/main/java/manager/chapter/CardList.java b/src/main/java/manager/chapter/CardList.java new file mode 100644 index 0000000000..095cb206c3 --- /dev/null +++ b/src/main/java/manager/chapter/CardList.java @@ -0,0 +1,37 @@ +package manager.chapter; + +import manager.card.Card; + +import java.util.ArrayList; + +public class CardList { + private final ArrayList cards; + + public CardList() { + this.cards = new ArrayList<>(); + } + + public CardList(ArrayList cards) { + this.cards = new ArrayList<>(cards); + } + + public void addCard(Card card) { + cards.add(card); + } + + public void removeCard(int removeIndex) { + cards.remove(removeIndex); + } + + public int getCardCount() { + return cards.size(); + } + + public Card getCard(int cardIndex) { + return cards.get(cardIndex); + } + + public ArrayList getAllCards() { + return cards; + } +} diff --git a/src/main/java/manager/chapter/Chapter.java b/src/main/java/manager/chapter/Chapter.java new file mode 100644 index 0000000000..e9bccff7f1 --- /dev/null +++ b/src/main/java/manager/chapter/Chapter.java @@ -0,0 +1,28 @@ +package manager.chapter; + +import manager.card.Card; + +import java.util.ArrayList; + +public class Chapter { + protected String chapterName; + protected CardList cards; + + public Chapter(String chapterName) { + this.chapterName = chapterName; + this.cards = new CardList(); + } + + public String getChapterName() { + return chapterName; + } + + public void setCards(ArrayList cards) { + this.cards = new CardList(cards); + } + + @Override + public String toString() { + return chapterName; + } +} diff --git a/src/main/java/manager/module/ChapterList.java b/src/main/java/manager/module/ChapterList.java new file mode 100644 index 0000000000..01055df847 --- /dev/null +++ b/src/main/java/manager/module/ChapterList.java @@ -0,0 +1,29 @@ +package manager.module; + +import manager.chapter.Chapter; + +import java.util.ArrayList; + +public class ChapterList { + private final ArrayList chapters; + + public ChapterList() { + chapters = new ArrayList<>(); + } + + public ChapterList(ArrayList chapters) { + this.chapters = chapters; + } + + public void addChapter(Chapter chapter) { + chapters.add(chapter); + } + + public ArrayList getAllChapters() { + return chapters; + } + + public int getChapterCount() { + return chapters.size(); + } +} diff --git a/src/main/java/manager/module/Module.java b/src/main/java/manager/module/Module.java new file mode 100644 index 0000000000..0c01387f37 --- /dev/null +++ b/src/main/java/manager/module/Module.java @@ -0,0 +1,37 @@ +package manager.module; + +import manager.chapter.Chapter; + +import java.util.ArrayList; + +public class Module { + protected ChapterList chapters; + protected String moduleName; + + public Module(String moduleName) { + this.moduleName = moduleName; + chapters = new ChapterList(); + } + + public Module(String moduleName, ArrayList chapters) { + this.moduleName = moduleName; + this.chapters = new ChapterList(chapters); + } + + + public String getModuleName() { + return moduleName; + } + + public ChapterList getChapters() { + return chapters; + } + + public void setChapters(ArrayList chapters) { + this.chapters = new ChapterList(chapters); + } + + public String toString() { + return moduleName; + } +} \ No newline at end of file diff --git a/src/main/java/parser/Parser.java b/src/main/java/parser/Parser.java new file mode 100644 index 0000000000..f9a37196e2 --- /dev/null +++ b/src/main/java/parser/Parser.java @@ -0,0 +1,211 @@ +package parser; + +import commands.Command; +import commands.ListCommand; +import commands.AddChapterCommand; +import commands.AddCommand; +import commands.AddModuleCommand; +import commands.BackChapterCommand; +import commands.GoChapterCommand; +import commands.HelpCommand; +import commands.RemoveCommand; +import commands.ReviseCommand; +import commands.ExitCommand; +import commands.GoModuleCommand; +import commands.BackModuleCommand; + +import exception.InvalidFileFormatException; +import exception.InvalidInputException; +import storage.Storage; + + +public class Parser { + public static Command parse(String fullCommand) throws InvalidInputException { + String[] commandTypeAndArgs = splitCommandTypeAndArgs(fullCommand); + String commandType = commandTypeAndArgs[0].trim().toLowerCase(); + String commandArgs = commandTypeAndArgs[1].trim(); + + switch (commandType) { + case ListCommand.COMMAND_WORD: + return prepareList(commandArgs); + case AddCommand.COMMAND_WORD: + return prepareAdd(commandArgs); + case RemoveCommand.COMMAND_WORD: + return prepareRemove(commandArgs); + case ReviseCommand.COMMAND_WORD: + return prepareRevise(commandArgs); + case ExitCommand.COMMAND_WORD: + return prepareExit(commandArgs); + case HelpCommand.COMMAND_WORD: + return prepareHelp(commandArgs); + case AddModuleCommand.COMMAND_WORD: + return prepareAddModule(commandArgs); + case AddChapterCommand.COMMAND_WORD: + return prepareAddChapter(commandArgs); + case BackModuleCommand.COMMAND_WORD: + return prepareBackModule(commandArgs); + case BackChapterCommand.COMMAND_WORD: + return prepareBackChapter(commandArgs); + case GoModuleCommand.COMMAND_WORD: + return prepareGoModule(commandArgs); + case GoChapterCommand.COMMAND_WORD: + return prepareGoChapter(commandArgs); + default: + throw new InvalidInputException(); + } + } + + private static Command prepareGoChapter(String commandArgs) throws InvalidInputException { + if (commandArgs.isEmpty()) { + throw new InvalidInputException(); + } + return new GoChapterCommand(commandArgs); + } + + private static Command prepareGoModule(String commandArgs) throws InvalidInputException { + if (commandArgs.isEmpty()) { + throw new InvalidInputException(); + } + return new GoModuleCommand(commandArgs); + } + + private static Command prepareBackChapter(String commandArgs) throws InvalidInputException { + if (!commandArgs.isEmpty()) { + throw new InvalidInputException(); + } + return new BackChapterCommand(); + } + + private static Command prepareBackModule(String commandArgs) throws InvalidInputException { + if (!commandArgs.isEmpty()) { + throw new InvalidInputException(); + } + return new BackModuleCommand(); + } + + private static Command prepareAddChapter(String commandArgs) throws InvalidInputException { + if (commandArgs.isEmpty()) { + throw new InvalidInputException(); + } + return new AddChapterCommand(commandArgs); + } + + private static Command prepareAddModule(String commandArgs) throws InvalidInputException { + if (commandArgs.isEmpty()) { + throw new InvalidInputException(); + } + return new AddModuleCommand(commandArgs); + } + + private static String[] splitCommandTypeAndArgs(String userCommand) { + String[] commandTypeAndParams = userCommand.trim().split(" ", 2); + if (commandTypeAndParams.length != 2) { + commandTypeAndParams = new String[]{commandTypeAndParams[0], ""}; + } + return commandTypeAndParams; + } + + private static Command prepareList(String commandArgs) throws InvalidInputException { + if (!commandArgs.isEmpty()) { + throw new InvalidInputException(); + } + return new ListCommand(); + } + + private static Command prepareAdd(String commandArgs) throws InvalidInputException { + try { + String[] args = commandArgs.split(AddCommand.QUESTION_ANSWER_PREFIX, 2); + String question = parseQuestion(args[0]); + String answer = parseAnswer(args[1]); + return new AddCommand(question, answer); + } catch (IndexOutOfBoundsException | InvalidInputException e) { + throw new InvalidInputException(); + } + } + + private static Command prepareRemove(String commandArgs) throws InvalidInputException { + int removeIndex; + if (commandArgs.isEmpty()) { + throw new InvalidInputException(); + } + try { + removeIndex = Integer.parseInt(commandArgs) - 1; + } catch (NumberFormatException e) { + throw new InvalidInputException(); + } + return new RemoveCommand(removeIndex); + } + + private static String parseQuestion(String arg) throws InvalidInputException { + if (!(arg.trim().toLowerCase().startsWith(AddCommand.QUESTION_PREFIX))) { + throw new InvalidInputException(); + } + + String question = arg.substring(2).trim(); + if (question.isEmpty()) { + throw new InvalidInputException(); + } + + return question; + } + + private static String parseAnswer(String arg) throws InvalidInputException { + if (!(arg.trim().toLowerCase().startsWith(AddCommand.ANSWER_PREFIX))) { + throw new InvalidInputException(); + } + + String answer = arg.substring(2).trim(); + if (answer.isEmpty()) { + throw new InvalidInputException(); + } + + return answer; + } + + private static Command prepareRevise(String commandArgs) throws InvalidInputException { + if (commandArgs.isEmpty()) { + throw new InvalidInputException(); + } + return new ReviseCommand(commandArgs); + } + + private static Command prepareExit(String commandArgs) throws InvalidInputException { + if (!commandArgs.isEmpty()) { + throw new InvalidInputException(); + } + return new ExitCommand(); + } + + private static Command prepareHelp(String commandArgs) throws InvalidInputException { + if (!commandArgs.isEmpty()) { + throw new InvalidInputException(); + } + return new HelpCommand(); + } + + public static String parseQuestioninFile(String arg) throws InvalidFileFormatException { + if (!(arg.trim().startsWith(Storage.QUESTION_PREFIX))) { + throw new InvalidFileFormatException(); + } + + String question = arg.substring(3).trim(); + if (question.isEmpty()) { + throw new InvalidFileFormatException(); + } + + return question; + } + + public static String parseAnswerinFile(String arg) throws InvalidFileFormatException { + if (!(arg.trim().startsWith(Storage.ANSWER_PREFIX))) { + throw new InvalidFileFormatException(); + } + + String answer = arg.substring(3).trim(); + if (answer.isEmpty()) { + throw new InvalidFileFormatException(); + } + + return answer; + } +} diff --git a/src/main/java/scheduler/Scheduler.java b/src/main/java/scheduler/Scheduler.java new file mode 100644 index 0000000000..5461d8381f --- /dev/null +++ b/src/main/java/scheduler/Scheduler.java @@ -0,0 +1,76 @@ +package scheduler; + +import java.time.LocalDate; +import java.lang.Math; + +public class Scheduler { + public static final double EASY_MULTIPLIER = 1.1; + public static final double MEDIUM_MULTIPLIER = 2.2; + public static final double HARD_MULTIPLIER = 4.4; + public static final int MAX_INTERVAL = 365; + + public static boolean isDeadlineDue(LocalDate dueBy) { + return dueBy.isBefore(getCurrentDate()) || dueBy.isEqual(getCurrentDate()); + } + + public static LocalDate getCurrentDate() { + return LocalDate.now(); + } + + public static int computeEasyInterval(int previousInterval) { + int newInterval = (int) Math.round(previousInterval * EASY_MULTIPLIER); + if (newInterval > MAX_INTERVAL) { + return previousInterval; + } else { + return newInterval; + } + } + + public static LocalDate computeEasyDeadline(int previousInterval) { + int interval = computeEasyInterval(previousInterval); + return getCurrentDate().plusDays(interval); + } + + public static int computeMediumInterval(int previousInterval) { + int newInterval = (int) Math.round(previousInterval * MEDIUM_MULTIPLIER); + if (newInterval > MAX_INTERVAL) { + return previousInterval; + } else { + return newInterval; + } + } + + public static LocalDate computeMediumDeadline(int previousInterval) { + int interval = computeMediumInterval(previousInterval); + return getCurrentDate().plusDays(interval); + } + + public static int computeHardInterval(int previousInterval) { + int newInterval = (int) Math.round(previousInterval * HARD_MULTIPLIER); + if (newInterval > MAX_INTERVAL) { + return previousInterval; + } else { + return newInterval; + } + } + + public static LocalDate computeHardDeadline(int previousInterval) { + int interval = computeHardInterval(previousInterval); + return getCurrentDate().plusDays(interval); + } + + public static int computeDeckInterval(double totalMultiplier, int cardCount, int previousInterval) { + double averageMultiplier = (totalMultiplier / cardCount); + int newInterval = (int) Math.round(averageMultiplier * previousInterval); + if (newInterval > MAX_INTERVAL) { + return previousInterval; + } else { + return newInterval; + } + } + + public static LocalDate computeDeckDeadline(double totalMultiplier, int cardCount, int previousInterval) { + int interval = computeDeckInterval(totalMultiplier, cardCount, previousInterval); + return getCurrentDate().plusDays(interval); + } +} diff --git a/src/main/java/seedu/duke/Duke.java b/src/main/java/seedu/duke/Duke.java index 5c74e68d59..9f8063ee94 100644 --- a/src/main/java/seedu/duke/Duke.java +++ b/src/main/java/seedu/duke/Duke.java @@ -18,4 +18,4 @@ public static void main(String[] args) { Scanner in = new Scanner(System.in); System.out.println("Hello " + in.nextLine()); } -} +} \ No newline at end of file diff --git a/src/main/java/storage/Storage.java b/src/main/java/storage/Storage.java new file mode 100644 index 0000000000..472b458613 --- /dev/null +++ b/src/main/java/storage/Storage.java @@ -0,0 +1,174 @@ +package storage; + +import exception.InvalidFileFormatException; +import manager.card.Card; +import manager.chapter.CardList; +import manager.chapter.Chapter; +import parser.Parser; +import manager.module.Module; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Scanner; + +public class Storage { + public static final String FILE_PATHWAY = "questions.txt"; // file pathway + + public static final String QUESTION_ANSWER_PREFIX = " \\| "; + public static final String QUESTION_PREFIX = "[Q]"; + public static final String ANSWER_PREFIX = "[A]"; + + protected String filePath; + + public Storage(String filePath) { + this.filePath = filePath; + } + + //create the folder --> 'data/admin' + public void createAdmin() { + File f = new File(filePath); + System.out.println("Filepath: " + filePath); + + boolean dataDirExists = f.getParentFile().exists(); + boolean dataDirCreated = false; + if (!dataDirExists) { + dataDirCreated = f.getParentFile().mkdir(); + } else { + System.out.println("Directory " + f.getParentFile().getName() + " already exists"); + } + if (dataDirCreated) { + System.out.println("Successfully created new directory " + f.getParentFile().getName()); + } + + boolean adminDirExists = f.exists(); + boolean adminDirCreated = false; + if (!adminDirExists) { + adminDirCreated = f.mkdir(); + } else { + System.out.println("Directory " + f + " already exists"); + } + if (adminDirCreated) { + System.out.println("Successfully created new directory " + f); + } + } + + public void createModule(String moduleName) { + File f = new File(filePath + "/" + moduleName); + boolean moduleDirExists = f.exists(); + boolean moduleDirCreated = false; + if (!moduleDirExists) { + moduleDirCreated = f.mkdir(); + } else { + System.out.println(" Directory " + f + " already exists"); + } + if (moduleDirCreated) { + System.out.println(" Successfully created new directory " + f); + } + } + + public void createChapter(String chapterName, String moduleName) { + try { + File f = new File(filePath + "/" + moduleName + "/" + chapterName + ".txt"); + boolean chapterFileExists = f.exists(); + boolean chapterFileCreated = false; + if (!chapterFileExists) { + chapterFileCreated = f.createNewFile(); + } else { + System.out.println(" File " + f + " already exists"); + } + if (chapterFileCreated) { + System.out.println(" Successfully created new file " + chapterName + ".txt"); + } + } catch (IOException e) { + System.out.println("Error creating the file."); + } + } + + public ArrayList loadModule() throws FileNotFoundException { + File f = new File(filePath); + boolean dirExists = f.exists(); + if (!dirExists) { + throw new FileNotFoundException(); + } + + ArrayList modules = new ArrayList<>(); + String[] contents = f.list(); + System.out.println("List of files and directories in the specified directory:"); + for (int i = 0; i < contents.length; i++) { + System.out.println(contents[i]); + modules.add(new Module(contents[i])); + } + return modules; + } + + public ArrayList loadChapter(String module) throws FileNotFoundException { + File f = new File(filePath + "/" + module); + boolean dirExists = f.exists(); + if (!dirExists) { + throw new FileNotFoundException(); + } + + ArrayList chapters = new ArrayList<>(); + String[] contents = f.list(); + if (contents.length == 0) { + return chapters; + } + System.out.println("List of files and directories in the specified directory:"); + for (int i = 0; i < contents.length; i++) { + String target = contents[i].replace(".txt", ""); + System.out.println(contents[i]); + chapters.add(new Chapter(target)); + } + return chapters; + } + + public ArrayList loadCard(String module, String chapter) throws FileNotFoundException { + File f = new File(filePath + "/" + module + "/" + chapter + ".txt"); + boolean fileExists = f.exists(); + if (!fileExists) { + throw new FileNotFoundException(); + } + + ArrayList cards = new ArrayList<>(); + Scanner s = new Scanner(f); + int totalCards = 0; + while (s.hasNext()) { + //to read the card + } + return cards; + } + + public static void getFileContents(CardList cards) { + try { + File f = new File(FILE_PATHWAY); // create a File for the given file path + Scanner s = new Scanner(f); // create a Scanner using the File as the source + while (s.hasNext()) { + String fileCommand = s.nextLine(); + String[] args = fileCommand.split(QUESTION_ANSWER_PREFIX, 2); + String question = Parser.parseQuestioninFile(args[0]); + String answer = Parser.parseAnswerinFile(args[1]); + Card card = new Card(question, answer); + cards.addCard(card); + } + } catch (FileNotFoundException e) { + System.out.println("File not found"); + } catch (InvalidFileFormatException e) { + System.out.println("The format of some commands in the file is invalid"); + } + } + + public static void writeToFile(CardList cards) throws IOException { + FileWriter fw = new FileWriter(FILE_PATHWAY); + for (int i = 0; i < cards.getCardCount(); i++) { + fw.write(cards.getCard(i).toString() + "\n"); + } + fw.close(); + } + + public String getFilePath() { + return filePath; + } +} diff --git a/src/main/java/ui/Ui.java b/src/main/java/ui/Ui.java new file mode 100644 index 0000000000..161bfb2800 --- /dev/null +++ b/src/main/java/ui/Ui.java @@ -0,0 +1,124 @@ +package ui; + +import access.Access; +import commands.AddCommand; +import commands.ExitCommand; +import commands.ListCommand; +import commands.HelpCommand; +import commands.ReviseCommand; + +import manager.card.Card; +import manager.chapter.Chapter; +import manager.module.Module; + +import java.io.InputStream; +import java.io.PrintStream; +import java.util.ArrayList; +import java.util.Scanner; + +import static commands.ReviseCommand.MESSAGE_SHOW_ANSWER_PROMPT; +import static commands.ReviseCommand.MESSAGE_SHOW_RATING_PROMPT; + +public class Ui { + private final Scanner in; + private final PrintStream out; + private static final String lineSplit = " ____________________________________________________________"; + + public Ui() { + this(System.in, System.out); + } + + public Ui(InputStream in, PrintStream out) { + this.in = new Scanner(in); + this.out = out; + } + + public String readCommand() { + String userCommand = in.nextLine(); + while (userCommand.trim().isEmpty()) { + userCommand = in.nextLine(); + } + return userCommand; + } + + public void showWelcome() { + out.println("Welcome to Kaji!\n"); + } + + public void showLevel(Access access) { + out.println(access.getLevel()); + } + + public void printEmptyLine() { + out.println(); + } + + public void showCardAdded(Card card, int cardCount) { + out.println("Got it. I've added this card:"); + out.println(card); + if (cardCount == 1) { + out.println("Now you have " + cardCount + " card in the list."); + return; + } + out.println("Now you have " + cardCount + " cards in the list."); + } + + public void showCardList(ArrayList cards, int cardCount) { + if (cardCount == 0) { + out.println("There are no cards in your list."); + return; + } + out.println("Here are the cards in your list:"); + for (Card c : cards) { + out.println((cards.indexOf(c) + 1) + "." + c); + } + } + + public void showToUser(String message) { + out.println(message); + } + + public void showCard(Card c) { + out.println(c.getQuestion() + MESSAGE_SHOW_ANSWER_PROMPT); + getAnswerInput(c); + } + + public void getAnswerInput(Card c) { + String input = in.nextLine(); + while (!input.equalsIgnoreCase("s")) { + out.println("You have entered an invalid input, please try again."); + input = in.nextLine(); + } + out.println(c.getAnswer()); + } + + public String getRating() { + out.println(MESSAGE_SHOW_RATING_PROMPT); + return in.nextLine(); + } + + public void showExit() { + out.println("Exiting the program..."); + } + + public void showHelpList() { + out.println("Here is a list of commands available:" + "\n"); + out.println("1. " + ListCommand.MESSAGE_USAGE); + out.println("2. " + ReviseCommand.MESSAGE_USAGE); + out.println("3. " + HelpCommand.MESSAGE_USAGE); + out.println("4. " + AddCommand.MESSAGE_USAGE); + out.println("5. " + ExitCommand.MESSAGE_USAGE); + } + + public void showModuleAdded(Module module, int moduleCount) { + out.println(" Got it. I've added this module:"); + out.println(" " + module); + out.println(" Now you have " + moduleCount + " modules in the list."); + } + + public void showChapterAdded(Chapter chapter, int chapterCount) { + out.println(" Got it. I've added this chapter:"); + out.println(" " + chapter); + out.println(" Now you have " + chapterCount + " chapters in the list."); + } +} diff --git a/src/test/java/commands/ReviseCommandTest.java b/src/test/java/commands/ReviseCommandTest.java new file mode 100644 index 0000000000..e179131d97 --- /dev/null +++ b/src/test/java/commands/ReviseCommandTest.java @@ -0,0 +1,31 @@ +package commands; + +import manager.card.Card; +import org.junit.jupiter.api.Test; +import ui.Ui; + +import java.util.ArrayList; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class ReviseCommandTest { + @Test + public void rateCard_cannotAnswer_returnsSizeOne() { + String question = "1+1?"; + String answer = "2"; + ArrayList cards = new ArrayList<>(); + Card card = new Card(question, answer); + Ui ui = new Ui(); + assertEquals(ReviseCommand.rateCard(ui, cards, card, "c").size(), 1); + } + + @Test + public void rateCard_easy_returnsSizeZero() { + String question = "1+1?"; + String answer = "2"; + ArrayList cards = new ArrayList<>(); + Card card = new Card(question, answer); + Ui ui = new Ui(); + assertEquals(ReviseCommand.rateCard(ui, cards, card, "e").size(), 0); + } +} diff --git a/src/test/java/parser/ParserTest.java b/src/test/java/parser/ParserTest.java new file mode 100644 index 0000000000..2c62227d01 --- /dev/null +++ b/src/test/java/parser/ParserTest.java @@ -0,0 +1,60 @@ +package parser; + +import exception.InvalidInputException; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +class ParserTest { + @Test + public void parse_addCommandInvalidArgs_expectException() { + Parser parser = new Parser(); + final String[] inputs = { + "add", + "add ", + "add wrong args format", + // no question and answer separator prefix + "add q:When is v1.0 due? a:15 Oct 2020", + // no question prefix + "add When is v1.0 due? | a:15 Oct 2020", + // no answer prefix + "add q:When is v1.0 due? | 15 Oct 2020", + }; + for (String input : inputs) { + assertThrows(InvalidInputException.class, () -> parser.parse(input)); + } + } + + @Test + public void parse_listCommandWithArgs_expectException() { + Parser parser = new Parser(); + final String input = "list args"; + assertThrows(InvalidInputException.class, () -> parser.parse(input)); + } + + @Test + public void parse_exitCommandWithArgs_expectException() { + Parser parser = new Parser(); + final String input = "exit args"; + assertThrows(InvalidInputException.class, () -> parser.parse(input)); + } + + @Test + public void parse_removeCommandEmptyArgs_exception() { + Parser parser = new Parser(); + final String[] inputs = { + "remove", + "remove ", + }; + for (String input : inputs) { + assertThrows(InvalidInputException.class, () -> parser.parse(input)); + } + } + + @Test + public void parse_removeCommandNonIntegerArgs_exception() { + Parser parser = new Parser(); + String input = "remove two"; + assertThrows(InvalidInputException.class, () -> parser.parse(input)); + } +} diff --git a/src/test/java/scheduler/SchedulerTest.java b/src/test/java/scheduler/SchedulerTest.java new file mode 100644 index 0000000000..31e4d62975 --- /dev/null +++ b/src/test/java/scheduler/SchedulerTest.java @@ -0,0 +1,62 @@ +package scheduler; + +import org.junit.jupiter.api.Test; +import java.time.LocalDate; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; + +class SchedulerTest { + + @Test + void computeEasyDeadline_newIntervalOverLimit_intervalUnchanged() { + assertEquals(LocalDate.now().plusDays(333), Scheduler.computeEasyDeadline(333)); + } + + @Test + void computeEasyDeadline_newIntervalWithinLimit_increasedInterval() { + assertEquals(LocalDate.now().plusDays(1), Scheduler.computeEasyDeadline(1)); + } + + @Test + void computeMediumDeadline_newIntervalOverLimit_intervalUnchanged() { + assertEquals(LocalDate.now().plusDays(333), Scheduler.computeMediumDeadline(333)); + } + + @Test + void computeMediumDeadline_newIntervalWithinLimit_increasedInterval() { + assertEquals(LocalDate.now().plusDays(2), Scheduler.computeMediumDeadline(1)); + } + + @Test + void computeHardDeadline_newIntervalOverLimit_intervalUnchanged() { + assertEquals(LocalDate.now().plusDays(333), Scheduler.computeHardDeadline(333)); + } + + @Test + void computeHardDeadline_newIntervalWithinLimit_increasedInterval() { + assertEquals(LocalDate.now().plusDays(4), Scheduler.computeHardDeadline(1)); + } + + @Test + void computeDeckDeadline_newIntervalOverLimit_intervalUnchanged() { + assertEquals(LocalDate.now().plusDays(333), Scheduler.computeDeckDeadline(20, 1, 333)); + } + + @Test + void computeDeckDeadline_newIntervalWithinLimit_increasedInterval() { + assertEquals(LocalDate.now().plusDays(20), Scheduler.computeDeckDeadline(20, 1, 1)); + } + + @Test + void isDeadlineDue_deadlineIsDue_true() { + assertTrue(Scheduler.isDeadlineDue(Scheduler.getCurrentDate().minusDays(1))); + } + + @Test + void isDeadlineDue_deadlineNotDue_false() { + assertFalse(Scheduler.isDeadlineDue(Scheduler.getCurrentDate().plusDays(1))); + } + +} \ No newline at end of file