Open-Greek-Financial-LLM-Leaderboard
/
frontend
/src
/pages
/LeaderboardPage
/components
/Leaderboard
/hooks
/useDataUtils.js
import { useMemo } from "react"; | |
import { | |
looksLikeRegex, | |
parseSearchQuery, | |
getValueByPath, | |
} from "../utils/searchUtils"; | |
// Calculate min/max averages | |
export const useAverageRange = (data) => { | |
return useMemo(() => { | |
const averages = data.map((item) => item.model.average_score); | |
return { | |
minAverage: Math.min(...averages), | |
maxAverage: Math.max(...averages), | |
}; | |
}, [data]); | |
}; | |
// Generate colors for scores | |
export const useColorGenerator = (minAverage, maxAverage) => { | |
return useMemo(() => { | |
const colorCache = new Map(); | |
return (value) => { | |
const cached = colorCache.get(value); | |
if (cached) return cached; | |
const normalizedValue = (value - minAverage) / (maxAverage - minAverage); | |
const red = Math.round(255 * (1 - normalizedValue) * 1); | |
const green = Math.round(255 * normalizedValue) * 1; | |
// const color = `rgba(${red}, ${green}, 0, 1)`; | |
const color = `rgba(${red}, 0, ${green}, 1)`; | |
colorCache.set(value, color); | |
return color; | |
}; | |
}, [minAverage, maxAverage]); | |
}; | |
// Process data with boolean standardization | |
export const useProcessedData = (data, averageMode, visibleColumns) => { | |
return useMemo(() => { | |
let processed = data.map((item) => { | |
const evaluationScores = Object.entries(item.evaluations) | |
.filter(([key]) => { | |
if (averageMode === "all") return true; | |
return visibleColumns.includes(`evaluations.${key}.normalized_score`); | |
}) | |
.map(([, value]) => value.normalized_score); | |
const average = | |
evaluationScores.length > 0 | |
? evaluationScores.reduce((a, b) => a + b, 0) / | |
evaluationScores.length | |
: averageMode === "visible" | |
? null | |
: 0; | |
// Boolean standardization | |
const standardizedFeatures = { | |
...item.features, | |
is_moe: Boolean(item.features.is_moe), | |
is_flagged: Boolean(item.features.is_flagged), | |
is_highlighted_by_maintainer: Boolean( | |
item.features.is_highlighted_by_maintainer | |
), | |
is_merged: Boolean(item.features.is_merged), | |
is_not_available_on_hub: Boolean(item.features.is_not_available_on_hub), | |
}; | |
return { | |
...item, | |
features: standardizedFeatures, | |
model: { | |
...item.model, | |
has_chat_template: Boolean(item.model.has_chat_template), | |
average_score: average, | |
}, | |
}; | |
}); | |
processed.sort((a, b) => { | |
if (a.model.average_score === null && b.model.average_score === null) | |
return 0; | |
if (a.model.average_score === null) return 1; | |
if (b.model.average_score === null) return -1; | |
return b.model.average_score - a.model.average_score; | |
}); | |
return processed.map((item, index) => ({ | |
...item, | |
static_rank: index + 1, | |
})); | |
}, [data, averageMode, visibleColumns]); | |
}; | |
// Common filtering logic | |
export const useFilteredData = ( | |
processedData, | |
selectedPrecisions, | |
selectedTypes, | |
paramsRange, | |
searchValue, | |
selectedBooleanFilters, | |
rankingMode, | |
pinnedModels = [], | |
isOfficialProviderActive = false | |
) => { | |
return useMemo(() => { | |
const pinnedData = processedData.filter((row) => { | |
return pinnedModels.includes(row.id); | |
}); | |
const unpinnedData = processedData.filter((row) => { | |
return !pinnedModels.includes(row.id); | |
}); | |
let filteredUnpinned = unpinnedData; | |
// Filter by official providers | |
if (isOfficialProviderActive) { | |
filteredUnpinned = filteredUnpinned.filter( | |
(row) => | |
row.features?.is_highlighted_by_maintainer || | |
row.metadata?.is_highlighted_by_maintainer | |
); | |
} | |
// Filter by precision | |
if (selectedPrecisions.length > 0) { | |
filteredUnpinned = filteredUnpinned.filter((row) => | |
selectedPrecisions.includes(row.model.precision) | |
); | |
} | |
// Filter by type | |
if (selectedTypes.length > 0) { | |
filteredUnpinned = filteredUnpinned.filter((row) => { | |
const modelType = row.model.type?.toLowerCase().trim(); | |
return selectedTypes.some((type) => modelType?.includes(type)); | |
}); | |
} | |
// Filter by parameters | |
filteredUnpinned = filteredUnpinned.filter((row) => { | |
// Skip parameter filtering if no filter is active | |
if (paramsRange[0] === -1 && paramsRange[1] === 140) return true; | |
const params = | |
row.metadata?.params_billions || row.features?.params_billions; | |
if (params === undefined || params === null) return false; | |
return params >= paramsRange[0] && params < paramsRange[1]; | |
}); | |
// Filter by search | |
if (searchValue) { | |
const searchQueries = searchValue | |
.split(";") | |
.map((q) => q.trim()) | |
.filter((q) => q); | |
if (searchQueries.length > 0) { | |
filteredUnpinned = filteredUnpinned.filter((row) => { | |
return searchQueries.some((query) => { | |
const { specialSearches, textSearch } = parseSearchQuery(query); | |
const specialSearchMatch = specialSearches.every( | |
({ field, value }) => { | |
const fieldValue = getValueByPath(row, field) | |
?.toString() | |
.toLowerCase(); | |
return fieldValue?.includes(value.toLowerCase()); | |
} | |
); | |
if (!specialSearchMatch) return false; | |
if (!textSearch) return true; | |
const modelName = row.model.name.toLowerCase(); | |
const searchLower = textSearch.toLowerCase(); | |
if (looksLikeRegex(textSearch)) { | |
try { | |
const regex = new RegExp(textSearch, "i"); | |
return regex.test(modelName); | |
} catch (e) { | |
return modelName.includes(searchLower); | |
} | |
} else { | |
return modelName.includes(searchLower); | |
} | |
}); | |
}); | |
} | |
} | |
// Filter by booleans | |
if (selectedBooleanFilters.length > 0) { | |
filteredUnpinned = filteredUnpinned.filter((row) => { | |
return selectedBooleanFilters.every((filter) => { | |
const filterValue = | |
typeof filter === "object" ? filter.value : filter; | |
// Maintainer's Highlight keeps positive logic | |
if (filterValue === "is_highlighted_by_maintainer") { | |
return row.features[filterValue]; | |
} | |
// For all other filters, invert the logic | |
if (filterValue === "is_not_available_on_hub") { | |
return row.features[filterValue]; | |
} | |
return !row.features[filterValue]; | |
}); | |
}); | |
} | |
// Create ordered array of pinned models respecting pinnedModels order | |
const orderedPinnedData = pinnedModels | |
.map((pinnedModelId) => | |
pinnedData.find((item) => item.id === pinnedModelId) | |
) | |
.filter(Boolean); | |
// Combine all filtered data | |
const allFilteredData = [...filteredUnpinned, ...orderedPinnedData]; | |
// Sort all data by average_score for dynamic_rank | |
const sortedByScore = [...allFilteredData].sort((a, b) => { | |
// Si les scores moyens sont différents, trier par score | |
if (a.model.average_score !== b.model.average_score) { | |
if (a.model.average_score === null && b.model.average_score === null) | |
return 0; | |
if (a.model.average_score === null) return 1; | |
if (b.model.average_score === null) return -1; | |
return b.model.average_score - a.model.average_score; | |
} | |
// Si les scores sont égaux, comparer le nom du modèle et la date de soumission | |
if (a.model.name === b.model.name) { | |
// Si même nom, trier par date de soumission (la plus récente d'abord) | |
const dateA = new Date(a.metadata?.submission_date || 0); | |
const dateB = new Date(b.metadata?.submission_date || 0); | |
return dateB - dateA; | |
} | |
// Si noms différents, trier par nom | |
return a.model.name.localeCompare(b.model.name); | |
}); | |
// Create Map to store dynamic_ranks | |
const dynamicRankMap = new Map(); | |
sortedByScore.forEach((item, index) => { | |
dynamicRankMap.set(item.id, index + 1); | |
}); | |
// Add ranks to final data | |
const finalData = [...orderedPinnedData, ...filteredUnpinned].map( | |
(item) => { | |
return { | |
...item, | |
dynamic_rank: dynamicRankMap.get(item.id), | |
rank: item.isPinned | |
? pinnedModels.indexOf(item.id) + 1 | |
: rankingMode === "static" | |
? item.static_rank | |
: dynamicRankMap.get(item.id), | |
isPinned: pinnedModels.includes(item.id), | |
}; | |
} | |
); | |
return finalData; | |
}, [ | |
processedData, | |
selectedPrecisions, | |
selectedTypes, | |
paramsRange, | |
searchValue, | |
selectedBooleanFilters, | |
rankingMode, | |
pinnedModels, | |
isOfficialProviderActive, | |
]); | |
}; | |
// Column visibility management | |
export const useColumnVisibility = (visibleColumns = []) => { | |
// Create secure visibility object | |
const columnVisibility = useMemo(() => { | |
// Check visible columns | |
const safeVisibleColumns = Array.isArray(visibleColumns) | |
? visibleColumns | |
: []; | |
const visibility = {}; | |
try { | |
safeVisibleColumns.forEach((columnKey) => { | |
if (typeof columnKey === "string") { | |
visibility[columnKey] = true; | |
} | |
}); | |
} catch (error) { | |
console.warn("Error in useColumnVisibility:", error); | |
} | |
return visibility; | |
}, [visibleColumns]); | |
return columnVisibility; | |
}; | |