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.
| 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 |
# 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 dev
Once running, you can access:
System health checks and monitoring endpoints.
GET /v1/health # System health status
GET /v1/health/db # Database connectivity
Response includes:
Core endpoints for park information, weather, schedules, and wait times. All routes use the full geographic path structure for consistency and SEO-friendly URLs.
Geographic Routes:
GET /v1/parks # List all parks (paginated)
GET /v1/parks/:continent # Parks by continent
GET /v1/parks/:continent/:country # Parks by country
GET /v1/parks/:continent/:country/:city # Parks by city
GET /v1/parks/:continent/:country/:city/:parkSlug # Get park by location
GET /v1/parks/:continent/:country/:city/:parkSlug/calendar # Integrated calendar
GET /v1/parks/:continent/:country/:city/:parkSlug/weather # Current weather & history
GET /v1/parks/:continent/:country/:city/:parkSlug/weather/forecast # 16-day forecast
GET /v1/parks/:continent/:country/:city/:parkSlug/schedule # Operating hours
GET /v1/parks/:continent/:country/:city/:parkSlug/wait-times # Live wait times
GET /v1/parks/:continent/:country/:city/:parkSlug/predictions/yearly # Yearly crowd predictions
GET /v1/parks/:continent/:country/:city/:parkSlug/attractions # List park attractions
GET /v1/parks/:continent/:country/:city/:parkSlug/attractions/:attractionSlug # Get attraction
Query Parameters:
continent, country, city โ Filter by location (in list endpoint)sort โ Sort order (name, popularity, etc.)page, limit โ Pagination (default: page=1, limit=10)from, to โ Date range for weather/schedule (YYYY-MM-DD format)Example Geographic Route:
GET /v1/parks/north-america/united-states/orlando/magic-kingdom
Example Response:
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Magic Kingdom",
"slug": "magic-kingdom",
"url": "/v1/parks/north-america/united-states/orlando/magic-kingdom",
"continent": "North America",
"country": "United States",
"city": "Orlando",
"timezone": "America/New_York",
"currentStatus": "OPERATING",
"currentLoad": {
"crowdLevel": "moderate",
"occupancy": 0.65
},
"coordinates": { "lat": 28.3772, "lng": -81.5707 },
"attractions": [
{
"id": "...",
"name": "Space Mountain",
"slug": "space-mountain",
"url": "/v1/parks/north-america/united-states/orlando/magic-kingdom/attractions/space-mountain"
}
]
}
Detailed attraction data with ML predictions and historical analytics. Access attractions through their park's geographic route.
Routes:
GET /v1/parks/:continent/:country/:city/:parkSlug/attractions # List park attractions
GET /v1/parks/:continent/:country/:city/:parkSlug/attractions/:attractionSlug # Get attraction details
Query Parameters:
page, limit โ Pagination for attraction list (default: page=1, limit=10)Response includes:
Example Response:
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"name": "Space Mountain",
"slug": "space-mountain",
"url": "/v1/parks/north-america/united-states/orlando/magic-kingdom/attractions/space-mountain",
"park": {
"id": "...",
"name": "Magic Kingdom",
"slug": "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 continent
Response 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. Destinations are used internally for data organization but are not exposed as top-level API endpoints. Parks are accessed directly via their geographic routes.
Examples:
Entertainment and dining options are available through the park endpoints. Shows and restaurants are not exposed as top-level API endpoints but are included in park responses and can be accessed via the search endpoint.
Global search with enriched results across parks and attractions.
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 city
Search Features:
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. Holidays are used internally for ML predictions and analytics but are not exposed as top-level API endpoints.
v4.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:reset
Production 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.ts
Code Quality:
# Lint code
npm run lint
# Format code
npm run format
# Type check
npm run build
NODE_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 * * * * # Hourly
This 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:
Special thanks to these services for making real-time theme park data accessible.
Made with โค๏ธ for theme park enthusiasts worldwide