diff --git a/README.md b/README.md index e03d1198391..b8ff2883cb4 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ This is **ModCraft**.
ModCraft provides a fast and easy way for students to track courses to take to meet graduation requirements and plan courses to take. - + Example usages: * as a platform to plan and track your NUS modules * as a way to keep track of your current progess in NUS, @@ -24,7 +24,4 @@ This project is **currently ongoing** with the following features planned: * Delete taken modules * See taken modules - - -This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org). - +This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org). diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 9038a1c2957..a7eddb32ac0 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -16,7 +16,7 @@ You can reach us at the email `seer[at]comp.nus.edu.sg` [[github](https://github.com/rocketninja7)] -[[portfolio](team/andrewyapp.md)] +[[portfolio](team/rocketninja7.md)] - Role: Project Advisor @@ -32,7 +32,7 @@ You can reach us at the email `seer[at]comp.nus.edu.sg` ### Wong Ji Kean - + [[github](http://github.com/ji-just-ji)] [[portfolio](team/johndoe.md)] @@ -53,7 +53,7 @@ You can reach us at the email `seer[at]comp.nus.edu.sg` ### Huan Yaohong - + [[github](http://github.com/yyyaohhh)] [[portfolio](team/yyyaohhh.md)] diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 86c36051554..a90c44e141c 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -353,7 +353,7 @@ Use case resumes from step 2. * 3a. Modcraft detects that the module is unavailable for the semester. * 3a1. Modcraft informs the user it is unavailable - * 3a2. User searches another module + * 3a2. User searches another module Steps 3a1 to 3a2 are repeated until the module is available Use case resumes from step 4. @@ -376,7 +376,7 @@ Use case ends. * 1a. Grade is invalid * 1a1. System shows the user the grade is invalid - * 1a2. User inputs correct grade + * 1a2. User inputs correct grade Steps 1a1 and 1a2 are repeated until the user inputs the correct grade Use case resumes from step 2. diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 25aed51b142..97bb6cd6bcf 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -1,8 +1,8 @@ # ModCraft User Guide -ModCraft is an app that provides a fast and easy way for students to track courses -to take to meet graduation requirements and plan courses to take. The user interacts +ModCraft is an app that provides a fast and easy way for students to track courses +to take to meet graduation requirements and plan courses to take. The user interacts with it using a CLI, and it has a GUI created with JavaFX. @@ -24,11 +24,11 @@ with it using a CLI, and it has a GUI created with JavaFX. 1. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
Some example commands you can try: - + * `info CS1101S` : Shows Information about the module CS1101S - + * `add CS2030S Y1S2` : Adds the module CS2030S to semester 2 in year 1 - + * `delete CS2040S` : Deletes the module CS2040S if present from the list of modules taken * `exit` : Exits the app. @@ -94,7 +94,7 @@ Format: `delete m/MODULE` Examples: -* `delete GEA1000` +* `delete GEA1000` diff --git a/docs/images/ji-just-ji.png b/docs/images/ji-just-ji.png new file mode 100644 index 00000000000..5625050bf2d Binary files /dev/null and b/docs/images/ji-just-ji.png differ diff --git a/docs/images/yh.jpg b/docs/images/yh.jpg deleted file mode 100644 index bff40a83186..00000000000 Binary files a/docs/images/yh.jpg and /dev/null differ diff --git a/docs/images/yyyaohhh.png b/docs/images/yyyaohhh.png new file mode 100644 index 00000000000..fe993a6b1e0 Binary files /dev/null and b/docs/images/yyyaohhh.png differ diff --git a/docs/team/ji-just-ji.md b/docs/team/ji-just-ji.md index 4684de1b1a0..00c29f488ee 100644 --- a/docs/team/ji-just-ji.md +++ b/docs/team/ji-just-ji.md @@ -1,10 +1,10 @@ # Ji Kean's Project Portfolio Page - -## Project ModCraft -ModCraft is an app that provides a fast and easy way for students to track courses -to take to meet graduation requirements and plan courses to take. The user interacts +## Project ModCraft + +ModCraft is an app that provides a fast and easy way for students to track courses +to take to meet graduation requirements and plan courses to take. The user interacts with it using a CLI, and it has a GUI created with JavaFX. Given below are my contributions to the project. diff --git a/docs/team/andrewyapp.md b/docs/team/rocketninja7.md similarity index 96% rename from docs/team/andrewyapp.md rename to docs/team/rocketninja7.md index 99cd4b4f167..59e08e6a067 100644 --- a/docs/team/andrewyapp.md +++ b/docs/team/rocketninja7.md @@ -5,8 +5,8 @@ ### Project: ModCraft -ModCraft is an app that provides a fast and easy way for students to track courses -to take to meet graduation requirements and plan courses to take. The user interacts +ModCraft is an app that provides a fast and easy way for students to track courses +to take to meet graduation requirements and plan courses to take. The user interacts with it using a CLI, and it has a GUI created with JavaFX. Given below are my contributions to the project. diff --git a/docs/team/yyyaohhh.md b/docs/team/yyyaohhh.md index b003e547ce8..3ba1b606f8a 100644 --- a/docs/team/yyyaohhh.md +++ b/docs/team/yyyaohhh.md @@ -2,6 +2,7 @@ ## Project ModCraft + ModCraft is an app that provides a fast and easy way for students to track courses to take to meet graduation requirements and plan courses to take. The user interacts with it using a CLI, and it has a GUI created with JavaFX. @@ -32,4 +33,5 @@ Given below are my contributions to the project. - Some parts of some feature I added was adopted by several other class mates (to be added soon) - **Tools**: - - to be added soon \ No newline at end of file + + - to be added soon diff --git a/src/main/java/seedu/address/logic/Messages.java b/src/main/java/seedu/address/logic/Messages.java index ecd32c31b53..1b1988b1fb6 100644 --- a/src/main/java/seedu/address/logic/Messages.java +++ b/src/main/java/seedu/address/logic/Messages.java @@ -5,6 +5,7 @@ import java.util.stream.Stream; import seedu.address.logic.parser.Prefix; +import seedu.address.model.module.Module; import seedu.address.model.person.Person; /** @@ -48,4 +49,14 @@ public static String format(Person person) { return builder.toString(); } + public static String format(Module module) { + final StringBuilder builder = new StringBuilder(); + builder.append((module.getModuleCode())) + .append("; Semester: ") + .append("Y" + module.getYearTaken() + "S" + module.getSemesterTaken()) + .append("; Grade: ") + .append(module.getGrade()); + return builder.toString(); + } + } diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/seedu/address/logic/commands/AddCommand.java index 5d7185a9680..13e4a6dfad6 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddCommand.java @@ -1,17 +1,13 @@ package seedu.address.logic.commands; import static java.util.Objects.requireNonNull; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static seedu.address.logic.parser.CliSyntax.*; import seedu.address.commons.util.ToStringBuilder; import seedu.address.logic.Messages; import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; -import seedu.address.model.person.Person; +import seedu.address.model.module.Module; /** * Adds a person to the address book. @@ -22,41 +18,40 @@ public class AddCommand extends Command { public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. " + "Parameters: " - + PREFIX_NAME + "NAME " - + PREFIX_PHONE + "PHONE " - + PREFIX_EMAIL + "EMAIL " - + PREFIX_ADDRESS + "ADDRESS " - + "[" + PREFIX_TAG + "TAG]...\n" + + PREFIX_CODE + "Code " + + PREFIX_YEAR + "Year " + + PREFIX_SEMESTER + "Semester " + + PREFIX_GRADE + "Grade " + "Example: " + COMMAND_WORD + " " - + PREFIX_NAME + "John Doe " - + PREFIX_PHONE + "98765432 " - + PREFIX_EMAIL + "johnd@example.com " - + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 " - + PREFIX_TAG + "friends " - + PREFIX_TAG + "owesMoney"; + + PREFIX_CODE + "CS2103T " + + PREFIX_YEAR + "2 " + + PREFIX_SEMESTER + "1 " + + PREFIX_GRADE + "B "; - public static final String MESSAGE_SUCCESS = "New person added: %1$s"; - public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book"; + public static final String MESSAGE_SUCCESS = "New module added: %1$s"; + public static final String MESSAGE_DUPLICATE_MODULE = "This module already has already been added."; - private final Person toAdd; + private final Module toAdd; /** * Creates an AddCommand to add the specified {@code Person} */ - public AddCommand(Person person) { - requireNonNull(person); - toAdd = person; + public AddCommand(Module module) { + requireNonNull(module); + toAdd = module; } @Override public CommandResult execute(Model model) throws CommandException { requireNonNull(model); - if (model.hasPerson(toAdd)) { - throw new CommandException(MESSAGE_DUPLICATE_PERSON); + + if (model.hasModule(toAdd)) { + throw new CommandException(MESSAGE_DUPLICATE_MODULE); + } - model.addPerson(toAdd); + model.addModule(toAdd); return new CommandResult(String.format(MESSAGE_SUCCESS, Messages.format(toAdd))); } diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 4ff1a97ed77..134f1e3edc7 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -1,23 +1,18 @@ package seedu.address.logic.parser; import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static seedu.address.logic.parser.CliSyntax.*; + -import java.util.Set; import java.util.stream.Stream; import seedu.address.logic.commands.AddCommand; import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; +import seedu.address.model.module.Grade; +import seedu.address.model.module.ModuleCode; +import seedu.address.model.module.Semester; +import seedu.address.model.module.Year; +import seedu.address.model.module.Module; /** * Parses input arguments and creates a new AddCommand object @@ -31,23 +26,22 @@ public class AddCommandParser implements Parser { */ public AddCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + ArgumentTokenizer.tokenize(args, PREFIX_CODE, PREFIX_YEAR, PREFIX_SEMESTER, PREFIX_GRADE); - if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL) + if (!arePrefixesPresent(argMultimap, PREFIX_CODE, PREFIX_YEAR, PREFIX_SEMESTER, PREFIX_GRADE) || !argMultimap.getPreamble().isEmpty()) { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); } - argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS); - Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()); - Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()); - Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()); - Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()); - Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + argMultimap.verifyNoDuplicatePrefixesFor( PREFIX_CODE, PREFIX_YEAR, PREFIX_SEMESTER, PREFIX_GRADE); + ModuleCode code = ParserUtil.parseCode(argMultimap.getValue(PREFIX_CODE).get()); + Year year = ParserUtil.parseYear(argMultimap.getValue(PREFIX_YEAR).get()); + Semester semester = ParserUtil.parseSem(argMultimap.getValue(PREFIX_SEMESTER).get()); + Grade grade = ParserUtil.parseGrade(argMultimap.getValue(PREFIX_GRADE).get()); - Person person = new Person(name, phone, email, address, tagList); + Module module = new Module(code, year, semester, grade); - return new AddCommand(person); + return new AddCommand(module); } /** diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java index 75b1a9bf119..45414d513ea 100644 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java @@ -12,4 +12,9 @@ public class CliSyntax { public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); public static final Prefix PREFIX_TAG = new Prefix("t/"); + public static final Prefix PREFIX_CODE = new Prefix("c/"); + public static final Prefix PREFIX_YEAR = new Prefix("y/"); + public static final Prefix PREFIX_SEMESTER = new Prefix("s/"); + public static final Prefix PREFIX_GRADE = new Prefix("g/"); + } diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index b117acb9c55..a2b41baee17 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -9,12 +9,19 @@ import seedu.address.commons.core.index.Index; import seedu.address.commons.util.StringUtil; import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.Model; +import seedu.address.model.module.ModuleCode; +import seedu.address.model.module.Year; +import seedu.address.model.module.Semester; +import seedu.address.model.module.Grade; +import seedu.address.model.module.Name; +import seedu.address.model.module.Description; import seedu.address.model.person.Address; import seedu.address.model.person.Email; -import seedu.address.model.person.Name; import seedu.address.model.person.Phone; import seedu.address.model.tag.Tag; + /** * Contains utility methods used for parsing strings in the various *Parser classes. */ @@ -41,6 +48,7 @@ public static Index parseIndex(String oneBasedIndex) throws ParseException { * * @throws ParseException if the given {@code name} is invalid. */ + /* public static Name parseName(String name) throws ParseException { requireNonNull(name); String trimmedName = name.trim(); @@ -50,6 +58,8 @@ public static Name parseName(String name) throws ParseException { return new Name(trimmedName); } + */ + /** * Parses a {@code String phone} into a {@code Phone}. * Leading and trailing whitespaces will be trimmed. @@ -121,4 +131,40 @@ public static Set parseTags(Collection tags) throws ParseException } return tagSet; } + + public static ModuleCode parseCode(String code) throws ParseException { + requireNonNull(code); + String trimmedCode = code.trim(); + if (!ModuleCode.isValidModuleCode(trimmedCode)) { + throw new ParseException(ModuleCode.MESSAGE_CONSTRAINTS); + } + return new ModuleCode(trimmedCode); + } + + public static Year parseYear(String year) throws ParseException { + requireNonNull(year); + String trimmedYear = year.trim(); + if (!Year.isValidYear(trimmedYear)) { + throw new ParseException(Year.MESSAGE_CONSTRAINTS); + } + return new Year(trimmedYear); + } + + public static Semester parseSem(String sem) throws ParseException { + requireNonNull(sem); + String trimmedSem = sem.trim(); + if (!Semester.isValidSemester(trimmedSem)) { + throw new ParseException(Semester.MESSAGE_CONSTRAINTS); + } + return new Semester(trimmedSem); + } + + public static Grade parseGrade(String grade) throws ParseException { + requireNonNull(grade); + String trimmedGrade = grade.trim(); + if (!Grade.isValidGrade(trimmedGrade)) { + throw new ParseException(Grade.MESSAGE_CONSTRAINTS); + } + return new Grade(trimmedGrade); + } } diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/seedu/address/model/AddressBook.java index 73397161e84..f5396247773 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/seedu/address/model/AddressBook.java @@ -6,8 +6,8 @@ import javafx.collections.ObservableList; import seedu.address.commons.util.ToStringBuilder; -import seedu.address.model.person.Person; -import seedu.address.model.person.UniquePersonList; +import seedu.address.model.module.Module; +import seedu.address.model.module.UniqueModuleList; /** * Wraps all data at the address-book level @@ -15,7 +15,7 @@ */ public class AddressBook implements ReadOnlyAddressBook { - private final UniquePersonList persons; + private final UniqueModuleList modules; /* * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication @@ -25,7 +25,7 @@ public class AddressBook implements ReadOnlyAddressBook { * among constructors. */ { - persons = new UniquePersonList(); + modules = new UniqueModuleList(); } public AddressBook() {} @@ -40,21 +40,22 @@ public AddressBook(ReadOnlyAddressBook toBeCopied) { //// list overwrite operations - /** - * Replaces the contents of the person list with {@code persons}. - * {@code persons} must not contain duplicate persons. - */ - public void setPersons(List persons) { - this.persons.setPersons(persons); - } /** * Resets the existing data of this {@code AddressBook} with {@code newData}. */ public void resetData(ReadOnlyAddressBook newData) { requireNonNull(newData); + setModules(newData.getModuleList()); + //setPersons(newData.getPersonList()); + } - setPersons(newData.getPersonList()); + /** + * Replaces the contents of the module list with {@code modules}. + * {@code modules} must not contain duplicate persons. + */ + public void setModules(List modules) { + this.modules.setModules(modules); } //// person-level operations @@ -62,17 +63,27 @@ public void resetData(ReadOnlyAddressBook newData) { /** * Returns true if a person with the same identity as {@code person} exists in the address book. */ - public boolean hasPerson(Person person) { - requireNonNull(person); - return persons.contains(person); + public boolean hasModule(Module m) { + requireNonNull(m); + return modules.contains(m); } /** * Adds a person to the address book. * The person must not already exist in the address book. */ - public void addPerson(Person p) { - persons.add(p); + public void addModule(Module m) { + modules.add(m); + } + + + + /** + * Removes {@code key} from this {@code AddressBook}. + * {@code key} must exist in the address book. + */ + public void removeModule(Module key) { + modules.remove(key); } /** @@ -80,32 +91,26 @@ public void addPerson(Person p) { * {@code target} must exist in the address book. * The person identity of {@code editedPerson} must not be the same as another existing person in the address book. */ - public void setPerson(Person target, Person editedPerson) { - requireNonNull(editedPerson); + public void setModule(Module target, Module editedModule) { + requireNonNull(editedModule); - persons.setPerson(target, editedPerson); + modules.setModules(target, editedModule); } - /** - * Removes {@code key} from this {@code AddressBook}. - * {@code key} must exist in the address book. - */ - public void removePerson(Person key) { - persons.remove(key); - } + //// util methods @Override public String toString() { return new ToStringBuilder(this) - .add("persons", persons) + .add("modules", modules) .toString(); } @Override - public ObservableList getPersonList() { - return persons.asUnmodifiableObservableList(); + public ObservableList getModuleList() { + return modules.asUnmodifiableObservableList(); } @Override @@ -120,11 +125,11 @@ public boolean equals(Object other) { } AddressBook otherAddressBook = (AddressBook) other; - return persons.equals(otherAddressBook.persons); + return modules.equals(otherAddressBook.modules); } @Override public int hashCode() { - return persons.hashCode(); + return modules.hashCode(); } } diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/seedu/address/model/Model.java index d54df471c1f..b439a20e0b1 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/seedu/address/model/Model.java @@ -5,6 +5,7 @@ import javafx.collections.ObservableList; import seedu.address.commons.core.GuiSettings; +import seedu.address.model.module.Module; import seedu.address.model.person.Person; /** @@ -12,7 +13,7 @@ */ public interface Model { /** {@code Predicate} that always evaluate to true */ - Predicate PREDICATE_SHOW_ALL_PERSONS = unused -> true; + Predicate PREDICATE_SHOW_ALL_MODULES = unused -> true; /** * Replaces user prefs data with the data in {@code userPrefs}. @@ -55,33 +56,33 @@ public interface Model { /** * Returns true if a person with the same identity as {@code person} exists in the address book. */ - boolean hasPerson(Person person); + + boolean hasModule(Module module); /** * Deletes the given person. * The person must exist in the address book. */ - void deletePerson(Person target); - + void deleteModule(Module module); /** * Adds the given person. * {@code person} must not already exist in the address book. */ - void addPerson(Person person); + void addModule(Module module); /** * Replaces the given person {@code target} with {@code editedPerson}. * {@code target} must exist in the address book. * The person identity of {@code editedPerson} must not be the same as another existing person in the address book. */ - void setPerson(Person target, Person editedPerson); + void setModule(Module target, Module editedPerson); /** Returns an unmodifiable view of the filtered person list */ - ObservableList getFilteredPersonList(); + ObservableList getFilteredModuleList(); /** * Updates the filter of the filtered person list to filter by the given {@code predicate}. * @throws NullPointerException if {@code predicate} is null. */ - void updateFilteredPersonList(Predicate predicate); + void updateFilteredModuleList(Predicate predicate); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/seedu/address/model/ModelManager.java index 57bc563fde6..dd3b6ac8250 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/seedu/address/model/ModelManager.java @@ -11,6 +11,7 @@ import javafx.collections.transformation.FilteredList; import seedu.address.commons.core.GuiSettings; import seedu.address.commons.core.LogsCenter; +import seedu.address.model.module.Module; import seedu.address.model.person.Person; /** @@ -21,7 +22,7 @@ public class ModelManager implements Model { private final AddressBook addressBook; private final UserPrefs userPrefs; - private final FilteredList filteredPersons; + private final FilteredList filteredModules; /** * Initializes a ModelManager with the given addressBook and userPrefs. @@ -33,7 +34,7 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs this.addressBook = new AddressBook(addressBook); this.userPrefs = new UserPrefs(userPrefs); - filteredPersons = new FilteredList<>(this.addressBook.getPersonList()); + filteredModules = new FilteredList<>(this.addressBook.getModuleList()); } public ModelManager() { @@ -87,28 +88,29 @@ public ReadOnlyAddressBook getAddressBook() { return addressBook; } - @Override - public boolean hasPerson(Person person) { - requireNonNull(person); - return addressBook.hasPerson(person); - } @Override - public void deletePerson(Person target) { - addressBook.removePerson(target); + public boolean hasModule(Module module) { + requireNonNull(module); + return addressBook.hasModule(module); } + public void deleteModule(Module module) { + requireNonNull(module); + addressBook.removeModule(module); + } @Override - public void addPerson(Person person) { - addressBook.addPerson(person); - updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + public void addModule(Module module) { + requireNonNull(module); + addressBook.addModule(module); + updateFilteredModuleList(PREDICATE_SHOW_ALL_MODULES); } - @Override - public void setPerson(Person target, Person editedPerson) { - requireAllNonNull(target, editedPerson); - addressBook.setPerson(target, editedPerson); + @Override + public void setModule(Module target, Module editedModule) { + requireAllNonNull(target, editedModule); + addressBook.setModule(target, editedModule); } //=========== Filtered Person List Accessors ============================================================= @@ -118,14 +120,14 @@ public void setPerson(Person target, Person editedPerson) { * {@code versionedAddressBook} */ @Override - public ObservableList getFilteredPersonList() { - return filteredPersons; + public ObservableList getFilteredModuleList() { + return filteredModules; } @Override - public void updateFilteredPersonList(Predicate predicate) { + public void updateFilteredModuleList(Predicate predicate) { requireNonNull(predicate); - filteredPersons.setPredicate(predicate); + filteredModules.setPredicate(predicate); } @Override @@ -142,7 +144,7 @@ public boolean equals(Object other) { ModelManager otherModelManager = (ModelManager) other; return addressBook.equals(otherModelManager.addressBook) && userPrefs.equals(otherModelManager.userPrefs) - && filteredPersons.equals(otherModelManager.filteredPersons); + && filteredModules.equals(otherModelManager.filteredModules); } } diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java index 6ddc2cd9a29..8364fcf65bc 100644 --- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java +++ b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java @@ -1,6 +1,7 @@ package seedu.address.model; import javafx.collections.ObservableList; +import seedu.address.model.module.Module; import seedu.address.model.person.Person; /** @@ -9,9 +10,9 @@ public interface ReadOnlyAddressBook { /** - * Returns an unmodifiable view of the persons list. - * This list will not contain any duplicate persons. + * Returns an unmodifiable view of the modules list. + * This list will not contain any duplicate modules. */ - ObservableList getPersonList(); + ObservableList getModuleList(); } diff --git a/src/main/java/seedu/address/model/module/Module.java b/src/main/java/seedu/address/model/module/Module.java index 388e32f469c..633482320a6 100644 --- a/src/main/java/seedu/address/model/module/Module.java +++ b/src/main/java/seedu/address/model/module/Module.java @@ -10,7 +10,7 @@ */ public class Module { // Identity fields - private final Name name; + private final ModuleName moduleName; private final ModuleCode moduleCode; // Data fields @@ -25,10 +25,10 @@ public class Module { * Every field must be present and not null. */ public Module( - Name name, ModuleCode moduleCode, Description description, List lecturers, + ModuleName name, ModuleCode moduleCode, Description description, List lecturers, Year yearTaken, Semester semesterTaken, Grade grade, ModularCredit modularCredit) { - requireAllNonNull(name, moduleCode, description, lecturers, yearTaken, semesterTaken, grade, modularCredit); - this.name = name; + requireAllNonNull(name, moduleCode, description, lecturers, yearTaken, semesterTaken, grade); + this.moduleName = name; this.moduleCode = moduleCode; this.description = description; this.lecturers = lecturers; @@ -37,9 +37,21 @@ public Module( this.grade = grade; this.modularCredit = modularCredit; } + public Module(ModuleCode moduleCode, Year year, Semester semester, Grade grade) { + requireAllNonNull(moduleCode, year, semester, grade); + this.moduleCode = moduleCode; + this.yearTaken = year; + this.semesterTaken = semester; + this.grade = grade; + // Temporary until we get back-end setup + this.moduleName = null; + this.description = null; + this.lecturers = null; + this.modularCredit = null; + } - public Name getName() { - return name; + public ModuleName getName() { + return moduleName; } public ModuleCode getModuleCode() { diff --git a/src/main/java/seedu/address/model/module/Name.java b/src/main/java/seedu/address/model/module/ModuleName.java similarity index 85% rename from src/main/java/seedu/address/model/module/Name.java rename to src/main/java/seedu/address/model/module/ModuleName.java index facde67ed7c..fcf6a607cb4 100644 --- a/src/main/java/seedu/address/model/module/Name.java +++ b/src/main/java/seedu/address/model/module/ModuleName.java @@ -7,7 +7,7 @@ * Represents a Module's name in the system. * Guarantees: immutable; is valid as declared in {@link #isValidName(String)} */ -public class Name { +public class ModuleName { public static final String MESSAGE_CONSTRAINTS = "Names should only contain alphanumeric characters and spaces, and it should not start with space."; @@ -17,17 +17,17 @@ public class Name { */ public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*"; - public final String name; + public final String moduleName; /** * Constructs a {@code Name}. * * @param name A valid name. */ - public Name(String name) { + public ModuleName(String name) { requireNonNull(name); checkArgument(isValidName(name), MESSAGE_CONSTRAINTS); - this.name = name; + this.moduleName = name; } /** @@ -39,7 +39,7 @@ public static boolean isValidName(String test) { @Override public String toString() { - return name; + return moduleName; } @Override @@ -54,11 +54,11 @@ public boolean equals(Object other) { } seedu.address.model.person.Name otherName = (seedu.address.model.person.Name) other; - return name.equals(otherName.fullName); + return moduleName.equals(otherName.fullName); } @Override public int hashCode() { - return name.hashCode(); + return moduleName.hashCode(); } } diff --git a/src/main/java/seedu/address/model/module/UniqueModuleList.java b/src/main/java/seedu/address/model/module/UniqueModuleList.java new file mode 100644 index 00000000000..e30afe9bca0 --- /dev/null +++ b/src/main/java/seedu/address/model/module/UniqueModuleList.java @@ -0,0 +1,150 @@ +package seedu.address.model.module; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; + +import java.util.Iterator; +import java.util.List; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; +import seedu.address.model.module.exceptions.DuplicateModuleException; +import seedu.address.model.module.exceptions.ModuleNotFoundException; + + +/** + * A list of modules that enforces uniqueness between its elements and does not allow nulls. + * A module is considered unique by comparing using {@code Module#isSameModule(Module)}. As such, adding and updating of + * module uses Module#isSameModule(Module) for equality so as to ensure that the module being added or updated is + * unique in terms of identity in the UniqueModuleList. However, the removal of a module uses Module#equals(Object) so + * as to ensure that the module with exactly the same fields will be removed. + * + * Supports a minimal set of list operations. + * + * @see Module#isSameModule(Module) + */ +public class UniqueModuleList implements Iterable { + private final ObservableList internalList = FXCollections.observableArrayList(); + private final ObservableList internalUnmodifiableList = + FXCollections.unmodifiableObservableList(internalList); + + /** + * Returns true if the list contains an equivalent module as the given argument. + */ + public boolean contains(Module toCheck) { + requireNonNull(toCheck); + return internalList.stream().anyMatch(toCheck::isSameModule); + } + + /** + * Adds a module to the list. + * The module must not already exist in the list. + */ + public void add(Module toAdd) { + requireNonNull(toAdd); + if (contains(toAdd)) { + throw new DuplicateModuleException(); + } + internalList.add(toAdd); + } + + /** + * Replaces the module {@code target} in the list with {@code editedmodule}. + * {@code target} must exist in the list. + * The module identity of {@code editedmodule} must not be the same as another existing module in the list. + */ + public void setModules(Module target, Module editedModule) { + requireAllNonNull(target, editedModule); + + int index = internalList.indexOf(target); + if (index == -1) { + throw new ModuleNotFoundException(); + } + + if (!target.isSameModule(editedModule) && contains(editedModule)) { + throw new DuplicateModuleException(); + } + + internalList.set(index, editedModule); + } + + /** + * Removes the equivalent module from the list. + * The module must exist in the list. + */ + public void remove(Module toRemove) { + requireNonNull(toRemove); + if (!internalList.remove(toRemove)) { + throw new ModuleNotFoundException(); + } + } + + public void setModules(UniqueModuleList replacement) { + requireNonNull(replacement); + internalList.setAll(replacement.internalList); + } + + /** + * Replaces the contents of this list with {@code modules}. + * {@code modules} must not contain duplicate modules. + */ + public void setModules(List modules) { + requireAllNonNull(modules); + if (!modulesAreUnique(modules)) { + throw new DuplicateModuleException(); + } + + internalList.setAll(modules); + } + + /** + * Returns the backing list as an unmodifiable {@code ObservableList}. + */ + public ObservableList asUnmodifiableObservableList() { + return internalUnmodifiableList; + } + + @Override + public Iterator iterator() { + return internalList.iterator(); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof UniqueModuleList)) { + return false; + } + + UniqueModuleList otherUniqueModuleList = (UniqueModuleList) other; + return internalList.equals(otherUniqueModuleList.internalList); + } + + @Override + public int hashCode() { + return internalList.hashCode(); + } + + @Override + public String toString() { + return internalList.toString(); + } + + /** + * Returns true if {@code modules} contains only unique modules. + */ + private boolean modulesAreUnique(List modules) { + for (int i = 0; i < modules.size() - 1; i++) { + for (int j = i + 1; j < modules.size(); j++) { + if (modules.get(i).isSameModule(modules.get(j))) { + return false; + } + } + } + return true; + } +} diff --git a/src/main/java/seedu/address/model/module/exceptions/DuplicateModuleException.java b/src/main/java/seedu/address/model/module/exceptions/DuplicateModuleException.java new file mode 100644 index 00000000000..f9e344f5305 --- /dev/null +++ b/src/main/java/seedu/address/model/module/exceptions/DuplicateModuleException.java @@ -0,0 +1,11 @@ +package seedu.address.model.module.exceptions; + +/** + * Signals that the operation will result in duplicate Persons (Persons are considered duplicates if they have the same + * identity). + */ +public class DuplicateModuleException extends RuntimeException { + public DuplicateModuleException() { + super("Operation would result in duplicate modules"); + } +} diff --git a/src/main/java/seedu/address/model/module/exceptions/ModuleNotFoundException.java b/src/main/java/seedu/address/model/module/exceptions/ModuleNotFoundException.java new file mode 100644 index 00000000000..31f2ed86278 --- /dev/null +++ b/src/main/java/seedu/address/model/module/exceptions/ModuleNotFoundException.java @@ -0,0 +1,6 @@ +package seedu.address.model.module.exceptions; + +/** + * Signals that the operation is unable to find the specified person. + */ +public class ModuleNotFoundException extends RuntimeException {}