140 lines
5.0 KiB
Python
140 lines
5.0 KiB
Python
# app/models/green_space.py
|
|
from pydantic import BaseModel, Field
|
|
from typing import Optional, List, Dict, Tuple, Any
|
|
from datetime import datetime
|
|
from enum import Enum
|
|
|
|
class GreenSpaceType(str, Enum):
|
|
PARK = "park"
|
|
GARDEN = "garden"
|
|
FOREST = "forest"
|
|
RIVERSIDE = "riverside"
|
|
CEMETERY = "cemetery"
|
|
PLAYGROUND = "playground"
|
|
SPORTS_FIELD = "sports_field"
|
|
ALLOTMENT = "allotment"
|
|
SQUARE = "square"
|
|
OTHER = "other"
|
|
|
|
class NoiseLevel(int, Enum):
|
|
VERY_QUIET = 1
|
|
QUIET = 2
|
|
MODERATE = 3
|
|
NOISY = 4
|
|
VERY_NOISY = 5
|
|
|
|
class AmenityType(str, Enum):
|
|
TOILET = "toilet"
|
|
RESTAURANT = "restaurant"
|
|
CAFE = "cafe"
|
|
ICE_CREAM = "ice_cream"
|
|
SPATI = "spati"
|
|
PLAYGROUND = "playground"
|
|
WATER_FEATURE = "water_feature"
|
|
FITNESS = "fitness"
|
|
BIKE_RENTAL = "bike_rental"
|
|
PARKING = "parking"
|
|
PUBLIC_TRANSPORT = "public_transport"
|
|
|
|
class Coordinates(BaseModel):
|
|
lat: float = Field(..., ge=-90, le=90)
|
|
lng: float = Field(..., ge=-180, le=180)
|
|
|
|
class Amenity(BaseModel):
|
|
id: str
|
|
name: str
|
|
type: AmenityType
|
|
coordinates: Coordinates
|
|
distance_meters: int
|
|
rating: Optional[float] = Field(None, ge=0, le=5)
|
|
opening_hours: Optional[str] = None
|
|
description: Optional[str] = None
|
|
|
|
class EnvironmentalFeatures(BaseModel):
|
|
"""Environmental characteristics of the green space."""
|
|
tree_coverage_percent: int = Field(..., ge=0, le=100, description="Percentage of area covered by trees")
|
|
shade_quality: int = Field(..., ge=0, le=100, description="Quality of shade availability")
|
|
noise_level: NoiseLevel = Field(..., description="Average noise level")
|
|
wildlife_diversity_score: int = Field(..., ge=0, le=100, description="Biodiversity indicator")
|
|
water_features: bool = Field(False, description="Has ponds, fountains, or streams")
|
|
natural_surface_percent: int = Field(..., ge=0, le=100, description="Percentage of natural vs paved surface")
|
|
|
|
class AccessibilityFeatures(BaseModel):
|
|
"""Accessibility and infrastructure features."""
|
|
wheelchair_accessible: bool = Field(False)
|
|
public_transport_score: int = Field(..., ge=1, le=5, description="Public transport accessibility")
|
|
cycling_infrastructure: bool = Field(False, description="Has bike paths or bike parking")
|
|
parking_availability: int = Field(..., ge=1, le=5, description="Car parking availability")
|
|
lighting_quality: int = Field(..., ge=1, le=5, description="Evening lighting quality")
|
|
|
|
class RecreationFeatures(BaseModel):
|
|
"""Recreation and activity features."""
|
|
playground_quality: int = Field(0, ge=0, le=100, description="Playground facilities quality")
|
|
sports_facilities: bool = Field(False, description="Has sports courts, fitness equipment")
|
|
running_paths: bool = Field(False, description="Has designated running/walking paths")
|
|
cycling_paths: bool = Field(False, description="Has cycling paths")
|
|
dog_friendly: bool = Field(True, description="Dogs allowed")
|
|
bbq_allowed: bool = Field(False, description="BBQ/grilling allowed")
|
|
|
|
class PersonalityScore(BaseModel):
|
|
"""Personality-specific score with explanation."""
|
|
personality: str
|
|
score: int = Field(..., ge=0, le=100)
|
|
explanation: str
|
|
key_factors: List[str]
|
|
recommendations: List[str]
|
|
|
|
class GreenSpace(BaseModel):
|
|
"""Complete green space model with all features and scoring."""
|
|
# Basic info
|
|
id: str
|
|
name: str
|
|
description: Optional[str] = None
|
|
type: GreenSpaceType
|
|
|
|
# Location
|
|
coordinates: Coordinates
|
|
neighborhood: str
|
|
address: Optional[str] = None
|
|
|
|
# Physical characteristics
|
|
area_sqm: Optional[int] = Field(None, ge=1, description="Area in square meters")
|
|
perimeter_m: Optional[int] = Field(None, ge=1, description="Perimeter in meters")
|
|
|
|
# Features
|
|
environmental: EnvironmentalFeatures
|
|
accessibility: AccessibilityFeatures
|
|
recreation: RecreationFeatures
|
|
|
|
# Nearby amenities (within search radius)
|
|
nearby_amenities: List[Amenity] = []
|
|
|
|
# Personality scoring (for current request)
|
|
current_personality_score: Optional[PersonalityScore] = None
|
|
all_personality_scores: Optional[Dict[str, int]] = None
|
|
|
|
# Metadata
|
|
last_updated: datetime
|
|
data_sources: List[str] = []
|
|
confidence_score: int = Field(..., ge=0, le=100, description="Data quality confidence")
|
|
|
|
class ScoringRequest(BaseModel):
|
|
"""Request parameters for green space scoring."""
|
|
personality: str
|
|
location: Optional[Tuple[float, float]] = None # (lat, lng)
|
|
radius: int = Field(2000, ge=100, le=10000)
|
|
neighborhood: Optional[str] = None
|
|
min_score: int = Field(60, ge=0, le=100)
|
|
filters: Dict[str, Any] = {}
|
|
limit: int = Field(20, ge=1, le=100)
|
|
include_amenities: bool = False
|
|
|
|
class LocationScore(BaseModel):
|
|
"""Score for a specific location within a green space."""
|
|
coordinates: Coordinates
|
|
score: int = Field(..., ge=0, le=100)
|
|
explanation: str
|
|
nearby_features: List[str]
|
|
best_for: List[str] # Best personality types for this location
|
|
recommendations: List[str]
|