122 lines
4.6 KiB
Python
122 lines
4.6 KiB
Python
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()
|