Inspiració A DDI Mollet, cada matí surt un camió ple de cervesa Damm cap a Osona. El conductor porta una full de ruta impresa i un palet de retornables que sovint queda enterrat sota la càrrega nova. Si un client està tancat, improvisa. Si un palet no encaixa, improvisa. Si plou a Vic, improvisa.
El problema no és que el conductor no sàpiga la seva feina — la sap perfectament. El problema és que la ruta i la càrrega del camió es decideixen per separat, en oficines diferents, per persones diferents, hores abans que el camió surti. I quan les dues decisions no parlen entre elles, el repartidor paga el preu al carrer.
Volíem demostrar que es poden unir aquestes dues decisions en un sol pla, i donar al conductor una eina tan senzilla com el seu paper actual — però que respongui quan la realitat canvia.
Què hem après Optimitzar ruta i càrrega alhora no és un problema d'algoritme, és un problema d'UX. El bin-packing 3D i el TSP són tractables; el que costa és visualitzar-los de manera que un humà confiï a primera vista. En un hackathon de 14 hores, el demo és el producte. Cada minut invertit en una funcionalitat que no surt al pitch és temps regalat. Vam tallar auth, persistència i mode offline complet — i el resultat és més ferm. Honestedat radical guanya. Marcar les heurístiques com a mocks dins la pròpia UI ens va donar més credibilitat que amagar-les rere paraules grans. MapLibre, deck.gl i Three.js conviuen millor del que sembla quan els sincronitzes amb un store mínim i frameloop sota demanda. Com ho hem construït Una sola app Next.js 14 amb dues rutes que comparteixen components:
/planner — plataforma per a operacions DDI: pugen els CSVs del dia i veuen palets agrupats, càrrega 3D del camió amb reserva per a retornables, ruta sobre mapa real i KPIs de temps, km i CO₂. /driver — app per a tauleta horitzontal: mapa per zones, mini-camió 3D que es buida en temps real, panell del client amb dos botons — Entregat o Client tancat. Quan passa l'excepció, la ruta es re-seqüencia automàticament dins la zona actual sense replanificar tot el viatge. Les dades són reals: cas DR0027 de DDI Mollet (18 clients a Osona, 837 unitats, 259 envasos retornats), extretes dels PDFs originals amb un pipeline Python (pdfplumber + pandas), geocodificades amb Nominatim i complementades amb meteo real d'Open-Meteo. Tot precalculat a JSON estàtic — la demo és 100 % offline-capable excepte els tiles del mapa.
Les heurístiques estan a la vista i etiquetades com a tals:
Clustering de clients per municipi Pallet builder greedy amb reserva fixa del 25 % per a retornables Truck loader amb restricció de pes (mai pesant a sobre de lleuger) Route planner nearest-neighbor amb re-seqüenciació local Reptes Sincronitzar Three.js i MapLibre sense que la GPU es disparés. Solució: i invalidar només quan canvia l'estop actual. Bin-packing 3D prou ràpid per a feedback instantani — primer intent amb solver complet trigava segons; vam canviar a greedy amb footprint més gran primer i ara és immediat. L'excepció "client tancat" — la temptació era replanificar tota la ruta. Vam decidir re-seqüenciar només la zona actual: més ràpid, més predictible, i casa amb com pensa el conductor. Decidir què NO fer. Cada "i si afegim..." va ser una batalla. Mantenir el scope va ser el repte més gran. Coordinar 4 persones en 14 hores sense pisar-nos: owner per carpeta, branches pN/feat-*, merges cada ≤ 2 h. Cap conflict greu.
Built With
- carto
- deck.gl
- open-meteo-(meteo)
- python-next.js-14
- react-18
- tailwind-maplibre-gl
- three.js-+-react-three-fiber-zustand-pdfplumber
- typescript
- vercel
Log in or sign up for Devpost to join the conversation.