Skip to content

Commit

Permalink
Separate column titles from Schedule's observable list (AY1920S1-CS21…
Browse files Browse the repository at this point in the history
…03-F09-1#73) (#13)

* Separate column titles from Schedule's observable list

* Separate column titles from Schedule's observable list

* Fix failing tests

* Fix travis issue
  • Loading branch information
mrchensheng21 committed Oct 21, 2019
1 parent af0685a commit 5f50478
Show file tree
Hide file tree
Showing 9 changed files with 158 additions and 61 deletions.
29 changes: 29 additions & 0 deletions src/main/java/seedu/address/commons/util/Pair.java
@@ -0,0 +1,29 @@
package seedu.address.commons.util;

/**
* Encapsulates a pair, with a head and a tail.
* @param <H> head of the pair.
* @param <T> tail of the pair.
*/
public class Pair<H, T> {
private H head;
private T tail;

public Pair(H head, T tail) {
this.head = head;
this.tail = tail;
}

public H getHead() {
return head;
}

public T getTail() {
return tail;
}

@Override
public String toString() {
return String.format("(%s, %s)", head, tail);
}
}
3 changes: 3 additions & 0 deletions src/main/java/seedu/address/logic/Logic.java
Expand Up @@ -50,6 +50,9 @@ public interface Logic {
/** Returns a list of @code{ObservableList} objects, each representing a Schedule table*/
List<ObservableList<ObservableList<String>>> getObservableLists();

/** Returns a list of lists of column titles, each list of column titles belong to a Schedule table*/
List<List<String>> getTitlesLists();

/**
* Returns the user prefs' GUI settings.
*/
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/seedu/address/logic/LogicManager.java
Expand Up @@ -78,6 +78,11 @@ public List<ObservableList<ObservableList<String>>> getObservableLists() {
return model.getObservableLists();
}

@Override
public List<List<String>> getTitlesLists() {
return model.getTitlesLists();
}

@Override
public GuiSettings getGuiSettings() {
return model.getGuiSettings();
Expand Down
3 changes: 3 additions & 0 deletions src/main/java/seedu/address/model/Model.java
Expand Up @@ -53,6 +53,9 @@ public interface Model {
*/
List<ObservableList<ObservableList<String>>> getObservableLists();

/** Returns a list of lists of column titles, each list of column titles belong to a Schedule table*/
List<List<String>> getTitlesLists();

/**
* Returns an Interviewee given the intervieweeName.
* The Interviewee must exist in the database.
Expand Down
10 changes: 10 additions & 0 deletions src/main/java/seedu/address/model/ModelManager.java
Expand Up @@ -123,6 +123,16 @@ public List<ObservableList<ObservableList<String>>> getObservableLists() {
return observableLists;
}

/** Returns a list of lists of column titles, each list of column titles belong to a Schedule table*/
@Override
public List<List<String>> getTitlesLists() {
List<List<String>> titlesLists = new LinkedList<>();
for (Schedule schedule : schedulesList) {
titlesLists.add(schedule.getTitles());
}
return titlesLists;
}

@Override
public Interviewee getInterviewee(String intervieweeName) throws NoSuchElementException {
Person person = getPerson(intervieweeName);
Expand Down
118 changes: 76 additions & 42 deletions src/main/java/seedu/address/model/Schedule.java
Expand Up @@ -17,11 +17,20 @@
*/
public class Schedule {
private String date;
private ObservableList<ObservableList<String>> table; // Include the first row which is the column titles
private ObservableList<String> titles;
private ObservableList<ObservableList<String>> data; // EXCLUDE the first row which is the column titles

public Schedule(String date, LinkedList<LinkedList<String>> list) {
this.date = date;
this.table = toTwoDimensionalObservableList(list);

ObservableList<ObservableList<String>> table = toTwoDimensionalObservableList(list);
if (table.isEmpty()) {
this.titles = FXCollections.observableList(new LinkedList<>());
} else {
this.titles = table.remove(0);
}

this.data = table;
}

private Schedule() {
Expand All @@ -31,17 +40,22 @@ public String getDate() {
return date;
}

public ObservableList<String> getTitles() {
return titles;
}

public ObservableList<ObservableList<String>> getObservableList() {
return table;
return data;
}

public List<Slot> getInterviewSlots(String intervieweeName) {
List<Slot> slots = new LinkedList<>();
int tableSize = table.size();
int tableSize = data.size();

// Exclude search in the first row as the first row is column titles
for (int i = 1; i < tableSize; i++) {
ObservableList<String> row = table.get(i);
// Need to search the first row as well because now the first row of data(table) is not the titles,
// it is data.
for (int i = 0; i < tableSize; i++) {
ObservableList<String> row = data.get(i);
int rowSize = row.size();

// Exclude search in the first cell as the first cell is the time slot
Expand All @@ -67,10 +81,9 @@ public List<Slot> getInterviewSlots(String intervieweeName) {
*/
public boolean hasInterviewer(Interviewer interviewer) {
String columnTitle = generateColumnTitle(interviewer);
ObservableList<String> firstRow = table.get(0);

boolean found = false;
for (String title : firstRow) {
for (String title : titles) {
if (title.equals(columnTitle)) {
found = true;
break;
Expand Down Expand Up @@ -100,9 +113,9 @@ public boolean addInterviewer(Interviewer interviewer) {
.collect(Collectors.toList());

boolean added = false;
int currRowIndex = 1;
int currRowIndex = 0;
for (String availability : availabilities) {
if (currRowIndex > table.size()) {
if (currRowIndex > data.size()) {
break;
}

Expand All @@ -115,10 +128,10 @@ public boolean addInterviewer(Interviewer interviewer) {
}

// Iterate through the table rows
int tableSize = table.size();
int i;
int tableSize = data.size();
for (i = currRowIndex; i < tableSize; i++) {
ObservableList<String> currRow = table.get(i);
ObservableList<String> currRow = data.get(i);
String currRowTime = currRow.get(0);

if (!currRowTime.equals(time)) {
Expand All @@ -132,12 +145,13 @@ public boolean addInterviewer(Interviewer interviewer) {
currRowIndex = i;
}

// Add 0 to other rows to ensure that the table rows size are correct
if (added) {
int initialRowSize = table.get(0).size();
table.get(0).add(columnTitle);
for (int i = 1; i < table.size(); i++) {
ObservableList<String> currRow = table.get(i);
int initialRowSize = titles.size();
titles.add(columnTitle);

// Add 0 to other rows to ensure that the table rows size are correct
for (int i = 0; i < data.size(); i++) {
ObservableList<String> currRow = data.get(i);
if (currRow.size() == initialRowSize) {
currRow.add("0");
}
Expand Down Expand Up @@ -169,47 +183,48 @@ public boolean equals(Object s) {
}
Schedule sCasted = (Schedule) s;
return date.equals(sCasted.date)
&& table.equals(sCasted.table);
&& titles.equals(sCasted.titles)
&& data.equals(sCasted.data);
}

/**
* Returns a copy of the @code{Schedule} object given.
*
* @param schedule the @code{Schedule} object to be copied.
* @return the copy of the @code{Schedule} object.
*/
public static Schedule cloneSchedule(Schedule schedule) {
Schedule clone = new Schedule();
clone.date = String.valueOf(schedule.date);
clone.table = cloneTable(schedule.table);
clone.titles = cloneRow(schedule.titles);
clone.data = cloneTable(schedule.data);
return clone;
}

/**
* Returns an independent copy of the table given in observable list form.
*
* @param table the table to copy.
* @return the copy of the table.
* Returns an independent deep copy of the table given in observable list form.
*/
private static ObservableList<ObservableList<String>> cloneTable(ObservableList<ObservableList<String>> table) {
ObservableList<ObservableList<String>> tableClone = FXCollections.observableList(new LinkedList<>());

for (ObservableList<String> row : table) {
ObservableList<String> rowClone = FXCollections.observableList(new LinkedList<>());
for (String string : row) {
rowClone.add(String.valueOf(string));
}
ObservableList<String> rowClone = cloneRow(row);
tableClone.add(rowClone);
}

return tableClone;
}

/**
* Returns an independent deep copy of the row given in observable list form.
*/
private static ObservableList<String> cloneRow(ObservableList<String> row) {
ObservableList<String> rowClone = FXCollections.observableList(new LinkedList<>());
for (String string : row) {
rowClone.add(String.valueOf(string));
}
return rowClone;
}

/**
* Convert a two-dimensional LinkedList into a two-dimensional Observable list.
*
* @param list a two-dimensional LinkedList
* @return the corresponding two-dimensional Observable list
*/
public static ObservableList<ObservableList<String>> toTwoDimensionalObservableList(
LinkedList<LinkedList<String>> list) {
Expand All @@ -226,15 +241,34 @@ public static ObservableList<ObservableList<String>> toTwoDimensionalObservableL

@Override
public String toString() {
StringBuffer buffer = new StringBuffer(450);
for (ObservableList<String> row : table) {
for (String value : row) {
buffer.append(value);
buffer.append(",");
}
buffer.append("\n");
StringBuilder builder = new StringBuilder(450);

// Append the title rows
String titleRep = rowToString(titles);
builder.append(titleRep);

// Append the other rows
for (ObservableList<String> row : data) {
String rowRep = rowToString(row);
builder.append(rowRep);
}

return builder.toString();
}

/**
* Convert a row to its string representation (each value separated by a comma, then the row ends with
* a newline character.
*/
private String rowToString(List<String> row) {
StringBuilder builder = new StringBuilder(110);

for (String value : row) {
builder.append(value);
builder.append(",");
}

return buffer.toString();
builder.append("\n");
return builder.toString();
}
}
12 changes: 6 additions & 6 deletions src/main/java/seedu/address/model/util/SampleDataUtil.java
Expand Up @@ -24,12 +24,12 @@ public class SampleDataUtil {
private static String[][] sampleFilledTable =
new String[][]{
{"10/9/2019", "Welfare - Hazel", "Technical - Johnathan", "Publicity - Lucia"},
{"18:00 - 18:30", "John", "Steven", "0"},
{"18:30 - 19:00", "Alex", "Clark", "John"},
{"19:00 - 19:30", "Alicia", "0", "charlie"},
{"19:30 - 20:00", "Charlie", "0", "Selina"},
{"20:00 - 20:30", "Selina", "0", "0"},
{"20:30 - 21:00", "Natal", "0", "0"}};
{"18:00-18:30", "John", "Steven", "0"},
{"18:30-19:00", "Alex", "Clark", "John"},
{"19:00-19:30", "Alicia", "0", "charlie"},
{"19:30-20:00", "Charlie", "0", "Selina"},
{"20:00-20:30", "Selina", "0", "0"},
{"20:30-21:00", "Natal", "0", "0"}};

public static Person[] getSamplePersons() {
return new Person[] {
Expand Down
Expand Up @@ -120,6 +120,12 @@ public List<ObservableList<ObservableList<String>>> getObservableLists() {
throw new AssertionError("This method should not be called.");
}

@Override
public List<List<String>> getTitlesLists() {
// TODO: Implementation
return null;
}

@Override
public void emailInterviewee(Interviewee interviewee) {
throw new AssertionError("This method should not be called.");
Expand Down
33 changes: 20 additions & 13 deletions src/test/java/seedu/address/model/ScheduleTest.java
Expand Up @@ -72,8 +72,9 @@ public void addInterviewer_oneValidAvailability_true() {

// Generate the expected Schedule
Schedule expectedSchedule = SampleSchedules.getSampleAvailabilityTable();
String[] newColumn = new String[]{"Technical - Alice Pauline", "1", "0", "0", "0", "0", "0"};
addColumn(expectedSchedule, newColumn);
String newTitle = "Technical - Alice Pauline";
String[] newColumn = new String[]{"1", "0", "0", "0", "0", "0"};
addColumn(expectedSchedule, newTitle, newColumn);

assertTrue(scheduleTest.addInterviewer(interviewer));
assertEquals(expectedSchedule, scheduleTest);
Expand All @@ -86,8 +87,9 @@ public void addInterviewer_multipleValidAvailabilities_true() {

// Generate the expected Schedule
Schedule expectedSchedule = SampleSchedules.getSampleAvailabilityTable();
String[] newColumn = new String[]{"Technical - Alice Pauline", "0", "1", "1", "0", "1", "0"};
addColumn(expectedSchedule, newColumn);
String newTitle = "Technical - Alice Pauline";
String[] newColumn = new String[]{"0", "1", "1", "0", "1", "0"};
addColumn(expectedSchedule, newTitle, newColumn);

assertTrue(scheduleTest.addInterviewer(interviewer));
assertEquals(expectedSchedule, scheduleTest);
Expand All @@ -110,8 +112,9 @@ public void addInterviewer_multipleAvailabilitiesSomeInvalid_true() {

// Generate the expected Schedule
Schedule expectedSchedule = SampleSchedules.getSampleAvailabilityTable();
String[] newColumn = new String[]{"Technical - Alice Pauline", "0", "0", "1", "0", "1", "0"};
addColumn(expectedSchedule, newColumn);
String newTitle = "Technical - Alice Pauline";
String[] newColumn = new String[]{ "0", "0", "1", "0", "1", "0"};
addColumn(expectedSchedule, newTitle, newColumn);

assertTrue(scheduleTest.addInterviewer(interviewer));
assertEquals(expectedSchedule, scheduleTest);
Expand All @@ -120,11 +123,14 @@ public void addInterviewer_multipleAvailabilitiesSomeInvalid_true() {
/**
* Add a column into the schedule.
*/
private void addColumn(Schedule schedule, String[] newColumn) {
ObservableList<ObservableList<String>> table = schedule.getObservableList();
int numColumns = table.size();
IntStream.range(0, numColumns).forEach(i -> {
ObservableList<String> row = table.get(i);
private void addColumn(Schedule schedule, String newTitle, String[] newColumn) {
ObservableList<String> titles = schedule.getTitles();
titles.add(newTitle);

ObservableList<ObservableList<String>> data = schedule.getObservableList();
int numRows = data.size();
IntStream.range(0, numRows).forEach(i -> {
ObservableList<String> row = data.get(i);
row.add(newColumn[i]);
});
}
Expand All @@ -148,8 +154,9 @@ public void cloneSchedule_independentTest_notEqual() {
Schedule schedule = SampleSchedules.getSampleFilledSchedule();
Schedule cloneSchedule = Schedule.cloneSchedule(schedule);

String[] newColumn = new String[]{"Technical - Alice Pauline", "0", "0", "1", "0", "1", "0"};
addColumn(schedule, newColumn);
String newTitle = "Technical - Alice Pauline";
String[] newColumn = new String[]{"0", "0", "1", "0", "1", "0"};
addColumn(schedule, newTitle, newColumn);

assertNotEquals(schedule, cloneSchedule);
}
Expand Down

0 comments on commit 5f50478

Please sign in to comment.