Time Table Fixed

This commit is contained in:
RIT Services
2026-08-20 04:58:20 +00:00
parent f0011b4af1
commit 9d83dec681
6 changed files with 557 additions and 87 deletions

View File

@@ -81,6 +81,7 @@ public class StudentMenuHandler {
weeklyBtn.put("id", "student_weekly_timetable");
weeklyBtn.put("title", "Weekly Timetable");
buttons.add(weeklyBtn);
System.out.println("FINAL TODAY TIMETABLE MESSAGE:\n" + todaySchedule);
Map<String, Object> buttonMessage = WhatsAppMessageBuilder.buildButtonMessage(todaySchedule, buttons);
messageService.sendInteractiveMessage(phoneNumber, buttonMessage);

View File

@@ -95,74 +95,136 @@ public class MessageFormatter {
return sb.toString();
}
public static String formatTimetable(String rawJson) {
private static class TimetableEntry {
String subjectName;
String subjectCode;
String staffName;
String staffCode;
public TimetableEntry(String subjectName, String subjectCode, String staffName, String staffCode) {
this.subjectName = subjectName != null ? subjectName.trim() : "";
this.subjectCode = subjectCode != null ? subjectCode.trim() : "";
this.staffName = staffName != null ? staffName.trim() : "";
this.staffCode = staffCode != null ? staffCode.trim() : "";
}
public boolean isValid() {
return !subjectName.isEmpty() && !subjectCode.isEmpty();
}
public String getUniqueKey() {
return subjectName + "||" + subjectCode;
}
}
public static String formatTodayTimetable(String rawJson) {
String day = java.time.LocalDate.now()
.getDayOfWeek()
.getDisplayName(java.time.format.TextStyle.FULL, java.util.Locale.ENGLISH)
.toLowerCase(java.util.Locale.ROOT);
return formatTodayTimetableForDay(rawJson, day);
}
public static String formatTodayTimetableForDay(String rawJson, String day) {
if (rawJson == null) return "❌ Failed to retrieve timetable data.";
try {
JsonNode root = mapper.readTree(rawJson);
if (!root.has("data") || !root.get("data").isObject() || !root.get("data").has("schedule")) {
return "❌ Timetable details not available in this format.";
}
JsonNode schedule = root.get("data").get("schedule");
System.out.println("TIMETABLE DEBUG");
System.out.println("Current day: " + day.toUpperCase());
System.out.println("Normalized day: " + day);
boolean hasSchedule = schedule.has(day);
System.out.println("Schedule found: " + hasSchedule);
StringBuilder sb = new StringBuilder();
sb.append("\ud83d\uddd3\ufe0f *Today's Classes*\n\n");
sb.append("📅 *Today's Classes*\n");
sb.append("━━━━━━━━━━━━━━\n\n");
boolean validFormat = false;
boolean hasClassesToday = false;
if (root.has("data") && root.get("data").isObject() && root.get("data").has("schedule")) {
validFormat = true;
JsonNode schedule = root.get("data").get("schedule");
if (hasSchedule) {
JsonNode daySchedule = schedule.get(day);
String today = java.time.LocalDate.now().getDayOfWeek().toString().toLowerCase();
int maxPeriod = 7;
java.util.Iterator<String> fieldNames = daySchedule.fieldNames();
java.util.List<String> foundPeriods = new java.util.ArrayList<>();
while (fieldNames.hasNext()) {
String fName = fieldNames.next();
foundPeriods.add(fName);
try {
int p = Integer.parseInt(fName);
if (p > maxPeriod) {
maxPeriod = p;
}
} catch (NumberFormatException e) {}
}
System.out.println("Periods found: [" + String.join(", ", foundPeriods) + "]");
if (schedule.has(today)) {
JsonNode todaySchedule = schedule.get(today);
for (int period = 1; period <= maxPeriod; period++) {
String periodKey = String.valueOf(period);
sb.append(getNumberEmoji(period)).append(" ");
if (todaySchedule.isObject() && todaySchedule.size() > 0) {
java.util.Iterator<java.util.Map.Entry<String, JsonNode>> fields = todaySchedule.fields();
while (fields.hasNext()) {
java.util.Map.Entry<String, JsonNode> field = fields.next();
String timeOrPeriod = field.getKey();
JsonNode details = field.getValue();
if (details.isObject()) {
String course = details.has("course_name") ? details.get("course_name").asText() :
(details.has("name") ? details.get("name").asText() : "Unknown");
String room = details.has("room") ? details.get("room").asText() : "";
sb.append("*").append(timeOrPeriod).append(":* ").append(course);
if (!room.isEmpty()) sb.append(" (Room ").append(room).append(")");
sb.append("\n");
} else {
sb.append("*").append(timeOrPeriod).append(":* ").append(details.asText()).append("\n");
if (daySchedule.has(periodKey)) {
JsonNode periodNode = daySchedule.get(periodKey);
java.util.List<TimetableEntry> entries = new java.util.ArrayList<>();
if (periodNode.isArray()) {
for (JsonNode node : periodNode) {
String sName = node.has("subjectName") ? node.get("subjectName").asText() : "";
String sCode = node.has("subjectCode") ? node.get("subjectCode").asText() : "";
String stName = node.has("staffName") ? node.get("staffName").asText() : "";
String stCode = node.has("staffCode") ? node.get("staffCode").asText() : "";
entries.add(new TimetableEntry(sName, sCode, stName, stCode));
}
hasClassesToday = true;
}
} else if (todaySchedule.isArray() && todaySchedule.size() > 0) {
for (JsonNode details : todaySchedule) {
String time = details.has("time") ? details.get("time").asText() : "TBA";
String course = details.has("course_name") ? details.get("course_name").asText() : "Unknown";
String room = details.has("room") ? details.get("room").asText() : "";
sb.append("*").append(time).append(":* ").append(course);
if (!room.isEmpty()) sb.append(" (Room ").append(room).append(")");
sb.append("\n");
hasClassesToday = true;
System.out.println("Period " + period + " entries: " + entries.size());
if (!entries.isEmpty()) {
TimetableEntry first = entries.get(0);
System.out.println("Period " + period + " first subjectName: " + first.subjectName);
System.out.println("Period " + period + " first subjectCode: " + first.subjectCode);
}
java.util.Map<String, TimetableEntry> uniqueMap = new java.util.LinkedHashMap<>();
for (TimetableEntry entry : entries) {
if (entry.isValid()) {
uniqueMap.putIfAbsent(entry.getUniqueKey(), entry);
}
}
if (!uniqueMap.isEmpty()) {
java.util.List<String> formattedSubjects = new java.util.ArrayList<>();
for (TimetableEntry entry : uniqueMap.values()) {
formattedSubjects.add("*" + entry.subjectName + "*\n `" + entry.subjectCode + "`");
}
sb.append(String.join(" / ", formattedSubjects)).append("\n\n");
} else {
sb.append("*Free Period*\n\n");
}
} else {
sb.append("*Free Period*\n\n");
}
}
} else {
sb.append("No classes scheduled for today.\n\n");
}
if (validFormat && !hasClassesToday) {
sb.append("No classes scheduled for today.\n");
} else if (!validFormat) {
sb.append("Details not available in this format.\n");
sb.append("\n\n*DEBUG RAW JSON:*\n").append(rawJson);
}
sb.append("━━━━━━━━━━━━━━");
return sb.toString();
} catch (Exception e) {
return "⚠️ Error formatting timetable data.\nRAW JSON: " + rawJson;
System.err.println("Error formatting today's timetable: " + e.getMessage());
return "⚠️ Error formatting timetable data.";
}
}
public static String formatTimetable(String rawJson) {
return formatTodayTimetable(rawJson);
}
public static String formatResults(String rawJson, int semester) {
if (rawJson == null) return "❌ Failed to retrieve semester results.";
@@ -444,76 +506,105 @@ public class MessageFormatter {
return rows;
}
private static String getNumberEmoji(int num) {
switch (num) {
case 1: return "1️⃣";
case 2: return "2️⃣";
case 3: return "3️⃣";
case 4: return "4️⃣";
case 5: return "5️⃣";
case 6: return "6️⃣";
case 7: return "7️⃣";
case 8: return "8️⃣";
case 9: return "9️⃣";
default: return num + "️⃣";
}
}
public static String formatWeeklyTimetable(String rawJson) {
if (rawJson == null) return "❌ Failed to retrieve weekly timetable data.";
try {
JsonNode root = mapper.readTree(rawJson);
if (!root.has("data") || !root.get("data").isObject() || !root.get("data").has("schedule")) {
return "❌ Weekly timetable details not available in the response.";
}
JsonNode schedule = root.get("data").get("schedule");
StringBuilder sb = new StringBuilder();
sb.append("📅 *Weekly Class Timetable*\n\n");
sb.append("```\n");
sb.append(String.format("%-3s | %-11s | %s\n", "Day", "Time/Period", "Subject (Room)"));
sb.append("----+-------------+------------------------\n");
sb.append("📚 WEEKLY TIMETABLE\n\n");
String[] days = {"monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"};
String[] dayAbbrevs = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
String[] days = {"monday", "tuesday", "wednesday", "thursday", "friday", "saturday"};
String[] dayLabels = {"MON", "TUE", "WED", "THU", "FRI", "SAT"};
boolean hasAnyClasses = false;
for (int i = 0; i < days.length; i++) {
String day = days[i];
String abbrev = dayAbbrevs[i];
String label = dayLabels[i];
if (schedule.has(day)) {
JsonNode daySchedule = schedule.get(day);
if (daySchedule.isObject() && daySchedule.size() > 0) {
java.util.Iterator<java.util.Map.Entry<String, JsonNode>> fields = daySchedule.fields();
while (fields.hasNext()) {
java.util.Map.Entry<String, JsonNode> field = fields.next();
String timeOrPeriod = field.getKey();
JsonNode details = field.getValue();
sb.append(label).append("\n");
int maxPeriod = 7;
java.util.Iterator<String> fieldNames = daySchedule.fieldNames();
while (fieldNames.hasNext()) {
try {
int p = Integer.parseInt(fieldNames.next());
if (p > maxPeriod) {
maxPeriod = p;
}
} catch (NumberFormatException e) {}
}
for (int period = 1; period <= maxPeriod; period++) {
String periodKey = String.valueOf(period);
sb.append(getNumberEmoji(period)).append(" ");
if (daySchedule.has(periodKey)) {
JsonNode details = daySchedule.get(periodKey);
java.util.Set<String> subjects = new java.util.LinkedHashSet<>();
String course = "";
String room = "";
if (details.isObject()) {
course = details.has("course_name") ? details.get("course_name").asText() :
(details.has("name") ? details.get("name").asText() : "Unknown");
room = details.has("room") ? details.get("room").asText() : "";
} else {
course = details.asText();
if (details.isArray()) {
for (JsonNode entry : details) {
String name = entry.has("subjectName") ? entry.get("subjectName").asText() : "";
String code = entry.has("subjectCode") ? entry.get("subjectCode").asText() : "";
if (!name.trim().isEmpty()) {
subjects.add(name.trim() + " — " + code.trim());
}
}
} else if (details.isObject()) {
String name = details.has("course_name") ? details.get("course_name").asText() :
(details.has("name") ? details.get("name").asText() :
(details.has("subjectName") ? details.get("subjectName").asText() : ""));
String code = details.has("course_code") ? details.get("course_code").asText() :
(details.has("code") ? details.get("code").asText() :
(details.has("subjectCode") ? details.get("subjectCode").asText() : ""));
if (!name.trim().isEmpty()) {
subjects.add(name.trim() + " — " + code.trim());
}
}
String subjectRoom = room.isEmpty() ? course : course + " (" + room + ")";
sb.append(String.format("%-3s | %-11s | %s\n", abbrev, truncate(timeOrPeriod, 11), subjectRoom));
hasAnyClasses = true;
}
} else if (daySchedule.isArray() && daySchedule.size() > 0) {
for (JsonNode details : daySchedule) {
String time = details.has("time") ? details.get("time").asText() : "TBA";
String course = details.has("course_name") ? details.get("course_name").asText() : "Unknown";
String room = details.has("room") ? details.get("room").asText() : "";
String subjectRoom = room.isEmpty() ? course : course + " (" + room + ")";
sb.append(String.format("%-3s | %-11s | %s\n", abbrev, truncate(time, 11), subjectRoom));
hasAnyClasses = true;
if (!subjects.isEmpty()) {
sb.append(String.join(" / ", subjects)).append("\n");
hasAnyClasses = true;
} else {
sb.append("—\n");
}
} else {
sb.append("—\n");
}
}
sb.append("\n");
}
}
sb.append("```");
if (!hasAnyClasses) {
return "📅 *Weekly Class Timetable*\n\nNo classes scheduled for this week.";
return "📚 WEEKLY TIMETABLE\n\nNo classes scheduled for this week.";
}
return sb.toString();
return sb.toString().trim();
} catch (Exception e) {
return "⚠️ Error formatting weekly timetable data.";
}

View File

@@ -19,4 +19,4 @@ spring.h2.console.enabled=true
# Encryption Secret for Passcodes (Must be 16, 24, or 32 bytes)
bot.encryption.secret=12345678901234567890123456789012
whatsapp.api-token=EAAc3Wjql00oBSdoBhXozC8gKyWN9Il6cqpjvE531hZAnuFqOfHCuCBGt8hYZCICzm2dnXsH2RR3HIi3dpZAZBbNFE9Xj8Hvs3TS94nHrmxevicgThlqSQDjZCDm6SS1qFvt7NwRjiy1TWtZCuLLvcTxyjjNPUtjt91OZBr5DtddHzESLezP6R3oJEzIhSjLqlRAvNwfhW8wDYiCkkx0Qw69iO2UeodHw5E8Q86kZCPEvocldDZCyb7qZCMZAELPbYJYkWVLk8MjVyZAXjmnoGFnS5n4ZAsXBE
whatsapp.api-token=EAAc3Wjql00oBSUjYhQ1TZBiNJNmwNlpktCtJpqSLXycDVjWjPiP5dBWHvvFX2Deq1tGXQO2jgVOGChnJk9jsMxLVdxvUs4z7g7xlfcQtAPYiHwvQbPVSbGTTCBvjv2IvHf7Ql2iNBKL72GZCrxAJrQpmjHUG5sbQkVWmMpNfwgI52iDBw0BifU1QhQHFEOnQfiPu19KUp3hJOg6XkUbbXyfBKvbSkZB57xj0XHMv6wgpqDrQwAACOjSlSPrNEC3eZB9DbZAqWYnPkJCsX99Pz3GhA