mirrored 16 minutes ago
0
Your Namefix type error, fix custom challenge b90d114
"""
Shared Pydantic dataclasses for vimgolf-gym
"""

import json
from datetime import datetime
from pathlib import Path

from parse import parse
from pydantic import BaseModel, Field
from typing import Optional

class VimGolfCustomChallenge(BaseModel):
    """Represents a custom VimGolf challenge

    Attributes:
        input: The input of the challenge (required)
        output: The output of the challenge (required)
        name: The name of the challenge (optional)
        description: The description of the challenge (optional)
        solution: The VimGolf solution (optional)
    """
    input: str
    output: str
    name: Optional[str] = None
    description: Optional[str] = None
    solution: Optional[str] = None


class VimGolfEnvResult(BaseModel):
    """Represents a single result of VimGolf challenge environment,

    Attributes:
        correct: The challenge is solved or not
        keys: VimGolf solution keys (converted from raw representation)
        score: Keystrokes count (the lower the better)
    """

    correct: bool
    keys: str
    score: int


class VimGolfParsedPublicSolutionHeader(BaseModel):
    """Represents the header of a VimGolf public solution entry.

    Attributes:
        rank: The rank of the solution (provided as a string in the reference).
        score: The score of the solution (provided as a string in the reference).
        user_name: The name of the user who submitted the solution.
        user_id: The ID of the user who submitted the solution.
        date: The date the solution was submitted.
    """

    rank: str
    score: str
    user_name: str
    user_id: str
    date: datetime


class VimGolfPublicSolution(BaseModel):
    """Represents a public solution entry in VimGolf.

    Attributes:
        rank: The rank of the solution (provided as a string in the reference).
        solution: The sequence of Vim keystrokes used in the solution.
        header: Descriptive header containing user and challenge details.
    """

    rank: str
    solution: str
    header: str


class VimGolfChallengeMetadata(BaseModel):
    """
    Represents metadata for a VimGolf challenge.

    Attributes:
        href: URL path to the challenge.
        title: Name/description of the challenge.
        detail: Explanation of the challenge task.
        challenge_hash: Unique identifier hash for the challenge.
    """

    href: str
    title: str
    detail: str
    challenge_hash: str


class VimGolfChallengeDefinition(BaseModel):
    """
    Represents a VimGolf challenge definition including input/output code and client information.

    Attributes:
        input: Starting code and its type (nested model)
        output: Expected solution code and its type (nested model)
        client_version: Version of the client that created the challenge
    """

    class InputOutputModel(BaseModel):
        """
        Nested model for input/output code definitions.

        Attributes:
            data: The actual code content
            type: Programming language identifier (e.g., 'rb' for Ruby)
        """

        data: str
        type: str

    input: InputOutputModel = Field(..., alias="in")
    output: InputOutputModel = Field(..., alias="out")
    client_version: str = Field(..., alias="client")

    class Config:
        validate_by_name = True


def parse_json_file(file_path: Path, model: type[BaseModel]) -> BaseModel:
    """Parse a JSON file into a specified Pydantic model
    
    Args:
        file_path (Path): Path to the JSON file.
        model (type[BaseModel]): Pydantic model to parse the JSON into.
    
    Returns:
        BaseModel: Parsed model instance
    """
    with open(file_path, "r", encoding="utf-8") as f:
        data = json.load(f)
    return model.parse_obj(data)


def parse_public_solution_header(input_str: str) -> VimGolfParsedPublicSolutionHeader:
    """Parse the public solution header string
    
    Args:
        input_str (str): Public solution header string.
    
    Returns:
        VimGolfParsedPublicSolutionHeader
    """
    template = "#{rank} {user_name} / @{user_id} - Score: {score} - {month}/{day}/{year} @ {hour}:{minute}"

    # Parse the input string using the template
    parsed_data = parse(template, input_str)

    # Convert parsed fields to integers and process the year
    month = int(parsed_data["month"])
    day = int(parsed_data["day"])
    year = int(parsed_data["year"])
    hour = int(parsed_data["hour"])
    minute = int(parsed_data["minute"])

    # Adjust two-digit year to four digits
    full_year = year + 2000 if year < 70 else year + 1900

    # Create a datetime object and format the timestamp
    dt = datetime(full_year, month, day, hour, minute)
    # timestamp = dt.strftime("%Y-%m-%d %H:%M:%S")

    ret = VimGolfParsedPublicSolutionHeader(
        rank=parsed_data["rank"],
        score=parsed_data["score"],
        user_name=parsed_data["user_name"],
        user_id=parsed_data["user_id"],
        date=dt,
    )
    return ret