export type PrincipleCategoryId = 'people' | 'environment' | 'things' export interface Principle { id: string categoryId: PrincipleCategoryId order: number name: string description: string } export interface PrincipleGroup { id: PrincipleCategoryId label: string order: number items: Principle[] } export const principleGroups: PrincipleGroup[] = [ { id: 'people', label: '人', order: 1, items: [ { id: 'people-stewardship', categoryId: 'people', order: 1, name: '管家式管理', description: '勤勉、尊重和关心他人', }, { id: 'people-stakeholders', categoryId: 'people', order: 2, name: '干系人', description: '促进干系人有效参与', }, { id: 'people-leadership', categoryId: 'people', order: 3, name: '领导力', description: '展现领导力行为', }, { id: 'people-team', categoryId: 'people', order: 4, name: '团队', description: '营造协作的项目团队环境', }, ], }, { id: 'environment', label: '环境', order: 2, items: [ { id: 'env-complexity', categoryId: 'environment', order: 1, name: '复杂性', description: '驾驭复杂性', }, { id: 'env-change', categoryId: 'environment', order: 2, name: '变革', description: '为实现目标而驱动变革', }, { id: 'env-value', categoryId: 'environment', order: 3, name: '价值', description: '聚焦于价值', }, { id: 'env-adaptability', categoryId: 'environment', order: 4, name: '适应性和韧性', description: '拥抱适应性和韧性', }, ], }, { id: 'things', label: '事', order: 3, items: [ { id: 'things-tailoring', categoryId: 'things', order: 1, name: '裁剪', description: '根据环境进行裁剪', }, { id: 'things-risk', categoryId: 'things', order: 2, name: '风险', description: '优化风险应对', }, { id: 'things-quality', categoryId: 'things', order: 3, name: '质量', description: '将质量融入到过程和成果中', }, { id: 'things-system', categoryId: 'things', order: 4, name: '系统交互', description: '识别、评估和响应系统交互', }, ], }, ] /** 所有原则的扁平数组,顺序为:人×4 → 环境×4 → 事×4 */ export const principles: Principle[] = principleGroups.flatMap((g) => g.items) /** 原则 id → Principle 快速查找 */ export const principleMap = new Map( principles.map((p) => [p.id, p]) ) /** 从当前原则 id 出发,找下一个未答对的原则(环形搜索) */ export function getNextUnanswered( currentId: string, answered: Map ): Principle | null { const startIdx = principles.findIndex((p) => p.id === currentId) for (let offset = 1; offset <= principles.length; offset++) { const candidate = principles[(startIdx + offset) % principles.length] if (!answered.get(candidate.id)) return candidate } return null }