import type { Evaluation, DimensionScore, TemplateDimension, Template } from "@prisma/client"; export interface EvaluationWithScores extends Evaluation { template?: Template | null; dimensionScores: (DimensionScore & { dimension: TemplateDimension })[]; } /** Compute average score across dimensions (1-5 scale) */ export function computeAverageScore(scores: { score: number | null }[]): number { const valid = scores.filter((s) => s.score != null && s.score >= 1 && s.score <= 5); if (valid.length === 0) return 0; return valid.reduce((a, s) => a + (s.score ?? 0), 0) / valid.length; } /** Generate findings paragraph from scores (deterministic template) */ export function generateFindings( scores: { score: number | null; dimension: { name?: string; title?: string } }[] ): string { const withScore = scores.filter((s) => s.score != null); if (withScore.length === 0) return "Aucun score enregistré pour l'instant."; const avg = computeAverageScore(withScore); const dimName = (d: { name?: string; title?: string }) => d.title ?? d.name ?? ""; const weak = withScore.filter((s) => (s.score ?? 0) <= 2).map((s) => dimName(s.dimension)); const strong = withScore.filter((s) => (s.score ?? 0) >= 4).map((s) => dimName(s.dimension)); let text = `Score de maturité global : ${avg.toFixed(1)}/5. `; if (strong.length > 0) { text += `Points forts : ${strong.join(", ")}. `; } if (weak.length > 0) { text += `Axes d'amélioration : ${weak.join(", ")}.`; } else if (strong.length === 0) { text += "Les scores indiquent une maturité modérée sur les dimensions."; } return text; } /** Generate recommendations (deterministic template) */ export function generateRecommendations( scores: { score: number | null; dimension: { name?: string; title?: string } }[] ): string { const dimName = (d: { name?: string; title?: string }) => d.title ?? d.name ?? ""; const weak = scores.filter((s) => (s.score ?? 5) <= 2).map((s) => dimName(s.dimension)); if (weak.length === 0) return "Continuer à s'appuyer sur les pratiques actuelles. Envisager le mentorat pour les juniors."; return `Prioriser la formation et le développement pour : ${weak.join(", ")}. Envisager des programmes de montée en compétence structurés et une expertise externe si les écarts sont importants.`; } /** Convert evaluation to CSV rows (one per dimension + metadata row) */ export function evaluationToCsvRows(evalData: EvaluationWithScores): string[][] { const rows: string[][] = []; rows.push([ "candidateName", "candidateRole", "evaluatorName", "evaluationDate", "template", "status", "dimension", "score", "justification", "examplesObserved", "confidence", ]); for (const ds of evalData.dimensionScores) { rows.push([ evalData.candidateName, evalData.candidateRole, evalData.evaluatorName, evalData.evaluationDate.toISOString().split("T")[0], evalData.template?.name ?? "", evalData.status, (ds.dimension as { name?: string; title?: string }).title ?? (ds.dimension as { name?: string }).name ?? "", String(ds.score ?? ""), ds.justification ?? "", ds.examplesObserved ?? "", ds.confidence ?? "", ]); } return rows; }