""" Custom managers and QuerySets for Rides models. Optimized queries following Django styleguide patterns. """ from typing import Optional, List, Union from django.db.models import Q, F, Count, Prefetch from core.managers import ( BaseQuerySet, BaseManager, ReviewableQuerySet, ReviewableManager, StatusQuerySet, StatusManager, ) class RideQuerySet(StatusQuerySet, ReviewableQuerySet): """Optimized QuerySet for Ride model.""" def by_category(self, *, category: Union[str, List[str]]): """Filter rides by category.""" if isinstance(category, list): return self.filter(category__in=category) return self.filter(category=category) def coasters(self): """Filter for roller coasters.""" return self.filter(category__in=["RC", "WC"]) def thrill_rides(self): """Filter for thrill rides.""" return self.filter(category__in=["RC", "WC", "FR"]) def family_friendly(self, *, max_height_requirement: int = 42): """Filter for family-friendly rides.""" return self.filter( Q(min_height_in__lte=max_height_requirement) | Q(min_height_in__isnull=True) ) def by_park(self, *, park_id: int): """Filter rides by park.""" return self.filter(park_id=park_id) def by_manufacturer(self, *, manufacturer_id: int): """Filter rides by manufacturer.""" return self.filter(manufacturer_id=manufacturer_id) def by_designer(self, *, designer_id: int): """Filter rides by designer.""" return self.filter(designer_id=designer_id) def with_capacity_info(self): """Add capacity-related annotations.""" return self.annotate( estimated_daily_capacity=F("capacity_per_hour") * 10, # Assuming 10 operating hours duration_minutes=F("ride_duration_seconds") / 60.0, ) def high_capacity(self, *, min_capacity: int = 1000): """Filter for high-capacity rides.""" return self.filter(capacity_per_hour__gte=min_capacity) def optimized_for_list(self): """Optimize for ride list display.""" return self.select_related( "park", "park_area", "manufacturer", "designer", "ride_model" ).with_review_stats() def optimized_for_detail(self): """Optimize for ride detail display.""" from .models import RideReview return self.select_related( "park", "park_area", "manufacturer", "designer", "ride_model__manufacturer", ).prefetch_related( "location", "rollercoaster_stats", Prefetch( "reviews", queryset=RideReview.objects.select_related("user") .filter(is_published=True) .order_by("-created_at")[:10], ), "photos", ) def for_map_display(self): """Optimize for map display.""" return ( self.select_related("park", "park_area") .prefetch_related("location") .values( "id", "name", "slug", "category", "status", "park__name", "park__slug", "park_area__name", "location__point", ) ) def search_by_specs( self, *, min_height: Optional[int] = None, max_height: Optional[int] = None, min_speed: Optional[float] = None, inversions: Optional[bool] = None, ): """Search rides by physical specifications.""" queryset = self if min_height: queryset = queryset.filter( Q(rollercoaster_stats__height_ft__gte=min_height) | Q(min_height_in__gte=min_height) ) if max_height: queryset = queryset.filter( Q(rollercoaster_stats__height_ft__lte=max_height) | Q(max_height_in__lte=max_height) ) if min_speed: queryset = queryset.filter(rollercoaster_stats__speed_mph__gte=min_speed) if inversions is not None: if inversions: queryset = queryset.filter(rollercoaster_stats__inversions__gt=0) else: queryset = queryset.filter( Q(rollercoaster_stats__inversions=0) | Q(rollercoaster_stats__isnull=True) ) return queryset class RideManager(StatusManager, ReviewableManager): """Custom manager for Ride model.""" def get_queryset(self): return RideQuerySet(self.model, using=self._db) def coasters(self): return self.get_queryset().coasters() def thrill_rides(self): return self.get_queryset().thrill_rides() def family_friendly(self, *, max_height_requirement: int = 42): return self.get_queryset().family_friendly( max_height_requirement=max_height_requirement ) def by_park(self, *, park_id: int): return self.get_queryset().by_park(park_id=park_id) def high_capacity(self, *, min_capacity: int = 1000): return self.get_queryset().high_capacity(min_capacity=min_capacity) def optimized_for_list(self): return self.get_queryset().optimized_for_list() def optimized_for_detail(self): return self.get_queryset().optimized_for_detail() class RideModelQuerySet(BaseQuerySet): """QuerySet for RideModel model.""" def by_manufacturer(self, *, manufacturer_id: int): """Filter ride models by manufacturer.""" return self.filter(manufacturer_id=manufacturer_id) def by_category(self, *, category: str): """Filter ride models by category.""" return self.filter(category=category) def with_ride_counts(self): """Add count of rides using this model.""" return self.annotate( ride_count=Count("rides", distinct=True), operating_rides_count=Count( "rides", filter=Q(rides__status="OPERATING"), distinct=True ), ) def popular_models(self, *, min_installations: int = 5): """Filter for popular ride models.""" return self.with_ride_counts().filter(ride_count__gte=min_installations) def optimized_for_list(self): """Optimize for model list display.""" return self.select_related("manufacturer").with_ride_counts() class RideModelManager(BaseManager): """Manager for RideModel model.""" def get_queryset(self): return RideModelQuerySet(self.model, using=self._db) def by_manufacturer(self, *, manufacturer_id: int): return self.get_queryset().by_manufacturer(manufacturer_id=manufacturer_id) def popular_models(self, *, min_installations: int = 5): return self.get_queryset().popular_models(min_installations=min_installations) class RideReviewQuerySet(ReviewableQuerySet): """QuerySet for RideReview model.""" def for_ride(self, *, ride_id: int): """Filter reviews for a specific ride.""" return self.filter(ride_id=ride_id) def by_user(self, *, user_id: int): """Filter reviews by user.""" return self.filter(user_id=user_id) def by_rating_range(self, *, min_rating: int = 1, max_rating: int = 10): """Filter reviews by rating range.""" return self.filter(rating__gte=min_rating, rating__lte=max_rating) def optimized_for_display(self): """Optimize for review display.""" return self.select_related("user", "ride", "moderated_by") class RideReviewManager(BaseManager): """Manager for RideReview model.""" def get_queryset(self): return RideReviewQuerySet(self.model, using=self._db) def for_ride(self, *, ride_id: int): return self.get_queryset().for_ride(ride_id=ride_id) def by_rating_range(self, *, min_rating: int = 1, max_rating: int = 10): return self.get_queryset().by_rating_range( min_rating=min_rating, max_rating=max_rating ) class RollerCoasterStatsQuerySet(BaseQuerySet): """QuerySet for RollerCoasterStats model.""" def tall_coasters(self, *, min_height_ft: float = 200): """Filter for tall roller coasters.""" return self.filter(height_ft__gte=min_height_ft) def fast_coasters(self, *, min_speed_mph: float = 60): """Filter for fast roller coasters.""" return self.filter(speed_mph__gte=min_speed_mph) def with_inversions(self): """Filter for coasters with inversions.""" return self.filter(inversions__gt=0) def launched_coasters(self): """Filter for launched coasters.""" return self.exclude(launch_type="NONE") def by_track_type(self, *, track_type: str): """Filter by track type.""" return self.filter(track_type=track_type) def optimized_for_list(self): """Optimize for stats list display.""" return self.select_related("ride", "ride__park") class RollerCoasterStatsManager(BaseManager): """Manager for RollerCoasterStats model.""" def get_queryset(self): return RollerCoasterStatsQuerySet(self.model, using=self._db) def tall_coasters(self, *, min_height_ft: float = 200): return self.get_queryset().tall_coasters(min_height_ft=min_height_ft) def fast_coasters(self, *, min_speed_mph: float = 60): return self.get_queryset().fast_coasters(min_speed_mph=min_speed_mph) def with_inversions(self): return self.get_queryset().with_inversions() def launched_coasters(self): return self.get_queryset().launched_coasters()