Das Problem
TotoMondiale ist ein kostenloses Tippspiel, das ich seit Mitte der 2000er-Jahre für die großen Fußballturniere betreibe. Die Ruhmeshalle verzeichnet TotoEuropeo 2008, TotoEuropeo 2012, TotoMondiale 2014 und TotoEuropeo 2016. Die Regeln haben sich kaum verändert: Für jedes Spiel füllt man einen Tippschein aus, die Punkte richten sich nach den Quoten, und jeder Tippschein wird vor dem Anpfiff veröffentlicht, damit niemand schummeln kann. Die alte Website in klassischem ASP konnte den Spielern nicht mehr bieten, was sie heute erwarten: private Ligen mit Freunden, eine handytaugliche Oberfläche und Live-Ergebnisse. Für die WM 2026 habe ich alles neu geschrieben.
Was ich gebaut habe
Eine neue Plattform in Node.js, die die alten Regeln beibehält und Ligen, Live-Daten und eine Portion Spaß hinzufügt.
- Tippschein mit 9 Tipps: Endergebnis, Halbzeit, beide Teams treffen ja/nein, Under/Over, Elfmeter, Halbzeit/Endstand, gerade/ungerade, exaktes Ergebnis, Gesamttore. Die Quoten kommen von API-Football, mit Standardquoten, wenn keine vorliegen.
- Private und öffentliche Ligen: Jede Liga hat eine eigene Tabelle, ein Banner, einen News-Ticker und einen Chat.
- Sonderkarten: Sesto Senso bringt einen Bonus auf das exakte Ergebnis, Malocchio zieht einem anderen Spieler Punkte ab, Cornicello hebt einen Malocchio auf.
- Fairplay im Code: Tippscheine und Karten der anderen bleiben verborgen, bis das Spiel gesperrt wird. Diese Regel gilt auch für die Plattform-Admins. Wer einen Tippschein vergisst, bekommt vom System einen zufällig ausgefüllten, genau wie es die ursprünglichen Regeln vorsahen.
- Live-Spiele: Ein Job fragt alle 30 Sekunden API-Football ab und aktualisiert die Spielstände während der Partie.
- KI-Funktionen: Claude schreibt täglich eine Reihe von Tippvorschlägen, Liga-Admins können mit DALL-E 3 ein Banner erstellen und mit OpenAI eine kurze Ligazeitung.
- Turnierseiten und Sprachen: Mannschaften, Stadien, Geschichte, Gruppenphase und K.-o.-Runde, in fünf Sprachen, mit Google-Login.
Womit es gebaut ist
Node.js 20, Express 4, EJS, MySQL 8, Passport mit Google OAuth, Nodemailer und ImapFlow, auf Phusion Passenger unter cPanel. Ich veröffentliche in kleinen Schritten und erhöhe jedes Mal die Versionsnummer: Der Code steht bei Version 5.1.642, Build 665. Frühere Ausgaben liefen auf klassischem ASP mit Access-Datenbanken.
Warum so gebaut
Die Anstoßzeiten werden in UTC gespeichert, mit einem separaten Versatz für die Anzeige. API-Football braucht die echte UTC-Zeit, um eine Partie zu finden, die Spieler wollen dagegen die italienische Uhrzeit lesen. Wer beides trennt, vermeidet eine ganze Klasse von Fehlern, bei denen ein Spiel eine Stunde zu früh oder zu spät gesperrt wird.


