108 lines
2.7 KiB
Python
108 lines
2.7 KiB
Python
"""Pydantic schemas for API request/response models."""
|
|
|
|
from datetime import datetime
|
|
|
|
from pydantic import BaseModel
|
|
|
|
|
|
class ListingResponse(BaseModel):
|
|
"""Listing combined with its ELO rating data."""
|
|
|
|
global_id: str
|
|
tiny_id: str | None = None
|
|
url: str | None = None
|
|
title: str | None = None
|
|
city: str | None = None
|
|
postcode: str | None = None
|
|
province: str | None = None
|
|
neighbourhood: str | None = None
|
|
municipality: str | None = None
|
|
latitude: float | None = None
|
|
longitude: float | None = None
|
|
object_type: str | None = None
|
|
house_type: str | None = None
|
|
offering_type: str | None = None
|
|
construction_type: str | None = None
|
|
construction_year: str | None = None
|
|
energy_label: str | None = None
|
|
living_area: int | None = None
|
|
plot_area: int | None = None
|
|
bedrooms: int | None = None
|
|
rooms: int | None = None
|
|
has_garden: bool | None = None
|
|
has_balcony: bool | None = None
|
|
has_solar_panels: bool | None = None
|
|
has_heat_pump: bool | None = None
|
|
has_roof_terrace: bool | None = None
|
|
is_energy_efficient: bool | None = None
|
|
is_monument: bool | None = None
|
|
current_price: int | None = None
|
|
status: str | None = None
|
|
price_per_sqm: float | None = None
|
|
publication_date: str | None = None
|
|
elo_rating: float
|
|
comparison_count: int
|
|
wins: int
|
|
losses: int
|
|
|
|
|
|
class MatchupResponse(BaseModel):
|
|
"""A pair of listings to compare."""
|
|
|
|
listing_a: ListingResponse
|
|
listing_b: ListingResponse
|
|
|
|
|
|
class CompareRequest(BaseModel):
|
|
"""Submit the result of a pairwise comparison."""
|
|
|
|
winner_id: str
|
|
loser_id: str
|
|
|
|
|
|
class CompareResponse(BaseModel):
|
|
"""Result of a comparison submission with ELO changes."""
|
|
|
|
winner_id: str
|
|
loser_id: str
|
|
elo_change: float
|
|
new_winner_elo: float
|
|
new_loser_elo: float
|
|
|
|
|
|
class RankingResponse(BaseModel):
|
|
"""A listing with its rank position."""
|
|
|
|
rank: int
|
|
listing: ListingResponse
|
|
|
|
|
|
class ComparisonHistoryItem(BaseModel):
|
|
"""A single historical comparison record."""
|
|
|
|
id: int
|
|
listing_a_title: str | None
|
|
listing_b_title: str | None
|
|
winner_title: str | None
|
|
listing_a_id: str
|
|
listing_b_id: str
|
|
winner_id: str
|
|
elo_a_before: float
|
|
elo_b_before: float
|
|
elo_a_after: float
|
|
elo_b_after: float
|
|
created_at: datetime
|
|
|
|
|
|
class StatsResponse(BaseModel):
|
|
"""Overall statistics about comparisons and ratings."""
|
|
|
|
total_comparisons: int
|
|
total_rated_listings: int
|
|
total_listings: int
|
|
avg_elo: float | None
|
|
max_elo: float | None
|
|
min_elo: float | None
|
|
elo_distribution: list[dict]
|
|
recent_comparisons: list[ComparisonHistoryItem]
|