Files
OnlineJudge/problemset/signals.py
2025-10-22 18:47:40 +08:00

74 lines
2.6 KiB
Python

from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils import timezone
from .models import ProblemSetProgress, ProblemSetBadge, UserBadge
from submission.models import Submission
@receiver(post_save, sender=Submission)
def update_problemset_progress(sender, instance, created, **kwargs):
"""当提交状态更新时,自动更新题单进度"""
if not created: # 只处理更新,不处理新建
return
# 检查该提交是否属于某个题单中的题目
try:
from .models import ProblemSetProblem
problemset_problems = ProblemSetProblem.objects.filter(problem=instance.problem)
for psp in problemset_problems:
# 获取或创建用户在该题单中的进度记录
progress, created = ProblemSetProgress.objects.get_or_create(
problemset=psp.problemset, user=instance.user
)
# 更新详细进度
problem_id = str(instance.problem.id)
progress.progress_detail[problem_id] = {
"status": "completed"
if instance.result == 0
else "attempted", # 0表示AC
"score": instance.score if hasattr(instance, "score") else 0,
"submit_time": timezone.now().isoformat(),
}
# 更新进度
progress.update_progress()
# 检查是否获得奖章
check_and_award_badges(progress)
except Exception as e:
# 记录错误但不影响主流程
import logging
logger = logging.getLogger(__name__)
logger.error(f"更新题单进度时出错: {e}")
def check_and_award_badges(progress):
"""检查并颁发奖章"""
badges = ProblemSetBadge.objects.filter(problemset=progress.problemset)
for badge in badges:
# 检查是否已经获得该奖章
if UserBadge.objects.filter(user=progress.user, badge=badge).exists():
continue
# 检查是否满足获得条件
should_award = False
if badge.condition_type == "all_problems":
should_award = (
progress.completed_problems_count == progress.total_problems_count
)
elif badge.condition_type == "problem_count":
should_award = progress.completed_problems_count >= badge.condition_value
elif badge.condition_type == "score":
should_award = progress.total_score >= badge.condition_value
if should_award:
UserBadge.objects.create(user=progress.user, badge=badge)