""" The parsing code for the ScheduleMaker. Author: David Mutchler and his colleagues. """ import dateutil.parser from typing import List from Constants import * # All constants, and only constants, are in ALL_CAPS. from Topic import Topic import re class Parser: @staticmethod def parse_first_and_last_days_of_term(lines: List[str]) -> (str, str): # CONSIDER: Reformat data to make this method less brittle. datestring = " ".join(lines[0].split()[2:]) first_day_of_term = dateutil.parser.parse(datestring).date() datestring = " ".join(lines[1].split()[2:]) last_day_of_tenth_week = dateutil.parser.parse(datestring).date() return first_day_of_term, last_day_of_tenth_week @staticmethod def parse_class_meeting_days_of_week(lines: List[str]) -> List[int]: # CONSIDER: Reformat data to make this method less brittle. class_meeting_days_of_week_text = lines[2].split()[2:] # Check for bad data: assert (len(class_meeting_days_of_week_text) == 3) for day_of_week in class_meeting_days_of_week_text: assert (day_of_week in DAYS_OF_WEEK) # Store class meeting days as integers: 0 = Monday, 1 = Tuesday, etc: class_meeting_days_of_week = [] for day_of_week in class_meeting_days_of_week_text: class_meeting_days_of_week.append( DAYS_OF_WEEK.index(day_of_week)) return class_meeting_days_of_week @staticmethod def parse_days_for_break(lines: List[str]) -> (str, str): # Days for break (Fall break, Winter break, Spring break): datestring = " ".join(lines[3].split()[2:]) start_date_of_break = dateutil.parser.parse(datestring).date() datestring = " ".join(lines[4].split()[2:]) end_date_of_break = dateutil.parser.parse(datestring).date() return start_date_of_break, end_date_of_break @staticmethod def parse_piazza_url(lines: List[str]) -> str: return lines[5].split()[2] @staticmethod def parse_session_number(lines: List[str]) -> int: session_blah = lines[0].split(":")[0] session_number = int(session_blah.split(" ")[1]) return session_number @staticmethod def parse_session_title(lines: List[str]) -> str: return lines[0].split(":")[1] @staticmethod def parse_session_type(lines: List[str]) -> SessionType: # FIXME: The following is brittle. session_title = Parser.parse_session_title(lines) topic_lines = "\n".join(lines[1:]).lower() if session_title.strip()[:5] == "Exam " \ and "practice" not in session_title.lower(): if "evening" in topic_lines.lower(): return SessionType.EVENING_EXAM else: return SessionType.IN_CLASS_EXAM if "exam" in session_title.lower() and \ "practice" in topic_lines.lower(): return SessionType.REVIEW elif "capstone project" in topic_lines.lower(): return SessionType.CAPSTONE_PROJECT else: return SessionType.REGULAR # old, throw away when change is OK # topic_lines = "\n".join(lines[1:]).lower() # if "Practice for Exam" in topic_lines: # return SessionType.REVIEW # elif "exam " in topic_lines and "evening" in topic_lines: # return SessionType.EVENING_EXAM # elif "exam" in topic_lines: # return SessionType.IN_CLASS_EXAM # elif "capstone project" in topic_lines: # return SessionType.CAPSTONE_PROJECT # else: # return SessionType.REGULAR @staticmethod def parse_topics(lines: List[str]) -> List[Topic]: topics = [] for k in range(1, len(lines)): line = lines[k] before_dash = re.sub(r"- .*$", "", line) if len(before_dash) % 2 == 0: level = len(before_dash) // 2 topic_item = re.sub(r"^ +- ", "", line) topics.append(Topic(topic_item, level)) print(level, topic_item) else: raise ValueError("Bad topic line {}: {}".format(k, lines[k])) return topics @staticmethod def parse_type_of_exam_or_review(lines: List[str]) -> ExamOrReviewType: pass @staticmethod def parse_exam_information(lines: List[str]) -> (str, str, str, str): # FIXME: the following is brittle exam_number = int(Parser.parse_session_title(lines)[6]) day_of_week = lines[1].split(": ")[1].strip() date = lines[2].split(": ")[1].strip() time = lines[3].split(": ")[1].strip() no_regular_class = lines[4].split(": ")[1].strip() return exam_number, day_of_week, date, time, no_regular_class @staticmethod def parse_sprint_number(lines: List[str]) -> int: pass