Traveller - Find the mathematical minimum for group travel
Tagline
Find the mathematical minimum for group travel: sync schedules, scrape live flights, and discover the optimal central meeting hub.
About the Project
Inspiration Organizing a trip for a distributed group of friends is a logistical nightmare. You have multiple travelers originating from different cities, varying constraints on budget and travel time, and a massive matrix of flight costs. We realized that finding the best meeting spot isn't just about picking a cool city—it's a complex, multivariable optimization problem. We wanted to build a tool that solves this mathematically while ensuring the flights are actually real and bookable, bypassing the stale data of standard APIs.
What We Learned
We learned the hard way that flight aggregators actively fight automation. We had to dive deep into async browser automation, crafting native locators that rely on accessibility tags (aria-labels) rather than brittle CSS classes, and figuring out how to bypass bot-detection just long enough to construct our cost matrix. We also learned how to stream Server-Sent Events (SSE) with FastAPI to keep the user engaged via a live progress UI while headless browsers did the heavy lifting in the background.
How We Built It Traveller is built with a decoupled, asymmetric architecture:
- Backend: FastAPI (Python 3.11+) orchestrating an asynchronous optimization pipeline.
- Data Engine: Parallelized headless Chromium instances via
playwright-stealththat asynchronously scrape live pricing, dynamically responding to DOM loads. - Frontend: A single-file, vanilla HTML/JS client featuring a sleek, dark glassmorphism UI, connected to the backend via SSE for real-time progress updates.
To find the global minimum cost for $N$ travelers to meet at destination $d \in D$, the backend minimizes the cost function: $$ \arg\min_{d \in D} \left( \sum_{i=1}^{N} \Big( P_{\text{outbound}}(i, d) + P_{\text{return}}(d, i) \Big) \right) - \lambda V(d) $$ Where $P$ represents the parsed flight price in EUR, and $V(d)$ is a qualitative heuristic score modeling the destination's neighborhood transit and vibe modifier.
Challenges We Faced
- Dynamic DOMs: Writing parsers for Google Flights and search aggregators that won't break when they deploy A/B tests. We solved this by abandoning BeautifulSoup for complex nested elements and leveraging Playwright's native accessibility tree locators.
- Terminal Encoding Crashes: Dealing with server 500 errors and surrogate Unicode crashes caused by emoji flags when printing scraper logs to
sys.stdouton Windows. We fixed this by enforcing strict UTF-8 re-encoding loops at the application root. - CAPTCHAs & Rate Limits: Aggressive rate-limiting by search engines. We instituted smart back-off algorithms and parallelized task queueing to keep the scraper alive without triggering hard bot walls.
Testing Instructions
- Ensure Python 3.11+ is installed on your machine.
- Clone the repository and install dependencies: ```bash pip install -r requirements.txt playwright install chromium 3. Run the application: python server.py 4. The server will boot up and automatically open http://localhost:8345 in your default browser. 5. Add 2 or more travelers (e.g., origin "London" and "Berlin"). 6. Set your trip duration and start dates. Provide a candidate destination city. 7. Click "Find Global Minimum" and watch the live SSE progress stream as the headless browsers traverse the web to calculate your matrix.
Built With
- algorithms
- architecture-&-frameworks-decoupled-architecture
- asymmetric-architecture
- cost-minimization
- dark-ui
- data-engine
- dom
- fastapi
- fintech
- flight
- glassmorphism
- global-minimum
- group-travel
- headless-chrome
- heuristics
- html
- live-pricing
- mathematical-modeling
- parallelization-algorithms-&-math-optimization
- playwright-stealth
- python-3.11
- python-data-engineering-&-scraping-playwright
- real-time-updates-industry/niche-travel-tech
- search
- server-sent-events
- sse
- vanilla-js
- vibe-modifier-frontend-&-ui-frontend-dev
- web-scraping
Log in or sign up for Devpost to join the conversation.