feat: add rate normalization helpers
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
type ComparableRate = {
|
||||
isLessThan: boolean;
|
||||
numeric: number;
|
||||
};
|
||||
|
||||
export function normalizeRateDisplay(value: string): string {
|
||||
const trimmedValue = value.trim();
|
||||
const rangeMatch = trimmedValue.match(
|
||||
/^([0-9]+(?:\.[0-9]+)?)\s*%?\s*-\s*([0-9]+(?:\.[0-9]+)?)\s*%$/
|
||||
);
|
||||
|
||||
if (rangeMatch) {
|
||||
const [, lowerBound, upperBound] = rangeMatch;
|
||||
return `${lowerBound}% - ${upperBound}%`;
|
||||
}
|
||||
|
||||
return trimmedValue.replace(/\s+/g, "");
|
||||
}
|
||||
|
||||
export function parseRateLowerBound(value: string | null | undefined): number | null {
|
||||
const comparableRate = toComparableRate(value);
|
||||
return comparableRate?.numeric ?? null;
|
||||
}
|
||||
|
||||
export function compareRateValues(
|
||||
leftValue: string | null | undefined,
|
||||
rightValue: string | null | undefined
|
||||
): number {
|
||||
const leftComparable = toComparableRate(leftValue);
|
||||
const rightComparable = toComparableRate(rightValue);
|
||||
|
||||
if (!leftComparable && !rightComparable) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!leftComparable) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!rightComparable) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (leftComparable.numeric !== rightComparable.numeric) {
|
||||
return leftComparable.numeric - rightComparable.numeric;
|
||||
}
|
||||
|
||||
if (leftComparable.isLessThan === rightComparable.isLessThan) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return leftComparable.isLessThan ? -1 : 1;
|
||||
}
|
||||
|
||||
function toComparableRate(value: string | null | undefined): ComparableRate | null {
|
||||
if (!value) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const normalizedValue = normalizeRateDisplay(value);
|
||||
const lessThanMatch = normalizedValue.match(/^<\s*([0-9]+(?:\.[0-9]+)?)%$/);
|
||||
if (lessThanMatch) {
|
||||
return {
|
||||
isLessThan: true,
|
||||
numeric: Number(lessThanMatch[1])
|
||||
};
|
||||
}
|
||||
|
||||
const rangeMatch = normalizedValue.match(
|
||||
/^([0-9]+(?:\.[0-9]+)?)%\s*-\s*([0-9]+(?:\.[0-9]+)?)%$/
|
||||
);
|
||||
if (rangeMatch) {
|
||||
return {
|
||||
isLessThan: false,
|
||||
numeric: Number(rangeMatch[1])
|
||||
};
|
||||
}
|
||||
|
||||
const exactMatch = normalizedValue.match(/^([0-9]+(?:\.[0-9]+)?)%$/);
|
||||
if (exactMatch) {
|
||||
return {
|
||||
isLessThan: false,
|
||||
numeric: Number(exactMatch[1])
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
Reference in New Issue
Block a user