import java.util.*; import java.io.*; /** Information shares by all elements of a course section */ class Course implements Serializable, Comparable { char status; // 'R' = Rolled, 'O' = Open, 'C' = Closed, // 'X' = Cancelled, 'A','P' = approved in department String crn; String courseId; String sectionId; String title; CourseElement[] elements; public Course() { status = 'X'; crn = ""; courseId = ""; sectionId = ""; title = ""; elements = new CourseElement[6]; } /** @return the name of the course in the usual form, like "1055.001" */ public String getName() { return courseId + "." + sectionId; } /** Ordering courses by course id + section id */ public int compareTo(Course c) { String first = courseId+sectionId; String second = c.courseId+c.sectionId; return first.compareTo(second); } public String toString() { String s = status + " " + crn + " " + getName() + " " + elements[0].campus + " " + elements[0].dayOrEvening + " |" + title + "|"; for (int k = 0; k < 6; k++) { CourseElement e = elements[k]; if (e != null) s = s + "\n\t" + e; } return s; } } /** Description of one of the weekly sessions of a class. */ class CourseElement implements Serializable, Comparable { Course parent; char campus; // 'M' = main, 'A' = Ambler, 'C' = Center city, 'J' = Japan char dayOrEvening; // 'D' = Day, 'E' = Evening String maxSize; char kind; // 'B' = Base i.e. lecture, 'L' = Laboratory, 'R' = Recitation char day; // 'M' = Monday, 'T' = Tuesday, 'W' = Wednesday, 'R' = Thursday // 'F' = Friday String startTime; String endTime; String building; String room; String[] instructors; public String getRoom() { if (building == null || building.equals("") || room == null || room.equals("")) return ""; else return building + room; } public String toString() { return maxSize + " " + day + " " + startTime + "-" + endTime + " " + getRoom() + " " + instructors[0] + instructors[1]; } public CourseElement() {instructors = new String[2]; instructors[0] = ""; instructors[1] = "";} public CourseElement(CourseElement a) { parent = a.parent; campus = a.campus; dayOrEvening = a.dayOrEvening; maxSize = a.maxSize; kind = a.kind; day = a.day; startTime = a.startTime; endTime = a.endTime; building = a.building; room = a.room; instructors = a.instructors; } public static final HashMap dayScore = new HashMap(){{put("M", 1); put("T", 2); put("W", 3); put("R", 4); put("F", 5);}}; /** Ordering CourseElements by day (M,T,W,R,F) and start time */ public int compareTo(CourseElement e) { int d = dayScore.get(day + "") - dayScore.get(e.day + ""); if (d < 0) return -1; if (d == 0) { if (startTime != null && e.startTime != null) return startTime.compareTo(e.startTime); return 0; } return 1; } } /** The program prompts for the name of a file produced by saving as text the section listing of a session from SIMS. Say this name is SIMS-date.txt. The program then displays a menu of actions that can be taken. */ public class Session9 { static Scanner scan; static String[] times = {"08:00", "08:30", "09:00", "09:30", "10:00", "10:30", "11:00", "11:30", "12:00", "12:30", "13:00", "13:30", "14:00", "14:30", "15:00", "15:30", "16:00", "16:30", "17:00", "20:00"}; // static String[] times = {"08:40", "09:10", "09:40", "10:10", "10:40", "11:10", // "11:40", "12:10", "12:40", "13:10", "13:40", "14:10", // "14:40", "15:10", "15:40", "16:10", "16:40", "19:25"}; private String sessionName; // The name of the session, for instance F2007 private ArrayList theCourses; // Normalized text derived from a SIMS session private ArrayList trueCourses; // All the courses defined in a SIMS session private TreeSet instructors; // Sorted list of the instructors in a session private TreeSet rooms; // Sorted list of the rooms used in a session private HashMap> instructorCourses; // For each instructor // it keeps all the courses taught by that instructor private HashMap> roomElements; // For each room // it keeps all the courses taught in that room /** Given the scanner fd, It collects a maximal sequence (at least 2) of non- blank lines from fd and returns them as a single string. This sequence of lines will represent a CourseElement. It will be used to obtain the normalized text for a SIMS session. */ public static String readCourse(Scanner fd) { String item; int count; do { item = ""; count = 0; // Skip initial empty lines if any while (fd.hasNextLine() ) { String s = fd.nextLine().trim(); if (s.length() > 0) { item += s + "\n"; count = 1; break; } } // Collect non empty lines while (fd.hasNextLine() ) { String s = fd.nextLine().trim(); if (s.length() == 0) break; item += s + "\n"; count++; } } while ((count < 2) && fd.hasNextLine()); return item; } /** We read from inFile the text produced by saving in SIMS the section list. We represent each section by a string in a normalized form. This is done to simplify the reading of the SIMS section listing. We store a list of all these strings in the Courses. */ public void normalizeCourseText(String inFile) { theCourses = new ArrayList(); Scanner fin = null; try { fin = new Scanner(new File(inFile)); // Skip initial info written by SIMS while (true) { if (!fin.hasNextLine() ) { System.out.println("Trouble: There is no course information. Bye."); System.exit(1); } String line = fin.nextLine().trim(); if (line.indexOf("CRNCrseSect") >= 0) break; // End of header in section listing } // We are now at the beginning of the course information String a = readCourse(fin); while (a.length() != 0) { theCourses.add(a); a = readCourse(fin); } } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (fin != null) fin.close(); } } /** @param time should be of the form 10:40 @param amPm should be of the form A or P @return returns the corresponding military time as a string */ private static String computeTime(String time, String amPm) { int colon = time.indexOf(':'); if (colon < 0 ) // illegal time return "ARR"; String h = time.substring(0, colon); String m = time.substring(colon+1); try { int hour = Integer.parseInt(h); if (hour != 12 && amPm.equals("P")) hour += 12; String hh = "" + hour; if (hh.length() == 1) hh = "0"+ hh; if (m.length() == 1) m = "0" + m; return hh + ":" + m; } catch (Exception e) { return "ARR"; } } /** Convenience method used in the implementation of getTrueCourses. It returns the updated value of elementIndex */ private static int processElement(Scanner scan, CourseElement currentElement, Course currentCourse, int elementIndex) { System.out.println("Element " + elementIndex ); currentElement.campus = scan.next().charAt(0); currentElement.dayOrEvening = scan.next().charAt(0); currentElement.maxSize = scan.next(); if (currentElement.maxSize.length() == 1) currentElement.maxSize = "0" + currentElement.maxSize; String extraDay = ""; String extraExtraDay = ""; currentElement.day = scan.next().charAt(0); String next = scan.next(); char c = next.charAt(0); if (c == 'M' || c == 'T' || c == 'W' || c == 'R' || c == 'F') { extraDay += c; next = scan.next(); } c = next.charAt(0); if (c == 'M' || c == 'T' || c == 'W' || c == 'R' || c == 'F') { extraExtraDay += c; next = scan.next(); } currentElement.startTime = computeTime(next, scan.next()); currentElement.endTime = computeTime(scan.next(), scan.next()); if (scan.hasNext()) currentElement.building = scan.next(); if (scan.hasNext()) currentElement.room = scan.next(); // Collecting the instructor names int k = 0; String previous = ""; while (scan.hasNext()) { String ie = scan.next(); if (k < 2) {currentElement.instructors[0] += ie + " ";} else if (k == 2) { if ( ie.length() < 2 || (ie.length() == 2 && ie.indexOf(".") >= 0) || !scan.hasNext() || previous.length() <= 2 || ie.equals("ARNIOKLD")) // SORRY, but can't help it! currentElement.instructors[0] += ie + " "; else currentElement.instructors[1] += ie + " "; } else {currentElement.instructors[1] += ie + " ";} k++; previous = ie; } // Dealing with multiple days with same schedule, like T R or M W F if (extraDay.length() > 0 ) { // there is a second day specified for this class currentCourse.elements[elementIndex] = new CourseElement(currentElement); currentCourse.elements[elementIndex].day = extraDay.charAt(0); elementIndex++; } if (extraExtraDay.length() > 0 ) { // there is a third day specified for this class currentCourse.elements[elementIndex] = new CourseElement(currentElement); currentCourse.elements[elementIndex].day = extraExtraDay.charAt(0); elementIndex++; } return elementIndex; } /** Here we do the heavy lifting: we take the normalized text information about courses and their elements as stored in theCourses, and we build the corresponding Course objects in trueCourses. */ public void getTrueCourses() { trueCourses = new ArrayList(); Course currentCourse = null; // The course we are building int elementIndex = 0; // The index of the next course element for (String a: theCourses) { Scanner scan = new Scanner(a); String next = scan.next(); CourseElement currentElement; if (next.equals("R") || next.equals("C") || next.equals("O") || next.equals("A") || next.equals("P") || next.equals("X") ){ // we are starting a new course if (elementIndex > 0) { // i.e. we are not at the beginning trueCourses.add(currentCourse); elementIndex = 0; } currentCourse = new Course(); elementIndex = 0; currentCourse.elements[elementIndex] = new CourseElement(); currentElement = currentCourse.elements[elementIndex]; currentElement.parent = currentCourse; elementIndex++; currentElement.kind = 'B'; currentCourse.status = next.charAt(0); currentCourse.crn = scan.next(); currentCourse.courseId = scan.next(); currentCourse.sectionId = scan.next(); System.out.println("courseId: " + currentCourse.courseId + " sectionId: " + currentCourse.sectionId); while (true) { String token = scan.next(); currentCourse.title += token; if (token.indexOf("...") >= 0) break; } elementIndex = processElement(scan, currentElement, currentCourse, elementIndex); } else if (next.equals(currentCourse.crn)) { // another element for the current course // skip courseId+sectionId scan.next(); scan.next(); currentCourse.elements[elementIndex] = new CourseElement(); currentElement = currentCourse.elements[elementIndex]; currentElement.parent = currentCourse; elementIndex++; elementIndex = processElement(scan, currentElement, currentCourse, elementIndex); } } if (currentCourse != null) trueCourses.add(currentCourse); } /** It writes out to SIMS-sessionName-LOADS.html in sorted the teaching load of each instructor */ public void HTMLFacultyLoad( ) { PrintWriter fout = null; try { fout = new PrintWriter(new File("SIMS-" + sessionName + "-LOADS.html")); fout.println("\n\n

" + sessionName + "

    "); fout.println("We only list courses with scheduled meeting times"); Iterator firsts = instructors.iterator(); while (firsts.hasNext()) { String who = firsts.next(); ArrayList ac = instructorCourses.get(who); Course[] aa = new Course[ac.size()]; ac.toArray(aa); Arrays.sort(aa); String who_ = who.replace(' ', '_'); fout.println("

  • " + who + ""); for (Course c: aa) { String s = c.status + " " + c.crn + " " + c.getName() + " " + c.elements[0].campus + " " + c.elements[0].dayOrEvening + " |" + c.title + "|"; fout.println("

    " + s + "\n

      "); for (int k = 0; k < 6; k++) { CourseElement e = c.elements[k]; if (e != null) { s = e.maxSize + " " + e.day + " " + e.startTime + "-" + e.endTime + " " + e.getRoom(); fout.println("
      " + s); } } fout.println("
    "); } } fout.println("
"); } catch (IOException e) { e.printStackTrace(); return; } finally { if (fout != null) fout.close(); } } /** Given the name of a room, say TL0302, and the list of corresponding course elements saves to the file TL0302.html a table with the schedule of that room */ public void HTMLOfRoom(String roomName, ArrayList roomElems) { String[][] table = new String[times.length][5];//5 are the days // Populate table with default data for (int day = 0; day < table[0].length; day++) { for (int time = 0; time < table.length; time++) { table[time][day] = " "; } } // Populate table with information from roomElems if (roomElems != null) { for (CourseElement e: roomElems) { char d = e.day; int day = (d == 'M')?0:(d == 'T')?1:(d == 'W')?2:(d=='R')?3:4; for (int t = 0; t < table.length; t++) { //GPI if (e.startTime.compareTo(times[t]) <= 0 && e.endTime.compareTo(times[t]) >= 0) { if (table[t][day].equals(" ")) table[t][day] = e.parent.getName(); else table[t][day] += "/" + e.parent.getName(); } } } } // Format in HTML the table and output it PrintWriter fout = null; try { fout = new PrintWriter(new File("SIMS-" + sessionName + "-" + roomName + ".html")); fout.println("\n"); fout.println(""); fout.println(""); fout.println(""); for (int k = 0; k < table.length; k++) { fout.print(""); for (int j = 0; j < table[0].length; j++) { fout.print(""); } fout.println(""); } fout.println("
" + sessionName + " " + roomName + "
MONDAYTUESDAYWEDNESDAYTHURSDAYFRIDAY
" + times[k] + "" + table[k][j] + "
\n\n"); } catch (IOException e) { e.printStackTrace(); return; } finally { if (fout != null) fout.close(); } } /** If the current session is, say S2007, it creates the file SIMS-S2007-ROOMS.html, and lists there the rooms used in the current session and uses each room to point to the corresponding schedule, say for room TL00302, to SIMS-S2007-TL00302.html */ public void HTMLRooms() { PrintWriter fout = null; try { fout = new PrintWriter(new File("SIMS-" + sessionName + "-ROOMS.html")); fout.println("\n\n

" + sessionName + "

    "); Iterator first = rooms.iterator(); while (first.hasNext()) { String room = first.next(); String who = "SIMS-" + sessionName + "-" + room + ".html"; fout.println("
  • " + room + ""); } fout.println("
"); } catch (IOException e) { e.printStackTrace(); return; } finally { if (fout != null) fout.close(); } } /** It prints for each time slot timeXday the courses at that time and the romm they are held in */ public void HTMLOfSession() { String[][] table = new String[times.length][5];//5 are the days // Populate table with default data for (int day = 0; day < table[0].length; day++) { for (int time = 0; time < table.length; time++) { table[time][day] = " "; } } // Now populate table with scheduling info Iterator firsts = rooms.iterator(); while (firsts.hasNext()) { String roomName = firsts.next(); ArrayList roomElems = roomElements.get(roomName); // Populate table with information from roomElems if (roomElems != null) { for (CourseElement e: roomElems) { char d = e.day; int day = (d == 'M')?0:(d == 'T')?1:(d == 'W')?2:(d=='R')?3:4; for (int t = 0; t < table.length; t++) { //GPI if (e.startTime.compareTo(times[t]) <= 0 && e.endTime.compareTo(times[t]) >= 0) { if (table[t][day].equals(" ")) table[t][day] = e.parent.getName() + "-" + roomName; else table[t][day] += " " + e.parent.getName() +"-" + roomName; } } } } } // Format in HTML the table and output it PrintWriter fout = null; try { fout = new PrintWriter(new File("SIMS-" + sessionName + "-SESSION.html")); fout.println("\n"); fout.println(""); fout.println(""); fout.println(""); for (int k = 0; k < table.length; k++) { fout.print(""); for (int j = 0; j < table[0].length; j++) { fout.print(""); } fout.println(""); } fout.println("
" + sessionName + " SESSION
MONDAYTUESDAYWEDNESDAYTHURSDAYFRIDAY
" + times[k] + "" + table[k][j] + "
\n\n"); } catch (IOException e) { e.printStackTrace(); return; } finally { if (fout != null) fout.close(); } } /** If the current session is, say S2007, it creates the file SIMS-S2007-INSTRUCTORS.html, and lists there the instructors in the current session and uses each instructor to point to the corresponding course load within SIMS-S2007-LOADS.html */ public void HTMLInstructors() { PrintWriter fout = null; try { fout = new PrintWriter(new File("SIMS-" + sessionName + "-INSTRUCTORS.html")); fout.println("\n\n

" + sessionName + "

    "); String file = "SIMS-" + sessionName + "-LOADS.html"; Iterator first = instructors.iterator(); while (first.hasNext()) { String who = first.next(); String who_ = who.replace(' ', '_'); fout.println("
  • " + who + ""); } fout.println("
"); } catch (IOException e) { e.printStackTrace(); return; } finally { if (fout != null) fout.close(); } } /** If the current session is S2007, it creates the file SIMS-S2008-COURSES.html and writes there information about all the courses */ public void HTMLCourses() { Course[] aa = new Course[trueCourses.size()]; trueCourses.toArray(aa); Arrays.sort(aa); PrintWriter fout = null; try { fout = new PrintWriter(new File("SIMS-" + sessionName + "-COURSES.html")); fout.println("\n\n

" + sessionName + "

    "); fout.println("We only list courses with scheduled meeting times"); for (Course c: aa) { if (isLegalCourse(c)) { String s = c.status + " " + c.crn + " " + c.getName() + " " + c.elements[0].campus + " " + c.elements[0].dayOrEvening + " |" + c.title + "| " + c.elements[0].instructors[0] + " " + c.elements[0].instructors[1]; fout.println("

    " + s + "\n

      "); for (int k = 0; k < 6; k++) { CourseElement e = c.elements[k]; if (e != null) { s = e.maxSize + " " + e.day + " " + e.startTime + "-" + e.endTime + " " + e.getRoom(); fout.println("
      " + s); } } fout.println("
    "); } } fout.println("
"); } catch (IOException e) { e.printStackTrace(); return; } finally { if (fout != null) fout.close(); } } /** A course we wish to consider - self evident */ public static boolean isLegalCourse(Course c) { return c != null && c.status != 'X' && c.elements[0].campus != 'J'; } /** it collects in instructors and rooms the appropriate information from cc */ public void collect() { instructors = new TreeSet(); rooms = new TreeSet(); for (Course c: trueCourses) { if (isLegalCourse(c)) { for (CourseElement e: c.elements) { if (e != null) { String room = e.getRoom(); if (!room.equals("ARR")) rooms.add(room); } if (e != null && e.instructors != null ) { if (e.instructors[0] != null && !e.instructors[0].equals("")) instructors.add(e.instructors[0]); if (e.instructors[0] != null && !e.instructors[1].equals("")) instructors.add(e.instructors[1]); } } } } } /** It determines for each instructor the courses taught by that instructor */ public void coursesOfInstructors() { instructorCourses = new HashMap>(2*instructors.size(), 0.5f); for (String first: instructors) { if (!first.equals("")) instructorCourses.put(first, new ArrayList()); } for (Course c: trueCourses) { if (isLegalCourse(c)) { CourseElement e = c.elements[0]; if (e != null) { String first = e.instructors[0]; if (first != null && !first.equals("")) instructorCourses.get(first).add(c); String second = e.instructors[1]; if (second != null && !second.equals("")) instructorCourses.get(second).add(c); } } } } /** It determines for each room the course elements scheduled in that room */ public void elementsOfRooms() { roomElements = new HashMap>(6*rooms.size(), 0.5f); for (String r: rooms) { roomElements.put(r, new ArrayList()); } for (Course c: trueCourses) { if (isLegalCourse(c)) { for (CourseElement e: c.elements) { if (e != null && e.startTime != null && !e.startTime.equals("")) { String room = e.getRoom(); if (!room.equals("ARR")) { roomElements.get(room).add(e); } } } } } } public Session9(){} /** For the specified SIMS file fileIn it creates all the needed pages about courses, instructors, their loads, room, and their schedules */ public Session9(String fileIn) { int d = fileIn.indexOf("."); if (d < 0) return; sessionName = fileIn.substring(5, d); normalizeCourseText(fileIn); getTrueCourses(); collect(); coursesOfInstructors(); elementsOfRooms(); // Create HTML pages for schedules of rooms // SIMS-sessionName-roomName.html Iterator firsts = rooms.iterator(); while (firsts.hasNext()) { String who = firsts.next(); ArrayList ac = roomElements.get(who); HTMLOfRoom(who, roomElements.get(who)); } // and page to point to those schedules SIMS-sessionName-ROOMS.html HTMLRooms(); // Create page with instructors pointing to their teaching loads // SIMS-sessionName-INSTRUCTORS.html HTMLInstructors(); // Create page with teaching loads SIMS-sessionName-LOADS.html HTMLFacultyLoad( ); // Create page with all the courses SIMS-sessionName-COURSES.html HTMLCourses(); // Create page with a table of timeXday with all the courses at a // particular time slot HTMLOfSession(); } public static void main(String[] args) { scan = new Scanner(System.in); while (true) { System.out.print("Enter name of file to be analyzed[SIMS-XXXXX.txt or empty string to terminate]: "); String fileIn = scan.nextLine().trim(); if (fileIn.length() <= 5 || !"SIMS-".equals(fileIn.substring(0,5))) break; Session9 session = new Session9(fileIn); if (session.trueCourses != null) System.out.println("We have now information for " + session.trueCourses.size() + " courses"); else System.out.println("Non existent or non accessible file"); } System.out.println("Goodbye"); } }