aboutsummaryrefslogtreecommitdiff
path: root/src/cleaners/achievements.ts
blob: dcb1becd84729582f6b01ef0176732e36badcd60 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import typedHypixelApi from 'typed-hypixel-api'
import { fetchAchievements } from '../hypixelCached.js'

interface TieredAchievement {
	id: string
	name: string
	tier: number
	amount: number
	/**
	 * The amount that has to be gotten to get to the next tier. If this is
	 * null, that means the player is at the max tier.
	 */
	next: number | null
	description: string
}

interface ChallengeAchievement {
	id: string
	name: string
	unlocked: boolean
	description: string
}

export interface Achievements {
	tiered: TieredAchievement[]
	challenge: ChallengeAchievement[]
}

export async function cleanPlayerAchievements(data: typedHypixelApi.PlayerDataResponse['player']): Promise<Achievements> {
	const gameAchievements: typedHypixelApi.AchievementsResponse['achievements'] = await fetchAchievements()

	for (const [gameId, achievementsData] of Object.entries(gameAchievements)) {
		if (gameId !== 'skyblock') continue


		let tieredAchievements: TieredAchievement[] = []
		for (const [achievementId, achievementData] of Object.entries(achievementsData.tiered)) {
			const amount = data.achievements[`skyblock_${achievementId.toLowerCase()}`] ?? null

			let tier = 0
			for (const tierData of achievementData.tiers) {
				if (amount >= tierData.amount)
					tier = tierData.tier
				else
					break
			}
			const next = achievementData.tiers[tier]?.amount ?? null

			tieredAchievements.push({
				id: achievementId.toLowerCase(),
				name: achievementData.name,
				tier,
				next,
				amount,
				description: achievementData.description.replace(/%s/g, (achievementData.tiers[Math.max(0, tier - 1)].amount).toString())
			})
		}
		tieredAchievements.sort((a, b) => (b.amount ?? 0) - (a.amount ?? 0))

		let unlockedChallengeAchievements: ChallengeAchievement[] = []
		let lockedChallengeAchievements: ChallengeAchievement[] = []

		for (const [achievementId, achievementData] of Object.entries(achievementsData.one_time)) {
			const achievement: ChallengeAchievement = {
				id: achievementId.toLowerCase(),
				name: achievementData.name,
				unlocked: data.achievementsOneTime.includes(`skyblock_${achievementId.toLowerCase()}`),
				description: achievementData.description
			}
			if (achievement.unlocked)
				unlockedChallengeAchievements.push(achievement)
			else
				lockedChallengeAchievements.push(achievement)
		}

		return {
			tiered: tieredAchievements, challenge: [
				...unlockedChallengeAchievements,
				...lockedChallengeAchievements
			]
		}
	}

	// this shouldn't be possible
	console.debug('skyblock not found in achievements?')
	return { tiered: [], challenge: [] }
}