Files
grademaxxing/app/utils/gradeSystems.ts
2026-01-17 13:37:57 +01:00

180 lines
5.0 KiB
TypeScript

/**
* 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<GradeSystem, GradeSystemConfig> = {
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;
}