- Run
python explore_api.pyto understand EOG's API structure - Read
API_EXPLORATION_GUIDE.mdfor manual exploration - Set up GitHub repo
- Assign roles to 5 team members
- Install dependencies
- Start server with
python start_server.py(automatically populates database)
- Document API endpoints in shared doc
- Backend: Fetch and cache data
- Data Analysis: Study historical patterns
- Frontend: Set up React app
- Detection: Design matching algorithm
- Optimization: Plan routing approach
- Connect frontend to backend
- Implement drain detection
- Build ticket matching
- Create visualizations
- Add optimization features
- End-to-end testing
- UI improvements
- Demo preparation
- Practice presentation
explore_api.py- Automated API endpoint discovery scriptAPI_EXPLORATION_GUIDE.md- Manual exploration guide with Swagger tips
PROJECT_STRUCTURE.md- Complete folder structure and team division- Role assignments for 5 people
- Code templates for each role
- Tech stack recommendations
- Communication protocols
ALGORITHMS.md- Detailed pseudocode for core challenges- Drain event detection (accounting for continuous filling)
- Ticket matching (date-only to timestamp mapping)
- Route optimization (minimum witches calculation)
- Real-time monitoring architecture
- Testing strategies
DEMO_SCRIPT.md- Complete presentation guide- 5-7 minute demo flow
- Live demo walkthrough
- Q&A preparation
- Backup plans
- Success metrics
Focus: Fetch EOG data, cache locally, provide clean API
Key responsibilities:
- EOG API client
- FastAPI endpoints
- WebSocket for real-time
- Database setup
Files to create:
backend/api/main.pybackend/api/eog_client.pybackend/api/websocket.pybackend/models/*.py
✨ Automatic Setup: The server now automatically populates the database on startup! Just run:
python start_server.pyOr set the environment variable:
AUTO_POPULATE_DB=true uvicorn backend.api.main:app --reloadWhat happens automatically:
- Server checks if database is populated
- If empty, automatically fetches essential data from EOG API
- Calculates and stores precomputed x, y coordinates (normalized 0-1)
- Calculates network edge weights and distances
- Server starts immediately with data ready
Why this matters:
- Precomputed coordinates make the frontend network visualization much faster
- All data is cached locally, reducing API calls and improving performance
- The database includes computed fields (weight, distance, x, y) that aren't in the original API
- No manual steps needed - just start the server!
Focus: Analyze time series, detect drain events
Key responsibilities:
- Drain detection algorithm
- Fill rate calculation
- Account for continuous filling during drainage
- Historical data processing
Files to create:
data-analysis/drain_detector.pydata-analysis/rate_calculator.pydata-analysis/analyzer.py
Critical insight: Potion continues filling DURING drainage!
Total drained = actual_drop + (fill_rate × drain_duration)
Focus: Match tickets to drains, flag suspicious activity
Key responsibilities:
- Dynamic ticket matching (adapts to changing data)
- Match date-only tickets to timestamped drains
- Calculate discrepancies
- Categorize alert severity
Files to create:
detection/ticket_matcher.pydetection/discrepancy.pydetection/validator.py
Critical challenge: Tickets have DATE only, drains have TIMESTAMP
Solution: Group drains by date, sum volumes, compare
Focus: Interactive map, real-time updates, historical playback
Key responsibilities:
- React dashboard
- Leaflet map with cauldron markers
- Real-time WebSocket connection
- Historical playback controls
- Alert displays
Files to create:
frontend/src/components/Map.jsxfrontend/src/components/Timeline.jsxfrontend/src/components/AlertPanel.jsxfrontend/src/hooks/useWebSocket.js
Focus: Calculate minimum witches, optimal routes
Key responsibilities:
- Calculate time to overflow
- Greedy scheduling algorithm
- Route optimization (TSP)
- Account for travel time + unload time
Files to create:
optimization/route_optimizer.pyoptimization/scheduler.pyoptimization/graph_utils.py
Key constraint: 15 minute unload time at market
Challenge: When a cauldron is being drained, potion continues to fill!
Solution:
# Don't just use level drop
volume_drained = start_level - end_level # WRONG!
# Account for filling during drain
drain_duration = end_time - start_time
fill_during_drain = fill_rate * drain_duration
volume_drained = (start_level - end_level) + fill_during_drain # CORRECT!Challenge: Tickets only have dates, drains have timestamps
Solution:
# Group by date
drains_on_date = filter(drains, date(timestamp) == ticket.date)
total_drained = sum(drain.volume for drain in drains_on_date)
# Compare
if abs(total_drained - ticket.volume) > tolerance:
flag_as_suspicious()Challenge: "Ticket data may change during judging"
Solution:
- Never hardcode ticket IDs or assumptions
- Recalculate matching on every API fetch
- Build robust matching logic that handles new patterns
Challenge: Witches take 15 minutes to unload at market
Solution:
total_time = (
travel_to_cauldron +
drain_time +
travel_to_market +
UNLOAD_TIME # Don't forget this!
)
# Must finish before overflow
assert completion_time < time_to_overflowpip install fastapi uvicorn sqlalchemy pydantic pandas requests websocketsCore:
- FastAPI - API server
- Pandas - Time series analysis
- SQLAlchemy - Database ORM
- WebSockets - Real-time updates
npm install react leaflet react-leaflet recharts axiosCore:
- React - UI framework
- Leaflet - Interactive maps
- Recharts - Charts and graphs
- Axios - API calls
pip install networkx scipyCore:
- NetworkX - Graph algorithms
- SciPy - Optimization routines
After 9 hours, you should have:
✅ Real-time dashboard monitoring 20+ cauldrons ✅ Interactive map with color-coded urgency ✅ Historical playback with timeline controls ✅ Automatic drain event detection ✅ Dynamic ticket matching ✅ Discrepancy alerts (Critical/Warning/Info) ✅ Fast network visualization using precomputed coordinates
✅ Minimum witches calculation ✅ Optimized route visualization ✅ Overflow prevention scheduling
✅ Cauldrons monitored: 23
✅ Historical data points: 10,080 (1 week × 1,440 min/day)
✅ Drain events detected: ~150
✅ Tickets matched: ~140
✅ Discrepancies found: ~10 (6-7%)
✅ Minimum witches needed: 3-4
✅ Overflows prevented: 100%
Highlight:
- Dynamic ticket matching algorithm
- Accounting for continuous filling during drainage
- Adaptive to changing data
Highlight:
- Time series analysis
- Graph algorithms for optimization
- Real-time WebSocket architecture
- Constraint satisfaction for scheduling
Highlight:
- All required features ✅
- Bonus optimization ✅
- Robust error handling ✅
- Well-tested algorithms ✅
Highlight:
- Intuitive color coding
- Interactive map
- Clear alert explanations
- Historical investigation tools
Highlight:
- Clear narrative
- Live demo
- Real discrepancies shown
- Q&A preparation
❌ Wrong: drained = start_level - end_level
✅ Right: drained = (start_level - end_level) + (fill_rate × duration)
❌ Wrong: if ticket.id == "T123": match_to_drain_456()
✅ Right: Dynamic matching that works with any ticket data
❌ Wrong: time = travel + drain
✅ Right: time = travel + drain + return + 15_min_unload
- Multiple drains per day
- No tickets for a drain (unlogged)
- Multiple tickets for one drain
- Measurement tolerance
- Don't build complex ML models (simple detection works!)
- Don't optimize prematurely
- Focus on working features over perfect code
- Run the API explorer:
python explore_api.py- Start the server (database auto-populates):
# Easy way - automatically populates database on startup
python start_server.py
# Or manually populate first (optional):
python backend/populate_database.py
uvicorn backend.api.main:app --reload✨ NEW: Automatic Database Population! The server now automatically checks and populates the database on startup:
- Checks if database has data and precomputed coordinates
- If empty, automatically fetches and caches essential data
- Calculates x, y coordinates for fast network visualization
- Server starts immediately (no waiting for full population)
What gets populated automatically:
- Cauldrons with coordinates
- Market with coordinates
- Network edges with weights and distances
- Couriers
- Precomputed x, y coordinates for visualization
Note: Historical data and tickets load on-demand via API (faster startup).
- While that runs, divide into teams:
- Assign the 5 roles
- Create shared Google Doc for API documentation
- Set up GitHub repo
- Read the relevant guide for your role:
- Backend →
PROJECT_STRUCTURE.md(Person 1 section) - Data Analysis →
ALGORITHMS.md(Drain Detection) - Detection →
ALGORITHMS.md(Ticket Matching) - Frontend →
PROJECT_STRUCTURE.md(Person 4 section) - Optimization →
ALGORITHMS.md(Route Optimization)
- Hour 1 sync-up:
- Share API findings
- Finalize data models
- Set up communication channels
- Define API contracts between backend/frontend
#general- Team coordination#backend- Person 1#data-analysis- Person 2#detection- Person 3#frontend- Person 4#optimization- Person 5#api-docs- Shared API documentation
- Hour 1: API documented? Roles clear?
- Hour 3: Can fetch data? Drain detection working?
- Hour 5: Frontend connected? Matching logic ready?
- Hour 7: Integration complete? Optimization working?
- Hour 8: Demo practice run
- Hour 8.5: Final polish
- Blockers: Post immediately, don't wait
- API changes: Update shared doc
- Breaking changes: Warn other team members
- Success: Share wins to keep morale up!
You're on track if by:
Hour 3:
- All EOG endpoints documented
- Server started (database auto-populated on startup)
- Can fetch and display cauldron list
- Historical data loading
- Basic React app running
- Network visualization showing cauldrons and market with precomputed coordinates
Hour 5:
- Drain detection algorithm working
- Frontend showing map with cauldrons
- Backend API returning data to frontend
- Ticket data loaded
Hour 7:
- Discrepancies being detected
- Real-time updates working
- Historical playback functional
- Alerts displaying
Hour 9:
- Full demo run-through complete
- All features working
- Team practiced presentation
- Backup plans ready
Your team has strong backgrounds in:
- Backend development (Tom: FastAPI experience)
- Machine learning (Tom: PyTorch, TensorFlow)
- Full-stack (internship experience)
- Problem-solving (CS coursework)
This challenge is absolutely achievable in 9 hours with 5 people!
Key to success:
- ✅ Clear communication
- ✅ Parallel work (minimal dependencies)
- ✅ Focus on working features over perfection
- ✅ Test early, test often
- ✅ Practice the demo!
start_server.py # 🚀 Start server with auto-populate (RECOMMENDED)
explore_api.py # Run this first to explore the API
backend/populate_database.py # Manual database population (optional, server does this automatically)
API_EXPLORATION_GUIDE.md # Manual API exploration
PROJECT_STRUCTURE.md # Team roles & code templates
ALGORITHMS.md # Core algorithm pseudocode
DEMO_SCRIPT.md # Presentation guide
- Challenge: https://hackutd2025.eog.systems/
- Swagger: https://hackutd2025.eog.systems/swagger/index.html
- (Your backend will run on: http://localhost:8000)
- (Your frontend will run on: http://localhost:5173)
Option 1: Automatic (Recommended) The server now automatically checks and populates the database on startup!
# Easy way - auto-populates database on startup
python start_server.py
# Or use environment variable
AUTO_POPULATE_DB=true uvicorn backend.api.main:app --reloadOption 2: Manual Population If you prefer to populate manually before starting:
python backend/populate_database.py
uvicorn backend.api.main:app --reloadWhat happens automatically:
- Server checks if database is populated on startup
- If empty or missing coordinates, it automatically fetches and caches data
- Calculates precomputed x, y coordinates (normalized 0-1) for fast visualization
- Calculates network edge weights and distances using Haversine formula
- Server starts immediately (population happens in background if needed)
Database location: data/cauldronwatch.db
Why this matters:
- Frontend network visualization requires precomputed coordinates for optimal performance
- All computed fields (x, y, weight, distance) are stored in the database
- Local caching reduces API calls and improves response times
- Coordinates are calculated once on the backend and reused for fast rendering
Note: The server will start even if database is empty, but data will load incrementally (slower). Use start_server.py or set AUTO_POPULATE_DB=true for automatic population.
UNLOAD_TIME = 15 # minutes at market
TOLERANCE = 5.0 # 5% volume difference acceptable
UPDATE_INTERVAL = 5 # seconds for real-time updatesGood luck! 🧙♀️✨
Remember: The goal isn't perfection, it's a working demo that shows you understood the problem and built a creative solution. You can do this! 💪