Project 03Academic team project
Football Transfer & Performance Simulator
A squad-management web app where transfer and lineup decisions are tested by an ML match-simulation engine, built as four Docker services.
My role
Designed and built jointly with Daniel Kon. The linked repository is my copy of our shared project.
Project overview
Problem
How can transfer and lineup decisions be tied to measurable results? Coaches manage a budget, buy and sell players, save an eleven-player lineup, and test it against five benchmark teams.
Objective
Build a full-stack application whose simulations come from trained models, with inference in its own service and one MongoDB database shared by the backend and the engine.
Tech stack
Languages and tools
- Flask
- scikit-learn
- MongoDB
- React
- Docker Compose
- Nginx
- pytest
Methods
- Model serving over HTTP/JSON
- Batch inference
- Random forests
- JWT authentication
- Integration testing with mongomock
Architecture and implementation
Four Docker services separate the interface, application logic, model inference, and storage. Nginx serves the React/Vite build and proxies /api/ requests to the Flask backend, which calls a separate Flask and scikit-learn engine over HTTP/JSON.
Serve the models as their own service
The prediction engine is a separate Flask service with bundled model artifacts for local inference. It reads player statistics from MongoDB and seeds the initial player collection.
Predict matches
Goal prediction combines attacking and physical matchup information. Team ranking uses an antisymmetric random-forest wrapper, so swapping the two teams reverses the prediction. The squad rating shown after a simulation is a separate statistical formula, not the ranking model.
Batch where it helps
League matches and hypothetical transfer replacements go to the engine in batches. Ordinary benchmark simulations use one call per match.
Recommend transfers
Recommendations filter out owned and unaffordable players, score candidates against squad weaknesses, and rank replacements with the engine when the lineup is complete. If ML ranking is unavailable, statistical recommendations remain.
Persist only what succeeded
Saved scenarios and completed leagues are written only after their simulations succeed. Engine timeouts and connection failures return HTTP 503 and store a pending record. The production Compose file keeps MongoDB data and uploaded media in separate named volumes.
Accounts and community
JWT authentication with user, moderator, and owner roles, plus a forum, direct messages, and media handling.
The browser talks to the React frontend served by Nginx, which proxies /api/ requests to the Flask backend. The backend calls the Flask and scikit-learn prediction engine over HTTP/JSON. The backend and the engine share one MongoDB database.
Outcomes and links
119 tests
Tests recorded as passing, run against the real Flask application factory with mongomock.
Results
| TestsRecorded as passing, using mongomock | 119 |
|---|---|
| Docker servicesFrontend, backend, prediction engine, MongoDB | 4 |
| Benchmark teamsAttack, defense, athleticism, aggression, balanced | 5 |
| Seeded playersOn a fresh database | 200+ |
Takeaways and limits
- The models support an academic simulation. Their accuracy on real match outcomes has not been established.
- The first clean start downloads an external dataset to seed players, so it needs internet access.
