123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185 |
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- import os
- from fastapi.background import BackgroundTasks
- from pydantic import Field
- from sqlalchemy.ext.asyncio import AsyncSession
- from crud.mark import crud_mark, crud_studentmark
- from crud.school import crud_grade, crud_system, crud_class
- from crud.user import crud_teacher, crud_student
- from models.mark import StudentMarkTask, StudentAnswer
- from models.school import SchoolGrade, SchoolClass
- from models.user import Teacher, Student
- from schemas.app.task import BgUpdateTaskReviewInfo, BgUpdateStudentTaskInfo
- from schemas.school.school import NewGrade
- async def delete_related_object(db: AsyncSession,
- *,
- sid: int = 0,
- gid: int = 0,
- cid: int = 0):
- # 根据学校删除年级、班级、教师、学生等
- if sid and (not gid) and (not cid):
- # 1、删除年级
- await crud_grade.delete(db,
- where_clauses=[SchoolGrade.school_id == sid])
- # 2、删除班级
- await crud_class.delete(db,
- where_clauses=[SchoolClass.school_id == sid])
- # TODO: 删除教师、学生、作业、考试、阅卷任务等
- await crud_teacher.delete(db, where_clauses=[Teacher.school_id == sid])
- await crud_student.delete(db, where_clauses=[Student.school_id == sid])
- elif gid and (not cid): # 如果是年级被删除,则删除该年级下的所有班级
- await crud_class.delete(db, where_clauses=[SchoolClass.grade_id == gid])
- # TODO: 删除学生、作业、考试、阅卷任务等
- await crud_student.delete(db, where_clauses=[Student.grade_id == gid])
- elif cid: # 如果班级被删除了,则删除该班级下的所有学生
- # TODO: 删除学生、作业、考试、阅卷任务等
- await crud_student.delete(db, where_clauses=[Student.class_id == cid])
- else:
- pass
- async def delete_remote_file(filepath: str):
- urls = [x.strip() for x in filepath.split(";")]
- try:
- for url in urls:
- os.remove(url)
- except Exception as ex:
- print(f"[Error] Delete file: {str(ex)}")
- async def rank_score(db: AsyncSession,
- task_id: int = Field(..., description="阅卷任务ID")):
- # 根据 task_id 查询 StudentMarkTask
- stmt = f"""SELECT id,
- CASE
- WHEN @prevRank = score THEN @curRank
- WHEN @prevRank := score THEN @curRank := @curRank + 1
- END AS rank
- FROM {StudentMarkTask.__tablename__},
- (SELECT @curRank :=0, @prevRank := NULL) rb
- WHERE task_id={task_id}
- ORDER BY score desc;
- """
- ranks = await crud_studentmark.execute(db, stmt)
- for idx, sid in enumerate(ranks):
- stmt = f"UPDATE {StudentMarkTask.__tablename__} SET rank={idx+1} WHERE id={sid};"
- await crud_studentmark.execute(db, stmt)
- async def update_mark_task(db: AsyncSession,
- bg_task: BackgroundTasks,
- task_id: int = Field(..., description="学生阅卷任务ID"),
- qtype: int = Field(...,
- description="试题类型,0:客观题,1: 主观题"),
- score: int = Field(..., description="得分"),
- editor_id: int = Field(..., description="最后编辑人ID"),
- editor_name: str = Field(...,
- description="最后编辑人姓名")):
- """
- 数据更新流程:
- 1、根据task_id更新StudentMarkTask,
- 2、如果该学生的所有试题已经被批阅完,则根据StudentMarkTask.task_id 更新 MarkTask 的最高分/最低分/平均分...等信息。
- 3、如果MarkTask批阅完成,则对StudentMarkTask进行排名。
- """
- # ------------------ 更新学生阅卷任-----------------------------------
- student_task = await crud_studentmark.find_one(db, filters={"id": task_id})
- # 判断该学生是否已经被批阅完成
- marked_amount = student_task.marked_amount + 1
- smt = BgUpdateStudentTaskInfo(
- marked_amount=marked_amount,
- is_completed=marked_amount == student_task.question_amount,
- score=student_task.score + score,
- editor_id=editor_id,
- editor_name=editor_name,
- )
- # 按题型统计得分
- if qtype:
- smt.subjective_score = student_task.subjective_score + score
- else:
- smt.objective_score = student_task.objective_score + score
- # 开始更新
- student_task = await crud_studentmark.update(db, student_task, smt)
- # ------------------ 更新学生阅卷任务结束 ---------------------------
- # ------------------ 更新阅卷任务 ---------------------------------
- if student_task.is_completed:
- # 查询MarkTask是否存在
- db_obj = await crud_mark.find_one(db,
- filters={"id": student_task.task_id})
- # 批阅完成学生数量
- marked_amount = db_obj.marked_amount + 1
- if marked_amount == db_obj.student_amount:
- bg_task.add_task(rank_score, db, student_task.task_id)
- # 最高分 / 最低分
- high_score = student_task.score if student_task.score > db_obj.high_score else db_obj.high_score
- low_score = student_task.score if student_task.score <= db_obj.low_score else db_obj.low_score
- # 平均分
- avg_score = round(
- ((db_obj.avg_score * db_obj.marked_amount) + score) / marked_amount,
- 2)
- # 及格人数
- if student_task.score >= 60:
- pass_amount = db_obj.pass_amount + 1
- else:
- pass_amount = db_obj.pass_amount
- pass_rate = round(pass_amount / marked_amount, 2)
- # 批阅状态
- status = 2 if marked_amount == db_obj.student_amount else 1
- # 更新
- mt = BgUpdateTaskReviewInfo(marked_amount=marked_amount,
- high_score=high_score,
- low_score=low_score,
- avg_score=avg_score,
- pass_amount=pass_amount,
- pass_rate=pass_rate,
- status=status)
- await crud_mark.update(db, db_obj, mt)
- print("Async Update MarkTask OK!")
- async def async_create_grade(db: AsyncSession, sid: int, category: int):
- # 年级列表
- school_system = await crud_system.find_one(db,
- filters={"id": category},
- return_fields={"grades"})
- grade_set = set(school_system.grades.split(","))
- # 查询学校是否存在
- _, db_grades = await crud_grade.find_all(db, filters={"school_id": sid})
- db_grade_set = set([x.name for x in db_grades])
- diff_grades = grade_set - db_grade_set
- new_grades = [NewGrade(sid=sid, name=x) for x in diff_grades]
- try:
- await crud_grade.insert_many(db, new_grades)
- except Exception as ex:
- print(f"AutoCreateGradeError: {str(ex)}")
- return
- async def delete_student_task_question(db: AsyncSession, task_id: int):
- # 查询学生任务ID列表
- _, student_tasks = await crud_studentmark.find_all(
- db, filters={"task_id": task_id}, return_fields=["id"])
- student_task_ids = ",".join([str(x.id) for x in student_tasks])
- # 删除学生任务和答题
- task_stmt = "DELETE FROM `{}` WHERE task_id={};".format(
- StudentMarkTask.__tablename__, task_id)
- await crud_studentmark.execute(db, task_stmt)
- question_stmt = "DELETE FROM `{}` WHERE task_id IN ({});".format(
- StudentAnswer.__tablename__, student_task_ids)
- await crud_studentmark.execute(db, question_stmt)
|