""" Custom managers and QuerySets for Rides models. Optimized queries following Django styleguide patterns. """ from typing import Optional, List, Dict, Any, Union from django.db import models from django.db.models import Q, F, Count, Avg, Max, Min, 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()