feat: multi-test case view
This commit is contained in:
parent
6477fdc20c
commit
aab211902e
12 changed files with 315 additions and 124 deletions
|
|
@ -16,6 +16,7 @@ from urllib3.util.retry import Retry
|
|||
|
||||
from .base import BaseScraper
|
||||
from .models import (
|
||||
CombinedTest,
|
||||
ContestListResult,
|
||||
ContestSummary,
|
||||
MetadataResult,
|
||||
|
|
@ -364,6 +365,7 @@ async def main_async() -> int:
|
|||
success=False,
|
||||
error="Usage: atcoder.py tests <contest_id>",
|
||||
problem_id="",
|
||||
combined=CombinedTest(input="", expected=""),
|
||||
tests=[],
|
||||
timeout_ms=0,
|
||||
memory_mb=0,
|
||||
|
|
|
|||
|
|
@ -34,10 +34,13 @@ class BaseScraper(ABC):
|
|||
def _create_tests_error(
|
||||
self, error_msg: str, problem_id: str = "", url: str = ""
|
||||
) -> TestsResult:
|
||||
from .models import CombinedTest
|
||||
|
||||
return TestsResult(
|
||||
success=False,
|
||||
error=f"{self.platform_name}: {error_msg}",
|
||||
problem_id=problem_id,
|
||||
combined=CombinedTest(input="", expected=""),
|
||||
tests=[],
|
||||
timeout_ms=0,
|
||||
memory_mb=0,
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ from scrapling.fetchers import StealthyFetcher
|
|||
|
||||
from .base import BaseScraper
|
||||
from .models import (
|
||||
CombinedTest,
|
||||
ContestListResult,
|
||||
ContestSummary,
|
||||
MetadataResult,
|
||||
|
|
@ -279,6 +280,7 @@ async def main_async() -> int:
|
|||
success=False,
|
||||
error="Usage: codechef.py tests <contest_id>",
|
||||
problem_id="",
|
||||
combined=CombinedTest(input="", expected=""),
|
||||
tests=[],
|
||||
timeout_ms=0,
|
||||
memory_mb=0,
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ from scrapling.fetchers import StealthyFetcher
|
|||
|
||||
from .base import BaseScraper
|
||||
from .models import (
|
||||
CombinedTest,
|
||||
ContestListResult,
|
||||
ContestSummary,
|
||||
MetadataResult,
|
||||
|
|
@ -126,16 +127,12 @@ def _extract_samples(block: Tag) -> tuple[list[TestCase], bool]:
|
|||
)
|
||||
for k in keys
|
||||
]
|
||||
samples_with_prefix = [
|
||||
TestCase(input=f"1\n{tc.input}", expected=tc.expected) for tc in samples
|
||||
]
|
||||
return samples_with_prefix, True
|
||||
return samples, True
|
||||
|
||||
inputs = [_text_from_pre(p) for p in input_pres]
|
||||
outputs = [_text_from_pre(p) for p in output_pres]
|
||||
n = min(len(inputs), len(outputs))
|
||||
samples = [TestCase(input=inputs[i], expected=outputs[i]) for i in range(n)]
|
||||
return samples, False
|
||||
return [TestCase(input=inputs[i], expected=outputs[i]) for i in range(n)], False
|
||||
|
||||
|
||||
def _is_interactive(block: Tag) -> bool:
|
||||
|
|
@ -164,18 +161,35 @@ def _parse_all_blocks(html: str) -> list[dict[str, Any]]:
|
|||
name = _extract_title(b)[1]
|
||||
if not letter:
|
||||
continue
|
||||
tests, multi_test = _extract_samples(b)
|
||||
raw_samples, is_grouped = _extract_samples(b)
|
||||
timeout_ms, memory_mb = _extract_limits(b)
|
||||
interactive = _is_interactive(b)
|
||||
|
||||
if is_grouped and raw_samples:
|
||||
combined_input = f"{len(raw_samples)}\n" + "\n".join(
|
||||
tc.input for tc in raw_samples
|
||||
)
|
||||
combined_expected = "\n".join(tc.expected for tc in raw_samples)
|
||||
individual_tests = [
|
||||
TestCase(input=f"1\n{tc.input}", expected=tc.expected)
|
||||
for tc in raw_samples
|
||||
]
|
||||
else:
|
||||
combined_input = "\n".join(tc.input for tc in raw_samples)
|
||||
combined_expected = "\n".join(tc.expected for tc in raw_samples)
|
||||
individual_tests = raw_samples
|
||||
|
||||
out.append(
|
||||
{
|
||||
"letter": letter,
|
||||
"name": name,
|
||||
"tests": tests,
|
||||
"combined_input": combined_input,
|
||||
"combined_expected": combined_expected,
|
||||
"tests": individual_tests,
|
||||
"timeout_ms": timeout_ms,
|
||||
"memory_mb": memory_mb,
|
||||
"interactive": interactive,
|
||||
"multi_test": multi_test,
|
||||
"multi_test": is_grouped,
|
||||
}
|
||||
)
|
||||
return out
|
||||
|
|
@ -252,6 +266,10 @@ class CodeforcesScraper(BaseScraper):
|
|||
json.dumps(
|
||||
{
|
||||
"problem_id": pid,
|
||||
"combined": {
|
||||
"input": b.get("combined_input", ""),
|
||||
"expected": b.get("combined_expected", ""),
|
||||
},
|
||||
"tests": [
|
||||
{"input": t.input, "expected": t.expected} for t in tests
|
||||
],
|
||||
|
|
@ -298,6 +316,7 @@ async def main_async() -> int:
|
|||
success=False,
|
||||
error="Usage: codeforces.py tests <contest_id>",
|
||||
problem_id="",
|
||||
combined=CombinedTest(input="", expected=""),
|
||||
tests=[],
|
||||
timeout_ms=0,
|
||||
memory_mb=0,
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ import httpx
|
|||
|
||||
from .base import BaseScraper
|
||||
from .models import (
|
||||
CombinedTest,
|
||||
ContestListResult,
|
||||
ContestSummary,
|
||||
MetadataResult,
|
||||
|
|
@ -233,8 +234,16 @@ class CSESScraper(BaseScraper):
|
|||
except Exception:
|
||||
tests = []
|
||||
timeout_ms, memory_mb, interactive = 0, 0, False
|
||||
|
||||
combined_input = "\n".join(t.input for t in tests)
|
||||
combined_expected = "\n".join(t.expected for t in tests)
|
||||
|
||||
return {
|
||||
"problem_id": pid,
|
||||
"combined": {
|
||||
"input": combined_input,
|
||||
"expected": combined_expected,
|
||||
},
|
||||
"tests": [
|
||||
{"input": t.input, "expected": t.expected} for t in tests
|
||||
],
|
||||
|
|
@ -282,6 +291,7 @@ async def main_async() -> int:
|
|||
success=False,
|
||||
error="Usage: cses.py tests <category>",
|
||||
problem_id="",
|
||||
combined=CombinedTest(input="", expected=""),
|
||||
tests=[],
|
||||
timeout_ms=0,
|
||||
memory_mb=0,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,13 @@ class TestCase(BaseModel):
|
|||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
|
||||
class CombinedTest(BaseModel):
|
||||
input: str
|
||||
expected: str
|
||||
|
||||
model_config = ConfigDict(extra="forbid")
|
||||
|
||||
|
||||
class ProblemSummary(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
|
|
@ -46,6 +53,7 @@ class ContestListResult(ScrapingResult):
|
|||
|
||||
class TestsResult(ScrapingResult):
|
||||
problem_id: str
|
||||
combined: CombinedTest
|
||||
tests: list[TestCase] = Field(default_factory=list)
|
||||
timeout_ms: int
|
||||
memory_mb: float
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue