Real-time theme park intelligence powered by machine learning
Aggregating wait times, weather forecasts, park schedules, and ML-powered predictions for optimal theme park experiences worldwide.
- β¨ Features
- π Quick Start
- π API Documentation
- π οΈ Tech Stack
- π Project Structure
- π³ Docker Commands
- π§ͺ Testing
- π§ Environment Variables
- π Real-time Wait Times β Live queue data for attractions, shows, and restaurants
- π€ ML Predictions β Machine learning forecasts for wait times and crowd levels
- π€οΈ Weather Integration β Current conditions and 16-day forecasts for all parks
- π Park Schedules β Opening hours, special events, and operating calendars
- π Multi-Source Data β Aggregated from multiple providers for maximum coverage
- π Analytics Ready β TimescaleDB-powered time-series data for insights
- β‘ High Performance β Redis caching and Bull queue processing
- π― RESTful API β Clean endpoints with full Swagger/OpenAPI documentation
| Category | Technology |
|---|---|
| Backend | NestJS 11 Β· TypeScript (strict mode) |
| Database | PostgreSQL 16 Β· TimescaleDB |
| Cache & Queue | Redis 7 Β· Bull Queue |
| ML Service | Python 3.11 Β· CatBoost Β· FastAPI |
| DevOps | Docker Compose Β· GitHub Actions |
| Testing | Jest Β· Supertest Β· Testcontainers |
- Node.js 20+
- Docker & Docker Compose
- Git
# Clone the repository
git clone https://github.com/PArns/v4.api.park.fan.git
cd v4.api.park.fan
# Install dependencies
npm install
# Copy environment configuration
cp .env.example .env
# Start infrastructure (PostgreSQL + Redis)
npm run docker:up
# Start development server
npm run devOnce running, you can access:
- API Root: http://localhost:3000/ (this README)
- API Base: http://localhost:3000/v1
- API Docs: http://localhost:3000/api (Swagger)
System health checks and monitoring endpoints.
GET /v1/health # System health status
GET /v1/health/db # Database connectivityResponse includes:
- System uptime
- Database connection status
- Last sync timestamps (wait times, park metadata)
- Active jobs and queue status
Core endpoints for park information, weather, schedules, and wait times.
GET /v1/parks # List all parks
GET /v1/parks/:slug # Get park by slug
GET /v1/parks/:continent/:country/:city/:parkSlug # Get park by location
GET /v1/parks/:slug/wait-times # Live wait times
GET /v1/parks/:slug/weather # Current weather
GET /v1/parks/:slug/weather/forecast # 16-day forecast
GET /v1/parks/:slug/schedule # Operating hours
GET /v1/parks/:slug/schedule/:date # Schedule for specific dateQuery Parameters:
continent,country,cityβ Filter by locationsortβ Sort order (name, popularity, etc.)includeβ Include related data (attractions, schedule, weather)
Example Response:
{
"id": 1,
"name": "Magic Kingdom",
"slug": "magic-kingdom",
"continent": "North America",
"country": "United States",
"city": "Orlando",
"timezone": "America/New_York",
"currentStatus": "OPERATING",
"currentCrowdLevel": "MODERATE",
"coordinates": { "lat": 28.3772, "lng": -81.5707 }
}Detailed attraction data with ML predictions and historical analytics.
GET /v1/attractions # List all attractions
GET /v1/attractions/:slug # Get attraction detailsResponse includes:
- Live wait times and status (OPERATING, CLOSED, DOWN, REFURBISHMENT)
- 24-hour ML-powered wait time forecasts
- Daily predictions with confidence scores
- Historical statistics (average, percentiles)
- Downtime tracking and reliability metrics
Example Response:
{
"id": 123,
"name": "Space Mountain",
"slug": "space-mountain",
"parkSlug": "magic-kingdom",
"category": "RIDE",
"currentWaitTime": 45,
"status": "OPERATING",
"lastUpdate": "2025-12-23T19:30:00Z",
"forecast": [
{ "hour": "20:00", "predictedWaitTime": 50, "confidence": 0.87 },
{ "hour": "21:00", "predictedWaitTime": 35, "confidence": 0.82 }
],
"stats": {
"averageWaitTime": 42,
"p50": 40,
"p75": 55,
"p90": 70
}
}Navigate parks by geographic hierarchy for route generation and exploration.
GET /v1/discovery/geo # Full geo hierarchy
GET /v1/discovery/continents # List continents
GET /v1/discovery/continents/:continent # Countries in continentResponse Structure:
{
"continents": [
{
"continent": "North America",
"countries": [
{
"country": "United States",
"cities": [
{
"city": "Orlando",
"parks": [
{
"name": "Magic Kingdom",
"url": "/north-america/united-states/orlando/magic-kingdom",
"attractions": [...]
}
]
}
]
}
]
}
]
}Resort-level aggregation grouping multiple parks.
GET /v1/destinations # List all destinations
GET /v1/destinations/:slug # Get destination detailsExamples:
- Walt Disney World (Magic Kingdom, EPCOT, Hollywood Studios, Animal Kingdom)
- Disneyland Paris (Disneyland Park, Walt Disney Studios Park)
Entertainment and dining options across all parks.
GET /v1/shows # List all shows
GET /v1/shows/:slug # Get show details
GET /v1/restaurants # List all restaurants
GET /v1/restaurants/:slug # Get restaurant detailsResponse includes:
- Showtimes and schedules
- Operating hours
- Wait times (for restaurants)
- Location and park information
Global search with enriched results across parks, attractions, shows, and restaurants.
GET /v1/search?q=disney # Search all types
GET /v1/search?q=thunder&type=attraction # Filter by type
GET /v1/search?q=paris # Search by citySearch Features:
- Multi-entity search: Parks, attractions, shows, restaurants
- Geographic search: By city, country, or continent
- Per-type counts: Shows returned vs total results
- Enriched results: Coordinates, wait times, park hours, show times
- Smart filtering: Type-based filtering with max 5 results per type
- Fast response: Redis-cached for 5min, <3ms cached response
Response Structure:
{
"query": "disney",
"counts": {
"park": {"returned": 5, "total": 13},
"attraction": {"returned": 5, "total": 156}
},
"results": [
{
"type": "park",
"name": "Disneyland Park",
"status": "OPERATING",
"load": "normal",
"parkHours": {...},
"coordinates": {...}
},
{
"type": "attraction",
"name": "Space Mountain",
"waitTime": 45,
"load": "higher",
"parentPark": {...}
}
]
}Public holiday data affecting park crowds and operating hours.
GET /v1/holidays/:isoCountryCode # Holidays by country
GET /v1/holidays/:isoCountryCode/:year # Holidays for specific yearv4.api.park.fan/
βββ src/
β βββ config/ # App configuration & environment
β βββ common/ # Shared utilities, filters, interceptors
β βββ database/ # Database utilities & migrations
β βββ queues/ # Bull queue setup & processors
β βββ health/ # Health check endpoints
β βββ destinations/ # Resort/destination grouping
β βββ parks/ # Parks, weather, schedules
β βββ attractions/ # Attractions & data sources
β βββ shows/ # Entertainment shows
β βββ restaurants/ # Dining locations
β βββ queue-data/ # Wait time data & history
β βββ ml/ # ML prediction integration
β βββ analytics/ # Statistics & analytics
β βββ holidays/ # Public holiday data
β βββ date-features/ # Date-based features for ML
β βββ discovery/ # Geographic discovery endpoints
β βββ search/ # Global search functionality
βββ ml-service/ # Python ML service (CatBoost)
β βββ train.py # Model training script
β βββ inference.py # FastAPI prediction service
β βββ features.py # Feature engineering
β βββ db.py # Database connection
βββ docker/ # Docker configurations
βββ scripts/ # Utility & debug scripts
βββ migrations/ # Database migrations
βββ test/ # E2E tests
# Start all services (PostgreSQL + Redis)
npm run docker:up
# Stop all services
npm run docker:down
# View logs
npm run docker:logs
# Restart services
npm run docker:restart
# Reset database (WARNING: deletes all data)
npm run db:resetProduction Deployment:
docker-compose -f docker-compose.production.yml up -d# Run unit tests
npm run test
# Run e2e tests
npm run test:e2e
# Run all tests with coverage
npm run test:all:cov
# Watch mode for development
npm run test:watch
# Specific test file
npm run test -- wait-times.processor.spec.tsCode Quality:
# Lint code
npm run lint
# Format code
npm run format
# Type check
npm run buildNODE_ENV=development # development | production | test
PORT=3000 # API server port
API_PREFIX=v1 # API version prefix# PostgreSQL with TimescaleDB
DB_HOST=localhost
DB_PORT=5432
DB_USERNAME=parkfan
DB_PASSWORD=your_secure_password
DB_DATABASE=parkfan
DB_SYNCHRONIZE=true # β οΈ Set to false in production!
DB_LOGGING=false # Enable for debugging
DB_SSL_ENABLED=false # Enable for production# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_PASSWORD= # Optional, recommended for production
# Bull Queue
BULL_PREFIX=parkfan# Google APIs (Geocoding, Places)
GOOGLE_API_KEY=your_google_api_key
# Weather Data
OPEN_WEATHER_API_KEY=your_openweather_key
# Data Sources (optional, for enhanced coverage)
QUEUE_TIMES_API_KEY= # Queue-Times.com
THEMEPARKS_API_KEY= # ThemeParks.wiki# ML Service Configuration
ML_SERVICE_URL=http://localhost:8000 # Development
# ML_SERVICE_URL=http://ml-service:8000 # Production (Docker)
MODEL_DIR=/app/models # Model storage directory
MODEL_VERSION=v1.1.0 # Current model version# Data Sync Intervals (cron expressions)
SYNC_WAIT_TIMES_CRON=*/5 * * * * # Every 5 minutes
SYNC_PARK_METADATA_CRON=0 6 * * * # Daily at 6 AM
SYNC_WEATHER_CRON=0 * * * * # HourlyThis is a private project. For questions or collaboration inquiries, please contact the maintainer.
UNLICENSED β Private project by Patrick Arns
This project aggregates data from multiple sources:
- Queue-Times.com β Real-time wait time data
- ThemeParks.wiki β Comprehensive park information and live data
- Wartezeiten.app β Wait times, crowd levels, and opening hours enrichment
Special thanks to these services for making real-time theme park data accessible.
Made with β€οΈ for theme park enthusiasts worldwide