The grade label or percentage to convert (e.g. "ACS Grade", "≥99.8%")
Roughly [0, 100] — the parsed percentage, plus a comparator offset of at most ±0.02;
0 when no grade or number can be read
sortablePurityGrade("95%") // Returns 95
sortablePurityGrade("ACS Grade") // Returns 99.8
sortablePurityGrade("USP Grade") // Returns 99.5
sortablePurityGrade(">75%") // Returns 75.02 (sorts just above a bare 75%)
sortablePurityGrade("<75%") // Returns 74.98 (sorts just below a bare 75%)
sortablePurityGrade("99.9+%") // Returns 99.9
sortablePurityGrade("99.9-100%") // Returns 99.9 (lower bound of the range)
sortablePurityGrade("99,5%") // Returns 99.5 (European comma decimal)
sortablePurityGrade("120%") // Returns 100 (clamped)
sortablePurityGrade("Ungraded") // Returns 0
export function sortablePurityGrade(grade: string): number {
if (grade.endsWith(' Grade')) return purityGradeToPercentage(grade) ?? 0;
// First number only, with any leading comparator. Stripping every non-digit instead would
// splice a range's two bounds into one bogus number ("99.9-100%" -> "99.9100").
const match = grade.match(/(?<modifier>[<>≤≥≈]\s?)?(?<percent>\d+(?:[.,]\d+)?)/);
if (!match?.groups) return 0;
const num = Number(match.groups.percent.replace(',', '.'));
if (Number.isNaN(num) || num < 0) return 0;
// modifier keeps the optional trailing space the regex allows ("> 75%"); take just the operator.
const offset = PURITY_COMPARATOR_OFFSET[match.groups.modifier?.[0] ?? ''] ?? 0;
return Math.min(num, 100) + offset;
}
Converts a purity value — either a grade label or a percentage — to a number the Purity column can sort on. Grades route through purityGradeToPercentage; everything else is read as the FIRST number in the string, so a range sorts on its lower bound and a trailing qualifier ("+", "or better") is ignored. A leading comparator (
<>≤≥≈) applies a smallPURITY_COMPARATOR_OFFSETso e.g.>75%sorts just above a bare75%. Anything unreadable sorts as0.