Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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: 1 addition & 2 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,8 @@ name: Deploy to dev
on:
push:
branches:
- deploy/add-email-sender
- dev
- feat/api-SandBox
- feat/finish_all_submission_function

concurrency: deploy-dev

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 5.2.7 on 2025-12-28 11:16

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('submissions', '0003_remove_editorial_editorials_problem_79b740_idx_and_more'),
]

operations = [
migrations.AlterField(
model_name='submissionresult',
name='status',
field=models.CharField(choices=[('accepted', 'Accepted'), ('wrong_answer', 'Wrong Answer'), ('compile_error', 'Compile Error'), ('time_limit_exceeded', 'Time Limit Exceeded'), ('memory_limit_exceeded', 'Memory Limit Exceeded'), ('runtime_error', 'Runtime Error')], max_length=30),
),
migrations.AlterField(
model_name='submissionresult',
name='test_case_id',
field=models.IntegerField(blank=True, null=True),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Generated by Django 5.2.7 on 2025-12-28 15:01

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('submissions', '0004_alter_submissionresult_status_and_more'),
]

operations = [
migrations.AlterModelOptions(
name='submissionresult',
options={'ordering': ['subtask_id', 'test_case_index']},
),
migrations.RemoveIndex(
model_name='submissionresult',
name='submission__submiss_cb29e7_idx',
),
migrations.AddField(
model_name='submissionresult',
name='subtask_id',
field=models.IntegerField(default=0),
preserve_default=False,
),
migrations.AlterField(
model_name='submissionresult',
name='id',
field=models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
),
migrations.AlterUniqueTogether(
name='submissionresult',
unique_together={('submission', 'subtask_id', 'test_case_index')},
),
migrations.AddIndex(
model_name='submissionresult',
index=models.Index(fields=['submission', 'subtask_id', 'test_case_index'], name='submission__submiss_37b35f_idx'),
),
]
19 changes: 11 additions & 8 deletions submissions/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class SubmissionResult(models.Model):
STATUS_CHOICES = [
('accepted', 'Accepted'),
('wrong_answer', 'Wrong Answer'),
('compile_error', 'Compile Error'),
('time_limit_exceeded', 'Time Limit Exceeded'),
('memory_limit_exceeded', 'Memory Limit Exceeded'),
('runtime_error', 'Runtime Error'),
Expand All @@ -119,14 +120,14 @@ class SubmissionResult(models.Model):
('solved', 'Solved'),
]

# Primary key - UUID
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
# Foreign keys - 複合主鍵的一部分
submission = models.ForeignKey(Submission, on_delete=models.CASCADE, related_name='results')
subtask_id = models.IntegerField() # 複合主鍵:第幾個子題
test_case_index = models.IntegerField() # 複合主鍵:第幾筆測資(相對於 subtask)

# Foreign keys
# Other foreign keys
problem_id = models.IntegerField()
submission = models.ForeignKey(Submission, on_delete=models.CASCADE, related_name='results')
test_case_id = models.IntegerField()
test_case_index = models.IntegerField()
test_case_id = models.IntegerField(null=True, blank=True) # CE 時可能為 None

# Status and scoring
status = models.CharField(max_length=30, choices=STATUS_CHOICES)
Expand All @@ -149,10 +150,12 @@ class SubmissionResult(models.Model):
created_at = models.DateTimeField(auto_now_add=True)

class Meta:
# 複合主鍵:submission + subtask_id + test_case_index
unique_together = [['submission', 'subtask_id', 'test_case_index']]
indexes = [
models.Index(fields=['submission', 'test_case_index']),
models.Index(fields=['submission', 'subtask_id', 'test_case_index']),
]
ordering = ['test_case_index']
ordering = ['subtask_id', 'test_case_index']
db_table = 'submission_results'

def __str__(self):
Expand Down
24 changes: 21 additions & 3 deletions submissions/sandbox_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ def submit_to_sandbox(submission):
# 只有在啟用自訂 checker 時才使用設定的 checker_name,否則強制使用 'diff'
'use_checker': problem.use_custom_checker,
'checker_name': problem.checker_name if problem.use_custom_checker else 'diff',
'use_static_analysis': False, # TODO: 從 assignment 設定取得
'use_static_analysis': problem.use_static_analysis,
'priority': 0, # 一般優先級
'callback_url': settings.BACKEND_BASE_URL.rstrip('/'), # Sandbox 判題完成後回傳結果的 URL(注意:是 submission 不是 submissions)
}
Expand All @@ -116,6 +116,13 @@ def submit_to_sandbox(submission):
headers = {}
if SANDBOX_API_KEY:
headers['X-API-KEY'] = SANDBOX_API_KEY
logger.info(f'Using API Key: {SANDBOX_API_KEY[:10]}...') # 只顯示前 10 個字元
else:
logger.warning('SANDBOX_API_KEY is not set!')

logger.debug(f'Request URL: {url}')
logger.debug(f'Request data: {data}')
logger.debug(f'Request headers: {headers}')

response = requests.post(
url,
Expand All @@ -125,7 +132,10 @@ def submit_to_sandbox(submission):
timeout=SANDBOX_TIMEOUT
)

# 8. 檢查回應
# 7. 檢查回應
logger.info(f'Sandbox response status: {response.status_code}')
if response.status_code >= 400:
logger.error(f'Sandbox error response: {response.text}')
response.raise_for_status()
result = response.json()

Expand Down Expand Up @@ -161,8 +171,16 @@ def submit_selftest_to_sandbox(problem_id, language_type, source_code, stdin_dat
"""
import uuid
import hashlib
from problems.models import Problems

try:
# 取得題目資訊(用於靜態分析設定)
try:
problem = Problems.objects.get(id=problem_id)
except Problems.DoesNotExist:
logger.error(f'Problem {problem_id} not found for selftest')
return None

# 產生臨時 ID(不存 DB,只用於追蹤)
temp_id = f"selftest-{uuid.uuid4()}"

Expand All @@ -186,7 +204,7 @@ def submit_selftest_to_sandbox(problem_id, language_type, source_code, stdin_dat
'memory_limit': 262144, # 256 MB
'use_checker': False,
'checker_name': 'diff',
'use_static_analysis': False,
'use_static_analysis': problem.use_static_analysis,
'priority': -1, # 低優先級(自定義測試不影響正式提交)
'callback_url': settings.BACKEND_BASE_URL.rstrip('/'), # Custom test callback URL
}
Expand Down
2 changes: 1 addition & 1 deletion submissions/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ class SubmissionResultSerializer(serializers.ModelSerializer):
class Meta:
model = SubmissionResult
fields = '__all__'
read_only_fields = ['id', 'created_at']
read_only_fields = ['created_at'] # 移除 'id',因為不再有單一主鍵


class UserProblemStatsSerializer(serializers.ModelSerializer):
Expand Down
Loading