From ec818de8d2ea7c4a571f34a76b265cb47ed64b15 Mon Sep 17 00:00:00 2001 From: william-lyh Date: Mon, 1 Apr 2024 14:11:29 -0700 Subject: [PATCH 1/2] API v2 - add support for JSON arg input --- progressReport/app.py | 88 ++++++++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 23 deletions(-) diff --git a/progressReport/app.py b/progressReport/app.py index d5c857b..4a85c5c 100644 --- a/progressReport/app.py +++ b/progressReport/app.py @@ -65,8 +65,7 @@ app = Flask(__name__) -@app.route('/', methods=["GET"]) -def index(): +def render(school_name, course_name, student_mastery, class_mastery, use_json=False): def assign_node_levels(node, student_levels_count, class_levels_count): nonlocal student_mastery, class_mastery if not node["children"]: @@ -93,28 +92,64 @@ def assign_node_levels(node, student_levels_count, class_levels_count): node["class_level"] = sum(children_class_levels) // len(children_class_levels) return node["student_level"], node["class_level"] - school_name = request.args.get("school", "Berkeley") - course_name = request.args.get("class", "CS10") - student_mastery = request.args.get("student_mastery", "000000") - class_mastery = request.args.get("class_mastery", "") - use_url_class_mastery = True if class_mastery != "" else False - if not student_mastery.isdigit(): - return "URL parameter student_mastery is invalid", 400 - if use_url_class_mastery and not class_mastery.isdigit(): - return "URL parameter class_mastery is invalid", 400 + def assign_node_levels_json(node, student_mastery, class_mastery, student_levels_count, class_levels_count): + if not node["children"]: + if node["name"] in student_mastery: + node["student_level"] = int(student_mastery[node["name"]]) \ + if int(student_mastery[node["name"]]) < student_levels_count \ + else student_levels_count - 1 + else: + node["student_level"] = 0 + if node["name"] in class_mastery: + node["class_level"] = int(class_mastery[node["name"]]) \ + if int(class_mastery[node["name"]]) < class_levels_count \ + else class_levels_count - 1 + else: + node["class_level"] = 0 + else: + children_student_levels = [] + children_class_levels = [] + for child in node["children"]: + student_level, class_level = assign_node_levels_json(child, student_mastery, class_mastery, + student_levels_count, class_levels_count) + children_student_levels.append(student_level) + children_class_levels.append(class_level) + node["student_level"] = sum(children_student_levels) // len(children_student_levels) + node["class_level"] = sum(children_class_levels) // len(children_class_levels) + return node["student_level"], node["class_level"] + + if not use_json: + use_url_class_mastery = True if class_mastery != "" else False + if not student_mastery.isdigit(): + return "URL parameter student_mastery is invalid", 400 + if use_url_class_mastery and not class_mastery.isdigit(): + return "URL parameter class_mastery is invalid", 400 + else: + if not isinstance(student_mastery, dict): + return "URL parameter student_mastery is invalid", 400 + if not isinstance(class_mastery, dict): + return "URL parameter class_mastery is invalid", 400 + use_url_class_mastery = True if len(class_mastery) > 0 else False + parser.generate_map(school_name=secure_filename(school_name), course_name=secure_filename(course_name), render=True) try: with open("data/{}_{}.json".format(secure_filename(school_name), secure_filename(course_name))) as data_file: course_data = json.load(data_file) except FileNotFoundError: return "Class not found", 400 + start_date = course_data["start date"] course_term = course_data["term"] class_levels = course_data["class levels"] student_levels = course_data["student levels"] course_node_count = course_data["count"] course_nodes = course_data["nodes"] - assign_node_levels(course_nodes, len(student_levels), len(class_levels)) + + if not use_json: + assign_node_levels(course_nodes, len(student_levels), len(class_levels)) + else: + assign_node_levels_json(course_nodes, student_mastery, class_mastery, len(student_levels), len(class_levels)) + return render_template("web_ui.html", start_date=start_date, course_name=course_name, @@ -126,17 +161,24 @@ def assign_node_levels(node, student_levels_count, class_levels_count): course_data=course_nodes) -@app.route('/parse', methods=["POST"]) -def parse(): - school_name = request.args.get("school_name", "Berkeley") - course_name = request.form.get("course_name", "CS10") - parser.generate_map(school_name=secure_filename(school_name), course_name=secure_filename(course_name), render=False) - try: - with open("data/{}_{}.json".format(secure_filename(school_name), secure_filename(course_name))) as data_file: - course_data = json.load(data_file) - except FileNotFoundError: - return "Class not found", 400 - return course_data +@app.route('/', methods=["GET"]) +def index(): + school_name = request.args.get("school", "Berkeley") + course_name = request.args.get("class", "CS10") + student_mastery = request.args.get("student_mastery", "0") + class_mastery = request.args.get("class_mastery", "0") + return render(school_name, course_name, student_mastery, class_mastery) + +@app.route('/json', methods=["POST"]) +def index_json(): + args_json = request.get_json() + if args_json is None: + return "URL JSON parameter is invalid", 400 + school_name = args_json["school"] if "school" in args_json else "Berkeley" + course_name = args_json["class"] if "class" in args_json else "CS10" + student_mastery = args_json["student_mastery"] if "student_mastery" in args_json else {} + class_mastery = args_json["class_mastery"] if "class_mastery" in args_json else {} + return render(school_name, course_name, student_mastery, class_mastery, use_json=True) if __name__ == '__main__': From 277f0db9eb31dbd1e5e23276d0cbfd01bac6cc48 Mon Sep 17 00:00:00 2001 From: william-lyh Date: Wed, 10 Apr 2024 12:06:03 -0700 Subject: [PATCH 2/2] change POST return to redirect --- progressReport/app.py | 82 ++++++++++++++++++++++++------------------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/progressReport/app.py b/progressReport/app.py index 4a85c5c..48a0eb3 100644 --- a/progressReport/app.py +++ b/progressReport/app.py @@ -1,4 +1,4 @@ -from flask import Flask, request, render_template +from flask import Flask, request, render_template, redirect, url_for from werkzeug.utils import secure_filename import json import os @@ -92,32 +92,6 @@ def assign_node_levels(node, student_levels_count, class_levels_count): node["class_level"] = sum(children_class_levels) // len(children_class_levels) return node["student_level"], node["class_level"] - def assign_node_levels_json(node, student_mastery, class_mastery, student_levels_count, class_levels_count): - if not node["children"]: - if node["name"] in student_mastery: - node["student_level"] = int(student_mastery[node["name"]]) \ - if int(student_mastery[node["name"]]) < student_levels_count \ - else student_levels_count - 1 - else: - node["student_level"] = 0 - if node["name"] in class_mastery: - node["class_level"] = int(class_mastery[node["name"]]) \ - if int(class_mastery[node["name"]]) < class_levels_count \ - else class_levels_count - 1 - else: - node["class_level"] = 0 - else: - children_student_levels = [] - children_class_levels = [] - for child in node["children"]: - student_level, class_level = assign_node_levels_json(child, student_mastery, class_mastery, - student_levels_count, class_levels_count) - children_student_levels.append(student_level) - children_class_levels.append(class_level) - node["student_level"] = sum(children_student_levels) // len(children_student_levels) - node["class_level"] = sum(children_class_levels) // len(children_class_levels) - return node["student_level"], node["class_level"] - if not use_json: use_url_class_mastery = True if class_mastery != "" else False if not student_mastery.isdigit(): @@ -136,7 +110,7 @@ def assign_node_levels_json(node, student_mastery, class_mastery, student_levels with open("data/{}_{}.json".format(secure_filename(school_name), secure_filename(course_name))) as data_file: course_data = json.load(data_file) except FileNotFoundError: - return "Class not found", 400 + return "Course not found", 400 start_date = course_data["start date"] course_term = course_data["term"] @@ -145,10 +119,7 @@ def assign_node_levels_json(node, student_mastery, class_mastery, student_levels course_node_count = course_data["count"] course_nodes = course_data["nodes"] - if not use_json: - assign_node_levels(course_nodes, len(student_levels), len(class_levels)) - else: - assign_node_levels_json(course_nodes, student_mastery, class_mastery, len(student_levels), len(class_levels)) + assign_node_levels(course_nodes, len(student_levels), len(class_levels)) return render_template("web_ui.html", start_date=start_date, @@ -160,11 +131,43 @@ def assign_node_levels_json(node, student_mastery, class_mastery, student_levels course_node_count=course_node_count, course_data=course_nodes) +def parse_json_mastery(school_name, course_name, student_mastery_json, class_mastery_json): + def assign_node_levels_json(node, student_levels_count, class_levels_count): + nonlocal student_mastery, class_mastery + if not node["children"]: + if node["name"] in student_mastery_json and isinstance(student_mastery_json[node["name"]], int): + student_mastery += str(student_mastery_json[node["name"]]) \ + if student_mastery_json[node["name"]] < student_levels_count \ + else student_levels_count - 1 + else: + student_mastery += "0" + if node["name"] in class_mastery_json and isinstance(class_mastery_json[node["name"]], int): + class_mastery += str(class_mastery_json[node["name"]]) \ + if class_mastery_json[node["name"]] < class_levels_count \ + else class_levels_count - 1 + else: + class_mastery += "0" + else: + for child in node["children"]: + assign_node_levels_json(child, student_levels_count, class_levels_count) + return + + parser.generate_map(school_name=secure_filename(school_name), course_name=secure_filename(course_name), render=True) + try: + with open("data/{}_{}.json".format(secure_filename(school_name), secure_filename(course_name))) as data_file: + course_data = json.load(data_file) + except FileNotFoundError: + return None, None + course_nodes = course_data["nodes"] + student_mastery, class_mastery = "", "" + assign_node_levels_json(course_nodes, len(course_data["student levels"]), len(course_data["class levels"])) + return student_mastery, class_mastery + @app.route('/', methods=["GET"]) def index(): school_name = request.args.get("school", "Berkeley") - course_name = request.args.get("class", "CS10") + course_name = request.args.get("course", "CS10") student_mastery = request.args.get("student_mastery", "0") class_mastery = request.args.get("class_mastery", "0") return render(school_name, course_name, student_mastery, class_mastery) @@ -175,10 +178,15 @@ def index_json(): if args_json is None: return "URL JSON parameter is invalid", 400 school_name = args_json["school"] if "school" in args_json else "Berkeley" - course_name = args_json["class"] if "class" in args_json else "CS10" - student_mastery = args_json["student_mastery"] if "student_mastery" in args_json else {} - class_mastery = args_json["class_mastery"] if "class_mastery" in args_json else {} - return render(school_name, course_name, student_mastery, class_mastery, use_json=True) + course_name = args_json["course"] if "course" in args_json else "CS10" + student_mastery_json = args_json["student_mastery"] if "student_mastery" in args_json else {} + class_mastery_json = args_json["class_mastery"] if "class_mastery" in args_json else {} + student_mastery, class_mastery = parse_json_mastery(school_name, course_name, + student_mastery_json, class_mastery_json) + if student_mastery is None or class_mastery is None: + return "Course not found", 400 + return redirect(url_for("index", school=school_name, course=course_name, + student_mastery=student_mastery, class_mastery=class_mastery)) if __name__ == '__main__':