What is an achievements system?
Achievements — rewards for completing tasks.
Why does it matter?
Achievements = Motivation + Engagement
Gamification boosts retention by 30–40%! 🎮
Basic achievements system
Achievement Class:
class Achievement:
"""An achievement."""
def __init__(self, id, name, description, points, condition):
"""
Args:
id: Unique ID
name: Achievement name
description: Description
points: How many points it awards
condition: Check function (returns True/False)
"""
self.id = id
self.name = name
self.description = description
self.points = points
self.condition = condition
self.unlocked = False
self.unlocked_at = None
def check(self, user_data):
"""Check whether the achievement is unlocked."""
if self.unlocked:
return False # Already unlocked
if self.condition(user_data):
self.unlocked = True
from datetime import datetime
self.unlocked_at = datetime.now()
return True
return False
def __str__(self):
status = "🔓" if self.unlocked else "🔒"
return f"{status} {self.name} ({self.points} pts)"
# Example conditions
def first_login(data):
"""First login."""
return data.get("logins", 0) >= 1
def power_user(data):
"""100+ logins."""
return data.get("logins", 0) >= 100
# Creating achievements
achievements = [
Achievement(
id="first_login",
name="First Step",
description="Log in for the first time",
points=10,
condition=first_login
),
Achievement(
id="power_user",
name="Power User",
description="100 logins",
points=100,
condition=power_user
)
]
# Check
user = {"logins": 1}
for ach in achievements:
if ach.check(user):
print(f"🎉 Unlocked: {ach.name} (+{ach.points} pts)")
Progress Tracking
ProgressTracker Class:
class ProgressTracker:
"""Track a user's progress."""
def __init__(self, user_id):
self.user_id = user_id
self.stats = {
"logins": 0,
"tasks_completed": 0,
"points_earned": 0,
"days_active": 0,
"streak": 0, # Consecutive days
"lessons_finished": 0,
"code_lines": 0
}
self.achievements_unlocked = []
self.last_active = None
def record_action(self, action_type, value=1):
"""Record an action."""
if action_type in self.stats:
self.stats[action_type] += value
# Streak check
from datetime import datetime, timedelta
today = datetime.now().date()
if self.last_active:
last_date = self.last_active.date()
if today == last_date + timedelta(days=1):
self.stats["streak"] += 1
elif today != last_date:
self.stats["streak"] = 1
else:
self.stats["streak"] = 1
self.last_active = datetime.now()
def get_progress_percent(self, achievement):
"""Percentage progress toward an achievement."""
# Already unlocked
if achievement.unlocked:
return 100
# Approximate check (simplified)
# In production you'd parse the condition
return min(100, (self.stats.get("tasks_completed", 0) / 10) * 100)
def get_summary(self):
"""Progress summary."""
return {
"total_points": self.stats["points_earned"],
"achievements": len(self.achievements_unlocked),
"streak": self.stats["streak"],
"tasks": self.stats["tasks_completed"]
}
# Usage
tracker = ProgressTracker(user_id=1)
# User performs actions
tracker.record_action("logins")
tracker.record_action("tasks_completed")
tracker.record_action("points_earned", 50)
print(tracker.get_summary())
# {'total_points': 50, 'achievements': 0, 'streak': 1, 'tasks': 1}
Achievement Manager
Central management system:
class AchievementManager:
"""Manage all achievements."""
def __init__(self):
self.achievements = []
self.user_progresses = {}
def register_achievement(self, achievement):
"""Register an achievement."""
self.achievements.append(achievement)
def get_user_progress(self, user_id):
"""Get a user's progress tracker."""
if user_id not in self.user_progresses:
self.user_progresses[user_id] = ProgressTracker(user_id)
return self.user_progresses[user_id]
def check_achievements(self, user_id):
"""Check all achievements for a user."""
tracker = self.get_user_progress(user_id)
newly_unlocked = []
for achievement in self.achievements:
if achievement.check(tracker.stats):
tracker.achievements_unlocked.append(achievement.id)
tracker.stats["points_earned"] += achievement.points
newly_unlocked.append(achievement)
return newly_unlocked
def get_user_achievements(self, user_id):
"""All achievements for a user."""
tracker = self.get_user_progress(user_id)
result = {
"unlocked": [],
"locked": [],
"total_points": tracker.stats["points_earned"]
}
for ach in self.achievements:
if ach.id in tracker.achievements_unlocked:
result["unlocked"].append({
"name": ach.name,
"points": ach.points,
"unlocked_at": ach.unlocked_at
})
else:
result["locked"].append({
"name": ach.name,
"description": ach.description,
"points": ach.points
})
return result
# Example usage
manager = AchievementManager()
# Register achievements
manager.register_achievement(Achievement(
"first_task", "First Steps", "Complete your first task",
points=10,
condition=lambda data: data.get("tasks_completed", 0) >= 1
))
manager.register_achievement(Achievement(
"task_master", "Task Master", "Complete 50 tasks",
points=200,
condition=lambda data: data.get("tasks_completed", 0) >= 50
))
# User completes a task
tracker = manager.get_user_progress(user_id=1)
tracker.record_action("tasks_completed")
# Check
new_achievements = manager.check_achievements(user_id=1)
for ach in new_achievements:
print(f"🎉 {ach.name} (+{ach.points} pts)")
Achievement types
1. Milestone Achievements (count-based):
def create_milestone_achievement(name, stat_key, threshold, points):
"""Achievement for reaching a numeric threshold."""
return Achievement(
id=f"{stat_key}_{threshold}",
name=name,
description=f"Reach {threshold} {stat_key}",
points=points,
condition=lambda data: data.get(stat_key, 0) >= threshold
)
# Examples
milestones = [
create_milestone_achievement("Beginner", "lessons_finished", 1, 10),
create_milestone_achievement("Student", "lessons_finished", 5, 50),
create_milestone_achievement("Expert", "lessons_finished", 20, 200),
create_milestone_achievement("Master", "lessons_finished", 50, 500)
]
2. Streak Achievements (consistency-based):
def create_streak_achievement(days, points):
"""Achievement for consecutive days."""
return Achievement(
id=f"streak_{days}",
name=f"{days}-day streak",
description=f"Log in {days} days in a row",
points=points,
condition=lambda data: data.get("streak", 0) >= days
)
streaks = [
create_streak_achievement(3, 30),
create_streak_achievement(7, 100),
create_streak_achievement(30, 500),
create_streak_achievement(100, 2000)
]
3. Challenge Achievements (special conditions):
# Combined conditions
def early_bird_condition(data):
"""Early bird — log in before 6 AM."""
if not data.get("last_login_hour"):
return False
return data["last_login_hour"] < 6
def night_owl_condition(data):
"""Night owl — log in after 11 PM."""
if not data.get("last_login_hour"):
return False
return data["last_login_hour"] >= 23
challenges = [
Achievement(
"early_bird", "Early Bird", "Log in before 6:00 AM", 50, early_bird_condition
),
Achievement(
"night_owl", "Night Owl", "Log in after 11:00 PM", 50, night_owl_condition
)
]
Badges & Tiers
Tier system:
class BadgeSystem:
"""Badge and tier system."""
TIERS = [
{"name": "Beginner", "min_points": 0, "badge": "🥉"},
{"name": "Student", "min_points": 100, "badge": "🥈"},
{"name": "Expert", "min_points": 500, "badge": "🥇"},
{"name": "Master", "min_points": 1000, "badge": "💎"},
{"name": "Legend", "min_points": 5000, "badge": "👑"}
]
@classmethod
def get_tier(cls, points):
"""Get tier by points."""
current_tier = cls.TIERS[0]
for tier in cls.TIERS:
if points >= tier["min_points"]:
current_tier = tier
else:
break
return current_tier
@classmethod
def get_next_tier(cls, points):
"""Get the next tier."""
for tier in cls.TIERS:
if points < tier["min_points"]:
return tier
return None
@classmethod
def progress_to_next(cls, points):
"""Progress percentage toward the next tier."""
next_tier = cls.get_next_tier(points)
if not next_tier:
return 100 # Max tier
current = cls.get_tier(points)
needed = next_tier["min_points"] - current["min_points"]
earned = points - current["min_points"]
return (earned / needed) * 100 if needed > 0 else 100
# Usage
user_points = 350
tier = BadgeSystem.get_tier(user_points)
print(f"Current tier: {tier['badge']} {tier['name']}")
next_tier = BadgeSystem.get_next_tier(user_points)
if next_tier:
progress = BadgeSystem.progress_to_next(user_points)
print(f"Progress to {next_tier['name']}: {progress:.1f}%")
Leaderboard
Ranking system:
class Leaderboard:
"""Leaderboard."""
def __init__(self):
self.users = []
def add_user(self, user_id, username, points):
"""Add a user."""
self.users.append({
"user_id": user_id,
"username": username,
"points": points
})
def get_rankings(self, limit=10):
"""Top users."""
sorted_users = sorted(
self.users,
key=lambda x: x["points"],
reverse=True
)
# Add position
for i, user in enumerate(sorted_users[:limit], 1):
user["rank"] = i
# Medals for top 3
if i == 1:
user["medal"] = "🥇"
elif i == 2:
user["medal"] = "🥈"
elif i == 3:
user["medal"] = "🥉"
else:
user["medal"] = ""
return sorted_users[:limit]
def get_user_rank(self, user_id):
"""A user's position on the leaderboard."""
sorted_users = sorted(
self.users,
key=lambda x: x["points"],
reverse=True
)
for i, user in enumerate(sorted_users, 1):
if user["user_id"] == user_id:
return {
"rank": i,
"total_users": len(self.users),
"percentile": ((len(self.users) - i) / len(self.users)) * 100
}
return None
# Example
leaderboard = Leaderboard()
leaderboard.add_user(1, "Alice", 5000)
leaderboard.add_user(2, "Bob", 3500)
leaderboard.add_user(3, "Charlie", 4200)
leaderboard.add_user(4, "Diana", 2800)
print("🏆 Top users:")
for user in leaderboard.get_rankings():
medal = user.get("medal", "")
print(f"{medal} #{user['rank']} {user['username']}: {user['points']} pts")
# Rank for a specific user
rank_info = leaderboard.get_user_rank(4)
print(f"\nYour rank: #{rank_info['rank']}/{rank_info['total_users']}")
print(f"Top {rank_info['percentile']:.0f}%")
Notifications & Rewards
Notification system:
class AchievementNotification:
"""Achievement notifications."""
@staticmethod
def show_unlock(achievement):
"""Show an unlock notification."""
print("=" * 50)
print("🎉 ACHIEVEMENT UNLOCKED! 🎉")
print("=" * 50)
print(f"✨ {achievement.name}")
print(f"📝 {achievement.description}")
print(f"⭐ +{achievement.points} points")
print("=" * 50)
@staticmethod
def show_progress(achievement, percent):
"""Show progress toward an achievement."""
bar_length = 20
filled = int(bar_length * percent / 100)
bar = "█" * filled + "░" * (bar_length - filled)
print(f"{achievement.name}: [{bar}] {percent:.0f}%")
@staticmethod
def show_tier_up(old_tier, new_tier):
"""Show a tier-up notification."""
print("=" * 50)
print("🎊 TIER UP! 🎊")
print("=" * 50)
print(f"{old_tier['badge']} {old_tier['name']} → {new_tier['badge']} {new_tier['name']}")
print("=" * 50)
# Example
achievement = Achievement(
"master", "Python Master", "Complete 100 tasks",
points=500,
condition=lambda x: x.get("tasks", 0) >= 100
)
# On unlock
AchievementNotification.show_unlock(achievement)
# Progress
AchievementNotification.show_progress(achievement, 75)
Full system
Putting it all together:
class GamificationSystem:
"""Full gamification system."""
def __init__(self):
self.achievement_manager = AchievementManager()
self.badge_system = BadgeSystem()
self.leaderboard = Leaderboard()
# Register default achievements
self._register_default_achievements()
def _register_default_achievements(self):
"""Default achievements."""
# Milestones
for tasks in [1, 10, 50, 100]:
self.achievement_manager.register_achievement(
create_milestone_achievement(
f"{tasks} tasks",
"tasks_completed",
tasks,
tasks * 10
)
)
# Streaks
for days in [3, 7, 30]:
self.achievement_manager.register_achievement(
create_streak_achievement(days, days * 10)
)
def record_user_action(self, user_id, action_type, value=1):
"""Record a user action."""
# Update tracker
tracker = self.achievement_manager.get_user_progress(user_id)
old_points = tracker.stats["points_earned"]
old_tier = self.badge_system.get_tier(old_points)
tracker.record_action(action_type, value)
# Check achievements
new_achievements = self.achievement_manager.check_achievements(user_id)
# Show notifications
for ach in new_achievements:
AchievementNotification.show_unlock(ach)
# Check for tier up
new_points = tracker.stats["points_earned"]
new_tier = self.badge_system.get_tier(new_points)
if new_tier["name"] != old_tier["name"]:
AchievementNotification.show_tier_up(old_tier, new_tier)
# Update leaderboard
self._update_leaderboard(user_id, new_points)
def _update_leaderboard(self, user_id, points):
"""Update the leaderboard."""
# Remove old entry
self.leaderboard.users = [
u for u in self.leaderboard.users if u["user_id"] != user_id
]
# Add new entry
self.leaderboard.add_user(user_id, f"User{user_id}", points)
def get_user_dashboard(self, user_id):
"""User dashboard."""
tracker = self.achievement_manager.get_user_progress(user_id)
points = tracker.stats["points_earned"]
tier = self.badge_system.get_tier(points)
rank_info = self.leaderboard.get_user_rank(user_id)
return {
"tier": tier,
"points": points,
"rank": rank_info,
"achievements": self.achievement_manager.get_user_achievements(user_id),
"stats": tracker.stats
}
# Usage
system = GamificationSystem()
# User completes tasks
system.record_user_action(user_id=1, action_type="tasks_completed")
system.record_user_action(user_id=1, action_type="tasks_completed")
system.record_user_action(user_id=1, action_type="tasks_completed")
# Dashboard
dashboard = system.get_user_dashboard(user_id=1)
print(f"\n{dashboard['tier']['badge']} {dashboard['tier']['name']}")
print(f"Points: {dashboard['points']}")
print(f"Achievements unlocked: {len(dashboard['achievements']['unlocked'])}")
Common mistakes
❌ Mistake 1: Achievements that are too easy
# BAD: unlocked immediately
Achievement("easy", "Hello", "Just show up", 1000,
lambda x: True) # Way too easy!
# ✅ GOOD: real goals
Achievement("hard", "Master", "100 tasks", 500,
lambda x: x.get("tasks", 0) >= 100)
❌ Mistake 2: Achievements that are too hard
# BAD: impossible
Achievement("impossible", "God", "1 million tasks", 1,
lambda x: x.get("tasks", 0) >= 1000000) # Unrealistic!
# ✅ GOOD: challenging but achievable
Achievement("challenge", "Hero", "500 tasks", 1000,
lambda x: x.get("tasks", 0) >= 500)
❌ Mistake 3: No progress feedback
# BAD: don't show progress
show_only_unlocked() # Users don't know what to aim for
# ✅ GOOD: show progress
for ach in all_achievements:
progress = tracker.get_progress_percent(ach)
AchievementNotification.show_progress(ach, progress)
Best Practices
1. Balance rewards:
reward_tiers = {
"easy": (1, 50), # First achievements
"medium": (50, 200), # Mid-tier
"hard": (200, 500), # Hard
"epic": (500, 2000) # Epic
}
2. Variety:
achievement_types = [
"milestones", # Count-based
"streaks", # Consistency-based
"challenges", # Special conditions
"hidden", # Secret (condition hidden)
"time_limited" # Time-limited
]
3. Engagement Loops:
def create_engagement_loop():
"""Engagement loop."""
steps = [
"1. User sees their progress",
"2. Almost unlocked an achievement (80%)",
"3. Motivation to finish",
"4. Unlock → satisfaction",
"5. User sees the next achievement",
"6. Loop repeats"
]
return steps
Summary
System components:
components = {
"Achievement": "The achievement itself",
"ProgressTracker": "Tracks progress",
"AchievementManager": "Manages everything",
"BadgeSystem": "Tiers and badges",
"Leaderboard": "Rankings",
"Notifications": "Notifications"
}
Achievement types:
types = {
"Milestone": "Count-based (10, 50, 100 tasks)",
"Streak": "Consecutive days (3, 7, 30 days)",
"Challenge": "Special conditions (early bird, night owl)",
"Hidden": "Secret (condition hidden)",
"Tier": "Tiers (beginner → master)"
}
System balance:
- ⚡ Early achievements — quick wins for onboarding
- 📈 Mid-tier — regular rewards for retention
- 🏆 Hard — rare rewards for prestige
- 👑 Epic — extremely rare, legendary status
Build an achievement system and keep your users engaged! 🎮🚀
💬 Comments (0)
No comments yet
Be the first to share your opinion about this article!