Spaces:
Running
Running
| import { | |
| ProviderInfo, | |
| CalendarData, | |
| ModelData, | |
| OrgCandidate, | |
| CandidateSummary, | |
| } from "../types/heatmap"; | |
| import { generateCalendarData } from "./calendar"; | |
| import { fetchAllProvidersData, fetchAllAuthorsData } from "./authors"; | |
| import { assignColor } from "../constants/colors"; | |
| import { LEADERBOARD_SIZE } from "../constants/organizations"; | |
| export interface RankingBadge { | |
| className: string; | |
| icon: string | null; | |
| } | |
| export const getRankingBadge = (rank: number): RankingBadge => { | |
| if (rank === 1) { | |
| return { | |
| className: | |
| "absolute -top-4 -left-4 w-12 h-12 bg-gradient-to-br from-yellow-400 via-yellow-500 to-yellow-600 text-white rounded-full flex items-center justify-center text-lg font-bold shadow-2xl border-4 border-yellow-300", | |
| icon: "👑", | |
| }; | |
| } else if (rank === 2) { | |
| return { | |
| className: | |
| "absolute -top-4 -left-4 w-10 h-10 bg-gradient-to-br from-gray-300 via-gray-400 to-gray-500 text-white rounded-full flex items-center justify-center text-base font-bold shadow-xl border-3 border-gray-200", | |
| icon: "🥈", | |
| }; | |
| } else if (rank === 3) { | |
| return { | |
| className: | |
| "absolute -top-4 -left-4 w-10 h-10 bg-gradient-to-br from-amber-600 via-amber-700 to-amber-800 text-white rounded-full flex items-center justify-center text-base font-bold shadow-xl border-3 border-amber-400", | |
| icon: "🥉", | |
| }; | |
| } else { | |
| return { | |
| className: | |
| "absolute -top-3 -left-3 w-8 h-8 bg-gradient-to-br from-blue-500 to-blue-600 text-white rounded-full flex items-center justify-center text-sm font-bold shadow-lg", | |
| icon: null, | |
| }; | |
| } | |
| }; | |
| export const extractUniqueAuthors = (providers: ProviderInfo[]): string[] => { | |
| const allAuthors = providers.flatMap(({ authors }) => authors); | |
| return Array.from(new Set(allAuthors)); | |
| }; | |
| export const sortProvidersByActivity = ( | |
| providers: ProviderInfo[], | |
| calendarData: CalendarData | |
| ): ProviderInfo[] => { | |
| return [...providers].sort((a, b) => { | |
| const aCount = (calendarData[a.authors[0]] || []).reduce( | |
| (sum, day) => sum + day.count, | |
| 0 | |
| ); | |
| const bCount = (calendarData[b.authors[0]] || []).reduce( | |
| (sum, day) => sum + day.count, | |
| 0 | |
| ); | |
| return bCount - aCount; | |
| }); | |
| }; | |
| const candidatesToProviders = (candidates: OrgCandidate[]): ProviderInfo[] => | |
| candidates.map((c) => ({ | |
| color: c.color || "", | |
| authors: c.authors, | |
| })); | |
| export const getProviders = async (candidates: OrgCandidate[]) => { | |
| const allProviders = candidatesToProviders(candidates); | |
| const uniqueAuthors = extractUniqueAuthors(allProviders); | |
| const [authorModelsData, providersWithMetadata] = await Promise.all([ | |
| fetchAllAuthorsData(uniqueAuthors), | |
| fetchAllProvidersData(allProviders), | |
| ]); | |
| const calendarData = generateCalendarData( | |
| authorModelsData, | |
| providersWithMetadata | |
| ); | |
| const sorted = sortProvidersByActivity(providersWithMetadata, calendarData); | |
| const topN = sorted.slice(0, LEADERBOARD_SIZE); | |
| const coloredProviders = topN.map((provider, index) => ({ | |
| ...provider, | |
| color: provider.color || assignColor(index), | |
| })); | |
| const topKeys = new Set(coloredProviders.map((p) => p.authors[0])); | |
| const filteredCalendar: CalendarData = {}; | |
| for (const key of Object.keys(calendarData)) { | |
| if (topKeys.has(key)) { | |
| filteredCalendar[key] = calendarData[key]; | |
| } | |
| } | |
| const lastProvider = coloredProviders[coloredProviders.length - 1]; | |
| const lastKey = lastProvider?.authors[0]; | |
| const minActivityCount = lastKey | |
| ? (filteredCalendar[lastKey] || []).reduce((s, d) => s + d.count, 0) | |
| : 0; | |
| const allCandidates: CandidateSummary[] = sorted.map((p) => ({ | |
| author: p.authors[0], | |
| fullName: p.fullName || p.authors[0], | |
| avatarUrl: p.avatarUrl || null, | |
| })); | |
| return { | |
| calendarData: filteredCalendar, | |
| providers: coloredProviders, | |
| allCandidates, | |
| minActivityCount, | |
| }; | |
| }; | |