From 92cb2cd1abce9d5c1facd9af1883c39782c56e01 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Thu, 7 Mar 2019 19:49:57 +0800 Subject: [PATCH 01/22] Planner: Initialize weekType for each Day --- src/planmysem/data/Planner.java | 25 +++++++++++++++++++++++-- src/planmysem/data/semester/Day.java | 4 ++-- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/src/planmysem/data/Planner.java b/src/planmysem/data/Planner.java index 4080aa688..ac8ea8b86 100644 --- a/src/planmysem/data/Planner.java +++ b/src/planmysem/data/Planner.java @@ -4,6 +4,8 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.time.LocalDate; +import java.time.temporal.TemporalField; +import java.time.temporal.WeekFields; import java.util.Calendar; import java.util.HashMap; import java.util.HashSet; @@ -42,17 +44,20 @@ public Planner() { Set recessDays = new HashSet<>(); Set readingDays = new HashSet<>(); Set normalDays = new HashSet<>(); + Map acadCalMap = null; // Read AcademicCalendar.txt to get current academic week try { Stream lines = Files.lines(Paths.get(filePath)); - Map acadCalMap = lines + acadCalMap = lines .collect(Collectors.toMap(key -> key.split(":")[0], val -> val.split(":")[1])); acadWeek = acadCalMap.get(Integer.toString(currentWeekOfYear)); } catch (IOException ioe) { // TODO: remove displaying of errors + // What if file is unable to be read? ioe.getMessage(); } + //System.out.println(acadCalMap); // Set variables if it is currently vacation if (acadWeek != null && acadWeek.equals("Vacation")) { @@ -113,9 +118,25 @@ public Planner() { HashMap days = new HashMap<>(); List datesList = startDate.datesUntil(endDate).collect(Collectors.toList()); for (LocalDate date: datesList) { - days.put(date, new Day(date.getDayOfWeek(), "")); + TemporalField weekField = WeekFields.ISO.weekOfWeekBasedYear(); + String weekOfYear = Integer.toString(date.get(weekField)); + String weekType = acadCalMap.get(weekOfYear); + days.put(date, new Day(date.getDayOfWeek(), weekType)); // TODO: Add type of the day here, recess/reading or normal + switch (weekType) { + case "Recess Week": + recessDays.add(date); + break; + case "Reading Week": + readingDays.add(date); + break; + default: + normalDays.add(date); + } } + //System.out.println(recessDays); + //System.out.println(readingDays); + //System.out.println(normalDays); semester = new Semester(acadSem, acadYear, days, startDate, endDate, noOfWeeks, recessDays, readingDays, normalDays); // TODO: set constants for fixed numbers, simplify/optimise code, handle ioe exception diff --git a/src/planmysem/data/semester/Day.java b/src/planmysem/data/semester/Day.java index ef9d2c531..27b736f63 100644 --- a/src/planmysem/data/semester/Day.java +++ b/src/planmysem/data/semester/Day.java @@ -20,12 +20,12 @@ public class Day implements ReadOnlyDay { */ public Day(DayOfWeek dayOfWeek, String weekType) { this.dayOfWeek = dayOfWeek; - this.type = null; + this.type = weekType; } public Day(DayOfWeek dayOfWeek, String weekType, ArrayList slots) { this.dayOfWeek = dayOfWeek; - this.type = null; + this.type = weekType; for (Slot slot : slots) { this.slots.add(slot); From 1a98449f838da47f90c4e05f12689b1bb15eb7b5 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Thu, 7 Mar 2019 19:59:19 +0800 Subject: [PATCH 02/22] Planner: Fix Codacy issue --- src/planmysem/data/Planner.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/planmysem/data/Planner.java b/src/planmysem/data/Planner.java index ac8ea8b86..f0e5f6cc4 100644 --- a/src/planmysem/data/Planner.java +++ b/src/planmysem/data/Planner.java @@ -132,6 +132,7 @@ public Planner() { break; default: normalDays.add(date); + break; } } //System.out.println(recessDays); From 45f791587eb6d283ec51580c5268789a00e81df8 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Fri, 8 Mar 2019 19:55:59 +0800 Subject: [PATCH 03/22] Planner: Update code for initialisation of semester --- AcademicCalendar.txt | 105 ++++++------- src/planmysem/data/Planner.java | 223 ++++++++++++++++----------- src/planmysem/data/semester/Day.java | 1 - 3 files changed, 183 insertions(+), 146 deletions(-) diff --git a/AcademicCalendar.txt b/AcademicCalendar.txt index 40bd2316d..237e292bd 100644 --- a/AcademicCalendar.txt +++ b/AcademicCalendar.txt @@ -1,52 +1,53 @@ -1:Vacation -2:Vacation -3:Week 1 -4:Week 2 -5:Week 3 -6:Week 4 -7:Week 5 -8:Week 6 -9:Recess Week -10:Week 7 -11:Week 8 -12:Week 9 -13:Week 10 -14:Week 11 -15:Week 12 -16:Week 13 -17:Reading Week -18:Examination Week -19:Examination Week -20:Vacation -21:Vacation -22:Vacation -23:Vacation -24:Vacation -25:Vacation -26:Vacation -27:Vacation -28:Vacation -29:Vacation -30:Vacation -31:Vacation -32:Orientation Week -33:Week 1 -34:Week 2 -35:Week 3 -36:Week 4 -37:Week 5 -38:Week 6 -39:Recess Week -40:Week 7 -41:Week 8 -42:Week 9 -43:Week 10 -44:Week 11 -45:Week 12 -46:Week 13 -47:Reading Week -48:Examination Week -49:Examination Week -50:Vacation -51:Vacation -52:Vacation \ No newline at end of file +1:Vacation_Sem 1 +2:Vacation_Sem 1 +3:Week 1_Sem 2 +4:Week 2_Sem 2 +5:Week 3_Sem 2 +6:Week 4_Sem 2 +7:Week 5_Sem 2 +8:Week 6_Sem 2 +9:Recess Week_Sem 2 +10:Week 7_Sem 2 +11:Week 8_Sem 2 +12:Week 9_Sem 2 +13:Week 10_Sem 2 +14:Week 11_Sem 2 +15:Week 12_Sem 2 +16:Week 13_Sem 2 +17:Reading Week_Sem 2 +18:Examination Week_Sem 2 +19:Examination Week_Sem 2 +20:Vacation_Sem 2 +21:Vacation_Sem 2 +22:Vacation_Sem 2 +23:Vacation_Sem 2 +24:Vacation_Sem 2 +25:Vacation_Sem 2 +26:Vacation_Sem 2 +27:Vacation_Sem 2 +28:Vacation_Sem 2 +29:Vacation_Sem 2 +30:Vacation_Sem 2 +31:Vacation_Sem 2 +32:Orientation Week_Sem 1 +33:Week 1_Sem 1 +34:Week 2_Sem 1 +35:Week 3_Sem 1 +36:Week 4_Sem 1 +37:Week 5_Sem 1 +38:Week 6_Sem 1 +39:Recess Week_Sem 1 +40:Week 7_Sem 1 +41:Week 8_Sem 1 +42:Week 9_Sem 1 +43:Week 10_Sem 1 +44:Week 11_Sem 1 +45:Week 12_Sem 1 +46:Week 13_Sem 1 +47:Reading Week_Sem 1 +48:Examination Week_Sem 1 +49:Examination Week_Sem 1 +50:Vacation_Sem 1 +51:Vacation_Sem 1 +52:Vacation_Sem 1 +53:Vacation_Sem 1 \ No newline at end of file diff --git a/src/planmysem/data/Planner.java b/src/planmysem/data/Planner.java index f0e5f6cc4..ee6f40e76 100644 --- a/src/planmysem/data/Planner.java +++ b/src/planmysem/data/Planner.java @@ -3,10 +3,11 @@ import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; +import java.time.DayOfWeek; import java.time.LocalDate; +import java.time.temporal.TemporalAdjusters; import java.time.temporal.TemporalField; import java.time.temporal.WeekFields; -import java.util.Calendar; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -30,99 +31,41 @@ public class Planner { * Creates an empty planner. */ public Planner() { - String filePath = "AcademicCalendar.txt"; - String acadWeek = null; - String acadYear = null; - String acadSem = null; - int noOfWeeks = 0; - Calendar cal = Calendar.getInstance(); - int currentWeekOfYear = cal.get(Calendar.WEEK_OF_YEAR); - int currentYear = cal.get(Calendar.YEAR); - LocalDate startDate = LocalDate.now(); - LocalDate endDate = LocalDate.now(); - // TODO: add recess days, reading days, normal days + String acadWeek; + String acadSem; + String acadYear; + String[] semesterDetails; + int noOfWeeks; + LocalDate startDate; + LocalDate endDate; + List datesList; + Map acadCalMap; + HashMap days = new HashMap<>(); Set recessDays = new HashSet<>(); Set readingDays = new HashSet<>(); Set normalDays = new HashSet<>(); - Map acadCalMap = null; - - // Read AcademicCalendar.txt to get current academic week - try { - Stream lines = Files.lines(Paths.get(filePath)); - acadCalMap = lines - .collect(Collectors.toMap(key -> key.split(":")[0], val -> val.split(":")[1])); - acadWeek = acadCalMap.get(Integer.toString(currentWeekOfYear)); - } catch (IOException ioe) { - // TODO: remove displaying of errors - // What if file is unable to be read? - ioe.getMessage(); - } - //System.out.println(acadCalMap); - - // Set variables if it is currently vacation - if (acadWeek != null && acadWeek.equals("Vacation")) { - acadSem = "Vacation"; - if (currentWeekOfYear < 3 || currentWeekOfYear > 49) { - noOfWeeks = 5; - - cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); - cal.set(Calendar.WEEK_OF_YEAR, 50); - startDate = LocalDate.of(currentYear, 12, cal.get(Calendar.DATE)); - - cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); - cal.set(Calendar.WEEK_OF_YEAR, 2); - endDate = LocalDate.of(currentYear, 1, cal.get(Calendar.DATE)); - } - if (currentWeekOfYear > 19 && currentWeekOfYear < 32) { - noOfWeeks = 12; - - cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); - cal.set(Calendar.WEEK_OF_YEAR, 20); - startDate = LocalDate.of(currentYear, 5, cal.get(Calendar.DATE)); - - cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); - cal.set(Calendar.WEEK_OF_YEAR, 31); - endDate = LocalDate.of(currentYear, 8, cal.get(Calendar.DATE)); - } - } - - // Set variables if it is currently not vacation - if (currentWeekOfYear > 31 && currentWeekOfYear < 50) { - acadYear = "AY" + currentYear + "/" + (currentYear + 1); - acadSem = "Sem 1"; - noOfWeeks = 18; - - cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); - cal.set(Calendar.WEEK_OF_YEAR, 32); - startDate = LocalDate.of(currentYear, 8, cal.get(Calendar.DATE)); - - cal.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY); - cal.set(Calendar.WEEK_OF_YEAR, 49); - endDate = LocalDate.of(currentYear, 12, cal.get(Calendar.DATE)); - } - if (currentWeekOfYear > 2 && currentWeekOfYear < 20) { - acadYear = "AY" + (currentYear - 1) + "/" + currentYear; - acadSem = "Sem 2"; - noOfWeeks = 17; - - cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); - cal.set(Calendar.WEEK_OF_YEAR, 3); - startDate = LocalDate.of(currentYear, 1, cal.get(Calendar.DATE)); - - cal.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY); - cal.set(Calendar.WEEK_OF_YEAR, 19); - endDate = LocalDate.of(currentYear, 5, cal.get(Calendar.DATE)); - } - - // Initialise hashmap of all days in current semester - HashMap days = new HashMap<>(); - List datesList = startDate.datesUntil(endDate).collect(Collectors.toList()); + + acadCalMap = getAcadCalMap(); + TemporalField weekField = WeekFields.ISO.weekOfWeekBasedYear(); + int currentWeekOfYear = LocalDate.now().get(weekField); + semesterDetails = getSemesterDetails(currentWeekOfYear, acadCalMap); + acadWeek = semesterDetails[0]; + acadSem = semesterDetails[1]; + acadYear = semesterDetails[2]; + noOfWeeks = Integer.parseInt(semesterDetails[3]); + startDate = LocalDate.parse(semesterDetails[4]); + endDate = LocalDate.parse(semesterDetails[5]); + + // Initialises HashMap and Sets of all days in current semester + datesList = startDate.datesUntil(endDate).collect(Collectors.toList()); for (LocalDate date: datesList) { - TemporalField weekField = WeekFields.ISO.weekOfWeekBasedYear(); - String weekOfYear = Integer.toString(date.get(weekField)); - String weekType = acadCalMap.get(weekOfYear); + int weekOfYear = date.get(weekField); + int firstMonOfYear = date.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)).getDayOfMonth(); + if (firstMonOfYear == 1) { + weekOfYear += 1; + } + String weekType = acadCalMap.get(Integer.toString(weekOfYear)).split("_")[0]; days.put(date, new Day(date.getDayOfWeek(), weekType)); - // TODO: Add type of the day here, recess/reading or normal switch (weekType) { case "Recess Week": recessDays.add(date); @@ -135,12 +78,9 @@ public Planner() { break; } } - //System.out.println(recessDays); - //System.out.println(readingDays); - //System.out.println(normalDays); + semester = new Semester(acadSem, acadYear, days, startDate, endDate, noOfWeeks, recessDays, readingDays, normalDays); - // TODO: set constants for fixed numbers, simplify/optimise code, handle ioe exception } /** @@ -156,6 +96,103 @@ public static Planner empty() { return new Planner(); } + /** + * Reads a file containing academic calendar details. + * + * @return a map of week of year to academic week + * throws some exception if a AcademicCalendar.txt is unable to be read. + */ + private Map getAcadCalMap() { + String filePath = "AcademicCalendar.txt"; + Map acadCalMap = null; + try { + Stream lines = Files.lines(Paths.get(filePath)); + acadCalMap = lines + .collect(Collectors.toMap(key -> key.split(":")[0], val -> val.split(":")[1])); + } catch (IOException ioe) { + // TODO: remove displaying of errors + // What if file is unable to be read? + ioe.getMessage(); + } + return acadCalMap; + } + + /** + * Initialises current semester's details. + * + * @param currentWeekOfYear current week of the year + * @param acadCalMap used to determine current academic week + * @return an array of Strings of the current semester's details + */ + private String[] getSemesterDetails(int currentWeekOfYear, Map acadCalMap) { + String acadWeek = null; + String acadSem = null; + String acadYear = null; + String noOfWeeks = null; + String[] acadWeekDetails; + LocalDate startDate = LocalDate.now(); + LocalDate endDate = LocalDate.now(); + int currentYear = LocalDate.now().getYear(); + // Initialise week numbers for certain weeks. + int firstWeekSemOne = 32; + int lastWeekSemOne = 49; + int firstWeekSemOneHol = 50; + int lastWeekSemOneHol = 2; + int firstWeekSemTwo = 3; + int lastWeekSemTwo = 19; + int firstWeekSemTwoHol = 20; + int lastWeekSemTwoHol = 31; + int firstMonOfYear = LocalDate.of(currentYear, 1, 1) + .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)).getDayOfMonth(); + // Readjust weeks if first Monday of the year falls on the 1st. + if (firstMonOfYear == 1) { + currentWeekOfYear += 1; + firstWeekSemOne -= 1; + lastWeekSemOne -= 1; + firstWeekSemOneHol -= 1; + lastWeekSemOneHol -= 1; + firstWeekSemTwo -= 1; + lastWeekSemTwo -= 1; + firstWeekSemTwoHol -= 1; + lastWeekSemTwoHol -= 1; + } + // Set semester details. + acadWeekDetails = acadCalMap.get(Integer.toString(currentWeekOfYear)).split("_"); + acadWeek = acadWeekDetails[0]; + acadSem = acadWeekDetails[1]; + if (acadWeek.equals("Vacation") && acadSem.equals("Sem 1")) { + noOfWeeks = "5"; + acadYear = "AY" + currentYear + "/" + (currentYear + 1); + startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOneHol); + startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); + endDate = LocalDate.of(currentYear + 1, 1, 1); + endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemOneHol); + endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); + } else if (acadWeek.equals("Vacation") && acadSem.equals("Sem 2")) { + noOfWeeks = "12"; + acadYear = "AY" + (currentYear - 1) + "/" + currentYear; + startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwoHol); + startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); + endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemTwoHol); + endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); + } else if (acadSem.equals("Sem 1")) { + noOfWeeks = "18"; + acadYear = "AY" + currentYear + "/" + (currentYear + 1); + startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOne); + startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); + endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemOne); + endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); + } else if (acadSem.equals("Sem 2")) { + noOfWeeks = "17"; + acadYear = "AY" + (currentYear - 1) + "/" + currentYear; + startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwo); + startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); + endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemTwo); + endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); + } + return new String[] {acadWeek, acadSem, acadYear, noOfWeeks, startDate.toString(), endDate.toString()}; + } + /** * Adds a day to the Planner. * diff --git a/src/planmysem/data/semester/Day.java b/src/planmysem/data/semester/Day.java index 27b736f63..0513fd125 100644 --- a/src/planmysem/data/semester/Day.java +++ b/src/planmysem/data/semester/Day.java @@ -16,7 +16,6 @@ public class Day implements ReadOnlyDay { /** * Assumption: Every field must be present and not null. - * TODO: Ding Heng, please init type */ public Day(DayOfWeek dayOfWeek, String weekType) { this.dayOfWeek = dayOfWeek; From 2c631dfeb915dd276660a082a58b9551e052c062 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Sat, 9 Mar 2019 16:59:31 +0800 Subject: [PATCH 04/22] Planner: Fix Codacy and checkstyle issues --- src/planmysem/data/Planner.java | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/planmysem/data/Planner.java b/src/planmysem/data/Planner.java index ee6f40e76..ef59cf3b1 100644 --- a/src/planmysem/data/Planner.java +++ b/src/planmysem/data/Planner.java @@ -31,7 +31,6 @@ public class Planner { * Creates an empty planner. */ public Planner() { - String acadWeek; String acadSem; String acadYear; String[] semesterDetails; @@ -44,18 +43,17 @@ public Planner() { Set recessDays = new HashSet<>(); Set readingDays = new HashSet<>(); Set normalDays = new HashSet<>(); - + acadCalMap = getAcadCalMap(); TemporalField weekField = WeekFields.ISO.weekOfWeekBasedYear(); int currentWeekOfYear = LocalDate.now().get(weekField); semesterDetails = getSemesterDetails(currentWeekOfYear, acadCalMap); - acadWeek = semesterDetails[0]; acadSem = semesterDetails[1]; acadYear = semesterDetails[2]; noOfWeeks = Integer.parseInt(semesterDetails[3]); startDate = LocalDate.parse(semesterDetails[4]); endDate = LocalDate.parse(semesterDetails[5]); - + // Initialises HashMap and Sets of all days in current semester datesList = startDate.datesUntil(endDate).collect(Collectors.toList()); for (LocalDate date: datesList) { @@ -78,7 +76,7 @@ public Planner() { break; } } - + semester = new Semester(acadSem, acadYear, days, startDate, endDate, noOfWeeks, recessDays, readingDays, normalDays); } @@ -133,6 +131,8 @@ private String[] getSemesterDetails(int currentWeekOfYear, Map a LocalDate startDate = LocalDate.now(); LocalDate endDate = LocalDate.now(); int currentYear = LocalDate.now().getYear(); + int weekOfYear = currentWeekOfYear; + // Initialise week numbers for certain weeks. int firstWeekSemOne = 32; int lastWeekSemOne = 49; @@ -144,9 +144,10 @@ private String[] getSemesterDetails(int currentWeekOfYear, Map a int lastWeekSemTwoHol = 31; int firstMonOfYear = LocalDate.of(currentYear, 1, 1) .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)).getDayOfMonth(); + // Readjust weeks if first Monday of the year falls on the 1st. if (firstMonOfYear == 1) { - currentWeekOfYear += 1; + weekOfYear += 1; firstWeekSemOne -= 1; lastWeekSemOne -= 1; firstWeekSemOneHol -= 1; @@ -156,11 +157,12 @@ private String[] getSemesterDetails(int currentWeekOfYear, Map a firstWeekSemTwoHol -= 1; lastWeekSemTwoHol -= 1; } + // Set semester details. - acadWeekDetails = acadCalMap.get(Integer.toString(currentWeekOfYear)).split("_"); + acadWeekDetails = acadCalMap.get(Integer.toString(weekOfYear)).split("_"); acadWeek = acadWeekDetails[0]; acadSem = acadWeekDetails[1]; - if (acadWeek.equals("Vacation") && acadSem.equals("Sem 1")) { + if ("Vacation".equals(acadWeek) && "Sem 1".equals(acadSem)) { noOfWeeks = "5"; acadYear = "AY" + currentYear + "/" + (currentYear + 1); startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOneHol); @@ -168,21 +170,21 @@ private String[] getSemesterDetails(int currentWeekOfYear, Map a endDate = LocalDate.of(currentYear + 1, 1, 1); endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemOneHol); endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); - } else if (acadWeek.equals("Vacation") && acadSem.equals("Sem 2")) { + } else if ("Vacation".equals(acadWeek) && "Sem 2".equals(acadSem)) { noOfWeeks = "12"; acadYear = "AY" + (currentYear - 1) + "/" + currentYear; startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwoHol); startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemTwoHol); endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); - } else if (acadSem.equals("Sem 1")) { + } else if ("Sem 1".equals(acadSem)) { noOfWeeks = "18"; acadYear = "AY" + currentYear + "/" + (currentYear + 1); startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOne); startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemOne); endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); - } else if (acadSem.equals("Sem 2")) { + } else if ("Sem 2".equals(acadSem)) { noOfWeeks = "17"; acadYear = "AY" + (currentYear - 1) + "/" + currentYear; startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwo); @@ -192,7 +194,7 @@ private String[] getSemesterDetails(int currentWeekOfYear, Map a } return new String[] {acadWeek, acadSem, acadYear, noOfWeeks, startDate.toString(), endDate.toString()}; } - + /** * Adds a day to the Planner. * From 5ac6ca98210e6a9d674d8042f566391ae551b7ce Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Sat, 9 Mar 2019 17:31:31 +0800 Subject: [PATCH 05/22] Planner: Fix build error --- src/planmysem/data/Planner.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/planmysem/data/Planner.java b/src/planmysem/data/Planner.java index 7dc6aa55c..ef59cf3b1 100644 --- a/src/planmysem/data/Planner.java +++ b/src/planmysem/data/Planner.java @@ -43,7 +43,6 @@ public Planner() { Set recessDays = new HashSet<>(); Set readingDays = new HashSet<>(); Set normalDays = new HashSet<>(); - Map acadCalMap = null; acadCalMap = getAcadCalMap(); TemporalField weekField = WeekFields.ISO.weekOfWeekBasedYear(); From 7e5b58cf1f4daf273afae3223f45227ad3539b0d Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Sun, 17 Mar 2019 03:20:40 +0800 Subject: [PATCH 06/22] Planner: Dynamic generation of semester from date --- src/planmysem/data/Planner.java | 242 +++++++++++++++++++++----------- 1 file changed, 162 insertions(+), 80 deletions(-) diff --git a/src/planmysem/data/Planner.java b/src/planmysem/data/Planner.java index 480d933b1..ef22434c3 100644 --- a/src/planmysem/data/Planner.java +++ b/src/planmysem/data/Planner.java @@ -1,13 +1,9 @@ package planmysem.data; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalTime; import java.time.temporal.TemporalAdjusters; -import java.time.temporal.TemporalField; import java.time.temporal.WeekFields; import java.util.HashMap; import java.util.HashSet; @@ -15,7 +11,6 @@ import java.util.Map; import java.util.Set; import java.util.stream.Collectors; -import java.util.stream.Stream; import planmysem.data.exception.IllegalValueException; import planmysem.data.semester.Day; @@ -35,6 +30,30 @@ public class Planner { * Creates an empty planner. */ public Planner() { + semester = generateSemester(LocalDate.now()); + } + + /** + * Constructs a Planner with the given data. + * + * @param semester external changes to this will not affect this Planner + */ + public Planner(Semester semester) { + this.semester = new Semester(semester); + } + + public static Planner empty() { + return new Planner(); + } + + /** + * Generates current semester based on current date. + * As long as the current date falls within a semester, the generated semester is always the same. + * + * @param currentDate the current date when the program is run + * @return the current semester object + */ + public static Semester generateSemester(LocalDate currentDate) { String acadSem; String acadYear; String[] semesterDetails; @@ -42,33 +61,26 @@ public Planner() { LocalDate startDate; LocalDate endDate; List datesList; - Map acadCalMap; + HashMap acadCalMap; HashMap days = new HashMap<>(); Set recessDays = new HashSet<>(); Set readingDays = new HashSet<>(); Set normalDays = new HashSet<>(); Set examDays = new HashSet<>(); - acadCalMap = getAcadCalMap(); - TemporalField weekField = WeekFields.ISO.weekOfWeekBasedYear(); - int currentWeekOfYear = LocalDate.now().get(weekField); - semesterDetails = getSemesterDetails(currentWeekOfYear, acadCalMap); + acadCalMap = generateAcadCalMap(currentDate); + semesterDetails = getSemesterDetails(currentDate, acadCalMap); acadSem = semesterDetails[1]; acadYear = semesterDetails[2]; noOfWeeks = Integer.parseInt(semesterDetails[3]); startDate = LocalDate.parse(semesterDetails[4]); endDate = LocalDate.parse(semesterDetails[5]); - // Initialises HashMap and Sets of all days in current semester + // Initialise HashMap and Sets of all days in current semester datesList = startDate.datesUntil(endDate).collect(Collectors.toList()); for (LocalDate date: datesList) { - int weekOfYear = date.get(weekField); - LocalDate firstDayOfYear = date.with(TemporalAdjusters.firstDayOfYear()); - int firstMonOfYear = firstDayOfYear.with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)).getDayOfMonth(); - if (firstMonOfYear == 1) { - weekOfYear += 1; - } - String weekType = acadCalMap.get(Integer.toString(weekOfYear)).split("_")[0]; + int weekOfYear = date.get(WeekFields.ISO.weekOfWeekBasedYear()); + String weekType = acadCalMap.get(weekOfYear).split("_")[0]; days.put(date, new Day(date.getDayOfWeek(), weekType)); switch (weekType) { case "Recess Week": @@ -86,97 +98,167 @@ public Planner() { } } - semester = new Semester(acadSem, acadYear, days, startDate, endDate, noOfWeeks, + return new Semester(acadSem, acadYear, days, startDate, endDate, noOfWeeks, recessDays, readingDays, normalDays, examDays); } /** - * Constructs a Planner with the given data. + * Generates academic calendar for a given date. * - * @param semester external changes to this will not affect this Planner + * @param date used to determine academic year + * @return details of academic calendar */ - public Planner(Semester semester) { - this.semester = new Semester(semester); - } + private static HashMap generateAcadCalMap(LocalDate date) { + HashMap acadCalMap = new HashMap<>(); + LocalDate semOneStartDate = date; + LocalDate semTwoEndDate = date; + int currentMonth = date.getMonthValue(); + int currentYear = date.getYear(); + int semOneStartWeek; + int semTwoStartWeek; + int semTwoEndWeek; + int acadWeekNo; + int noOfWeeksInYear; + int vacationWeekNo; - public static Planner empty() { - return new Planner(); - } + if (currentMonth < 8) { + // Academic Year beginning from August of previous year + semOneStartDate = semOneStartDate.withYear(currentYear - 1).withMonth(8) + .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); + semOneStartWeek = semOneStartDate.get(WeekFields.ISO.weekOfWeekBasedYear()); + semTwoEndDate = semTwoEndDate.withYear(currentYear).withMonth(8) + .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)).minusDays(1); + semTwoEndWeek = semTwoEndDate.get(WeekFields.ISO.weekOfWeekBasedYear()); + } else { + // Academic Year beginning from August of current year + semOneStartDate = semOneStartDate.withYear(currentYear).withMonth(8) + .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); + semOneStartWeek = semOneStartDate.get(WeekFields.ISO.weekOfWeekBasedYear()); + semTwoEndDate = semTwoEndDate.withYear(currentYear + 1).withMonth(8) + .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)).minusDays(1); + semTwoEndWeek = semTwoEndDate.get(WeekFields.ISO.weekOfWeekBasedYear()); + } - /** - * Reads a file containing academic calendar details. - * - * @return a map of week of year to academic week - * throws some exception if a AcademicCalendar.txt is unable to be read. - */ - private Map getAcadCalMap() { - String filePath = "AcademicCalendar.txt"; - Map acadCalMap = null; - try { - Stream lines = Files.lines(Paths.get(filePath)); - acadCalMap = lines - .collect(Collectors.toMap(key -> key.split(":")[0], val -> val.split(":")[1])); - } catch (IOException ioe) { - // TODO: remove displaying of errors - // What if file is unable to be read? - ioe.getMessage(); + // Sem 1 - Orientation Week + acadCalMap.put(semOneStartWeek, "Orientation Week_Sem 1"); + + // Sem 1 - Week 1 to 6 + acadWeekNo = 1; + for (int i = semOneStartWeek + 1; i < semOneStartWeek + 7; i++) { + acadCalMap.put(i, "Week " + acadWeekNo + "_Sem 1"); + acadWeekNo++; + } + + // Sem 1 - Recess Week + acadCalMap.put(semOneStartWeek + 7, "Recess Week_Sem 1"); + + // Sem 1 - Week 7 to 13 + acadWeekNo = 7; + for (int i = semOneStartWeek + 8; i < semOneStartWeek + 15; i++) { + acadCalMap.put(i, "Week " + acadWeekNo + "_Sem 1"); + acadWeekNo++; + } + + // Sem 1 - Reading & Examination Weeks + acadCalMap.put(semOneStartWeek + 15, "Reading Week_Sem 1"); + acadCalMap.put(semOneStartWeek + 16, "Examination Week_Sem 1"); + acadCalMap.put(semOneStartWeek + 17, "Examination Week_Sem 1"); + + // Sem 1 - Vacation + noOfWeeksInYear = (int) semOneStartDate.range(WeekFields.ISO.weekOfWeekBasedYear()).getMaximum(); + vacationWeekNo = semOneStartWeek + 18; + semTwoStartWeek = 1; + for (int i = 0; i < 5; i++) { + if ((vacationWeekNo + i) <= noOfWeeksInYear) { + acadCalMap.put(vacationWeekNo + i, "Vacation_Sem 1"); + } else { + acadCalMap.put(semTwoStartWeek++, "Vacation_Sem 1"); + } } + + // Sem 2 - Week 1 to 6 + acadWeekNo = 1; + for (int i = semTwoStartWeek; i < semTwoStartWeek + 6; i++) { + acadCalMap.put(i, "Week " + acadWeekNo + "_Sem 2"); + acadWeekNo++; + } + + // Sem 2 - Recess Week + acadCalMap.put(semTwoStartWeek + 6, "Recess Week_Sem 2"); + + // Sem 2 - Week 7 to 13 + acadWeekNo = 7; + for (int i = semTwoStartWeek + 7; i < semTwoStartWeek + 14; i++) { + acadCalMap.put(i, "Week " + acadWeekNo + "_Sem 2"); + acadWeekNo++; + } + + // Sem 2 - Reading & Examination Weeks + acadCalMap.put(semTwoStartWeek + 14, "Reading Week_Sem 2"); + acadCalMap.put(semTwoStartWeek + 15, "Examination Week_Sem 2"); + acadCalMap.put(semTwoStartWeek + 16, "Examination Week_Sem 2"); + + // Sem 2 - Vacation + vacationWeekNo = semTwoStartWeek + 17; + while (vacationWeekNo <= semTwoEndWeek) { + acadCalMap.put(vacationWeekNo++, "Vacation_Sem 2"); + } + return acadCalMap; } /** * Initialises current semester's details. * - * @param currentWeekOfYear current week of the year + * @param date the current date when the program is run * @param acadCalMap used to determine current academic week * @return an array of Strings of the current semester's details */ - private String[] getSemesterDetails(int currentWeekOfYear, Map acadCalMap) { - String acadWeek = null; - String acadSem = null; + private static String[] getSemesterDetails(LocalDate date, HashMap acadCalMap) { + String acadWeek; + String acadSem; String acadYear = null; String noOfWeeks = null; String[] acadWeekDetails; - LocalDate startDate = LocalDate.now(); - LocalDate endDate = LocalDate.now(); - int currentYear = LocalDate.now().getYear(); - int weekOfYear = currentWeekOfYear; + LocalDate startDate = date; + LocalDate endDate = date; + int currentYear = date.getYear(); + int currentWeekOfYear = date.get(WeekFields.ISO.weekOfWeekBasedYear()); // Initialise week numbers for certain weeks. - int firstWeekSemOne = 32; - int lastWeekSemOne = 49; - int firstWeekSemOneHol = 50; - int lastWeekSemOneHol = 2; - int firstWeekSemTwo = 3; - int lastWeekSemTwo = 19; - int firstWeekSemTwoHol = 20; - int lastWeekSemTwoHol = 31; - int firstMonOfYear = LocalDate.of(currentYear, 1, 1) - .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)).getDayOfMonth(); - - // Readjust weeks if first Monday of the year falls on the 1st. - if (firstMonOfYear == 1) { - weekOfYear += 1; - firstWeekSemOne -= 1; - lastWeekSemOne -= 1; - firstWeekSemOneHol -= 1; - lastWeekSemOneHol -= 1; - firstWeekSemTwo -= 1; - lastWeekSemTwo -= 1; - firstWeekSemTwoHol -= 1; - lastWeekSemTwoHol -= 1; + int firstWeekSemOne = 0; + int firstWeekSemOneHol = 0; + int lastWeekSemOneHol = 0; + int firstWeekSemTwo = 0; + int firstWeekSemTwoHol = 0; + for (Map.Entry entry: acadCalMap.entrySet()) { + if ("Orientation Week_Sem 1".equals(entry.getValue())) { + firstWeekSemOne = entry.getKey(); + } else if ("Examination Week_Sem 1".equals(entry.getValue())) { + firstWeekSemOneHol = entry.getKey() + 1; + } else if ("Week 1_Sem 2".equals(entry.getValue())) { + lastWeekSemOneHol = entry.getKey() - 1; + firstWeekSemTwo = entry.getKey(); + } else if ("Examination Week_Sem 2".equals(entry.getValue())) { + firstWeekSemTwoHol = entry.getKey() + 1; + } } // Set semester details. - acadWeekDetails = acadCalMap.get(Integer.toString(weekOfYear)).split("_"); + acadWeekDetails = acadCalMap.get(currentWeekOfYear).split("_"); acadWeek = acadWeekDetails[0]; acadSem = acadWeekDetails[1]; if ("Vacation".equals(acadWeek) && "Sem 1".equals(acadSem)) { noOfWeeks = "5"; - acadYear = "AY" + currentYear + "/" + (currentYear + 1); + if (currentWeekOfYear < 4) { + acadYear = "AY" + (currentYear - 1) + "/" + currentYear; + startDate = startDate.withYear(currentYear - 1); + } else { + acadYear = "AY" + currentYear + "/" + (currentYear + 1); + endDate = endDate.withYear(currentYear + 1); + } startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOneHol); startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); - endDate = LocalDate.of(currentYear + 1, 1, 1); endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemOneHol); endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); } else if ("Vacation".equals(acadWeek) && "Sem 2".equals(acadSem)) { @@ -184,21 +266,21 @@ private String[] getSemesterDetails(int currentWeekOfYear, Map a acadYear = "AY" + (currentYear - 1) + "/" + currentYear; startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwoHol); startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); - endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemTwoHol); + endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwoHol + 11); endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); } else if ("Sem 1".equals(acadSem)) { noOfWeeks = "18"; acadYear = "AY" + currentYear + "/" + (currentYear + 1); startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOne); startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); - endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemOne); + endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOne + 17); endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); } else if ("Sem 2".equals(acadSem)) { noOfWeeks = "17"; acadYear = "AY" + (currentYear - 1) + "/" + currentYear; startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwo); startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); - endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemTwo); + endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwo + 16); endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); } return new String[] {acadWeek, acadSem, acadYear, noOfWeeks, startDate.toString(), endDate.toString()}; From 60d1cda7c3f6427fdd4bc6660a616f35c98e4a07 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Sun, 17 Mar 2019 03:27:28 +0800 Subject: [PATCH 07/22] PlannerTest: Add JUnit test for generateSemester --- test/java/planmysem/data/PlannerTest.java | 157 ++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 test/java/planmysem/data/PlannerTest.java diff --git a/test/java/planmysem/data/PlannerTest.java b/test/java/planmysem/data/PlannerTest.java new file mode 100644 index 000000000..654b79633 --- /dev/null +++ b/test/java/planmysem/data/PlannerTest.java @@ -0,0 +1,157 @@ +package planmysem.data; + +import static junit.framework.TestCase.assertEquals; + +import java.time.LocalDate; +import java.time.temporal.WeekFields; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import org.junit.Test; + +import planmysem.data.semester.Day; +import planmysem.data.semester.Semester; + + +public class PlannerTest { + + @Test + public void execute_generateSemester() { + TestDataHelper helper = new TestDataHelper(); + Semester generatedSemester; + Semester expectedSemester; + + // Assert Semester One generation + generatedSemester = Planner.generateSemester(LocalDate.of(2018, 8, 6)); + LocalDate semOneDate = LocalDate.of(2018, 8, 6); + expectedSemester = helper.generateSemesterFromDate(semOneDate, "Sem 1"); + assertSameSemester(generatedSemester, expectedSemester); + + expectedSemester = Planner.generateSemester(LocalDate.of(2018, 10, 6)); + assertSameSemester(generatedSemester, expectedSemester); + + // Assert Semester Two generation + generatedSemester = Planner.generateSemester(LocalDate.of(2019, 1, 14)); + LocalDate semTwoDate = LocalDate.of(2019, 1, 14); + expectedSemester = helper.generateSemesterFromDate(semTwoDate, "Sem 2"); + assertSameSemester(generatedSemester, expectedSemester); + + expectedSemester = Planner.generateSemester(LocalDate.of(2019, 3, 17)); + assertSameSemester(generatedSemester, expectedSemester); + } + + /** + * Asserts that the generated and expected Semester contents are equal. + */ + private void assertSameSemester(Semester generatedSemester, Semester expectedSemester) { + //Confirm the state of data is as expected + assertEquals(generatedSemester.getName(), expectedSemester.getName()); + assertEquals(generatedSemester.getAcademicYear(), expectedSemester.getAcademicYear()); + assertEquals(generatedSemester.getNoOfWeeks(), expectedSemester.getNoOfWeeks()); + assertEquals(generatedSemester.getStartDate(), expectedSemester.getStartDate()); + assertEquals(generatedSemester.getEndDate(), expectedSemester.getEndDate()); + assertEquals(generatedSemester.getDays().size(), expectedSemester.getDays().size()); + assertEquals(generatedSemester.getRecessDays().size(), expectedSemester.getRecessDays().size()); + assertEquals(generatedSemester.getReadingDays().size(), expectedSemester.getReadingDays().size()); + assertEquals(generatedSemester.getExamDays().size(), expectedSemester.getExamDays().size()); + } + + /** + * A utility class to generate test data. + */ + class TestDataHelper { + + /** + * Generates a Semester from the given date + * + * @param startDate given date which the semester should start from + * @param acadSem the semester of the academic year + * @return a Semester object from a specified date + */ + Semester generateSemesterFromDate(LocalDate startDate, String acadSem) { + String acadYear = null; + LocalDate endDate = LocalDate.now(); + int givenYear = startDate.getYear(); + int weekOfStartDate = startDate.get(WeekFields.ISO.weekOfWeekBasedYear()); + int noOfWeeks = 0; + HashMap weekNames = new HashMap<>(); + HashMap days = new HashMap<>(); + Set recessDays = new HashSet<>(); + Set readingDays = new HashSet<>(); + Set normalDays = new HashSet<>(); + Set examDays = new HashSet<>(); + + if ("Sem 1".equals(acadSem)) { + noOfWeeks = 18; + acadYear = "AY" + givenYear + "/" + (givenYear + 1); + endDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), weekOfStartDate + 18 - 1); + endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); + + weekNames.put(weekOfStartDate, "Orientation Week"); + int week = 1; + for (int i = weekOfStartDate + 1; i < weekOfStartDate + 7; i++) { + weekNames.put(i, "Week " + week); + week++; + } + weekNames.put(weekOfStartDate + 7, "Recess Week"); + week = 7; + for (int i = weekOfStartDate + 8; i < weekOfStartDate + 15; i++) { + weekNames.put(i, "Week " + week); + week++; + } + weekNames.put(weekOfStartDate + 15, "Reading Week"); + weekNames.put(weekOfStartDate + 16, "Examination Week"); + weekNames.put(weekOfStartDate + 17, "Examination Week"); + } else if ("Sem 2".equals(acadSem)) { + noOfWeeks = 17; + acadYear = "AY" + (givenYear - 1) + "/" + givenYear; + endDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), weekOfStartDate + 17 - 1); + endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); + + int week = 1; + for (int i = weekOfStartDate; i < weekOfStartDate + 6; i++) { + weekNames.put(i, "Week " + week); + week++; + } + weekNames.put(weekOfStartDate + 6, "Recess Week"); + week = 7; + for (int i = weekOfStartDate + 7; i < weekOfStartDate + 14; i++) { + weekNames.put(i, "Week " + week); + week++; + } + weekNames.put(weekOfStartDate + 14, "Reading Week"); + weekNames.put(weekOfStartDate + 15, "Examination Week"); + weekNames.put(weekOfStartDate + 16, "Examination Week"); + } + + // Initialises HashMap and Sets of all days in current semester + List datesList = startDate.datesUntil(endDate).collect(Collectors.toList()); + for (LocalDate date: datesList) { + int weekOfYear = date.get(WeekFields.ISO.weekOfWeekBasedYear()); + String weekType = weekNames.get(weekOfYear); + days.put(date, new Day(date.getDayOfWeek(), weekType)); + switch (weekType) { + case "Recess Week": + recessDays.add(date); + break; + case "Reading Week": + readingDays.add(date); + break; + case "Examination Week": + examDays.add(date); + break; + default: + normalDays.add(date); + break; + } + } + + return new Semester(acadSem, acadYear, days, startDate, endDate, noOfWeeks, + recessDays, readingDays, normalDays, examDays); + } + } + +} From dbcf1fd41bbddf64735382e19afc68bd1e2fce3f Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Mon, 18 Mar 2019 01:38:40 +0800 Subject: [PATCH 08/22] Update documentation for view command --- docs/DeveloperGuide.adoc | 46 +++++++++++++++++++++++++++++++++++++--- docs/UserGuide.adoc | 19 +++++++++++------ 2 files changed, 56 insertions(+), 9 deletions(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 7d0cd425e..fce86da16 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -226,6 +226,15 @@ The `Storage` component, * can save `UserPref` objects in json format and read it back. * can save the Address Book data in json format and read it back. +[[Design-Planner]] +=== Planner component + +*API* : link:{repoURL}/src/planmysem/data/Planner.java[`Planner.java`] + +The `Planner` component, + +* can initialise and hold a `Semester` object. + [[Design-Commons]] === Common classes @@ -235,6 +244,37 @@ Classes used by multiple components are in the `seedu.addressbook.commons` packa This section describes some noteworthy details on how certain features are implemented. +=== Month/Week/Day View feature +==== Planned Implementation + +The month/week/day view mechanism is facilitated by `PlannerView`. +It extends `Planner` with different calendar views, stored internally as `monthView`, `weekView` and `dayView`. +Additionally, it implements the following operations: + +* `PlannerView.displayMonthView()` - Displays the current semester in a monthly calendar view. +* `PlannerView.displayWeekView()` - Displays the current semester in a weekly calendar view. +* `PlannerView.displayDayView()` - Displays the current semester in a daily calendar view. + +Given below is an example usage scenario and how the month/week/day view feature behaves at each step. + +Step 1. The user launches the application for the first time. The `PlannerView` will be initialized with the contents in the `Planner`. The `Planner` might contain a `Semester` which is empty or a `Semester` populated with slots after reading `PlanMySem.txt`. + +Step 2. The user executes `add n/CS2113T Tutorial ...` to add a new slot to the planner. The `add` command would add a new `Slot` to the `Semester` of the `Planner`. + +Step 3. The user executes `view month March` command to view the calendar for March. The `view` command calls `PlannerView.displayMonthView()`, which loads the data the updated `Semester` from the `Planner` into `monthView`. + + +==== Design Considerations + +===== Aspect: How a type of view is initialised or updated + +* **Alternative 1 (current choice):** Initialised from `Planner` only upon `view` command. +** Pros: Easy to implement. Less operations performed by the program. +* **Alternative 2:** Updated upon any `add`/`edit`/`delete` slot command. +** Pros: `PlannerView` is always updated. +** Cons: Large amount of extra operations. + + // tag::undoredo[] === Undo/Redo feature ==== Current Implementation @@ -841,7 +881,7 @@ Priorities: High (must have) - `* * \*`, Medium (nice to have) - `* \*`, Low (un |`* * *` |user |view all slots on a certain day |conveniently view my planner for the day |`* * *` |user |view all slots on a certain week |conveniently view my planner for the week |`* * *` |user |view all slots on a certain month |conveniently view my planner for the month -|`* * *` |user |add details to a slot |record information related to the slot +|`* * *` |user |add details to a slot |record information related to the slot |`* *` |user |view the planner in a graphic calendar format|easily view my schedule for the day/week/month/semester |`* *` |user |view a slot |view the details of a specific activity I am looking for |`* *` |user |remove tags on a time slot |remove unused/ unnecessary tags from an activity* @@ -880,7 +920,7 @@ User case ends. === Use Case: List and Delete a Module . User inputs the command to list all modules he/she is enrolled in. . System lists all the modules. -. User selects the intended module from the list and inputs the delete command along with the module name for deletion. +. User selects the intended module from the list and inputs the delete command along with the module name for deletion. + Use case ends. @@ -948,7 +988,7 @@ _{More to be added}_ . The system should respond relatively quickly to user commands so as to not make the user wait around; this is an advantage of using PlanMySem. . The system should take up relatively little space on the local machine so as to cater to all students and OS. . The system should be easy to use, intuitive and simple, such that any student regardless of past experience with calendar/scheduling softwares is able to use it. -. The system should be flexible to allow all kinds of schedules that target users might have. +. The system should be flexible to allow all kinds of schedules that target users might have. . The data should be encrypted to prevent private data from being accessed. [appendix] diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index f725bcc95..626b7dad1 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -198,16 +198,23 @@ Format: `view day DATE | view week WEEK | view month MONTH | view all` [NOTE] ==== . If no date is given, the current date is assumed. -. If the `all` option is specified, the planner will not be displayed, instead all the details in the planner will be displayed.==== +. If the `all` option is specified, the planner will not be displayed, instead all the details in the planner will be displayed. ==== Example: -* `view day` -* `view day 1-03` + -View the first of January. +* `view day` + +View planner for the current date. +* `view day 01/03/2019` + +View planner for the first of March. +* `view week 7` + +View planner for week 7 of the academic calendar. +* `view week recess` + +View planner for recess week of the academic calendar. +* `view month March` + +View planner for the month of March. * `view all` + -all the details in the planner. +View all the details in the planner. === Listing previous inputted commands : `history` @@ -307,7 +314,7 @@ e.g.`del c/CS2113T a/frisbee t/hard module` * *View planner* : `view day [DATE] | view week [WEEK] | view month [MONTH]` + e.g.`view day 01/04/2019` * *View all details* : `view all` + -e.g.`view day 01/04/2019` +e.g.`view all` * *View history* : `history` * *Undo previous command* : `undo` * *Redo previously undone co* : `redo` From f0d916b944ba45df332e407c04c8fb726dd49695 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Mon, 18 Mar 2019 17:12:28 +0800 Subject: [PATCH 09/22] Add view command for monthly calendar view --- src/planmysem/commands/ViewCommand.java | 137 ++++++++++++++++++++++++ src/planmysem/parser/Parser.java | 48 +++++---- src/planmysem/ui/DarkTheme.css | 2 +- 3 files changed, 163 insertions(+), 24 deletions(-) create mode 100644 src/planmysem/commands/ViewCommand.java diff --git a/src/planmysem/commands/ViewCommand.java b/src/planmysem/commands/ViewCommand.java new file mode 100644 index 000000000..a11b278ac --- /dev/null +++ b/src/planmysem/commands/ViewCommand.java @@ -0,0 +1,137 @@ +package planmysem.commands; + +import java.time.LocalDate; +import java.util.HashMap; + +import planmysem.data.semester.Day; +import planmysem.data.semester.Semester; + +/** + * Adds a person to the address book. + */ +public class ViewCommand extends Command { + + public static final String COMMAND_WORD = "view"; + public static final String COMMAND_WORD_SHORT = "v"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": View month/week/day view or all details of planner." + + "\n\tParameters: " + + "\n\t\tMandatory: [viewType] [specifier]" + + "\n\tExample 1: " + COMMAND_WORD + + " month" + + "\n\tExample 2: " + COMMAND_WORD + + " week 7" + + "\n\tExample 3: " + COMMAND_WORD + + " week recess" + + "\n\tExample 4: " + COMMAND_WORD + + " day 01/03/2019" + + "\n\tExample 5: " + COMMAND_WORD + + " all"; + + private final String viewArgs; + + public ViewCommand(String viewArgs) { + this.viewArgs = viewArgs; + } + + @Override + public CommandResult execute() { + String viewType; + String viewSpecifier; + final Semester currentSemester = planner.getSemester(); + String output = null; + + if ("all".equals(viewArgs)) { + //TODO: print all planner details + output = "all"; + } else if ("month".equals(viewArgs)) { + output = displayMonthView(currentSemester); + } else { + viewType = viewArgs.split(" ")[0]; + //viewSpecifier = viewArgs.split(" ")[1]; + + switch (viewType) { + case "month": + //TODO: month view + break; + case "week": + //TODO: week view + break; + case "day": + //TODO: day view + break; + default: + break; + } + } + + return new CommandResult(output); + } + + /** + * Display all months for the semester. + */ + private String displayMonthView(Semester currentSemester) { + HashMap allDays = currentSemester.getDays(); + LocalDate semesterStartDate = currentSemester.getStartDate(); + LocalDate semesterEndDate = currentSemester.getEndDate(); + int year = semesterStartDate.getYear(); + LocalDate firstDayOfMonth = semesterStartDate.withDayOfMonth(1); + int spaces = firstDayOfMonth.getDayOfWeek().getValue(); + int lastMonthOfSem = semesterEndDate.getMonthValue(); + StringBuilder sb = new StringBuilder(); + + String[] months = {"", "January", "February", "March", "April", "May", "June", + "July", "August", "September", "October", "November", "December"}; + + int[] days = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; + + for (int m = 1; m <= lastMonthOfSem; m++) { + // Set number of days in February to 29 if it is a leap year. + if ((((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) && m == 2) { + days[m] = 29; + } + + // Print calendar header. + sb.append(" " + months[m] + " " + year + "\n"); + sb.append("_____________________________________\n"); + sb.append(" Sun Mon Tue Wed Thu Fri Sat\n"); + + // Print spaces required for the start of a month. + spaces = (days[m - 1] + spaces) % 7; + for (int i = 0; i < spaces; i++) { + sb.append(" "); + } + // Print the days in the month. + for (int i = 1; i <= days[m]; i++) { + sb.append(String.format(" %3d", i)); + if (((i + spaces) % 7 == 0)) { + Day tempDay = allDays.get(LocalDate.of(year, m, i)); + String weekType = ""; + if (tempDay != null) { + weekType = tempDay.getType(); + } + sb.append(" | " + weekType + "\n"); + } + if (i == days[m]) { + LocalDate tempDate = LocalDate.of(year, m, i); + Day tempDay = allDays.get(tempDate); + String weekType = ""; + int extraSpaces = 6 - (tempDate.getDayOfWeek().getValue() % 7); + for (int j = 0; j < extraSpaces; j++) { + sb.append(" "); + } + if (tempDay != null) { + weekType = tempDay.getType(); + } + sb.append(" | " + weekType + "\n"); + } + } + + sb.append("\n"); + } + + return sb.toString(); + } + +} diff --git a/src/planmysem/parser/Parser.java b/src/planmysem/parser/Parser.java index 3cdf637bd..c012c1358 100644 --- a/src/planmysem/parser/Parser.java +++ b/src/planmysem/parser/Parser.java @@ -22,6 +22,7 @@ import planmysem.commands.HelpCommand; import planmysem.commands.IncorrectCommand; import planmysem.commands.ListCommand; +import planmysem.commands.ViewCommand; import planmysem.common.Utils; import planmysem.data.exception.IllegalValueException; @@ -90,6 +91,10 @@ public Command parseCommand(String userInput) { case ListCommand.COMMAND_WORD_SHORT: return prepareList(arguments); + case ViewCommand.COMMAND_WORD: + case ViewCommand.COMMAND_WORD_SHORT: + return prepareView(arguments); + case ClearCommand.COMMAND_WORD: return new ClearCommand(); @@ -317,31 +322,28 @@ private Command prepareList(String args) { * @param args full command args string * @return the prepared command */ - // private Command prepareView(String args) { - // - // try { - // final int targetIndex = parseArgsAsDisplayedIndex(args); - // return new ViewCommand(targetIndex); - // } catch (ParseException | NumberFormatException e) { - // return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, - // ViewCommand.MESSAGE_USAGE)); - // } - // } + private Command prepareView(String args) { + if (args == null || args.trim().isEmpty()) { + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewCommand.MESSAGE_USAGE)); + } - /** - * Parses the given arguments string as a single index number. - * - * @param args arguments string to parse as index number - * @return the parsed index number - * @throws ParseException if no region of the args string could be found for the index - * @throws NumberFormatException the args string region is not a valid number - */ - private int parseArgsAsDisplayedIndex(String args) throws ParseException, NumberFormatException { - final Matcher matcher = PERSON_INDEX_ARGS_FORMAT.matcher(args.trim()); - if (!matcher.matches()) { - throw new ParseException("Could not find index number to parse"); + String[] viewArgs = args.split(" "); + if ("all".equals(viewArgs[1]) && viewArgs.length == 2) { + return new ViewCommand(viewArgs[1]); + } else if ("month".equals(viewArgs[1]) && viewArgs.length == 2) { + return new ViewCommand(viewArgs[1]); + } else if ("month".equals(viewArgs[1]) && viewArgs.length == 3) { + //TODO: ensure month arguments + return new ViewCommand(viewArgs[1] + " " + viewArgs[2]); + } else if ("week".equals(viewArgs[1]) && viewArgs.length == 3) { + //TODO: ensure week arguments + return new ViewCommand(viewArgs[1] + " " + viewArgs[2]); + } else if ("day".equals(viewArgs[1]) && viewArgs.length == 3) { + //TODO: ensure day arguments + return new ViewCommand(viewArgs[1] + " " + viewArgs[2]); } - return Integer.parseInt(matcher.group("targetIndex")); + + return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT, ViewCommand.MESSAGE_USAGE)); } /** diff --git a/src/planmysem/ui/DarkTheme.css b/src/planmysem/ui/DarkTheme.css index 5b2b70656..1c619d1de 100644 --- a/src/planmysem/ui/DarkTheme.css +++ b/src/planmysem/ui/DarkTheme.css @@ -10,7 +10,7 @@ .text-area { -fx-background-color: black; -fx-control-inner-background: black; - -fx-font-family: "Segoe UI Semibold"; + -fx-font-family: "Lucida Console"; -fx-font-size: 10pt; -fx-padding: 5 5 5 5; } From 1eded380524d018aedf53130f9c73a4edd91d428 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Mon, 18 Mar 2019 17:26:07 +0800 Subject: [PATCH 10/22] Fix Codacy issue --- src/planmysem/commands/ViewCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/planmysem/commands/ViewCommand.java b/src/planmysem/commands/ViewCommand.java index a11b278ac..e5796f1e0 100644 --- a/src/planmysem/commands/ViewCommand.java +++ b/src/planmysem/commands/ViewCommand.java @@ -37,7 +37,7 @@ public ViewCommand(String viewArgs) { @Override public CommandResult execute() { String viewType; - String viewSpecifier; + //String viewSpecifier; final Semester currentSemester = planner.getSemester(); String output = null; From bfac0783f26911b8f2f933965b6f5eb0f6689f87 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Tue, 19 Mar 2019 20:49:55 +0800 Subject: [PATCH 11/22] UserGuide: Update user guide documentation --- docs/UserGuide.adoc | 68 ++++++++++++++++++++++++++------------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index e54efc2a7..257d53537 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -18,7 +18,7 @@ By: `Team T08-3` Since: `Jan 2019` Licence: `MIT` == Introduction -Welcome to _PlanMySem_! +Welcome to _PlanMySem_! Choose a topic from the table of contents to learn about available features with examples, find answers or view a summary of the commands. _PlanMySem_ is a text-based (Command Line Interface) scheduling/calendar application that targets NUS students and staff who prefer to use a desktop application for managing their schedule/calendar. _PlanMySem_ automatically creates a planner that is synchronised according to the NUS academic calendar for the current semester and enables easy creation, editing and deleting of items. @@ -27,6 +27,8 @@ Items can then be efficiently managed via the intuitive tagging system. _PlanMySem_ is optimized for those who prefer to work with a Command Line Interface (CLI) and/or are learning to work more efficiently with CLI tools. Additionally, unlike traditional calendar/scheduling applications, _PlanMySem_ utilizes minimal resources on the user’s machine while still allowing the user to view their schedules swiftly and efficiently. +This user guide provides a quick start guide for you to easily setup and install _PlanMySem_, documentation of all the various features _PlanMySem_ offers, frequently asked questions and a summary of the available commands. + == Quick Start . Ensure you have Java version `9` or later installed in your Computer. @@ -58,9 +60,9 @@ This section displays the current implemented features as well as features that *Command Format* * Words in UPPER_CASE are the parameters to be supplied by the user. E.g. in `t/TAG`, `TAG` is a parameter which can be used as the name of the tag. -* Items in square brackets are optional. e.g add act NAME `[c/NAME]`. -* Items with `…` after them can be used multiple times including zero times e.g. `[t/TAG]…` can be used as (i.e. 0 times), `t/lab`, `t/lecture`, `t/tutorial` etc. -* Parameters can be in any order e.g. if the command specifies `st/START_TIME et/END_TIME d/DATE`, then both `et/09:00 st/08:00 d/2-13-2019` and `et/09:00 d/2-13-2019 st/08:00` is also acceptable. +* Items in square brackets are optional. e.g in `add n/NAME [l/LOCATION]`, `LOCATION` is an optional parameter and is not required to successfully run the command. +* Items with `…` after them can be used multiple times including zero times e.g. `[t/TAG]…` can be used 0 times, or as `t/lab`, `t/lecture`, `t/tutorial` etc. +* Parameters can be in any order e.g. if the command specifies `st/START_TIME et/END_TIME d/DATE`, then both `et/09:00 st/08:00 d/2-13-2019` and `et/09:00 d/2-13-2019 st/08:00` are acceptable. *Parameters* @@ -69,22 +71,22 @@ The list of parameters below is useful for your reference as you jump right into [horizontal] *Parameter*:: *Description* -`n/`:: *Name specific to the object at hand.* +`n/`:: *Name of an activity _slot_.* `d/`:: *Date / Day of week.* + Format: + * Dates: `01-01`, `2019-01-02` * Day of Week: `Monday`, `mon`, `1` -`st/`:: *Start Time.* +`st/`:: *Start Time.* + Format: + * 24-Hour in the form of “hh:mm”. e.g. `23:00` * 12-Hour in the form of `hh:mm+AM|PM`. e.g. `12:30 AM` `et/`:: *End Time / duration.* + - Format: + Format: + * 24-Hour in the form of “hh:mm”. e.g. `23:00` * 12-Hour in the form of `hh:mm+AM|PM`. e.g. `12:30 AM` * Duration of the event in minutes. e.g. `60` represents 60 minutes -`r/`:: *recurrence.* + - Format: +`r/`:: *Specify recurrence of an activity _slot_.* + + Format: + * Select normal weeks: `normal` * Select recess week: `recess` * Select reading week: `reading` @@ -93,7 +95,7 @@ The list of parameters below is useful for your reference as you jump right into `l/`:: *Location.* `des/`:: *Description.* `t/`:: *Tag.* -`nn/`:: *New name of the object at hand.* +`nn/`:: *New name of an activity _slot_.* `nd/`:: *New Date.* `nst/`:: *New Start Time.* `net/`:: *New End Time.* @@ -102,7 +104,7 @@ The list of parameters below is useful for your reference as you jump right into ==== === Viewing help : `help` - +Displays all the available commands with the syntax and examples. + Format: `help` === Adding Slots : `add` / `a` @@ -111,7 +113,7 @@ Add _slots_ to the planner. + Format: `add n/NAME d/DATE_OR_DAY_OF_WEEK st/START_TIME et/END_TIME_OR_DURATION + [l/LOCATION] [des/DESCRIPTION] [r/normal] [r/recess] [r/reading] [r/exam] [r/past] [t/TAG]...` -Examples: +Examples: + * `add n/CS2113T Tutorial d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial` + Add a _slot_, named "CS2113T Tutorial" on the coming monday, from 0800hrs to 0900hrs with the tags "CS2113T" and "Tutorial". @@ -123,7 +125,7 @@ Do the same but recurse the slot on "normal", instructional, weeks. [NOTE] ==== -You may add single slots by neglecting the recurrence parameters. +You may add single _slots_ by omitting the recurrence parameter. ==== === Editing Slots: `edit` / `e` @@ -164,7 +166,7 @@ Examples: * `delete t/CS2113T t/Tutorial` + Delete _slots_ that contain tags "CS2113T" and "Tutorial". -* `list delete 2` + +* `delete 2` + Delete the second _slot_ shown via the `list` command. === Listing Slots: `list` / `l` @@ -195,22 +197,29 @@ Format: `find [KEYWORD]...` Example: -* `find CS` +* `find CS` + Find all _slots_ whose name contains `CS` (eg. CS1010, CS2113T, SCS1010) -=== View the Planner : `view` +=== View the Planner : `view` / `v` -View the planner according to day/week/month. + -Format: `view day DATE | view week WEEK | view month MONTH | view all` +View the planner in a month/week/day view. + +1. View the monthly calendar view of the current academic semester. + +Format: `view month [MONTH]` +2. View the weekly calendar view of the current academic week. + +Format: `view week [WEEK]` +3. View the day view of a particular day in the academic semester. + +Format: `view day [DATE]` +4. View all the details in the planner. + +Format: `view all` [NOTE] ==== -. If no date is given, the current date is assumed. -. If the `all` option is specified, the planner will not be displayed, instead all the details in the planner will be displayed. +If MONTH/WEEK/DATE is not specified, the current date is assumed. ==== -Example: +Examples: * `view day` + View planner for the current date. @@ -263,14 +272,15 @@ Format: `exit` === Saving the data -Planner data is saved in the hard disk automatically after any command that changes the data is executed. + There is no need to save manually. +Planner data is saved in the hard disk automatically after any command that changes the data is executed. + +There is no need to save manually. === Encrypting/decrypting data files Planner data is automatically encrypted before saving. You do not need to encrypt the data manually. -Planner data is automatically decrypted before loading. You do not need to decrypt the data manually. +Planner data is automatically decrypted after loading. You do not need to decrypt the data manually. // tag::importICS[] === Importing .ics formated files `[coming in v2.0]` @@ -298,7 +308,8 @@ These are plain text files that include calendar event details like a descriptio == FAQ *Q*: How do I transfer my data to another Computer? + -*A*: In order to transfer your data to another Computer, you should: + +*A*: In order to transfer your data to another Computer, you should: + 1. Install the app on the other computer + 2. Copy _PlanMySem.txt_ from your old _PlanMySem_ folder and paste it into the new _PlanMySem_ folder. + @@ -307,7 +318,7 @@ This will overwrite the empty data file it creates with the file that contains t == Command Summary -* *View help* `help` + +* *View help* : `help` + * *Add Slot* : `add n/NAME d/DATE_OR_DAY_OF_WEEK st/START_TIME et/END_TIME_OR_DURATION [l/LOCATION] [des/DESCRIPTION] [r/normal] [r/recess] [r/reading] [r/exam] [r/past] [t/TAG]…​` + e.g. `add n/CS2113T Tutorial d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial` + * *List Slot(s)* : `list n/NAME` + @@ -321,13 +332,12 @@ e.g. `edit 1 des/Topic: Sequence Diagram` 1. Via tags: `delete t/TAG…​` + eg. `delete t/CS2113T t/Tutorial` 2. Via `list` command: `delete INDEX` + -eg. `list delete 2` +eg. `delete 2` * *Find Slots* : `find [KEYWORD]…​` + e.g. `find CS` * *View planner* : `view day [DATE] | view week [WEEK] | view month [MONTH]` + -e.g.`view day 01/04/2019` -* *View all details* : `view all` + -e.g.`view all` +e.g.`view month` +* *View all details* : `view all` * *View history* : `history` * *Undo previous command* : `undo` * *Redo previously undone command* : `redo` From 936a8804b0510f27a8aaeab3effa41fe1e9e02f6 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Tue, 19 Mar 2019 20:54:22 +0800 Subject: [PATCH 12/22] UserGuide: Update user guide documentation --- docs/UserGuide.adoc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 257d53537..cdf36c186 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -113,7 +113,8 @@ Add _slots_ to the planner. + Format: `add n/NAME d/DATE_OR_DAY_OF_WEEK st/START_TIME et/END_TIME_OR_DURATION + [l/LOCATION] [des/DESCRIPTION] [r/normal] [r/recess] [r/reading] [r/exam] [r/past] [t/TAG]...` -Examples: + +Examples: + * `add n/CS2113T Tutorial d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial` + Add a _slot_, named "CS2113T Tutorial" on the coming monday, from 0800hrs to 0900hrs with the tags "CS2113T" and "Tutorial". From a2c34facd2eeed5a786e7c50da5baf74b6045068 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Thu, 21 Mar 2019 16:31:17 +0800 Subject: [PATCH 13/22] UserGuide: Update user guide documentation --- docs/UserGuide.adoc | 99 ++++++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 42 deletions(-) diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 4bce16558..cb6273a33 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -18,7 +18,7 @@ By: `Team T08-3` Since: `Jan 2019` Licence: `MIT` == Introduction -Welcome to _PlanMySem_! Choose a topic from the table of contents to learn about available features with examples, find answers or view a summary of the commands. +Welcome to _PlanMySem_! _PlanMySem_ is a text-based (Command Line Interface) scheduling/calendar application that targets NUS students and staff who prefer to use a desktop application for managing their schedule/calendar. _PlanMySem_ automatically creates a planner that is synchronised according to the NUS academic calendar for the current semester and enables easy creation, editing and deleting of items. @@ -26,13 +26,28 @@ Special weeks such as recess week and reading week are taken into account within Items can then be efficiently managed via the intuitive tagging system. _PlanMySem_ is optimized for those who prefer to work with a Command Line Interface (CLI) and/or are learning to work more efficiently with CLI tools. Additionally, unlike traditional calendar/scheduling applications, _PlanMySem_ utilizes minimal resources on the user’s machine while still allowing the user to view their schedules swiftly and efficiently. +{zwsp} -This user guide provides a quick start guide for you to easily setup and install _PlanMySem_, documentation of all the various features _PlanMySem_ offers, frequently asked questions and a summary of the available commands. +{zwsp} + +== About this User Guide +This user guide provides a quick start guide for you to easily setup and install _PlanMySem_, documentation of all the various features _PlanMySem_ offers, frequently asked questions and a summary of the available commands. To navigate between the different sections, you could use the table of contents above. + +For ease of communication, this document will refer to lessons/activities/events/appointments that you might add into the Planner as _slots_. + +Throughout this user guide, there will be various icons used as described below. + +TIP: This is a tip. These tips will enhance your experience while using _PlanMySem_! + +NOTE: This is a note. These are things for you to take note of when using _PlanMySem_. + +WARNING: This is a warning. Ensure that you heed these warnings for a smooth experience while using _PlanMySem_. {zwsp} {zwsp} == Quick Start +This section guides you through the installation of _PlanMySem_ and provides a few example commands you may try. . Ensure you have Java version `9` or later installed in your Computer. . Download the latest `planmysem.jar` link:{repoURL}/releases[here]. @@ -49,9 +64,9 @@ e.g. typing *`help`* and pressing kbd:[Enter] will open the help window. * **`add`**`n/CS2113T d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial` : + -Add a slot, named "CS2113T" on the coming monday, from 0800hrs to 0900hrs with the tags "CS2113T" and "Tutorial". -* *`list`*`n/CS2113T` : list all slots named "CS2113T" -* **`delete`**`3` : delete the 3rd slot shown in the current list +Add a _slot_, named "CS2113T" on the coming monday, from 0800hrs to 0900hrs with the tags "CS2113T" and "Tutorial". +* *`list`*`n/CS2113T` : list all _slots_ named "CS2113T" +* **`delete`**`3` : delete the 3rd _slot_ shown in the current list * *`exit`* : exit the app . Refer to <> for details of each command. @@ -62,18 +77,14 @@ Add a slot, named "CS2113T" on the coming monday, from 0800hrs to 0900hrs with t [[Features]] == Features -This section displays the current implemented features as well as features that will be implemented in the future. - -[NOTE] -*For ease of communication, this document will refer to lessons/activities/events/appointments that you might add into the Planner as _slots_.* +This section displays the available features of _PlanMySem_ together with examples for you to refer to. ==== - *Tagging System* -Unlike other commercial calendar/scheduling/planner software, PlanMySem makes use of a tagging system to manage slots. +Unlike other commercial calendar/scheduling/planner software, PlanMySem makes use of a tagging system to manage _slots_. -Using tags to tag slots will make tasks easier for you in the future. Performing tasks such as viewing, deleting and editing slots will be more efficient. +Using tags to tag _slots_ will make tasks easier for you in the future. Performing tasks such as viewing, deleting and editing _slots_ will be more efficient. Recommended uses for tags: @@ -84,9 +95,9 @@ Recommended uses for tags: *Recursion System* -Recursion facilitates quick addition of multiple slots, similar to Microsoft Outlook's series of appointments. +Recursion facilitates quick addition of multiple _slots_, similar to Microsoft Outlook's series of appointments. -In NUS, academic semesters are split into weeks of several types. Recursion allows you to add slots to these types of weeks with ease through the use of the `r/`(recursion) parameter. +In NUS, academic semesters are split into weeks of several types. Recursion allows you to add _slots_ to these types of weeks with ease through the use of the `r/`(recursion) parameter. *Command Format* @@ -165,10 +176,10 @@ Add a _slot_, named "CS2113T Tutorial" on the coming monday, from 0800hrs to 090 image::Add_Command_Output_1.png[width="790"] * `add n/CS2113T Tutorial d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/recess r/reading` + -Do the same but additionally, recurse the slot on recess and reading week. +Do the same but additionally, recurse the _slot_ on recess and reading week. * `add n/CS2113T Tutorial d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial r/normal` + -Do the same but recurse the slot on "normal", instructional, weeks. +Do the same but recurse the _slot_ on "normal", instructional, weeks. [TIP] ==== @@ -189,14 +200,14 @@ Format: `edit INDEX [nn/NEW_NAME] [nd/NEW_DATE] [nst/NEW_START_TIME] [net/NEW_EN [WARNING] ==== -You are not able to edit a slot's date when editing via _tags_. +You are not able to edit a _slot_'s date when editing via _tags_. To edit a _slot_'s date, you may use the `list` or `find` command and edit specific _slot(s)_ via index. ==== Examples: * `edit t/CS2113T t/Tutorial nl/COM2 04-01` + -Edit slots that contain tags "CS2113T" and "Tutorial", set these _slot's_ location to "COM2 04-01". +Edit _slots_ that contain tags "CS2113T" and "Tutorial", set these _slot's_ location to "COM2 04-01". [#img-edit] .[.underline]#Output after entering `edit t/CS2113T t/Tutorial nl/COM2 04-01`# @@ -217,7 +228,7 @@ Format: `delete INDEX` [TIP] ==== -You may delete a specific slot by using the `list` or `find` command and select the specific _slot_ via index. +You may delete a specific _slot_ by using the `list` or `find` command and select the specific _slot_ via index. ==== Examples: @@ -237,7 +248,7 @@ Delete the second _slot_ shown via the `list` command. === Listing Slots: `list` / `l` -Lists all slots whose name directly matches the specified keyword (not case-sensitive). + +Lists all _slots_ whose name directly matches the specified keyword (not case-sensitive). + Format: `list n/NAME` Examples: @@ -436,30 +447,34 @@ This will overwrite the empty data file it creates with the file that contains t == Command Summary -* *View help* : `help` + -* *Add Slot* : `add n/NAME d/DATE_OR_DAY_OF_WEEK st/START_TIME et/END_TIME_OR_DURATION [l/LOCATION] [des/DESCRIPTION] [r/normal] [r/recess] [r/reading] [r/exam] [r/past] [t/TAG]…​` + -e.g. `add n/CS2113T Tutorial d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial` + -* *List Slot(s)* : `list n/NAME` + -eg. `list n/CS2113T` -* *Edit Slot* : `edit` + -1. Via tags: `edit t/TAG... [nn/NEW_NAME] [nst/NEW_START_TIME] [net/NEW_END_TIME|DURATION] [nl/NEW_LOCATION] [nd/NEW_DESCRIPTION] [nt/NEW_TAG]...` + -e.g. `edit t/CS2113T t/Tutorial nl/COM2 04-01` -2. Via `list` command: `edit INDEX [nn/NEW_NAME] [nd/NEW_DATE] [nst/NEW_START_TIME] [net/NEW_END_TIME|DURATION] [nl/NEW_LOCATION] [nd/NEW_DESCRIPTION] [nt/NEW_TAG]...` + +[width=100%, cols="1,20"] +|=== +| *Command* | *Syntax* +| *View help* : `help` | `help` +| *Add Slot* : `add` | `add n/NAME d/DATE_OR_DAY_OF_WEEK st/START_TIME et/END_TIME_OR_DURATION [l/LOCATION] [des/DESCRIPTION] [r/normal] [r/recess] [r/reading] [r/exam] [r/past] [t/TAG]…​` + +e.g. `add n/CS2113T Tutorial d/mon st/08:00 et/09:00 des/Topic: Sequence Diagram t/CS2113T t/Tutorial` +| *List Slot(s)* : `list` | `list n/NAME` + +e.g. `list n/CS2113T` +| *Edit Slot* : `edit` | +1. Via tags: `edit t/TAG... [nn/NEW_NAME] [nst/NEW_START_TIME] [net/NEW_END_TIME\|DURATION] [nl/NEW_LOCATION] [nd/NEW_DESCRIPTION] [nt/NEW_TAG]...` + +e.g. `edit t/CS2113T t/Tutorial nl/COM2 04-01` + +2. Via `list` command: `edit INDEX [nn/NEW_NAME] [nd/NEW_DATE] [nst/NEW_START_TIME] [net/NEW_END_TIME\|DURATION] [nl/NEW_LOCATION] [nd/NEW_DESCRIPTION] [nt/NEW_TAG]...` + e.g. `edit 1 des/Topic: Sequence Diagram` -* *Delete Slot* : `delete` + +| *Delete Slot* : `delete` | 1. Via tags: `delete t/TAG…​` + -eg. `delete t/CS2113T t/Tutorial` +e.g. `delete t/CS2113T t/Tutorial` + 2. Via `list` command: `delete INDEX` + -eg. `delete 2` -* *Find Slots* : `find [KEYWORD]…​` + +e.g. `delete 2` +| *Find Slots* : `find` | `find [KEYWORD]…​` + e.g. `find CS` -* *View planner* : `view day [DATE] | view week [WEEK] | view month [MONTH]` + +| *View planner* : `view` | `view day [DATE] \| view week [WEEK] \| view month [MONTH]` + e.g.`view month` -* *View all details* : `view all` -* *View history* : `history` -* *Undo previous command* : `undo` -* *Redo previously undone command* : `redo` -* *Clear all data* : `clear` -* *Exit the program* : `exit` -* *Export .ics file* : `export` -* *Import .ics file* : `import FILENAME` +| *View all details* : `view all` | `view all` +| *View history* : `history` | `history` +| *Undo previous command* : `undo` | `undo` +| *Redo previously undone command* : `redo` | `redo` +| *Clear all data* : `clear` | `clear` +| *Exit the program* : `exit` | `exit` +| *Export .ics file* : `export` | `export` +| *Import .ics file* : `import` | `import FILENAME` +|=== From e14f4765023b670ddb8631506c5c931c1583a694 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Thu, 21 Mar 2019 16:44:35 +0800 Subject: [PATCH 14/22] UserGuide: Update user guide documentation --- docs/UserGuide.adoc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index cb6273a33..e6e004f9d 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -11,6 +11,9 @@ ifdef::env-github[] :tip-caption: :bulb: :note-caption: :information_source: +:important-caption: :heavy_exclamation_mark: +:caution-caption: :fire: +:warning-caption: :warning: endif::[] :repoURL: https://github.com/CS2113-AY1819S2-T08-3/main From d7cb58039792ccca22fb8d638e80ff5106a749d5 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Thu, 21 Mar 2019 22:16:49 +0800 Subject: [PATCH 15/22] UserGuide: Update user guide documentation --- docs/UserGuide.adoc | 46 +++++---------------------------------------- 1 file changed, 5 insertions(+), 41 deletions(-) diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index e2da94b30..b81f6da4f 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -20,7 +20,6 @@ endif::[] By: `Team T08-3` Since: `Jan 2019` Licence: `MIT` == Introduction - Welcome to _PlanMySem_! _PlanMySem_ is a text-based (Command Line Interface) scheduling/calendar application that targets NUS students and staff who prefer to use a desktop application for managing their schedule/calendar. @@ -87,7 +86,6 @@ Add a _slot_, named "CS2113T" on the coming monday, from 0800hrs to 0900hrs with [[Features]] == Features - This section displays the available features of _PlanMySem_ together with examples for you to refer to. *Tagging System* @@ -135,7 +133,7 @@ The table of Identifiers and Parameters and their descriptions (Table 1) below i |`KEYWORD` |Text that are part of the name of a _slot_ |Text |`n/CS` |`l/` |`LOCATION` |Location of a _slot_ |Text |`l/COM2 04-22` |`des/` |`DESCRIPTION` |Description of a _slot_ |Text |`des/Topic: Abstraction` -|`t/` |`TAG` |Tag of a _slot_ |Text |`nt/Lab` +|`t/` |`TAG` |Tag of a _slot_ |Text |`t/Lab` .4+|`d/` .2+|`DATE` .2+|Date @@ -151,8 +149,8 @@ The table of Identifiers and Parameters and their descriptions (Table 1) below i .3+|`et/` .2+|`END_TIME` .2+|End Time - |Time in 24-Hour format, `hh:mm` |`e/23:00` - |Time 12-Hour format, `hh:mm+AM\|PM` |`e/11:00 PM` + |Time in 24-Hour format, `hh:mm` |`et/23:00` + |Time 12-Hour format, `hh:mm+AM\|PM` |`et/11:00 PM` |`DURATION` |Duration from Start Time |Number of minutes |`et/60` .5+|`r/` .5+|`RECURRENCE` @@ -164,22 +162,17 @@ The table of Identifiers and Parameters and their descriptions (Table 1) below i |======================================================================= [TIP] -==== You may order identifiers and parameters in any fashion and you will still be able to achieve what you want! So, do not bother thinking about where to place parameters as ordering does not matter, instead become more efficient and save your time! -==== [IMPORTANT] -==== Identifiers may be appended with a `n` to dictate "new". + E.g. `nt/NEW_TAG` signifies new tags in which you want to replace existing tags with. -==== [CAUTION] -==== -While this table 1 shows you all the identifiers and parameters that _PlanMySem_ uses, there are some commands that do not make use of identifiers nor parameters. +While table 1 shows you all the identifiers and parameters that _PlanMySem_ uses, there are some commands that do not make use of identifiers nor parameters. The view command is one such exception that make use of keywords that must be typed in a specific order. -==== + // //[horizontal] //==== @@ -234,7 +227,6 @@ image::Help_Command_Output.png[width="790"] [[add]] === Adding Slots : `add` / `a` - Add _slot(s)_ to the planner. + Format: `add n/NAME d/DATE_OR_DAY_OF_WEEK st/START_TIME et/END_TIME_OR_DURATION + [l/LOCATION] [des/DESCRIPTION] [r/normal] [r/recess] [r/reading] [r/exam] [r/past] [t/TAG]...` @@ -255,16 +247,13 @@ Do the same but additionally, recurse the _slot_ on recess and reading week. Do the same but recurse the _slot_ on "normal", instructional, weeks. [TIP] -==== You may add single _slots_ by omitting the `r/` identifiers and its parameters. -==== {zwsp} {zwsp} [[edit]] === Editing Slots: `edit` / `e` - Edit _slot(s)_. 1. Edit _slot(s)_ which contains certain _tag_(s). + @@ -273,10 +262,8 @@ Format: `edit t/TAG... [nn/NEW_NAME] [nst/NEW_START_TIME] [net/NEW_END_TIME|DURA Format: `edit INDEX [nn/NEW_NAME] [nd/NEW_DATE] [nst/NEW_START_TIME] [net/NEW_END_TIME|DURATION] [nl/NEW_LOCATION] [nd/NEW_DESCRIPTION] [nt/NEW_TAG]...` [NOTE] -==== You will not be able to edit a _slot_'s date when editing via _tags_. + To edit a _slot_'s date, you may use the `list` or `find` command and edit specific _slot(s)_ via index. -==== Examples: @@ -295,7 +282,6 @@ Edit the first item from the previous result of the `list` or `find` command. [[delete]] === Delete Slots: `delete` / `del` / `d` - 1. Delete _slot(s)_ which contains certain _tag_(s). + Format: `delete t/TAG...` 2. Delete _slot_ via the `list` command. + @@ -321,7 +307,6 @@ Delete the second _slot_ shown via the `list` command. [[list]] === Listing Slots: `list` / `l` - Lists all _slots_ whose name directly matches the specified keyword (not case-sensitive). + Format: `list n/NAME` @@ -339,7 +324,6 @@ image::List_Command_Output_1.png[width="790"] [[find]] === Locating Slots: `find` / `f` - Find all _slots_ whose part of their name contains the specified keyword and displays them as a list. + Format: `find n/KEYWORD` @@ -357,7 +341,6 @@ image::Find_Command_Output_1.png[width="790"] [[view]] === View the Planner : `view` / `v` - View the planner in a month/week/day view. 1. View the monthly calendar view of the current academic semester. + @@ -370,10 +353,8 @@ Format: `view day [DATE]` Format: `view all` [TIP] -==== You may omit `[MONTH]`/`[WEEK]`/`[DATE]` to view the format chosen in respect to the current day! + E.g. `view month` will allow you to view the current month and `view day` will allow you to view the current day! -==== Examples: @@ -400,7 +381,6 @@ View all the details in the planner. [[history]] === Listing previous input commands : `history` `[coming in v2.0]` - Lists all the commands that you have entered in reverse chronological order. + Format: `history` {zwsp} @@ -409,20 +389,17 @@ Format: `history` [[undo]] === Undoing previous command : `undo` `[coming in v2.0]` - Restores the planner to the state before the previous command was executed. + Format: `undo` [TIP] The `clear` command cannot be undone. - {zwsp} {zwsp} [[redo]] === Redoing the previously undone command : `redo` `[coming in v2.0]` - Reverses the most recent `undo` command. + Format: `redo` {zwsp} @@ -431,7 +408,6 @@ Format: `redo` [[encrypt]] === Encrypting/decrypting data files - Planner data is automatically encrypted before saving and decrypted before loading. You do not need to encrypt or decrypt he data manually. {zwsp} @@ -439,7 +415,6 @@ Planner data is automatically encrypted before saving and decrypted before loadi [[import]] === Importing .ics formatted files `[coming in v2.0]` - You can import an .ics file into the planner. Format: `import FILENAME` {zwsp} @@ -448,7 +423,6 @@ Format: `import FILENAME` [[export]] === Exporting .ics formatted files: `export` - You can export the planner as a .ics file. [#img-export] @@ -470,33 +444,25 @@ A file with the ICS file extension is an iCalendar file. These are plain text files that include calendar event details like a description, beginning and ending times, location, etc. {zwsp} -{zwsp} -{zwsp} - {zwsp} [[clear]] === Clear all data : `clear` - Clear all data stored on the planner. + Format: `clear` [#img-find] .[.underline]#Output after entering `clear`# image::Clear_Command_Output_1.png[width="790"] -{zwsp} [NOTE] -==== The `clear` command cannot be undone! Your data will be permanently removed once `clear` is executed. -==== {zwsp} {zwsp} [[exit]] === Exiting the program : `exit` - Exits the program. + Format: `exit` {zwsp} @@ -505,7 +471,6 @@ Format: `exit` [[save]] === Saving the data - Planner data is saved in the hard disk automatically after any command that changes the data is executed. + There is no need to save manually. {zwsp} @@ -513,7 +478,6 @@ There is no need to save manually. {zwsp} == FAQ - *Q*: How do I transfer my data to another Computer? + *A*: In order to transfer your data to another Computer, you should: From 17f1e8d7a336441dc17cae948f3309c869cf5036 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Sun, 24 Mar 2019 15:49:12 +0800 Subject: [PATCH 16/22] Moved Semester generation code --- docs/DeveloperGuide.adoc | 27 ++- src/planmysem/data/Planner.java | 242 +-------------------- src/planmysem/data/semester/Semester.java | 250 +++++++++++++++++++++- test/java/planmysem/data/PlannerTest.java | 18 +- 4 files changed, 277 insertions(+), 260 deletions(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 0f87ed8fe..e3f021a1b 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -258,9 +258,32 @@ Classes used by multiple components are in the `planmysem.commons` package. This section describes some noteworthy details on how certain features are implemented. -=== Initializing of the Planner and it's Semesters +=== Initialization of the Planner and it's Semester -==== Future Implementation +The Planner and it's Semester has to be initialized for _PlanMySem_ to work as all other features of _PlanMySem_ would +interact with this Semester object. + +==== Current Implementation + +Upon launching _PlanMySem_, the initialization of the Planner and it's Semester would be implemented via two steps: + +1. Automatically generate the academic calendar from the current date. +2. Setup current Semester from the academic calendar. + +//The academic calendar is dynamically generated by invoking the function +//based on the current date retrieved from the system clock. +//TBC +==== Design Considerations + +===== Aspect: Generation of academic calendar + +* *Alternative 1 (current choice):* Generate academic calendar by performing calculations from the current date. +** Pros: Generation of academic calendar is dynamic and will work for future dates. +** Cons: Computationally expensive as many operations have to be performed. + +* *Alternative 2:* Retrieve academic calendar from a pre-generated file. +** Pros: Generation of academic calendar is efficient and not prone to calculation errors. +** Cons: Requires the pre-generated file which may be accidentally edited or deleted by the user. === Reinventing the Parser / Command Format and Structure diff --git a/src/planmysem/data/Planner.java b/src/planmysem/data/Planner.java index 843b6ca4b..9ae024141 100644 --- a/src/planmysem/data/Planner.java +++ b/src/planmysem/data/Planner.java @@ -31,7 +31,7 @@ public class Planner { * Creates an empty planner. */ public Planner() { - semester = generateSemester(LocalDate.now()); + semester = Semester.generateSemester(LocalDate.now()); } /** @@ -43,246 +43,6 @@ public Planner(Semester semester) { this.semester = new Semester(semester); } - /** - * Generates current semester based on current date. - * As long as the current date falls within a semester, the generated semester is always the same. - * - * @param currentDate the current date when the program is run - * @return the current semester object - */ - public static Semester generateSemester(LocalDate currentDate) { - String acadSem; - String acadYear; - String[] semesterDetails; - int noOfWeeks; - LocalDate startDate; - LocalDate endDate; - List datesList; - HashMap acadCalMap; - HashMap days = new HashMap<>(); - Set recessDays = new HashSet<>(); - Set readingDays = new HashSet<>(); - Set normalDays = new HashSet<>(); - Set examDays = new HashSet<>(); - - acadCalMap = generateAcadCalMap(currentDate); - semesterDetails = getSemesterDetails(currentDate, acadCalMap); - acadSem = semesterDetails[1]; - acadYear = semesterDetails[2]; - noOfWeeks = Integer.parseInt(semesterDetails[3]); - startDate = LocalDate.parse(semesterDetails[4]); - endDate = LocalDate.parse(semesterDetails[5]); - - // Initialise HashMap and Sets of all days in current semester - datesList = startDate.datesUntil(endDate).collect(Collectors.toList()); - for (LocalDate date: datesList) { - int weekOfYear = date.get(WeekFields.ISO.weekOfWeekBasedYear()); - String weekType = acadCalMap.get(weekOfYear).split("_")[0]; - days.put(date, new Day(date.getDayOfWeek(), weekType)); - switch (weekType) { - case "Recess Week": - recessDays.add(date); - break; - case "Reading Week": - readingDays.add(date); - break; - case "Examination Week": - examDays.add(date); - break; - default: - normalDays.add(date); - break; - } - } - - return new Semester(acadSem, acadYear, days, startDate, endDate, noOfWeeks, - recessDays, readingDays, normalDays, examDays); - } - - /** - * Generates academic calendar for a given date. - * - * @param date used to determine academic year - * @return details of academic calendar - */ - private static HashMap generateAcadCalMap(LocalDate date) { - HashMap acadCalMap = new HashMap<>(); - LocalDate semOneStartDate = date; - LocalDate semTwoEndDate = date; - int currentMonth = date.getMonthValue(); - int currentYear = date.getYear(); - int semOneStartWeek; - int semTwoStartWeek; - int semTwoEndWeek; - int acadWeekNo; - int noOfWeeksInYear; - int vacationWeekNo; - - if (currentMonth < 8) { - // Academic Year beginning from August of previous year - semOneStartDate = semOneStartDate.withYear(currentYear - 1).withMonth(8) - .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); - semOneStartWeek = semOneStartDate.get(WeekFields.ISO.weekOfWeekBasedYear()); - semTwoEndDate = semTwoEndDate.withYear(currentYear).withMonth(8) - .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)).minusDays(1); - semTwoEndWeek = semTwoEndDate.get(WeekFields.ISO.weekOfWeekBasedYear()); - } else { - // Academic Year beginning from August of current year - semOneStartDate = semOneStartDate.withYear(currentYear).withMonth(8) - .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); - semOneStartWeek = semOneStartDate.get(WeekFields.ISO.weekOfWeekBasedYear()); - semTwoEndDate = semTwoEndDate.withYear(currentYear + 1).withMonth(8) - .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)).minusDays(1); - semTwoEndWeek = semTwoEndDate.get(WeekFields.ISO.weekOfWeekBasedYear()); - } - - // Sem 1 - Orientation Week - acadCalMap.put(semOneStartWeek, "Orientation Week_Sem 1"); - - // Sem 1 - Week 1 to 6 - acadWeekNo = 1; - for (int i = semOneStartWeek + 1; i < semOneStartWeek + 7; i++) { - acadCalMap.put(i, "Week " + acadWeekNo + "_Sem 1"); - acadWeekNo++; - } - - // Sem 1 - Recess Week - acadCalMap.put(semOneStartWeek + 7, "Recess Week_Sem 1"); - - // Sem 1 - Week 7 to 13 - acadWeekNo = 7; - for (int i = semOneStartWeek + 8; i < semOneStartWeek + 15; i++) { - acadCalMap.put(i, "Week " + acadWeekNo + "_Sem 1"); - acadWeekNo++; - } - - // Sem 1 - Reading & Examination Weeks - acadCalMap.put(semOneStartWeek + 15, "Reading Week_Sem 1"); - acadCalMap.put(semOneStartWeek + 16, "Examination Week_Sem 1"); - acadCalMap.put(semOneStartWeek + 17, "Examination Week_Sem 1"); - - // Sem 1 - Vacation - noOfWeeksInYear = (int) semOneStartDate.range(WeekFields.ISO.weekOfWeekBasedYear()).getMaximum(); - vacationWeekNo = semOneStartWeek + 18; - semTwoStartWeek = 1; - for (int i = 0; i < 5; i++) { - if ((vacationWeekNo + i) <= noOfWeeksInYear) { - acadCalMap.put(vacationWeekNo + i, "Vacation_Sem 1"); - } else { - acadCalMap.put(semTwoStartWeek++, "Vacation_Sem 1"); - } - } - - // Sem 2 - Week 1 to 6 - acadWeekNo = 1; - for (int i = semTwoStartWeek; i < semTwoStartWeek + 6; i++) { - acadCalMap.put(i, "Week " + acadWeekNo + "_Sem 2"); - acadWeekNo++; - } - - // Sem 2 - Recess Week - acadCalMap.put(semTwoStartWeek + 6, "Recess Week_Sem 2"); - - // Sem 2 - Week 7 to 13 - acadWeekNo = 7; - for (int i = semTwoStartWeek + 7; i < semTwoStartWeek + 14; i++) { - acadCalMap.put(i, "Week " + acadWeekNo + "_Sem 2"); - acadWeekNo++; - } - - // Sem 2 - Reading & Examination Weeks - acadCalMap.put(semTwoStartWeek + 14, "Reading Week_Sem 2"); - acadCalMap.put(semTwoStartWeek + 15, "Examination Week_Sem 2"); - acadCalMap.put(semTwoStartWeek + 16, "Examination Week_Sem 2"); - - // Sem 2 - Vacation - vacationWeekNo = semTwoStartWeek + 17; - while (vacationWeekNo <= semTwoEndWeek) { - acadCalMap.put(vacationWeekNo++, "Vacation_Sem 2"); - } - - return acadCalMap; - } - - /** - * Initialises current semester's details. - * - * @param date the current date when the program is run - * @param acadCalMap used to determine current academic week - * @return an array of Strings of the current semester's details - */ - private static String[] getSemesterDetails(LocalDate date, HashMap acadCalMap) { - String acadWeek; - String acadSem; - String acadYear = null; - String noOfWeeks = null; - String[] acadWeekDetails; - LocalDate startDate = date; - LocalDate endDate = date; - int currentYear = date.getYear(); - int currentWeekOfYear = date.get(WeekFields.ISO.weekOfWeekBasedYear()); - - // Initialise week numbers for certain weeks. - int firstWeekSemOne = 0; - int firstWeekSemOneHol = 0; - int lastWeekSemOneHol = 0; - int firstWeekSemTwo = 0; - int firstWeekSemTwoHol = 0; - for (Map.Entry entry: acadCalMap.entrySet()) { - if ("Orientation Week_Sem 1".equals(entry.getValue())) { - firstWeekSemOne = entry.getKey(); - } else if ("Examination Week_Sem 1".equals(entry.getValue())) { - firstWeekSemOneHol = entry.getKey() + 1; - } else if ("Week 1_Sem 2".equals(entry.getValue())) { - lastWeekSemOneHol = entry.getKey() - 1; - firstWeekSemTwo = entry.getKey(); - } else if ("Examination Week_Sem 2".equals(entry.getValue())) { - firstWeekSemTwoHol = entry.getKey() + 1; - } - } - - // Set semester details. - acadWeekDetails = acadCalMap.get(currentWeekOfYear).split("_"); - acadWeek = acadWeekDetails[0]; - acadSem = acadWeekDetails[1]; - if ("Vacation".equals(acadWeek) && "Sem 1".equals(acadSem)) { - noOfWeeks = "5"; - if (currentWeekOfYear < 4) { - acadYear = "AY" + (currentYear - 1) + "/" + currentYear; - startDate = startDate.withYear(currentYear - 1); - } else { - acadYear = "AY" + currentYear + "/" + (currentYear + 1); - endDate = endDate.withYear(currentYear + 1); - } - startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOneHol); - startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); - endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemOneHol); - endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); - } else if ("Vacation".equals(acadWeek) && "Sem 2".equals(acadSem)) { - noOfWeeks = "12"; - acadYear = "AY" + (currentYear - 1) + "/" + currentYear; - startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwoHol); - startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); - endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwoHol + 11); - endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); - } else if ("Sem 1".equals(acadSem)) { - noOfWeeks = "18"; - acadYear = "AY" + currentYear + "/" + (currentYear + 1); - startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOne); - startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); - endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOne + 17); - endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); - } else if ("Sem 2".equals(acadSem)) { - noOfWeeks = "17"; - acadYear = "AY" + (currentYear - 1) + "/" + currentYear; - startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwo); - startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); - endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwo + 16); - endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); - } - return new String[] {acadWeek, acadSem, acadYear, noOfWeeks, startDate.toString(), endDate.toString()}; - } - /** * Adds a day to the Planner. * diff --git a/src/planmysem/data/semester/Semester.java b/src/planmysem/data/semester/Semester.java index 3c18db98e..f9502177a 100644 --- a/src/planmysem/data/semester/Semester.java +++ b/src/planmysem/data/semester/Semester.java @@ -1,14 +1,19 @@ package planmysem.data.semester; +import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; +import java.time.temporal.TemporalAdjusters; +import java.time.temporal.WeekFields; import java.util.HashMap; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.Objects; import java.util.Set; import java.util.TreeMap; +import java.util.stream.Collectors; import planmysem.data.exception.DuplicateDataException; import planmysem.data.exception.IllegalValueException; @@ -82,6 +87,246 @@ public Semester(Semester source) { this.examDays.addAll(source.examDays); } + /** + * Generates current semester based on current date. + * As long as the current date falls within a semester, the generated semester is always the same. + * + * @param currentDate the current date when the program is run + * @return the current semester object + */ + public static Semester generateSemester(LocalDate currentDate) { + String acadSem; + String acadYear; + String[] semesterDetails; + int noOfWeeks; + LocalDate startDate; + LocalDate endDate; + List datesList; + HashMap acadCalMap; + HashMap days = new HashMap<>(); + Set recessDays = new HashSet<>(); + Set readingDays = new HashSet<>(); + Set normalDays = new HashSet<>(); + Set examDays = new HashSet<>(); + + acadCalMap = generateAcadCalMap(currentDate); + semesterDetails = getSemesterDetails(currentDate, acadCalMap); + acadSem = semesterDetails[1]; + acadYear = semesterDetails[2]; + noOfWeeks = Integer.parseInt(semesterDetails[3]); + startDate = LocalDate.parse(semesterDetails[4]); + endDate = LocalDate.parse(semesterDetails[5]); + + // Initialise HashMap and Sets of all days in current semester + datesList = startDate.datesUntil(endDate).collect(Collectors.toList()); + for (LocalDate date: datesList) { + int weekOfYear = date.get(WeekFields.ISO.weekOfWeekBasedYear()); + String weekType = acadCalMap.get(weekOfYear).split("_")[0]; + days.put(date, new Day(date.getDayOfWeek(), weekType)); + switch (weekType) { + case "Recess Week": + recessDays.add(date); + break; + case "Reading Week": + readingDays.add(date); + break; + case "Examination Week": + examDays.add(date); + break; + default: + normalDays.add(date); + break; + } + } + + return new Semester(acadSem, acadYear, days, startDate, endDate, noOfWeeks, + recessDays, readingDays, normalDays, examDays); + } + + /** + * Generates academic calendar for a given date. + * + * @param date used to determine academic year + * @return details of academic calendar + */ + private static HashMap generateAcadCalMap(LocalDate date) { + HashMap acadCalMap = new HashMap<>(); + LocalDate semOneStartDate = date; + LocalDate semTwoEndDate = date; + int currentMonth = date.getMonthValue(); + int currentYear = date.getYear(); + int semOneStartWeek; + int semTwoStartWeek; + int semTwoEndWeek; + int acadWeekNo; + int noOfWeeksInYear; + int vacationWeekNo; + + if (currentMonth < 8) { + // Academic Year beginning from August of previous year + semOneStartDate = semOneStartDate.withYear(currentYear - 1).withMonth(8) + .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); + semOneStartWeek = semOneStartDate.get(WeekFields.ISO.weekOfWeekBasedYear()); + semTwoEndDate = semTwoEndDate.withYear(currentYear).withMonth(8) + .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)).minusDays(1); + semTwoEndWeek = semTwoEndDate.get(WeekFields.ISO.weekOfWeekBasedYear()); + } else { + // Academic Year beginning from August of current year + semOneStartDate = semOneStartDate.withYear(currentYear).withMonth(8) + .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); + semOneStartWeek = semOneStartDate.get(WeekFields.ISO.weekOfWeekBasedYear()); + semTwoEndDate = semTwoEndDate.withYear(currentYear + 1).withMonth(8) + .with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)).minusDays(1); + semTwoEndWeek = semTwoEndDate.get(WeekFields.ISO.weekOfWeekBasedYear()); + } + + // Sem 1 - Orientation Week + acadCalMap.put(semOneStartWeek, "Orientation Week_Sem 1"); + + // Sem 1 - Week 1 to 6 + acadWeekNo = 1; + for (int i = semOneStartWeek + 1; i < semOneStartWeek + 7; i++) { + acadCalMap.put(i, "Week " + acadWeekNo + "_Sem 1"); + acadWeekNo++; + } + + // Sem 1 - Recess Week + acadCalMap.put(semOneStartWeek + 7, "Recess Week_Sem 1"); + + // Sem 1 - Week 7 to 13 + acadWeekNo = 7; + for (int i = semOneStartWeek + 8; i < semOneStartWeek + 15; i++) { + acadCalMap.put(i, "Week " + acadWeekNo + "_Sem 1"); + acadWeekNo++; + } + + // Sem 1 - Reading & Examination Weeks + acadCalMap.put(semOneStartWeek + 15, "Reading Week_Sem 1"); + acadCalMap.put(semOneStartWeek + 16, "Examination Week_Sem 1"); + acadCalMap.put(semOneStartWeek + 17, "Examination Week_Sem 1"); + + // Sem 1 - Vacation + noOfWeeksInYear = (int) semOneStartDate.range(WeekFields.ISO.weekOfWeekBasedYear()).getMaximum(); + vacationWeekNo = semOneStartWeek + 18; + semTwoStartWeek = 1; + for (int i = 0; i < 5; i++) { + if ((vacationWeekNo + i) <= noOfWeeksInYear) { + acadCalMap.put(vacationWeekNo + i, "Vacation_Sem 1"); + } else { + acadCalMap.put(semTwoStartWeek++, "Vacation_Sem 1"); + } + } + + // Sem 2 - Week 1 to 6 + acadWeekNo = 1; + for (int i = semTwoStartWeek; i < semTwoStartWeek + 6; i++) { + acadCalMap.put(i, "Week " + acadWeekNo + "_Sem 2"); + acadWeekNo++; + } + + // Sem 2 - Recess Week + acadCalMap.put(semTwoStartWeek + 6, "Recess Week_Sem 2"); + + // Sem 2 - Week 7 to 13 + acadWeekNo = 7; + for (int i = semTwoStartWeek + 7; i < semTwoStartWeek + 14; i++) { + acadCalMap.put(i, "Week " + acadWeekNo + "_Sem 2"); + acadWeekNo++; + } + + // Sem 2 - Reading & Examination Weeks + acadCalMap.put(semTwoStartWeek + 14, "Reading Week_Sem 2"); + acadCalMap.put(semTwoStartWeek + 15, "Examination Week_Sem 2"); + acadCalMap.put(semTwoStartWeek + 16, "Examination Week_Sem 2"); + + // Sem 2 - Vacation + vacationWeekNo = semTwoStartWeek + 17; + while (vacationWeekNo <= semTwoEndWeek) { + acadCalMap.put(vacationWeekNo++, "Vacation_Sem 2"); + } + + return acadCalMap; + } + + /** + * Initialises current semester's details. + * + * @param date the current date when the program is run + * @param acadCalMap used to determine current academic week + * @return an array of Strings of the current semester's details + */ + private static String[] getSemesterDetails(LocalDate date, HashMap acadCalMap) { + String acadWeek; + String acadSem; + String acadYear = null; + String noOfWeeks = null; + String[] acadWeekDetails; + LocalDate startDate = date; + LocalDate endDate = date; + int currentYear = date.getYear(); + int currentWeekOfYear = date.get(WeekFields.ISO.weekOfWeekBasedYear()); + + // Initialise week numbers for certain weeks. + int firstWeekSemOne = 0; + int firstWeekSemOneHol = 0; + int lastWeekSemOneHol = 0; + int firstWeekSemTwo = 0; + int firstWeekSemTwoHol = 0; + for (Map.Entry entry: acadCalMap.entrySet()) { + if ("Orientation Week_Sem 1".equals(entry.getValue())) { + firstWeekSemOne = entry.getKey(); + } else if ("Examination Week_Sem 1".equals(entry.getValue())) { + firstWeekSemOneHol = entry.getKey() + 1; + } else if ("Week 1_Sem 2".equals(entry.getValue())) { + lastWeekSemOneHol = entry.getKey() - 1; + firstWeekSemTwo = entry.getKey(); + } else if ("Examination Week_Sem 2".equals(entry.getValue())) { + firstWeekSemTwoHol = entry.getKey() + 1; + } + } + + // Set semester details. + acadWeekDetails = acadCalMap.get(currentWeekOfYear).split("_"); + acadWeek = acadWeekDetails[0]; + acadSem = acadWeekDetails[1]; + if ("Vacation".equals(acadWeek) && "Sem 1".equals(acadSem)) { + noOfWeeks = "5"; + if (currentWeekOfYear < 4) { + acadYear = "AY" + (currentYear - 1) + "/" + currentYear; + startDate = startDate.withYear(currentYear - 1); + } else { + acadYear = "AY" + currentYear + "/" + (currentYear + 1); + endDate = endDate.withYear(currentYear + 1); + } + startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOneHol); + startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); + endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), lastWeekSemOneHol); + endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); + } else if ("Vacation".equals(acadWeek) && "Sem 2".equals(acadSem)) { + noOfWeeks = "12"; + acadYear = "AY" + (currentYear - 1) + "/" + currentYear; + startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwoHol); + startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); + endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwoHol + 11); + endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); + } else if ("Sem 1".equals(acadSem)) { + noOfWeeks = "18"; + acadYear = "AY" + currentYear + "/" + (currentYear + 1); + startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOne); + startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); + endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemOne + 17); + endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); + } else if ("Sem 2".equals(acadSem)) { + noOfWeeks = "17"; + acadYear = "AY" + (currentYear - 1) + "/" + currentYear; + startDate = startDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwo); + startDate = startDate.with(WeekFields.ISO.dayOfWeek(), 1); + endDate = endDate.with(WeekFields.ISO.weekOfWeekBasedYear(), firstWeekSemTwo + 16); + endDate = endDate.with(WeekFields.ISO.dayOfWeek(), 7); + } + return new String[] {acadWeek, acadSem, acadYear, noOfWeeks, startDate.toString(), endDate.toString()}; + } + /** * Adds a Day to the list. * @@ -139,10 +384,7 @@ public void removeSlot(LocalDate date, ReadOnlySlot slot) { */ public void editSlot(LocalDate targetDate, ReadOnlySlot targetSlot, LocalDate date, LocalTime startTime, int duration, String name, String location, String description, Set tags) - throws DateNotFoundException, IllegalValueException { - if (targetDate == null || (targetDate.isBefore(startDate) || targetDate.isAfter(endDate))) { - throw new DateNotFoundException(); - } + throws IllegalValueException { Slot editingSlot = days.get(targetDate).getSlots().stream() .filter(s -> s.equals(targetSlot)).findAny().orElse(null); diff --git a/test/java/planmysem/data/PlannerTest.java b/test/java/planmysem/data/PlannerTest.java index 654b79633..f2074ec94 100644 --- a/test/java/planmysem/data/PlannerTest.java +++ b/test/java/planmysem/data/PlannerTest.java @@ -25,21 +25,21 @@ public void execute_generateSemester() { Semester expectedSemester; // Assert Semester One generation - generatedSemester = Planner.generateSemester(LocalDate.of(2018, 8, 6)); + generatedSemester = Semester.generateSemester(LocalDate.of(2018, 8, 6)); LocalDate semOneDate = LocalDate.of(2018, 8, 6); expectedSemester = helper.generateSemesterFromDate(semOneDate, "Sem 1"); assertSameSemester(generatedSemester, expectedSemester); - expectedSemester = Planner.generateSemester(LocalDate.of(2018, 10, 6)); + expectedSemester = Semester.generateSemester(LocalDate.of(2018, 10, 6)); assertSameSemester(generatedSemester, expectedSemester); // Assert Semester Two generation - generatedSemester = Planner.generateSemester(LocalDate.of(2019, 1, 14)); + generatedSemester = Semester.generateSemester(LocalDate.of(2019, 1, 14)); LocalDate semTwoDate = LocalDate.of(2019, 1, 14); expectedSemester = helper.generateSemesterFromDate(semTwoDate, "Sem 2"); assertSameSemester(generatedSemester, expectedSemester); - expectedSemester = Planner.generateSemester(LocalDate.of(2019, 3, 17)); + expectedSemester = Semester.generateSemester(LocalDate.of(2019, 3, 17)); assertSameSemester(generatedSemester, expectedSemester); } @@ -48,15 +48,7 @@ public void execute_generateSemester() { */ private void assertSameSemester(Semester generatedSemester, Semester expectedSemester) { //Confirm the state of data is as expected - assertEquals(generatedSemester.getName(), expectedSemester.getName()); - assertEquals(generatedSemester.getAcademicYear(), expectedSemester.getAcademicYear()); - assertEquals(generatedSemester.getNoOfWeeks(), expectedSemester.getNoOfWeeks()); - assertEquals(generatedSemester.getStartDate(), expectedSemester.getStartDate()); - assertEquals(generatedSemester.getEndDate(), expectedSemester.getEndDate()); - assertEquals(generatedSemester.getDays().size(), expectedSemester.getDays().size()); - assertEquals(generatedSemester.getRecessDays().size(), expectedSemester.getRecessDays().size()); - assertEquals(generatedSemester.getReadingDays().size(), expectedSemester.getReadingDays().size()); - assertEquals(generatedSemester.getExamDays().size(), expectedSemester.getExamDays().size()); + assertEquals(generatedSemester.hashCode(), expectedSemester.hashCode()); } /** From 48db5f1a5471d6c9494b7165671a2371fb7c187d Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Sun, 24 Mar 2019 15:53:43 +0800 Subject: [PATCH 17/22] Planner: remove unused imports --- src/planmysem/data/Planner.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/planmysem/data/Planner.java b/src/planmysem/data/Planner.java index 9ae024141..3a0785509 100644 --- a/src/planmysem/data/Planner.java +++ b/src/planmysem/data/Planner.java @@ -1,17 +1,10 @@ package planmysem.data; -import java.time.DayOfWeek; import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.temporal.TemporalAdjusters; -import java.time.temporal.WeekFields; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; import java.util.Map; import java.util.Set; -import java.util.stream.Collectors; import planmysem.data.exception.IllegalValueException; import planmysem.data.semester.Day; From fe1f0e48ba0831367f9659bd14181324e11af390 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Sun, 24 Mar 2019 16:01:45 +0800 Subject: [PATCH 18/22] Semester: undo minor change --- src/planmysem/data/semester/Semester.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/planmysem/data/semester/Semester.java b/src/planmysem/data/semester/Semester.java index f9502177a..9d4fd9b12 100644 --- a/src/planmysem/data/semester/Semester.java +++ b/src/planmysem/data/semester/Semester.java @@ -384,7 +384,10 @@ public void removeSlot(LocalDate date, ReadOnlySlot slot) { */ public void editSlot(LocalDate targetDate, ReadOnlySlot targetSlot, LocalDate date, LocalTime startTime, int duration, String name, String location, String description, Set tags) - throws IllegalValueException { + throws DateNotFoundException, IllegalValueException { + if (targetDate == null || (targetDate.isBefore(startDate) || targetDate.isAfter(endDate))) { + throw new DateNotFoundException(); + } Slot editingSlot = days.get(targetDate).getSlots().stream() .filter(s -> s.equals(targetSlot)).findAny().orElse(null); From 7a60cb4dc098c5eae1d2e191e54043783c152171 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Mon, 25 Mar 2019 04:51:30 +0800 Subject: [PATCH 19/22] DeveloperGuide: Update documentation on initialization of Semester --- docs/DeveloperGuide.adoc | 90 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 83 insertions(+), 7 deletions(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index e3f021a1b..8bb554bb4 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -260,19 +260,95 @@ This section describes some noteworthy details on how certain features are imple === Initialization of the Planner and it's Semester -The Planner and it's Semester has to be initialized for _PlanMySem_ to work as all other features of _PlanMySem_ would -interact with this Semester object. +The `Planner` and it's `Semester` has to be initialized for _PlanMySem_ to work as all other features of _PlanMySem_ would +interact with this `Semester` object. ==== Current Implementation -Upon launching _PlanMySem_, the initialization of the Planner and it's Semester would be implemented via two steps: +Upon launching _PlanMySem_, the initialization of the `Planner` and it's `Semester` would be implemented via two steps: 1. Automatically generate the academic calendar from the current date. -2. Setup current Semester from the academic calendar. +2. Setup current `Semester` from the academic calendar. + +The academic calendar is dynamically generated by invoking the function `generateSemester` in the `Semester` class. +The function will first retrieve the current date from the system clock to determine which academic year it is. +As a new academic year starts from August, it can be determined from the month of the current date. + +* If the current date is before August, the current academic year is "the previous year / current year". + +e.g. If the date is 25/3/2019, the academic year is "2018 / 2019". +* If the current date is after August, the current academic year is "the current year / next year". + +e.g. If the date is 25/8/2019, the academic year is "2019 / 2020". + +After determining the academic year, the details of the semesters will be generated. Semester 1 will always begin from +the first Monday of August. The rest of the weeks can be calculated from the first day of semester 1 since each +semester has a fixed amount of weeks. + +* Semester 1 has 18 weeks (inclusive of orientation week) and semester 2 has 17 weeks. +* The vacation between semester 1 and 2 has 5 weeks. +* The vacation between academic years will have 12 or 13 weeks depending on the starting week of the next academic year. + +Each week of the year will correspond to an academic week and this information will be stored in a `HashMap`. This +`HashMap` can be used to determine the academic week given a date (by finding out the week of the year for that date). +Table 1 shows an example of the relation between academic week and the week of the year for academic year 2018/2019. + +.Weeks in academic year 2018/2019. +[width="100%",cols="5%,5%,<10%",options="header"] +|======================================================================= +|Academic Week |Example (Week of the year) |Example (Period) +|Orientation Week |32 |6 Aug 2018 (First Monday of Aug 2018) - 12 Aug 2018 +|Week 1 |33 |13 Aug 2018 - 19 Aug 2018 +|Week 2 |34 |20 Aug 2018 - 26 Aug 2018 +|Week 3 |35 |27 Aug 2018 - 2 Sep 2018 +|Week 4 |36 |3 Sep 2018 - 9 Sep 2018 +|Week 5 |37 |10 Sep 2018 - 16 Sep 2018 +|Week 6 |38 |17 Sep 2018 - 23 Sep 2018 +|Recess Week|39 |24 Sep 2018 - 30 Sep 2018 +|Week 7 |40 |1 Oct 2018 - 7 Oct 2018 +|Week 8 |41 |8 Oct 2018 - 14 Oct 2018 +|Week 9 |42 |15 Oct 2018 - 21 Oct 2018 +|Week 10 |43 |22 Oct 2018 - 28 Oct 2018 +|Week 11 |44 |29 Oct 2018 - 4 Nov 2018 +|Week 12 |45 |5 Nov 2018 - 11 Nov 2018 +|Week 13 |46 |12 Nov 2018 - 18 Nov 2018 +|Reading Week |47 |19 Nov 2018 - 25 Nov 2018 +|Examination Week |48 |26 Nov 2018 - 2 Dec 2018 +|Examination Week |49 |3 Dec 2018 - 9 Dec 2018 +|Vacation |50 |10 Dec 2018 - 16 Dec 2018 +|Vacation |51 |17 Dec 2018 - 23 Dec 2018 +|Vacation |52 |24 Dec 2018 - 30 Dec 2018 +|Vacation |1 |31 Dec 2018 - 6 Jan 2019 +|Vacation |2 |7 Jan 2019 - 13 Jan 2019 +|Week 1 |3 |14 Jan 2019 - 20 Jan 2019 +|Week 2 |4 |21 Jan 2019 - 27 Jan 2019 +|Week 3 |5 |28 Jan 2019 - 3 Feb 2019 +|Week 4 |6 |4 Feb 2019 - 10 Feb 2019 +|Week 5 |7 |11 Feb 2019 - 17 Feb 2019 +|Week 6 |8 |18 Feb 2019 - 24 Feb 2019 +|Recess Week|9 |25 Feb 2019 - 3 Mar 2019 +|Week 7 |10 |4 Mar 2019 - 10 Mar 2019 +|Week 8 |11 |11 Mar 2019 - 17 Mar 2019 +|Week 9 |12 |18 Mar 2019 - 24 Mar 2019 +|Week 10 |13 |25 Mar 2019 - 31 Mar 2019 +|Week 11 |14 |1 Apr 2019 - 7 Apr 2019 +|Week 12 |15 |8 Apr 2019 - 14 Apr 2019 +|Week 13 |16 |15 Apr 2019 - 21 Apr 2019 +|Reading Week |17 |22 Apr 2019 - 28 Apr 2019 +|Examination Week |18 |29 Apr 2019 - 5 May 2019 +|Examination Week |19 |6 May 2019 - 12 May 2019 +|Vacation |20 - 31 |12 weeks duration +|======================================================================= + +Hence, the information listed below can be determined from the current date. + +* Current academic week +* Current academic semester +* Current academic year +* Number of weeks in current academic semester +* Start date of current academic semester +* End date of current academic semester + +These information would be assigned to the `Semester` object upon initialization of the `Planner`. -//The academic calendar is dynamically generated by invoking the function -//based on the current date retrieved from the system clock. -//TBC ==== Design Considerations ===== Aspect: Generation of academic calendar From dcc4a849aa5257ca8ad20083aa14060d6cf09e4c Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Fri, 29 Mar 2019 19:36:32 +0800 Subject: [PATCH 20/22] Merge commit --- docs/DeveloperGuide.adoc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/DeveloperGuide.adoc b/docs/DeveloperGuide.adoc index 23a96df2a..8eeb60f9a 100644 --- a/docs/DeveloperGuide.adoc +++ b/docs/DeveloperGuide.adoc @@ -516,7 +516,7 @@ FindCommand will be enhanced by using Levenshtein Distance to generate an ordere ** Cons: Large amount of additional operations. ==== Future Implementation - +// to be edited The month/week/day view mechanism is facilitated by `PlannerView`. It extends `Planner` with different calendar views, stored internally as `monthView`, `weekView` and `dayView`. Additionally, it implements the following operations: From f3d3b3a2e7869e7419076e659431838dd1260765 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Sat, 30 Mar 2019 19:57:00 +0800 Subject: [PATCH 21/22] Update view command for calendar day view --- docs/UserGuide.adoc | 12 +-- src/planmysem/logic/commands/HelpCommand.java | 2 +- src/planmysem/logic/commands/ViewCommand.java | 90 +++++++++++++++++-- .../logic/parser/ViewCommandParser.java | 2 + 4 files changed, 93 insertions(+), 13 deletions(-) diff --git a/docs/UserGuide.adoc b/docs/UserGuide.adoc index 43f4d0918..6ba70f16c 100644 --- a/docs/UserGuide.adoc +++ b/docs/UserGuide.adoc @@ -344,24 +344,26 @@ image::Find_Command_Output_1.png[width="790"] View the planner in a month/week/day view. 1. View the monthly calendar view of the current academic semester. + -Format: `view month [MONTH]` +Format: `view month` 2. View the weekly calendar view of the current academic week. + Format: `view week [WEEK]` 3. View the day view of a particular day in the academic semester. + -Format: `view day [DATE]` +Format: `view day [DATE_OR_DAY_OF_WEEK]` 4. View all the details in the planner. + Format: `view all` [TIP] -You may omit `[MONTH]`/`[WEEK]`/`[DATE]` to view the format chosen in respect to the current day! + -E.g. `view month` will allow you to view the current month and `view day` will allow you to view the current day! +You may omit `[WEEK]`/`[DATE_OR_DAY_OF_WEEK]` to view the calendar with respect to the current date! + +E.g. `view week` will allow you to view the current week and `view day` will allow you to view the current day! Examples: * `view day` + View planner for the current date. -* `view day 01/03/2019` + +* `view day 01-03-2019` + View planner for the first of March. +* `view day monday` + +View planner for the upcoming Monday. * `view week 7` + View planner for week 7 of the academic calendar. * `view week recess` + diff --git a/src/planmysem/logic/commands/HelpCommand.java b/src/planmysem/logic/commands/HelpCommand.java index 773f580ca..87212fe01 100644 --- a/src/planmysem/logic/commands/HelpCommand.java +++ b/src/planmysem/logic/commands/HelpCommand.java @@ -18,7 +18,7 @@ public class HelpCommand extends Command { + "\n\n" + DeleteCommand.MESSAGE_USAGE + "\n\n" + ListCommand.MESSAGE_USAGE + "\n\n" + FindCommand.MESSAGE_USAGE - // + "\n\n" + ViewCommand.MESSAGE_USAGE + + "\n\n" + ViewCommand.MESSAGE_USAGE // + "\n\n" + ViewAllCommand.MESSAGE_USAGE + "\n\n" + ClearCommand.MESSAGE_USAGE + "\n\n" + HelpCommand.MESSAGE_USAGE diff --git a/src/planmysem/logic/commands/ViewCommand.java b/src/planmysem/logic/commands/ViewCommand.java index febbfd811..7564c3e01 100644 --- a/src/planmysem/logic/commands/ViewCommand.java +++ b/src/planmysem/logic/commands/ViewCommand.java @@ -1,15 +1,23 @@ package planmysem.logic.commands; +import static planmysem.common.Utils.getNearestDayOfWeek; + import java.time.LocalDate; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.Comparator; import java.util.HashMap; +import planmysem.common.Clock; +import planmysem.common.Utils; import planmysem.logic.CommandHistory; import planmysem.model.Model; import planmysem.model.semester.Day; import planmysem.model.semester.Semester; +import planmysem.model.slot.Slot; /** - * Adds a person to the address book. + * View the planner. */ public class ViewCommand extends Command { @@ -17,8 +25,10 @@ public class ViewCommand extends Command { public static final String COMMAND_WORD_SHORT = "v"; public static final String MESSAGE_USAGE = COMMAND_WORD + ": View month/week/day view or all details of planner." - + "\n\tParameters: " - + "\n\t\tMandatory: [viewType] [specifier]" + + "\n\tFormat: view [viewType] [specifier]" + + "\n\tParameters:" + + "\n\t\tMandatory: [viewType]" + + "\n\t\tOptional: [specifier]" + "\n\tExample 1: " + COMMAND_WORD + " month" + "\n\tExample 2: " + COMMAND_WORD @@ -26,8 +36,14 @@ public class ViewCommand extends Command { + "\n\tExample 3: " + COMMAND_WORD + " week recess" + "\n\tExample 4: " + COMMAND_WORD - + " day 01/03/2019" + + " week" + "\n\tExample 5: " + COMMAND_WORD + + " day 01/03/2019" + + "\n\tExample 6: " + COMMAND_WORD + + " day monday" + + "\n\tExample 7: " + COMMAND_WORD + + " day" + + "\n\tExample 8: " + COMMAND_WORD + " all"; private final String viewArgs; @@ -39,7 +55,7 @@ public ViewCommand(String viewArgs) { @Override public CommandResult execute(Model model, CommandHistory commandHistory) { String viewType; - //String viewSpecifier; + String viewSpecifier; final Semester currentSemester = model.getPlanner().getSemester(); String output = null; @@ -48,9 +64,13 @@ public CommandResult execute(Model model, CommandHistory commandHistory) { output = "all"; } else if ("month".equals(viewArgs)) { output = displayMonthView(currentSemester); + } else if ("day".equals(viewArgs)) { + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); + String currentDate = LocalDate.now().format(formatter); + output = displayDayView(currentSemester, currentDate); } else { viewType = viewArgs.split(" ")[0]; - //viewSpecifier = viewArgs.split(" ")[1]; + viewSpecifier = viewArgs.split(" ")[1]; switch (viewType) { case "month": @@ -60,7 +80,7 @@ public CommandResult execute(Model model, CommandHistory commandHistory) { //TODO: week view break; case "day": - //TODO: day view + output = displayDayView(currentSemester, viewSpecifier); break; default: break; @@ -136,4 +156,60 @@ private String displayMonthView(Semester currentSemester) { return sb.toString(); } + /** + * Display all slots for a given day/date. + */ + private String displayDayView(Semester currentSemester, String dateOrDay) { + HashMap allDays = currentSemester.getDays(); + StringBuilder sb = new StringBuilder(); + + // Parse different formats of given day/date. + int day = -1; + LocalDate givenDate = Utils.parseDate(dateOrDay); + if (givenDate == null) { + day = Utils.parseDay(dateOrDay); + } + if (day == -1 && givenDate == null) { + return MESSAGE_USAGE; + } + if (day != -1) { + givenDate = getNearestDayOfWeek(LocalDate.now(Clock.get()), day); + } + sb.append(givenDate.getDayOfWeek().name() + " , " + givenDate + "\n\n"); + + // Retrieve all slots for given day/date in sorted order. + ArrayList allSlotsInDay = allDays.get(givenDate).getSlots(); + Comparator comparator = new Comparator() { + @Override + public int compare(final Slot o1, final Slot o2) { + return o1.getStartTime().compareTo(o2.getStartTime()); + } + }; + allSlotsInDay.sort(comparator); + + // Print each slot. + for (Slot slot : allSlotsInDay) { + sb.append("* " + slot.getStartTime()); + sb.append(" to "); + sb.append(Utils.getEndTime(slot.getStartTime(), slot.getDuration())); + + sb.append("\n\t" + slot.getName() + "\n"); + sb.append("\t" + "Location: " + slot.getLocation() + "\n"); + sb.append("\t" + "Description: " + slot.getDescription() + "\n"); + sb.append("\n\tTags: \n"); + + int count = 1; + for (String tag : slot.getTags()) { + sb.append("\t"); + sb.append(count); + sb.append(". "); + sb.append(tag); + count++; + } + + sb.append("\n\n"); + } + + return sb.toString(); + } } diff --git a/src/planmysem/logic/parser/ViewCommandParser.java b/src/planmysem/logic/parser/ViewCommandParser.java index 5fc2a392d..37599452a 100644 --- a/src/planmysem/logic/parser/ViewCommandParser.java +++ b/src/planmysem/logic/parser/ViewCommandParser.java @@ -27,6 +27,8 @@ public ViewCommand parse(String args) throws ParseException { return new ViewCommand(viewArgs[1]); } else if ("month".equals(viewArgs[1]) && viewArgs.length == 2) { return new ViewCommand(viewArgs[1]); + } else if ("day".equals(viewArgs[1]) && viewArgs.length == 2) { + return new ViewCommand(viewArgs[1]); } else if ("month".equals(viewArgs[1]) && viewArgs.length == 3) { //TODO: ensure month arguments return new ViewCommand(viewArgs[1] + " " + viewArgs[2]); From 0006b6284274b0965e4d6e33579b64740d85a3f7 Mon Sep 17 00:00:00 2001 From: dingheng4448 Date: Sun, 31 Mar 2019 00:57:04 +0800 Subject: [PATCH 22/22] Update view command for calendar week view --- src/planmysem/logic/commands/ViewCommand.java | 102 +++++++++++++++--- .../logic/parser/ViewCommandParser.java | 2 + .../model/semester/ReadOnlySemester.java | 1 + src/planmysem/model/semester/Semester.java | 18 +++- 4 files changed, 101 insertions(+), 22 deletions(-) diff --git a/src/planmysem/logic/commands/ViewCommand.java b/src/planmysem/logic/commands/ViewCommand.java index 7564c3e01..bad9ee31f 100644 --- a/src/planmysem/logic/commands/ViewCommand.java +++ b/src/planmysem/logic/commands/ViewCommand.java @@ -4,9 +4,13 @@ import java.time.LocalDate; import java.time.format.DateTimeFormatter; +import java.time.temporal.WeekFields; import java.util.ArrayList; import java.util.Comparator; import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import planmysem.common.Clock; import planmysem.common.Utils; @@ -64,20 +68,17 @@ public CommandResult execute(Model model, CommandHistory commandHistory) { output = "all"; } else if ("month".equals(viewArgs)) { output = displayMonthView(currentSemester); + } else if ("week".equals(viewArgs)) { + output = displayWeekView(currentSemester, null); } else if ("day".equals(viewArgs)) { - DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); - String currentDate = LocalDate.now().format(formatter); - output = displayDayView(currentSemester, currentDate); + output = displayDayView(currentSemester, null); } else { viewType = viewArgs.split(" ")[0]; viewSpecifier = viewArgs.split(" ")[1]; switch (viewType) { - case "month": - //TODO: month view - break; case "week": - //TODO: week view + output = displayWeekView(currentSemester, viewSpecifier); break; case "day": output = displayDayView(currentSemester, viewSpecifier); @@ -156,6 +157,68 @@ private String displayMonthView(Semester currentSemester) { return sb.toString(); } + /** + * Display all slots for a given week. + */ + private String displayWeekView(Semester currentSemester, String week) { + HashMap allDays = currentSemester.getDays(); + StringBuilder sb = new StringBuilder(); + + if (week == null) { + System.out.println(allDays.get(LocalDate.now()).getType()); + + } else { + HashMap acadCal = currentSemester.getAcadCal(); + //System.out.println(currentSemester.getAcadCal()); + String key; + int[] weekOfYear = {0, 0}; + List datesList; + + if ("Recess".equals(week) || "Reading".equals(week) || "Examination".equals(week) + || "Orientation".equals(week)) { + key = week + " Week" + "_" + currentSemester.getName(); + sb.append(week + "Week" + " of " + currentSemester.getName() + "\n"); + } else { + key = "Week " + week + "_" + currentSemester.getName(); + sb.append("Week " + week + " of " + currentSemester.getName() + "\n"); + } + //System.out.println(key); + + for (Map.Entry entry: acadCal.entrySet()) { + if (key.equals(entry.getValue())) { + if (weekOfYear[0] == 0) { + weekOfYear[0] = entry.getKey(); + } else { + weekOfYear[1] = entry.getKey(); + } + } + } + //System.out.println(weekOfYear[0] + ", " + weekOfYear[1]); + + LocalDate weekStart = LocalDate.now().with(WeekFields.ISO.weekOfWeekBasedYear(), weekOfYear[0]); + weekStart = weekStart.with(WeekFields.ISO.dayOfWeek(), 1); + LocalDate weekEnd = weekStart.with(WeekFields.ISO.weekOfWeekBasedYear(), weekOfYear[0] + 1); + datesList = weekStart.datesUntil(weekEnd).collect(Collectors.toList()); + //System.out.println(datesList); + + sb.append("__________________________________________________________________________\n\n"); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-MM-yyyy"); + for (LocalDate date : datesList) { + sb.append(displayDayView(currentSemester, date.format(formatter))); + sb.append("__________________________________________________________________________\n\n"); + } + + // get acad cal map + // swap key and value + // find week of year from acad week + // get all dates for week of year + // get all slots for all dates found + // format and print out all slots + } + + return sb.toString(); + } + /** * Display all slots for a given day/date. */ @@ -164,16 +227,21 @@ private String displayDayView(Semester currentSemester, String dateOrDay) { StringBuilder sb = new StringBuilder(); // Parse different formats of given day/date. - int day = -1; - LocalDate givenDate = Utils.parseDate(dateOrDay); - if (givenDate == null) { - day = Utils.parseDay(dateOrDay); - } - if (day == -1 && givenDate == null) { - return MESSAGE_USAGE; - } - if (day != -1) { - givenDate = getNearestDayOfWeek(LocalDate.now(Clock.get()), day); + LocalDate givenDate; + if (dateOrDay == null) { + givenDate = LocalDate.now(); + } else { + int day = -1; + givenDate = Utils.parseDate(dateOrDay); + if (givenDate == null) { + day = Utils.parseDay(dateOrDay); + } + if (day == -1 && givenDate == null) { + return MESSAGE_USAGE; + } + if (day != -1) { + givenDate = getNearestDayOfWeek(LocalDate.now(Clock.get()), day); + } } sb.append(givenDate.getDayOfWeek().name() + " , " + givenDate + "\n\n"); diff --git a/src/planmysem/logic/parser/ViewCommandParser.java b/src/planmysem/logic/parser/ViewCommandParser.java index 37599452a..f2242baf1 100644 --- a/src/planmysem/logic/parser/ViewCommandParser.java +++ b/src/planmysem/logic/parser/ViewCommandParser.java @@ -27,6 +27,8 @@ public ViewCommand parse(String args) throws ParseException { return new ViewCommand(viewArgs[1]); } else if ("month".equals(viewArgs[1]) && viewArgs.length == 2) { return new ViewCommand(viewArgs[1]); + } else if ("week".equals(viewArgs[1]) && viewArgs.length == 2) { + return new ViewCommand(viewArgs[1]); } else if ("day".equals(viewArgs[1]) && viewArgs.length == 2) { return new ViewCommand(viewArgs[1]); } else if ("month".equals(viewArgs[1]) && viewArgs.length == 3) { diff --git a/src/planmysem/model/semester/ReadOnlySemester.java b/src/planmysem/model/semester/ReadOnlySemester.java index a7f679602..4c97d05fd 100644 --- a/src/planmysem/model/semester/ReadOnlySemester.java +++ b/src/planmysem/model/semester/ReadOnlySemester.java @@ -16,6 +16,7 @@ public interface ReadOnlySemester { LocalDate getStartDate(); LocalDate getEndDate(); int getNoOfWeeks(); + HashMap getAcadCal(); // These variables aid in making searches more effective Set getRecessDays(); diff --git a/src/planmysem/model/semester/Semester.java b/src/planmysem/model/semester/Semester.java index a6cf8751a..4bbe76a10 100644 --- a/src/planmysem/model/semester/Semester.java +++ b/src/planmysem/model/semester/Semester.java @@ -24,6 +24,7 @@ * @see Day#equals(Object) */ public class Semester implements ReadOnlySemester { + private static HashMap acadCal = new HashMap<>(); private final String name; private final String academicYear; private final HashMap days = new HashMap<>(); @@ -107,6 +108,7 @@ public static Semester generateSemester(LocalDate currentDate) { Set examDays = new HashSet<>(); acadCalMap = generateAcadCalMap(currentDate); + acadCal = acadCalMap; semesterDetails = getSemesterDetails(currentDate, acadCalMap); acadSem = semesterDetails[1]; acadYear = semesterDetails[2]; @@ -242,6 +244,7 @@ private static HashMap generateAcadCalMap(LocalDate date) { acadCalMap.put(vacationWeekNo++, "Vacation_Sem 2"); } + //System.out.println(acadCalMap); //why does this print twice? return acadCalMap; } @@ -467,11 +470,6 @@ public void setDays(HashMap days) { this.days.putAll(days); } - @Override - public HashMap getDays() { - return days; - } - @Override public LocalDate getStartDate() { return startDate; @@ -507,6 +505,16 @@ public Set getExamDays() { return examDays; } + @Override + public HashMap getDays() { + return days; + } + + @Override + public HashMap getAcadCal() { + return acadCal; + } + @Override public boolean equals(Object other) { return other == this // short circuit if same object