update
This commit is contained in:
@@ -0,0 +1,57 @@
|
|||||||
|
# Generated by Django 5.2.3 on 2025-10-23 01:34
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('problem', '0005_remove_spj_fields'),
|
||||||
|
('problemset', '0004_alter_problemset_status_problemsetsubmission'),
|
||||||
|
('submission', '0002_submission_user_create_time_idx'),
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='problemsetsubmission',
|
||||||
|
options={'ordering': ('-submission__create_time',), 'verbose_name': '题单提交记录', 'verbose_name_plural': '题单提交记录'},
|
||||||
|
),
|
||||||
|
migrations.RemoveIndex(
|
||||||
|
model_name='problemsetsubmission',
|
||||||
|
name='problemset__user_id_63c1d0_idx',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='problemsetsubmission',
|
||||||
|
name='code_length',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='problemsetsubmission',
|
||||||
|
name='execution_time',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='problemsetsubmission',
|
||||||
|
name='language',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='problemsetsubmission',
|
||||||
|
name='memory_usage',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='problemsetsubmission',
|
||||||
|
name='result',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='problemsetsubmission',
|
||||||
|
name='score',
|
||||||
|
),
|
||||||
|
migrations.RemoveField(
|
||||||
|
model_name='problemsetsubmission',
|
||||||
|
name='submit_time',
|
||||||
|
),
|
||||||
|
migrations.AddIndex(
|
||||||
|
model_name='problemsetsubmission',
|
||||||
|
index=models.Index(fields=['user'], name='problemset__user_id_2f1501_idx'),
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -113,7 +113,7 @@ class ProblemSetProgress(models.Model):
|
|||||||
# 获得的总分
|
# 获得的总分
|
||||||
total_score = models.IntegerField(default=0, verbose_name="总分")
|
total_score = models.IntegerField(default=0, verbose_name="总分")
|
||||||
# 用户在该题单中的详细进度信息
|
# 用户在该题单中的详细进度信息
|
||||||
# {"problem_id": {"status": "completed", "score": 100, "submit_time": "2024-01-01T00:00:00Z"}}
|
# {"problem_id": {"score": 20, "submit_time": "2024-01-01T00:00:00Z"}}
|
||||||
progress_detail = JSONField(default=dict, verbose_name="详细进度")
|
progress_detail = JSONField(default=dict, verbose_name="详细进度")
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
@@ -141,7 +141,6 @@ class ProblemSetProgress(models.Model):
|
|||||||
problem_id = str(psp.problem.id)
|
problem_id = str(psp.problem.id)
|
||||||
if problem_id in self.progress_detail:
|
if problem_id in self.progress_detail:
|
||||||
problem_progress = self.progress_detail[problem_id]
|
problem_progress = self.progress_detail[problem_id]
|
||||||
if problem_progress.get("status") == "completed":
|
|
||||||
completed_count += 1
|
completed_count += 1
|
||||||
total_score += problem_progress.get("score", 0)
|
total_score += problem_progress.get("score", 0)
|
||||||
|
|
||||||
@@ -177,35 +176,35 @@ class ProblemSetSubmission(models.Model):
|
|||||||
problem = models.ForeignKey(
|
problem = models.ForeignKey(
|
||||||
"problem.Problem", on_delete=models.CASCADE, verbose_name="题目"
|
"problem.Problem", on_delete=models.CASCADE, verbose_name="题目"
|
||||||
)
|
)
|
||||||
# 提交时间
|
|
||||||
submit_time = models.DateTimeField(auto_now_add=True, verbose_name="提交时间")
|
|
||||||
# 提交结果
|
|
||||||
result = models.IntegerField(verbose_name="提交结果")
|
|
||||||
# 得分
|
|
||||||
score = models.IntegerField(default=0, verbose_name="得分")
|
|
||||||
# 语言
|
|
||||||
language = models.CharField(max_length=20, verbose_name="编程语言")
|
|
||||||
# 代码长度
|
|
||||||
code_length = models.IntegerField(default=0, verbose_name="代码长度")
|
|
||||||
# 执行时间(毫秒)
|
|
||||||
execution_time = models.IntegerField(default=0, verbose_name="执行时间")
|
|
||||||
# 内存使用(KB)
|
|
||||||
memory_usage = models.IntegerField(default=0, verbose_name="内存使用")
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
db_table = "problemset_submission"
|
db_table = "problemset_submission"
|
||||||
ordering = ("-submit_time",)
|
ordering = ("-submission__create_time",)
|
||||||
verbose_name = "题单提交记录"
|
verbose_name = "题单提交记录"
|
||||||
verbose_name_plural = "题单提交记录"
|
verbose_name_plural = "题单提交记录"
|
||||||
indexes = [
|
indexes = [
|
||||||
models.Index(fields=["problemset", "user"]),
|
models.Index(fields=["problemset", "user"]),
|
||||||
models.Index(fields=["problemset", "problem"]),
|
models.Index(fields=["problemset", "problem"]),
|
||||||
models.Index(fields=["user", "submit_time"]),
|
models.Index(fields=["user"]),
|
||||||
]
|
]
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return f"{self.user.username} - {self.problemset.title} - {self.problem.title}"
|
return f"{self.user.username} - {self.problemset.title} - {self.problem.title}"
|
||||||
|
|
||||||
|
@property
|
||||||
|
def submit_time(self):
|
||||||
|
"""提交时间"""
|
||||||
|
return self.submission.create_time
|
||||||
|
|
||||||
|
@property
|
||||||
|
def result(self):
|
||||||
|
"""提交结果"""
|
||||||
|
return self.submission.result
|
||||||
|
|
||||||
|
@property
|
||||||
|
def language(self):
|
||||||
|
"""编程语言"""
|
||||||
|
return self.submission.language
|
||||||
|
|
||||||
class UserBadge(models.Model):
|
class UserBadge(models.Model):
|
||||||
"""用户奖章模型"""
|
"""用户奖章模型"""
|
||||||
|
|||||||
@@ -227,10 +227,6 @@ class UpdateProgressSerializer(serializers.Serializer):
|
|||||||
|
|
||||||
problemset_id = serializers.IntegerField()
|
problemset_id = serializers.IntegerField()
|
||||||
problem_id = serializers.IntegerField()
|
problem_id = serializers.IntegerField()
|
||||||
status = serializers.CharField() # completed, attempted, not_started
|
|
||||||
score = serializers.IntegerField(default=0)
|
|
||||||
submit_time = serializers.DateTimeField(required=False)
|
|
||||||
|
|
||||||
|
|
||||||
class ProblemSetSubmissionSerializer(serializers.ModelSerializer):
|
class ProblemSetSubmissionSerializer(serializers.ModelSerializer):
|
||||||
"""题单提交记录序列化器"""
|
"""题单提交记录序列化器"""
|
||||||
@@ -238,6 +234,7 @@ class ProblemSetSubmissionSerializer(serializers.ModelSerializer):
|
|||||||
problem_title = serializers.CharField(source="problem.title", read_only=True)
|
problem_title = serializers.CharField(source="problem.title", read_only=True)
|
||||||
problem_id = serializers.IntegerField(source="problem.id", read_only=True)
|
problem_id = serializers.IntegerField(source="problem.id", read_only=True)
|
||||||
result_text = serializers.SerializerMethodField()
|
result_text = serializers.SerializerMethodField()
|
||||||
|
submit_time = serializers.DateTimeField(source="submission.create_time", read_only=True)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = ProblemSetSubmission
|
model = ProblemSetSubmission
|
||||||
@@ -248,28 +245,7 @@ class ProblemSetSubmissionSerializer(serializers.ModelSerializer):
|
|||||||
"problem_title",
|
"problem_title",
|
||||||
"submission",
|
"submission",
|
||||||
"result",
|
"result",
|
||||||
"result_text",
|
|
||||||
"score",
|
|
||||||
"language",
|
"language",
|
||||||
"code_length",
|
|
||||||
"execution_time",
|
|
||||||
"memory_usage",
|
|
||||||
"submit_time",
|
"submit_time",
|
||||||
]
|
]
|
||||||
|
|
||||||
def get_result_text(self, obj):
|
|
||||||
"""获取结果文本"""
|
|
||||||
result_map = {
|
|
||||||
-2: "编译错误",
|
|
||||||
-1: "答案错误",
|
|
||||||
0: "通过",
|
|
||||||
1: "时间超限",
|
|
||||||
2: "时间超限",
|
|
||||||
3: "内存超限",
|
|
||||||
4: "运行时错误",
|
|
||||||
5: "系统错误",
|
|
||||||
6: "等待中",
|
|
||||||
7: "评测中",
|
|
||||||
8: "部分通过",
|
|
||||||
}
|
|
||||||
return result_map.get(obj.result, "未知")
|
|
||||||
|
|||||||
@@ -1,94 +1,2 @@
|
|||||||
from django.db.models.signals import post_save
|
# 题单应用信号处理
|
||||||
from django.dispatch import receiver
|
# 目前暂时为空,后续可以添加信号处理逻辑
|
||||||
from django.utils import timezone
|
|
||||||
|
|
||||||
from .models import ProblemSetProgress, ProblemSetBadge, UserBadge, ProblemSetSubmission
|
|
||||||
from submission.models import Submission
|
|
||||||
|
|
||||||
|
|
||||||
@receiver(post_save, sender=Submission)
|
|
||||||
def update_problemset_progress(sender, instance, created, **kwargs):
|
|
||||||
"""当提交状态更新时,自动更新题单进度"""
|
|
||||||
# 处理新建和更新,但只在提交状态确定时更新(不是Pending状态)
|
|
||||||
if instance.result == 6: # 6表示PENDING状态,不更新进度
|
|
||||||
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
|
|
||||||
)
|
|
||||||
|
|
||||||
# 创建题单提交记录
|
|
||||||
ProblemSetSubmission.objects.create(
|
|
||||||
problemset=psp.problemset,
|
|
||||||
user=instance.user,
|
|
||||||
submission=instance,
|
|
||||||
problem=instance.problem,
|
|
||||||
result=instance.result,
|
|
||||||
score=instance.score if hasattr(instance, "score") else 0,
|
|
||||||
language=instance.language,
|
|
||||||
code_length=len(instance.code) if hasattr(instance, "code") else 0,
|
|
||||||
execution_time=instance.statistic_info.get("time_cost", 0) if hasattr(instance, "statistic_info") else 0,
|
|
||||||
memory_usage=instance.statistic_info.get("memory_cost", 0) if hasattr(instance, "statistic_info") else 0,
|
|
||||||
)
|
|
||||||
|
|
||||||
# 更新详细进度
|
|
||||||
problem_id = str(instance.problem.id)
|
|
||||||
|
|
||||||
# 确定题目状态
|
|
||||||
if instance.result == 0: # ACCEPTED
|
|
||||||
status = "completed" # 部分通过也算完成
|
|
||||||
else: # 其他状态(错误、超时等)
|
|
||||||
status = "attempted"
|
|
||||||
|
|
||||||
progress.progress_detail[problem_id] = {
|
|
||||||
"status": status,
|
|
||||||
"score": instance.score if hasattr(instance, "score") else 0,
|
|
||||||
"submit_time": timezone.now().isoformat(),
|
|
||||||
"result": instance.result, # 保存原始结果代码
|
|
||||||
}
|
|
||||||
|
|
||||||
# 更新进度
|
|
||||||
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)
|
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
from django.db.models import Q
|
from django.db.models import Q
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
@@ -65,7 +64,11 @@ class ProblemSetDetailAPI(APIView):
|
|||||||
def get(self, request, problem_set_id):
|
def get(self, request, problem_set_id):
|
||||||
"""获取题单详情"""
|
"""获取题单详情"""
|
||||||
try:
|
try:
|
||||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status="draft").get()
|
problem_set = (
|
||||||
|
ProblemSet.objects.filter(id=problem_set_id, visible=True)
|
||||||
|
.exclude(status="draft")
|
||||||
|
.get()
|
||||||
|
)
|
||||||
except ProblemSet.DoesNotExist:
|
except ProblemSet.DoesNotExist:
|
||||||
return self.error("题单不存在")
|
return self.error("题单不存在")
|
||||||
|
|
||||||
@@ -79,7 +82,11 @@ class ProblemSetProblemAPI(APIView):
|
|||||||
def get(self, request, problem_set_id):
|
def get(self, request, problem_set_id):
|
||||||
"""获取题单中的题目列表"""
|
"""获取题单中的题目列表"""
|
||||||
try:
|
try:
|
||||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status="draft").get()
|
problem_set = (
|
||||||
|
ProblemSet.objects.filter(id=problem_set_id, visible=True)
|
||||||
|
.exclude(status="draft")
|
||||||
|
.get()
|
||||||
|
)
|
||||||
except ProblemSet.DoesNotExist:
|
except ProblemSet.DoesNotExist:
|
||||||
return self.error("题单不存在")
|
return self.error("题单不存在")
|
||||||
|
|
||||||
@@ -100,7 +107,11 @@ class ProblemSetProgressAPI(APIView):
|
|||||||
"""加入题单"""
|
"""加入题单"""
|
||||||
data = request.data
|
data = request.data
|
||||||
try:
|
try:
|
||||||
problem_set = ProblemSet.objects.filter(id=data["problemset_id"], visible=True).exclude(status="draft").get()
|
problem_set = (
|
||||||
|
ProblemSet.objects.filter(id=data["problemset_id"], visible=True)
|
||||||
|
.exclude(status="draft")
|
||||||
|
.get()
|
||||||
|
)
|
||||||
except ProblemSet.DoesNotExist:
|
except ProblemSet.DoesNotExist:
|
||||||
return self.error("题单不存在")
|
return self.error("题单不存在")
|
||||||
|
|
||||||
@@ -120,7 +131,11 @@ class ProblemSetProgressAPI(APIView):
|
|||||||
def get(self, request, problem_set_id):
|
def get(self, request, problem_set_id):
|
||||||
"""获取题单进度"""
|
"""获取题单进度"""
|
||||||
try:
|
try:
|
||||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status="draft").get()
|
problem_set = (
|
||||||
|
ProblemSet.objects.filter(id=problem_set_id, visible=True)
|
||||||
|
.exclude(status="draft")
|
||||||
|
.get()
|
||||||
|
)
|
||||||
except ProblemSet.DoesNotExist:
|
except ProblemSet.DoesNotExist:
|
||||||
return self.error("题单不存在")
|
return self.error("题单不存在")
|
||||||
|
|
||||||
@@ -139,7 +154,11 @@ class ProblemSetProgressAPI(APIView):
|
|||||||
"""更新进度"""
|
"""更新进度"""
|
||||||
data = request.data
|
data = request.data
|
||||||
try:
|
try:
|
||||||
problem_set = ProblemSet.objects.filter(id=data["problemset_id"], visible=True).exclude(status="draft").get()
|
problem_set = (
|
||||||
|
ProblemSet.objects.filter(id=data["problemset_id"], visible=True)
|
||||||
|
.exclude(status="draft")
|
||||||
|
.get()
|
||||||
|
)
|
||||||
except ProblemSet.DoesNotExist:
|
except ProblemSet.DoesNotExist:
|
||||||
return self.error("题单不存在")
|
return self.error("题单不存在")
|
||||||
|
|
||||||
@@ -152,9 +171,18 @@ class ProblemSetProgressAPI(APIView):
|
|||||||
|
|
||||||
# 更新详细进度
|
# 更新详细进度
|
||||||
problem_id = str(data["problem_id"])
|
problem_id = str(data["problem_id"])
|
||||||
|
|
||||||
|
# 获取该题目在题单中的分值
|
||||||
|
try:
|
||||||
|
problemset_problem = ProblemSetProblem.objects.get(
|
||||||
|
problemset=problem_set, problem_id=problem_id
|
||||||
|
)
|
||||||
|
problem_score = problemset_problem.score
|
||||||
|
except ProblemSetProblem.DoesNotExist:
|
||||||
|
problem_score = 0
|
||||||
|
|
||||||
progress.progress_detail[problem_id] = {
|
progress.progress_detail[problem_id] = {
|
||||||
"status": data["status"],
|
"score": problem_score,
|
||||||
"score": data.get("score", 0),
|
|
||||||
"submit_time": data.get("submit_time", timezone.now().isoformat()),
|
"submit_time": data.get("submit_time", timezone.now().isoformat()),
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,7 +253,11 @@ class ProblemSetBadgeAPI(APIView):
|
|||||||
def get(self, request, problem_set_id):
|
def get(self, request, problem_set_id):
|
||||||
"""获取题单的奖章列表"""
|
"""获取题单的奖章列表"""
|
||||||
try:
|
try:
|
||||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status="draft").get()
|
problem_set = (
|
||||||
|
ProblemSet.objects.filter(id=problem_set_id, visible=True)
|
||||||
|
.exclude(status="draft")
|
||||||
|
.get()
|
||||||
|
)
|
||||||
except ProblemSet.DoesNotExist:
|
except ProblemSet.DoesNotExist:
|
||||||
return self.error("题单不存在")
|
return self.error("题单不存在")
|
||||||
|
|
||||||
@@ -240,7 +272,11 @@ class ProblemSetSubmissionAPI(APIView):
|
|||||||
def get(self, request, problem_set_id):
|
def get(self, request, problem_set_id):
|
||||||
"""获取用户在题单中的提交记录"""
|
"""获取用户在题单中的提交记录"""
|
||||||
try:
|
try:
|
||||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status="draft").get()
|
problem_set = (
|
||||||
|
ProblemSet.objects.filter(id=problem_set_id, visible=True)
|
||||||
|
.exclude(status="draft")
|
||||||
|
.get()
|
||||||
|
)
|
||||||
except ProblemSet.DoesNotExist:
|
except ProblemSet.DoesNotExist:
|
||||||
return self.error("题单不存在")
|
return self.error("题单不存在")
|
||||||
|
|
||||||
@@ -256,20 +292,19 @@ class ProblemSetSubmissionAPI(APIView):
|
|||||||
language = request.GET.get("language")
|
language = request.GET.get("language")
|
||||||
|
|
||||||
# 构建查询条件
|
# 构建查询条件
|
||||||
query_filter = {
|
query_filter = {"problemset": problem_set, "user": request.user}
|
||||||
"problemset": problem_set,
|
|
||||||
"user": request.user
|
|
||||||
}
|
|
||||||
|
|
||||||
if problem_id:
|
if problem_id:
|
||||||
query_filter["problem_id"] = problem_id
|
query_filter["problem_id"] = problem_id
|
||||||
if result:
|
if result:
|
||||||
query_filter["result"] = result
|
query_filter["submission__result"] = result
|
||||||
if language:
|
if language:
|
||||||
query_filter["language"] = language
|
query_filter["submission__language"] = language
|
||||||
|
|
||||||
# 获取提交记录
|
# 获取提交记录
|
||||||
submissions = ProblemSetSubmission.objects.filter(**query_filter).order_by("-submit_time")
|
submissions = ProblemSetSubmission.objects.filter(**query_filter).order_by(
|
||||||
|
"-submission__create_time"
|
||||||
|
)
|
||||||
|
|
||||||
# 分页
|
# 分页
|
||||||
data = self.paginate_data(request, submissions, ProblemSetSubmissionSerializer)
|
data = self.paginate_data(request, submissions, ProblemSetSubmissionSerializer)
|
||||||
@@ -282,13 +317,19 @@ class ProblemSetStatisticsAPI(APIView):
|
|||||||
def get(self, request, problem_set_id):
|
def get(self, request, problem_set_id):
|
||||||
"""获取题单统计信息"""
|
"""获取题单统计信息"""
|
||||||
try:
|
try:
|
||||||
problem_set = ProblemSet.objects.filter(id=problem_set_id, visible=True).exclude(status="draft").get()
|
problem_set = (
|
||||||
|
ProblemSet.objects.filter(id=problem_set_id, visible=True)
|
||||||
|
.exclude(status="draft")
|
||||||
|
.get()
|
||||||
|
)
|
||||||
except ProblemSet.DoesNotExist:
|
except ProblemSet.DoesNotExist:
|
||||||
return self.error("题单不存在")
|
return self.error("题单不存在")
|
||||||
|
|
||||||
# 检查用户是否已加入该题单
|
# 检查用户是否已加入该题单
|
||||||
try:
|
try:
|
||||||
progress = ProblemSetProgress.objects.get(problemset=problem_set, user=request.user)
|
progress = ProblemSetProgress.objects.get(
|
||||||
|
problemset=problem_set, user=request.user
|
||||||
|
)
|
||||||
except ProblemSetProgress.DoesNotExist:
|
except ProblemSetProgress.DoesNotExist:
|
||||||
return self.error("您还未加入该题单")
|
return self.error("您还未加入该题单")
|
||||||
|
|
||||||
@@ -298,7 +339,7 @@ class ProblemSetStatisticsAPI(APIView):
|
|||||||
).count()
|
).count()
|
||||||
|
|
||||||
accepted_submissions = ProblemSetSubmission.objects.filter(
|
accepted_submissions = ProblemSetSubmission.objects.filter(
|
||||||
problemset=problem_set, user=request.user, result=0
|
problemset=problem_set, user=request.user, submission__result=0
|
||||||
).count()
|
).count()
|
||||||
|
|
||||||
# 按题目统计
|
# 按题目统计
|
||||||
@@ -308,41 +349,48 @@ class ProblemSetStatisticsAPI(APIView):
|
|||||||
for psp in problemset_problems:
|
for psp in problemset_problems:
|
||||||
problem_id = psp.problem.id
|
problem_id = psp.problem.id
|
||||||
problem_submissions = ProblemSetSubmission.objects.filter(
|
problem_submissions = ProblemSetSubmission.objects.filter(
|
||||||
problemset=problem_set,
|
problemset=problem_set, user=request.user, problem=psp.problem
|
||||||
user=request.user,
|
|
||||||
problem=psp.problem
|
|
||||||
)
|
)
|
||||||
|
|
||||||
problem_stats[str(problem_id)] = {
|
problem_stats[str(problem_id)] = {
|
||||||
"problem_title": psp.problem.title,
|
"problem_title": psp.problem.title,
|
||||||
"total_submissions": problem_submissions.count(),
|
"total_submissions": problem_submissions.count(),
|
||||||
"accepted_submissions": problem_submissions.filter(result=0).count(),
|
"accepted_submissions": problem_submissions.filter(submission__result=0).count(),
|
||||||
"is_completed": str(problem_id) in progress.progress_detail and
|
"is_completed": str(problem_id) in progress.progress_detail,
|
||||||
progress.progress_detail[str(problem_id)].get("status") == "completed"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# 按语言统计
|
# 按语言统计
|
||||||
language_stats = {}
|
language_stats = {}
|
||||||
language_submissions = ProblemSetSubmission.objects.filter(
|
language_submissions = (
|
||||||
|
ProblemSetSubmission.objects.filter(
|
||||||
problemset=problem_set, user=request.user
|
problemset=problem_set, user=request.user
|
||||||
).values('language').annotate(count=models.Count('id'))
|
)
|
||||||
|
.values("submission__language")
|
||||||
|
.annotate(count=models.Count("id"))
|
||||||
|
)
|
||||||
|
|
||||||
for item in language_submissions:
|
for item in language_submissions:
|
||||||
language_stats[item['language']] = item['count']
|
language_stats[item["submission__language"]] = item["count"]
|
||||||
|
|
||||||
# 按结果统计
|
# 按结果统计
|
||||||
result_stats = {}
|
result_stats = {}
|
||||||
result_submissions = ProblemSetSubmission.objects.filter(
|
result_submissions = (
|
||||||
|
ProblemSetSubmission.objects.filter(
|
||||||
problemset=problem_set, user=request.user
|
problemset=problem_set, user=request.user
|
||||||
).values('result').annotate(count=models.Count('id'))
|
)
|
||||||
|
.values("submission__result")
|
||||||
|
.annotate(count=models.Count("id"))
|
||||||
|
)
|
||||||
|
|
||||||
for item in result_submissions:
|
for item in result_submissions:
|
||||||
result_stats[item['result']] = item['count']
|
result_stats[item["submission__result"]] = item["count"]
|
||||||
|
|
||||||
data = {
|
data = {
|
||||||
"total_submissions": total_submissions,
|
"total_submissions": total_submissions,
|
||||||
"accepted_submissions": accepted_submissions,
|
"accepted_submissions": accepted_submissions,
|
||||||
"acceptance_rate": round(accepted_submissions / total_submissions * 100, 2) if total_submissions > 0 else 0,
|
"acceptance_rate": round(accepted_submissions / total_submissions * 100, 2)
|
||||||
|
if total_submissions > 0
|
||||||
|
else 0,
|
||||||
"problem_stats": problem_stats,
|
"problem_stats": problem_stats,
|
||||||
"language_stats": language_stats,
|
"language_stats": language_stats,
|
||||||
"result_stats": result_stats,
|
"result_stats": result_stats,
|
||||||
@@ -350,8 +398,8 @@ class ProblemSetStatisticsAPI(APIView):
|
|||||||
"completed_problems_count": progress.completed_problems_count,
|
"completed_problems_count": progress.completed_problems_count,
|
||||||
"total_problems_count": progress.total_problems_count,
|
"total_problems_count": progress.total_problems_count,
|
||||||
"progress_percentage": progress.progress_percentage,
|
"progress_percentage": progress.progress_percentage,
|
||||||
"total_score": progress.total_score
|
"total_score": progress.total_score,
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
return self.success(data)
|
return self.success(data)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ class CreateSubmissionSerializer(serializers.Serializer):
|
|||||||
language = LanguageNameChoiceField()
|
language = LanguageNameChoiceField()
|
||||||
code = serializers.CharField(max_length=1024 * 1024)
|
code = serializers.CharField(max_length=1024 * 1024)
|
||||||
contest_id = serializers.IntegerField(required=False)
|
contest_id = serializers.IntegerField(required=False)
|
||||||
|
problemset_id = serializers.IntegerField(required=False)
|
||||||
captcha = serializers.CharField(required=False)
|
captcha = serializers.CharField(required=False)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ from ..serializers import (
|
|||||||
ShareSubmissionSerializer,
|
ShareSubmissionSerializer,
|
||||||
)
|
)
|
||||||
from ..serializers import SubmissionSafeModelSerializer, SubmissionListSerializer
|
from ..serializers import SubmissionSafeModelSerializer, SubmissionListSerializer
|
||||||
|
from problemset.models import ProblemSetSubmission
|
||||||
|
|
||||||
|
|
||||||
class SubmissionAPI(APIView):
|
class SubmissionAPI(APIView):
|
||||||
@@ -91,6 +92,16 @@ class SubmissionAPI(APIView):
|
|||||||
ip=request.session["ip"],
|
ip=request.session["ip"],
|
||||||
contest_id=data.get("contest_id"),
|
contest_id=data.get("contest_id"),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 如果有problemset_id,创建ProblemSetSubmission记录
|
||||||
|
if data.get("problemset_id"):
|
||||||
|
ProblemSetSubmission.objects.create(
|
||||||
|
problemset_id=data["problemset_id"],
|
||||||
|
user=request.user,
|
||||||
|
submission=submission,
|
||||||
|
problem=problem,
|
||||||
|
)
|
||||||
|
|
||||||
# use this for debug
|
# use this for debug
|
||||||
# JudgeDispatcher(submission.id, problem.id).judge()
|
# JudgeDispatcher(submission.id, problem.id).judge()
|
||||||
judge_task.send(submission.id, problem.id)
|
judge_task.send(submission.id, problem.id)
|
||||||
@@ -174,10 +185,7 @@ class SubmissionListAPI(APIView):
|
|||||||
return self.error("Problem doesn't exist")
|
return self.error("Problem doesn't exist")
|
||||||
submissions = submissions.filter(problem=problem)
|
submissions = submissions.filter(problem=problem)
|
||||||
|
|
||||||
if (
|
if not SysOptions.submission_list_show_all and request.user.is_regular_user():
|
||||||
not SysOptions.submission_list_show_all
|
|
||||||
and request.user.is_regular_user()
|
|
||||||
):
|
|
||||||
return self.success({"results": [], "total": 0})
|
return self.success({"results": [], "total": 0})
|
||||||
|
|
||||||
if myself and myself == "1":
|
if myself and myself == "1":
|
||||||
|
|||||||
Reference in New Issue
Block a user