|
"""
|
|
Pydantic models for proportion calculation inputs and outputs.
|
|
Provides robust validation and clear error messages.
|
|
"""
|
|
|
|
from typing import Optional
|
|
from pydantic import BaseModel, Field, model_validator
|
|
|
|
|
|
class PercentOfInput(BaseModel):
|
|
"""Input for calculating what percentage part is of whole."""
|
|
|
|
part: float = Field(description="The part value")
|
|
whole: float = Field(description="The whole value (must not be zero)")
|
|
|
|
|
|
|
|
class PercentOfOutput(BaseModel):
|
|
"""Output for percentage calculation."""
|
|
|
|
percentage: float = Field(description="The calculated percentage")
|
|
|
|
|
|
class ProportionInput(BaseModel):
|
|
"""Input for solving proportion a/b = c/d with exactly one missing value."""
|
|
|
|
a: Optional[float] = Field(None, description="First numerator")
|
|
b: Optional[float] = Field(None, description="First denominator")
|
|
c: Optional[float] = Field(None, description="Second numerator")
|
|
d: Optional[float] = Field(None, description="Second denominator")
|
|
|
|
@model_validator(mode='after')
|
|
def validate_exactly_one_none(self) -> 'ProportionInput':
|
|
"""Ensure exactly one value is None (missing)."""
|
|
values = [self.a, self.b, self.c, self.d]
|
|
none_count = sum(1 for v in values if v is None)
|
|
|
|
assert none_count == 1, "Exactly one value must be None (missing) to solve proportion"
|
|
|
|
return self
|
|
|
|
|
|
class ProportionOutput(BaseModel):
|
|
"""Output for proportion calculation."""
|
|
|
|
missing: float = Field(description="The calculated missing value")
|
|
|
|
|
|
class ScaleByRatioInput(BaseModel):
|
|
"""Input for scaling a value by a ratio."""
|
|
|
|
value: float = Field(description="The value to scale")
|
|
ratio: float = Field(description="The scaling ratio")
|
|
|
|
|
|
class ScaleByRatioOutput(BaseModel):
|
|
"""Output for ratio scaling."""
|
|
|
|
result: float = Field(description="The scaled result")
|
|
|
|
|
|
class DirectKInput(BaseModel):
|
|
"""Input for finding constant of proportionality k in y = kx."""
|
|
|
|
x: float = Field(description="The x value (cannot be zero)")
|
|
y: float = Field(description="The y value")
|
|
|
|
|
|
|
|
class DirectKOutput(BaseModel):
|
|
"""Output for proportionality constant calculation."""
|
|
|
|
k: float = Field(description="The proportionality constant")
|
|
|
|
|
|
class ResizeDimensionsInput(BaseModel):
|
|
"""Input for resizing dimensions with uniform scale factor."""
|
|
|
|
width: float = Field(description="Original width (must be non-negative)")
|
|
height: float = Field(description="Original height (must be non-negative)")
|
|
scale: float = Field(description="Scale factor (must be positive)")
|
|
|
|
|
|
class ResizeDimensionsOutput(BaseModel):
|
|
"""Output for dimension resizing."""
|
|
|
|
new_width: float = Field(description="The new width after scaling")
|
|
new_height: float = Field(description="The new height after scaling")
|
|
|
|
|
|
|
|
class ErrorResponse(BaseModel):
|
|
"""Standard error response format."""
|
|
|
|
error: str = Field(description="Error message")
|
|
detail: Optional[str] = Field(None, description="Additional error details") |