/
Vimgolfb90d114
"""
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