本文档说明「未来专业人格卡」的打分算法。实现见 src/lib/score.ts,
对应测试见 src/lib/score.test.ts,依据 PRD v1.1 §8 / §9 / §10。
当前实现的推荐链路是:
18 道双选题 → RIASEC 六维分 → 人格卡 → 人格卡候选专业池排序 → 结果页推荐
↘ 全量 99 大类排序 → 完整专业报告
题目选项绑定的专业大类只提供「提示分」,用于微调排序;完整专业覆盖由 31 张人格卡的
persona.majors 候选池共同承担。
算法对外只有一个入口:
scoreAll(answers: Answer[]): ScoreResultanswers 是用户对 18 道题的作答,每题一条:
interface Answer {
qIndex: number; // 题目下标 0–17
first: Letter | null; // 「最想做」选项的 RIASEC 字母
second: Letter | null; // 「第二想做」选项的 RIASEC 字母
}Letter 为 RIASEC 六维之一:R 现实型 / I 研究型 / A 艺术型 / S 社会型 / E 企业型 / C 常规型。
PRD §8.1 的核心思路是「先判人格,再推专业」:
| 层 | 算什么 | 用途 |
|---|---|---|
| 第一层 | RIASEC 兴趣分 | 决定人格卡(稳定、易分享) |
| 第二层 | 专业大类提示分 | 让专业推荐贴近学生的具体作答(可细化) |
两层结果再加权成「专业推荐分」,对专业大类排序。
数据层位于 src/data/quiz.ts,核心有三组:
| 数据 | 数量 | 用途 |
|---|---|---|
QUIZ_BANK |
18 题 | 产生 RIASEC 兴趣分和专业提示分 |
PERSONAS |
31 张 | 承接 30 个有序双维人格 + 1 个「未来多面手」 |
MAJORS |
99 个 | 专业大类元数据,顺序来自 major_data/major_categories.md |
MAJORS.rank 与 major_data/major_categories.md 的序号一致,也作为同分时的稳定排序依据。
新增大类没有富详情时,详情页仍走现有「暂无解析」占位;这不影响推荐排序。
PERSONAS[].majors 是当前人格卡的完整专业候选池。31 张卡合起来覆盖 99 个大类;
单张卡通常保留约 9–11 个候选,结果页再从当前卡里切出「优先探索」和「继续了解」。
QUIZ_BANK.options[].majors 不是 99 大类全集,只是该题选项的提示标签。它可以让用户的具体作答
影响同一人格卡内部的排序,但不负责完整覆盖。
-
第 1 题(场景题·大学专业开放日):你最想先去哪类展台?
A. 机器人 / 无人机现场演示
B. AI / 数据 / 生命科学讲座
C. 设计 / 影像 / 建筑模型
D. 心理 / 教育 / 公益项目
E. 创业路演 / 金融模拟 / 法学辩论
F. 培养方案 / 录取规则 / 课程表 -
第 2 题(项目题·第一学期项目制课程):你最想负责什么?
A. 做实物原型 / 装置
B. 查资料 / 实验 / 数据验证
C. 设计页面 / 海报 / 视觉
D. 用户访谈 / 同伴辅导
E. 路演 / 合作沟通 / 资源争取
F. 预算 / 排期 / 风险管理 -
第 3 题(场景题·AI 应用比赛):你更想做哪件事?
A. 把 AI 接到硬件 / 机器人
B. 训练或评估 AI 模型
C. 设计 AI 产品界面 / 脚本
D. AI 助学 / 心理 / 医疗
E. 规划 AI 产品商业模式
F. 整理需求 / 测试 / 数据规范 -
第 4 题(选择题·大学实验室 / 实践基地):你想进入哪一个?
A. 智能制造 / 车辆 / 无人机
B. 算法 / 生命科学 / 材料
C. 数字媒体 / 影视 / 建筑设计
D. 教育实践 / 心理 / 临床
E. 创业孵化 / 投资 / 模拟法庭
F. 数据治理 / 供应链 / 政务 -
第 5 题(主题题·新能源与双碳):你更想参与什么?
A. 电池 / 储能 / 能源设备
B. 碳排放数据 / 政策建模
C. 低碳传播 / 海报 / 展览
D. 社区节能 / 公众教育
E. 新能源商业 / 融资 / 推广
F. 碳核算 / 项目流程 / 合规 -
第 6 题(主题题·医学与健康):你更想做什么?
A. 康复设备 / 医学影像
B. 研究疾病 / 药物 / 流行病
C. 健康科普短视频 / 图文
D. 陪伴患者 / 心理支持 / 护理
E. 医疗服务产品 / 医院运营
F. 病历 / 检验 / 药品合规 -
第 7 题(项目题·校园创业项目):你最想负责什么?
A. 产品样机 / 线下服务流程
B. 用户数据 / 竞品 / 成本分析
C. 品牌 / 宣传片 / 短视频
D. 用户关系 / 客服 / 社群
E. 定价 / 销售 / 融资路演
F. 订单 / 库存 / 财务合同 -
第 8 题(主题题·未来城市项目):你更想做哪部分?
A. 交通 / 能源 / 基础设施模型
B. 人口 / 地理 / 交通数据
C. 城市公共空间 / 文旅体验
D. 居民访谈 / 社区治理
E. 城市招商 / 产业规划
F. 审批 / 预算 / 风险管理 -
第 9 题(项目题·大学生新闻 / 传播项目):你更想负责什么?
A. 现场拍摄 / 搭直播设备
B. 核查资料 / 数据 / 证据
C. 写稿 / 剪片 / 视觉包装
D. 采访不同群体 / 理解立场
E. 传播节奏 / 品牌 / 增长
F. 素材库 / 审核 / 版权流程 -
第 10 题(问题题·面对学生学习焦虑):你更想怎么做?
A. 做一个学习工具 / 教具
B. 研究学习数据 / 心理机制
C. 课程动画 / 讲解视频 / 图文
D. 辅导 / 倾听 / 班级活动
E. 推广学习产品 / 训练营
F. 学习计划 / 测评 / 反馈流程 -
第 11 题(场景题·一个数据项目):你更想处理哪类数据?
A. 设备 / 交通 / 能源 / 传感器
B. 算法 / 金融 / 医学 / 调查
C. 点击 / 传播 / 体验 / 视觉
D. 学习 / 心理 / 健康 / 公共服务
E. 销售 / 消费 / 投资 / 经营
F. 预算 / 流程 / 供应链 / 档案 -
第 12 题(项目题·机器人 / 智能装备项目):你更想做什么?
A. 结构 / 控制 / 设备调试
B. 识别算法 / 路径规划
C. 外观 / 交互 / 展示视频
D. 服务老人 / 学生 / 社区
E. 行业应用 / 商业模式
F. 安全规范 / 测试 / 采购 -
第 13 题(主题题·法律和社会议题):你更想做什么?
A. 走访现场 / 记录证据
B. 研究法条 / 案例 / 政策
C. 写评论 / 普法短视频
D. 为弱势群体咨询 / 调解
E. 辩论 / 谈判 / 公共倡议
F. 合同 / 合规 / 档案 / 风控 -
第 14 题(场景题·国际交流 / 跨境项目):你更想负责什么?
A. 跨境物流 / 设备 / 技术对接
B. 国际市场 / 政策 / 汇率
C. 翻译 / 写作 / 国际传播
D. 接待交流学生 / 文化沟通
E. 商务拓展 / 跨境电商
F. 合同 / 报关 / 税务 / 合规 -
第 15 题(主题题·数字文旅 / 城市文化项目):你更想做什么?
A. 展陈设备 / 空间动线 / 互动装置
B. 历史资料 / 游客数据 / 文脉
C. 短剧 / 展览 / 游戏化体验
D. 导览服务 / 志愿者培训
E. 文旅产品 / 商业合作 / 营销
F. 票务 / 预算 / 版权 / 运营 -
第 16 题(展望题·毕业设计):你希望最后呈现什么成果?
A. 能运行的装置 / 系统 / 工程
B. 数据 / 实验 / 模型支撑的研究
C. 作品集 / 短片 / 展览 / 剧本
D. 帮助人的课程 / 咨询 / 公共服务
E. 商业计划 / 品牌 / 创业方案
F. 流程 / 预算 / 标准 / 管理手册 -
第 17 题(角色题·大学团队):你最自然会承担哪种角色?
A. 动手解决设备 / 现场问题
B. 找资料 / 分析 / 验证判断
C. 表达 / 审美 / 内容包装
D. 照顾团队关系 / 支持他人
E. 争取资源 / 对外推动决策
F. 管理任务 / 进度 / 资料 / 风控 -
第 18 题(终极题·真正选专业时):哪类大学生活最让你愿意投入四年?
A. 实验室 / 车间 / 现场做实物
B. 研究问题 / 写代码 / 读论文
C. 创作作品 / 设计体验 / 讲故事
D. 帮助人成长 / 变好 / 解决困难
E. 商业 / 法律 / 谈判 / 公共表达
F. 规则 / 数据 / 流程 / 系统运行
每道题用户选两次,按 PRD §8.1 计分:
最想做(first) → 对应维度 +2
第二想做(second) → 对应维度 +1
完整有效作答时,18 题、每题 2 + 1 = 3 分,六维总分恒为 54(单元测试有断言)。
scoreAll 对空答案、缺少第二选择或越界题号做容错处理,这些边缘输入不会强行补分。
六维累计后降序排序;同分时按 RIASEC 规范序 R < I < A < S < E < C 固定先后,
保证同一组答案每次得到完全一致的结果(确定性)。
排序后的前两维拼成人格代码,按得分主次序书写(主导维在前),
因此「C 排第 1、I 排第 2」得到代码 C-I,而「I 排第 1、C 排第 2」得到 I-C,二者是不同的人格卡,
命中 30 个有序双维人格之一;满足「多面手」条件时则取「未来多面手」(见下文)。
完全平分时由上面的规范序兜底确定谁是主导维,仍保持确定性。
每个选项除了一个 RIASEC 字母,还绑定若干「专业大类标签」(见 quiz.ts 中每个 option 的 majors)。
用户选中该选项时,对这些专业大类累加提示分(PRD §8.1):
最想做选项绑定的每个专业大类 → +1.0
第二想做选项绑定的每个专业大类 → +0.5
累计结果记为 hintScore[专业大类]。
如果某个专业大类从未出现在用户选中的题目选项里,它的 hintScore 默认为 0,仍会参与
RIASEC 匹配排序。
对每个专业大类,按 PRD §8.1 的公式算综合推荐分:
推荐分 = 0.65 × RIASEC匹配分 + 0.35 × 题目专业提示分 + 主导维对齐微调
其中 RIASEC 匹配分 r 按学生维度排名命中专业的 RIASEC 标签计:
专业的 RIASEC 标签命中学生第 1 维度 → r += 5
第 2 维度 → r += 3
第 3 维度 → r += 1
「命中」指专业的标签集合包含该维度,与标签在集合中的位置无关。
题目专业提示分 即上一节的 hintScore[该专业大类]。
主导维对齐微调:若专业自身首要标签(riasec[0])等于学生第 1 维,则 +0.05。
它小于最小的提示分步长(0.5×0.35=0.175),只在 r 与提示分都打平时拆平局,不会打乱已分高下的排名。
作用是让有序双维卡的正/反两张(如 R-I 与 I-R)在专业排序上分出先后——
那些「骨子里更偏主导维」的专业(如兵器类标签 [R,I,C],首位 R)会对 R 主导用户上浮、对 C 主导用户不上浮。
注:当某专业被用户作答的提示分明显顶高时,提示分优先级高于此微调(这是有意的:实际作答 > 结构性拆平局)。
同分时统一按 rank 升序排序,保证同一组答案每次返回一致结果。
scoreAll 会生成三类专业列表,取值范围不同:
| 字段 | 候选范围 | 数量 | 用途 |
|---|---|---|---|
personaMajors |
当前 persona.majors |
当前人格卡完整候选池 | 结果页和完整专业报告展示本卡全部候选 |
priorityMajors |
当前 persona.majors |
3 | 本卡候选池前 3 个,高优先级推荐 |
continueMajors |
当前 persona.majors |
3 | 本卡候选池第 4–6 个,继续了解方向 |
deepReport |
全量 99 个 MAJORS |
10 | 完整专业报告 |
排序都使用同一个「专业推荐分」公式。差别只在候选范围:
- 结果页推荐只从当前人格卡候选池里取,并展示完整的
personaMajors顺序 priorityMajors和continueMajors是为了局部强调,不代表人格卡候选池只有 3 个或 6 个- 完整专业报告从 99 个大类全量排序,给用户看到更宽的探索面
- 多面手结果额外生成
multiTracks,见下文
PRD §8.2 给出 5 条相互独立、可同时成立的展示规则。算法返回一组布尔标记, 而不是单一枚举,结果页据此可叠加展示多条文案:
interface Confidence {
mainClear: boolean; // 第1名比第2名高 ≥5 分 → 主线很清晰
dualCore: boolean; // 第1名与第2名差 0–4 分 → 双核心人格
thirdColor: boolean; // 第2名与第3名差 0–2 分 → 潜在第三色
multi: boolean; // 最高与最低差 <8 分 → 未来多面手
lowDims: Letter[]; // 显著偏低的维度
}判定细节:
| 标记 | 条件 |
|---|---|
mainClear |
非多面手,且 gap12 = 第1名 − 第2名 ≥ 5 |
dualCore |
非多面手,且 gap12 ≤ 4 |
thirdColor |
非多面手,且 gap23 = 第2名 − 第3名 ≤ 2 |
multi |
spread = 最高分 − 最低分 < 8 |
lowDims |
非多面手时,所有满足 最高分 − 该维度 ≥ 10 的维度 |
mainClear 与 dualCore 互斥(gap12 要么 ≥5 要么 ≤4),但 dualCore 与 thirdColor 可并存。
对 lowDims 里的维度,结果页用「当前吸引力较低」措辞,禁止写「不适合」(PRD §13.4)。
设计稿(design-reference/)里的原型打分函数与 PRD 有三处不一致,本实现已修订。
原型从全量专业大类的排名里切前 3 / 第 4–6。当前数据层已有
99 个专业大类,但 PRD §10 的结果页模板明确是
人格卡专属的专业大类(§9 每张卡的「优先探索专业大类」列、§12.3 的 recommended_major_categories)。
本实现:
- 候选集 = 当前人格卡的
persona.majors(约 9–11 项) - 用「专业推荐分」对候选集排序:全部 →
personaMajors,前 3 →priorityMajors,第 4–6 →continueMajors - 题目选项绑定的专业大类只作为提示分来源,不承担完整覆盖;完整 99 大类覆盖由人格卡候选池承担
- 全量 99 大类的推荐分排名单独保留为
deepReport(取前 10),仅供「完整专业报告页」的 深度报告区按需展开(PRD §8.3「深度报告 8–12 个」),不进结果页首屏
原型把置信度做成单选枚举(multi > dual > third > clear 取一个)。
PRD §8.2 是 5 条独立规则,已改为上文的布尔标记组。
原型在「多面手」时用「未来多面手」卡的固定 majors 列表。PRD §9 多线行要求
「根据前三高维度生成组合,展示 3 条专业探索线」。
本实现:multi 为真时人格取「未来多面手」卡,但额外按前三高维度各生成一条探索线 ——
每条线 = { 该维度, 该维度下推荐分最高的 1–2 个专业大类 },三条线之间去重,存入 multiTracks。
interface ScoreResult {
dim: Record<Letter, number>; // 六维原始分
ordered: [Letter, number][]; // 六维降序(含同分确定性排序)
top: Letter; second: Letter; third: Letter;
persona: Persona; // 命中的人格卡
confidence: Confidence; // 置信度标记组
personaMajors: Major[]; // 当前人格卡完整候选池,按推荐分排序
priorityMajors: Major[]; // 修订1:人格卡范围内推荐分前 3
continueMajors: Major[]; // 修订1:人格卡范围内推荐分第 4–6
deepReport: Major[]; // 全量 99 排名前 10,供深度报告
multiTracks?: MultiTrack[]; // 修订3:仅多面手时有,3 条探索线
}DEMO_RESULT(结果页在「尚未作答」时的占位数据)也通过对一组真实答案跑 scoreAll 生成,
避免演示数据与算法逻辑漂移。
src/lib/score.test.ts 覆盖:
- 六维总分恒为 54
- 人格代码落在有效 31 张之内
- 修订 1:
personaMajors覆盖当前人格卡完整候选池,priorityMajors/continueMajors全部 ⊆persona.majors - 修订 2:构造
gap12 ≤ 4且gap23 ≤ 2的答案,dualCore与thirdColor同时为 true - 修订 3:构造
spread < 8的答案,multi为 true 且multiTracks含 3 条线
运行:npm run test
src/data/quiz.test.ts 额外守住数据口径:
MAJORS恰好 99 项- 名称、顺序、门类与
major_data/major_categories.md完全一致 rank为 1–99 且唯一- 所有题目选项与人格卡引用的大类都能被
findMajor解析 - 99 个大类都至少被 1 张人格卡覆盖