File size: 4,733 Bytes
78d0e31 |
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 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 |
// XP calculations
const XP_PER_LEVEL = 1000
const XP_GROWTH_FACTOR = 1.2
export const calculateLevel = (xp: number): number => {
return Math.floor(xp / XP_PER_LEVEL) + 1
}
export const xpToNextLevel = (xp: number): number => {
const currentLevel = calculateLevel(xp)
return currentLevel * XP_PER_LEVEL * XP_GROWTH_FACTOR - xp
}
// FLB reward algorithm
export const calculateFLBReward = (
difficulty: "easy" | "medium" | "hard" | "expert",
timeTaken: number, // in minutes
accuracy: number, // 0-100%
streakBonus: number,
): number => {
const baseRewards = {
easy: 10,
medium: 25,
hard: 50,
expert: 100,
}
// Time bonus (faster completion = higher bonus)
const timeFactor = Math.max(0, 1 - timeTaken / 30)
// Accuracy multiplier
const accuracyMultiplier = accuracy / 100
// Streak bonus (2% per consecutive day)
const streakMultiplier = 1 + streakBonus * 0.02
return Math.round(baseRewards[difficulty] * timeFactor * accuracyMultiplier * streakMultiplier)
}
// Streak management
export const updateStreak = (lastActivity: Date): number => {
const today = new Date()
const lastDate = new Date(lastActivity)
const diffDays = Math.floor((today.getTime() - lastDate.getTime()) / (1000 * 60 * 60 * 24))
// If last activity was yesterday, increment streak
if (diffDays === 1) {
const currentStreak = Number.parseInt(localStorage.getItem("currentStreak") || "0")
const newStreak = currentStreak + 1
localStorage.setItem("currentStreak", newStreak.toString())
return newStreak
}
// If last activity was today, maintain streak
if (diffDays === 0) {
return Number.parseInt(localStorage.getItem("currentStreak") || "1")
}
// If more than 1 day gap, reset streak
localStorage.setItem("currentStreak", "1")
return 1
}
// Achievement checking
export const checkAchievements = (userStats: {
completedModules: number
streak: number
storiesShared: number
flbEarned: number
tribesJoined: number
}): string[] => {
const achievements: string[] = []
// First Steps - Complete first module
if (userStats.completedModules >= 1) {
achievements.push("first-steps")
}
// Streak Starter - 7 day streak
if (userStats.streak >= 7) {
achievements.push("streak-starter")
}
// Wisdom Seeker - Complete 10 modules
if (userStats.completedModules >= 10) {
achievements.push("wisdom-seeker")
}
// Community Builder - Join a tribe
if (userStats.tribesJoined >= 1) {
achievements.push("community-builder")
}
// Story Teller - Share 5 stories
if (userStats.storiesShared >= 5) {
achievements.push("story-teller")
}
// FLB Collector - Earn 100 FLB
if (userStats.flbEarned >= 100) {
achievements.push("flb-collector")
}
// Streak Master - 30 day streak
if (userStats.streak >= 30) {
achievements.push("streak-master")
}
// Ubuntu Spirit - Share 50 stories
if (userStats.storiesShared >= 50) {
achievements.push("ubuntu-spirit")
}
return achievements
}
// Level benefits calculation
export const getLevelBenefits = (level: number) => {
return {
flbMultiplier: 1 + (level - 1) * 0.1, // 10% bonus per level
xpMultiplier: 1 + (level - 1) * 0.05, // 5% bonus per level
dailyChallenges: Math.min(3 + Math.floor(level / 5), 10), // More challenges at higher levels
specialAccess: level >= 10, // Special content access at level 10+
}
}
// Progress tracking utilities
export const calculateProgress = (current: number, target: number): number => {
return Math.min((current / target) * 100, 100)
}
export const getNextMilestone = (current: number, milestones: number[]): number | null => {
return milestones.find((milestone) => milestone > current) || null
}
// Reward distribution logic
export const distributeRewards = async (
walletAddress: string,
flbAmount: number,
xpAmount: number,
achievementIds: string[] = [],
) => {
try {
// In a real implementation, this would interact with smart contracts
console.log(`Distributing rewards to ${walletAddress}:`)
console.log(`- FLB: ${flbAmount}`)
console.log(`- XP: ${xpAmount}`)
console.log(`- Achievements: ${achievementIds.join(", ")}`)
// Mock API call
const response = await fetch("/api/youth/distribute-rewards", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
walletAddress,
flbAmount,
xpAmount,
achievementIds,
}),
})
if (!response.ok) {
throw new Error("Failed to distribute rewards")
}
return await response.json()
} catch (error) {
console.error("Error distributing rewards:", error)
throw error
}
}
|