diff --git a/src/main/java/seedu/address/logic/commands/AddApptCommand.java b/src/main/java/seedu/address/logic/commands/AddApptCommand.java index 1ae76cf7f46d..994cbf80e5f8 100644 --- a/src/main/java/seedu/address/logic/commands/AddApptCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddApptCommand.java @@ -8,9 +8,10 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_APPT_VENUE; import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; -import java.util.HashSet; +import java.time.LocalDateTime; import java.util.List; import java.util.Set; +import java.util.TreeSet; import seedu.address.commons.core.Messages; import seedu.address.commons.core.index.Index; @@ -19,7 +20,9 @@ import seedu.address.model.Model; import seedu.address.model.person.Person; import seedu.address.model.timetable.Appt; +import seedu.address.model.timetable.ApptComparator; +//@@author brandonccm1996 /** * Adds an appointment to a person's timetable. */ @@ -36,13 +39,15 @@ public class AddApptCommand extends Command { + PREFIX_APPT_INFO + "[INFO] " + PREFIX_APPT_DRNAME + "[DOCTOR'S NAME]\n" + "Example: " + COMMAND_WORD + " 1 " - + PREFIX_APPT_START + "16/09/2018 1500 " - + PREFIX_APPT_END + "16/09/2018 1530 " + + PREFIX_APPT_START + "16-09-2018 15:00 " + + PREFIX_APPT_END + "16-09-2018 15:30 " + PREFIX_APPT_VENUE + "Consultation Room 12 " + PREFIX_APPT_INFO + "Diabetes Checkup " + PREFIX_APPT_DRNAME + "Dr Tan"; public static final String MESSAGE_ADD_APPT_SUCCESS = "Added appt to Person: %1$s"; + public static final String MESSAGE_APPT_CLASH = "The appt you are adding clashes with the timing of another appt"; + public static final String MESSAGE_INVALID_TIME = "The end time of an appt must be after the start time"; public static final String MESSAGE_DELETE_APPT_SUCCESS = "Removed appt from Person: %1$s"; private final Index index; @@ -68,14 +73,26 @@ public CommandResult execute(Model model, CommandHistory history) throws Command Person personToEdit = lastShownList.get(index.getZeroBased()); Set oldAppts = personToEdit.getAppts(); - Set newAppts = new HashSet<>(); + + if (hasInvalidTiming(appt)) { + throw new CommandException(MESSAGE_INVALID_TIME); + } + + for (Appt oldAppt : oldAppts) { + if (hasApptClash(oldAppt, appt)) { + throw new CommandException(MESSAGE_APPT_CLASH); + } + } + + Set newAppts = new TreeSet<>(new ApptComparator()); for (Appt appt : oldAppts) { newAppts.add(appt); } newAppts.add(appt); Person editedPerson = new Person(personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(), personToEdit.getAddress(), personToEdit.getMedicalReports(), personToEdit.getMedHistory(), newAppts, - personToEdit.getNric(), personToEdit.getDateOfBirth(), personToEdit.getTags()); + personToEdit.getNric(), personToEdit.getDateOfBirth(), personToEdit.getHeight(), + personToEdit.getWeight(), personToEdit.getTags()); model.updatePerson(personToEdit, editedPerson); model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); @@ -92,6 +109,40 @@ private String generateSuccessMessage(Person personToEdit) { return String.format(MESSAGE_ADD_APPT_SUCCESS, personToEdit); } + /** + * Checks if an appt has end time before or equal to start time + */ + private boolean hasInvalidTiming(Appt appt) { + LocalDateTime start = appt.getStart().value; + LocalDateTime end = appt.getEnd().value; + + if (!end.isAfter(start)) { + return true; + } + return false; + } + + /** + * Checks if appt1 and appt2 have timings which clash + */ + private boolean hasApptClash(Appt appt1, Appt appt2) { + LocalDateTime start1 = appt1.getStart().value; + LocalDateTime end1 = appt1.getEnd().value; + LocalDateTime start2 = appt2.getStart().value; + LocalDateTime end2 = appt2.getEnd().value; + + // Example: + // if appt1 is from 1600-1700, appt2 cannot start between 1600-1759, and cannot end between 1601-1800 + // if appt2 is from 1600-1700, appt1 cannot start between 1600-1759, and cannot end between 1601-1800 + if (((start1.isEqual(start2) || start1.isAfter(start2)) && start1.isBefore(end2)) + || ((start2.isEqual(start1) || start2.isAfter(start1)) && start2.isBefore(end1)) + || (end1.isAfter(start2) && (end1.isBefore(end2) || end1.isEqual(end2))) + || (end2.isAfter(start1) && (end2.isBefore(end1) || end2.isEqual(end1)))) { + return true; + } + return false; + } + @Override public boolean equals(Object other) { // short circuit if same object diff --git a/src/main/java/seedu/address/logic/commands/AddHistCommand.java b/src/main/java/seedu/address/logic/commands/AddHistCommand.java index 68c17a6196bb..ef9986aecac6 100644 --- a/src/main/java/seedu/address/logic/commands/AddHistCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddHistCommand.java @@ -16,7 +16,18 @@ import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; import seedu.address.model.medhistory.MedHistory; +import seedu.address.model.medicalreport.MedicalReport; +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.person.addinfo.DateOfBirth; +import seedu.address.model.person.addinfo.Height; +import seedu.address.model.person.addinfo.Nric; +import seedu.address.model.person.addinfo.Weight; +import seedu.address.model.tag.Tag; +import seedu.address.model.timetable.Appt; /** * Adds/Edits medical history of a patient in the Health Book. @@ -34,6 +45,7 @@ public class AddHistCommand extends Command { + PREFIX_HISTORY_COUNTRY + " Kuwait "; public static final String MESSAGE_ADD_MEDHISTORY_SUCCESS = "Added medical history to Person: %1$s"; + public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided."; public static final String MESSAGE_DELETE_MEDHISTORY_SUCCESS = "Removed medical history from Person: %1$s"; private final Index index; private final MedHistory medHistory; @@ -44,7 +56,7 @@ public class AddHistCommand extends Command { public AddHistCommand(Index index, MedHistory medHistory) { requireAllNonNull(index, medHistory); this.index = index; - this.medHistory = medHistory; + this.medHistory = new MedHistory(medHistory); } @Override @@ -62,21 +74,36 @@ public CommandResult execute(Model model, CommandHistory history) throws Command } // adds the new history from command newMedHistories.add(medHistory); - Person editedPerson = new Person(personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(), - personToEdit.getAddress(), personToEdit.getMedicalReports(), newMedHistories, personToEdit.getAppts(), - personToEdit.getNric(), personToEdit.getDateOfBirth(), personToEdit.getTags()); + Person editedPerson = createEditedPerson(personToEdit, newMedHistories); model.updatePerson(personToEdit, editedPerson); model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); model.commitAddressBook(); - return new CommandResult(generateSuccessMessage(editedPerson)); + return new CommandResult(String.format(MESSAGE_ADD_MEDHISTORY_SUCCESS, editedPerson)); } /** - * Generates a command execution success message based on whether the medical history is added to or removed from - * {@code personToEdit}. + * Creates and returns a {@code Person} with the details of {@code personToEdit} + * edited with {@code editPersonDescriptor}. */ - private String generateSuccessMessage(Person personToEdit) { - return String.format(MESSAGE_ADD_MEDHISTORY_SUCCESS, personToEdit); + private static Person createEditedPerson(Person personToEdit, Set newMedHistories) { + assert personToEdit != null; + + Name name = personToEdit.getName(); + Phone phone = personToEdit.getPhone(); + Email email = personToEdit.getEmail(); + Address address = personToEdit.getAddress(); + Set appts = personToEdit.getAppts(); + Set medicalReports = personToEdit.getMedicalReports(); + Set medHistories = newMedHistories; + Set tags = personToEdit.getTags(); + + Nric nric = personToEdit.getNric(); + DateOfBirth dateOfBirth = personToEdit.getDateOfBirth(); + Height height = personToEdit.getHeight(); + Weight weight = personToEdit.getWeight(); + + return new Person(name, phone, email, address, medicalReports, medHistories, appts, + nric, dateOfBirth, height, weight, tags); } @Override diff --git a/src/main/java/seedu/address/logic/commands/AddInfoCommand.java b/src/main/java/seedu/address/logic/commands/AddInfoCommand.java index 6ac973713ba6..19cd337f585f 100644 --- a/src/main/java/seedu/address/logic/commands/AddInfoCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddInfoCommand.java @@ -16,12 +16,14 @@ import seedu.address.model.medhistory.MedHistory; import seedu.address.model.medicalreport.MedicalReport; import seedu.address.model.person.Address; -import seedu.address.model.person.DateOfBirth; import seedu.address.model.person.Email; import seedu.address.model.person.Name; -import seedu.address.model.person.Nric; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; +import seedu.address.model.person.addinfo.DateOfBirth; +import seedu.address.model.person.addinfo.Height; +import seedu.address.model.person.addinfo.Nric; +import seedu.address.model.person.addinfo.Weight; import seedu.address.model.tag.Tag; import seedu.address.model.timetable.Appt; @@ -41,7 +43,6 @@ public class AddInfoCommand extends Command { public static final String MESSAGE_NOT_EDITED = "At least one field to add additional information must be provided"; public static final String MESSAGE_ADD_INFO_SUCCESS = "Added additional info to Person: %1$s"; - public static final String MESSAGE_DELETE_INFO_SUCCESS = "Removed additional info to person: %1$s"; private final Index index; private final AddInfoPersonDescriptor addInfoPersonDescriptor; @@ -96,9 +97,11 @@ private static Person createEditedPerson(Person personToEdit, AddInfoPersonDescr Nric updatedNric = addInfoPersonDescriptor.getNric().orElse(personToEdit.getNric()); DateOfBirth updatedDateOfBirth = addInfoPersonDescriptor.getDateOfBirth().orElse(personToEdit.getDateOfBirth()); + Height updatedHeight = addInfoPersonDescriptor.getHeight().orElse(personToEdit.getHeight()); + Weight updatedWeight = addInfoPersonDescriptor.getWeight().orElse(personToEdit.getWeight()); return new Person(name, phone, email, address, medicalReports, medHistory, appts, - updatedNric, updatedDateOfBirth, tags); + updatedNric, updatedDateOfBirth, updatedHeight, updatedWeight, tags); } @Override @@ -126,16 +129,20 @@ public boolean equals(Object other) { public static class AddInfoPersonDescriptor { private Nric nric; private DateOfBirth dateOfBirth; + private Height height; + private Weight weight; public AddInfoPersonDescriptor() {} public AddInfoPersonDescriptor(AddInfoPersonDescriptor toCopy) { setNric(toCopy.nric); setDateOfBirth(toCopy.dateOfBirth); + setHeight(toCopy.height); + setWeight(toCopy.weight); } public boolean isAnyFieldEdited() { - return CollectionUtil.isAnyNonNull(nric, dateOfBirth); + return CollectionUtil.isAnyNonNull(nric, dateOfBirth, height, weight); } public void setNric(Nric nric) { @@ -154,6 +161,22 @@ public Optional getDateOfBirth() { return Optional.ofNullable(dateOfBirth); } + public void setHeight(Height height) { + this.height = height; + } + + public Optional getHeight() { + return Optional.ofNullable(height); + } + + public void setWeight(Weight weight) { + this.weight = weight; + } + + public Optional getWeight() { + return Optional.ofNullable(weight); + } + @Override public boolean equals(Object other) { if (other == this) { diff --git a/src/main/java/seedu/address/logic/commands/AddMedicalReportCommand.java b/src/main/java/seedu/address/logic/commands/AddMedicalReportCommand.java index 3867282fc6a6..ee505bdbb3c7 100644 --- a/src/main/java/seedu/address/logic/commands/AddMedicalReportCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddMedicalReportCommand.java @@ -18,6 +18,7 @@ import seedu.address.model.medicalreport.MedicalReport; import seedu.address.model.person.Person; +//@@author chewkahmeng /** * Adds a medical report to a person. */ @@ -33,8 +34,8 @@ public class AddMedicalReportCommand extends Command { + PREFIX_INFORMATION + "[INFORMATION]\n" + "Example: " + COMMAND_WORD + " 1 " + PREFIX_TITLE + "Asthma " - + PREFIX_DATE + "01/01/2018 " - + PREFIX_INFORMATION + "prescribed XXX medicine, next appointment on 02/02/2018. "; + + PREFIX_DATE + "01-01-2018 " + + PREFIX_INFORMATION + "prescribed XXX medicine, next appointment on 02-02-2018. "; public static final String MESSAGE_ADD_REPORT_SUCCESS = "Added medical report to Person: %1$s"; @@ -70,7 +71,8 @@ public CommandResult execute(Model model, CommandHistory history) throws Command newReports.add(report); Person editedPerson = new Person(personToEdit.getName(), personToEdit.getPhone(), personToEdit.getEmail(), personToEdit.getAddress(), newReports, personToEdit.getMedHistory(), personToEdit.getAppts(), - personToEdit.getNric(), personToEdit.getDateOfBirth(), personToEdit.getTags()); + personToEdit.getNric(), personToEdit.getDateOfBirth(), personToEdit.getHeight(), + personToEdit.getWeight(), personToEdit.getTags()); model.updatePerson(personToEdit, editedPerson); model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index 3d00a3b942c9..b98c57858362 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -23,12 +23,14 @@ import seedu.address.model.medhistory.MedHistory; import seedu.address.model.medicalreport.MedicalReport; import seedu.address.model.person.Address; -import seedu.address.model.person.DateOfBirth; import seedu.address.model.person.Email; import seedu.address.model.person.Name; -import seedu.address.model.person.Nric; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; +import seedu.address.model.person.addinfo.DateOfBirth; +import seedu.address.model.person.addinfo.Height; +import seedu.address.model.person.addinfo.Nric; +import seedu.address.model.person.addinfo.Weight; import seedu.address.model.tag.Tag; import seedu.address.model.timetable.Appt; @@ -104,16 +106,19 @@ private static Person createEditedPerson(Person personToEdit, EditPersonDescript Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone()); Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail()); Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress()); + Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); + + Nric nric = personToEdit.getNric(); + DateOfBirth dateOfBirth = personToEdit.getDateOfBirth(); + Height height = personToEdit.getHeight(); + Weight weight = personToEdit.getWeight(); Set updatedReports = personToEdit.getMedicalReports(); // edit command disallow editing reports Set updatedMedHistory = personToEdit.getMedHistory(); // edit command does not edit MedHistory now Set updatedAppts = personToEdit.getAppts(); // edit command does not allow editing appts - Nric updatedNric = personToEdit.getNric(); - DateOfBirth updatedDateOfBirth = personToEdit.getDateOfBirth(); - Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedReports, - updatedMedHistory, updatedAppts, updatedNric, updatedDateOfBirth, updatedTags); + updatedMedHistory, updatedAppts, nric, dateOfBirth, height, weight, updatedTags); } @Override diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/seedu/address/logic/commands/FindCommand.java index 551186c4913d..73eb0b0b7f97 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/seedu/address/logic/commands/FindCommand.java @@ -19,10 +19,12 @@ public class FindCommand extends Command { public static final String COMMAND_WORD = "find"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose PREFIX contain any " + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Finds all persons whose prefix contain any " + "of the specified keywords (case-insensitive) and displays them as a list with index numbers.\n" - + "Parameters: PREFIX KEYWORD [MORE_KEYWORDS]...\n" - + "Example: " + COMMAND_WORD + " n/ " + " alice" + " or " + "p/ " + "91234567."; + + "Parameters: PREFIX/ KEYWORD [MORE_KEYWORDS]...\n" + + "Example: " + COMMAND_WORD + " n/ " + "aliCe Bernard" + "\t" + COMMAND_WORD + " p/ " + "91234567\n" + + "Personal prefixes:\t n/ (Name)\t p/ (Phone)\t e/ (Email)\t\t\t a/ (Address)\t\t t/ (tag)\t ic/ (NRIC)\n" + + "Medical prefixes:\t i/ (MedInfo)\t hsa/ (Allergy)\t hsb/ (BloodType)\t hsc/ (LastCountry)"; private final Predicate predicate; diff --git a/src/main/java/seedu/address/logic/parser/AddApptCommandParser.java b/src/main/java/seedu/address/logic/parser/AddApptCommandParser.java index 62465ee0a55c..0dd354fe82f3 100644 --- a/src/main/java/seedu/address/logic/parser/AddApptCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddApptCommandParser.java @@ -20,6 +20,7 @@ import seedu.address.model.timetable.ApptInfo; import seedu.address.model.timetable.ApptVenue; +//@@author brandonccm1996 /** * Parses input arguments and creates a new {@code AddApptCommand} object */ diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index a22738f6c46d..5f0e652d4936 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -9,6 +9,7 @@ import java.util.HashSet; import java.util.Set; +import java.util.TreeSet; import java.util.stream.Stream; import seedu.address.logic.commands.AddCommand; @@ -16,14 +17,17 @@ import seedu.address.model.medhistory.MedHistory; import seedu.address.model.medicalreport.MedicalReport; import seedu.address.model.person.Address; -import seedu.address.model.person.DateOfBirth; import seedu.address.model.person.Email; import seedu.address.model.person.Name; -import seedu.address.model.person.Nric; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; +import seedu.address.model.person.addinfo.DateOfBirth; +import seedu.address.model.person.addinfo.Height; +import seedu.address.model.person.addinfo.Nric; +import seedu.address.model.person.addinfo.Weight; import seedu.address.model.tag.Tag; import seedu.address.model.timetable.Appt; +import seedu.address.model.timetable.ApptComparator; /** * Parses input arguments and creates a new AddCommand object @@ -48,15 +52,18 @@ public AddCommand parse(String args) throws ParseException { 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)); + Set reports = new HashSet<>(); // add command does not allow adding reports straight away Set medHistories = new HashSet<>(); - Set appts = new HashSet<>(); // add command does not allow adding appts straight away + Set appts = new TreeSet<>(new ApptComparator()); // add command does not allow adding appts straight away Nric nric = new Nric(""); DateOfBirth dateOfBirth = new DateOfBirth("01-01-1970"); - Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + Height height = new Height(""); + Weight weight = new Weight(""); - Person person = new Person(name, phone, email, address, reports, medHistories, appts, nric, dateOfBirth, - tagList); + Person person = new Person(name, phone, email, address, reports, medHistories, appts, nric, dateOfBirth, height, + weight, tagList); return new AddCommand(person); } diff --git a/src/main/java/seedu/address/logic/parser/AddHistCommandParser.java b/src/main/java/seedu/address/logic/parser/AddHistCommandParser.java index 5c80a6f8f9c6..4cde2ea3b53a 100644 --- a/src/main/java/seedu/address/logic/parser/AddHistCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddHistCommandParser.java @@ -6,8 +6,6 @@ import static seedu.address.logic.parser.CliSyntax.PREFIX_HISTORY_COUNTRY; import static seedu.address.logic.parser.CliSyntax.PREFIX_HISTORY_DATE; -import java.util.stream.Stream; - import seedu.address.commons.core.index.Index; import seedu.address.commons.exceptions.IllegalValueException; import seedu.address.logic.commands.AddHistCommand; @@ -34,11 +32,6 @@ public AddHistCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = ArgumentTokenizer.tokenize(args, PREFIX_HISTORY_DATE, PREFIX_HISTORY_ALLERGY, PREFIX_HISTORY_COUNTRY); - if (!arePrefixesPresent(argMultimap, PREFIX_HISTORY_DATE, PREFIX_HISTORY_ALLERGY, - PREFIX_HISTORY_COUNTRY)) { - throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddHistCommand.MESSAGE_USAGE)); - } - Index index; try { @@ -47,17 +40,29 @@ public AddHistCommand parse(String args) throws ParseException { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddHistCommand.MESSAGE_USAGE), ive); } - Allergy allergy = ParserUtil.parseAllergy(argMultimap.getValue(PREFIX_HISTORY_ALLERGY).get()); - PrevCountry prevCountry = ParserUtil.parsePrevCountry(argMultimap.getValue(PREFIX_HISTORY_COUNTRY).get()); - MedHistDate medHistDate = ParserUtil.parseMedHistDate(argMultimap.getValue(PREFIX_HISTORY_DATE).get()); - return new AddHistCommand(index, new MedHistory (medHistDate, allergy, prevCountry)); - } + MedHistory medHistory = new MedHistory(); + if (argMultimap.getValue(PREFIX_HISTORY_DATE).isPresent()) { + medHistory.setMedHistDate(ParserUtil + .parseMedHistDate(argMultimap.getValue(PREFIX_HISTORY_DATE).get())); + } else { + medHistory.setMedHistDate(new MedHistDate("")); + } + if (argMultimap.getValue(PREFIX_HISTORY_ALLERGY).isPresent()) { + medHistory.setAllergy(ParserUtil + .parseAllergy(argMultimap.getValue(PREFIX_HISTORY_ALLERGY).get())); + } else { + medHistory.setAllergy(new Allergy("")); + } + if (argMultimap.getValue(PREFIX_HISTORY_COUNTRY).isPresent()) { + medHistory.setPrevCountry(ParserUtil + .parsePrevCountry(argMultimap.getValue(PREFIX_HISTORY_COUNTRY).get())); + } else { + medHistory.setPrevCountry(new PrevCountry("")); + } + if (!medHistory.isAnyFieldEdited()) { + throw new ParseException(AddHistCommand.MESSAGE_NOT_EDITED); + } - /** - * Returns true if none of the prefixes contains empty {@code Optional} values in the given - * {@code ArgumentMultimap}. - */ - private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { - return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + return new AddHistCommand(index, medHistory); } } diff --git a/src/main/java/seedu/address/logic/parser/AddInfoCommandParser.java b/src/main/java/seedu/address/logic/parser/AddInfoCommandParser.java index 690af0d3fd69..ecb47f42441c 100644 --- a/src/main/java/seedu/address/logic/parser/AddInfoCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddInfoCommandParser.java @@ -3,7 +3,9 @@ import static java.util.Objects.requireNonNull; import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_INFO_DOB; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_INFO_HEIGHT; import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_INFO_NRIC; +import static seedu.address.logic.parser.CliSyntax.PREFIX_ADD_INFO_WEIGHT; import seedu.address.commons.core.index.Index; import seedu.address.commons.exceptions.IllegalValueException; @@ -23,7 +25,8 @@ public class AddInfoCommandParser implements Parser { */ public AddInfoCommand parse(String args) throws ParseException { requireNonNull(args); - ArgumentMultimap argMultiMap = ArgumentTokenizer.tokenize(args, PREFIX_ADD_INFO_NRIC, PREFIX_ADD_INFO_DOB); + ArgumentMultimap argMultiMap = ArgumentTokenizer.tokenize(args, PREFIX_ADD_INFO_NRIC, PREFIX_ADD_INFO_DOB, + PREFIX_ADD_INFO_HEIGHT, PREFIX_ADD_INFO_WEIGHT); Index index; try { @@ -40,6 +43,14 @@ public AddInfoCommand parse(String args) throws ParseException { addInfoPersonDescriptor.setDateOfBirth(ParserUtil.parseDateOfBirth( argMultiMap.getValue(PREFIX_ADD_INFO_DOB).get())); } + if (argMultiMap.getValue(PREFIX_ADD_INFO_HEIGHT).isPresent()) { + addInfoPersonDescriptor.setHeight(ParserUtil.parseHeight( + argMultiMap.getValue(PREFIX_ADD_INFO_HEIGHT).get())); + } + if (argMultiMap.getValue(PREFIX_ADD_INFO_WEIGHT).isPresent()) { + addInfoPersonDescriptor.setWeight(ParserUtil.parseWeight( + argMultiMap.getValue(PREFIX_ADD_INFO_WEIGHT).get())); + } if (!addInfoPersonDescriptor.isAnyFieldEdited()) { throw new ParseException(AddInfoCommand.MESSAGE_NOT_EDITED); diff --git a/src/main/java/seedu/address/logic/parser/AddMedicalReportCommandParser.java b/src/main/java/seedu/address/logic/parser/AddMedicalReportCommandParser.java index ff3f3bc4c387..69bd8191a523 100644 --- a/src/main/java/seedu/address/logic/parser/AddMedicalReportCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddMedicalReportCommandParser.java @@ -17,6 +17,7 @@ import seedu.address.model.medicalreport.ReportDate; import seedu.address.model.medicalreport.Title; +//@@author chewkahmeng /** * Parses input arguments and creates a new AddMedicalReport object */ diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 0199978df851..c9964f56220d 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -51,8 +51,8 @@ public Command parseCommand(String userInput) throws ParseException { final String commandWord = matcher.group("commandWord"); final String arguments = matcher.group("arguments"); - switch (commandWord) { + switch (commandWord) { case AddCommand.COMMAND_WORD: return new AddCommandParser().parse(arguments); diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/seedu/address/logic/parser/FindCommandParser.java index 31d37259c94c..b93a2c1b791a 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/FindCommandParser.java @@ -7,8 +7,13 @@ import seedu.address.logic.commands.FindCommand; import seedu.address.logic.parser.exceptions.ParseException; import seedu.address.model.person.AddressContainsKeywordsPredicate; +//import seedu.address.model.person.AllergyContainsKeywordsPredicate; +//import seedu.address.model.person.BloodTypeContainsKeywordsPredicate; +//import seedu.address.model.person.CountryContainsKeywordsPredicate; import seedu.address.model.person.EmailContainsKeywordsPredicate; +//import seedu.address.model.person.InfoContainsKeywordsPredicate; import seedu.address.model.person.NameContainsKeywordsPredicate; +import seedu.address.model.person.NricContainsKeywordsPredicate; import seedu.address.model.person.PhoneContainsKeywordsPredicate; import seedu.address.model.person.TagContainsKeywordsPredicate; @@ -34,8 +39,13 @@ public FindCommand parse(String args) throws ParseException { String[] nameKeywords = trimmedArgs.split("\\s+"); switch(nameKeywords[0]) { - + //Personal prefixes case "n/": + //create NameContainsKeywordsPredicate + /* + String keywords = nameKeywords[1] + nameKeywords[2]; + return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(keywords))); + */ return new FindCommand(new NameContainsKeywordsPredicate(Arrays.asList(nameKeywords[1]))); case "p/": @@ -54,6 +64,28 @@ public FindCommand parse(String args) throws ParseException { //create TagContainsKeywordsPredicate return new FindCommand(new TagContainsKeywordsPredicate(Arrays.asList(nameKeywords[1]))); + case "ic/": + //create NricContainsKeywordsPredicate + return new FindCommand(new NricContainsKeywordsPredicate(Arrays.asList(nameKeywords[1]))); + + //Medical Prefixes + /* + case "i/": + //create InfoContainsKeywordsPredicate + return new FindCommand(new InfoContainsKeywordsPredicate(Arrays.asList(nameKeywords[1]))); + + case "hsb/": + //create BloodTypeContainsKeywordsPredicate + return new FindCommand(new BloodTypeContainsKeywordsPredicate(Arrays.asList(nameKeywords[1]))); + + case "hsc/": + //create CountryContainsKeywordsPredicate + return new FindCommand(new CountryContainsKeywordsPredicate(Arrays.asList(nameKeywords[1]))); + + case "hsa/": + //create AllergyContainsKeywordsPredicate + return new FindCommand(new AllergyContainsKeywordsPredicate(Arrays.asList(nameKeywords[1]))); + */ default: throw new ParseException(MESSAGE_INVALID_COMMAND_FORMAT); } diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index 214e6674e06d..3ff1452b8a08 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -2,8 +2,7 @@ import static java.util.Objects.requireNonNull; -import java.time.LocalDate; -import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -18,16 +17,19 @@ import seedu.address.model.medicalreport.ReportDate; import seedu.address.model.medicalreport.Title; import seedu.address.model.person.Address; -import seedu.address.model.person.DateOfBirth; import seedu.address.model.person.Email; import seedu.address.model.person.Name; -import seedu.address.model.person.Nric; import seedu.address.model.person.Phone; +import seedu.address.model.person.addinfo.DateOfBirth; +import seedu.address.model.person.addinfo.Height; +import seedu.address.model.person.addinfo.Nric; +import seedu.address.model.person.addinfo.Weight; import seedu.address.model.tag.Tag; import seedu.address.model.timetable.ApptDateTime; import seedu.address.model.timetable.ApptDrName; import seedu.address.model.timetable.ApptInfo; import seedu.address.model.timetable.ApptVenue; +import seedu.address.model.util.DateTimeUtil; /** * Contains utility methods used for parsing strings in the various *Parser classes. @@ -119,9 +121,15 @@ public static Email parseEmail(String email) throws ParseException { public static Nric parseNric(String nric) throws ParseException { requireNonNull(nric); String trimmedNric = nric.trim(); + if (!Nric.isValidNric(trimmedNric)) { throw new ParseException(Nric.MESSAGE_NRIC_CONSTRAINTS); } + + if (!Nric.isCorrectNric(trimmedNric)) { + throw new ParseException(Nric.MESSAGE_NRIC_INVALID); + } + return new Nric(trimmedNric); } @@ -139,15 +147,48 @@ public static DateOfBirth parseDateOfBirth(String dateOfBirth) throws ParseExcep } try { - DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); - LocalDate.parse(dateOfBirth, dateTimeFormatter); - } catch (Exception e) { + DateTimeUtil.parseDate(dateOfBirth); + } catch (DateTimeParseException e) { throw new ParseException(DateOfBirth.DATE_OF_BIRTH_VALUE_EXCEEDED); } return new DateOfBirth(trimmedDateOfBirth); } + /** + * Parses a {@code String height} into a {@code Height}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if given {@code height} is invalid + */ + public static Height parseHeight(String height) throws ParseException { + requireNonNull(height); + String trimmedHeight = height.trim(); + + if (!Height.isValidHeight(trimmedHeight)) { + throw new ParseException(Height.MESSAGE_HEIGHT_CONSTRAINTS); + } + + return new Height(trimmedHeight); + } + + /** + * Parses a {@code String weight} into a {@code Weight}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if given {@code weight} is invalid + */ + public static Weight parseWeight(String weight) throws ParseException { + requireNonNull(weight); + String trimmedWeight = weight.trim(); + + if (!Weight.isValidWeight(trimmedWeight)) { + throw new ParseException(Weight.MESSAGE_WEIGHT_CONSTRAINTS); + } + + return new Weight(trimmedWeight); + } + /** * Parses a {@code String tag} into a {@code Tag}. * Leading and trailing whitespaces will be trimmed. @@ -217,6 +258,7 @@ public static PrevCountry parsePrevCountry(String prevCountry) { return new PrevCountry(trimmedPrevCountry); } + //@@author chewkahmeng /** * ================================================== * PARSER FOR MEDICAL REPORT SUBFIELDS @@ -238,13 +280,14 @@ public static Title parseTitle(String title) { * Leading and trailing whitespaces will be trimmed. * * @throws ParseException if the given {@code date} is invalid. - * ParseException is omitted for now. - */ - public static ReportDate parseDate(String date) { + public static ReportDate parseDate(String date) throws ParseException { requireNonNull(date); - String trimmedDate = date.trim(); - return new ReportDate(trimmedDate); + String trimmedReportDate = date.trim(); + if (!ReportDate.isValidDate(trimmedReportDate)) { + throw new ParseException(ReportDate.MESSAGE_DATE_CONSTRAINTS); + } + return new ReportDate(trimmedReportDate); } /** @@ -257,6 +300,7 @@ public static Information parseInformation(String information) { return new Information(trimmedInformation); } + //@@author brandonccm1996 /** * ================================================== * PARSER FOR APPT SUBFIELDS @@ -266,10 +310,15 @@ public static Information parseInformation(String information) { /** * Parses a {@code String apptDateTime} into an {@code ApptDateTime}. * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code apptDateTime} is invalid. */ - public static ApptDateTime parseApptTime(String apptDateTime) { + public static ApptDateTime parseApptTime(String apptDateTime) throws ParseException { requireNonNull(apptDateTime); String trimmedApptDateTime = apptDateTime.trim(); + if (!ApptDateTime.isValidDateTime(trimmedApptDateTime)) { + throw new ParseException(ApptDateTime.MESSAGE_NAME_CONSTRAINTS); + } return new ApptDateTime(trimmedApptDateTime); } diff --git a/src/main/java/seedu/address/model/medhistory/MedHistory.java b/src/main/java/seedu/address/model/medhistory/MedHistory.java index 9ee4ac8fda10..ba6b32a41ef6 100644 --- a/src/main/java/seedu/address/model/medhistory/MedHistory.java +++ b/src/main/java/seedu/address/model/medhistory/MedHistory.java @@ -3,18 +3,22 @@ import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import java.util.Objects; +import java.util.Optional; + +import seedu.address.commons.util.CollectionUtil; /** * Model of medical history of a patient. * Guarantees: details are present and not null, field values are validated, immutable. */ + public class MedHistory { + private MedHistDate medHistDate; + private Allergy allergy; + private PrevCountry prevCountry; - // Data fields - private final MedHistDate medHistDate; - private final Allergy allergy; - private final PrevCountry prevCountry; + public MedHistory() {} public MedHistory(MedHistDate medHistDate, Allergy allergy, PrevCountry prevCountry) { requireAllNonNull(medHistDate, allergy, prevCountry); @@ -23,30 +27,65 @@ public MedHistory(MedHistDate medHistDate, Allergy allergy, PrevCountry prevCoun this.prevCountry = prevCountry; } - public MedHistDate getMedHistDate() { - return medHistDate; + /** + * Copy constructor. + * A defensive copy of {@code tags} is used internally. + */ + public MedHistory(MedHistory toCopy) { + setMedHistDate(toCopy.medHistDate); + setAllergy(toCopy.allergy); + setPrevCountry(toCopy.prevCountry); + } + + /** + * Returns true if at least one field is edited. + */ + public boolean isAnyFieldEdited() { + return CollectionUtil.isAnyNonNull(medHistDate, allergy, prevCountry); + } + + public void setMedHistDate(MedHistDate medHistDate) { + this.medHistDate = medHistDate; + } + + public Optional getMedHistDate() { + return Optional.ofNullable(medHistDate); } - public Allergy getAllergy() { - return allergy; + + public void setAllergy(Allergy allergy) { + this.allergy = allergy; } - public PrevCountry getPrevCountry() { - return prevCountry; + + public Optional getAllergy() { + return Optional.ofNullable(allergy); + } + + public void setPrevCountry(PrevCountry prevCountry) { + this.prevCountry = prevCountry; + } + + public Optional getPrevCountry() { + return Optional.ofNullable(prevCountry); } @Override public boolean equals(Object other) { + // short circuit if same object if (other == this) { return true; } + // instanceof handles nulls if (!(other instanceof MedHistory)) { return false; } - MedHistory otherPerson = (MedHistory) other; - return otherPerson.getMedHistDate().equals(getMedHistDate()) - && otherPerson.getAllergy().equals(getAllergy()) - && otherPerson.getPrevCountry().equals(getPrevCountry()); + // state check + MedHistory e = (MedHistory) other; + + return getMedHistDate().equals(e.getMedHistDate()) + && getAllergy().equals(e.getAllergy()) + && getPrevCountry().equals(e.getPrevCountry()); } @Override diff --git a/src/main/java/seedu/address/model/medicalreport/Information.java b/src/main/java/seedu/address/model/medicalreport/Information.java index 4fbf6b4f45a9..02b8b04e9237 100644 --- a/src/main/java/seedu/address/model/medicalreport/Information.java +++ b/src/main/java/seedu/address/model/medicalreport/Information.java @@ -2,6 +2,7 @@ import static java.util.Objects.requireNonNull; +//@@author chewkahmeng /** * Represents a Medical Report's information in the address book. */ diff --git a/src/main/java/seedu/address/model/medicalreport/MedicalReport.java b/src/main/java/seedu/address/model/medicalreport/MedicalReport.java index 3464c5314c9d..64275101eb7f 100644 --- a/src/main/java/seedu/address/model/medicalreport/MedicalReport.java +++ b/src/main/java/seedu/address/model/medicalreport/MedicalReport.java @@ -4,6 +4,7 @@ import java.util.Objects; +//@@author chewkahmeng /** * Represents a Person's medical report in the health book. */ diff --git a/src/main/java/seedu/address/model/medicalreport/ReportDate.java b/src/main/java/seedu/address/model/medicalreport/ReportDate.java index 80a02dcecc25..7ff7ec17f8dc 100644 --- a/src/main/java/seedu/address/model/medicalreport/ReportDate.java +++ b/src/main/java/seedu/address/model/medicalreport/ReportDate.java @@ -2,6 +2,11 @@ import static java.util.Objects.requireNonNull; +import java.time.LocalDate; + +import seedu.address.model.util.DateTimeUtil; + +//@@author chewkahmeng /** * Represents a Medical Report's date in the address book. * Guarantees: immutable; is valid as declared in {@link #isValidDate(String)} @@ -9,15 +14,11 @@ public class ReportDate { public static final String MESSAGE_DATE_CONSTRAINTS = - "The full ReportDate should be of the format: DD/MM/YYYY"; - - /* - * The first character of the date must not be a whitespace, - * otherwise " " (a blank string) becomes a valid input. - */ - public static final String DATE_VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*"; + "The full ReportDate should be of the format: DD-MM-YYYY"; + public static final String REPORT_DATE_VALIDATION_REGEX = + "[0-9]{2}" + "[-]" + "[0-9]{2}" + "[-]" + "[0-9]{4}"; - public final String fullDate; + public final LocalDate fullDate; /** * Constructs a {@code ReportDate}. @@ -26,20 +27,20 @@ public class ReportDate { */ public ReportDate(String date) { requireNonNull(date); - fullDate = date; + fullDate = DateTimeUtil.parseDate(date); } /** * Returns true if a given string is a valid date. */ public static boolean isValidDate(String test) { - return test.matches(DATE_VALIDATION_REGEX); + return test.matches(REPORT_DATE_VALIDATION_REGEX); } @Override public String toString() { - return fullDate; + return DateTimeUtil.format(fullDate); } @Override @@ -53,8 +54,4 @@ public boolean equals(Object other) { public int hashCode() { return fullDate.hashCode(); } - - public boolean isFull() { - return true; - } } diff --git a/src/main/java/seedu/address/model/medicalreport/Title.java b/src/main/java/seedu/address/model/medicalreport/Title.java index a734c151944c..b281eb4ffcb3 100644 --- a/src/main/java/seedu/address/model/medicalreport/Title.java +++ b/src/main/java/seedu/address/model/medicalreport/Title.java @@ -2,6 +2,7 @@ import static java.util.Objects.requireNonNull; +//@@author chewkahmeng /** * Represents a Medical Report's title in the address book. * Guarantees: immutable; is valid as declared in {@link #isValidTitle(String)} diff --git a/src/main/java/seedu/address/model/person/AllergyContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/AllergyContainsKeywordsPredicate.java new file mode 100644 index 000000000000..846de299b4d9 --- /dev/null +++ b/src/main/java/seedu/address/model/person/AllergyContainsKeywordsPredicate.java @@ -0,0 +1,36 @@ +package seedu.address.model.person; + +import java.util.List; +import java.util.function.Predicate; + +import seedu.address.commons.util.StringUtil; +import seedu.address.model.medhistory.Allergy; +import seedu.address.model.medhistory.MedHistory; + +/** + * Tests that a {@code Person}'s {@code BloodType} matches any of the keyword given. + */ +public class AllergyContainsKeywordsPredicate implements Predicate { + private final List keywords; + + public AllergyContainsKeywordsPredicate(List keywords) { + this.keywords = keywords; + } + + @Override + public boolean test(MedHistory medHistory) { + Allergy allergy = medHistory.getAllergy().orElse(new Allergy("")); + + return keywords.stream() + .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(allergy.value, keyword)); + } + + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof AllergyContainsKeywordsPredicate // instanceof handles nulls + && keywords.equals(((AllergyContainsKeywordsPredicate) other).keywords)); // state check + } + +} diff --git a/src/main/java/seedu/address/model/person/BloodTypeContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/BloodTypeContainsKeywordsPredicate.java new file mode 100644 index 000000000000..c346e62b3bca --- /dev/null +++ b/src/main/java/seedu/address/model/person/BloodTypeContainsKeywordsPredicate.java @@ -0,0 +1,37 @@ +package seedu.address.model.person; + +import java.util.List; +import java.util.function.Predicate; + +import seedu.address.commons.util.StringUtil; +import seedu.address.model.medhistory.Allergy; +import seedu.address.model.medhistory.MedHistory; + +/** + * Tests that a {@code Person}'s {@code BloodType} matches any of the keyword given. + */ +public class BloodTypeContainsKeywordsPredicate implements Predicate { + private final List keywords; + + public BloodTypeContainsKeywordsPredicate(List keywords) { + this.keywords = keywords; + } + + @Override + public boolean test(MedHistory medHistory) { + Allergy allergy = medHistory.getAllergy().orElse(new Allergy("")); + + return keywords.stream() + .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(allergy.value, keyword)); + // BloodType not properly implemented yet, sticking to allergy first + } + + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof BloodTypeContainsKeywordsPredicate // instanceof handles nulls + && keywords.equals(((BloodTypeContainsKeywordsPredicate) other).keywords)); // state check + } + +} diff --git a/src/main/java/seedu/address/model/person/CountryContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/CountryContainsKeywordsPredicate.java new file mode 100644 index 000000000000..f999a6e6ab69 --- /dev/null +++ b/src/main/java/seedu/address/model/person/CountryContainsKeywordsPredicate.java @@ -0,0 +1,35 @@ +package seedu.address.model.person; + +import java.util.List; +import java.util.function.Predicate; + +import seedu.address.commons.util.StringUtil; +import seedu.address.model.medhistory.MedHistory; +import seedu.address.model.medhistory.PrevCountry; + +/** + * Tests that a {@code Person}'s {@code Last Visited Country} matches any of the keyword given. + */ +public class CountryContainsKeywordsPredicate implements Predicate { + private final List keywords; + + public CountryContainsKeywordsPredicate(List keywords) { + this.keywords = keywords; + } + + @Override + public boolean test(MedHistory medHistory) { + PrevCountry prevCountry = medHistory.getPrevCountry().orElse(new PrevCountry("")); + return keywords.stream() + .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(prevCountry.value, keyword)); + } + + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof CountryContainsKeywordsPredicate // instanceof handles nulls + && keywords.equals(((CountryContainsKeywordsPredicate) other).keywords)); // state check + } + +} diff --git a/src/main/java/seedu/address/model/person/InfoContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/InfoContainsKeywordsPredicate.java new file mode 100644 index 000000000000..5cc8e6f98514 --- /dev/null +++ b/src/main/java/seedu/address/model/person/InfoContainsKeywordsPredicate.java @@ -0,0 +1,35 @@ +package seedu.address.model.person; + +import java.util.List; +import java.util.function.Predicate; + +import seedu.address.commons.util.StringUtil; +import seedu.address.model.medicalreport.MedicalReport; + +/** + * Tests that a {@code Person}'s {@code Medical Report Information} matches any of the keyword given. + */ + +public class InfoContainsKeywordsPredicate implements Predicate { + private final List keywords; + + public InfoContainsKeywordsPredicate(List keywords) { + this.keywords = keywords; + } + + @Override + public boolean test(MedicalReport medicalreport) { + return keywords.stream() + .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(medicalreport.getInformation().fullInformation, + keyword)); + } + + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof InfoContainsKeywordsPredicate // instanceof handles nulls + && keywords.equals(((InfoContainsKeywordsPredicate) other).keywords)); // state check + } + +} diff --git a/src/main/java/seedu/address/model/person/Nric.java b/src/main/java/seedu/address/model/person/Nric.java deleted file mode 100644 index 763832dfb543..000000000000 --- a/src/main/java/seedu/address/model/person/Nric.java +++ /dev/null @@ -1,51 +0,0 @@ -package seedu.address.model.person; - -import static java.util.Objects.requireNonNull; - -/** - * Represents a person's NRIC in Health Book. - */ -public class Nric { - public static final String NRIC_VALIDATION_REGEX = "[ST]" + "[\\d]{7}" + "[A-Z]"; - public static final String MESSAGE_NRIC_CONSTRAINTS = "NRICs should adhere to the following constraints:\n" - + "1. It should begin with either S or T;\n" - + "2. The next 7 characters should be digits between 0 - 9, and;\n" - + "3. It should end of with any alphabet."; - - public final String value; - - /** - * Constructs an {@code Nric}. - * - * @param nric A valid nric. - */ - public Nric(String nric) { - requireNonNull(nric); - value = nric; - } - - /** - * Returns if a given string is a valid NRIC. - */ - public static boolean isValidNric(String test) { - return test.matches(NRIC_VALIDATION_REGEX); - } - - @Override - public String toString() { - return value; - } - - @Override - public boolean equals(Object other) { - return other == this // short circuit if same object - || (other instanceof Nric // instanceof handles nulls - && value.equals(((Nric) other).value)); // state check - } - - @Override - public int hashCode() { - return value.hashCode(); - } - -} diff --git a/src/main/java/seedu/address/model/person/NricContainsKeywordsPredicate.java b/src/main/java/seedu/address/model/person/NricContainsKeywordsPredicate.java new file mode 100644 index 000000000000..908e031814c0 --- /dev/null +++ b/src/main/java/seedu/address/model/person/NricContainsKeywordsPredicate.java @@ -0,0 +1,32 @@ +package seedu.address.model.person; + +import java.util.List; +import java.util.function.Predicate; + +import seedu.address.commons.util.StringUtil; + +/** + * Tests that a {@code Person}'s {@code nric} matches any of the keyword given. + */ +public class NricContainsKeywordsPredicate implements Predicate { + private final List keywords; + + public NricContainsKeywordsPredicate(List keywords) { + this.keywords = keywords; + } + + @Override + public boolean test(Person person) { + return keywords.stream() + .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getNric().value, keyword)); + } + + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof NricContainsKeywordsPredicate // instanceof handles nulls + && keywords.equals(((NricContainsKeywordsPredicate) other).keywords)); // state check + } + +} diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java index 1eb0af0be5fc..8b863a51d375 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/person/Person.java @@ -6,11 +6,17 @@ import java.util.HashSet; import java.util.Objects; import java.util.Set; +import java.util.TreeSet; import seedu.address.model.medhistory.MedHistory; import seedu.address.model.medicalreport.MedicalReport; +import seedu.address.model.person.addinfo.DateOfBirth; +import seedu.address.model.person.addinfo.Height; +import seedu.address.model.person.addinfo.Nric; +import seedu.address.model.person.addinfo.Weight; import seedu.address.model.tag.Tag; import seedu.address.model.timetable.Appt; +import seedu.address.model.timetable.ApptComparator; /** * Represents a Person in the address book. @@ -26,19 +32,23 @@ public class Person { // Data fields private final Address address; private final Set medHistories = new HashSet<>(); - private final Set appts = new HashSet<>(); + private final Set appts = new TreeSet<>(new ApptComparator()); private final Set tags = new HashSet<>(); private final Set reports = new HashSet<>(); // Additional information fields private final Nric nric; private final DateOfBirth dateOfBirth; + private final Height height; + private final Weight weight; + //private final Gender gender; /** * Every field must be present and not null. */ public Person(Name name, Phone phone, Email email, Address address, Set reports, - Set medHistories, Set appts, Nric nric, DateOfBirth dateOfBirth, Set tags) { + Set medHistories, Set appts, Nric nric, DateOfBirth dateOfBirth, Height height, + Weight weight, Set tags) { requireAllNonNull(name, phone, email, address, tags); this.name = name; this.phone = phone; @@ -46,6 +56,8 @@ public Person(Name name, Phone phone, Email email, Address address, Set getMedicalReports() { return Collections.unmodifiableSet(reports); } + //@@author public Set getMedHistory() { return Collections.unmodifiableSet(medHistories); } @@ -84,10 +98,20 @@ public DateOfBirth getDateOfBirth() { return dateOfBirth; } + public Height getHeight() { + return height; + } + + public Weight getWeight() { + return weight; + } + + //@@author brandonccm1996 public Set getAppts() { return Collections.unmodifiableSet(appts); } + //@@author /** * Returns an immutable tag set, which throws {@code UnsupportedOperationException} * if modification is attempted. diff --git a/src/main/java/seedu/address/model/person/BloodType.java b/src/main/java/seedu/address/model/person/addinfo/BloodType.java similarity index 96% rename from src/main/java/seedu/address/model/person/BloodType.java rename to src/main/java/seedu/address/model/person/addinfo/BloodType.java index 096ad2115586..70dea0712197 100644 --- a/src/main/java/seedu/address/model/person/BloodType.java +++ b/src/main/java/seedu/address/model/person/addinfo/BloodType.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package seedu.address.model.person.addinfo; import static java.util.Objects.requireNonNull; import static seedu.address.commons.util.AppUtil.checkArgument; diff --git a/src/main/java/seedu/address/model/person/DateOfBirth.java b/src/main/java/seedu/address/model/person/addinfo/DateOfBirth.java similarity index 81% rename from src/main/java/seedu/address/model/person/DateOfBirth.java rename to src/main/java/seedu/address/model/person/addinfo/DateOfBirth.java index 9807680fd783..ecc92d1390f3 100644 --- a/src/main/java/seedu/address/model/person/DateOfBirth.java +++ b/src/main/java/seedu/address/model/person/addinfo/DateOfBirth.java @@ -1,10 +1,11 @@ -package seedu.address.model.person; +package seedu.address.model.person.addinfo; import static java.util.Objects.requireNonNull; import java.text.ParseException; import java.time.LocalDate; -import java.time.format.DateTimeFormatter; + +import seedu.address.model.util.DateTimeUtil; /** * Represents ReportDate of Birth in Health Book @@ -16,16 +17,15 @@ public class DateOfBirth { public final LocalDate value; - private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); - /** * Constructs a {@code DateOfBirth} * @param value a valid date * @throws ParseException if date format is invalid */ + //TODO: (DateOfBirth) to be an Optional type to support null values public DateOfBirth(String value) { requireNonNull(value); - this.value = LocalDate.parse(value, dateTimeFormatter); + this.value = DateTimeUtil.parseDate(value); } public static boolean isValidDate(String test) { @@ -34,7 +34,7 @@ public static boolean isValidDate(String test) { @Override public String toString() { - return value.format(dateTimeFormatter); + return DateTimeUtil.format(value); } @Override diff --git a/src/main/java/seedu/address/model/person/addinfo/Gender.java b/src/main/java/seedu/address/model/person/addinfo/Gender.java new file mode 100644 index 000000000000..f4ef1138bd9d --- /dev/null +++ b/src/main/java/seedu/address/model/person/addinfo/Gender.java @@ -0,0 +1,39 @@ +package seedu.address.model.person.addinfo; + +import static java.util.Objects.requireNonNull; + +/** + * Represents a person's gender in Health Book. + */ +public class Gender { + public static final String GENDER_VALIDATION_REGEX = "[MF]"; + public static final String MESSAGE_GENDER_CONSTRAINTS = "Gender input can only be either M or F."; + + public final String value; + + public Gender(String gender) { + requireNonNull(gender); + gender.toUpperCase(); + value = gender; + } + + public static boolean isValidGender(String test) { + return test.matches(GENDER_VALIDATION_REGEX); + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this + || (other instanceof Gender && value.equals(((Gender) other).value)); + } + + @Override + public int hashCode() { + return value.hashCode(); + } +} diff --git a/src/main/java/seedu/address/model/person/addinfo/Height.java b/src/main/java/seedu/address/model/person/addinfo/Height.java new file mode 100644 index 000000000000..e1c26d02754e --- /dev/null +++ b/src/main/java/seedu/address/model/person/addinfo/Height.java @@ -0,0 +1,48 @@ +package seedu.address.model.person.addinfo; + +import static java.util.Objects.requireNonNull; + +/** + * Represents a person's height in Health Book + */ +public class Height { + public static final String HEIGHT_VALIDATION_REGEX = "[\\d]+"; + public static final String MESSAGE_HEIGHT_CONSTRAINTS = "Height should be numeric input only."; + + public final String value; + + /** + * Constructs an {@code Height}. + * + * @param height A valid height. + */ + public Height(String height) { + requireNonNull(height); + value = height; + } + + /** + * + * Returns if a given string is a valid Height + */ + public static boolean isValidHeight(String test) { + return test.matches(HEIGHT_VALIDATION_REGEX); + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this + || (other instanceof Height + && value.equals(((Height) other).value)); + } + + @Override + public int hashCode() { + return value.hashCode(); + } +} diff --git a/src/main/java/seedu/address/model/person/addinfo/Nric.java b/src/main/java/seedu/address/model/person/addinfo/Nric.java new file mode 100644 index 000000000000..fabe49b19063 --- /dev/null +++ b/src/main/java/seedu/address/model/person/addinfo/Nric.java @@ -0,0 +1,100 @@ +package seedu.address.model.person.addinfo; + +import static java.util.Objects.requireNonNull; + +/** + * Represents a person's NRIC in Health Book. + */ +public class Nric { + public static final String MESSAGE_NRIC_CONSTRAINTS = "NRICs should adhere to the following constraints:\n" + + "1. It should begin with either S or T;\n" + + "2. The next 7 characters should be digits between 0 - 9, and;\n" + + "3. It should end of with any alphabet."; + public static final String MESSAGE_NRIC_INVALID = "The input NRIC is not correct. Please check again."; + + private static final String NRIC_VALIDATION_REGEX = "[ST]" + "[\\d]{7}" + "[A-Z]"; + private static final int CHECKSUM_ADDITIONAL_DIGIT = 4; + private static final int CHECKSUM_MODULO_DIGIT = 11; + + public final String value; + + /** + * Constructs an {@code Nric}. + * + * @param nric A valid nric. + */ + public Nric(String nric) { + requireNonNull(nric); + value = nric; + } + + /** + * Returns if a given string is a valid NRIC. + */ + public static boolean isValidNric(String test) { + return test.matches(NRIC_VALIDATION_REGEX); + } + + /** + * Returns if a given string is a correct NRIC. + */ + public static boolean isCorrectNric(String test) { + final int[] weight = {2, 7, 6, 5, 4, 3, 2}; + + char[] input = test.toCharArray(); + int sum = 0; + + for (int i = 0; i < weight.length; i++) { + sum += weight[i] * Character.getNumericValue(input[i + 1]); + } + + if (input[0] == 'T') { + sum += CHECKSUM_ADDITIONAL_DIGIT; + } + + switch (sum % CHECKSUM_MODULO_DIGIT) { + case 10: + return (input[input.length - 1] == 'A'); + case 9: + return (input[input.length - 1] == 'B'); + case 8: + return (input[input.length - 1] == 'C'); + case 7: + return (input[input.length - 1] == 'D'); + case 6: + return (input[input.length - 1] == 'E'); + case 5: + return (input[input.length - 1] == 'F'); + case 4: + return (input[input.length - 1] == 'G'); + case 3: + return (input[input.length - 1] == 'H'); + case 2: + return (input[input.length - 1] == 'I'); + case 1: + return (input[input.length - 1] == 'Z'); + case 0: + + return (input[input.length - 1] == 'J'); + default: + return false; + } + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof Nric // instanceof handles nulls + && value.equals(((Nric) other).value)); // state check + } + + @Override + public int hashCode() { + return value.hashCode(); + } +} diff --git a/src/main/java/seedu/address/model/person/addinfo/Weight.java b/src/main/java/seedu/address/model/person/addinfo/Weight.java new file mode 100644 index 000000000000..b562fe467ed7 --- /dev/null +++ b/src/main/java/seedu/address/model/person/addinfo/Weight.java @@ -0,0 +1,48 @@ +package seedu.address.model.person.addinfo; + +import static java.util.Objects.requireNonNull; + +/** + * Represents a person's Weight in Health Book. + */ +public class Weight { + public static final String WEIGHT_VALIDATION_REGEX = "[\\d]+"; + public static final String MESSAGE_WEIGHT_CONSTRAINTS = "Weight should be numeric input only."; + + public final String value; + + /** + * Constructs an {@code Height}. + * + * @param weight A valid weight. + */ + public Weight(String weight) { + requireNonNull(weight); + value = weight; + } + + /** + * + * Returns if a given string is a valid Height + */ + public static boolean isValidWeight(String test) { + return test.matches(WEIGHT_VALIDATION_REGEX); + } + + @Override + public String toString() { + return value; + } + + @Override + public boolean equals(Object other) { + return other == this + || (other instanceof Weight + && value.equals(((Weight) other).value)); + } + + @Override + public int hashCode() { + return value.hashCode(); + } +} diff --git a/src/main/java/seedu/address/model/timetable/Appt.java b/src/main/java/seedu/address/model/timetable/Appt.java index b4aa04eb2642..b7bffcda2664 100644 --- a/src/main/java/seedu/address/model/timetable/Appt.java +++ b/src/main/java/seedu/address/model/timetable/Appt.java @@ -4,6 +4,7 @@ import java.util.Objects; +//@@author brandonccm1996 /** * Represents a Person's remark in the address book. * Guarantees: immutable; is always valid diff --git a/src/main/java/seedu/address/model/timetable/ApptComparator.java b/src/main/java/seedu/address/model/timetable/ApptComparator.java new file mode 100644 index 000000000000..7031adc4829c --- /dev/null +++ b/src/main/java/seedu/address/model/timetable/ApptComparator.java @@ -0,0 +1,20 @@ +package seedu.address.model.timetable; + +import java.util.Comparator; + +//@@author brandonccm1996 +/** + * A comparator class to compare Appts according to start date and end date + */ +public class ApptComparator implements Comparator { + + @Override + public int compare(Appt o1, Appt o2) { + if (!o1.getStart().value.equals(o2.getStart().value)) { + return o1.getStart().value.compareTo(o2.getStart().value); + } + else { + return o1.getEnd().value.compareTo(o2.getEnd().value); + } + } +} diff --git a/src/main/java/seedu/address/model/timetable/ApptDateTime.java b/src/main/java/seedu/address/model/timetable/ApptDateTime.java index ce012de584db..a29f776cad66 100644 --- a/src/main/java/seedu/address/model/timetable/ApptDateTime.java +++ b/src/main/java/seedu/address/model/timetable/ApptDateTime.java @@ -2,24 +2,35 @@ import static java.util.Objects.requireNonNull; +import java.time.LocalDateTime; + +import seedu.address.model.util.DateTimeUtil; + +//@@author brandonccm1996 /** * Represents an appt date and time in an appt in the address book. * Guarantees: immutable; is always valid */ public class ApptDateTime { - public static final String MESSAGE_NAME_CONSTRAINTS = "The full ReportDate and Time should be of the format: " - + "DD/MM/YYYY HH:MM."; + public static final String MESSAGE_NAME_CONSTRAINTS = + "The start and end Appt Date and Time should be of the format: " + "DD-MM-YYYY HH:MM"; + public static final String APPT_DATETIME_VALIDATION_REGEX = + "[0-9]{2}" + "[-]" + "[0-9]{2}" + "[-]" + "[0-9]{4}" + "[ ]" + "[0-9]{2}" + "[:]" + "[0-9]{2}"; - public final String value; + public final LocalDateTime value; public ApptDateTime(String apptDateTime) { requireNonNull(apptDateTime); - value = apptDateTime; + value = DateTimeUtil.parseDateTime(apptDateTime); + } + + public static boolean isValidDateTime(String test) { + return test.matches(APPT_DATETIME_VALIDATION_REGEX); } @Override public String toString() { - return value; + return DateTimeUtil.format(value); } @Override diff --git a/src/main/java/seedu/address/model/timetable/ApptDrName.java b/src/main/java/seedu/address/model/timetable/ApptDrName.java index a2b60057e6c4..873f848e9bad 100644 --- a/src/main/java/seedu/address/model/timetable/ApptDrName.java +++ b/src/main/java/seedu/address/model/timetable/ApptDrName.java @@ -2,6 +2,7 @@ import static java.util.Objects.requireNonNull; +//@@author brandonccm1996 /** * Represents a doctor (taking an appt) in an appt in the address book. * Guarantees: immutable; is always valid diff --git a/src/main/java/seedu/address/model/timetable/ApptInfo.java b/src/main/java/seedu/address/model/timetable/ApptInfo.java index a51e748a3033..0bd01b1c006e 100644 --- a/src/main/java/seedu/address/model/timetable/ApptInfo.java +++ b/src/main/java/seedu/address/model/timetable/ApptInfo.java @@ -2,6 +2,7 @@ import static java.util.Objects.requireNonNull; +//@@author brandonccm1996 /** * Represents appt info in an appt in the address book. * Guarantees: immutable; is always valid diff --git a/src/main/java/seedu/address/model/timetable/ApptVenue.java b/src/main/java/seedu/address/model/timetable/ApptVenue.java index 3698a1e91ea9..00a1d32f2891 100644 --- a/src/main/java/seedu/address/model/timetable/ApptVenue.java +++ b/src/main/java/seedu/address/model/timetable/ApptVenue.java @@ -2,6 +2,7 @@ import static java.util.Objects.requireNonNull; +//@@author brandonccm1996 /** * Represents an appt venue in an appt in the address book. * Guarantees: immutable; is always valid diff --git a/src/main/java/seedu/address/model/util/DateTimeUtil.java b/src/main/java/seedu/address/model/util/DateTimeUtil.java new file mode 100644 index 000000000000..4b1bfc09877b --- /dev/null +++ b/src/main/java/seedu/address/model/util/DateTimeUtil.java @@ -0,0 +1,58 @@ +package seedu.address.model.util; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; + +/** + * Helper functions for LocalDate and LocalDateTime conversion to and from String + */ +public class DateTimeUtil { + private static final String DATE_PATTERN = "dd-MM-yyyy"; + private static DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern(DATE_PATTERN); + private static final String DATETIME_PATTERN = "dd-MM-yyyy HH:mm"; + private static DateTimeFormatter DATETIME_FORMATTER = DateTimeFormatter.ofPattern(DATETIME_PATTERN); + + /** + * convert LocalDate to String + */ + public static String format(LocalDate date) { + if (date == null) { + return null; + } + return DATE_FORMATTER.format(date); + } + + /** + * convert LocalDateTime to String + */ + public static String format(LocalDateTime dateTime) { + if (dateTime == null) { + return null; + } + return DATETIME_FORMATTER.format(dateTime); + } + + /** + * convert String to LocalDate + * + * @param dateString String to be converted + * @return parsed local-date, not null + * @throws DateTimeParseException if String cannot be parsed + */ + public static LocalDate parseDate(String dateString) throws DateTimeParseException { + return LocalDate.parse(dateString, DATE_FORMATTER); + } + + /** + * convert String to LocalDateTime + * + * @param dateTimeString String to be converted + * @return parsed local-date-time, not null + * @throws DateTimeParseException if String cannot be parsed + */ + public static LocalDateTime parseDateTime(String dateTimeString) throws DateTimeParseException { + return LocalDateTime.parse(dateTimeString, DATETIME_FORMATTER); + } +} diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java index a511370663ba..07ddc22f2d69 100644 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ b/src/main/java/seedu/address/model/util/SampleDataUtil.java @@ -10,12 +10,14 @@ import seedu.address.model.medhistory.MedHistory; import seedu.address.model.medicalreport.MedicalReport; import seedu.address.model.person.Address; -import seedu.address.model.person.DateOfBirth; import seedu.address.model.person.Email; import seedu.address.model.person.Name; -import seedu.address.model.person.Nric; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; +import seedu.address.model.person.addinfo.DateOfBirth; +import seedu.address.model.person.addinfo.Height; +import seedu.address.model.person.addinfo.Nric; +import seedu.address.model.person.addinfo.Weight; import seedu.address.model.tag.Tag; import seedu.address.model.timetable.Appt; @@ -26,31 +28,34 @@ public class SampleDataUtil { public static final Nric EMPTY_NRIC = new Nric(""); public static final DateOfBirth EMPTY_DATE_OF_BIRTH = new DateOfBirth("01-01-1970"); + public static final Height EMPTY_HEIGHT = new Height(""); + public static final Weight EMPTY_WEIGHT = new Weight(""); public static Person[] getSamplePersons() { return new Person[] { new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), new Address("Blk 30 Geylang Street 29, #06-40"), getReportSet(), - getMedHistorySet(), getApptSet(), EMPTY_NRIC, EMPTY_DATE_OF_BIRTH, getTagSet("friends")), + getMedHistorySet(), getApptSet(), EMPTY_NRIC, EMPTY_DATE_OF_BIRTH, new Height("42"), EMPTY_WEIGHT, + getTagSet("friends")), new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"), new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"), getReportSet(), - getMedHistorySet(), getApptSet(), EMPTY_NRIC, EMPTY_DATE_OF_BIRTH, + getMedHistorySet(), getApptSet(), EMPTY_NRIC, EMPTY_DATE_OF_BIRTH, EMPTY_HEIGHT, EMPTY_WEIGHT, getTagSet("colleagues", "friends")), new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"), new Address("Blk 11 Ang Mo Kio Street 74, #11-04"), getReportSet(), - getMedHistorySet(), getApptSet(), EMPTY_NRIC, EMPTY_DATE_OF_BIRTH, + getMedHistorySet(), getApptSet(), EMPTY_NRIC, EMPTY_DATE_OF_BIRTH, EMPTY_HEIGHT, EMPTY_WEIGHT, getTagSet("neighbours")), new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"), new Address("Blk 436 Serangoon Gardens Street 26, #16-43"), getReportSet(), - getMedHistorySet(), getApptSet(), EMPTY_NRIC, EMPTY_DATE_OF_BIRTH, + getMedHistorySet(), getApptSet(), EMPTY_NRIC, EMPTY_DATE_OF_BIRTH, EMPTY_HEIGHT, EMPTY_WEIGHT, getTagSet("family")), new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"), new Address("Blk 47 Tampines Street 20, #17-35"), getReportSet(), - getMedHistorySet(), getApptSet(), EMPTY_NRIC, EMPTY_DATE_OF_BIRTH, + getMedHistorySet(), getApptSet(), EMPTY_NRIC, EMPTY_DATE_OF_BIRTH, EMPTY_HEIGHT, EMPTY_WEIGHT, getTagSet("classmates")), new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), new Address("Blk 45 Aljunied Street 85, #11-31"), getReportSet(), - getMedHistorySet(), getApptSet(), EMPTY_NRIC, EMPTY_DATE_OF_BIRTH, + getMedHistorySet(), getApptSet(), EMPTY_NRIC, EMPTY_DATE_OF_BIRTH, EMPTY_HEIGHT, EMPTY_WEIGHT, getTagSet("colleagues")) }; } @@ -95,6 +100,7 @@ public static Set getReportSet(MedicalReport ... reports) { return reportSet; } + //@@author brandonccm1996 /** * Returns an appt set containing the list of appts given. */ diff --git a/src/main/java/seedu/address/storage/XmlAdaptedAppt.java b/src/main/java/seedu/address/storage/XmlAdaptedAppt.java index 8c0447c90611..2a8e4dd88901 100644 --- a/src/main/java/seedu/address/storage/XmlAdaptedAppt.java +++ b/src/main/java/seedu/address/storage/XmlAdaptedAppt.java @@ -11,6 +11,7 @@ import seedu.address.model.timetable.ApptInfo; import seedu.address.model.timetable.ApptVenue; +//@@author brandonccm1996 /** * JAXB-friendly version of the Appt. */ diff --git a/src/main/java/seedu/address/storage/XmlAdaptedMedHistory.java b/src/main/java/seedu/address/storage/XmlAdaptedMedHistory.java index 9de5e980f642..b055427157e7 100644 --- a/src/main/java/seedu/address/storage/XmlAdaptedMedHistory.java +++ b/src/main/java/seedu/address/storage/XmlAdaptedMedHistory.java @@ -47,9 +47,14 @@ public XmlAdaptedMedHistory(String medHistDate, String allergy, String prevCount */ public XmlAdaptedMedHistory(MedHistory source) { - medHistDate = source.getMedHistDate().toString(); - allergy = source.getAllergy().toString(); - prevCountry = source.getPrevCountry().toString(); + MedHistDate medHistDate = source.getMedHistDate().orElse(new MedHistDate("")); + this.medHistDate = medHistDate.toString(); + + Allergy allergy = source.getAllergy().orElse(new Allergy("")); + this.allergy = allergy.toString(); + + PrevCountry prevCountry = source.getPrevCountry().orElse(new PrevCountry("")); + this.prevCountry = prevCountry.toString(); } /** diff --git a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java b/src/main/java/seedu/address/storage/XmlAdaptedPerson.java index 975712f80c3f..990f33ba015d 100644 --- a/src/main/java/seedu/address/storage/XmlAdaptedPerson.java +++ b/src/main/java/seedu/address/storage/XmlAdaptedPerson.java @@ -13,12 +13,14 @@ import seedu.address.model.medhistory.MedHistory; import seedu.address.model.medicalreport.MedicalReport; import seedu.address.model.person.Address; -import seedu.address.model.person.DateOfBirth; import seedu.address.model.person.Email; import seedu.address.model.person.Name; -import seedu.address.model.person.Nric; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; +import seedu.address.model.person.addinfo.DateOfBirth; +import seedu.address.model.person.addinfo.Height; +import seedu.address.model.person.addinfo.Nric; +import seedu.address.model.person.addinfo.Weight; import seedu.address.model.tag.Tag; import seedu.address.model.timetable.Appt; @@ -36,18 +38,24 @@ public class XmlAdaptedPerson { private String email; @XmlElement(required = true) private String address; + @XmlElement + private List tagged = new ArrayList<>(); + @XmlElement(required = true) private String nric; @XmlElement(required = true) private String dateOfBirth; + @XmlElement(required = true) + private String height; + @XmlElement(required = true) + private String weight; + @XmlElement private List reports = new ArrayList<>(); @XmlElement private List medHistories = new ArrayList<>(); @XmlElement private List appts = new ArrayList<>(); - @XmlElement - private List tagged = new ArrayList<>(); /** * Constructs an XmlAdaptedPerson. @@ -89,12 +97,16 @@ public XmlAdaptedPerson(Person source) { phone = source.getPhone().value; email = source.getEmail().value; address = source.getAddress().value; + tagged = source.getTags().stream().map(XmlAdaptedTag::new).collect(Collectors.toList()); + nric = source.getNric().value; dateOfBirth = source.getDateOfBirth().toString(); + height = source.getHeight().value; + weight = source.getWeight().value; + reports = source.getMedicalReports().stream().map(XmlAdaptedReport::new).collect(Collectors.toList()); medHistories = source.getMedHistory().stream().map(XmlAdaptedMedHistory::new).collect(Collectors.toList()); appts = source.getAppts().stream().map(XmlAdaptedAppt::new).collect(Collectors.toList()); - tagged = source.getTags().stream().map(XmlAdaptedTag::new).collect(Collectors.toList()); } /** @@ -152,6 +164,16 @@ public Person toModelType() throws IllegalValueException { } final DateOfBirth modelDateOfBirth = new DateOfBirth(dateOfBirth); + if (height == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Height.class.getSimpleName())); + } + final Height modelHeight = new Height(height); + + if (weight == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Weight.class.getSimpleName())); + } + final Weight modelWeight = new Weight(weight); + /** * ================================================== * SUBFIELDS IN LIST FORMAT @@ -170,12 +192,14 @@ public Person toModelType() throws IllegalValueException { } final Set modelMedHistory = new HashSet<>(personMedHistories); + //@@author brandonccm1996 final List personAppts = new ArrayList<>(); for (XmlAdaptedAppt appt : appts) { personAppts.add(appt.toModelType()); } final Set modelAppts = new HashSet<>(personAppts); + //@@author final List personTags = new ArrayList<>(); for (XmlAdaptedTag tag : tagged) { personTags.add(tag.toModelType()); @@ -183,7 +207,8 @@ public Person toModelType() throws IllegalValueException { final Set modelTags = new HashSet<>(personTags); return new Person(modelName, modelPhone, modelEmail, modelAddress, modelReports, - modelMedHistory, modelAppts, modelNric, modelDateOfBirth, modelTags); + modelMedHistory, modelAppts, modelNric, modelDateOfBirth, modelHeight, modelWeight, + modelTags); } @Override diff --git a/src/main/java/seedu/address/storage/XmlAdaptedReport.java b/src/main/java/seedu/address/storage/XmlAdaptedReport.java index ee15b2ab7535..0ef8374735dd 100644 --- a/src/main/java/seedu/address/storage/XmlAdaptedReport.java +++ b/src/main/java/seedu/address/storage/XmlAdaptedReport.java @@ -10,6 +10,7 @@ import seedu.address.model.medicalreport.ReportDate; import seedu.address.model.medicalreport.Title; +//@@author chewkahmeng /** * JAXB-friendly version of the Report. */ diff --git a/src/main/java/seedu/address/ui/BrowserPanel.java b/src/main/java/seedu/address/ui/BrowserPanel.java deleted file mode 100644 index b43de90a2b9f..000000000000 --- a/src/main/java/seedu/address/ui/BrowserPanel.java +++ /dev/null @@ -1,72 +0,0 @@ -package seedu.address.ui; - -import java.net.URL; -import java.util.logging.Logger; - -import com.google.common.eventbus.Subscribe; - -import javafx.application.Platform; -import javafx.event.Event; -import javafx.fxml.FXML; -import javafx.scene.layout.Region; -import javafx.scene.web.WebView; -import seedu.address.MainApp; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.events.ui.PersonPanelSelectionChangedEvent; -import seedu.address.model.person.Person; - -/** - * The Browser Panel of the App. - */ -public class BrowserPanel extends UiPart { - - public static final String DEFAULT_PAGE = "default.html"; - public static final String SEARCH_PAGE_URL = - "https://se-edu.github.io/addressbook-level4/DummySearchPage.html?name="; - - private static final String FXML = "BrowserPanel.fxml"; - - private final Logger logger = LogsCenter.getLogger(getClass()); - - @FXML - private WebView browser; - - public BrowserPanel() { - super(FXML); - - // To prevent triggering events for typing inside the loaded Web page. - getRoot().setOnKeyPressed(Event::consume); - - loadDefaultPage(); - registerAsAnEventHandler(this); - } - - private void loadPersonPage(Person person) { - loadPage(SEARCH_PAGE_URL + person.getName().fullName); - } - - public void loadPage(String url) { - Platform.runLater(() -> browser.getEngine().load(url)); - } - - /** - * Loads a default HTML file with a background that matches the general theme. - */ - private void loadDefaultPage() { - URL defaultPage = MainApp.class.getResource(FXML_FILE_FOLDER + DEFAULT_PAGE); - loadPage(defaultPage.toExternalForm()); - } - - /** - * Frees resources allocated to the browser. - */ - public void freeResources() { - browser = null; - } - - @Subscribe - private void handlePersonPanelSelectionChangedEvent(PersonPanelSelectionChangedEvent event) { - logger.info(LogsCenter.getEventHandlingLogMessage(event)); - loadPersonPage(event.getNewSelection()); - } -} diff --git a/src/main/java/seedu/address/ui/InfoPanel.java b/src/main/java/seedu/address/ui/InfoPanel.java new file mode 100644 index 000000000000..428ddb899f3c --- /dev/null +++ b/src/main/java/seedu/address/ui/InfoPanel.java @@ -0,0 +1,102 @@ +package seedu.address.ui; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.control.ScrollPane; +import javafx.scene.layout.AnchorPane; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.Region; + +import seedu.address.model.person.Person; + +/** + * The Info Panel of the App. + */ +public class InfoPanel extends UiPart { + private static final String FXML = "InfoPanel.fxml"; + private Person person; + + @FXML + private ScrollPane infoScrollPane; + @FXML + private AnchorPane additionalInfo; + @FXML + private AnchorPane medHistory; + @FXML + private AnchorPane medAppts; + @FXML + private AnchorPane medReports; + + @FXML + private Label nameLabel1; + @FXML + private Label nameLabel2; + @FXML + private Label nameLabel3; + @FXML + private Label nameLabel4; + + @FXML + private Label nricLabel; + @FXML + private FlowPane medHistoriesFlowPane; + @FXML + private FlowPane apptsFlowPane; + @FXML + private FlowPane medReportsFlowPane; + + public InfoPanel() { + super(FXML); + } + + public void setPerson(Person person) { + this.person = person; + + initialiseNameLabels(); + fillAdditionalInfoPane(); + fillMedHistoriesPane(); + fillApptsPane(); + fillMedReportsPane(); + } + + /** + * Initialises the name labels in all anchor panes + */ + private void initialiseNameLabels() { + nameLabel1.setText("Additional Info for " + person.getName()); + nameLabel2.setText("Medical History for " + person.getName()); + nameLabel3.setText("Appt Timetable for " + person.getName()); + nameLabel4.setText("Medical Reports for " + person.getName()); + } + + private void fillAdditionalInfoPane() { + additionalInfo.setStyle("-fx-background-color: #FCFCFC"); + nricLabel.setText(person.getNric().value); + } + + private void fillMedHistoriesPane() { + medHistory.setStyle("-fx-background-color: #ECECEC"); + person.getMedHistory().forEach(medHistory -> + medHistoriesFlowPane.getChildren().add(new Label(medHistory.toString()))); + } + + private void fillApptsPane() { + medAppts.setStyle("-fx-background-color: #DCDCDC"); + person.getAppts().forEach(appt -> apptsFlowPane.getChildren().add(new Label(appt.toString()))); + } + + private void fillMedReportsPane() { + medReports.setStyle("-fx-background-color: #CCCCCC"); + person.getMedicalReports().forEach(report -> + medReportsFlowPane.getChildren().add(new Label(report.toString()))); + } + + /** + * Empties flowpanes in all anchorpanes + */ + public void clearFlowPanes() { + medHistoriesFlowPane.getChildren().clear(); + medReportsFlowPane.getChildren().clear(); + apptsFlowPane.getChildren().clear(); + } +} diff --git a/src/main/java/seedu/address/ui/MainWindow.java b/src/main/java/seedu/address/ui/MainWindow.java index 0e361a4d7baf..68a5825016ca 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/seedu/address/ui/MainWindow.java @@ -19,6 +19,7 @@ import seedu.address.commons.events.ui.ShowHelpRequestEvent; import seedu.address.logic.Logic; import seedu.address.model.UserPrefs; +import seedu.address.model.person.Person; /** * The Main Window. Provides the basic application layout containing @@ -34,14 +35,14 @@ public class MainWindow extends UiPart { private Logic logic; // Independent Ui parts residing in this Ui container - private BrowserPanel browserPanel; + private InfoPanel infoPanel; private PersonListPanel personListPanel; private Config config; private UserPrefs prefs; private HelpWindow helpWindow; @FXML - private StackPane browserPlaceholder; + private StackPane infoPanelPlaceholder; @FXML private StackPane commandBoxPlaceholder; @@ -119,8 +120,8 @@ private void setAccelerator(MenuItem menuItem, KeyCombination keyCombination) { * Fills up all the placeholders of this window. */ void fillInnerParts() { - browserPanel = new BrowserPanel(); - browserPlaceholder.getChildren().add(browserPanel.getRoot()); + infoPanel = new InfoPanel(); + infoPanelPlaceholder.getChildren().add(infoPanel.getRoot()); personListPanel = new PersonListPanel(logic.getFilteredPersonList()); personListPanelPlaceholder.getChildren().add(personListPanel.getRoot()); @@ -191,13 +192,19 @@ public PersonListPanel getPersonListPanel() { return personListPanel; } - void releaseResources() { - browserPanel.freeResources(); - } + //void releaseResources() { + //browserPanel.freeResources(); + //} @Subscribe private void handleShowHelpEvent(ShowHelpRequestEvent event) { logger.info(LogsCenter.getEventHandlingLogMessage(event)); handleHelp(); } + + //@@author brandonccm1996 + void showPersonDetails(Person person) { + infoPanel.clearFlowPanes(); + infoPanel.setPerson(person); + } } diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java index 37dd85ba3396..d525320170b5 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/PersonCard.java @@ -41,6 +41,10 @@ public class PersonCard extends UiPart { @FXML private Label dateOfBirth; @FXML + private Label height; + @FXML + private Label weight; + @FXML private FlowPane reports; @FXML private FlowPane appts; @@ -57,8 +61,12 @@ public PersonCard(Person person, int displayedIndex) { phone.setText(person.getPhone().value); address.setText(person.getAddress().value); email.setText(person.getEmail().value); + + // TODO: Split the static text from dynamic text in UI nric.setText(person.getNric().value); - dateOfBirth.setText(person.getDateOfBirth().toString()); + dateOfBirth.setText("Date Of Birth: " + person.getDateOfBirth().toString()); + height.setText("Height: " + person.getHeight().value); + weight.setText("Weight: " + person.getWeight().value); person.getMedHistory().forEach(medHistory -> medHistories.getChildren().add(new Label(medHistory.toString()))); person.getMedicalReports().forEach(report -> reports.getChildren().add(new Label(report.toString()))); person.getAppts().forEach(appt -> appts.getChildren().add(new Label(appt.toString()))); diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/seedu/address/ui/UiManager.java index 3fd3c17be156..f75e3e786ccc 100644 --- a/src/main/java/seedu/address/ui/UiManager.java +++ b/src/main/java/seedu/address/ui/UiManager.java @@ -14,6 +14,7 @@ import seedu.address.commons.core.Config; import seedu.address.commons.core.LogsCenter; import seedu.address.commons.events.storage.DataSavingExceptionEvent; +import seedu.address.commons.events.ui.PersonPanelSelectionChangedEvent; import seedu.address.commons.util.StringUtil; import seedu.address.logic.Logic; import seedu.address.model.UserPrefs; @@ -66,7 +67,7 @@ public void start(Stage primaryStage) { public void stop() { prefs.updateLastUsedGuiSetting(mainWindow.getCurrentGuiSetting()); mainWindow.hide(); - mainWindow.releaseResources(); + //mainWindow.releaseResources(); } private void showFileOperationAlertAndWait(String description, String details, Throwable cause) { @@ -117,4 +118,11 @@ private void handleDataSavingExceptionEvent(DataSavingExceptionEvent event) { showFileOperationAlertAndWait(FILE_OPS_ERROR_DIALOG_HEADER_MESSAGE, FILE_OPS_ERROR_DIALOG_CONTENT_MESSAGE, event.exception); } + + //@@author brandonccm1996 + @Subscribe + private void handlePersonPanelSelectionChangedEvent(PersonPanelSelectionChangedEvent event) { + logger.info(LogsCenter.getEventHandlingLogMessage(event)); + mainWindow.showPersonDetails(event.getNewSelection()); + } } diff --git a/src/main/resources/view/BrowserPanel.fxml b/src/main/resources/view/BrowserPanel.fxml deleted file mode 100644 index 31670827e3da..000000000000 --- a/src/main/resources/view/BrowserPanel.fxml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - - diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css index c8941ea18263..7db4f87847a5 100644 --- a/src/main/resources/view/DarkTheme.css +++ b/src/main/resources/view/DarkTheme.css @@ -306,6 +306,10 @@ -fx-padding: 8 1 8 1; } +.infoPanelNameLabel { + -fx-font-size: 20px; +} + #cardPane { -fx-background-color: transparent; -fx-border-width: 0; diff --git a/src/main/resources/view/InfoPanel.fxml b/src/main/resources/view/InfoPanel.fxml new file mode 100644 index 000000000000..5738796b310c --- /dev/null +++ b/src/main/resources/view/InfoPanel.fxml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index daf386d8f5b8..7c0136028584 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -54,7 +54,7 @@ - + diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml index e85f39efdb58..b2144b26a821 100644 --- a/src/main/resources/view/PersonListCard.fxml +++ b/src/main/resources/view/PersonListCard.fxml @@ -33,6 +33,8 @@