import glob import json import ntpath import os from typing import cast from canvasapi.assignment import Assignment from joint_teapot import Teapot, logger from joint_teapot.utils.main import default_repo_name_convertor, first, percentile class VE482Teapot(Teapot): def p1_check(self) -> None: fault_repos = [] for repo_name in self.gitea.get_all_repo_names(): if not repo_name.endswith("p1"): continue faults = [] succeed = self.checkout_to_repo_by_release_name(repo_name, "p1") if succeed: contain_c_file = False contain_readme_file = False for fn in glob.glob(f"{self.git.repos_dir}/{repo_name}/*"): basename = ntpath.basename(fn) if basename.endswith(".c"): contain_c_file = True if basename.lower().startswith("readme"): contain_readme_file = True if not contain_c_file: faults.append( "no C file found in root directory in release p1, " "can not compile on JOJ" ) if not contain_readme_file: faults.append( "no README file found in root directory in release p1" ) else: faults.append("no release named p1") if faults: fault_string = "" for fault in faults: fault_string += f"- {fault}\n" logger.info("\n".join(("", repo_name, "", fault_string))) self.gitea.issue_api.issue_create_issue( self.gitea.org_name, repo_name, body={ "body": fault_string, "title": "p1 submission pre-check failed", }, ) fault_repos.append(repo_name) logger.info(f"{len(fault_repos)} fault repo(s): {fault_repos}") def p1_submit(self) -> None: res_dict = {} assignment_name = "p1.3" assignment = first(self.canvas.assignments, lambda x: x.name == assignment_name) if assignment is None: logger.info(f"Canvas assignment {assignment_name} not found") return assignment = cast(Assignment, assignment) students = self.canvas.students for submission in assignment.get_submissions(): student = first(students, lambda x: x.id == submission.user_id) if student is None: continue repo_name = default_repo_name_convertor(student) + "-p1" repo_dir = os.path.join(self.git.repos_dir, repo_name) base_score, base_url = self.joj.submit_dir( "https://joj.sjtu.edu.cn/d/ve482_fall_2021/p/61c2d0b27fe7290006b27034", repo_dir, "make", ) bonus_score, bonus_url = self.joj.submit_dir( "https://joj.sjtu.edu.cn/d/ve482_fall_2021/p/61c2d49e7fe7290006b2703e", repo_dir, "make", ) total_score = base_score / 520 * 100 + bonus_score / 220 * 30 res_dict[student.sis_login_id] = total_score data = { "submission": {"posted_grade": round(total_score, 2)}, "comment": { "text_comment": ( f"base score: {base_score} / 520, url: {base_url}\n" f"bonus score: {bonus_score} / 220, url: {bonus_url}\n" f"total score: {base_score} / 520 * 100 + " f"{bonus_score} / 220 * 30" ) }, } submission.edit(**data) float_grades = list(res_dict.values()) summary = [ min(float_grades), percentile(float_grades, 0.25), percentile(float_grades, 0.5), percentile(float_grades, 0.75), max(float_grades), ] average_grade = sum(float_grades) / len(float_grades) logger.info( f"Grades summary: " f"Min: {summary[0]:.2f}, " f"Q1: {summary[1]:.2f}, " f"Q2: {summary[2]:.2f}, " f"Q3: {summary[3]:.2f}, " f"Max: {summary[4]:.2f}, " f"Average: {average_grade:.2f}" ) json.dump( res_dict, open("ve482_p1_grade.json", "w"), ensure_ascii=False, indent=4 ) if __name__ == "__main__": teapot = VE482Teapot() teapot.p1_submit()