import type * as getProfile from '#lib/lexicons/dev/knotless/getProfile.ts'; import { capitalized, number } from '#lib/format.ts'; /** The metal of each tier, from the first to the fourth. */ const METALS = ['steel', 'bronze', 'silver', 'gold'] as const; /** How a badge is earned: by tiers, once, or once and only for a time. */ type Earned = 'tiers' | 'once' | 'limited'; /** Each badge knotless knows: its name, what its count is of, said of `n`, and how it is earned. */ const KNOWN: Record string; earned?: Earned }> = { upstream: { name: 'Upstream', counted: (n) => `Got ${pulls(n)} merged into other accounts' repositories.` }, 'second-pair': { name: 'Second pair of eyes', counted: (n) => `Weighed in on ${pulls(n)} from others before ${n === 1 ? 'it' : 'they'} merged.` }, peacemaker: { name: 'Peacemaker', counted: (n) => `Landed ${pulls(n)} after fixing a conflict the merge queue flagged.` }, 'forked-and-fixed': { name: 'Forked and fixed', counted: (n) => `Merged ${pulls(n)} sent from forks of their repositories.`, earned: 'once' }, 'good-company': { name: 'In good company', counted: (n) => `Landed ${pulls(n)} in a merge queue batch of five or more.` }, 'smooth-landing': { name: 'Smooth landing', counted: (n) => `Landed ${pulls(n)} through the merge queue on the first try.` }, bisected: { name: 'Bisected', counted: (n) => `Had ${pulls(n)} caught breaking a merge queue batch. It happens to everyone.`, earned: 'once' }, shipped: { name: 'Shipped', counted: (n) => `Published ${number(n)} ${n === 1 ? 'release' : 'releases'}.` }, stargazer: { name: 'Stargazer', counted: (n) => `${number(n)} ${n === 1 ? 'star' : 'stars'} on their most-starred repository.` }, 'carry-your-own': { name: 'Carry your own', counted: () => 'Hosts their account on a small PDS, five accounts or fewer.', earned: 'once' }, 'moved-house': { name: 'Moved house', counted: () => 'Moved their account to a new PDS.', earned: 'once' }, 'first-light': { name: 'First light', counted: () => 'Had a repository here before knotless 1.0.', earned: 'limited' } }; /** `n` pulls, in words. */ const pulls = (n: number) => `${number(n)} ${n === 1 ? 'pull' : 'pulls'}`; /** How a badge of `kind` is earned. */ const earned = (kind: string): Earned => KNOWN[kind]?.earned ?? 'tiers'; /** The metal a pin of `kind` at `tier` is ringed in: cobalt for a limited badge, steel for one earned once. */ export const metal = (kind: string, tier: number) => { if (earned(kind) === 'limited') return 'cobalt'; if (earned(kind) === 'once') return 'steel'; return METALS[Math.min(Math.max(tier, 1), METALS.length) - 1]; }; /** Whether knotless knows how to show a badge of its kind: one newer than these pages is left out. */ export const known = (b: getProfile.BadgeView) => b.kind in KNOWN; /** A badge's name. */ export const name = (b: getProfile.BadgeView) => KNOWN[b.kind].name; /** A badge's name and tier, as one says it: "Shipped, bronze". One without tiers is its name alone. */ export const named = (b: getProfile.BadgeView) => earned(b.kind) === 'tiers' ? `${name(b)}, ${metal(b.kind, b.tier)}` : name(b); /** Its tier, what it counted, and how far its next tier is, if it has one. */ export const said = (b: getProfile.BadgeView) => { const counted = KNOWN[b.kind].counted(b.count); if (earned(b.kind) === 'once') return { tier: 'One-time badge.', counted, next: undefined }; if (earned(b.kind) === 'limited') return { tier: 'Limited. Earned only before 1.0.', counted, next: undefined }; const at = metal(b.kind, b.tier); const tier = `${capitalized(at)}, tier ${METALS.indexOf(at as (typeof METALS)[number]) + 1} of ${METALS.length}.`; const next = b.next === undefined ? undefined : `${number(b.next - b.count)} more for ${metal(b.kind, b.tier + 1)}.`; return { tier, counted, next }; };