72 lines
2.3 KiB
JavaScript
72 lines
2.3 KiB
JavaScript
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
|
|
}
|