Skip to content

Commit

Permalink
Merge pull request #189 from Jollybomber/master
Browse files Browse the repository at this point in the history
Update UG and DG
  • Loading branch information
Jollybomber authored Nov 7, 2024
2 parents 271a795 + 98b4e49 commit e9681cf
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 36 deletions.
77 changes: 62 additions & 15 deletions docs/DeveloperGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,19 +463,19 @@ testers are expected to do more *exploratory* testing.

1. Initial launch

1. Download the jar file and copy into an empty folder
1a. Download the jar file and copy into an empty folder

1. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.
1b. Double-click the jar file Expected: Shows the GUI with a set of sample contacts. The window size may not be optimum.

1. Saving window preferences
2. Saving window preferences

1. Resize the window to an optimum size. Move the window to a different location. Close the window.
2a. Resize the window to an optimum size. Move the window to a different location. Close the window.

1. Re-launch the app by double-clicking the jar file.<br>
2b. Re-launch the app by double-clicking the jar file.<br>
Expected: The most recent window size and location is retained.

1. _{ more test cases …​ }_
2.
3. _{ more test cases …​ }_

### Adding a person

1. Adding a tutor with no email
Expand All @@ -487,18 +487,65 @@ testers are expected to do more *exploratory* testing.

1. Deleting a person while all persons are being shown

1. Prerequisites: List all persons using the `list` command. Multiple persons in the list.
1a. Prerequisites: List all persons using the `list` command. Multiple persons in the list.

1. Test case: `delete 1`<br>
Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
1b. Test case: `delete 1`<br>
Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.

1. Test case: `delete 0`<br>
Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
1c. Test case: `delete 0`<br>
Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.

1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)<br>
Expected: Similar to previous.
1d. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)<br>
Expected: Similar to previous.

1. _{ more test cases …​ }_
2. _{ more test cases …​ }_

### Adding a tutor

1. Adding a tutor with all fields filled

1a. Test case: `addTutor \n Alice \p 81234567 \e [email protected] \a Block 123, Alice Street, 123456 \h 20 \s math`<br>
Expected: New contact is added to the list. Details of the new contact shown in the status message.

1b. Test case: `addTutor \n Bob \p 98765432 \e invalid \a Block 123, Bob Street, 223456` <br>
Expected: No contact is added. Error details shown in the status message for invalid email.

1c. Other incorrect add tutor commands to try: `addTutor \x y` (where x is a tag and y is an invalid value for that field)<br>
Expected: Similar to previous.
2. _{ more test cases …​ }_

### Editing a tutor

1. Editing a tutor with all fields filled

1a. Prerequisites: Add a tutor with the command `addTutor \n Alice \p 81234567 \e [email protected] \a Block 123, Alice Street, 123456 \h 20 \s math`. <br>
Add another tutor with the command `addTutor \n Bob \p 98765432 \e [email protected] \a Block 123, Bob Street, 223456 \h 20 \s math`.

1b. Test case: `edit 1 \n Alicia`<br>
Expected: Contact is updated in the list. Details of the updated contact shown in the status message.

1c. Test case: `edit 2 \n Alice`<br>
Expected: No contact is updated. Error details shown in the status message for duplicate name.

1d. Other incorrect edit tutor commands to try: `edit 1 \x y` (where x is a tag and y is an invalid value for that field)<br>
Expected: Similar to previous.

2. _{ more test cases …​ }_

### Find subjects

1. Finding tutors by subject

1a. Prerequisites: Add a tutor with the command `addTutor \n Alice \p 81234567 \e [email protected] \a Block 123, Alice Street, 123456 \h 20 \s math`. <br>
Add another tutor with the command `addTutor \n Bob \p 98765432 \e [email protected] \a Block 123, Bob Street, 223456 \h 20 \s science`.

1b. Test case: `findSubject math`<br>
Expected: List of tutors (only Alice) with the subject `math` is shown.

1c. Test case: `findSubject chinese`<br>
Expected: No tutor is found. Error details shown in the status message.

2. _{ more test cases …​ }_

### Saving data

Expand Down
85 changes: 74 additions & 11 deletions docs/UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ Format: `findSubject SUBJECT [MORE_SUBJECTS]`
* The order of the keywords does not matter. e.g., `math science` will match `science math`
* Only the subject field is searched.
* Only full words will be matched e.g., `mat` will not match `math`
* Persons matching at least one keyword will be returned (i.e., `OR` search).
* Persons matching at least one keyword will be returned (i.e., `OR` search).
e.g., `math science` will return persons with subjects `Math`, `Science`, `Math and Science`

