加权概率随机点名器 — 学生被抽取次数越少,被选中的概率越高。基于 PyQt5,无边框半透明窗口,支持名单加密、配色切换、悬浮球最小化。
pip install PyQt5
python main.py$env:QT_QPA_PLATFORM='offscreen'; python tests\test_core.py| 功能 | 说明 |
|---|---|
| 🎯 加权随机 | 三层公平性保护 — 逆频次加权 + 平均值过滤 + 候选池下限保障;另有均匀随机 / 冷启动优先 / 按小组轮转三种模式 |
| 👥 多人抽取 | 右键 → 多人抽取...(Ctrl+M),无放回一次抽取 2–10 人 |
| 🔁 连续不重复 | 同一学生不会连续两轮被抽中,避免"刚被点又再点" |
| 📋 名单导入 | 右键 → 导入名单,支持 .txt / .csv(学号,姓名 或 #小组名 分组) |
| 🔒 名单加密 | 名单以 names.enc 本地存储,AES-GCM 加密(无 cryptography 时降级 XOR) |
| 🟢 悬浮球 | Esc 最小化到屏幕右侧可拖拽白色半透明圆球,点击恢复 |
| 🎨 4 套配色 | 晴空蓝 / 靛蓝 / 翡翠绿 / 日落橙 |
| 🔍 窗口透明度 | 5 档预设(30%~90%)+ 滑块实时自定义预览 |
| 🔤 字体切换 | 4 款:HarmonyOS Sans / Inter Display / Open Sans / Noto Sans |
| ⚡ 快速模式 | 右下角按钮,跳过名字闪动动画直接出结果 |
| 🔔 音效 | 右键菜单开关,winsound.Beep 合成蜂鸣音效(Windows) |
| 📊 统计弹窗 | 可排序表格,前三名金银铜高亮,含当前概率列,支持导出/重置 |
| 📈 概率分布 | 水平条形图面板,颜色从绿(高概率)渐变到红(低概率) |
| 📜 历史记录 | 自动记录每次抽取时间、模式、结果,支持清除 |
| 🖱️ 窗口拖拽 | 无边框窗口任意拖拽,关闭时自动记忆位置 |
| 快捷键 | 功能 |
|---|---|
Space / Enter |
单人抽取 |
Ctrl+M |
多人抽取 |
Esc |
最小化到悬浮球 |
Ctrl+T |
循环切换配色方案 |
| 双击 / 右键 | 抽取 / 打开菜单 |
├── 导入名单
├── 统计 ▸ (查看统计信息 / 查看概率分布 / 查看抽取历史 / 清除抽取历史 / 重置数据 / 导出统计数据)
├── 多人抽取...
├── 配色方案 ▸ (晴空蓝 / 靛蓝 / 翡翠绿 / 日落橙)
├── 窗口透明度 ▸ (极透明30% / 高透明45% / 默认60% / 低透明75% / 微透明90% / 自定义...)
├── 显示字体 ▸ (HarmonyOS Sans / Inter Display / Open Sans / Noto Sans)
├── 小球透明度 ▸ (微透明30% / 高透明50% / 默认70% / 低透明85% / 实心100% / 自定义...)
├── 音效
├── 快捷键说明
├── 关于软件
└── 关闭程序
├── main.py # 应用入口(DPI 适配 → 启动画面 → 主窗口)
├── config.py # 常量、路径管理、偏好 JSON 读写、QSS 样式生成
├── design_tokens.py # 4 套配色方案的 Token 定义(三层合并策略)
├── draw_strategy.py # 公平抽取策略注册表(逆频次/均匀/冷启动/小组轮转)
├── main_window.py # 主窗口:生命周期、状态持有、事件编排
├── draw_controller.py # 抽取流程控制:连续不重复、多人无放回、统计/历史写入
├── context_menu.py # 右键菜单构建与动作分发
├── ui_dialogs.py # 透明度、统计、概率、历史、多人抽取、关于等对话框
├── ui_styles.py # 各类对话框/消息框的 QSS 样式生成
├── result_animator.py # 结果文字自适应与淡入动画
├── toast_manager.py # Toast 提示生命周期与淡入动画
├── student_manager.py # 名单加载/导入/AES-GCM 加解密、随机默认名单生成
├── stats_manager.py # 统计 CRUD、概率计算(策略引擎带缓存)、导出
├── history_manager.py # 抽取历史 CRUD(自动截断至 500 条)
├── float_ball.py # 可拖拽圆形悬浮球迷你窗口
├── splash_screen.py # 启动画面(圆角卡片 + 点动画 + 淡入淡出)
├── flash_animation.py # 名字闪动动画(QTimer 递归,无线程)
├── sound_manager.py # winsound 蜂鸣音效(上升/下降音符序列)
├── tests/test_core.py # 核心逻辑测试(加解密、概率、缓存、统计持久化)
├── students_example.txt # 示例名单(40 人)
├── build.ps1 # 一键构建脚本(Nuitka + NSIS)
├── installer.nsi # NSIS 安装包脚本
└── AGENTS.md # AI 辅助开发指南
| 文件 | 路径(Windows) | 说明 |
|---|---|---|
names.enc |
%USERPROFILE%\Documents\check number\ |
加密的学生名单(AES-GCM,旧 XOR 格式自动迁移) |
stats.json |
%USERPROFILE%\Documents\check number\stats\ |
每人抽取次数统计 |
draw_history.json |
%USERPROFILE%\Documents\check number\stats\ |
抽取历史记录 |
config.json |
%USERPROFILE%\Documents\check number\ |
用户偏好(配色/透明度/字体/位置) |
纯文本,每行一个姓名,UTF-8 编码:
张三
李四
王五
也支持 CSV 两列(学号,姓名)与小组标记(#小组名 行后的学生归入该组,配合"按小组轮转"公平模式):
001,张三
002,李四
#第一组
003,王五
004,赵六
右键 → 导入名单,选择文件即可替换。首次运行无名单时自动生成随机中文姓名(共 60 人)。
| 变量 | 说明 | 默认值 |
|---|---|---|
secret.key(数据目录) |
自定义密钥文件,存在时优先(任意文本) | 无 |
CHECK_NUMBER_KEY |
环境变量密钥 | 内置默认值 |
名单本地存储、不上云。加密用 AES-GCM(cryptography 可选依赖,缺失时自动降级 XOR)。
# Nuitka 编译
pip install nuitka
python -m nuitka --standalone --enable-plugin=pyqt5 --windows-console-mode=disable --output-dir=build --output-filename=CheckNumber.exe --include-data-files=CHANGELOG.md=CHANGELOG.md --assume-yes-for-downloads main.py
# 或使用一键脚本
.\build.ps1 # Nuitka + NSIS 完整构建
.\build.ps1 -SkipNuitka # 仅重新打包安装包
.\build.ps1 -SkipInstaller # 仅编译
.\build.ps1 -Clean # 清理后构建已预构建安装包见 GitHub Releases。
- 概率算法: 策略引擎(
draw_strategy.py)四模式 — 逆频次加权(默认,三层公平保护)/ 均匀随机 / 冷启动优先 / 按小组轮转;random.choices()抽取,结果缓存预热 - 多人无放回: 循环抽取 N 次,每轮从剩余池移除已选学生,含连续不重复保护
- 名单加密: AES-GCM(magic 头 + nonce + tag),旧 XOR 格式读取时自动迁移;写入时原子替换(tmp → replace)
- 动画:
QPropertyAnimation(淡入)+QTimer递归(闪动),全程无需线程 - 窗口:
FramelessWindowHint+WA_TranslucentBackground,背景半透明而文字清晰 - 实时预览: 透明度/字体切换支持
save=False参数,滑块拖动时不写磁盘
详见 CHANGELOG.md
MIT License © 2023-2026 Kiuyor | 联系:750173212@qq.com