问题
TotoMondiale是我从2000年代中期起为各大足球赛事运营的免费竞猜游戏。它的名人堂记录了TotoEuropeo 2008、TotoEuropeo 2012、TotoMondiale 2014和TotoEuropeo 2016。规则一直变化不大:每场比赛填写一张竞猜单,积分按赔率计算,每张竞猜单都在开球前公开,谁也无法作弊。旧的经典ASP网站无法提供玩家如今期待的功能:与朋友组建私人联赛、适配手机的布局和实时比分。为了2026年世界杯,我将它彻底重写。
我做了什么
一个全新的Node.js平台,保留原有规则,并增加了联赛、实时数据和一些趣味玩法。
- 包含9种竞猜的竞猜单:全场结果、半场、双方是否进球、大小球、点球、半场/全场、单双、准确比分、总进球数。赔率来自API-Football,缺失时使用默认赔率。
- 私人联赛和公开联赛:每个联赛都有自己的积分榜、横幅、新闻滚动条和聊天。
- 特殊卡牌:Sesto Senso在准确比分上给予加分,Malocchio扣除另一名玩家的积分,Cornicello可以抵消Malocchio。
- 写进代码的公平竞赛:在比赛锁定之前,其他玩家的竞猜单和卡牌始终隐藏,平台管理员也不例外。如果有人忘了填写,系统会随机代填一张,与最初的规则完全一致。
- 实时比赛:一个定时任务每30秒查询一次API-Football,在比赛进行中更新比分。
- AI功能:Claude每天生成一组推荐竞猜;联赛管理员可以用DALL-E 3制作横幅,并用OpenAI生成一份简短的联赛报纸。
- 赛事页面和多语言:球队、球场、历史、小组赛和淘汰赛对阵图,支持五种语言,并可用Google登录。
技术栈
Node.js 20、Express 4、EJS、MySQL 8、使用Google OAuth的Passport、Nodemailer和ImapFlow,运行在cPanel的Phusion Passenger上。我以小步迭代发布,每次都升级版本号:代码目前为5.1.642版,构建号665。早期版本运行在经典ASP和Access数据库上。
为什么这样做
开球时间以UTC存储,显示用的时差单独保存。API-Football需要真实的UTC时间来查找比赛,而玩家想看到意大利时间。把两者分开,就杜绝了比赛提前或推迟一小时锁定这一整类问题。


