Généralise Podium et computeRanks au-delà des points
computeRanksBy(items, comparator) remplace la logique de classement "ex-aequo partagent le rang" en la rendant générique ; computeRanks devient un simple appel avec le comparateur points desc, sans rien changer pour l'appelant existant. Podium accepte maintenant un prop renderValue (+ valueLabel optionnel) à la place du "points/gloires" en dur, pour pouvoir afficher un classement par temps (Course du Char) avec le même composant que le classement par points.
This commit is contained in:
+16
-10
@@ -1,21 +1,27 @@
|
||||
export type RankedProfile<T extends { points: number }> = T & { rank: number };
|
||||
export type Ranked<T> = T & { rank: number };
|
||||
export type RankedProfile<T extends { points: number }> = Ranked<T>;
|
||||
|
||||
// Classement "compétition" : les ex-aequo partagent le même rang, et le
|
||||
// rang suivant saute en conséquence (1, 2, 2, 4 — pas 1, 2, 2, 3).
|
||||
export function computeRanks<T extends { points: number }>(profiles: T[]): RankedProfile<T>[] {
|
||||
const sorted = [...profiles].sort((a, b) => b.points - a.points);
|
||||
let lastPoints: number | null = null;
|
||||
// Classement "compétition" générique : les ex-aequo (selon le comparateur)
|
||||
// partagent le même rang, et le rang suivant saute en conséquence
|
||||
// (1, 2, 2, 4 — pas 1, 2, 2, 3).
|
||||
export function computeRanksBy<T>(items: T[], compare: (a: T, b: T) => number): Ranked<T>[] {
|
||||
const sorted = [...items].sort(compare);
|
||||
let lastItem: T | null = null;
|
||||
let lastRank = 0;
|
||||
|
||||
return sorted.map((profile, index) => {
|
||||
if (lastPoints === null || profile.points !== lastPoints) {
|
||||
return sorted.map((item, index) => {
|
||||
if (lastItem === null || compare(item, lastItem) !== 0) {
|
||||
lastRank = index + 1;
|
||||
lastPoints = profile.points;
|
||||
lastItem = item;
|
||||
}
|
||||
return { ...profile, rank: lastRank };
|
||||
return { ...item, rank: lastRank };
|
||||
});
|
||||
}
|
||||
|
||||
export function computeRanks<T extends { points: number }>(profiles: T[]): RankedProfile<T>[] {
|
||||
return computeRanksBy(profiles, (a, b) => b.points - a.points);
|
||||
}
|
||||
|
||||
const ROMAN_DIGITS: [number, string][] = [
|
||||
[10, "X"],
|
||||
[9, "IX"],
|
||||
|
||||
Reference in New Issue
Block a user