Files
KF-OnlineJudge/backend/src/kf_oj/modules/problems/publication.py
T

83 lines
3.1 KiB
Python

"""One admission and immutable publication path for local and web imports."""
from uuid import uuid4
from sqlalchemy import func, select
from kf_oj.contracts import judging_v2 as v2
from kf_oj.contracts.judging import MAX_SOURCE_BYTES, ArtifactReference
from kf_oj.modules.problems import repository
from kf_oj.modules.problems.import_format import ProblemImport
from kf_oj.modules.problems.models import ProblemCase, ProblemVersion
from kf_oj.modules.problems.public import JudgingVersion, ProblemUnavailable
def admit_version(policy, manifest, version_id, problem_id, cases):
legacy = isinstance(manifest, ProblemImport)
projection = JudgingVersion(
version_id,
problem_id,
manifest.languages,
manifest.toolchain if legacy else None,
manifest.compile_limits if legacy else None,
manifest.run_limits if legacy else None,
manifest.job_wall_time_us if legacy else None,
cases,
manifest.schema_version,
() if legacy else manifest.language_configurations,
)
for language in manifest.languages:
v2.admit_manifest(
policy,
projection.manifest(
uuid4(),
uuid4(),
language,
ArtifactReference(digest="0" * 64, bytes=MAX_SOURCE_BYTES),
),
1,
)
return projection
async def publish_version(session, problem, manifest, preview, version_id, cases):
"""Caller holds the logical slug/row locks and has made all artifacts durable."""
if not problem.enabled:
raise ProblemUnavailable("problem disabled")
legacy = isinstance(manifest, ProblemImport)
version = ProblemVersion(
id=version_id,
problem_id=problem.id,
revision=await repository.next_revision(session, problem.id),
title=manifest.title,
statement=preview.statement,
languages=[lang.value for lang in manifest.languages],
judging_schema_version=manifest.schema_version,
language_configurations=None
if legacy
else [c.model_dump(mode="json") for c in manifest.language_configurations],
toolchain=manifest.toolchain.model_dump(mode="json") if legacy else None,
compile_limits=manifest.compile_limits.model_dump(mode="json") if legacy else None,
run_limits=manifest.run_limits.model_dump(mode="json") if legacy else None,
job_wall_time_us=manifest.job_wall_time_us if legacy else None,
comparison=manifest.comparison,
public_samples=[s.model_dump(mode="json") for s in preview.samples],
)
session.add(version)
await session.flush()
for position, case in enumerate(cases):
session.add(
ProblemCase(
id=case.case_id,
version_id=version_id,
position=position,
input_digest=case.input.digest,
expected_digest=case.expected.digest,
)
)
await session.flush()
version.published_at = await session.scalar(select(func.now()))
problem.active_version_id = version_id
await session.flush()
return version