Examples:
Expand Down Expand Up @@ -321,38 +321,90 @@ Provides a list of commands executed, from the most recent to the earliest.
Format: `history`

* History displays only commands executed during the current session.
* History displays all commands that was entered, regardless if it was successful or not.

Examples:
* If you accidentally add a tutor as a tutee using the `addTutee` command instead of `addTutor`, `history` lets you easily select and copy the previous command, saving you from retyping it.
* If you were in the middle of updating records and was distracted, `history` will allow you to find out where you left off last.

### Viewing chart of tutors’ volunteer hours : `vtc`

Generates a chart displaying the total volunteering hours of all volunteer tutors.

Format: `vtc`

Examples:
* To see an overview of volunteer contributions, `vtc` will display a chart with each tutor's name and total hours logged.

<box type="info" seamless>
vtc will cause all persons to be listed
</box>


### Clearing all entries : `clear`

Clears all entries from the address book.

Format: `clear`


### Importing people from CSV files : `import`

Allows users to import data from a CSV file and add multiple persons at once to the address book.
If any rows fail the validation check or contain duplicates, they are skipped, and detailed feedback is provided to the user.

Format: `import \f FILEPATH`

<box type="tip" seamless>

**Tips**
* Use this to import your current users from your Excel spreadsheets to VolunTier.

* The .csv file to be imported must have these headings in this order: “name”, “phone”, “email”, “address”, “hours”, “role” and “subjects”.

* There should be no empty rows in your CSV file.

* For optional fields like hours and subject, leave a blank.<br>
For example, the following row leaves hours and subject blank: John, 91234567, [email protected], “1 Jurong, 123456”, , Tutor,

* For any field that requires a comma, surround it in quotes like this: "1 Jurong, 123456".

* For more than one subject, separate it with a semicolon like this: English; Science.
</box>

Example:
* `import \f ~/data/new_persons.csv` imports a list of people in new_persons.csv located in ~/data/ into VolunTier.
* Output: `5 persons added. Rows with duplicates: [2, 4]. The following rows had data which failed some constraints: Row 3: Invalid email format. Row 5: Missing phone number.`

<box type="info" seamless>

Import only works for a list of persons. It does not support the lessons feature.
</box>


### Exiting the program : `exit`

Exits the program.

Format: `exit`

--------------------------------------------------------------------------------------------------------------------

### Saving the data

AddressBook data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually.
VolunTier data is saved in the hard disk automatically after any command that changes the data. There is no need to save manually.

### Editing the data file

AddressBook data are saved automatically as a JSON file `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file.
VolunTier data are saved automatically as a JSON file `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file.

<box type="warning" seamless>

**Caution:**
If your changes to the data file makes its format invalid, AddressBook will discard all data and start with an empty data file at the next run. Hence, it is recommended to take a backup of the file before editing it.<br>
Furthermore, certain edits can cause the AddressBook to behave in unexpected ways (e.g., if a value entered is outside the acceptable range). Therefore, edit the data file only if you are confident that you can update it correctly.
If your changes to the data file makes its format invalid, VolunTier will discard all data and start with an empty data file at the next run. Hence, it is recommended to take a backup of the file before editing it.<br>
Furthermore, certain edits can cause the VolunTier to behave in unexpected ways (e.g., if a value entered is outside the acceptable range). Therefore, edit the data file only if you are confident that you can update it correctly.
</box>

### Archiving data files `[coming in v2.0]`

_Details coming soon ..._

--------------------------------------------------------------------------------------------------------------------

## FAQ
Expand All @@ -373,10 +425,21 @@ _Details coming soon ..._

