多人、多次作业的自动分组工具。自由设置人数、每次组数和类型,也可保留固定小组,让其余同学轮换。比较「机会均衡」和「整体覆盖」,让同学尽量遇到更多不同队友。
在线使用:mappedinfo.github.io/groupme
右上角可切换中文 / English;语言偏好单独保存在当前浏览器。页面按「基础信息 → 小组信息 → 特定分组 → 优化目标」分为四个同级区块。界面、校验提示、结果说明和复制名单随语言切换,姓名与自定义类型保留原文;切换不会重新求解或清空当前输入、草稿与结果。
- 设置总人数与作业次数。当前浏览器版本支持 6–300 人、1–30 次作业。
- 可填写「期望每组人数」,或点击下方推荐。页面会显示实际分成几组、每组几人。留空表示不限制期望人数。
- 每次作业的组数可以留空自动选择,也可分别指定。手动组数优先于期望人数;可点击「将各次组数全部改为自动」统一按期望求解。
- 如需考虑类型或水平,点击「编辑类型」,可快捷分 2 类或 3 类,再逐人下拉调整;也可按编号每行粘贴一个标签。保存后选择「不同类型混合」或「同类型内组队」。默认不区分类型。
- 如有需要保持不变的小组,点击「编辑固定小组」选取成员,或从已有结果中固定一组。保存后重新求解生效。
- 点击「求解并比较两种方案」,查看两种目标的轮换成员最低覆盖与全班不同搭档数。
- 选择目标、作业和同学,查看每次分组、固定或轮换状态、类型构成、新旧队友和个人合作历史。
- 可填写姓名,或继续使用编号;复制按钮导出当前目标下的全部作业名单、固定小组、期望设置与类型。
- 每次总共至少 3 组,固定小组计入总组数;其余轮换小组可以为 0、1 或 2 组。
- 每组至少 2 人,因此总人数至少为 6。
- 同一次作业中的组人数相差至多 1,只会出现一种或两种人数。
- N 人的每次总组数范围为 3 到 floor(N/2),实际还须满足固定小组与类型约束。
- 每人在每次作业中恰好进入一个组;各次作业可使用不同的组数。
自动模式可以选择各次组数。期望人数留空时,较少的大组可能更有利于认识更多同学;填写期望人数可控制自动作业的小组规模。
「期望每组人数」支持 2–300 的整数,也可留空。自动作业先从满足人数、固定小组与类型规则的合法总组数 K 中,选择全班平均人数 N/K 最接近期望值的安排,再优化新队友。实际人数仍须均匀分配,以预览为准。例如没有固定小组时,14 人期望每组 4 人,会分成 4、4、3、3;期望每组 3 人,会分成 3、3、3、3、2。
若多个组数同样接近,则全部保留,允许不同作业在其中选择。距离使用整数交叉乘积判断,避免浮点误差。例如 24 人分成两个各 12 人的类型、同类内组队、期望每组 5 人时,4 组×6 人与 6 组×4 人同样接近,均可使用。
推荐按当前总人数、固定小组与类型规则生成,按实际可选组数去重,最多显示四种。推荐只在点击后设置期望,不会自动覆盖逐次手动组数。所有作业都已指定组数时,界面会提示期望不影响当前分组规模,并提供显式的一键改为自动操作。
期望输入、推荐和逐次组数统一放在「小组信息」区域,分为「每组规模」和「每次作业的小组数」。两者可按作业混用:填写组数的作业采用指定组数,留空的作业按期望人数安排。区域顶部和每次输入下方显示当前采用方式;全部指定组数时明确标出「期望人数不生效」。收起逐次设置不会清除输入,非法组数或类型冲突会显示待调整提示。
期望设置、实际求解和最优性证明使用相同的自动组数候选。再次求解时,只有有效约束相同才保留旧的更优方案;例如全部组数都手动固定时,改变期望人数仍可复用旧方案。草稿与已求解结果分别保存,旧版没有期望字段的设置按留空恢复。
标签由使用者填写,不根据姓名推断。每人一个标签,最多 20 个字符;空白归为「未分类」,并作为一种类型。标签按同学编号绑定,姓名可以重复。
编辑窗口提供快捷分 2 类、分 3 类,默认尽可能均分。例如 14 人可一键预填 7+7 或 5+5+4,也可填写前一类或前两类的人数,最后一类自动取剩余人数。预览会列出各类名称、人数与编号范围;点击「应用到下方列表」才按编号顺序填入,仍可逐人下拉调整。类别可自定义名称,未出现在下拉选项中的名称可通过「添加类型」加入,批量粘贴的新标签也会自动加入选项。
快捷分类的每类至少 1 人,但不改变作业小组至少 2 人、每次至少 3 组的要求。关闭窗口或按 Esc 放弃未保存编辑;「保存类型设置」只保存列表,随后重新求解才更新结果。
- 不同类型混合:每种类型在轮换小组的数量相差至多 1。例如没有固定组时,6 位基础、8 位进阶分 3 组,每组有 2 位基础,进阶人数分别为 3、3、2。先满足这种均匀分散,再优化两种合作目标。并不要求每个组内各种类型的数量相等。
- 同类型内组队:每个轮换小组只能包含一种类型;全体小组仍须满足每组至少 2 人、总共至少 3 组、全轮大小相差至多 1。单个类型不要求至少分 3 组。自动模式只搜索可行组数;指定组数不兼容时会列出可行组数。轮换成员出现单人类型或任何组数都不可行时会说明原因。
- 不区分类型:沿用原有分组规则,可提前保存标签。仅修改标签不会丢弃同样约束下已找到的更好方案。
类型规则只约束轮换成员,固定小组可以跨类型。同类模式下,轮换成员的覆盖比例与未合作名单仅计算同类型轮换伙伴;固定成员只计算本固定组伙伴。页面同时保留全班实际覆盖比例。混合模式的轮换分母包含所有其他轮换成员;均匀类型规则可能让某些搭档无法同组,因此这个分母不代表所有搭档均可达到。没有固定组时,轮换范围就是全班。所有轮换成员类型均相同时,两种类型模式均等价于不区分类型。
类型编辑属于待求解设置;保存后需要重新求解才应用。旧结果继续使用原有类型快照,取消或失败不会用新标签重新标记旧结果。
结果中,边框以当前选中的同学为参照:实线表示同类型,虚线表示不同类型;饱和蓝色表示本次新队友、深橙色表示本次曾合作队友、深灰色表示当前同学,配合白字和 24 像素方形色块图例。分组卡片与个人队友列表同步更新,并保留类型文字和各组人数构成。选择「不区分类型」时,已保存到结果中的命名标签仍可显示和复制,只是不参与分组限制;全员未分类且未开启类型规则时不显示额外标记。
固定小组是独立的成员约束:从第一次作业起,每次都完整保留同一批成员,不加人、不拆组、不交换成员。每个固定组至少 2 人,同一人只能出现在一个固定组中。固定组可以包含不同类型,其余人员按所选类型规则轮换。
点击「编辑固定小组」,选择成员后加入列表,也可按编号每行填写一组。已有结果中的「固定这组」会把该组加入待求解设置;完全相同的组不会重复添加,与其他固定组有任何成员交集时会拒绝并保留原设置。编辑器中尚未加入列表的选员或尚未应用的批量输入必须先处理,防止保存时遗漏。关闭或取消放弃本次编辑。
「保存固定小组」只保存草稿,重新求解后才应用。可以先保存结构合法、但当前总人数、组数或类型设置暂时无解的草稿,再调整其他设置;页面会提示冲突。保存、取消或求解失败都不会改变旧结果,结果显示和复制始终使用该次求解的固定组快照。
固定组已计入每次总组数,也参加全轮人数均衡校验。固定组和轮换组之间的人数差仍不得超过 1,不能为了保留固定组而放宽规则。只剩 1 位轮换成员时会拒绝求解;所有人都已固定且全轮规则满足时,直接显示「无需轮换」。缩小总人数不会删除固定组或越界成员编号,而会明确提示先编辑固定小组或恢复人数。
固定成员的可合作范围仅包含本固定组;轮换成员的范围不包含任何固定成员,同类模式下还须限定为同类型轮换者。页面分别显示固定组和轮换成员的重复碰面次数,并保留全班不同搭档数与覆盖比例。
按顺序比较,前一项优先于后一项:
| 目标 | 第一优先 | 第二优先 | 平手时 |
|---|---|---|---|
| 机会均衡 | 提高轮换成员的最低不同队友数 | 增加不同搭档总数 | 缩小轮换成员覆盖差异 |
| 整体覆盖 | 增加不同搭档总数 | 提高轮换成员最低覆盖 | 缩小轮换成员覆盖差异 |
没有固定小组时,全员参与轮换。固定成员的队友数不会随方案改变,因此不让这个恒定值压低公平目标;在相同固定设置下,增加全班不同搭档数与增加轮换成员搭档数等价。全部固定时无需优化轮换。
不同搭档按无序人员对计数;个人覆盖差异使用不同队友数的平方差口径。重复碰面统计同一对人在第二次及之后同组的次数。求解不会把「重复最少」放在首位:一个大组可能同时带来旧队友和更多新队友。
两种搜索使用相同的限制,各自优先优化对应目标,并共同比较找到的可行候选。两种目标有时会得到相同结果。相同约束下再次求解,会保留每种目标已找到的更好方案;改变人数、次数、有效组数范围、固定成员集合或类型限制后重新比较。
两种目标使用紧凑卡片,仍同时显示最低个人覆盖、不同搭档数和是否证明最优。点击卡片切换下方完整方案,当前卡片标记「查看中」。
计算在 Web Worker 中执行,页面可随时停止求解。每种目标使用约 4 秒的搜索预算,较简单的组合可能提前完成。求解采用多起点启发式搜索,同时考虑组数和成员安排,保留可复现的随机种子。
有效分组不等于全局最优。 只有达到可验证的数学界时,页面才显示「已证明覆盖目标最优」;否则显示「本次找到的最好方案 · 未证明全局最优」。这也意味着任意人数、次数和组数下不能一概保证零重复队友。证明针对覆盖与公平目标,不保证重复碰面次数在所有完全平手方案中也最小。
对 N 人、K 个均衡小组,令 q=floor(N/K)、r=N mod K,每轮合作名额为 K·q·(q−1)/2+r·q。固定组内部的不同搭档只计一次;先从每轮名额中扣除固定组名额,再累加轮换名额,并用轮换范围内的允许关系数限制总覆盖上界。自动轮以合法组数中的最大轮换名额计算安全上界。最低个人覆盖与覆盖差异仅对轮换成员计算;这些上界不一定可达到。证明与统计都从实际分组重新计算,不信任浏览器存储中的派生指标。
同类模式的轮换覆盖上限为各类型轮换人数对数之和。如果轮换成员已遇到其允许范围内的全部伙伴,则三层目标都已最优,即使不同类型人数导致个人覆盖数不同。固定 K 时,先检查每个固定组大小均为 q 或 q+1,再考虑某类型 c 位轮换成员的组数区间 [ceil(c/(q+1)), floor(c/q)];这些区间须能凑成剩余轮换组数。混合模式通过循环分配轮换类型槽位构造均匀分散安排,换人和重建各轮时保持该约束。固定小组不会进入换人搜索。
需要 Node.js 20 或更高版本,无需安装依赖。
npm start
npm test默认地址为 http://127.0.0.1:4173,可用 PORT 调整。通过本地服务访问,不要直接打开文件。测试使用合成数据,覆盖分组约束、统计、输入错误与小规模独立最优值核对。
姓名、类型、固定小组、设置和分组仅保存在当前浏览器,没有后端、分析脚本或第三方字体。升级会保留旧版可识别的姓名和组数。人数缩小时暂时保留额外姓名与类型,随后增大人数可继续使用;固定小组中的越界编号保留并提示调整。待求解草稿与已求解结果分别保存。停止求解会保留原方案;浏览器拒绝复制时提供手动复制文本。
GitHub Pages 从 main 分支根目录发布,所有资源使用相对路径,无构建步骤。.nojekyll 关闭 Jekyll 处理。
发布涉及脚本或样式更新时,同步更新 HTML 入口、页面内核导入、Worker 地址与 Worker 内核导入的资源版本参数,避免浏览器把新页面与缓存的旧脚本混用。
当前显示版本的资源标识为 i18n-1;发布与线上验证状态见 HANDOFF.md。
src/grouping.js:约束、求解、统计与最优性界。src/solver-worker.js:后台求解消息协议。src/app.js:两方案比较、输入、浏览器保存与复制。src/type-editor.js:快捷分类的人数、标签与编号范围校验。src/i18n.js:语言偏好、纯文本插值与展示翻译,不修改业务数据。src/page-messages.js、src/app-messages.js:静态界面与动态界面的中英文文案。src/domain-error.js:保留中文错误接口,同时提供英文错误消息。src/style.css:白底样式与手机布局。tests/grouping.test.js:内核回归与独立验证。tests/fixed-groups.test.js:固定成员边界、轮换目标、可行组数与独立最优值验证。tests/type-editor.test.js:快捷分类与类型标签校验。tests/i18n.test.js、tests/i18n-kernel.test.js:双语完整性、数据保留、语言存储、校验错误与 Worker 消息。HANDOFF.md:唯一当前状态入口。
MIT,见 LICENSE。