/** * German Grading System Utilities * German grades: 1 (best) to 6 (worst) */ export type GradeSystem = "percentage" | "german" | "us-letter"; export interface GradeSystemConfig { type: GradeSystem; displayName: string; description: string; } export const GRADE_SYSTEMS: Record = { percentage: { type: "percentage", displayName: "Percentage (0-100%)", description: "Standard percentage-based grading", }, german: { type: "german", displayName: "German (1-6)", description: "1 = sehr gut (very good), 6 = ungenügend (insufficient)", }, "us-letter": { type: "us-letter", displayName: "US Letter (A-F)", description: "A = 90-100%, F = below 60%", }, }; /** * Convert percentage (0-100) to German grade (1-6) * German grading scale: * 1 (sehr gut / very good): 92-100% * 2 (gut / good): 81-91% * 3 (befriedigend / satisfactory): 67-80% * 4 (ausreichend / sufficient): 50-66% * 5 (mangelhaft / deficient): 30-49% * 6 (ungenügend / insufficient): 0-29% */ export function percentageToGermanGrade(percentage: number): number { if (percentage >= 92) return 1.0; if (percentage >= 81) return 2.0; if (percentage >= 67) return 3.0; if (percentage >= 50) return 4.0; if (percentage >= 30) return 5.0; return 6.0; } /** * Convert percentage to German grade with decimal precision * Uses linear interpolation within each grade range */ export function percentageToGermanGradeDetailed(percentage: number): number { if (percentage >= 92) { // 1.0 - 1.5 range (92-100%) const position = (100 - percentage) / (100 - 92); return 1.0 + position * 0.5; } else if (percentage >= 81) { // 1.5 - 2.5 range (81-91%) const position = (92 - percentage) / (92 - 81); return 1.5 + position * 1.0; } else if (percentage >= 67) { // 2.5 - 3.5 range (67-80%) const position = (81 - percentage) / (81 - 67); return 2.5 + position * 1.0; } else if (percentage >= 50) { // 3.5 - 4.5 range (50-66%) const position = (67 - percentage) / (67 - 50); return 3.5 + position * 1.0; } else if (percentage >= 30) { // 4.5 - 5.5 range (30-49%) const position = (50 - percentage) / (50 - 30); return 4.5 + position * 1.0; } else { // 5.5 - 6.0 range (0-29%) const position = (30 - percentage) / 30; return 5.5 + position * 0.5; } } /** * Convert German grade (1-6) to approximate percentage */ export function germanGradeToPercentage(grade: number): number { if (grade <= 1.5) return 92 + (1.5 - grade) * 16; // 92-100% if (grade <= 2.5) return 81 + (2.5 - grade) * 11; // 81-91% if (grade <= 3.5) return 67 + (3.5 - grade) * 14; // 67-80% if (grade <= 4.5) return 50 + (4.5 - grade) * 17; // 50-66% if (grade <= 5.5) return 30 + (5.5 - grade) * 20; // 30-49% return Math.max(0, 30 - (grade - 5.5) * 60); // 0-29% } /** * Get German grade description */ export function getGermanGradeDescription(grade: number): string { if (grade <= 1.5) return "sehr gut (very good)"; if (grade <= 2.5) return "gut (good)"; if (grade <= 3.5) return "befriedigend (satisfactory)"; if (grade <= 4.5) return "ausreichend (sufficient)"; if (grade <= 5.5) return "mangelhaft (deficient)"; return "ungenügend (insufficient)"; } /** * Get color for German grade */ export function getGermanGradeColor(grade: number): string { if (grade <= 2.0) return "text-green-600"; if (grade <= 3.0) return "text-blue-600"; if (grade <= 4.0) return "text-yellow-600"; if (grade <= 5.0) return "text-orange-600"; return "text-red-600"; } /** * Format grade based on system */ export function formatGradeBySystem( percentage: number, system: GradeSystem, decimals: number = 2 ): string { switch (system) { case "german": { const germanGrade = percentageToGermanGradeDetailed(percentage); return germanGrade.toFixed(1); } case "us-letter": { if (percentage >= 90) return "A"; if (percentage >= 80) return "B"; if (percentage >= 70) return "C"; if (percentage >= 60) return "D"; return "F"; } case "percentage": default: return `${percentage.toFixed(decimals)}%`; } } /** * Get color for grade based on system */ export function getGradeColorBySystem( percentage: number, system: GradeSystem ): string { switch (system) { case "german": { const germanGrade = percentageToGermanGradeDetailed(percentage); return getGermanGradeColor(germanGrade); } case "percentage": case "us-letter": default: if (percentage >= 90) return "text-green-600"; if (percentage >= 80) return "text-blue-600"; if (percentage >= 70) return "text-yellow-600"; if (percentage >= 60) return "text-orange-600"; return "text-red-600"; } } /** * Get description for grade */ export function getGradeDescription( percentage: number, system: GradeSystem ): string | null { if (system === "german") { const germanGrade = percentageToGermanGradeDetailed(percentage); return getGermanGradeDescription(germanGrade); } return null; }