def generate_scales(semester): scales = OrderedDict() scales_path = "./data/"+semester+"/outputs/scales.json" default_scales_path = "./resources/scales.json" if not os.path.exists(scales_path): scales = load_json(default_scales_path) else: scales = load_json(scales_path) if not scales: scales = OrderedDict() q = "Remove this example question - How do you rate the course in general? (Add questions like this)" scales[q] = OrderedDict() convert_answer_case(scales) responses_path = "./data/"+semester+"/outputs/responses/" for (dirpath, dirnames, filenames) in os.walk(responses_path): for filename in filenames: if filename.endswith(".json"): file_path = path_join(dirpath,filename) scales_add_course(file_path, scales) break default_sort_scales(scales) try: autofill_scales(scales) except AutofillException: save_prompt_exit(scales, scales_path) dump_json(scales, scales_path) if print_error_check(scales): print("One or more inconsistency detected in " + scales_path) print("You will have to edit the file manually to add/edit/remove questions.") sys.exit(1)
def web_reports_semester_folder(semester_path): semester = os.path.basename(semester_path) courses = load_json(semester_path + "/outputs/courses.json") scales = load_json(semester_path + "/outputs/scales.json") stats_path = semester_path + "/outputs/stats/" summaries_path = semester_path + "/outputs/web/converted" upload_path = semester_path + "/outputs/web/upload/" + semester html_templates = {} with open("./resources/web/course-no.html", 'r') as f: html_templates["NO"] = f.read() with open("./resources/web/course-en.html", 'r') as f: html_templates["EN"] = f.read() with open("./resources/web/semester-index.html", 'r') as f: html_templates["index"] = f.read() with open("./resources/web/semester-index-eng.html", 'r') as f: html_templates["index-eng"] = f.read() with open("./data/courses.json", 'r') as f: courses_all = json.load(f, object_pairs_hook=OrderedDict) links = [] links.append('<ul class="fui_courses">') for course_code in courses: summary_path = path_join(summaries_path, course_code + ".html") stat_path = path_join(stats_path, course_code + ".json") output_path = path_join(upload_path, course_code + ".html") res = web_report_course(summary_path, stat_path, output_path, html_templates, courses_all, scales, semester) if res: course_name = courses[course_code]["course"]["name"] links.append('<li><a href="' + course_code + '.html">' + course_code + ' - ' + course_name + '</a></li>') links.append("</ul>") links_str = "\n".join(links) letter, year = semester[0], semester[1:] title = {} if letter == "H": title["NO"] = "Høst " + year title["EN"] = "Fall " + year elif letter == "V": title["NO"] = "Vår " + year title["EN"] = "Spring " + year else: print("Error: unknown semester format: " + semester) sys.exit(1) links_str_no = "<h2>{}</h2>".format(title["NO"]) + links_str links_str_en = "<h2>{}</h2>".format(title["EN"]) + links_str index_html = html_templates["index"].replace("$COURSE_INDEX", links_str_no) index_eng_html = html_templates["index-eng"].replace( "$COURSE_INDEX", links_str_en) index_html = index_html.replace("$SEMESTER", semester) index_eng_html = index_eng_html.replace("$SEMESTER", semester) with open(upload_path + "/index.html", "w") as f: f.write(index_html) with open(upload_path + "/index-eng.html", "w") as f: f.write(index_eng_html)
def generate_stats_semester(semester_path, semester_name): scales_path = semester_path + "/outputs/scales.json" scales = load_json(scales_path) course_names = load_json("./resources/course_names/all.json") generate_stats_dir(semester_path + "/outputs/responses", semester_path + "/downloads/participation", semester_path + "/outputs/stats", scales, course_names, semester_name)
def generate_stats_semester(semester_path, semester_name): scales_path = semester_path+"/outputs/scales.json" scales = load_json(scales_path) course_names = load_json("./resources/course_names/all.json") generate_stats_dir(semester_path+"/outputs/responses", semester_path+"/downloads/participation", semester_path+"/outputs/stats", scales, course_names, semester_name)
def web_reports_semester_folder(semester_path): semester = os.path.basename(semester_path) courses = load_json(semester_path+"/outputs/courses.json") scales = load_json(semester_path+"/outputs/scales.json") stats_path = semester_path+"/outputs/stats/" summaries_path = semester_path+"/outputs/web/converted" upload_path = semester_path+"/outputs/web/upload/"+semester html_templates = {} with open("./resources/web/course-no.html",'r') as f: html_templates["NO"] = f.read() with open("./resources/web/course-en.html",'r') as f: html_templates["EN"] = f.read() with open("./resources/web/semester-index.html",'r') as f: html_templates["index"] = f.read() with open("./resources/web/semester-index-eng.html",'r') as f: html_templates["index-eng"] = f.read() with open("./data/courses.json",'r') as f: courses_all = json.load(f, object_pairs_hook=OrderedDict) links = [] links.append('<ul class="fui_courses">') for course_code in courses: summary_path = path_join(summaries_path, course_code+".html") stat_path = path_join(stats_path, course_code+".json") output_path = path_join(upload_path, course_code+".html") res = web_report_course(summary_path, stat_path, output_path, html_templates, courses_all, scales, semester) if res: course_name = courses[course_code]["course"]["name"] links.append('<li><a href="'+course_code+'.html">' + course_code + ' - ' + course_name + '</a></li>') links.append("</ul>") links_str = "\n".join(links) letter, year = semester[0],semester[1:] title = {} if letter == "H": title["NO"] = "Høst "+year title["EN"] = "Fall "+year elif letter == "V": title["NO"] = "Vår "+year title["EN"] = "Spring "+year else: print("Error: unknown semester format: " + semester) sys.exit(1) links_str_no = "<h2>{}</h2>".format(title["NO"]) + links_str links_str_en = "<h2>{}</h2>".format(title["EN"]) + links_str index_html = html_templates["index"].replace("$COURSE_INDEX", links_str_no) index_eng_html = html_templates["index-eng"].replace("$COURSE_INDEX", links_str_en) index_html = index_html.replace("$SEMESTER", semester) index_eng_html = index_eng_html.replace("$SEMESTER", semester) with open(upload_path+"/index.html", "w") as f: f.write(index_html) with open(upload_path+"/index-eng.html", "w") as f: f.write(index_eng_html)
def get_course_data(path): course = load_json(path) language = course["language"] if language == "NO": general_questions = [ "Hva er ditt generelle intrykk av kurset?", "Hva er ditt generelle inntrykk av kurset?" ] elif language == "EN": general_questions = [ "How do you rate the course in general?", "What is your general impression of the course?" ] else: print("Unknown language: " + str(language)) print("Path:" + str(path)) print("JSON:") print(json.dumps(course, indent=2)) sys.exit(1) for general_question in general_questions: if general_question in course["questions"]: course[general_question] = course["questions"][general_question] break del course["questions"] return course
def generate_plots(courses, scales, semester_name): semester = load_json("./data/" + semester_name + "/outputs/courses.json") courses_to_plot = list(semester.keys()) outdir = "".join(["./data/", semester_name, "/outputs/plots/"]) if not os.path.exists(outdir): os.makedirs(outdir) for c in courses_to_plot: plot_course(c, courses, outdir, scales, semester_name)
def generate_stats_file(responses_path, participation_path, output_path, scales, course): responses = load_json(responses_path) participation = load_json(participation_path) stats = OrderedDict() stats["course"] = course stats = generate_stats(responses, participation, scales, stats) if not stats: print("Skipping course with 0 answers:") print(json.dumps(course, indent=2)) return if not stats["language"]: print("Unable to detect language in course:") print(json.dumps(course, indent=2)) print("This most likely means that the questions have changed and need to be added to scales.json") sys.exit(1) dump_json(stats, output_path)
def read_course_names(semester): if semester.startswith('V'): filename = 'spring.json' elif semester.startswith('H'): filename = 'fall.json' else: print('Error: Invalid semester value, ' + semester) sys.exit() json_names = load_json('./resources/course_names/' + filename) return list(json_names.keys())
def generate_stats_file(responses_path, participation_path, output_path, scales, course): responses = load_json(responses_path) participation = load_json(participation_path) stats = OrderedDict() stats["course"] = course stats = generate_stats(responses, participation, scales, stats) if not stats: print("Skipping course with 0 answers:") print(json.dumps(course, indent=2)) return if not stats["language"]: print("Unable to detect language in course:") print(json.dumps(course, indent=2)) print( "This most likely means that the questions have changed and need to be added to scales.json" ) sys.exit(1) dump_json(stats, output_path)
def generate_scales(semester): scales = OrderedDict() scales_path = "./data/" + semester + "/outputs/scales.json" default_scales_path = "./resources/scales.json" if not os.path.exists(scales_path): scales = load_json(default_scales_path) else: scales = load_json(scales_path) if not scales: scales = OrderedDict() q = "Remove this example question - How do you rate the course in general? (Add questions like this)" scales[q] = OrderedDict() convert_answer_case(scales) responses_path = "./data/" + semester + "/outputs/responses/" for (dirpath, dirnames, filenames) in os.walk(responses_path): for filename in filenames: if filename.endswith(".json"): file_path = path_join(dirpath, filename) scales_add_course(file_path, scales) break default_sort_scales(scales) try: autofill_scales(scales) except AutofillException: save_prompt_exit(scales, scales_path) dump_json(scales, scales_path) if print_error_check(scales): print("One or more inconsistency detected in " + scales_path) print( "You will have to edit the file manually to add/edit/remove questions." ) sys.exit(1)
def scales_add_course(response_file_path, scales): course = load_json(response_file_path) for question, answers in course.items(): if question in scales: if "order" not in scales[question]: scales[question]["order"] = ["EDIT THIS, as well as ignore, see README.md."] if "all" not in scales[question]: scales[question]["all"] = [] if "ignore" not in scales[question]: scales[question]["ignore"] = [] for answer in answers: answer_cap = answer_case(answer) if answer_cap not in scales[question]["all"]: scales[question]["all"].append(answer_cap) print('Warning: Adding "{}" to "{}", you will probably have to update scales.json'.format(answer_cap, question))
def scales_add_course(response_file_path, scales): course = load_json(response_file_path) for question, answers in course.items(): if question in scales: if "order" not in scales[question]: scales[question]["order"] = [ "EDIT THIS, as well as ignore, see README.md." ] if "all" not in scales[question]: scales[question]["all"] = [] if "ignore" not in scales[question]: scales[question]["ignore"] = [] for answer in answers: answer_cap = answer_case(answer) if answer_cap not in scales[question]["all"]: scales[question]["all"].append(answer_cap) print( 'Warning: Adding "{}" to "{}", you will probably have to update scales.json' .format(answer_cap, question))
def get_course_data(path): course = load_json(path) language = course["language"] if language == "NO": general_questions = ["Hva er ditt generelle intrykk av kurset?", "Hva er ditt generelle inntrykk av kurset?"] elif language == "EN": general_questions = ["How do you rate the course in general?", "What is your general impression of the course?"] else: print("Unknown language: " + str(language)) print("Path:" + str(path)) print("JSON:") print(json.dumps(course, indent=2)) sys.exit(1) for general_question in general_questions: if general_question in course["questions"]: course[general_question] = course["questions"][general_question] break del course["questions"] return course
def participation_summary(input_path, output_path): semester = load_json(input_path) #if not os.path.exists(output_path): with open(output_path, "w") as f: f.write("\n".join([ r"\begin{table}[H]", r"\centering", r"\begin{tabular}{|l|c|c|c|}" ]) + "\n") f.write("\n".join([ r"\hline", r"Kurs & Respondenter & Inviterte & Prosent\\ \hline", "" ])) for course_code, content in semester.items(): answered = int(content["respondents"]["answered"]) invited = int(content["respondents"]["invited"]) if invited < 100: continue participation = "{0:.1f}\%".format(100 * answered / invited) f.write(" " + " & ".join( [course_code, str(answered), str(invited), participation])) f.write(r" \\ \hline" + "\n") f.write("\n".join([r"\end{tabular}", r"\end{table}"]))
def course_divide(semester, num): p = "./data/" + semester + "/outputs/courses.json" semester = load_json(p) courses = [] for name, data in semester.items(): answers = data["respondents"]["answered"] if answers > 4: courses.append((name, answers)) courses = sorted(courses, reverse=True, key=lambda x: x[1]) people = [] for i in range(num): people.append(OrderedDict()) people[-1]["name"] = "Unknown" people[-1]["answers"] = 0 people[-1]["courses"] = [] for course in courses: victim = people[0] for person in people: if person["answers"] < victim["answers"]: victim = person victim["answers"] += course[1] victim["courses"].append(course[0]) print(json.dumps(people, indent=1))
def course_divide(semester, num): p = "./data/"+semester+"/outputs/courses.json" semester = load_json(p) courses = [] for name, data in semester.items(): answers = data["respondents"]["answered"] if answers > 4: courses.append((name, answers)) courses = sorted(courses, reverse=True, key= lambda x: x[1]) people = [] for i in range(num): people.append( OrderedDict() ) people[-1]["name"] = "Unknown" people[-1]["answers"] = 0 people[-1]["courses"] = [] for course in courses: victim = people[0] for person in people: if person["answers"] < victim["answers"]: victim = person victim["answers"] += course[1] victim["courses"].append(course[0]) print(json.dumps(people, indent=1))
def web_report_course(summary_path, stat_path, output_path, html_templates, courses, scales, current_semester): stats = load_json(stat_path) participation = stats["respondents"] if participation["answered"] <= 4: return False course_code = stats["course"]["code"] course_name = stats["course"]["name"] semester = stats["course"]["semester"] language = stats["language"] participation_string = get_participation_string(participation, language) try: with open(summary_path,'r') as f: summary = f.read() except: print("Warning: Could not open '{}' - skipping".format(summary_path)) return False summary = summary.replace("</p>\n</blockquote>", "</blockquote>") summary = summary.replace("<blockquote>\n<p>", "<blockquote>") general_questions = get_general_questions() general_question = None for q in general_questions: if q in stats["questions"]: general_question = q break if not general_question: print("Could not find general question for {}".format(output_path)) general_average_text = stats["questions"][general_question]["average_text"] course_url = "https://www.uio.no/studier/emner/matnat/ifi/"+course_code main_contents = [] additional_js = [] if language == "NO": main_contents.append(r"<h2>Vurdering:</h2>") main_contents.append(r"Velg spørsmål for å se data fra studentenes vurdering:<br />") else: main_contents.append(r"<h2>Assessment:</h2>") main_contents.append(r"Choose a question to see data from the student assessment:<br />") options = [] questions = [] for question, question_stats in stats["questions"].items(): question_id = re.sub('[^a-z]+', '', question.lower()) chart_id = 'chart_' + question_id questions.append(''' <div id="{question_id}" class="question"> <h4>{question_label}: {question}</h4> <p>{average_label}: {average}</p> <div id="{chart_id}" class="d3kk-chart"></div> </div> '''.format( question_id=question_id, question_label='Spørsmål' if language == "NO" else 'Question', question=question, average_label='Gjennsomsnittlig svar' if language == "NO" else 'Average answer', average=question_stats["average_text"], chart_id=chart_id )) additional_js.append(create_chart_js(question, question_stats, scales, chart_id)) options.append('<option value="{}">{}</option>'.format(question_id, question)) main_contents.append('<select id="select_question" onchange="show_selected_question();">') main_contents.extend(options) main_contents.append('</select>') main_contents.append(''' <button id="button_show_all_questions" onclick="show_all_questions();">{}</button> <button id="button_hide_all_questions" onclick="show_all_questions();">{}</button> '''.format( 'Vis alle' if language == "NO" else 'Show all', 'Skjul' if language == "NO" else 'Hide' )) main_contents.extend(questions) additional_js.append(''' function show_selected_question() { var choice = document.getElementById("select_question").value; var questions = document.querySelectorAll('.question'); for (var i = 0; i < questions.length; i++) { questions[i].hidden = true; } document.querySelector('#' + choice).hidden = false; document.querySelector('#button_show_all_questions').style.display = 'inline'; document.querySelector('#button_hide_all_questions').style.display = 'none'; } function show_all_questions() { if (!document.querySelector('.question[hidden]')) { show_selected_question(); return; } var questions = document.querySelectorAll('.question'); for (var i = 0; i < questions.length; i++) { questions[i].hidden = false; } document.querySelector('#button_show_all_questions').style.display = 'none'; document.querySelector('#button_hide_all_questions').style.display = 'inline'; } show_selected_question(); ''') if language == "NO": main_contents.append(r"<h2>Oppsummering:</h2>") else: main_contents.append(r"<h2>Summary:</h2>") try: split_index = summary.index("<blockquote>") quotes = summary[split_index:] summary = summary[0:split_index] main_contents.append(summary) if language == "NO": main_contents.append(r"<h2>Sitater:</h2>") else: main_contents.append(r"<h2>Quotes:</h2>") main_contents.append(quotes) except ValueError: main_contents.append(summary) main_body = "\n".join(main_contents) course_rating = [] course_dict = courses[course_code] if int(current_semester[1:]) >= 2017: for sem in generate_semesters("V2000", "H2016"): if sem in course_dict: del course_dict[sem] for semester, semester_data in course_dict.items(): # Dirty, some courses have both english and norwegian semesters: question_text = look_for_general_question(semester_data) average = semester_data[question_text]["average"] course_rating.append([semester, round(average+1.0, 2)]) # Replace $ keywords from template html: replace_tags = { "$COURSE_CODE": course_code, "$COURSE_NAME": course_name, "$PARTICIPATION_STRING": participation_string, "$SEMESTER": semester, "$GENERAL_AVERAGE_TEXT": general_average_text, "$MAIN_BODY": main_body, "$ADDITIONAL_JS": "\n".join(additional_js), "$COURSE_URL": course_url, "$COURSE_RATING": str(course_rating).replace("'", '"') } html = html_templates[language] for tag, replacement in replace_tags.items(): html = html.replace(tag, replacement) with open(output_path,'w') as f: f.write(html) return True
def web_report_course(summary_path, stat_path, output_path, html_templates, courses, scales, current_semester): stats = load_json(stat_path) participation = stats["respondents"] if participation["answered"] <= 4: return False course_code = stats["course"]["code"] course_name = stats["course"]["name"] semester = stats["course"]["semester"] language = stats["language"] participation_string = get_participation_string(participation, language) try: with open(summary_path, 'r') as f: summary = f.read() except: print("Warning: Could not open '{}' - skipping".format(summary_path)) return False summary = summary.replace("</p>\n</blockquote>", "</blockquote>") summary = summary.replace("<blockquote>\n<p>", "<blockquote>") general_questions = get_general_questions() general_question = None for q in general_questions: if q in stats["questions"]: general_question = q break if not general_question: print("Could not find general question for {}".format(output_path)) general_average_text = stats["questions"][general_question]["average_text"] course_url = "https://www.uio.no/studier/emner/matnat/ifi/" + course_code main_contents = [] additional_js = [] if language == "NO": main_contents.append(r"<h2>Vurdering:</h2>") main_contents.append( r"Velg spørsmål for å se data fra studentenes vurdering:<br />") else: main_contents.append(r"<h2>Assessment:</h2>") main_contents.append( r"Choose a question to see data from the student assessment:<br />" ) options = [] questions = [] for question, question_stats in stats["questions"].items(): question_id = re.sub('[^a-z]+', '', question.lower()) chart_id = 'chart_' + question_id questions.append(''' <div id="{question_id}" class="question"> <h4>{question_label}: {question}</h4> <p>{average_label}: {average}</p> <div id="{chart_id}" class="d3kk-chart"></div> </div> '''.format( question_id=question_id, question_label='Spørsmål' if language == "NO" else 'Question', question=question, average_label='Gjennsomsnittlig svar' if language == "NO" else 'Average answer', average=question_stats["average_text"], chart_id=chart_id)) additional_js.append( create_chart_js(question, question_stats, scales, chart_id)) options.append('<option value="{}">{}</option>'.format( question_id, question)) main_contents.append( '<select id="select_question" onchange="show_selected_question();">') main_contents.extend(options) main_contents.append('</select>') main_contents.append(''' <button id="button_show_all_questions" onclick="show_all_questions();">{}</button> <button id="button_hide_all_questions" onclick="show_all_questions();">{}</button> '''.format('Vis alle' if language == "NO" else 'Show all', 'Skjul' if language == "NO" else 'Hide')) main_contents.extend(questions) additional_js.append(''' function show_selected_question() { var choice = document.getElementById("select_question").value; var questions = document.querySelectorAll('.question'); for (var i = 0; i < questions.length; i++) { questions[i].hidden = true; } document.querySelector('#' + choice).hidden = false; document.querySelector('#button_show_all_questions').style.display = 'inline'; document.querySelector('#button_hide_all_questions').style.display = 'none'; } function show_all_questions() { if (!document.querySelector('.question[hidden]')) { show_selected_question(); return; } var questions = document.querySelectorAll('.question'); for (var i = 0; i < questions.length; i++) { questions[i].hidden = false; } document.querySelector('#button_show_all_questions').style.display = 'none'; document.querySelector('#button_hide_all_questions').style.display = 'inline'; } show_selected_question(); ''') if language == "NO": main_contents.append(r"<h2>Oppsummering:</h2>") else: main_contents.append(r"<h2>Summary:</h2>") try: split_index = summary.index("<blockquote>") quotes = summary[split_index:] summary = summary[0:split_index] main_contents.append(summary) if language == "NO": main_contents.append(r"<h2>Sitater:</h2>") else: main_contents.append(r"<h2>Quotes:</h2>") main_contents.append(quotes) except ValueError: main_contents.append(summary) main_body = "\n".join(main_contents) course_rating = [] course_dict = courses[course_code] if int(current_semester[1:]) >= 2017: for sem in generate_semesters("V2000", "H2016"): if sem in course_dict: del course_dict[sem] for semester, semester_data in course_dict.items(): # Dirty, some courses have both english and norwegian semesters: question_text = look_for_general_question(semester_data) average = semester_data[question_text]["average"] course_rating.append([semester, round(average + 1.0, 2)]) # Replace $ keywords from template html: replace_tags = { "$COURSE_CODE": course_code, "$COURSE_NAME": course_name, "$PARTICIPATION_STRING": participation_string, "$SEMESTER": semester, "$GENERAL_AVERAGE_TEXT": general_average_text, "$MAIN_BODY": main_body, "$ADDITIONAL_JS": "\n".join(additional_js), "$COURSE_URL": course_url, "$COURSE_RATING": str(course_rating).replace("'", '"') } html = html_templates[language] for tag, replacement in replace_tags.items(): html = html.replace(tag, replacement) with open(output_path, 'w') as f: f.write(html) return True
def plot_courses(semester): semester = sys.argv[1] courses = load_json("./data/courses.json") scales = load_json("./data/" + semester + "/outputs/scales.json") generate_plots(courses, scales, semester)
def tex_combine(semester, verbose=False): semester_folder = data_folder(semester) path = semester_folder+"/resources/course_names/all.json" course_names = load_json(path) path = semester_folder + "/outputs/courses.json" semester_data = load_json(path) tex_contents = deque([]) with open(semester_folder+"/inputs/tex/header.tex") as f: tex_contents.append(f.read()) course_codes = [] for x in course_names: if x not in course_codes: course_codes.append(x) for x in semester_data: if x not in course_codes: course_codes.append(x) for course_code in course_codes: if course_code not in semester_data: continue course_data = semester_data[course_code] language = course_data["language"] if extract_number(course_code) >= 4000: langueage = "EN" else: language = "NO" path = semester_folder + "downloads/participation/" + course_code + ".json" participation_string = "" try: participation = load_json(path) if participation["answered"] <= 4: continue participation_string = get_participation_string(participation, language) except FileNotFoundError: print('Could not open '+path+' ! Skipping...') participation_string = ("\nThe course "+course_code+" numbers.json file is missing!\n") path = semester_folder + "outputs/tex/" + course_code + ".tex" try: with open(path,'r') as f: try: course_name = course_names[course_code] except KeyError: course_name = "Unknown course name" print("Warning: Unknown course name:" + course_code) tex_contents.append(r"\section{"+course_code+r" - "+course_name+r"}") tex_contents.append(r"\label{course:"+course_code+r"}") tex_contents.append(participation_string) tex_contents.append(r''' \begin{figure}[H] \begin{center} \includegraphics[width=0.99\textwidth]{../plots/COURSE.pdf} \end{center} \end{figure} '''.replace("COURSE", course_code)) tex_contents.append(f.read()) tex_contents.append(r"\newpage") except FileNotFoundError: print('Could not open '+path+' ! Skipping...') tex_contents.append("\nThe course "+course_code+" tex file is missing!\n") with open(semester_folder+"/inputs/tex/tail.tex") as f: tex_contents.append(f.read()) tex_final = "\n\n".join(tex_contents) report_folder = semester_folder + "/outputs/report/" os.makedirs(report_folder, exist_ok = True) report_name = "fui-kk_report_"+semester+".tex" with open(report_folder+report_name, 'w') as f: f.write(tex_final)
s_order = [] for i in range(start_year, stop_year): s_order.append("V" + str(i)) s_order.append("H" + str(i)) return s_order def get_semesters(path): semester_order = get_semester_order(2000, 2030) semesters = [] for root, subdirs, files in os.walk(path): semesters = list(filter(lambda x: x != ".git", subdirs)) break indices = [semester_order.index(x) for x in semesters] semesters = [x for (y, x) in sorted(zip(indices, semesters))] return semesters if __name__ == '__main__': semesters = get_semesters("./data") courses = OrderedDict() for s in semesters: p = "./data/" + s + "/outputs/courses.json" semester = load_json(p) for course in semester: if course not in courses: courses[course] = OrderedDict() courses[course][s] = semester[course] dump_json(courses, "./data/courses.json")