import type { PerformanceSurveyScoreBand, PerformanceSurveyTemplateShape } from './performance-survey-templates' export type SurveyScoringAssignment = { workflowStageKey?: string | null reviewerSource?: string | null evaluatorSnapshot?: unknown } /** The saved assessment workflow decides which reviewers contribute to the official result. */ export function isTemplateScoringAssignment(template: PerformanceSurveyTemplateShape, assignment?: SurveyScoringAssignment | null) { const scoring = template.workflow?.scoring if (!scoring) { const visual = template.surveyType === 'visual_case' || template.code === 'visual_brand_tone' const snapshot = assignment?.evaluatorSnapshot const role = snapshot && typeof snapshot === 'object' && !Array.isArray(snapshot) ? String((snapshot as Record).performanceSurveyWorkflowRole || '').trim() : '' return !visual || role === 'visual_final' || role === 'self_visual_final' } if (scoring.mode === 'final_reviewer') { return assignment?.workflowStageKey === scoring.stageKey && assignment?.reviewerSource === scoring.reviewerSource } return !scoring.stageKeys?.length || scoring.stageKeys.includes(String(assignment?.workflowStageKey || '')) } export function calculateAggregateScore( responses: Array<{ id?: string totalScore: number createdAt: Date | string scores?: Record | null respondentName?: string | null }>, _scoreBands: PerformanceSurveyScoreBand[], _weight: number, template?: Pick, ) { const directAverage = responses.length > 0 ? responses.reduce((sum, response) => sum + Number(response.totalScore || 0), 0) / responses.length : null const dimensionAverages = Object.fromEntries( (template?.questions || []).map((question) => { const values = responses .map((response) => Number(response.scores?.[question.id])) .filter(Number.isFinite) const average = values.length > 0 ? values.reduce((sum, value) => sum + value, 0) / values.length : null return [question.id, average == null ? null : roundScore(average)] }), ) const directScore = directAverage == null ? null : roundScore(directAverage) return { responseCount: responses.length, effectiveCount: responses.length, rawAverage: directScore, trimmedAverage: directScore, droppedHighestLowest: false, trimNote: responses.length > 0 ? '按全部评分直接计算平均分' : '暂无评分', removedHigh: null, removedLow: null, dimensionAverages, achievementLabel: template?.achievementLabel, achievementSuffix: template?.achievementSuffix, maxTotal: template?.maxTotal, weightLabel: template?.weightLabel, band: null, achievementScore: directScore, kpiScore: directScore, weightedScore: directScore, } } function roundScore(value: number) { return Math.round(Number(value || 0) * 100) / 100 }