Action | Format, Examples
-----------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------
**Add** | `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​` <br> e.g., `add n/James Ho p/22224444 e/[email protected] a/123, Clementi Rd, 1234665 t/friend t/colleague`
**Add Lesson** | `addLesson TUTOR_INDEX TUTEE_INDEX \s SUBJECT` <br> e.g., `addLesson 1 2 \s science`
**Add Tutee** | `addTutee \n NAME \p PHONE_NUMBER \e EMAIL \a ADDRESS [\h HOURS] [\s SUBJECT​]…​` <br> e.g., `addTutee \n Evan Lee \p 88889999 \e [email protected] \a 345, Clementi Rd, 1234665 \h 2 \s english`
**Add Tutor** | `addTutor \n NAME \p PHONE_NUMBER \e EMAIL \a ADDRESS [\h HOURS] [\s SUBJECT]…​` <br> e.g., `addTutor \n James Ho \p 92224444 \e [email protected] \a 123, Clementi Rd, 1234665 \h 7 \s math`
**Clear** | `clear`
**Delete** | `delete INDEX`<br> e.g., `delete 3`
**Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`<br> e.g.,`edit 2 n/James Lee e/[email protected]`
**DeleteLesson**| `deleteLesson TUTOR_INDEX TUTEE_INDEX \s SUBJECT `<br> e.g., `deleteLesson 1 2 \s science`
**Edit** | `edit INDEX [\n NAME] [\p PHONE_NUMBER] [\e EMAIL] [\a ADDRESS] [\h HOURS] [\s SUBJECT]…​`<br> e.g.,`edit 2 \n James Lee \e [email protected]`
**Find** | `find KEYWORD [MORE_KEYWORDS]`<br> e.g., `find James Jake`
**FindSubject** | `findSubject SUBJECT [MORE_SUBJECTS]` <br> e.g., `findSubject math science`
**History** | `history`
**Import** | `import \f FILEPATH`
**List** | `list`
**Undo** | `undo`
**Redo** | `redo`
**View** | `view`
**View Tutor Hours** | `vtc`
**Exit** | `exit`
**Help** | `help`
41 changes: 31 additions & 10 deletions src/main/java/seedu/address/storage/CsvImport.java
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ public class CsvImport {
private final String importFilePath;
private final ArrayList<Integer> duplicates;
private final Map<Integer, String> failedRows;
private final ArrayList<Integer> emptyRows;

/**
* Constructs a CsvImport instance with the specified file path.
Expand All @@ -47,6 +48,7 @@ public CsvImport(String importFilePath) {
this.importFilePath = importFilePath;
this.duplicates = new ArrayList<>();
this.failedRows = new HashMap<>();
this.emptyRows = new ArrayList<>();
}

/**
Expand All @@ -71,7 +73,11 @@ public int readCsv(Model model) throws ImproperFormatException, FileNotFoundExce
if (!validateHeaders(headerReader)) {
throw new ImproperFormatException(INCORRECT_HEADERS);
} else if (!validateCsv(rowReader)) {
throw new ImproperFormatException(String.format(INCORRECT_ROWS, HEADER_COUNT, duplicates));
if (!emptyRows.isEmpty()) {
throw new ImproperFormatException("Some rows are empty. The rows that failed are: " + emptyRows);
} else {
throw new ImproperFormatException(String.format(INCORRECT_ROWS, HEADER_COUNT, duplicates));
}
}

MappingStrategy<JsonAdaptedPerson> map = createMappingStrategy();
Expand All @@ -84,13 +90,7 @@ public int readCsv(Model model) throws ImproperFormatException, FileNotFoundExce
int success = 0;
for (JsonAdaptedPerson p : personList) {
try {
if (model.hasPerson(p.toModelType())) {
duplicates.add(personList.indexOf(p) + 1);
} else {
p.setId(Person.getNextIndex());
model.addPerson(p.toModelType());
success++;
}
success += addPerson(p, personList.indexOf(p), model);
} catch (IllegalValueException e) {
failedRows.put(personList.indexOf(p) + 1, e.getMessage());
}
Expand All @@ -114,6 +114,25 @@ public boolean hasFailed() {
return !failedRows.isEmpty();
}

/**
* Adds a person to the model if it is not a duplicate.
*
* @param person The person to be added.
* @param index The index of the person in the CSV file.
* @param model The model to which the person will be added.
* @return 1 if the person was successfully added, 0 if the person is a duplicate.
*/
public int addPerson(JsonAdaptedPerson person, int index, Model model) throws IllegalValueException {
if (model.hasPerson(person.toModelType())) {
duplicates.add(index + 1);
return 0;
} else {
person.setId(Person.getNextIndex());
model.addPerson(person.toModelType());
return 1;
}
}

private boolean validateHeaders(FileReader reader) {
CSVReader csvReader = new CSVReader(reader);

Expand Down Expand Up @@ -160,7 +179,9 @@ private boolean validateCsv(FileReader reader) {
int lineCount = 1;
String[] row = csvReader.readNext();
while (row != null) {
if (row.length != HEADER_COUNT) {
if (Arrays.stream(row).allMatch(String::isBlank)) {
emptyRows.add(lineCount);
} else if (row.length != HEADER_COUNT) {
duplicates.add(lineCount);
}
lineCount++;
Expand All @@ -169,7 +190,7 @@ private boolean validateCsv(FileReader reader) {
} catch (IOException | CsvValidationException e) {
e.printStackTrace();
}
return duplicates.isEmpty();
return duplicates.isEmpty() && emptyRows.isEmpty();
}

private MappingStrategy<JsonAdaptedPerson> createMappingStrategy() {
Expand Down

0 comments on commit e9681cf

Please sign in to comment.