Skip to content

Commit

Permalink
feat(online_judge): 从OJ获取题目
Browse files Browse the repository at this point in the history
  • Loading branch information
XYCode-Kerman committed Apr 16, 2024
1 parent 85462c5 commit 574d45e
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 5 deletions.
2 changes: 2 additions & 0 deletions online_judge/contests/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from fastapi import APIRouter

from .manager import router as manager_router
from .problems import router as problems_router

router = APIRouter(prefix='/contests', tags=['比赛'])
router.include_router(manager_router)
router.include_router(problems_router)
16 changes: 16 additions & 0 deletions online_judge/contests/problems.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from typing import *

from fastapi import APIRouter, Depends, HTTPException

from ..oj_models import OJContest, OJProblem
from ..utils.dependencies import require_contest_started

router = APIRouter(prefix='/detail', tags=['题目信息'])


@router.get('/{contest_id}/problems', name='获取比赛题目', summary='> 注意:仅当比赛开始后可以调用', response_model=List[OJProblem])
async def get_contest_problems(contest: OJContest = Depends(require_contest_started)):
return [
OJProblem.load_from_ccf_problem(x)
for x in contest.read_ccf.contest.problems
]
2 changes: 1 addition & 1 deletion online_judge/oj_models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .contest import OJContest
from .contest import OJContest, OJProblem
from .user import User
42 changes: 40 additions & 2 deletions online_judge/oj_models/contest.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
from __future__ import annotations

from datetime import datetime
from pathlib import Path
from uuid import UUID
from typing import *
from uuid import UUID, uuid5

from pydantic import BaseModel
from pydantic import BaseModel, computed_field

import ccf_parser
from ccf_parser import CCF

ITSWA_OJ_PROBLEM_NAMESPACE = UUID('3a438ef7-a46d-4c85-af4d-45cbad5af9f3')


class OJContest(BaseModel):
"""有别于 ccf_parser 中的 Contest,更加详细的比赛信息需要从 ccf_parser 中获取"""
Expand All @@ -19,3 +25,35 @@ class OJContest(BaseModel):
def read_ccf(self) -> CCF:
data = self.ccf_file.read_text('utf-8')
return CCF.model_validate_json(data)


class OJProblem(BaseModel):
"""有别于 ccf_parser 中的 Problem,更加详细的题目信息需要从 ccf_parser 中获取"""

name: str
background: Optional[str] = '此题无题目背景' # 题目背景
description: str
input_format: str
output_format: str
source_file_name: str
languages: List[Literal['CPP']] = ['CPP']

@computed_field
@property
def problem_id(self) -> UUID:
return uuid5(
ITSWA_OJ_PROBLEM_NAMESPACE,
self.source_file_name
)

@staticmethod
def load_from_ccf_problem(problem: ccf_parser.Problem) -> OJProblem:
return OJProblem(
name=problem.name,
background=problem.background,
description=problem.description,
input_format=problem.input_format,
output_format=problem.output_format,
source_file_name=problem.judge_config.source_file_name,
languages=['CPP'] # TODO: 默认支持 C++ 语言,后续可以添加更多语言支持。
)
3 changes: 2 additions & 1 deletion online_judge/utils/dependencies/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
from .base import require_ccf_file
from .base import (require_ccf, require_ccf_file, require_contest_started,
require_oj_contest)
29 changes: 28 additions & 1 deletion online_judge/utils/dependencies/base.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import datetime
import uuid
from pathlib import Path

import pydantic
from fastapi import HTTPException
from fastapi import Depends, HTTPException
from tinydb import Query

from ccf_parser import CCF

from ...oj_models import OJContest
from ..database import contestscol


def require_ccf_file(ccf_file: Path) -> Path:
if ccf_file.name != "ccf.json":
Expand All @@ -23,3 +29,24 @@ def require_ccf_file(ccf_file: Path) -> Path:
status_code=400, detail=f"CCF 文件格式错误: {e.errors()}")

return ccf_file


def require_ccf(ccf_file: Path = Depends(require_ccf_file)) -> CCF:
return CCF.model_validate_json(ccf_file.read_text('utf-8'))


def require_oj_contest(contest_id: uuid.UUID) -> OJContest:
query = Query()
results = contestscol.search(query.contest_id == contest_id.__str__())

if len(results) == 0:
raise HTTPException(status_code=404, detail="比赛不存在")

return OJContest.model_validate(results[0])


def require_contest_started(contest: OJContest = Depends(require_oj_contest)) -> OJContest:
if datetime.datetime.now().replace(tzinfo=None) < contest.start_time.replace(tzinfo=None):
raise HTTPException(status_code=403, detail="比赛未开始")

return contest

0 comments on commit 574d45e

Please sign in to comment.