course-assessment.js 2.2 KB

123456789101112131415161718192021222324252627282930313233343536
  1. // Generated by scripts/build-workshop-skill.mjs; maintain the Skill course-assessment.mjs source.
  2. /** v3 course scores live in an existing report table, separately from 0–100 peer reviews. */
  3. export const COURSE_ASSESSMENT_ID = 'course-priority';
  4. export const COURSE_ASSESSMENT_COLUMNS = Object.freeze(['机会', '证据强度', '可做性', '商业价值', '依据一句话', '排序']);
  5. const invalid = () => { throw Object.assign(Error('COURSE_ASSESSMENT_INVALID'), { code: 'COURSE_ASSESSMENT_INVALID' }); };
  6. const key = value => typeof value === 'string' ? value.replace(/\s/gu, '') : '';
  7. const text = value => typeof value === 'string' && Boolean(value.trim());
  8. const score = value => {
  9. if (value === null || value === '' || ['待确认', '未知', '未评分', '—'].includes(value)) return null;
  10. if (typeof value === 'string' && /^[123]$/.test(value.trim())) value = Number(value.trim());
  11. if (!Number.isInteger(value) || value < 1 || value > 3) invalid();
  12. return value;
  13. };
  14. export function courseAssessmentRows(section) {
  15. if (section?.id !== COURSE_ASSESSMENT_ID) return null;
  16. if (section.kind !== 'table' || !Array.isArray(section.data?.cols)
  17. || section.data.cols.length !== COURSE_ASSESSMENT_COLUMNS.length
  18. || section.data.cols.some((column, i) => key(column) !== key(COURSE_ASSESSMENT_COLUMNS[i]))
  19. || !Array.isArray(section.data.rows) || !section.data.rows.length) invalid();
  20. return section.data.rows.map(row => {
  21. if (!Array.isArray(row) || row.length !== 6) invalid();
  22. const [candidate, evidence, feasibility, business, basis, order] = row;
  23. if (!text(candidate) || !text(basis) || typeof order !== 'string') invalid();
  24. const scores = [evidence, feasibility, business].map(score);
  25. const unknown = scores.some(value => value === null);
  26. const low = scores.includes(1);
  27. if ((unknown || low) && /^(?:第\s*)?[123一二三]\s*(?:名|位)?$/.test(order.trim())) invalid();
  28. return { candidate, scores, basis, order, unknown, low,
  29. status: low ? '不进入前三' : unknown ? '未知项待补' : '可参与排序' };
  30. });
  31. }
  32. export function validateCourseAssessment(report) {
  33. for (const chapter of report?.chapters || []) for (const section of chapter.sections || []) courseAssessmentRows(section);
  34. }