const TRACK_PAD = 4 const roundPosition = (value) => Math.round(value * 10) / 10 const getBadgePositions = (badges) => { const defs = Array.isArray(badges) ? badges : [] if (defs.length === 0) return [] if (defs.length === 1) return [TRACK_PAD] const segmentWidth = (100 - TRACK_PAD * 2) / (defs.length - 1) return defs.map((_, index) => roundPosition(TRACK_PAD + index * segmentWidth)) } const getBadgeProgress = (badges, totalDays) => { const defs = Array.isArray(badges) ? badges : [] if (defs.length === 0) return 0 const days = Math.max(0, Number(totalDays) || 0) if (days < defs[0].days) return 0 if (defs.length === 1 || days >= defs[defs.length - 1].days) return 100 const positions = getBadgePositions(defs) let index = 0 while (index < defs.length - 1 && days >= defs[index + 1].days) index++ const ratio = (days - defs[index].days) / (defs[index + 1].days - defs[index].days) return roundPosition(positions[index] + ratio * (positions[index + 1] - positions[index])) } const getBadgeSegments = (badges, totalDays) => { const defs = Array.isArray(badges) ? badges : [] const positions = getBadgePositions(defs) const days = Math.max(0, Number(totalDays) || 0) return defs.slice(0, -1).map((badge, index) => { const nextBadge = defs[index + 1] const segmentDays = nextBadge.days - badge.days const progress = days <= badge.days ? 0 : days >= nextBadge.days ? 100 : roundPosition((days - badge.days) / segmentDays * 100) return { left: positions[index], width: roundPosition(positions[index + 1] - positions[index]), progress } }) } const getBadgeDisplayLabel = (badge, unlocked) => { if (!badge) return '' return unlocked && badge.name ? badge.name : `${badge.days}天` } const getBadgeCelebration = (previous, unlockedDays) => { const unlocked = Array.isArray(unlockedDays) ? unlockedDays : [] if (!Array.isArray(previous)) return { newly: [], seen: Array.from(new Set(unlocked)) } const previousSet = new Set(previous) const newly = unlocked.filter(days => !previousSet.has(days)) return { newly, seen: Array.from(new Set(previous.concat(unlocked))) } } module.exports = { getBadgeProgress, getBadgePositions, getBadgeSegments, getBadgeDisplayLabel, getBadgeCelebration }