提交题目完成的排名

This commit is contained in:
2025-09-21 19:11:18 +08:00
parent 81663e705b
commit 24f1a0372e
8 changed files with 97 additions and 8 deletions

View File

@@ -0,0 +1,18 @@
# Generated by Django 5.2.3 on 2025-09-19 06:11
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='userprofile',
name='class_name',
field=models.TextField(null=True),
),
]

View File

@@ -0,0 +1,22 @@
# Generated by Django 5.2.3 on 2025-09-19 06:14
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0002_userprofile_class_name'),
]
operations = [
migrations.RemoveField(
model_name='userprofile',
name='class_name',
),
migrations.AddField(
model_name='user',
name='class_name',
field=models.TextField(null=True),
),
]

View File

@@ -25,6 +25,7 @@ class UserManager(models.Manager):
class User(AbstractBaseUser):
username = models.TextField(unique=True)
class_name = models.TextField(null=True)
email = models.TextField(null=True)
create_time = models.DateTimeField(auto_now_add=True, null=True)
# One of UserType

View File

@@ -67,6 +67,7 @@ class UserAdminSerializer(serializers.ModelSerializer):
"open_api",
"is_disabled",
"raw_password",
"class_name",
]
def get_real_name(self, obj):
@@ -93,6 +94,7 @@ class UserSerializer(serializers.ModelSerializer):
"two_factor_auth",
"open_api",
"is_disabled",
"class_name",
]
@@ -129,7 +131,7 @@ class EditUserSerializer(serializers.Serializer):
open_api = serializers.BooleanField()
two_factor_auth = serializers.BooleanField()
is_disabled = serializers.BooleanField()
class_name = serializers.CharField(max_length=32, allow_blank=True, required=False)
class EditUserProfileSerializer(serializers.Serializer):
real_name = serializers.CharField(max_length=32, allow_null=True, required=False)
@@ -141,7 +143,6 @@ class EditUserProfileSerializer(serializers.Serializer):
major = serializers.CharField(max_length=64, allow_blank=True, required=False)
language = serializers.CharField(max_length=32, allow_blank=True, required=False)
class ApplyResetPasswordSerializer(serializers.Serializer):
email = serializers.EmailField()
captcha = serializers.CharField()

View File

@@ -15,6 +15,7 @@ from ..views.oj import (
UserProfileAPI,
UserRankAPI,
UserActivityRankAPI,
UserProblemRankAPI,
CheckTFARequiredAPI,
SessionManagementAPI,
ProfileProblemDisplayIDRefreshAPI,
@@ -45,6 +46,7 @@ urlpatterns = [
),
path("user_rank", UserRankAPI.as_view()),
path("user_activity_rank", UserActivityRankAPI.as_view()),
path("user_problem_rank", UserProblemRankAPI.as_view()),
path("sessions", SessionManagementAPI.as_view()),
path(
"open_api_appkey",

View File

@@ -1,4 +1,5 @@
import os
import re
from datetime import timedelta
from importlib import import_module
@@ -475,6 +476,47 @@ class UserActivityRankAPI(APIView):
return self.success(data[:10])
class UserProblemRankAPI(APIView):
def get(self, request):
problem_id = request.GET.get("problem_id")
user = request.user
if not user.is_authenticated:
return self.error("User is not authenticated")
problem = Problem.objects.get(_id=problem_id, contest_id__isnull=True, visible=True)
submissions = Submission.objects.filter(problem=problem, result=JudgeStatus.ACCEPTED)
all_ac_users = submissions.values("user_id").distinct()
all_ac_count = len(all_ac_users)
class_name = user.class_name or ""
class_ac_count = 0
if class_name:
users = User.objects.filter(class_name=user.class_name, is_disabled=False).values_list("id", flat=True)
submissions = submissions.filter(user_id__in=list(users))
class_ac_users = submissions.values("user_id").distinct()
class_ac_count = len(class_ac_users)
my_submissions = submissions.filter(user_id=user.id)
if len(my_submissions) == 0:
return self.success({
"class_name": class_name,
"rank": -1,
"class_ac_count": class_ac_count,
"all_ac_count": all_ac_count
})
my_first_submission = my_submissions.order_by("create_time").first()
rank = submissions.filter(create_time__lte=my_first_submission.create_time).count()
return self.success({
"class_name": class_name,
"rank": rank,
"class_ac_count": class_ac_count,
"all_ac_count": all_ac_count,
})
class ProfileProblemDisplayIDRefreshAPI(APIView):
@login_required
def get(self, request):

View File

@@ -6,14 +6,18 @@ BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
DATABASES = {
"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
"ENGINE": "django.db.backends.postgresql",
"HOST": "10.13.114.114",
"PORT": "5433",
"NAME": "onlinejudge",
"USER": "onlinejudge",
"PASSWORD": "onlinejudge",
}
}
REDIS_CONF = {
"host": get_env("REDIS_HOST", "127.0.0.1"),
"port": get_env("REDIS_PORT", "6380"),
"host": "10.13.114.114",
"port": 6379,
}

View File

@@ -210,8 +210,7 @@ def redis_config(db):
}
if production_env:
CACHES = {"default": redis_config(db=1)}
CACHES = {"default": redis_config(db=1)}
SESSION_ENGINE = "django.contrib.sessions.backends.cache"
SESSION_CACHE_ALIAS = "default"