1. 桥牌比赛计分系统架构设计
作为一名长期从事棋牌类游戏开发的工程师,我发现桥牌比赛的数字化计分一直是个痛点。传统纸质计分方式效率低下且容易出错,而市面上通用计分软件又难以满足专业比赛需求。这套基于Flask+微信小程序的解决方案,正是针对这个痛点设计的。
1.1 系统核心功能模块
系统采用模块化设计,主要分为四大功能板块:
-
用户认证模块:通过微信开放平台实现OAuth2.0授权登录,自动获取用户基本信息。根据用户角色(选手/裁判/管理员)动态分配权限,管理员可进行选手分组和裁判指派。
-
比赛管理模块:支持创建瑞士移位制或循环赛制的比赛,可自定义轮次数、每副牌编号范围。系统自动生成桌位分配方案,实时显示比赛进度和完成情况。
-
智能计分模块:核心功能包括:
- IMP(国际比赛分)计算:采用WBF标准公式,基准分可配置
- MP(比赛分)计算:实现自动排名和百分比转换
- 分差补偿:支持VP(胜利分)转换和调整分计算
- 实时排名:根据赛制自动生成个人/团队排行榜
-
数据服务模块:提供WebSocket实时推送成绩更新,支持历史记录查询和Excel报表导出。通过Redis缓存热门数据,减轻数据库压力。
1.2 技术选型考量
选择Flask作为后端框架主要基于以下考虑:
- 轻量级架构适合快速迭代开发
- 丰富的扩展生态(SQLAlchemy、Login、JWT等)
- Python在科学计算方面的优势便于实现计分算法
- 与微信小程序对接简单,RESTful API设计友好
数据库采用MySQL+Redis组合:
- MySQL存储结构化比赛数据,利用事务保证计分准确性
- Redis缓存实时排名和比赛状态,支撑高并发访问
前端选择微信小程序原生开发:
- 无需安装,扫码即用
- 完善的用户体系和消息通知能力
- 丰富的UI组件和API支持
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 数据库设计与优化
2.1 核心表结构设计
python复制# 比赛主表增加瑞士移位相关字段
class Tournament(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(80), unique=True)
start_time = db.Column(db.DateTime)
total_rounds = db.Column(db.Integer)
current_round = db.Column(db.Integer, default=0)
scoring_method = db.Column(db.String(20)) # IMP/MP/VP
status = db.Column(db.String(10)) # preparing/running/finished
# 队伍表增加瑞士移位积分
class Team(db.Model):
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(50))
captain_id = db.Column(db.Integer, db.ForeignKey('user.id'))
total_vp = db.Column(db.Float, default=0) # 胜利分累计
imp_diff = db.Column(db.Float, default=0) # IMP差累计
# 牌桌记录表优化
class Board(db.Model):
id = db.Column(db.Integer, primary_key=True)
round_num = db.Column(db.Integer)
table_num = db.Column(db.Integer)
board_num = db.Column(db.Integer) # 实际牌副号
ns_team = db.Column(db.Integer, db.ForeignKey('team.id'))
ew_team = db.Column(db.Integer, db.ForeignKey('team.id'))
is_finished = db.Column(db.Boolean, default=False)
2.2 关键索引设计
为提高查询性能,特别为以下字段创建组合索引:
Board(round_num, table_num)加速桌位查询Score(board_id, created_at)优化成绩检索Team(total_vp)加速排名计算
2.3 数据关系优化
使用SQLAlchemy的关系加载策略优化查询:
python复制class Score(db.Model):
# ...
board = db.relationship('Board', lazy='joined') # 立即加载关联牌桌
class Tournament(db.Model):
# ...
boards = db.relationship('Board', backref='tournament', lazy='dynamic') # 动态加载
3. 核心计分算法实现
3.1 IMP计算优化实现
python复制from math import log
def calculate_imp(difference, base=15):
"""
优化后的IMP计算函数,增加边界值处理
:param difference: 分差(NS得分-EW得分)
:param base: 基准分,默认15(WBF标准)
:return: 四舍五入到小数点后1位的IMP值
"""
if difference == 0:
return 0.0
try:
imp = 10 * log(1 + abs(difference)/base) / log(10)
imp = round(imp, 1)
return imp if difference > 0 else -imp
except ValueError:
return 0.0
3.2 MP排名算法升级
pyth复制
