testspace / space_app /models.py
nilshoehing's picture
Upload TopoBench Space app
67acd34 verified
Raw
History Blame Contribute Delete
1.99 kB
from __future__ import annotations
from dataclasses import dataclass
from statistics import mean, median
from typing import Any
ALLOWED_PUZZLES = [
"bridges",
"flow_free",
"galaxies",
"loopy",
"pattern",
"undead",
]
ALLOWED_DIFFICULTIES = ["easy", "medium", "hard"]
SESSION_STATUSES = ["assigned", "ready", "attempted", "solved"]
def normalize_player_name(value: str) -> str:
parts = value.strip().split()
return " ".join(parts).lower()
def engine_for_puzzle(puzzle_type: str) -> str:
return f"{puzzle_type}_ascii"
@dataclass(frozen=True)
class DatasetRow:
filename: str
puzzlename: str
args: str
problem: str
solution: str
difficulty: str
image_base64: str | None = None
@classmethod
def from_payload(cls, payload: dict[str, Any]) -> "DatasetRow":
return cls(
filename=str(payload["filename"]),
puzzlename=str(payload["puzzlename"]),
args=str(payload.get("args") or ""),
problem=str(payload["problem"]),
solution=str(payload["solution"]),
difficulty=str(payload["difficulty"]),
image_base64=payload.get("image_base64"),
)
@dataclass(frozen=True)
class SolveAggregate:
player_name_norm: str
puzzle_type: str
difficulty: str
solve_count: int
avg_ms: float
median_ms: float
min_ms: int
max_ms: int
@classmethod
def from_rows(
cls,
*,
player_name_norm: str,
puzzle_type: str,
difficulty: str,
elapsed_values: list[int],
) -> "SolveAggregate":
return cls(
player_name_norm=player_name_norm,
puzzle_type=puzzle_type,
difficulty=difficulty,
solve_count=len(elapsed_values),
avg_ms=float(mean(elapsed_values)),
median_ms=float(median(elapsed_values)),
min_ms=min(elapsed_values),
max_ms=max(elapsed_values),
)