api/app/models.py
2026-03-31 11:43:01 +02:00

175 lines
6.4 KiB
Python

from pydantic import BaseModel, Field
from typing import Optional
# ──────────────────────────────────────────────
# Core review models
# ──────────────────────────────────────────────
class Review(BaseModel):
"""A single review of a movie, book, or television show."""
date: str = Field(
...,
description="Date the review was recorded, in YYYY-MM-DD format.",
examples=["2025-02-06"],
)
unixTime: int = Field(
...,
description="Unix timestamp corresponding to the review date.",
examples=[1738796400],
)
category: Optional[str] = Field(
None,
description="Media type: Movies, Books, or Television.",
examples=["Movies"],
)
title: Optional[str] = Field(
None,
description="Title of the work being reviewed.",
examples=["The Brutalist"],
)
creator: Optional[str] = Field(
None,
description="Director, author, or showrunner of the work.",
examples=["Brady Corbet"],
)
genre: Optional[str] = Field(
None,
description="Genre classification of the work.",
examples=["Drama"],
)
rating: Optional[float] = Field(
None,
description="Rating on a scale from -3.0 (worst) to 3.0 (best). A rating of 0.0 indicates a neutral opinion (it was meh).",
examples=[3.0],
)
review: Optional[str] = Field(
None,
description="Free-text review. Empty string or '.' indicates no written review.",
examples=[
"A wonderfully expansive film about the immigrant experience."
],
)
year: Optional[int] = Field(
None,
description="Release or publication year of the work.",
examples=[2024],
)
model_config = {"from_attributes": True}
class ReviewListResponse(BaseModel):
"""Paginated response wrapper for a list of reviews."""
total: int = Field(
...,
description="Total number of reviews matching the query filters.",
examples=[642],
)
limit: int = Field(
...,
description="Maximum number of reviews returned in this response.",
examples=[20],
)
offset: int = Field(
...,
description="Number of reviews skipped from the start of the result set.",
examples=[0],
)
results: list[Review] = Field(
...,
description="The reviews for the current page.",
)
# ──────────────────────────────────────────────
# Discovery models
# ──────────────────────────────────────────────
class CategoryCount(BaseModel):
"""A category with its review count."""
category: str = Field(..., description="The media category name.", examples=["Movies"])
count: int = Field(..., description="Number of reviews in this category.", examples=[412])
class GenreCount(BaseModel):
"""A genre with its review count."""
genre: str = Field(..., description="The genre name.", examples=["Science Fiction"])
count: int = Field(..., description="Number of reviews in this genre.", examples=[58])
class CreatorCount(BaseModel):
"""A creator with their review count."""
creator: str = Field(..., description="Name of the director, author, or showrunner.", examples=["Steven Spielberg"])
count: int = Field(..., description="Number of works by this creator that have been reviewed.", examples=[7])
# ──────────────────────────────────────────────
# Stats models
# ──────────────────────────────────────────────
class CategoryBreakdown(BaseModel):
"""Review count for a single category."""
category: str = Field(..., examples=["Movies"])
count: int = Field(..., examples=[412])
class OverviewStats(BaseModel):
"""High-level statistics across all reviews."""
total_reviews: int = Field(..., description="Total number of reviews in the database.", examples=[642])
categories: list[CategoryBreakdown] = Field(..., description="Number of reviews per category.")
average_rating: float = Field(..., description="Mean rating across all reviews.", examples=[1.02])
earliest_review: str = Field(..., description="Date of the oldest review.", examples=["2001-06-29"])
latest_review: str = Field(..., description="Date of the most recent review.", examples=["2025-02-09"])
class CreatorStats(BaseModel):
"""A creator ranked by number of reviewed works."""
creator: str = Field(..., description="Name of the creator.", examples=["Steven Spielberg"])
review_count: int = Field(..., description="Number of reviewed works by this creator.", examples=[7])
average_rating: float = Field(..., description="Mean rating across this creator's reviewed works.", examples=[1.57])
class GenreStats(BaseModel):
"""A genre with aggregated review statistics."""
genre: str = Field(..., description="The genre name.", examples=["Science Fiction"])
review_count: int = Field(..., description="Number of reviews in this genre.", examples=[58])
average_rating: float = Field(..., description="Mean rating for reviews in this genre.", examples=[1.24])
class YearActivity(BaseModel):
"""Review activity for a single year."""
year: str = Field(..., description="The four-digit year.", examples=["2025"])
review_count: int = Field(..., description="Number of reviews recorded in this year.", examples=[3])
average_rating: float = Field(..., description="Mean rating for reviews in this year.", examples=[1.67])
class DecadeStats(BaseModel):
"""Review activity grouped by the decade the work was released."""
decade: str = Field(
...,
description="The decade label (e.g. '1990s').",
examples=["1990s"],
)
review_count: int = Field(
...,
description="Number of reviewed works released in this decade.",
examples=[45],
)
average_rating: float = Field(
...,
description="Mean rating for works released in this decade.",
examples=[1.35],
)