Skip to content

Commit

Permalink
Merge pull request #121 from souless94/ttv1.3
Browse files Browse the repository at this point in the history
Ttv1.3 resolves issues #100 -3,4,5
  • Loading branch information
Happytreat committed Oct 26, 2018
2 parents b418547 + 739727b commit ea35c50
Show file tree
Hide file tree
Showing 26 changed files with 590 additions and 248 deletions.
1 change: 1 addition & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ dependencies {
implementation group: 'com.sun.xml.bind', name: 'jaxb-impl', version: '2.3.0'
implementation group: 'com.sun.xml.bind', name: 'jaxb-core', version: '2.3.0'
implementation group: 'javax.activation', name: 'activation', version: '1.1.1'
implementation group: 'com.opencsv', name: 'opencsv' ,version: '4.3.2'

testImplementation group: 'junit', name: 'junit', version: '4.12'
testImplementation group: 'org.testfx', name: 'testfx-core', version: testFxVersion, {
Expand Down
84 changes: 71 additions & 13 deletions docs/DeveloperGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -263,39 +263,50 @@ Certain properties of the application can be controlled (e.g App name, logging l
This section describes some noteworthy details on how certain features are implemented.

=== Timetable Feature

==== Reason for implementation
The objective of the `add_timetable` feature is to to add data entries of a timetable into NUS Hangs. But it is hard to visualise the adding of the entries so we allowed user to add directly all the entries from a csv file. For `edit_timetable` , it is for User who just want to edit entries without going to find the timetable. For `download_timetable`, it is to allow the user to share their timetable to their friends.

==== How to implement
For `add_timetable` , we create a `timetable` class in `person` first,we store the `format` of the timetable , then we create a `timetableData` class with method to create a String [][] Matrix from the data from the csv file. Then we create a timetableString to which contains information on the entries about the `timetable` and store it in the xml file of the person in the addressbook.

==== Current Implementation

The `timetable` is contained in `person` which is in `model`.
The current `timetable` commands are:

* `add_timetable` -- adds a timetable from the csv file to the person.
* `delete_timetable` -- delete a timetable from the person and creates a default timetable in person. It will also find the timetable csv file of the person and deletes it.
* `edit_timetable` -- edit a timetable timeslot in the person
* `download_timetable` -- downloads a timetable into a csv file into a stored folder location from the person.

These operations are handled by the `logic` component and uses the `person` in `model` to do the execution.

Given below is an activity diagram.

image::timetableworkflow.png[width="500"]

Given below is an example usage scenario and how the `add_timetable` behaves at each step.

Step 1: The user launches the application for the first time. The NUS Hangs will initialise the person with the timetable with the details which was stored using Storage.

image::addTimetable-step-1.png[width="300"]
Step 2: user finds a timetable of first `person` in the stored location which is called 495011161 timetable.csv. Using this command, User does not need to find the timetable. As shown in the diagram below its easy to see what event the person has.

Step 2: user opens a timetable of first `person` in the stored location and edits it via microsoft excel or with his preferred software.
image::addTimetable-step-2.png[width="500"]

image::addTimetable-step-2.png[width="300"]
Step 3: The user executes `add_timetable 1` to add the timetable of first `person` in stored folder to NUS hangs. A new `timetable` will be created containing the data of the `timetable` of first `person` in stored folder. The `timetable` of first `person` will be replaced by this new `timetable`.

Step 3: The user executes `add_timetable 1` to add the timetable of first `person` in stored folder to NUS hangs. A new `timetable` will be created containing the data of the `timetable` of first `person` in stored folder. The `timetable` of first `person` will be replaced by this new `timetable`. The `timetable` is then added to storage as a String.
The `timetable` is then added to storage as a String which contains all of the data. This is to allow the app to save time in storage.

image::addTimetable-step-3.png[width="300"]

The following sequence diagram shows how `add_timetable` works.

image::addtimetablediagram.png[width="500"]

==== Design Considerations
* **Alternative 1 (current choice for v1.2):** adds the timetable via a csv file.
* **Alternative 1 :** adds the timetable via a csv file.
** Pros: Easier for user to visualise and edit his timetable
** Cons: Hard to implement. No choice other than to edit his timetable from the stored folder defined.
* **Alternative 2 :** adds the timetable via a csv file from other locations.
* **Alternative 2 (current choice) :** adds the timetable via a csv file from other locations.
** Pros: Easier for user to visualise and edit his timetable and allows user a choice on where to edit his timetable.
** Cons: Hard to implement, and user has to know how to get file location of a file.
* **Alternative 3:** User knows how to edit via the xml file of the person.
Expand All @@ -305,11 +316,11 @@ image::addtimetablediagram.png[width="500"]
===== Aspect: Data structure to support the add_timetable commands

* **Alternative 1 (current choice):** Use a String [][] Matrix to store entries of the timetable.
** Pros: Easy for new Computer Science student undergraduates to understand, who are likely to be the new incoming developers of our project.
** Cons: Slower Time efficiency because using 2 for loops to fill the Matrix with the data.
** Pros: Easy for new Computer Science student undergraduates to understand, who are likely to be the new incoming developers of our project. Better intuition to access entries of the matrix (matrix[i][j]) Which makes `edit_timetable` easier to implement.
** Cons: Slower Time efficiency because using 2 for loops to fill the Matrix with the data. Unable to use functions in ArrayList.
* **Alternative 2:** Use ArrayList<ArrayList<String>>
** Pros: Faster Time efficiency because using 1 for loops to fill the Matrix with the data.
** Cons: Harder for new Computer Science student undergraduates to understand, who are likely to be the new incoming developers of our project.
** Pros: Faster Time efficiency because using 1 for loops to fill the Matrix with the data. Able to use functions in ArrayList
** Cons: Harder for new Computer Science student undergraduates to understand, who are likely to be the new incoming developers of our project. Less intuition to access entries of the matrix (matrix.get(i).get(j)).

=== Security Mechanism

Expand Down Expand Up @@ -992,7 +1003,7 @@ Use case ends.

1. User logins to System and requests help to add a timetable
2. System shows how to add a timetable
3. User adds inputs accordingly
3. User enters inputs accordingly
4. System shows his timetable and ask user for confirmation.
5. User confirms the addition of his timetable into the System.
6. System shows his timetable is added successfully.
Expand All @@ -1016,6 +1027,53 @@ Use case resumes at step 2.
+
Use case ends

[discrete]
=== Use case: edit a timetable
*MSS*

1. User logins to System and requests help to edit a timetable
2. System shows how to edit a timetable
3. User enters inputs accordingly
4. System shows his timetable and ask user for confirmation.
5. User confirms the edit of his timetable into the System.
6. System shows his timetable is edit successfully.


*Extensions*

* 3a. User enters invalid input.
+
[none]
** 3a1.System shows an error message.
+
Use case resumes at step 2.
* 4a.User does not confirm the addition of the timetable into the System.
+
Use case ends

[discrete]
=== Use case: download a timetable
*MSS*

1. User logins to System and requests help to download a timetable
2. System shows how to download a timetable
3. User enters inputs accordingly
4. System shows his timetable and ask user for confirmation.
5. User confirms the edit of his timetable into the System.
6. System shows his timetable is edit successfully.


*Extensions*

* 3a. User enters invalid input.
+
[none]
** 3a1.System shows an error message.
+
Use case resumes at step 2.
* 4a.User does not confirm the download of the timetable
+
Use case ends

[discrete]
=== Use case: Delete a timetable
Expand Down
35 changes: 28 additions & 7 deletions docs/UserGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ e.g. typing *`help`* and pressing kbd:[Enter] will open the help window.
* Words in `UPPER_CASE` are the parameters to be supplied by the user e.g. in `n/NAME_OF_FRIEND`, `NAME_OF_FRIEND` is a parameter which can be used as `add n/John Doe`.
* Items in square brackets are optional e.g `n/NAME [i/INDEX_OF_TIMETABLE]` can be used as `n/John Doe i/1` or as `n/John Doe`.
* Items in square brackets /\ square brackets means have to choose either left choice or right choice e.g `add_timetable [f/FILENAME l/FILE_LOCATION ] /\ [o/LINK]` can be used as `add_timetable f/mytimetable.png l/C://Users/abc/mysecretstash` or `add_timetable o/http://modsn.us/wJsFc` but not `add_timetable f/mytimetable.png l/C://Users/abc/mysecretstash o/http://modsn.us/wJsFc`
* Parameters can be in any order e.g. if the command specifies `n/NAME_OF_FRIEND i/INDEX_OF_TIMETABLE`, `i/INDEX_OF_TIMETABLE n/NAME_OF_FRIEND` is also acceptable.
====

Expand Down Expand Up @@ -342,8 +341,8 @@ Format: `grouplist`

== Timetable(Wen Kai)
=== Adding a timetable: `add_timetable`
add a timetable from the stored folder in NUS Hangs +
Format: `add_timetable INDEX `
add a timetable from the stored folder in NUS Hangs or a file location +
Format: `add_timetable INDEX [fl/FILE_LOCATION] `

****
* Add the timetable at the specified `INDEX`.
Expand All @@ -355,10 +354,30 @@ Examples:

* `add_timetable 1`

* `add_timetable 1 fl/C:\Users\timetable\timetable.csv `

=== editing a timetable: `edit_timetable`
edit a timetable timeslot from the person from index specified +
Format: `add_timetable INDEX day/DAY timing/TIMING [m/DETAILS] `

****
* Add the timetable at the specified `INDEX`.
* The index refers to the index number shown in the displayed person list.
* The index *must be a positive integer* 1, 2, 3, ...
day refers to days of a week and day is in *full name(case insensitive)* monday,tuesday,TUesday ...
timing is in 24h format and is from 0800 to 2300
****

Examples:

* `edit_timetable 1 day/wednesday timing/0900 m/do cs2103`



=== Download timetable : `download_timetable`

Download a timetable in the System as a png file or csv file in the format of the person.+
Format: `download_timetable INDEX p/PASSWORD `
Download a timetable in the System as a csv file in the format of the person.+
Format: `download_timetable INDEX `

****
* Download the timetable at the specified `INDEX`.
Expand All @@ -368,7 +387,7 @@ Format: `download_timetable INDEX p/PASSWORD `

Examples:

* `download_timetable 1 p/password` +
* `download_timetable 1 ` +

=== Deleting a timetable : `delete_timetable`

Expand Down Expand Up @@ -593,8 +612,10 @@ e.g. `find_friend James Jake`
e.g. `delete_friend 3`
* *clear_friend* : `clear_friend`
* *grouplist* : `listgroup`
* *add_timetable* `add_timetable INDEX ` +
* *add_timetable* `add_timetable INDEX [fl/FILE_LOCATION]` +
e.g. `add_timetable 1`
* *edit_timetable* `edit_timetable INDEX day/DAY timing/TIMING [m/DETAILS]` +
e.g. `edit_timetable 1 day/wednesday timing/1800 m/do cs2103`
* *download_timetable* : `download_timetable INDEX` +
e.g. `download_timetable 1 l/C://Users/abc/mysecretstash`
* *delete_timetable* : `delete INDEX p/password` +
Expand Down
Binary file removed docs/images/addTimetable-step-1.png
Binary file not shown.
Binary file removed docs/images/addTimetable-step-3.png
Binary file not shown.
Binary file modified docs/images/addtimetablediagram.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/images/timetableworkflow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/main/java/seedu/address/commons/core/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,9 @@ public class Messages {
public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
public static final String MESSAGE_GROUPS_LISTED_OVERVIEW = "%1$d groups listed!";
public static final String MESSAGE_TIMETABLE_NOT_FOUND = "timetable to be added is not found";
public static final String MESSAGE_NOT_UNIQUE_PREFIX_INPUT = "can only enter 1 input per prefix";

public static final String INVALID_TIMETABLE_FORMAT = "format can only be horizontal or vertical";
public static final String INVALID_DAY = "Days are in full name, there is no such day in a week";
public static final String INVALID_TIMING = "timings are in 24h format and is from 0800 to 2300";
}
59 changes: 20 additions & 39 deletions src/main/java/seedu/address/logic/commands/AddTimetableCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,17 @@

import static java.util.Objects.requireNonNull;
import static seedu.address.commons.core.Messages.MESSAGE_TIMETABLE_NOT_FOUND;
import static seedu.address.logic.commands.EditTimetableCommand.createUpdatedPerson;
import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS;

import java.io.File;
import java.util.Set;

import seedu.address.commons.core.index.Index;
import seedu.address.logic.CommandHistory;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
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.timetable.Timetable;
import seedu.address.model.tag.Tag;

/**
* adds timetable to person
Expand All @@ -26,23 +21,26 @@ public class AddTimetableCommand extends Command {

public static final String COMMAND_WORD = "add_timetable";
public static final String MESSAGE_USAGE =
COMMAND_WORD + ": adds timetable to the person identified "
+ "by the index number used in the displayed person list."
+ " \n"
+ "Parameters : INDEX (must be a positive integer) "
+ "Example: " + COMMAND_WORD + " 1 ";
COMMAND_WORD + ": adds timetable to the person identified "
+ "by the index number used in the displayed person list."
+ " \n"
+ "Parameters : INDEX (must be a positive integer) "
+ "Example: " + COMMAND_WORD + " 1 ";

public static final String MESSAGE_ADD_TIMETABLE_SUCCESS = "timetable added successfully";


private final Index index;
private final String newFilePath;

/**
* @param index of the person in the filtered person list to edit
*/
public AddTimetableCommand(Index index) {
public AddTimetableCommand(Index index, String newFilePath) {
requireNonNull(index);
this.index = index;
this.newFilePath = newFilePath;

}


Expand All @@ -51,14 +49,17 @@ public CommandResult execute(Model model, CommandHistory history) throws Command
requireNonNull(model);

Person personToEdit = CommandUtil.retrievePersonFromIndex(model, index);

String filePath = personToEdit.getStoredLocation()
+ "/" + String.valueOf(personToEdit.hashCode())
+ " timetable";
File toRead = new File(filePath + ".csv");
String filePath;
if (newFilePath == null) {
filePath = personToEdit.getStoredLocation();
} else {
filePath = newFilePath.replace("\\", "/");
}
File toRead = new File(filePath);
if (toRead.exists()) {
Timetable timetable = new Timetable(filePath, personToEdit.getFormat(), index.getZeroBased());
Person updatedPerson = createUpdatedPerson(personToEdit, timetable);
Timetable timetable = new Timetable(filePath, personToEdit.getFormat(),
personToEdit.getTimetable().getTimetableDataString(), 2, null, null, null);
Person updatedPerson = createUpdatedPerson(personToEdit, timetable, filePath);
model.update(personToEdit, updatedPerson);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
model.commitAddressBook();
Expand All @@ -67,25 +68,5 @@ public CommandResult execute(Model model, CommandHistory history) throws Command
throw new CommandException(MESSAGE_TIMETABLE_NOT_FOUND);
}
}

/**
* it updates the timetableData of the person. Creates and returns a {@code Person} with the
* details of {@code personToEdit}
*/
private static Person createUpdatedPerson(Person personToEdit, Timetable timetable) {
assert personToEdit != null;

Name updatedName = personToEdit.getName();
Phone updatedPhone = personToEdit.getPhone();
Email updatedEmail = personToEdit.getEmail();
Address updatedAddress = personToEdit.getAddress();
Set<Tag> updatedTags = personToEdit.getTags();
String format = personToEdit.getFormat();
String storedLocation = personToEdit.getStoredLocation();
String timetableString = timetable.getTimetableDataString();

return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags,
format, storedLocation, timetableString);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,9 @@ public class DeleteTimetableCommand extends Command {
+ "Parameters : INDEX (must be a positive integer) "
+ "Example: " + COMMAND_WORD + " 1 ";

public static final String MESSAGE_DELETE_TIMETABLE_SUCCESS = "timetable deleted successfully";
public static final String MESSAGE_DELETE_TIMETABLE_SUCCESS = "delete and reset timetable successfully";

public static final String MESSAGE_RESET_TIMETABLE_SUCCESS = "reset timetable successfully";

private final Index index;

Expand All @@ -45,19 +46,20 @@ public DeleteTimetableCommand(Index index) {
public CommandResult execute(Model model, CommandHistory history) throws CommandException {
requireNonNull(model);
Person personToDeleteTimetable = CommandUtil.retrievePersonFromIndex(model, index);
File toBeDeleted = new File(personToDeleteTimetable.getStoredLocation());

File toBeDeleted = new File(
personToDeleteTimetable.getStoredLocation()
+ "/"
+ personToDeleteTimetable.hashCode() + " timetable.csv");
if (toBeDeleted.exists()) {
toBeDeleted.delete();
}
Person updatedPerson = createPersonWithNewTimetable(personToDeleteTimetable);
model.update(personToDeleteTimetable, updatedPerson);
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
model.commitAddressBook();
return new CommandResult(String.format(MESSAGE_DELETE_TIMETABLE_SUCCESS, updatedPerson));
if (toBeDeleted.exists()) {
toBeDeleted.delete();
return new CommandResult(
String.format(MESSAGE_DELETE_TIMETABLE_SUCCESS, updatedPerson));
} else {
return new CommandResult(
String.format(MESSAGE_RESET_TIMETABLE_SUCCESS, updatedPerson));
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class DownloadTimetableCommand extends Command {
/**
* location of the download is gotten from the person
*
* @param index of the person in the filtered person list to edit
* @param index of the person to download timetable from
*/
public DownloadTimetableCommand(Index index) {
this.index = index;
Expand All @@ -49,7 +49,7 @@ public CommandResult execute(Model model, CommandHistory history) throws Command

Person personToDownloadTimetable = lastShownList.get(index.getZeroBased());
Timetable timetable = personToDownloadTimetable.getTimetable();
timetable.downloadTimetable();
timetable.downloadTimetableAsCsv();
model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS);
model.commitAddressBook();
return new CommandResult(String.format(MESSAGE_DOWNLOAD_TIMETABLE_SUCCESS));
Expand Down
Loading

0 comments on commit ea35c50

Please sign in to comment.