Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
83 commits
Select commit Hold shift + click to select a range
fd3b25b
#595 불필요한 가로 스크롤 발생하던 문제 해결 (#598)
Neibce Mar 26, 2026
61f5170
ci: Update dev image tags to fd3b25b3bae56dfef7e8eaeb73b734a7d3c25ed6…
github-actions[bot] Mar 26, 2026
b7dd9e0
#601 vLLM Kubernetes 리소스 및 배포 가이드 추가 (#602)
Neibce Mar 31, 2026
e045a48
#601 vLLM 오버레이 참조 오류 수정 (#603)
Neibce Mar 31, 2026
c3e9f68
#601 vllm deploy 오류 수정 및 배포 (#604)
wlsgur11 Apr 1, 2026
fbd3cc1
#597 대회 랭킹 페이지 오류 수정 및 디자인 개선 (#605)
Neibce Apr 3, 2026
229fc33
ci: Update dev image tags to fbd3cc15e395360399fe4f70bb654ee126b3355c…
github-actions[bot] Apr 3, 2026
a55a1e2
ci: Update dev image tags to fbd3cc15e395360399fe4f70bb654ee126b3355c…
github-actions[bot] Apr 3, 2026
6d68220
#591 footer 사용자 가이드 노션 링크 업데이트 (#606)
wlsgur11 Apr 6, 2026
35836ed
ci: Update dev image tags to 6d68220bba46f63320fea5d54ac815674f56c943…
github-actions[bot] Apr 6, 2026
6c67ac3
#601 vLLM 기반 문제 힌트 스트리밍 API 초안 구현 (#608)
Neibce Apr 7, 2026
3ee1b6d
ci: Update dev image tags to 6c67ac38fc16d03ed82ee8d852eb0cb1c277d146…
github-actions[bot] Apr 7, 2026
3e3fb90
ci: Update dev image tags to 6c67ac38fc16d03ed82ee8d852eb0cb1c277d146…
github-actions[bot] Apr 7, 2026
6186394
fix: AI 힌트 프롬프트 개선 (#609)
Neibce Apr 7, 2026
a8a05b9
ci: Update dev image tags to 6186394fd1d3f76c8a555893217842226e01baef…
github-actions[bot] Apr 7, 2026
3c1ebd8
#601 AI조교 프론트 개발 (#607)
taekoong Apr 7, 2026
8de95cc
ci: Update dev image tags to 3c1ebd89bd1d667a8cfd7528bbd86ed508afbf6b…
github-actions[bot] Apr 7, 2026
156816b
#601 단순 AI 조교 프롬프트 개선 (#610)
Neibce Apr 8, 2026
e788205
ci: Update dev image tags to 156816bf53ff1e55a2bb95e81b40048ac32a9627…
github-actions[bot] Apr 8, 2026
717c2df
#581 대회 생성 페이지 UI 개선 (#613)
taekoong Apr 23, 2026
25d3e3d
ci: Update dev image tags to 717c2dfd36cec83768bc81270f0fc2b98630c742…
github-actions[bot] Apr 23, 2026
f3ce789
#601 AI 조교 호출 횟수 제한 및 히스토리 영구 저장 기능 구현 (#611)
wlsgur11 Apr 23, 2026
385ece2
ci: Update dev image tags to f3ce78949dc3465f9955a18edc0bbd23f0a7f5ce…
github-actions[bot] Apr 23, 2026
5562e5f
#614 헤더 디자인 개선 및 전역 폰트 및 코드 블럭 폰트 수정 (#615)
Neibce Apr 28, 2026
1570cf4
#601 단계별 힌트 제공을 위한 변경 (#618)
wlsgur11 Apr 28, 2026
130d3de
ci: Update dev image tags to 1570cf4c32240fb08cfba67db31d015652432bc1…
github-actions[bot] Apr 28, 2026
21e0d2e
ci: Update dev image tags to 5562e5f8b58a2e589ec8944a0c623f437fe09175…
github-actions[bot] Apr 28, 2026
8c73759
#601 핵심 힌트 소진 시 제공 프롬프트 추가 (#619)
wlsgur11 Apr 28, 2026
e9d50ca
ci: Update dev image tags to 8c73759011acd91ddfe59569bfd7d4f98c11108a…
github-actions[bot] Apr 28, 2026
1c7a8d8
feat: AI 힌트 5단계 구조 도입 및 단계별 중복 방지 로직 추가 (#620)
taekoong Apr 29, 2026
fa84aa9
ci: Update dev image tags to 1c7a8d822772b744a186f30f6e70da1c0fc0a33a…
github-actions[bot] Apr 29, 2026
a7a86c2
#601 AI 힌트 5단계 구조 도입 및 단계별 중복 방지 로직 추가 (#621)
taekoong Apr 29, 2026
feea139
Revert "#601 AI 힌트 5단계 구조 도입 및 단계별 중복 방지 로직 추가 (#621)" (#622)
taekoong Apr 29, 2026
2ad63d4
#601 AI 힌트 단계별 제공 도입 및 단계별 중복 방지 로직 추가 (#623)
taekoong Apr 29, 2026
57a95c6
ci: Update dev image tags to 2ad63d409648f81c7ca16a4fd838a612328808b2…
github-actions[bot] Apr 29, 2026
10d9e04
AI 조교 프롬프트 영어로 변경 (#624)
Neibce Apr 30, 2026
dc831a5
ci: Update dev image tags to 10d9e04cdc47b3454fcd18b4829d9e0c5ee428c3…
github-actions[bot] Apr 30, 2026
e11c43a
#601 AI 조교 힌트 단계 명확하게 수정 (#625)
Neibce Apr 30, 2026
2fa1f1f
ci: Update dev image tags to e11c43a6304fa7225c8621ba70ccbf8100fac4e4…
github-actions[bot] Apr 30, 2026
54dd647
#601 AI 조교 힌트 단계 프롬프트 개선 (#626)
Neibce Apr 30, 2026
4253079
ci: Update dev image tags to 54dd64705e5f5dd908f4be5c3ac082a1e0937ece…
github-actions[bot] Apr 30, 2026
05921d4
단순 LLM 프롬프트 개선 (#627)
Neibce Apr 30, 2026
1521ebf
ci: Update dev image tags to 05921d494ed176d54150aec960f581416b053034…
github-actions[bot] Apr 30, 2026
bfe086a
#601 모델 변경, vllm 버전 변경 (#628)
wlsgur11 May 1, 2026
6d67b26
ci: Update dev image tags to bfe086aaa5ded7efc8e66ea82668cdfdefcd96c9…
github-actions[bot] May 1, 2026
0f167b1
#601 Thinking 모드 비활성화 (#630)
wlsgur11 May 3, 2026
3757a39
ci: Update dev image tags to 0f167b1c9db9f051332e2f55ac3143b62bd7ee13…
github-actions[bot] May 3, 2026
1392635
#601 LLM 힌트 요청 시 사용자 현재 코드 컨텍스트 포함 (#631)
wlsgur11 May 4, 2026
b1eb094
ci: Update dev image tags to 1392635fbac9fab10a56226e8aff460fbe6c6d96…
github-actions[bot] May 4, 2026
4ff15cc
#601 user_code를 LLM 메시지 마지막에 배치하고 분석 지시 강화 (#632)
wlsgur11 May 4, 2026
def2d65
ci: Update dev image tags to 4ff15ccd111ca99202f2094802ec665bcf237e7f…
github-actions[bot] May 4, 2026
b00110d
#601 대회 생성 페이지에 AI 조교 사용 여부 설정 기능 추가 (#616)
taekoong May 14, 2026
178f575
ci: Update dev image tags to b00110d50c2add299240f1863eab9eea83af5e44…
github-actions[bot] May 14, 2026
8a8ad54
#635 AI융합교육원 공지사항 게시판 번호 변경 (#636)
wlsgur11 May 14, 2026
75a205f
ci: Update dev image tags to 8a8ad5424ddc6fd64d00e53e1def9e06278f2f69…
github-actions[bot] May 14, 2026
66883f2
#637 버그 제보 링크 수정 (#638)
wlsgur11 May 14, 2026
8655dd2
ci: Update dev image tags to 66883f2f0d1d50c0dfae4f84d4f6ac7f8e025479…
github-actions[bot] May 14, 2026
b6599bd
#635 공지사항 불러오기 방식 변경으로 인한 RSS 방식 도입 (#639)
wlsgur11 May 14, 2026
55d4a7f
ci: Update dev image tags to b6599bd32520e256ad42b24d6569419e7ac8b2df…
github-actions[bot] May 14, 2026
651bba0
fix: 대회 내 AI조교 기본값 off로 설정 (#640)
taekoong May 18, 2026
f8bbd94
ci: Update dev image tags to 651bba04b0bf46062df1955eb03c87f7c36b2a58…
github-actions[bot] May 18, 2026
f5c2827
#635 교육원 공지사항 제목 } 표시 제거 (#642)
wlsgur11 May 20, 2026
feba5c9
ci: Update dev image tags to f5c282783d9cdb556f0583994806afdaab6e044a…
github-actions[bot] May 20, 2026
66fcde5
test: AI 조교 기본값(off) 및 레거시 대회 동작 테스트 추가 (#643)
taekoong May 20, 2026
35b27d5
ci: Update dev image tags to 66fcde5bed3b6c52c0be12770cc581643a824ba5…
github-actions[bot] May 20, 2026
bcc5024
getProblemLLMHintUrl 함수 시그니처에서 누락된 userCode 파라미터 복원 (#650)
wlsgur11 May 21, 2026
fa087c3
ci: Update dev image tags to bcc5024bf35dbad161c5e0ef5ad96291444aebe5…
github-actions[bot] May 21, 2026
8394896
#644 질문 게시판 정렬 순서 변경 (#645)
wlsgur11 May 25, 2026
6d2268d
#646 언어 선택 드롭다운 위에 툴팁 겹침 현상 수정 (#647)
wlsgur11 May 25, 2026
5508013
ci: Update dev image tags to 83948960b5ae2aab6db50f6095ef1a5802d3a064…
github-actions[bot] May 25, 2026
11f4ee0
Revert "#646 언어 선택 드롭다운 위에 툴팁 겹침 현상 수정 (#647)" (#651)
wlsgur11 May 25, 2026
d72e121
ci: Update dev image tags to 11f4ee09c410105f023caeeccba13bd46ef69b7e…
github-actions[bot] May 25, 2026
4684404
#646 언어 선택 드롭다운 위에 툴팁 겹침 현상 수정 revert됨 (#652)
wlsgur11 May 25, 2026
b21bb8f
ci: Update dev image tags to 468440485ead433e5a11fbb710f82a79c6f7dc2a…
github-actions[bot] May 25, 2026
726976f
#653 문제 내 큰 이미지 잘리는 현상 수정 및 다크모드 폰트 색 수정(검->흰) (#654)
Neibce May 26, 2026
8bc29f7
ci: Update dev image tags to 726976f8f051b0fd026953374e6b9af7ec3f7647…
github-actions[bot] May 26, 2026
203e29e
#655 추천 문제 카드의 태그가 글자 단위로 줄바꿈되는 현상 수정 (#656)
Neibce May 26, 2026
25ec3f7
ci: Update dev image tags to 203e29eaf0c640d97dcfc89363d544d20645d03d…
github-actions[bot] May 26, 2026
b97f59f
프로덕션 배포 준비를 위해 vLLM pod를 prod namespace로 이동 (#657)
Neibce May 26, 2026
6a42f34
#658 prod의 각종 imagePullPolicy를 IfNotPresent로 설정 (#659)
Neibce May 26, 2026
974cd16
#633 대회 문제 풀이 페이지 내 남은 시간 표시하도록 수정 및 문제 풀이 결과 목록 표시 및 바로 이동 가능하도록 개선 …
Neibce May 26, 2026
d5d86f3
ci: Update dev image tags to 974cd1608cccf9b163081994d6f9e838c134d14c…
github-actions[bot] May 26, 2026
8547f8d
Merge branch 'main' into release-3.0.0
Neibce May 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .github/workflows/ci2develop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ jobs:
file: ./backend/Dockerfile
push: true
tags: ${{ secrets.HARBOR_REGISTRY }}/code-place-dev/backend:${{ github.sha }}-dev
provenance: false

ci-frontend-dev:
needs: [detect-changes-by-component]
Expand All @@ -81,6 +82,7 @@ jobs:
file: ./frontend/Dockerfile
push: true
tags: ${{ secrets.HARBOR_REGISTRY }}/code-place-dev/frontend:${{ github.sha }}-dev
provenance: false
build-args: |
SERVER_NAME=${{ secrets.DEV_SERVER_NAME }}
APP_VERSION=${{ github.sha }}-dev
Expand Down Expand Up @@ -110,6 +112,7 @@ jobs:
file: ./hub/auth_server/Dockerfile
push: true
tags: ${{ secrets.HARBOR_REGISTRY }}/code-place-dev/hub-auth:${{ github.sha }}-dev
provenance: false

update-dev-manifest:
needs: [ci-backend-dev, ci-frontend-dev, ci-hub-auth-dev]
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci2production-and-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ jobs:
file: ./backend/Dockerfile
push: true
tags: ${{ secrets.HARBOR_REGISTRY }}/code-place-prod/backend:${{ github.sha }}-prod
provenance: false

ci-frontend:
needs: [detect-changes-by-component]
Expand All @@ -109,6 +110,7 @@ jobs:
file: ./frontend/Dockerfile
push: true
tags: ${{ secrets.HARBOR_REGISTRY }}/code-place-prod/frontend:${{ github.sha }}-prod
provenance: false
build-args: |
SERVER_NAME=${{ secrets.PROD_SERVER_NAME }}
APP_VERSION=${{ github.sha }}
Expand Down Expand Up @@ -138,6 +140,7 @@ jobs:
file: ./hub/auth_server/Dockerfile
push: true
tags: ${{ secrets.HARBOR_REGISTRY }}/code-place-prod/hub-auth:${{ github.sha }}-prod
provenance: false

update-prod-manifest:
needs: [check-release-branch, ci-backend, ci-frontend, ci-hub-auth]
Expand Down
13 changes: 11 additions & 2 deletions backend/.dockerignore
Original file line number Diff line number Diff line change
@@ -1,4 +1,13 @@
venv
../.idea
venv/
.git
.idea
.DS_Store

__pycache__/
*.pyc
*.log
.env

node_modules/
dist/
build/
9 changes: 7 additions & 2 deletions backend/contents/views/oj.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,16 @@ def get(self, request):
root = ET.fromstring(response.content)

# 필요한 정보 추출
BASE_URL = "https://swedu.pusan.ac.kr"
items = []
for item in root.findall('.//item')[:5]:
link = item.find('link').text or ''
# RSS가 상대 경로(/bbs/...)로 반환할 경우 base URL을 붙여줌
if link and not link.startswith('http'):
link = BASE_URL + link
item_dict = {
'title': item.find('title').text,
'link': item.find('link').text,
'title': item.find('title').text.rstrip("}"),
'link': link,
'pubDate': item.find('pubDate').text
}
items.append(item_dict)
Expand Down
18 changes: 18 additions & 0 deletions backend/contest/migrations/0003_contest_ai_assistant_enabled.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Generated by Django 3.2.25 on 2026-04-23 05:36

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('contest', '0002_contest_allow_paste'),
]

operations = [
migrations.AddField(
model_name='contest',
name='ai_assistant_enabled',
field=models.BooleanField(default=True),
),
]
2 changes: 2 additions & 0 deletions backend/contest/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ class Contest(models.Model):
# 是否可见 false的话相当于删除
visible = models.BooleanField(default=True)
allowed_ip_ranges = JSONField(default=list)
#AI assistant
ai_assistant_enabled = models.BooleanField(default=False)

@property
def status(self):
Expand Down
14 changes: 8 additions & 6 deletions backend/contest/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@

class ContestUserSubmissionSummarySerializer(serializers.Serializer):
user_id = serializers.IntegerField()
username = serializers.CharField()
email = serializers.EmailField()
avatar = serializers.CharField()
school = serializers.CharField()
major = serializers.CharField()
username = serializers.CharField(allow_blank=True)
email = serializers.EmailField(allow_blank=True, required=False)
avatar = serializers.CharField(allow_blank=True)
school = serializers.CharField(allow_blank=True)
major = serializers.CharField(allow_blank=True)
submission_count = serializers.IntegerField()
last_submission_ip = serializers.CharField()
last_submission_ip = serializers.CharField(allow_blank=True)


class CreateConetestSeriaizer(serializers.Serializer):
Expand All @@ -28,6 +28,7 @@ class CreateConetestSeriaizer(serializers.Serializer):
real_time_rank = serializers.BooleanField()
allow_paste = serializers.BooleanField()
allowed_ip_ranges = serializers.ListField(child=serializers.CharField(max_length=32), allow_empty=True)
ai_assistant_enabled = serializers.BooleanField(default=False)


class EditConetestSeriaizer(serializers.Serializer):
Expand All @@ -41,6 +42,7 @@ class EditConetestSeriaizer(serializers.Serializer):
real_time_rank = serializers.BooleanField()
allow_paste = serializers.BooleanField()
allowed_ip_ranges = serializers.ListField(child=serializers.CharField(max_length=32))
ai_assistant_enabled = serializers.BooleanField(required=False)


class ContestAdminSerializer(serializers.ModelSerializer):
Expand Down
178 changes: 178 additions & 0 deletions backend/contest/tests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import copy
from datetime import datetime, timedelta

from django.conf import settings
from django.utils import timezone

from utils.api.tests import APITestCase
Expand Down Expand Up @@ -69,6 +70,75 @@ def test_get_one_contest(self):
response = self.client.get("{}?id={}".format(self.url, id))
self.assertSuccess(response)

def test_create_contest_without_ai_field_defaults_to_false(self):
"""ai_assistant_enabled 필드 없이 대회를 생성하면 기본값이 False여야 한다."""
# DEFAULT_CONTEST_DATA에 ai_assistant_enabled 없음 → 레거시 클라이언트 재현
resp = self.client.post(self.url, data=DEFAULT_CONTEST_DATA)
self.assertSuccess(resp)

contest_id = resp.data["data"]["id"]
contest = Contest.objects.get(id=contest_id)
self.assertFalse(contest.ai_assistant_enabled)

def test_create_contest_with_ai_enabled_explicit(self):
"""ai_assistant_enabled=True를 명시적으로 전달하면 True로 저장된다."""
data = copy.deepcopy(DEFAULT_CONTEST_DATA)
data["ai_assistant_enabled"] = True
resp = self.client.post(self.url, data=data)
self.assertSuccess(resp)

contest_id = resp.data["data"]["id"]
contest = Contest.objects.get(id=contest_id)
self.assertTrue(contest.ai_assistant_enabled)


class ContestAIAssistantMigrationTest(APITestCase):
"""데이터 마이그레이션: 기존 대회 ai_assistant_enabled 일괄 False 전환 검증."""

def setUp(self):
self.create_school_fixtures(college_id=1, college_name="Test", department_id=1, department_name="Test")
self.admin = self.create_admin()

def _bulk_disable(self):
"""0004 마이그레이션의 disable_ai_assistant 함수와 동일한 로직."""
Contest.objects.filter(ai_assistant_enabled=True).update(ai_assistant_enabled=False)

def test_all_enabled_contests_become_disabled(self):
"""ai_assistant_enabled=True인 대회가 모두 False로 전환된다."""
c1 = Contest.objects.create(created_by=self.admin, **DEFAULT_CONTEST_DATA)
c2 = Contest.objects.create(created_by=self.admin, **{**DEFAULT_CONTEST_DATA, "title": "second"})
Contest.objects.filter(pk__in=[c1.pk, c2.pk]).update(ai_assistant_enabled=True)

self._bulk_disable()

c1.refresh_from_db()
c2.refresh_from_db()
self.assertFalse(c1.ai_assistant_enabled)
self.assertFalse(c2.ai_assistant_enabled)

def test_already_disabled_contests_remain_disabled(self):
"""이미 ai_assistant_enabled=False인 대회는 마이그레이션 후에도 False를 유지한다."""
contest = Contest.objects.create(created_by=self.admin, **DEFAULT_CONTEST_DATA)
self.assertFalse(contest.ai_assistant_enabled)

self._bulk_disable()

contest.refresh_from_db()
self.assertFalse(contest.ai_assistant_enabled)

def test_migration_does_not_affect_other_fields(self):
"""마이그레이션이 ai_assistant_enabled 외의 필드를 변경하지 않는다."""
contest = Contest.objects.create(created_by=self.admin, **DEFAULT_CONTEST_DATA)
Contest.objects.filter(pk=contest.pk).update(ai_assistant_enabled=True)

self._bulk_disable()

contest.refresh_from_db()
self.assertFalse(contest.ai_assistant_enabled)
self.assertEqual(contest.title, DEFAULT_CONTEST_DATA["title"])
self.assertTrue(contest.visible)
self.assertTrue(contest.real_time_rank)


class ContestAPITest(APITestCase):

Expand Down Expand Up @@ -181,3 +251,111 @@ def setUp(self):
def get_contest_rank(self):
resp = self.client.get(self.url + "?contest_id=" + self.acm_contest.id)
self.assertSuccess(resp)


class ContestParticipantsAPITest(APITestCase):

def setUp(self):
from problem.tests import DEFAULT_PROBLEM_DATA, ProblemCreateTestBase

self.create_school_fixtures(college_id=1, college_name="Test", department_id=1, department_name="Test")
self.admin = self.create_admin()
self.user = self.create_user(email="test@test.com", username="test", password="test1234!", login=False)
self.contest = Contest.objects.create(created_by=self.admin, **DEFAULT_CONTEST_DATA)
self.problem = ProblemCreateTestBase.add_problem(DEFAULT_PROBLEM_DATA, self.admin)
self.problem.contest_id = self.contest.id
self.problem.save()
self.url = self.reverse("contest_participants_api")

def test_participants_are_grouped_by_user_id(self):
from submission.models import JudgeStatus, Submission

Submission.objects.create(
user_id=self.user.id,
username="oldname",
language="C++",
code="test code",
problem_id=self.problem.id,
ip="127.0.0.1",
contest_id=self.contest.id,
result=JudgeStatus.PENDING,
statistic_info={"time_cost": "100", "memory_cost": "1024"},
shared=False,
first_failed_tc_idx=None,
)
Submission.objects.create(
user_id=self.user.id,
username="newname",
language="C++",
code="test code",
problem_id=self.problem.id,
ip="127.0.0.1",
contest_id=self.contest.id,
result=JudgeStatus.PENDING,
statistic_info={"time_cost": "100", "memory_cost": "1024"},
shared=False,
first_failed_tc_idx=None,
)

resp = self.client.get(f"{self.url}?contest_id={self.contest.id}")
self.assertSuccess(resp)

participants = resp.data["data"]
self.assertEqual(len(participants), 1)
self.assertEqual(participants[0]["user_id"], self.user.id)
self.assertEqual(participants[0]["username"], self.user.username)
self.assertEqual(participants[0]["submission_count"], 2)

def test_participants_requires_contest_id(self):
resp = self.client.get(self.url)
self.assertFailed(resp, "Invalid parameter, contest_id is required")

def test_participants_rejects_invalid_contest_id(self):
resp = self.client.get(f"{self.url}?contest_id=abc")
self.assertFailed(resp, "Invalid parameter, contest_id is required")

def test_participants_fallback_to_submission_username_when_user_is_missing(self):
from submission.models import JudgeStatus, Submission

older_submission = Submission.objects.create(
user_id=self.user.id,
username="zzz_user",
language="C++",
code="test code",
problem_id=self.problem.id,
ip="9.9.9.9",
contest_id=self.contest.id,
result=JudgeStatus.PENDING,
statistic_info={"time_cost": "100", "memory_cost": "1024"},
shared=False,
first_failed_tc_idx=None,
)
latest_submission = Submission.objects.create(
user_id=self.user.id,
username="aaa_user",
language="C++",
code="test code",
problem_id=self.problem.id,
ip="1.1.1.1",
contest_id=self.contest.id,
result=JudgeStatus.PENDING,
statistic_info={"time_cost": "100", "memory_cost": "1024"},
shared=False,
first_failed_tc_idx=None,
)
Submission.objects.filter(id=older_submission.id).update(create_time=timezone.now() - timedelta(minutes=1))
Submission.objects.filter(id=latest_submission.id).update(create_time=timezone.now())

self.user.delete()

resp = self.client.get(f"{self.url}?contest_id={self.contest.id}")
self.assertSuccess(resp)

participants = resp.data["data"]
self.assertEqual(len(participants), 1)
self.assertEqual(participants[0]["username"], "aaa_user")
self.assertEqual(participants[0]["email"], "")
self.assertEqual(participants[0]["avatar"], f"{settings.AVATAR_URI_PREFIX}/default.png")
self.assertEqual(participants[0]["school"], "")
self.assertEqual(participants[0]["major"], "")
self.assertEqual(participants[0]["last_submission_ip"], "1.1.1.1")
Loading
Loading