Skip to content

Commit

Permalink
fix: badge service (#77)
Browse files Browse the repository at this point in the history
  • Loading branch information
aleortega authored Sep 24, 2024
1 parent 0fd7813 commit abcc6ee
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 88 deletions.
162 changes: 75 additions & 87 deletions api/src/adapters/badge-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,8 @@ import { Badge, BadgeId, BadgeTier, UserBadge } from '@badges/common'
export async function createBadgeService({
db,
badgeStorage,
logs,
config
}: Pick<AppComponents, 'db' | 'badgeStorage' | 'logs' | 'config'>): Promise<IBadgeService> {
const isDebugMode = (await config.getString('LOG_LEVEL'))?.toLocaleLowerCase() === 'debug'
logs
}: Pick<AppComponents, 'db' | 'badgeStorage' | 'logs'>): Promise<IBadgeService> {
const logger = logs.getLogger('badge-service')
const badges: Map<BadgeId, Badge> = badgeStorage.getBadges()

Expand Down Expand Up @@ -71,71 +69,77 @@ export async function createBadgeService({
userProgresses: UserBadge[],
shouldIncludeNotAchieved: boolean = false
): { achieved: any; notAchieved: any } {
const badgesProgresses = allBadges.reduce(
(accumulator, badge) => {
const isTierBadge = badge.tiers && badge.tiers.length > 0
const badgeProgress = userProgresses.find((userBadge) => userBadge.badge_id === badge.id) || {
badge_id: badge.id,
progress: { steps: 0 },
achieved_tiers: isTierBadge ? [] : undefined,
completed_at: undefined
}

const tierProgress = isTierBadge ? getCurrentTierProgress(badge, badgeProgress) : undefined

if (badgeProgress.completed_at || tierProgress?.currentTier) {
const calculatedNextTarget = isTierBadge
? tierProgress?.nextTier?.criteria.steps || badge.tiers![badge.tiers!.length - 1].criteria.steps
: badge.criteria.steps

accumulator.achieved.push({
id: badge.id,
name: badge.name,
description: badge.description,
category: badge.category,
isTier: !!isTierBadge,
completedAt: badgeProgress.completed_at,
assets: isTierBadge ? tierProgress?.currentTier?.assets : badge.assets,
progress: {
achievedTiers: badgeProgress.achieved_tiers?.map((achievedTier) => ({
tierId: achievedTier.tier_id,
completedAt: achievedTier.completed_at
})),
stepsDone: badgeProgress.progress.steps,
nextStepsTarget: badgeProgress.completed_at ? null : calculatedNextTarget,
totalStepsTarget: isTierBadge
? badge.tiers![badge.tiers!.length - 1].criteria.steps
: badge.criteria.steps,
lastCompletedTierAt: isTierBadge ? badgeProgress.achieved_tiers?.pop()?.completed_at : null,
lastCompletedTierName: isTierBadge ? tierProgress?.currentTier?.tierName : null,
lastCompletedTierImage: isTierBadge ? tierProgress?.currentTier?.assets?.['2d'].normal : null
}
})
} else if (shouldIncludeNotAchieved) {
accumulator.notAchieved.push({
id: badge.id,
name: badge.name,
description: badge.description,
category: badge.category,
isTier: !!isTierBadge,
completedAt: null,
assets: isTierBadge ? badge.tiers![0].assets : badge.assets,
progress: {
stepsDone: badgeProgress.progress.steps,
nextStepsTarget: isTierBadge ? badge.tiers![0].criteria.steps : badge.criteria.steps,
totalStepsTarget: isTierBadge
? badge.tiers![badge.tiers!.length - 1].criteria.steps
: badge.criteria.steps
}
})
}

return accumulator
},
{ achieved: [] as any, notAchieved: [] as any }
)

return badgesProgresses
try {
const badgesProgresses = allBadges.reduce(
(accumulator, badge) => {
const isTierBadge = badge.tiers && badge.tiers.length > 0
const badgeProgress = userProgresses.find((userBadge) => userBadge.badge_id === badge.id) || {
badge_id: badge.id,
progress: { steps: 0 },
achieved_tiers: isTierBadge ? [] : undefined,
completed_at: undefined
}

const tierProgress = isTierBadge ? getCurrentTierProgress(badge, badgeProgress) : undefined

if (badgeProgress.completed_at || tierProgress?.currentTier) {
const calculatedNextTarget = isTierBadge
? tierProgress?.nextTier?.criteria.steps || badge.tiers![badge.tiers!.length - 1].criteria.steps
: badge.criteria.steps

accumulator.achieved.push({
id: badge.id,
name: badge.name,
description: badge.description,
category: badge.category,
isTier: !!isTierBadge,
completedAt: badgeProgress.completed_at,
assets: isTierBadge ? tierProgress?.currentTier?.assets : badge.assets,
progress: {
achievedTiers: badgeProgress.achieved_tiers?.map((achievedTier) => ({
tierId: achievedTier.tier_id,
completedAt: achievedTier.completed_at
})),
stepsDone: badgeProgress.progress.steps,
nextStepsTarget: badgeProgress.completed_at ? null : calculatedNextTarget,
totalStepsTarget: isTierBadge
? badge.tiers![badge.tiers!.length - 1].criteria.steps
: badge.criteria.steps,
lastCompletedTierAt: isTierBadge ? badgeProgress.achieved_tiers?.pop()?.completed_at : null,
lastCompletedTierName: isTierBadge ? tierProgress?.currentTier?.tierName : null,
lastCompletedTierImage: isTierBadge ? tierProgress?.currentTier?.assets?.['2d'].normal : null
}
})
} else if (shouldIncludeNotAchieved) {
accumulator.notAchieved.push({
id: badge.id,
name: badge.name,
description: badge.description,
category: badge.category,
isTier: !!isTierBadge,
completedAt: null,
assets: isTierBadge ? badge.tiers![0].assets : badge.assets,
progress: {
stepsDone: badgeProgress.progress.steps,
nextStepsTarget: isTierBadge ? badge.tiers![0].criteria.steps : badge.criteria.steps,
totalStepsTarget: isTierBadge
? badge.tiers![badge.tiers!.length - 1].criteria.steps
: badge.criteria.steps
}
})
}

return accumulator
},
{ achieved: [] as any, notAchieved: [] as any }
)

return badgesProgresses
} catch (error: any) {
logger.error('Error calculating user progress:', error.message)
logger.debug('Stack trace:', error.stack)
throw error
}
}

function getCurrentTierProgress(
Expand Down Expand Up @@ -165,30 +169,14 @@ export async function createBadgeService({
await Promise.all(userBadges.map((userBadge) => db.saveUserProgress(userBadge)))
}

// Debug wrapper function
function debugWrapper<T extends (...args: any[]) => any>(fn: T): T {
return (async (...args: Parameters<T>) => {
try {
return await fn(...args)
} catch (error: any) {
if (isDebugMode) {
logger.debug('Error message:', error.message)
logger.debug('Stack trace:', error.stack)
}

throw error
}
}) as T
}

return {
getBadge,
getBadges,
getAllBadges,
getUserStates,
getUserState,
getLatestAchievedBadges: isDebugMode ? debugWrapper(getLatestAchievedBadges) : getLatestAchievedBadges,
calculateUserProgress: isDebugMode ? debugWrapper(calculateUserProgress) : calculateUserProgress,
getLatestAchievedBadges,
calculateUserProgress,
resetUserProgressFor,
saveOrUpdateUserProgresses
}
Expand Down
2 changes: 1 addition & 1 deletion api/src/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export async function initComponents(): Promise<AppComponents> {
const db = createDbComponent({ pg })

const badgeStorage = await createBadgeStorage({ config })
const badgeService = await createBadgeService({ db, badgeStorage, logs, config })
const badgeService = await createBadgeService({ db, badgeStorage, logs })
const backfillMerger = createBackfillMergerComponent({ logs, badgeService })

return {
Expand Down

0 comments on commit abcc6ee

Please sign in to comment.